5927 lines
237 KiB
Diff
5927 lines
237 KiB
Diff
diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/JavacTask.java b/src/jdk.compiler/share/classes/com/sun/source/util/JavacTask.java
|
|
index 8f1c99806..04b487053 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/source/util/JavacTask.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/JavacTask.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
@@ -29,6 +29,7 @@ import java.io.IOException;
|
|
|
|
import javax.annotation.processing.ProcessingEnvironment;
|
|
import javax.lang.model.element.Element;
|
|
+import javax.lang.model.element.VariableElement;
|
|
import javax.lang.model.type.TypeMirror;
|
|
import javax.lang.model.util.Elements;
|
|
import javax.lang.model.util.Types;
|
|
@@ -136,6 +137,27 @@ public abstract class JavacTask implements CompilationTask {
|
|
*/
|
|
public abstract void removeTaskListener(TaskListener taskListener);
|
|
|
|
+ /**
|
|
+ * Sets the specified {@link ParameterNameProvider}. It may be used when
|
|
+ * {@link VariableElement#getSimpleName()} is called for a method parameter
|
|
+ * for which an authoritative name is not found. The given
|
|
+ * {@code ParameterNameProvider} may infer a user-friendly name
|
|
+ * for the method parameter.
|
|
+ *
|
|
+ * Setting a new {@code ParameterNameProvider} will clear any previously set
|
|
+ * {@code ParameterNameProvider}, which won't be queried any more.
|
|
+ *
|
|
+ * When no {@code ParameterNameProvider} is set, or when it returns null from
|
|
+ * {@link ParameterNameProvider#getParameterName(javax.lang.model.element.VariableElement)},
|
|
+ * an automatically synthesized name is returned from {@code VariableElement.getSimpleName()}.
|
|
+ *
|
|
+ * @implSpec The default implementation of this method does nothing.
|
|
+ *
|
|
+ * @param provider the provider.
|
|
+ * @since 13
|
|
+ */
|
|
+ public void setParameterNameProvider(ParameterNameProvider provider) {}
|
|
+
|
|
/**
|
|
* Returns a type mirror of the tree node determined by the specified path.
|
|
* This method has been superceded by methods on
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/ParameterNameProvider.java b/src/jdk.compiler/share/classes/com/sun/source/util/ParameterNameProvider.java
|
|
new file mode 100644
|
|
index 000000000..c23d382cf
|
|
--- /dev/null
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/ParameterNameProvider.java
|
|
@@ -0,0 +1,50 @@
|
|
+/*
|
|
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
|
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
+ *
|
|
+ * This code is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 only, as
|
|
+ * published by the Free Software Foundation. Oracle designates this
|
|
+ * particular file as subject to the "Classpath" exception as provided
|
|
+ * by Oracle in the LICENSE file that accompanied this code.
|
|
+ *
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
|
+ * accompanied this code).
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License version
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
|
+ * questions.
|
|
+ */
|
|
+
|
|
+package com.sun.source.util;
|
|
+
|
|
+import javax.lang.model.element.VariableElement;
|
|
+
|
|
+/**
|
|
+ * A provider for parameter names when the parameter names are not determined from
|
|
+ * a reliable source, like a classfile.
|
|
+ *
|
|
+ * @since 13
|
|
+ */
|
|
+public interface ParameterNameProvider {
|
|
+
|
|
+ /**
|
|
+ * Infer a parameter name for the given parameter. The implementations of this method
|
|
+ * should infer parameter names in such a way that the parameter names are distinct
|
|
+ * for any given owning method.
|
|
+ *
|
|
+ * If the implementation of this method returns null, an automatically synthesized name is used.
|
|
+ *
|
|
+ * @param parameter the parameter for which the name should be inferred.
|
|
+ * @return a user-friendly name for the parameter, or null if unknown
|
|
+ */
|
|
+ public CharSequence getParameterName(VariableElement parameter);
|
|
+
|
|
+}
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java
|
|
index 094f002e3..0861412f2 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
@@ -43,9 +43,11 @@ import javax.tools.JavaFileObject;
|
|
import com.sun.source.tree.CompilationUnitTree;
|
|
import com.sun.source.tree.Tree;
|
|
import com.sun.source.util.JavacTask;
|
|
+import com.sun.source.util.ParameterNameProvider;
|
|
import com.sun.source.util.Plugin;
|
|
import com.sun.source.util.TaskListener;
|
|
import com.sun.tools.doclint.DocLint;
|
|
+import com.sun.tools.javac.code.MissingInfoHandler;
|
|
import com.sun.tools.javac.main.JavaCompiler;
|
|
import com.sun.tools.javac.model.JavacElements;
|
|
import com.sun.tools.javac.model.JavacTypes;
|
|
@@ -123,6 +125,11 @@ public class BasicJavacTask extends JavacTask {
|
|
mtl.remove(taskListener);
|
|
}
|
|
|
|
+ @Override
|
|
+ public void setParameterNameProvider(ParameterNameProvider handler) {
|
|
+ MissingInfoHandler.instance(context).setDelegate(handler);
|
|
+ }
|
|
+
|
|
public Collection<TaskListener> getTaskListeners() {
|
|
MultiTaskListener mtl = MultiTaskListener.instance(context);
|
|
return mtl.getTaskListeners();
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
|
|
index 81469471f..a5dbc9e5e 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
@@ -319,6 +319,11 @@ public class Flags {
|
|
*/
|
|
public static final long BODY_ONLY_FINALIZE = 1L<<17; //blocks only
|
|
|
|
+ /**
|
|
+ * Flag to indicate the given ParamSymbol has a user-friendly name filled.
|
|
+ */
|
|
+ public static final long NAME_FILLED = 1L<<58; //ParamSymbols only
|
|
+
|
|
/** Modifier masks.
|
|
*/
|
|
public static final int
|
|
@@ -433,7 +438,8 @@ public class Flags {
|
|
SYSTEM_MODULE(Flags.SYSTEM_MODULE),
|
|
DEPRECATED_ANNOTATION(Flags.DEPRECATED_ANNOTATION),
|
|
DEPRECATED_REMOVAL(Flags.DEPRECATED_REMOVAL),
|
|
- HAS_RESOURCE(Flags.HAS_RESOURCE);
|
|
+ HAS_RESOURCE(Flags.HAS_RESOURCE),
|
|
+ NAME_FILLED(Flags.NAME_FILLED);
|
|
|
|
Flag(long flag) {
|
|
this.value = flag;
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/MissingInfoHandler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/MissingInfoHandler.java
|
|
new file mode 100644
|
|
index 000000000..088df917d
|
|
--- /dev/null
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/MissingInfoHandler.java
|
|
@@ -0,0 +1,75 @@
|
|
+/*
|
|
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
|
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
+ *
|
|
+ * This code is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 only, as
|
|
+ * published by the Free Software Foundation. Oracle designates this
|
|
+ * particular file as subject to the "Classpath" exception as provided
|
|
+ * by Oracle in the LICENSE file that accompanied this code.
|
|
+ *
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
|
+ * accompanied this code).
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License version
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
|
+ * questions.
|
|
+ */
|
|
+
|
|
+package com.sun.tools.javac.code;
|
|
+
|
|
+import com.sun.source.util.ParameterNameProvider;
|
|
+import com.sun.tools.javac.code.Symbol.ParamSymbol;
|
|
+import com.sun.tools.javac.util.Context;
|
|
+import com.sun.tools.javac.util.Name;
|
|
+import com.sun.tools.javac.util.Names;
|
|
+
|
|
+/**
|
|
+ * A Context class, that can return additional useful information for Symbols, currently
|
|
+ * parameter names. It does so by calling user-supplied {@link ParameterNameProvider}.
|
|
+ *
|
|
+ * <p><b>This is NOT part of any supported API.
|
|
+ * If you write code that depends on this, you do so at your own risk.
|
|
+ * This code and its internal interfaces are subject to change or
|
|
+ * deletion without notice.</b>
|
|
+ */
|
|
+public class MissingInfoHandler {
|
|
+ protected static final Context.Key<MissingInfoHandler> missingInfoHandlerWrapperKey = new Context.Key<>();
|
|
+
|
|
+ public static MissingInfoHandler instance(Context context) {
|
|
+ MissingInfoHandler instance = context.get(missingInfoHandlerWrapperKey);
|
|
+ if (instance == null)
|
|
+ instance = new MissingInfoHandler(context);
|
|
+ return instance;
|
|
+ }
|
|
+
|
|
+ private final Names names;
|
|
+ private ParameterNameProvider parameterNameProvider;
|
|
+
|
|
+ protected MissingInfoHandler(Context context) {
|
|
+ context.put(missingInfoHandlerWrapperKey, this);
|
|
+ names = Names.instance(context);
|
|
+ }
|
|
+
|
|
+ public Name getParameterName(ParamSymbol parameter) {
|
|
+ if (parameterNameProvider != null) {
|
|
+ CharSequence name = parameterNameProvider.getParameterName(parameter);
|
|
+ if (name != null) {
|
|
+ return names.fromString(name.toString());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ public void setDelegate(ParameterNameProvider delegate) {
|
|
+ this.parameterNameProvider = delegate;
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
|
|
index bee3532c5..f50eae8dd 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
@@ -54,6 +54,7 @@ import com.sun.tools.javac.comp.Attr;
|
|
import com.sun.tools.javac.comp.AttrContext;
|
|
import com.sun.tools.javac.comp.Env;
|
|
import com.sun.tools.javac.jvm.*;
|
|
+import com.sun.tools.javac.jvm.PoolConstant;
|
|
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
|
|
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
|
import com.sun.tools.javac.tree.JCTree.Tag;
|
|
@@ -64,9 +65,12 @@ import com.sun.tools.javac.util.Name;
|
|
import static com.sun.tools.javac.code.Flags.*;
|
|
import static com.sun.tools.javac.code.Kinds.*;
|
|
import static com.sun.tools.javac.code.Kinds.Kind.*;
|
|
+import com.sun.tools.javac.code.MissingInfoHandler;
|
|
import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
|
|
import com.sun.tools.javac.code.Scope.WriteableScope;
|
|
+import com.sun.tools.javac.code.Symbol;
|
|
import static com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode.FIRSTASGOP;
|
|
+import com.sun.tools.javac.code.Type;
|
|
import static com.sun.tools.javac.code.TypeTag.CLASS;
|
|
import static com.sun.tools.javac.code.TypeTag.FORALL;
|
|
import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
|
|
@@ -75,6 +79,7 @@ import static com.sun.tools.javac.jvm.ByteCodes.ishll;
|
|
import static com.sun.tools.javac.jvm.ByteCodes.lushrl;
|
|
import static com.sun.tools.javac.jvm.ByteCodes.lxor;
|
|
import static com.sun.tools.javac.jvm.ByteCodes.string_add;
|
|
+import com.sun.tools.javac.util.Name;
|
|
|
|
/** Root class for Java symbols. It contains subclasses
|
|
* for specific sorts of symbols, such as variables, methods and operators,
|
|
@@ -86,7 +91,7 @@ import static com.sun.tools.javac.jvm.ByteCodes.string_add;
|
|
* This code and its internal interfaces are subject to change or
|
|
* deletion without notice.</b>
|
|
*/
|
|
-public abstract class Symbol extends AnnoConstruct implements Element {
|
|
+public abstract class Symbol extends AnnoConstruct implements PoolConstant, Element {
|
|
|
|
/** The kind of this symbol.
|
|
* @see Kinds
|
|
@@ -281,6 +286,11 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
|
this.name = name;
|
|
}
|
|
|
|
+ @Override
|
|
+ public int poolTag() {
|
|
+ throw new AssertionError("Invalid pool entry");
|
|
+ }
|
|
+
|
|
/** Clone this symbol with new owner.
|
|
* Legal only for fields and methods.
|
|
*/
|
|
@@ -966,6 +976,11 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
|
this.type = new ModuleType(this);
|
|
}
|
|
|
|
+ @Override
|
|
+ public int poolTag() {
|
|
+ return ClassFile.CONSTANT_Module;
|
|
+ }
|
|
+
|
|
@Override @DefinedBy(Api.LANGUAGE_MODEL)
|
|
public Name getSimpleName() {
|
|
return Convert.shortName(name);
|
|
@@ -1132,6 +1147,11 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
|
return members_field;
|
|
}
|
|
|
|
+ @Override
|
|
+ public int poolTag() {
|
|
+ return ClassFile.CONSTANT_Package;
|
|
+ }
|
|
+
|
|
public long flags() {
|
|
complete();
|
|
return flags_field;
|
|
@@ -1188,6 +1208,16 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
|
|
|
}
|
|
|
|
+ public static class RootPackageSymbol extends PackageSymbol {
|
|
+ public final MissingInfoHandler missingInfoHandler;
|
|
+
|
|
+ public RootPackageSymbol(Name name, Symbol owner, MissingInfoHandler missingInfoHandler) {
|
|
+ super(name, owner);
|
|
+ this.missingInfoHandler = missingInfoHandler;
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
/** A class for class symbols
|
|
*/
|
|
public static class ClassSymbol extends TypeSymbol implements TypeElement {
|
|
@@ -1222,10 +1252,6 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
|
*/
|
|
public List<ClassSymbol> trans_local;
|
|
|
|
- /** the constant pool of the class
|
|
- */
|
|
- public Pool pool;
|
|
-
|
|
/** the annotation metadata attached to this class */
|
|
private AnnotationTypeMetadata annotationTypeMetadata;
|
|
|
|
@@ -1236,7 +1262,6 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
|
this.flatname = formFlatName(name, owner);
|
|
this.sourcefile = null;
|
|
this.classfile = null;
|
|
- this.pool = null;
|
|
this.annotationTypeMetadata = AnnotationTypeMetadata.notAnAnnotationType();
|
|
}
|
|
|
|
@@ -1528,6 +1553,11 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
|
super(VAR, flags, name, type, owner);
|
|
}
|
|
|
|
+ @Override
|
|
+ public int poolTag() {
|
|
+ return ClassFile.CONSTANT_Fieldref;
|
|
+ }
|
|
+
|
|
/** Clone this symbol with new owner.
|
|
*/
|
|
public VarSymbol clone(Symbol newOwner) {
|
|
@@ -1536,6 +1566,11 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
|
public Symbol baseSymbol() {
|
|
return VarSymbol.this;
|
|
}
|
|
+
|
|
+ @Override
|
|
+ public Object poolKey(Types types) {
|
|
+ return new Pair<>(newOwner, baseSymbol());
|
|
+ }
|
|
};
|
|
v.pos = pos;
|
|
v.adr = adr;
|
|
@@ -1633,6 +1668,32 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
|
}
|
|
}
|
|
|
|
+ public static class ParamSymbol extends VarSymbol {
|
|
+ public ParamSymbol(long flags, Name name, Type type, Symbol owner) {
|
|
+ super(flags, name, type, owner);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Name getSimpleName() {
|
|
+ if ((flags_field & NAME_FILLED) == 0) {
|
|
+ flags_field |= NAME_FILLED;
|
|
+ Symbol rootPack = this;
|
|
+ while (rootPack != null && !(rootPack instanceof RootPackageSymbol)) {
|
|
+ rootPack = rootPack.owner;
|
|
+ }
|
|
+ if (rootPack != null) {
|
|
+ Name inferredName =
|
|
+ ((RootPackageSymbol) rootPack).missingInfoHandler.getParameterName(this);
|
|
+ if (inferredName != null) {
|
|
+ this.name = inferredName;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return super.getSimpleName();
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
/** A class for method symbols.
|
|
*/
|
|
public static class MethodSymbol extends Symbol implements ExecutableElement {
|
|
@@ -1670,6 +1731,11 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
|
public Symbol baseSymbol() {
|
|
return MethodSymbol.this;
|
|
}
|
|
+
|
|
+ @Override
|
|
+ public Object poolKey(Types types) {
|
|
+ return new Pair<>(newOwner, baseSymbol());
|
|
+ }
|
|
};
|
|
m.code = code;
|
|
return m;
|
|
@@ -1699,10 +1765,25 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
|
}
|
|
}
|
|
|
|
+ @Override
|
|
+ public int poolTag() {
|
|
+ return owner.isInterface() ?
|
|
+ ClassFile.CONSTANT_InterfaceMethodref : ClassFile.CONSTANT_Methodref;
|
|
+ }
|
|
+
|
|
public boolean isDynamic() {
|
|
return false;
|
|
}
|
|
|
|
+ public boolean isHandle() {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+
|
|
+ public MethodHandleSymbol asHandle() {
|
|
+ return new MethodHandleSymbol(this);
|
|
+ }
|
|
+
|
|
/** find a symbol that this (proxy method) symbol implements.
|
|
* @param c The class whose members are searched for
|
|
* implementations
|
|
@@ -1986,16 +2067,14 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
|
|
|
/** A class for invokedynamic method calls.
|
|
*/
|
|
- public static class DynamicMethodSymbol extends MethodSymbol {
|
|
+ public static class DynamicMethodSymbol extends MethodSymbol implements Dynamic {
|
|
|
|
- public Object[] staticArgs;
|
|
- public Symbol bsm;
|
|
- public int bsmKind;
|
|
+ public LoadableConstant[] staticArgs;
|
|
+ public MethodHandleSymbol bsm;
|
|
|
|
- public DynamicMethodSymbol(Name name, Symbol owner, int bsmKind, MethodSymbol bsm, Type type, Object[] staticArgs) {
|
|
+ public DynamicMethodSymbol(Name name, Symbol owner, MethodHandleSymbol bsm, Type type, LoadableConstant[] staticArgs) {
|
|
super(0, name, type, owner);
|
|
this.bsm = bsm;
|
|
- this.bsmKind = bsmKind;
|
|
this.staticArgs = staticArgs;
|
|
}
|
|
|
|
@@ -2003,6 +2082,83 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
|
public boolean isDynamic() {
|
|
return true;
|
|
}
|
|
+
|
|
+ @Override
|
|
+ public LoadableConstant[] staticArgs() {
|
|
+ return staticArgs;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public MethodHandleSymbol bootstrapMethod() {
|
|
+ return bsm;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int poolTag() {
|
|
+ return ClassFile.CONSTANT_InvokeDynamic;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Type dynamicType() {
|
|
+ return type;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /** A class for method handles.
|
|
+ */
|
|
+ public static class MethodHandleSymbol extends MethodSymbol implements LoadableConstant {
|
|
+
|
|
+ private Symbol refSym;
|
|
+
|
|
+ public MethodHandleSymbol(Symbol msym) {
|
|
+ super(msym.flags_field, msym.name, msym.type, msym.owner);
|
|
+ this.refSym = msym;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns the kind associated with this method handle.
|
|
+ */
|
|
+ public int referenceKind() {
|
|
+ if (refSym.isConstructor()) {
|
|
+ return ClassFile.REF_newInvokeSpecial;
|
|
+ } else {
|
|
+ if (refSym.isStatic()) {
|
|
+ return ClassFile.REF_invokeStatic;
|
|
+ } else if ((refSym.flags() & PRIVATE) != 0) {
|
|
+ return ClassFile.REF_invokeSpecial;
|
|
+ } else if (refSym.enclClass().isInterface()) {
|
|
+ return ClassFile.REF_invokeInterface;
|
|
+ } else {
|
|
+ return ClassFile.REF_invokeVirtual;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int poolTag() {
|
|
+ return ClassFile.CONSTANT_MethodHandle;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Object poolKey(Types types) {
|
|
+ return new Pair<>(baseSymbol(), referenceKind());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public MethodHandleSymbol asHandle() {
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Symbol baseSymbol() {
|
|
+ return refSym;
|
|
+ }
|
|
+
|
|
+
|
|
+ @Override
|
|
+ public boolean isHandle() {
|
|
+ return true;
|
|
+ }
|
|
}
|
|
|
|
/** A class for predefined operators.
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
|
|
index 01f374b30..6872245b3 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
|
|
@@ -42,6 +42,7 @@ import com.sun.tools.javac.code.Symbol.CompletionFailure;
|
|
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
|
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
|
|
import com.sun.tools.javac.code.Symbol.PackageSymbol;
|
|
+import com.sun.tools.javac.code.Symbol.RootPackageSymbol;
|
|
import com.sun.tools.javac.code.Symbol.TypeSymbol;
|
|
import com.sun.tools.javac.code.Symbol.VarSymbol;
|
|
import com.sun.tools.javac.code.Type.BottomType;
|
|
@@ -381,7 +382,9 @@ public class Symtab {
|
|
|
|
messages = JavacMessages.instance(context);
|
|
|
|
- rootPackage = new PackageSymbol(names.empty, null);
|
|
+ MissingInfoHandler missingInfoHandler = MissingInfoHandler.instance(context);
|
|
+
|
|
+ rootPackage = new RootPackageSymbol(names.empty, null, missingInfoHandler);
|
|
|
|
// create the basic builtin symbols
|
|
unnamedModule = new ModuleSymbol(names.empty, null) {
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
|
|
index 655f067d6..e92118120 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
|
|
@@ -36,7 +36,10 @@ import javax.lang.model.type.*;
|
|
import com.sun.tools.javac.code.Symbol.*;
|
|
import com.sun.tools.javac.code.TypeMetadata.Entry;
|
|
import com.sun.tools.javac.code.Types.TypeMapping;
|
|
+import com.sun.tools.javac.code.Types.UniqueType;
|
|
import com.sun.tools.javac.comp.Infer.IncorporationAction;
|
|
+import com.sun.tools.javac.jvm.ClassFile;
|
|
+import com.sun.tools.javac.jvm.PoolConstant;
|
|
import com.sun.tools.javac.util.*;
|
|
import com.sun.tools.javac.util.DefinedBy.Api;
|
|
|
|
@@ -73,7 +76,7 @@ import static com.sun.tools.javac.code.TypeTag.*;
|
|
*
|
|
* @see TypeTag
|
|
*/
|
|
-public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|
+public abstract class Type extends AnnoConstruct implements TypeMirror, PoolConstant {
|
|
|
|
/**
|
|
* Type metadata, Should be {@code null} for the default value.
|
|
@@ -125,6 +128,16 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|
*/
|
|
public TypeSymbol tsym;
|
|
|
|
+ @Override
|
|
+ public int poolTag() {
|
|
+ throw new AssertionError("Invalid pool entry");
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Object poolKey(Types types) {
|
|
+ return new UniqueType(this, types);
|
|
+ }
|
|
+
|
|
/**
|
|
* Checks if the current type tag is equal to the given tag.
|
|
* @return true if tag is equal to the current type tag.
|
|
@@ -930,7 +943,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|
}
|
|
}
|
|
|
|
- public static class ClassType extends Type implements DeclaredType,
|
|
+ public static class ClassType extends Type implements DeclaredType, LoadableConstant,
|
|
javax.lang.model.type.ErrorType {
|
|
|
|
/** The enclosing type of this type. If this is the type of an inner
|
|
@@ -975,6 +988,10 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|
this.interfaces_field = null;
|
|
}
|
|
|
|
+ public int poolTag() {
|
|
+ return ClassFile.CONSTANT_Class;
|
|
+ }
|
|
+
|
|
@Override
|
|
public ClassType cloneWithMetadata(TypeMetadata md) {
|
|
return new ClassType(outer_field, typarams_field, tsym, md) {
|
|
@@ -1277,7 +1294,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|
}
|
|
|
|
public static class ArrayType extends Type
|
|
- implements javax.lang.model.type.ArrayType {
|
|
+ implements LoadableConstant, javax.lang.model.type.ArrayType {
|
|
|
|
public Type elemtype;
|
|
|
|
@@ -1297,6 +1314,10 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|
this(that.elemtype, that.tsym, that.getMetadata());
|
|
}
|
|
|
|
+ public int poolTag() {
|
|
+ return ClassFile.CONSTANT_Class;
|
|
+ }
|
|
+
|
|
@Override
|
|
public ArrayType cloneWithMetadata(TypeMetadata md) {
|
|
return new ArrayType(elemtype, tsym, md) {
|
|
@@ -1412,7 +1433,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|
}
|
|
}
|
|
|
|
- public static class MethodType extends Type implements ExecutableType {
|
|
+ public static class MethodType extends Type implements ExecutableType, LoadableConstant {
|
|
|
|
public List<Type> argtypes;
|
|
public Type restype;
|
|
@@ -1479,6 +1500,11 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
|
|
restype != null && restype.isErroneous();
|
|
}
|
|
|
|
+ @Override
|
|
+ public int poolTag() {
|
|
+ return ClassFile.CONSTANT_MethodType;
|
|
+ }
|
|
+
|
|
public boolean contains(Type elem) {
|
|
return elem.equalsIgnoreMetadata(this) || contains(argtypes, elem) || restype.contains(elem) || contains(thrown, elem);
|
|
}
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
|
|
index d72f0781a..e4cbb810f 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
|
|
@@ -48,6 +48,8 @@ import com.sun.tools.javac.comp.AttrContext;
|
|
import com.sun.tools.javac.comp.Check;
|
|
import com.sun.tools.javac.comp.Enter;
|
|
import com.sun.tools.javac.comp.Env;
|
|
+import com.sun.tools.javac.comp.LambdaToMethod;
|
|
+import com.sun.tools.javac.jvm.ClassFile;
|
|
import com.sun.tools.javac.util.*;
|
|
|
|
import static com.sun.tools.javac.code.BoundKind.*;
|
|
@@ -5184,6 +5186,29 @@ public class Types {
|
|
}
|
|
}
|
|
}
|
|
+
|
|
+ public Type constantType(LoadableConstant c) {
|
|
+ switch (c.poolTag()) {
|
|
+ case ClassFile.CONSTANT_Class:
|
|
+ return syms.classType;
|
|
+ case ClassFile.CONSTANT_String:
|
|
+ return syms.stringType;
|
|
+ case ClassFile.CONSTANT_Integer:
|
|
+ return syms.intType;
|
|
+ case ClassFile.CONSTANT_Float:
|
|
+ return syms.floatType;
|
|
+ case ClassFile.CONSTANT_Long:
|
|
+ return syms.longType;
|
|
+ case ClassFile.CONSTANT_Double:
|
|
+ return syms.doubleType;
|
|
+ case ClassFile.CONSTANT_MethodHandle:
|
|
+ return syms.methodHandleType;
|
|
+ case ClassFile.CONSTANT_MethodType:
|
|
+ return syms.methodTypeType;
|
|
+ default:
|
|
+ throw new AssertionError("Not a loadable constant: " + c.poolTag());
|
|
+ }
|
|
+ }
|
|
// </editor-fold>
|
|
|
|
public void newRound() {
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
|
|
index a273a4c58..dcbee1bbc 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
|
|
@@ -25,7 +25,9 @@
|
|
|
|
package com.sun.tools.javac.comp;
|
|
|
|
+import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
|
|
import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
|
|
import com.sun.tools.javac.resources.CompilerProperties.Errors;
|
|
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
|
|
import com.sun.tools.javac.tree.*;
|
|
@@ -59,7 +61,6 @@ import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.Map;
|
|
-import java.util.Objects;
|
|
import java.util.Optional;
|
|
import java.util.Set;
|
|
import java.util.function.Consumer;
|
|
@@ -70,13 +71,10 @@ import static com.sun.tools.javac.code.Flags.*;
|
|
import static com.sun.tools.javac.code.Kinds.Kind.*;
|
|
import static com.sun.tools.javac.code.TypeTag.*;
|
|
import static com.sun.tools.javac.tree.JCTree.Tag.*;
|
|
-import static com.sun.tools.javac.jvm.Pool.DynamicMethod;
|
|
|
|
import javax.lang.model.element.ElementKind;
|
|
import javax.lang.model.type.TypeKind;
|
|
|
|
-import com.sun.tools.javac.code.Type.IntersectionClassType;
|
|
-import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
|
|
import com.sun.tools.javac.main.Option;
|
|
|
|
/**
|
|
@@ -214,7 +212,7 @@ public class LambdaToMethod extends TreeTranslator {
|
|
|
|
private Map<DedupedLambda, DedupedLambda> dedupedLambdas;
|
|
|
|
- private Map<DynamicMethod, DynamicMethodSymbol> dynMethSyms = new HashMap<>();
|
|
+ private Map<Object, DynamicMethodSymbol> dynMethSyms = new HashMap<>();
|
|
|
|
/**
|
|
* list of deserialization cases
|
|
@@ -439,11 +437,8 @@ public class LambdaToMethod extends TreeTranslator {
|
|
//then, determine the arguments to the indy call
|
|
List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
|
|
|
|
- //build a sam instance using an indy call to the meta-factory
|
|
- int refKind = referenceKind(sym);
|
|
-
|
|
//convert to an invokedynamic call
|
|
- result = makeMetafactoryIndyCall(context, refKind, sym, indy_args);
|
|
+ result = makeMetafactoryIndyCall(context, sym.asHandle(), indy_args);
|
|
}
|
|
|
|
// where
|
|
@@ -488,7 +483,7 @@ public class LambdaToMethod extends TreeTranslator {
|
|
|
|
//first determine the method symbol to be used to generate the sam instance
|
|
//this is either the method reference symbol, or the bridged reference symbol
|
|
- Symbol refSym = tree.sym;
|
|
+ MethodSymbol refSym = (MethodSymbol)tree.sym;
|
|
|
|
//the qualifying expression is treated as a special captured arg
|
|
JCExpression init;
|
|
@@ -521,7 +516,7 @@ public class LambdaToMethod extends TreeTranslator {
|
|
|
|
|
|
//build a sam instance using an indy call to the meta-factory
|
|
- result = makeMetafactoryIndyCall(localContext, localContext.referenceKind(), refSym, indy_args);
|
|
+ result = makeMetafactoryIndyCall(localContext, refSym.asHandle(), indy_args);
|
|
}
|
|
|
|
/**
|
|
@@ -764,8 +759,8 @@ public class LambdaToMethod extends TreeTranslator {
|
|
rs.resolveConstructor(null, attrEnv, ctype, TreeInfo.types(args), List.nil()));
|
|
}
|
|
|
|
- private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym,
|
|
- DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) {
|
|
+ private void addDeserializationCase(MethodHandleSymbol refSym, Type targetType, MethodSymbol samSym,
|
|
+ DiagnosticPosition pos, List<LoadableConstant> staticArgs, MethodType indyType) {
|
|
String functionalInterfaceClass = classSig(targetType);
|
|
String functionalInterfaceMethodName = samSym.getSimpleName().toString();
|
|
String functionalInterfaceMethodSignature = typeSig(types.erasure(samSym.type));
|
|
@@ -773,7 +768,8 @@ public class LambdaToMethod extends TreeTranslator {
|
|
String implMethodName = refSym.getQualifiedName().toString();
|
|
String implMethodSignature = typeSig(types.erasure(refSym.type));
|
|
|
|
- JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType), make.Literal(implMethodKind));
|
|
+ JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType),
|
|
+ make.Literal(refSym.referenceKind()));
|
|
ListBuffer<JCExpression> serArgs = new ListBuffer<>();
|
|
int i = 0;
|
|
for (Type t : indyType.getParameterTypes()) {
|
|
@@ -1105,13 +1101,13 @@ public class LambdaToMethod extends TreeTranslator {
|
|
* Generate an indy method call to the meta factory
|
|
*/
|
|
private JCExpression makeMetafactoryIndyCall(TranslationContext<?> context,
|
|
- int refKind, Symbol refSym, List<JCExpression> indy_args) {
|
|
+ MethodHandleSymbol refSym, List<JCExpression> indy_args) {
|
|
JCFunctionalExpression tree = context.tree;
|
|
//determine the static bsm args
|
|
MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.target.tsym);
|
|
- List<Object> staticArgs = List.of(
|
|
+ List<LoadableConstant> staticArgs = List.of(
|
|
typeToMethodType(samSym.type),
|
|
- new Pool.MethodHandle(refKind, refSym, types),
|
|
+ ((MethodSymbol)refSym).asHandle(),
|
|
typeToMethodType(tree.getDescriptorType(types)));
|
|
|
|
//computed indy arg types
|
|
@@ -1130,7 +1126,7 @@ public class LambdaToMethod extends TreeTranslator {
|
|
names.altMetafactory : names.metafactory;
|
|
|
|
if (context.needsAltMetafactory()) {
|
|
- ListBuffer<Object> markers = new ListBuffer<>();
|
|
+ ListBuffer<Type> markers = new ListBuffer<>();
|
|
List<Type> targets = tree.target.isIntersection() ?
|
|
types.directSupertypes(tree.target) :
|
|
List.nil();
|
|
@@ -1139,7 +1135,7 @@ public class LambdaToMethod extends TreeTranslator {
|
|
if (t.tsym != syms.serializableType.tsym &&
|
|
t.tsym != tree.type.tsym &&
|
|
t.tsym != syms.objectType.tsym) {
|
|
- markers.append(t.tsym);
|
|
+ markers.append(t);
|
|
}
|
|
}
|
|
int flags = context.isSerializable() ? FLAG_SERIALIZABLE : 0;
|
|
@@ -1151,17 +1147,17 @@ public class LambdaToMethod extends TreeTranslator {
|
|
if (hasBridges) {
|
|
flags |= FLAG_BRIDGES;
|
|
}
|
|
- staticArgs = staticArgs.append(flags);
|
|
+ staticArgs = staticArgs.append(LoadableConstant.Int(flags));
|
|
if (hasMarkers) {
|
|
- staticArgs = staticArgs.append(markers.length());
|
|
- staticArgs = staticArgs.appendList(markers.toList());
|
|
+ staticArgs = staticArgs.append(LoadableConstant.Int(markers.length()));
|
|
+ staticArgs = staticArgs.appendList(List.convert(LoadableConstant.class, markers.toList()));
|
|
}
|
|
if (hasBridges) {
|
|
- staticArgs = staticArgs.append(context.bridges.length() - 1);
|
|
+ staticArgs = staticArgs.append(LoadableConstant.Int(context.bridges.length() - 1));
|
|
for (Symbol s : context.bridges) {
|
|
Type s_erasure = s.erasure(types);
|
|
if (!types.isSameType(s_erasure, samSym.erasure(types))) {
|
|
- staticArgs = staticArgs.append(s.erasure(types));
|
|
+ staticArgs = staticArgs.append(((MethodType)s.erasure(types)));
|
|
}
|
|
}
|
|
}
|
|
@@ -1169,7 +1165,7 @@ public class LambdaToMethod extends TreeTranslator {
|
|
int prevPos = make.pos;
|
|
try {
|
|
make.at(kInfo.clazz);
|
|
- addDeserializationCase(refKind, refSym, tree.type, samSym,
|
|
+ addDeserializationCase(refSym, tree.type, samSym,
|
|
tree, staticArgs, indyType);
|
|
} finally {
|
|
make.at(prevPos);
|
|
@@ -1185,14 +1181,14 @@ public class LambdaToMethod extends TreeTranslator {
|
|
* arguments types
|
|
*/
|
|
private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,
|
|
- List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs,
|
|
- Name methName) {
|
|
+ List<LoadableConstant> staticArgs, MethodType indyType, List<JCExpression> indyArgs,
|
|
+ Name methName) {
|
|
int prevPos = make.pos;
|
|
try {
|
|
make.at(pos);
|
|
List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
|
|
- syms.stringType,
|
|
- syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs));
|
|
+ syms.stringType,
|
|
+ syms.methodTypeType).appendList(staticArgs.map(types::constantType));
|
|
|
|
Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
|
|
bsmName, bsm_staticArgs, List.nil());
|
|
@@ -1200,15 +1196,12 @@ public class LambdaToMethod extends TreeTranslator {
|
|
DynamicMethodSymbol dynSym =
|
|
new DynamicMethodSymbol(methName,
|
|
syms.noSymbol,
|
|
- bsm.isStatic() ?
|
|
- ClassFile.REF_invokeStatic :
|
|
- ClassFile.REF_invokeVirtual,
|
|
- (MethodSymbol)bsm,
|
|
+ ((MethodSymbol)bsm).asHandle(),
|
|
indyType,
|
|
- staticArgs.toArray());
|
|
+ staticArgs.toArray(new LoadableConstant[staticArgs.length()]));
|
|
JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
|
|
DynamicMethodSymbol existing = kInfo.dynMethSyms.putIfAbsent(
|
|
- new DynamicMethod(dynSym, types), dynSym);
|
|
+ dynSym.poolKey(types), dynSym);
|
|
qualifier.sym = existing != null ? existing : dynSym;
|
|
qualifier.type = indyType.getReturnType();
|
|
|
|
@@ -1219,57 +1212,6 @@ public class LambdaToMethod extends TreeTranslator {
|
|
make.at(prevPos);
|
|
}
|
|
}
|
|
- //where
|
|
- private List<Type> bsmStaticArgToTypes(List<Object> args) {
|
|
- ListBuffer<Type> argtypes = new ListBuffer<>();
|
|
- for (Object arg : args) {
|
|
- argtypes.append(bsmStaticArgToType(arg));
|
|
- }
|
|
- return argtypes.toList();
|
|
- }
|
|
-
|
|
- private Type bsmStaticArgToType(Object arg) {
|
|
- Assert.checkNonNull(arg);
|
|
- if (arg instanceof ClassSymbol) {
|
|
- return syms.classType;
|
|
- } else if (arg instanceof Integer) {
|
|
- return syms.intType;
|
|
- } else if (arg instanceof Long) {
|
|
- return syms.longType;
|
|
- } else if (arg instanceof Float) {
|
|
- return syms.floatType;
|
|
- } else if (arg instanceof Double) {
|
|
- return syms.doubleType;
|
|
- } else if (arg instanceof String) {
|
|
- return syms.stringType;
|
|
- } else if (arg instanceof Pool.MethodHandle) {
|
|
- return syms.methodHandleType;
|
|
- } else if (arg instanceof MethodType) {
|
|
- return syms.methodTypeType;
|
|
- } else {
|
|
- Assert.error("bad static arg " + arg.getClass());
|
|
- return null;
|
|
- }
|
|
- }
|
|
-
|
|
- /**
|
|
- * Get the opcode associated with this method reference
|
|
- */
|
|
- private int referenceKind(Symbol refSym) {
|
|
- if (refSym.isConstructor()) {
|
|
- return ClassFile.REF_newInvokeSpecial;
|
|
- } else {
|
|
- if (refSym.isStatic()) {
|
|
- return ClassFile.REF_invokeStatic;
|
|
- } else if ((refSym.flags() & PRIVATE) != 0) {
|
|
- return ClassFile.REF_invokeSpecial;
|
|
- } else if (refSym.enclClass().isInterface()) {
|
|
- return ClassFile.REF_invokeInterface;
|
|
- } else {
|
|
- return ClassFile.REF_invokeVirtual;
|
|
- }
|
|
- }
|
|
- }
|
|
|
|
// <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">
|
|
/**
|
|
@@ -2311,13 +2253,6 @@ public class LambdaToMethod extends TreeTranslator {
|
|
this.isSuper = tree.hasKind(ReferenceKind.SUPER);
|
|
}
|
|
|
|
- /**
|
|
- * Get the opcode associated with this method reference
|
|
- */
|
|
- int referenceKind() {
|
|
- return LambdaToMethod.this.referenceKind(tree.sym);
|
|
- }
|
|
-
|
|
boolean needsVarArgsConversion() {
|
|
return tree.varargsElement != null;
|
|
}
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
|
|
index 4f7d06f0f..69c4822ba 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
|
|
@@ -84,7 +84,6 @@ public class Lower extends TreeTranslator {
|
|
private final Attr attr;
|
|
private TreeMaker make;
|
|
private DiagnosticPosition make_pos;
|
|
- private final ClassWriter writer;
|
|
private final ConstFold cfolder;
|
|
private final Target target;
|
|
private final Source source;
|
|
@@ -107,7 +106,6 @@ public class Lower extends TreeTranslator {
|
|
chk = Check.instance(context);
|
|
attr = Attr.instance(context);
|
|
make = TreeMaker.instance(context);
|
|
- writer = ClassWriter.instance(context);
|
|
cfolder = ConstFold.instance(context);
|
|
target = Target.instance(context);
|
|
source = Source.instance(context);
|
|
@@ -458,7 +456,7 @@ public class Lower extends TreeTranslator {
|
|
.fromString(target.syntheticNameChar() +
|
|
"SwitchMap" +
|
|
target.syntheticNameChar() +
|
|
- writer.xClassName(forEnum.type).toString()
|
|
+ names.fromUtf(ClassWriter.externalize(forEnum.type.tsym.flatName())).toString()
|
|
.replace('/', '.')
|
|
.replace('.', target.syntheticNameChar()));
|
|
ClassSymbol outerCacheClass = outerCacheClass();
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
|
|
index 4daeb73bc..7319e2573 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
|
|
@@ -25,9 +25,6 @@
|
|
|
|
package com.sun.tools.javac.jvm;
|
|
|
|
-import com.sun.tools.javac.code.Type;
|
|
-import com.sun.tools.javac.code.Types;
|
|
-import com.sun.tools.javac.code.Types.UniqueType;
|
|
import com.sun.tools.javac.util.Name;
|
|
|
|
|
|
@@ -187,38 +184,4 @@ public class ClassFile {
|
|
public static byte[] externalize(Name name) {
|
|
return externalize(name.getByteArray(), name.getByteOffset(), name.getByteLength());
|
|
}
|
|
-
|
|
-/************************************************************************
|
|
- * Name-and-type
|
|
- ***********************************************************************/
|
|
-
|
|
- /** A class for the name-and-type signature of a method or field.
|
|
- */
|
|
- public static class NameAndType {
|
|
- Name name;
|
|
- UniqueType uniqueType;
|
|
- Types types;
|
|
-
|
|
- NameAndType(Name name, Type type, Types types) {
|
|
- this.name = name;
|
|
- this.uniqueType = new UniqueType(type, types);
|
|
- this.types = types;
|
|
- }
|
|
-
|
|
- void setType(Type type) {
|
|
- this.uniqueType = new UniqueType(type, types);
|
|
- }
|
|
-
|
|
- @Override
|
|
- public boolean equals(Object other) {
|
|
- return (other instanceof NameAndType &&
|
|
- name == ((NameAndType) other).name &&
|
|
- uniqueType.equals(((NameAndType) other).uniqueType));
|
|
- }
|
|
-
|
|
- @Override
|
|
- public int hashCode() {
|
|
- return name.hashCode() * uniqueType.hashCode();
|
|
- }
|
|
- }
|
|
}
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
|
|
index 9e6612f6f..47224bbf7 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
|
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
@@ -36,6 +36,7 @@ import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
+import java.util.function.IntFunction;
|
|
|
|
import javax.lang.model.element.Modifier;
|
|
import javax.lang.model.element.NestingKind;
|
|
@@ -55,8 +56,8 @@ import com.sun.tools.javac.code.Type.*;
|
|
import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
|
|
import com.sun.tools.javac.file.BaseFileManager;
|
|
import com.sun.tools.javac.file.PathFileObject;
|
|
-import com.sun.tools.javac.jvm.ClassFile.NameAndType;
|
|
import com.sun.tools.javac.jvm.ClassFile.Version;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
|
|
import com.sun.tools.javac.main.Option;
|
|
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
|
|
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
|
|
@@ -100,11 +101,6 @@ public class ClassReader {
|
|
*/
|
|
boolean verbose;
|
|
|
|
- /** Switch: read constant pool and code sections. This switch is initially
|
|
- * set to false but can be turned on from outside.
|
|
- */
|
|
- public boolean readAllOfClassFile = false;
|
|
-
|
|
/** Switch: allow simplified varargs.
|
|
*/
|
|
boolean allowSimplifiedVarargs;
|
|
@@ -174,20 +170,15 @@ public class ClassReader {
|
|
|
|
/** The buffer containing the currently read class file.
|
|
*/
|
|
- byte[] buf = new byte[INITIAL_BUFFER_SIZE];
|
|
+ ByteBuffer buf = new ByteBuffer(INITIAL_BUFFER_SIZE);
|
|
|
|
/** The current input pointer.
|
|
*/
|
|
protected int bp;
|
|
|
|
- /** The objects of the constant pool.
|
|
- */
|
|
- Object[] poolObj;
|
|
-
|
|
- /** For every constant pool entry, an index into buf where the
|
|
- * defining section of the entry is found.
|
|
+ /** The pool reader.
|
|
*/
|
|
- int[] poolIdx;
|
|
+ PoolReader poolReader;
|
|
|
|
/** The major version number of the class file being read. */
|
|
int majorVersion;
|
|
@@ -328,294 +319,29 @@ public class ClassReader {
|
|
/** Read a character.
|
|
*/
|
|
char nextChar() {
|
|
- return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
|
|
+ char res = buf.getChar(bp);
|
|
+ bp += 2;
|
|
+ return res;
|
|
}
|
|
|
|
/** Read a byte.
|
|
*/
|
|
int nextByte() {
|
|
- return buf[bp++] & 0xFF;
|
|
+ return buf.getByte(bp++) & 0xFF;
|
|
}
|
|
|
|
/** Read an integer.
|
|
*/
|
|
int nextInt() {
|
|
- return
|
|
- ((buf[bp++] & 0xFF) << 24) +
|
|
- ((buf[bp++] & 0xFF) << 16) +
|
|
- ((buf[bp++] & 0xFF) << 8) +
|
|
- (buf[bp++] & 0xFF);
|
|
- }
|
|
-
|
|
- /** Extract a character at position bp from buf.
|
|
- */
|
|
- char getChar(int bp) {
|
|
- return
|
|
- (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF));
|
|
- }
|
|
-
|
|
- /** Extract an integer at position bp from buf.
|
|
- */
|
|
- int getInt(int bp) {
|
|
- return
|
|
- ((buf[bp] & 0xFF) << 24) +
|
|
- ((buf[bp+1] & 0xFF) << 16) +
|
|
- ((buf[bp+2] & 0xFF) << 8) +
|
|
- (buf[bp+3] & 0xFF);
|
|
- }
|
|
-
|
|
-
|
|
- /** Extract a long integer at position bp from buf.
|
|
- */
|
|
- long getLong(int bp) {
|
|
- DataInputStream bufin =
|
|
- new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
|
|
- try {
|
|
- return bufin.readLong();
|
|
- } catch (IOException e) {
|
|
- throw new AssertionError(e);
|
|
- }
|
|
- }
|
|
-
|
|
- /** Extract a float at position bp from buf.
|
|
- */
|
|
- float getFloat(int bp) {
|
|
- DataInputStream bufin =
|
|
- new DataInputStream(new ByteArrayInputStream(buf, bp, 4));
|
|
- try {
|
|
- return bufin.readFloat();
|
|
- } catch (IOException e) {
|
|
- throw new AssertionError(e);
|
|
- }
|
|
- }
|
|
-
|
|
- /** Extract a double at position bp from buf.
|
|
- */
|
|
- double getDouble(int bp) {
|
|
- DataInputStream bufin =
|
|
- new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
|
|
- try {
|
|
- return bufin.readDouble();
|
|
- } catch (IOException e) {
|
|
- throw new AssertionError(e);
|
|
- }
|
|
+ int res = buf.getInt(bp);
|
|
+ bp += 4;
|
|
+ return res;
|
|
}
|
|
|
|
/************************************************************************
|
|
* Constant Pool Access
|
|
***********************************************************************/
|
|
|
|
- /** Index all constant pool entries, writing their start addresses into
|
|
- * poolIdx.
|
|
- */
|
|
- void indexPool() {
|
|
- poolIdx = new int[nextChar()];
|
|
- poolObj = new Object[poolIdx.length];
|
|
- int i = 1;
|
|
- while (i < poolIdx.length) {
|
|
- poolIdx[i++] = bp;
|
|
- byte tag = buf[bp++];
|
|
- switch (tag) {
|
|
- case CONSTANT_Utf8: case CONSTANT_Unicode: {
|
|
- int len = nextChar();
|
|
- bp = bp + len;
|
|
- break;
|
|
- }
|
|
- case CONSTANT_Class:
|
|
- case CONSTANT_String:
|
|
- case CONSTANT_MethodType:
|
|
- case CONSTANT_Module:
|
|
- case CONSTANT_Package:
|
|
- bp = bp + 2;
|
|
- break;
|
|
- case CONSTANT_MethodHandle:
|
|
- bp = bp + 3;
|
|
- break;
|
|
- case CONSTANT_Fieldref:
|
|
- case CONSTANT_Methodref:
|
|
- case CONSTANT_InterfaceMethodref:
|
|
- case CONSTANT_NameandType:
|
|
- case CONSTANT_Integer:
|
|
- case CONSTANT_Float:
|
|
- case CONSTANT_Dynamic:
|
|
- case CONSTANT_InvokeDynamic:
|
|
- bp = bp + 4;
|
|
- break;
|
|
- case CONSTANT_Long:
|
|
- case CONSTANT_Double:
|
|
- bp = bp + 8;
|
|
- i++;
|
|
- break;
|
|
- default:
|
|
- throw badClassFile("bad.const.pool.tag.at",
|
|
- Byte.toString(tag),
|
|
- Integer.toString(bp -1));
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /** Read constant pool entry at start address i, use pool as a cache.
|
|
- */
|
|
- Object readPool(int i) {
|
|
- Object result = poolObj[i];
|
|
- if (result != null) return result;
|
|
-
|
|
- int index = poolIdx[i];
|
|
- if (index == 0) return null;
|
|
-
|
|
- byte tag = buf[index];
|
|
- switch (tag) {
|
|
- case CONSTANT_Utf8:
|
|
- poolObj[i] = names.fromUtf(buf, index + 3, getChar(index + 1));
|
|
- break;
|
|
- case CONSTANT_Unicode:
|
|
- throw badClassFile("unicode.str.not.supported");
|
|
- case CONSTANT_Class:
|
|
- poolObj[i] = readClassOrType(getChar(index + 1));
|
|
- break;
|
|
- case CONSTANT_String:
|
|
- // FIXME: (footprint) do not use toString here
|
|
- poolObj[i] = readName(getChar(index + 1)).toString();
|
|
- break;
|
|
- case CONSTANT_Fieldref: {
|
|
- ClassSymbol owner = readClassSymbol(getChar(index + 1));
|
|
- NameAndType nt = readNameAndType(getChar(index + 3));
|
|
- poolObj[i] = new VarSymbol(0, nt.name, nt.uniqueType.type, owner);
|
|
- break;
|
|
- }
|
|
- case CONSTANT_Methodref:
|
|
- case CONSTANT_InterfaceMethodref: {
|
|
- ClassSymbol owner = readClassSymbol(getChar(index + 1));
|
|
- NameAndType nt = readNameAndType(getChar(index + 3));
|
|
- poolObj[i] = new MethodSymbol(0, nt.name, nt.uniqueType.type, owner);
|
|
- break;
|
|
- }
|
|
- case CONSTANT_NameandType:
|
|
- poolObj[i] = new NameAndType(
|
|
- readName(getChar(index + 1)),
|
|
- readType(getChar(index + 3)), types);
|
|
- break;
|
|
- case CONSTANT_Integer:
|
|
- poolObj[i] = getInt(index + 1);
|
|
- break;
|
|
- case CONSTANT_Float:
|
|
- poolObj[i] = Float.valueOf(getFloat(index + 1));
|
|
- break;
|
|
- case CONSTANT_Long:
|
|
- poolObj[i] = Long.valueOf(getLong(index + 1));
|
|
- break;
|
|
- case CONSTANT_Double:
|
|
- poolObj[i] = Double.valueOf(getDouble(index + 1));
|
|
- break;
|
|
- case CONSTANT_MethodHandle:
|
|
- skipBytes(4);
|
|
- break;
|
|
- case CONSTANT_MethodType:
|
|
- skipBytes(3);
|
|
- break;
|
|
- case CONSTANT_Dynamic:
|
|
- case CONSTANT_InvokeDynamic:
|
|
- skipBytes(5);
|
|
- break;
|
|
- case CONSTANT_Module:
|
|
- case CONSTANT_Package:
|
|
- // this is temporary for now: treat as a simple reference to the underlying Utf8.
|
|
- poolObj[i] = readName(getChar(index + 1));
|
|
- break;
|
|
- default:
|
|
- throw badClassFile("bad.const.pool.tag", Byte.toString(tag));
|
|
- }
|
|
- return poolObj[i];
|
|
- }
|
|
-
|
|
- /** Read signature and convert to type.
|
|
- */
|
|
- Type readType(int i) {
|
|
- int index = poolIdx[i];
|
|
- return sigToType(buf, index + 3, getChar(index + 1));
|
|
- }
|
|
-
|
|
- /** If name is an array type or class signature, return the
|
|
- * corresponding type; otherwise return a ClassSymbol with given name.
|
|
- */
|
|
- Object readClassOrType(int i) {
|
|
- int index = poolIdx[i];
|
|
- int len = getChar(index + 1);
|
|
- int start = index + 3;
|
|
- Assert.check(buf[start] == '[' || buf[start + len - 1] != ';');
|
|
- // by the above assertion, the following test can be
|
|
- // simplified to (buf[start] == '[')
|
|
- return (buf[start] == '[' || buf[start + len - 1] == ';')
|
|
- ? (Object)sigToType(buf, start, len)
|
|
- : (Object)enterClass(names.fromUtf(internalize(buf, start,
|
|
- len)));
|
|
- }
|
|
-
|
|
- /** Read signature and convert to type parameters.
|
|
- */
|
|
- List<Type> readTypeParams(int i) {
|
|
- int index = poolIdx[i];
|
|
- return sigToTypeParams(buf, index + 3, getChar(index + 1));
|
|
- }
|
|
-
|
|
- /** Read class entry.
|
|
- */
|
|
- ClassSymbol readClassSymbol(int i) {
|
|
- Object obj = readPool(i);
|
|
- if (obj != null && !(obj instanceof ClassSymbol))
|
|
- throw badClassFile("bad.const.pool.entry",
|
|
- currentClassFile.toString(),
|
|
- "CONSTANT_Class_info", i);
|
|
- return (ClassSymbol)obj;
|
|
- }
|
|
-
|
|
- Name readClassName(int i) {
|
|
- int index = poolIdx[i];
|
|
- if (index == 0) return null;
|
|
- byte tag = buf[index];
|
|
- if (tag != CONSTANT_Class) {
|
|
- throw badClassFile("bad.const.pool.entry",
|
|
- currentClassFile.toString(),
|
|
- "CONSTANT_Class_info", i);
|
|
- }
|
|
- int nameIndex = poolIdx[getChar(index + 1)];
|
|
- int len = getChar(nameIndex + 1);
|
|
- int start = nameIndex + 3;
|
|
- if (buf[start] == '[' || buf[start + len - 1] == ';')
|
|
- throw badClassFile("wrong class name"); //TODO: proper diagnostics
|
|
- return names.fromUtf(internalize(buf, start, len));
|
|
- }
|
|
-
|
|
- /** Read name.
|
|
- */
|
|
- Name readName(int i) {
|
|
- Object obj = readPool(i);
|
|
- if (obj != null && !(obj instanceof Name))
|
|
- throw badClassFile("bad.const.pool.entry",
|
|
- currentClassFile.toString(),
|
|
- "CONSTANT_Utf8_info or CONSTANT_String_info", i);
|
|
- return (Name)obj;
|
|
- }
|
|
-
|
|
- /** Read name and type.
|
|
- */
|
|
- NameAndType readNameAndType(int i) {
|
|
- Object obj = readPool(i);
|
|
- if (obj != null && !(obj instanceof NameAndType))
|
|
- throw badClassFile("bad.const.pool.entry",
|
|
- currentClassFile.toString(),
|
|
- "CONSTANT_NameAndType_info", i);
|
|
- return (NameAndType)obj;
|
|
- }
|
|
-
|
|
- /** Read the name of a module.
|
|
- * The name is stored in a CONSTANT_Module entry, in
|
|
- * JVMS 4.2 binary form (using ".", not "/")
|
|
- */
|
|
- Name readModuleName(int i) {
|
|
- return readName(i);
|
|
- }
|
|
-
|
|
/** Read module_flags.
|
|
*/
|
|
Set<ModuleFlags> readModuleFlags(int flags) {
|
|
@@ -767,7 +493,7 @@ public class ClassReader {
|
|
List<Type> argtypes = sigToTypes(')');
|
|
Type restype = sigToType();
|
|
List<Type> thrown = List.nil();
|
|
- while (signature[sigp] == '^') {
|
|
+ while (sigp < siglimit && signature[sigp] == '^') {
|
|
sigp++;
|
|
thrown = thrown.prepend(sigToType());
|
|
}
|
|
@@ -860,7 +586,7 @@ public class ClassReader {
|
|
};
|
|
switch (signature[sigp++]) {
|
|
case ';':
|
|
- if (sigp < signature.length && signature[sigp] == '.') {
|
|
+ if (sigp < siglimit && signature[sigp] == '.') {
|
|
// support old-style GJC signatures
|
|
// The signature produced was
|
|
// Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>;
|
|
@@ -1054,7 +780,7 @@ public class ClassReader {
|
|
|
|
new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
|
|
protected void read(Symbol sym, int attrLen) {
|
|
- if (readAllOfClassFile || saveParameterNames)
|
|
+ if (saveParameterNames)
|
|
((MethodSymbol)sym).code = readCode(sym);
|
|
else
|
|
bp = bp + attrLen;
|
|
@@ -1063,7 +789,7 @@ public class ClassReader {
|
|
|
|
new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
|
|
protected void read(Symbol sym, int attrLen) {
|
|
- Object v = readPool(nextChar());
|
|
+ Object v = poolReader.getConstant(nextChar());
|
|
// Ignore ConstantValue attribute if field not final.
|
|
if ((sym.flags() & FINAL) == 0) {
|
|
return;
|
|
@@ -1120,7 +846,7 @@ public class ClassReader {
|
|
int nexceptions = nextChar();
|
|
List<Type> thrown = List.nil();
|
|
for (int j = 0; j < nexceptions; j++)
|
|
- thrown = thrown.prepend(readClassSymbol(nextChar()).type);
|
|
+ thrown = thrown.prepend(poolReader.getClass(nextChar()).type);
|
|
if (sym.type.getThrownTypes().isEmpty())
|
|
sym.type.asMethodType().thrown = thrown.reverse();
|
|
}
|
|
@@ -1178,7 +904,7 @@ public class ClassReader {
|
|
new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
|
|
protected void read(Symbol sym, int attrLen) {
|
|
ClassSymbol c = (ClassSymbol) sym;
|
|
- Name n = readName(nextChar());
|
|
+ Name n = poolReader.getName(nextChar());
|
|
c.sourcefile = new SourceFileObject(n, c.flatname);
|
|
// If the class is a toplevel class, originating from a Java source file,
|
|
// but the class name does not match the file name, then it is
|
|
@@ -1216,7 +942,8 @@ public class ClassReader {
|
|
try {
|
|
ClassType ct1 = (ClassType)c.type;
|
|
Assert.check(c == currentOwner);
|
|
- ct1.typarams_field = readTypeParams(nextChar());
|
|
+ ct1.typarams_field = poolReader.getName(nextChar())
|
|
+ .map(ClassReader.this::sigToTypeParams);
|
|
ct1.supertype_field = sigToType();
|
|
ListBuffer<Type> is = new ListBuffer<>();
|
|
while (sigp != siglimit) is.append(sigToType());
|
|
@@ -1226,7 +953,7 @@ public class ClassReader {
|
|
}
|
|
} else {
|
|
List<Type> thrown = sym.type.getThrownTypes();
|
|
- sym.type = readType(nextChar());
|
|
+ sym.type = poolReader.getType(nextChar());
|
|
//- System.err.println(" # " + sym.type);
|
|
if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
|
|
sym.type.asMethodType().thrown = thrown;
|
|
@@ -1347,19 +1074,19 @@ public class ClassReader {
|
|
ModuleSymbol msym = (ModuleSymbol) sym.owner;
|
|
ListBuffer<Directive> directives = new ListBuffer<>();
|
|
|
|
- Name moduleName = readModuleName(nextChar());
|
|
+ Name moduleName = poolReader.peekModuleName(nextChar(), names::fromUtf);
|
|
if (currentModule.name != moduleName) {
|
|
throw badClassFile("module.name.mismatch", moduleName, currentModule.name);
|
|
}
|
|
|
|
Set<ModuleFlags> moduleFlags = readModuleFlags(nextChar());
|
|
msym.flags.addAll(moduleFlags);
|
|
- msym.version = readName(nextChar());
|
|
+ msym.version = optPoolEntry(nextChar(), poolReader::getName, null);
|
|
|
|
ListBuffer<RequiresDirective> requires = new ListBuffer<>();
|
|
int nrequires = nextChar();
|
|
for (int i = 0; i < nrequires; i++) {
|
|
- ModuleSymbol rsym = syms.enterModule(readModuleName(nextChar()));
|
|
+ ModuleSymbol rsym = poolReader.getModule(nextChar());
|
|
Set<RequiresFlag> flags = readRequiresFlags(nextChar());
|
|
if (rsym == syms.java_base && majorVersion >= V54.major) {
|
|
if (flags.contains(RequiresFlag.TRANSITIVE)) {
|
|
@@ -1378,8 +1105,7 @@ public class ClassReader {
|
|
ListBuffer<ExportsDirective> exports = new ListBuffer<>();
|
|
int nexports = nextChar();
|
|
for (int i = 0; i < nexports; i++) {
|
|
- Name n = readName(nextChar());
|
|
- PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
|
|
+ PackageSymbol p = poolReader.getPackage(nextChar());
|
|
Set<ExportsFlag> flags = readExportsFlags(nextChar());
|
|
int nto = nextChar();
|
|
List<ModuleSymbol> to;
|
|
@@ -1388,7 +1114,7 @@ public class ClassReader {
|
|
} else {
|
|
ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
|
|
for (int t = 0; t < nto; t++)
|
|
- lb.append(syms.enterModule(readModuleName(nextChar())));
|
|
+ lb.append(poolReader.getModule(nextChar()));
|
|
to = lb.toList();
|
|
}
|
|
exports.add(new ExportsDirective(p, to, flags));
|
|
@@ -1401,8 +1127,7 @@ public class ClassReader {
|
|
throw badClassFile("module.non.zero.opens", currentModule.name);
|
|
}
|
|
for (int i = 0; i < nopens; i++) {
|
|
- Name n = readName(nextChar());
|
|
- PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
|
|
+ PackageSymbol p = poolReader.getPackage(nextChar());
|
|
Set<OpensFlag> flags = readOpensFlags(nextChar());
|
|
int nto = nextChar();
|
|
List<ModuleSymbol> to;
|
|
@@ -1411,7 +1136,7 @@ public class ClassReader {
|
|
} else {
|
|
ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
|
|
for (int t = 0; t < nto; t++)
|
|
- lb.append(syms.enterModule(readModuleName(nextChar())));
|
|
+ lb.append(poolReader.getModule(nextChar()));
|
|
to = lb.toList();
|
|
}
|
|
opens.add(new OpensDirective(p, to, flags));
|
|
@@ -1424,7 +1149,7 @@ public class ClassReader {
|
|
ListBuffer<InterimUsesDirective> uses = new ListBuffer<>();
|
|
int nuses = nextChar();
|
|
for (int i = 0; i < nuses; i++) {
|
|
- Name srvc = readClassName(nextChar());
|
|
+ Name srvc = poolReader.peekClassName(nextChar(), this::classNameMapper);
|
|
uses.add(new InterimUsesDirective(srvc));
|
|
}
|
|
interimUses = uses.toList();
|
|
@@ -1432,17 +1157,21 @@ public class ClassReader {
|
|
ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>();
|
|
int nprovides = nextChar();
|
|
for (int p = 0; p < nprovides; p++) {
|
|
- Name srvc = readClassName(nextChar());
|
|
+ Name srvc = poolReader.peekClassName(nextChar(), this::classNameMapper);
|
|
int nimpls = nextChar();
|
|
ListBuffer<Name> impls = new ListBuffer<>();
|
|
for (int i = 0; i < nimpls; i++) {
|
|
- impls.append(readClassName(nextChar()));
|
|
+ impls.append(poolReader.peekClassName(nextChar(), this::classNameMapper));
|
|
provides.add(new InterimProvidesDirective(srvc, impls.toList()));
|
|
}
|
|
}
|
|
interimProvides = provides.toList();
|
|
}
|
|
}
|
|
+
|
|
+ private Name classNameMapper(byte[] arr, int offset, int length) {
|
|
+ return names.fromUtf(ClassFile.internalize(arr, offset, length));
|
|
+ }
|
|
},
|
|
|
|
new AttributeReader(names.ModuleResolution, V53, CLASS_ATTRIBUTE) {
|
|
@@ -1469,8 +1198,8 @@ public class ClassReader {
|
|
// the scope specified by the attribute
|
|
sym.owner.members().remove(sym);
|
|
ClassSymbol self = (ClassSymbol)sym;
|
|
- ClassSymbol c = readClassSymbol(nextChar());
|
|
- NameAndType nt = readNameAndType(nextChar());
|
|
+ ClassSymbol c = poolReader.getClass(nextChar());
|
|
+ NameAndType nt = optPoolEntry(nextChar(), poolReader::getNameAndType, null);
|
|
|
|
if (c.members_field == null || c.kind != TYP)
|
|
throw badClassFile("bad.enclosing.class", self, c);
|
|
@@ -1521,7 +1250,7 @@ public class ClassReader {
|
|
if (nt == null)
|
|
return null;
|
|
|
|
- MethodType type = nt.uniqueType.type.asMethodType();
|
|
+ MethodType type = nt.type.asMethodType();
|
|
|
|
for (Symbol sym : scope.getSymbolsByName(nt.name)) {
|
|
if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
|
|
@@ -1534,15 +1263,15 @@ public class ClassReader {
|
|
if ((flags & INTERFACE) != 0)
|
|
// no enclosing instance
|
|
return null;
|
|
- if (nt.uniqueType.type.getParameterTypes().isEmpty())
|
|
+ if (nt.type.getParameterTypes().isEmpty())
|
|
// no parameters
|
|
return null;
|
|
|
|
// A constructor of an inner class.
|
|
// Remove the first argument (the enclosing instance)
|
|
- nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail,
|
|
- nt.uniqueType.type.getReturnType(),
|
|
- nt.uniqueType.type.getThrownTypes(),
|
|
+ nt = new NameAndType(nt.name, new MethodType(nt.type.getParameterTypes().tail,
|
|
+ nt.type.getReturnType(),
|
|
+ nt.type.getThrownTypes(),
|
|
syms.methodClass));
|
|
// Try searching again
|
|
return findMethod(nt, scope, flags);
|
|
@@ -1579,7 +1308,7 @@ public class ClassReader {
|
|
void readAttrs(Symbol sym, AttributeKind kind) {
|
|
char ac = nextChar();
|
|
for (int i = 0; i < ac; i++) {
|
|
- Name attrName = readName(nextChar());
|
|
+ Name attrName = poolReader.getName(nextChar());
|
|
int attrLen = nextInt();
|
|
AttributeReader r = attributeReaders.get(attrName);
|
|
if (r != null && r.accepts(kind))
|
|
@@ -1682,7 +1411,7 @@ public class ClassReader {
|
|
/** Read parameter annotations.
|
|
*/
|
|
void readParameterAnnotations(Symbol meth) {
|
|
- int numParameters = buf[bp++] & 0xFF;
|
|
+ int numParameters = buf.getByte(bp++) & 0xFF;
|
|
if (parameterAnnotations == null) {
|
|
parameterAnnotations = new ParameterAnnotations[numParameters];
|
|
} else if (parameterAnnotations.length != numParameters) {
|
|
@@ -1726,39 +1455,30 @@ public class ClassReader {
|
|
|
|
Type readTypeOrClassSymbol(int i) {
|
|
// support preliminary jsr175-format class files
|
|
- if (buf[poolIdx[i]] == CONSTANT_Class)
|
|
- return readClassSymbol(i).type;
|
|
- return readTypeToProxy(i);
|
|
- }
|
|
- Type readEnumType(int i) {
|
|
- // support preliminary jsr175-format class files
|
|
- int index = poolIdx[i];
|
|
- int length = getChar(index + 1);
|
|
- if (buf[index + length + 2] != ';')
|
|
- return enterClass(readName(i)).type;
|
|
+ if (poolReader.hasTag(i, CONSTANT_Class))
|
|
+ return poolReader.getClass(i).type;
|
|
return readTypeToProxy(i);
|
|
}
|
|
Type readTypeToProxy(int i) {
|
|
if (currentModule.module_info == currentOwner) {
|
|
- int index = poolIdx[i];
|
|
- return new ProxyType(Arrays.copyOfRange(buf, index + 3, index + 3 + getChar(index + 1)));
|
|
+ return new ProxyType(i);
|
|
} else {
|
|
- return readType(i);
|
|
+ return poolReader.getType(i);
|
|
}
|
|
}
|
|
|
|
CompoundAnnotationProxy readCompoundAnnotation() {
|
|
Type t;
|
|
if (currentModule.module_info == currentOwner) {
|
|
- int index = poolIdx[nextChar()];
|
|
- t = new ProxyType(Arrays.copyOfRange(buf, index + 3, index + 3 + getChar(index + 1)));
|
|
+ int cpIndex = nextChar();
|
|
+ t = new ProxyType(cpIndex);
|
|
} else {
|
|
t = readTypeOrClassSymbol(nextChar());
|
|
}
|
|
int numFields = nextChar();
|
|
ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>();
|
|
for (int i=0; i<numFields; i++) {
|
|
- Name name = readName(nextChar());
|
|
+ Name name = poolReader.getName(nextChar());
|
|
Attribute value = readAttributeValue();
|
|
pairs.append(new Pair<>(name, value));
|
|
}
|
|
@@ -1971,29 +1691,40 @@ public class ClassReader {
|
|
|
|
}
|
|
|
|
+ /**
|
|
+ * Helper function to read an optional pool entry (with given function); this is used while parsing
|
|
+ * InnerClasses and EnclosingMethod attributes, as well as when parsing supertype descriptor,
|
|
+ * as per JVMS.
|
|
+ */
|
|
+ <Z> Z optPoolEntry(int index, IntFunction<Z> poolFunc, Z defaultValue) {
|
|
+ return (index == 0) ?
|
|
+ defaultValue :
|
|
+ poolFunc.apply(index);
|
|
+ }
|
|
+
|
|
Attribute readAttributeValue() {
|
|
- char c = (char) buf[bp++];
|
|
+ char c = (char) buf.getByte(bp++);
|
|
switch (c) {
|
|
case 'B':
|
|
- return new Attribute.Constant(syms.byteType, readPool(nextChar()));
|
|
+ return new Attribute.Constant(syms.byteType, poolReader.getConstant(nextChar()));
|
|
case 'C':
|
|
- return new Attribute.Constant(syms.charType, readPool(nextChar()));
|
|
+ return new Attribute.Constant(syms.charType, poolReader.getConstant(nextChar()));
|
|
case 'D':
|
|
- return new Attribute.Constant(syms.doubleType, readPool(nextChar()));
|
|
+ return new Attribute.Constant(syms.doubleType, poolReader.getConstant(nextChar()));
|
|
case 'F':
|
|
- return new Attribute.Constant(syms.floatType, readPool(nextChar()));
|
|
+ return new Attribute.Constant(syms.floatType, poolReader.getConstant(nextChar()));
|
|
case 'I':
|
|
- return new Attribute.Constant(syms.intType, readPool(nextChar()));
|
|
+ return new Attribute.Constant(syms.intType, poolReader.getConstant(nextChar()));
|
|
case 'J':
|
|
- return new Attribute.Constant(syms.longType, readPool(nextChar()));
|
|
+ return new Attribute.Constant(syms.longType, poolReader.getConstant(nextChar()));
|
|
case 'S':
|
|
- return new Attribute.Constant(syms.shortType, readPool(nextChar()));
|
|
+ return new Attribute.Constant(syms.shortType, poolReader.getConstant(nextChar()));
|
|
case 'Z':
|
|
- return new Attribute.Constant(syms.booleanType, readPool(nextChar()));
|
|
+ return new Attribute.Constant(syms.booleanType, poolReader.getConstant(nextChar()));
|
|
case 's':
|
|
- return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString());
|
|
+ return new Attribute.Constant(syms.stringType, poolReader.getName(nextChar()).toString());
|
|
case 'e':
|
|
- return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar()));
|
|
+ return new EnumAttributeProxy(readTypeToProxy(nextChar()), poolReader.getName(nextChar()));
|
|
case 'c':
|
|
return new ClassAttributeProxy(readTypeOrClassSymbol(nextChar()));
|
|
case '[': {
|
|
@@ -2402,8 +2133,8 @@ public class ClassReader {
|
|
*/
|
|
VarSymbol readField() {
|
|
long flags = adjustFieldFlags(nextChar());
|
|
- Name name = readName(nextChar());
|
|
- Type type = readType(nextChar());
|
|
+ Name name = poolReader.getName(nextChar());
|
|
+ Type type = poolReader.getType(nextChar());
|
|
VarSymbol v = new VarSymbol(flags, name, type, currentOwner);
|
|
readMemberAttrs(v);
|
|
return v;
|
|
@@ -2413,8 +2144,8 @@ public class ClassReader {
|
|
*/
|
|
MethodSymbol readMethod() {
|
|
long flags = adjustMethodFlags(nextChar());
|
|
- Name name = readName(nextChar());
|
|
- Type type = readType(nextChar());
|
|
+ Name name = poolReader.getName(nextChar());
|
|
+ Type type = poolReader.getType(nextChar());
|
|
if (currentOwner.isInterface() &&
|
|
(flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
|
|
if (majorVersion > Version.V52.major ||
|
|
@@ -2558,14 +2289,12 @@ public class ClassReader {
|
|
firstParam += skip;
|
|
}
|
|
}
|
|
- List<Name> paramNames = List.nil();
|
|
+ Set<Name> paramNames = new HashSet<>();
|
|
ListBuffer<VarSymbol> params = new ListBuffer<>();
|
|
int nameIndex = firstParam;
|
|
int annotationIndex = 0;
|
|
for (Type t: sym.type.getParameterTypes()) {
|
|
- Name name = parameterName(nameIndex, paramNames);
|
|
- paramNames = paramNames.prepend(name);
|
|
- VarSymbol param = new VarSymbol(PARAMETER, name, t, sym);
|
|
+ VarSymbol param = parameter(nameIndex, t, sym, paramNames);
|
|
params.append(param);
|
|
if (parameterAnnotations != null) {
|
|
ParameterAnnotations annotations = parameterAnnotations[annotationIndex];
|
|
@@ -2590,18 +2319,24 @@ public class ClassReader {
|
|
// Returns the name for the parameter at position 'index', either using
|
|
// names read from the MethodParameters, or by synthesizing a name that
|
|
// is not on the 'exclude' list.
|
|
- private Name parameterName(int index, List<Name> exclude) {
|
|
+ private VarSymbol parameter(int index, Type t, MethodSymbol owner, Set<Name> exclude) {
|
|
+ long flags = PARAMETER;
|
|
+ Name argName;
|
|
if (parameterNameIndices != null && index < parameterNameIndices.length
|
|
&& parameterNameIndices[index] != 0) {
|
|
- return readName(parameterNameIndices[index]);
|
|
- }
|
|
- String prefix = "arg";
|
|
- while (true) {
|
|
- Name argName = names.fromString(prefix + exclude.size());
|
|
- if (!exclude.contains(argName))
|
|
- return argName;
|
|
- prefix += "$";
|
|
+ argName = optPoolEntry(parameterNameIndices[index], poolReader::getName, names.empty);
|
|
+ flags |= NAME_FILLED;
|
|
+ } else {
|
|
+ String prefix = "arg";
|
|
+ while (true) {
|
|
+ argName = names.fromString(prefix + exclude.size());
|
|
+ if (!exclude.contains(argName))
|
|
+ break;
|
|
+ prefix += "$";
|
|
+ }
|
|
}
|
|
+ exclude.add(argName);
|
|
+ return new ParamSymbol(flags, argName, t, owner);
|
|
}
|
|
|
|
/**
|
|
@@ -2680,7 +2415,7 @@ public class ClassReader {
|
|
if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
|
|
// read own class name and check that it matches
|
|
currentModule = c.packge().modle;
|
|
- ClassSymbol self = readClassSymbol(nextChar());
|
|
+ ClassSymbol self = poolReader.getClass(nextChar());
|
|
if (c != self) {
|
|
throw badClassFile("class.file.wrong.class",
|
|
self.flatname);
|
|
@@ -2709,11 +2444,6 @@ public class ClassReader {
|
|
for (int i = 0; i < methodCount; i++) skipMember();
|
|
readClassAttrs(c);
|
|
|
|
- if (readAllOfClassFile) {
|
|
- for (int i = 1; i < poolObj.length; i++) readPool(i);
|
|
- c.pool = new Pool(poolObj.length, poolObj, types);
|
|
- }
|
|
-
|
|
// reset and read rest of classinfo
|
|
bp = startbp;
|
|
int n = nextChar();
|
|
@@ -2721,13 +2451,12 @@ public class ClassReader {
|
|
throw badClassFile("module.info.invalid.super.class");
|
|
}
|
|
if (ct.supertype_field == null)
|
|
- ct.supertype_field = (n == 0)
|
|
- ? Type.noType
|
|
- : readClassSymbol(n).erasure(types);
|
|
+ ct.supertype_field =
|
|
+ optPoolEntry(n, idx -> poolReader.getClass(idx).erasure(types), Type.noType);
|
|
n = nextChar();
|
|
List<Type> is = List.nil();
|
|
for (int i = 0; i < n; i++) {
|
|
- Type _inter = readClassSymbol(nextChar()).erasure(types);
|
|
+ Type _inter = poolReader.getClass(nextChar()).erasure(types);
|
|
is = is.prepend(_inter);
|
|
}
|
|
if (ct.interfaces_field == null)
|
|
@@ -2748,8 +2477,10 @@ public class ClassReader {
|
|
int n = nextChar();
|
|
for (int i = 0; i < n; i++) {
|
|
nextChar(); // skip inner class symbol
|
|
- ClassSymbol outer = readClassSymbol(nextChar());
|
|
- Name name = readName(nextChar());
|
|
+ int outerIdx = nextChar();
|
|
+ int nameIdx = nextChar();
|
|
+ ClassSymbol outer = optPoolEntry(outerIdx, poolReader::getClass, null);
|
|
+ Name name = optPoolEntry(nameIdx, poolReader::getName, names.empty);
|
|
if (name == null) name = names.empty;
|
|
long flags = adjustClassFlags(nextChar());
|
|
if (outer != null) { // we have a member class
|
|
@@ -2803,7 +2534,8 @@ public class ClassReader {
|
|
}
|
|
}
|
|
|
|
- indexPool();
|
|
+ poolReader = new PoolReader(this, names, syms);
|
|
+ bp = poolReader.readPool(buf, bp);
|
|
if (signatureBuffer.length < bp) {
|
|
int ns = Integer.highestOneBit(bp) << 1;
|
|
signatureBuffer = new byte[ns];
|
|
@@ -2820,7 +2552,8 @@ public class ClassReader {
|
|
repeatable = null;
|
|
try {
|
|
bp = 0;
|
|
- buf = readInputStream(buf, c.classfile.openInputStream());
|
|
+ buf.reset();
|
|
+ buf.appendStream(c.classfile.openInputStream());
|
|
readClassBuffer(c);
|
|
if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
|
|
List<Type> missing = missingTypeVariables;
|
|
@@ -2874,43 +2607,6 @@ public class ClassReader {
|
|
filling = false;
|
|
}
|
|
}
|
|
- // where
|
|
- private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
|
|
- try {
|
|
- buf = ensureCapacity(buf, s.available());
|
|
- int r = s.read(buf);
|
|
- int bp = 0;
|
|
- while (r != -1) {
|
|
- bp += r;
|
|
- buf = ensureCapacity(buf, bp);
|
|
- r = s.read(buf, bp, buf.length - bp);
|
|
- }
|
|
- return buf;
|
|
- } finally {
|
|
- try {
|
|
- s.close();
|
|
- } catch (IOException e) {
|
|
- /* Ignore any errors, as this stream may have already
|
|
- * thrown a related exception which is the one that
|
|
- * should be reported.
|
|
- */
|
|
- }
|
|
- }
|
|
- }
|
|
- /*
|
|
- * ensureCapacity will increase the buffer as needed, taking note that
|
|
- * the new buffer will always be greater than the needed and never
|
|
- * exactly equal to the needed size or bp. If equal then the read (above)
|
|
- * will infinitely loop as buf.length - bp == 0.
|
|
- */
|
|
- private static byte[] ensureCapacity(byte[] buf, int needed) {
|
|
- if (buf.length <= needed) {
|
|
- byte[] old = buf;
|
|
- buf = new byte[Integer.highestOneBit(needed) << 1];
|
|
- System.arraycopy(old, 0, buf, 0, old.length);
|
|
- }
|
|
- return buf;
|
|
- }
|
|
|
|
/** We can only read a single class file at a time; this
|
|
* flag keeps track of when we are currently reading a class
|
|
@@ -3099,11 +2795,11 @@ public class ClassReader {
|
|
|
|
private class ProxyType extends Type {
|
|
|
|
- private final byte[] content;
|
|
+ private final Name name;
|
|
|
|
- public ProxyType(byte[] content) {
|
|
+ public ProxyType(int index) {
|
|
super(syms.noSymbol, TypeMetadata.EMPTY);
|
|
- this.content = content;
|
|
+ this.name = poolReader.getName(index);
|
|
}
|
|
|
|
@Override
|
|
@@ -3117,7 +2813,7 @@ public class ClassReader {
|
|
}
|
|
|
|
public Type resolve() {
|
|
- return sigToType(content, 0, content.length);
|
|
+ return name.map(ClassReader.this::sigToType);
|
|
}
|
|
|
|
@Override @DefinedBy(Api.LANGUAGE_MODEL)
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
|
|
index b73c2f835..5f956e1df 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
|
|
@@ -29,9 +29,7 @@ import java.io.*;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
-import java.util.HashSet;
|
|
import java.util.LinkedHashSet;
|
|
-import java.util.stream.Collectors;
|
|
|
|
import javax.tools.JavaFileManager;
|
|
import javax.tools.FileObject;
|
|
@@ -44,13 +42,10 @@ import com.sun.tools.javac.code.Directive.*;
|
|
import com.sun.tools.javac.code.Symbol.*;
|
|
import com.sun.tools.javac.code.Type.*;
|
|
import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;
|
|
-import com.sun.tools.javac.code.Types.UniqueType;
|
|
import com.sun.tools.javac.comp.Check;
|
|
import com.sun.tools.javac.file.PathFileObject;
|
|
-import com.sun.tools.javac.jvm.Pool.DynamicMethod;
|
|
-import com.sun.tools.javac.jvm.Pool.Method;
|
|
-import com.sun.tools.javac.jvm.Pool.MethodHandle;
|
|
-import com.sun.tools.javac.jvm.Pool.Variable;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.Dynamic.BsmKey;
|
|
import com.sun.tools.javac.resources.CompilerProperties.Errors;
|
|
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
|
|
import com.sun.tools.javac.util.*;
|
|
@@ -121,7 +116,7 @@ public class ClassWriter extends ClassFile {
|
|
* Sizes are increased when buffers get full.
|
|
*/
|
|
static final int DATA_BUF_SIZE = 0x0fff0;
|
|
- static final int POOL_BUF_SIZE = 0x1fff0;
|
|
+ static final int CLASS_BUF_SIZE = 0x1fff0;
|
|
|
|
/** An output buffer for member info.
|
|
*/
|
|
@@ -129,25 +124,11 @@ public class ClassWriter extends ClassFile {
|
|
|
|
/** An output buffer for the constant pool.
|
|
*/
|
|
- ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE);
|
|
+ ByteBuffer poolbuf = new ByteBuffer(CLASS_BUF_SIZE);
|
|
|
|
- /** The constant pool.
|
|
+ /** The constant pool writer.
|
|
*/
|
|
- Pool pool;
|
|
-
|
|
- /** The inner classes to be written, as a set.
|
|
- */
|
|
- Set<ClassSymbol> innerClasses;
|
|
-
|
|
- /** The inner classes to be written, as a queue where
|
|
- * enclosing classes come first.
|
|
- */
|
|
- ListBuffer<ClassSymbol> innerClassesQueue;
|
|
-
|
|
- /** The bootstrap methods to be written in the corresponding class attribute
|
|
- * (one for each invokedynamic)
|
|
- */
|
|
- Map<DynamicMethod.BootstrapMethodsKey, DynamicMethod.BootstrapMethodsValue> bootstrapMethods;
|
|
+ final PoolWriter poolWriter;
|
|
|
|
/** The log to use for verbose output.
|
|
*/
|
|
@@ -159,9 +140,6 @@ public class ClassWriter extends ClassFile {
|
|
/** Access to files. */
|
|
private final JavaFileManager fileManager;
|
|
|
|
- /** Sole signature generator */
|
|
- private final CWSignatureGenerator signatureGen;
|
|
-
|
|
/** The tags and constants used in compressed stackmap. */
|
|
static final int SAME_FRAME_SIZE = 64;
|
|
static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
|
|
@@ -191,7 +169,7 @@ public class ClassWriter extends ClassFile {
|
|
types = Types.instance(context);
|
|
check = Check.instance(context);
|
|
fileManager = context.get(JavaFileManager.class);
|
|
- signatureGen = new CWSignatureGenerator(types);
|
|
+ poolWriter = Gen.instance(context).poolWriter;
|
|
|
|
verbose = options.isSet(VERBOSE);
|
|
genCrt = options.isSet(XJCOV);
|
|
@@ -272,108 +250,17 @@ public class ClassWriter extends ClassFile {
|
|
buf.elems[adr+3] = (byte)((x ) & 0xFF);
|
|
}
|
|
|
|
- /**
|
|
- * Signature Generation
|
|
- */
|
|
- private class CWSignatureGenerator extends Types.SignatureGenerator {
|
|
-
|
|
- /**
|
|
- * An output buffer for type signatures.
|
|
- */
|
|
- ByteBuffer sigbuf = new ByteBuffer();
|
|
-
|
|
- CWSignatureGenerator(Types types) {
|
|
- super(types);
|
|
- }
|
|
-
|
|
- /**
|
|
- * Assemble signature of given type in string buffer.
|
|
- * Check for uninitialized types before calling the general case.
|
|
- */
|
|
- @Override
|
|
- public void assembleSig(Type type) {
|
|
- switch (type.getTag()) {
|
|
- case UNINITIALIZED_THIS:
|
|
- case UNINITIALIZED_OBJECT:
|
|
- // we don't yet have a spec for uninitialized types in the
|
|
- // local variable table
|
|
- assembleSig(types.erasure(((UninitializedType)type).qtype));
|
|
- break;
|
|
- default:
|
|
- super.assembleSig(type);
|
|
- }
|
|
- }
|
|
-
|
|
- @Override
|
|
- protected void append(char ch) {
|
|
- sigbuf.appendByte(ch);
|
|
- }
|
|
-
|
|
- @Override
|
|
- protected void append(byte[] ba) {
|
|
- sigbuf.appendBytes(ba);
|
|
- }
|
|
-
|
|
- @Override
|
|
- protected void append(Name name) {
|
|
- sigbuf.appendName(name);
|
|
- }
|
|
-
|
|
- @Override
|
|
- protected void classReference(ClassSymbol c) {
|
|
- enterInner(c);
|
|
- }
|
|
-
|
|
- private void reset() {
|
|
- sigbuf.reset();
|
|
- }
|
|
-
|
|
- private Name toName() {
|
|
- return sigbuf.toName(names);
|
|
- }
|
|
-
|
|
- private boolean isEmpty() {
|
|
- return sigbuf.length == 0;
|
|
- }
|
|
- }
|
|
-
|
|
- /**
|
|
- * Return signature of given type
|
|
- */
|
|
- Name typeSig(Type type) {
|
|
- Assert.check(signatureGen.isEmpty());
|
|
- //- System.out.println(" ? " + type);
|
|
- signatureGen.assembleSig(type);
|
|
- Name n = signatureGen.toName();
|
|
- signatureGen.reset();
|
|
- //- System.out.println(" " + n);
|
|
- return n;
|
|
- }
|
|
-
|
|
- /** Given a type t, return the extended class name of its erasure in
|
|
- * external representation.
|
|
- */
|
|
- public Name xClassName(Type t) {
|
|
- if (t.hasTag(CLASS)) {
|
|
- return names.fromUtf(externalize(t.tsym.flatName()));
|
|
- } else if (t.hasTag(ARRAY)) {
|
|
- return typeSig(types.erasure(t));
|
|
- } else {
|
|
- throw new AssertionError("xClassName expects class or array type, got " + t);
|
|
- }
|
|
- }
|
|
-
|
|
/******************************************************************
|
|
* Writing the Constant Pool
|
|
******************************************************************/
|
|
|
|
/** Thrown when the constant pool is over full.
|
|
*/
|
|
- public static class PoolOverflow extends Exception {
|
|
+ public static class PoolOverflow extends RuntimeException {
|
|
private static final long serialVersionUID = 0;
|
|
public PoolOverflow() {}
|
|
}
|
|
- public static class StringOverflow extends Exception {
|
|
+ public static class StringOverflow extends RuntimeException {
|
|
private static final long serialVersionUID = 0;
|
|
public final String value;
|
|
public StringOverflow(String s) {
|
|
@@ -381,137 +268,6 @@ public class ClassWriter extends ClassFile {
|
|
}
|
|
}
|
|
|
|
- /** Write constant pool to pool buffer.
|
|
- * Note: during writing, constant pool
|
|
- * might grow since some parts of constants still need to be entered.
|
|
- */
|
|
- void writePool(Pool pool) throws PoolOverflow, StringOverflow {
|
|
- int poolCountIdx = poolbuf.length;
|
|
- poolbuf.appendChar(0);
|
|
- int i = 1;
|
|
- while (i < pool.pp) {
|
|
- Object value = pool.pool[i];
|
|
- Assert.checkNonNull(value);
|
|
- if (value instanceof Method || value instanceof Variable)
|
|
- value = ((DelegatedSymbol)value).getUnderlyingSymbol();
|
|
-
|
|
- if (value instanceof MethodSymbol) {
|
|
- MethodSymbol m = (MethodSymbol)value;
|
|
- if (!m.isDynamic()) {
|
|
- poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0
|
|
- ? CONSTANT_InterfaceMethodref
|
|
- : CONSTANT_Methodref);
|
|
- poolbuf.appendChar(pool.put(m.owner));
|
|
- poolbuf.appendChar(pool.put(nameType(m)));
|
|
- } else {
|
|
- //invokedynamic
|
|
- DynamicMethodSymbol dynSym = (DynamicMethodSymbol)m;
|
|
- MethodHandle handle = new MethodHandle(dynSym.bsmKind, dynSym.bsm, types);
|
|
- DynamicMethod.BootstrapMethodsKey key = new DynamicMethod.BootstrapMethodsKey(dynSym, types);
|
|
-
|
|
- // Figure out the index for existing BSM; create a new BSM if no key
|
|
- DynamicMethod.BootstrapMethodsValue val = bootstrapMethods.get(key);
|
|
- if (val == null) {
|
|
- int index = bootstrapMethods.size();
|
|
- val = new DynamicMethod.BootstrapMethodsValue(handle, index);
|
|
- bootstrapMethods.put(key, val);
|
|
- }
|
|
-
|
|
- //init cp entries
|
|
- pool.put(names.BootstrapMethods);
|
|
- pool.put(handle);
|
|
- for (Object staticArg : dynSym.staticArgs) {
|
|
- pool.put(staticArg);
|
|
- }
|
|
- poolbuf.appendByte(CONSTANT_InvokeDynamic);
|
|
- poolbuf.appendChar(val.index);
|
|
- poolbuf.appendChar(pool.put(nameType(dynSym)));
|
|
- }
|
|
- } else if (value instanceof VarSymbol) {
|
|
- VarSymbol v = (VarSymbol)value;
|
|
- poolbuf.appendByte(CONSTANT_Fieldref);
|
|
- poolbuf.appendChar(pool.put(v.owner));
|
|
- poolbuf.appendChar(pool.put(nameType(v)));
|
|
- } else if (value instanceof Name) {
|
|
- poolbuf.appendByte(CONSTANT_Utf8);
|
|
- byte[] bs = ((Name)value).toUtf();
|
|
- poolbuf.appendChar(bs.length);
|
|
- poolbuf.appendBytes(bs, 0, bs.length);
|
|
- if (bs.length > Pool.MAX_STRING_LENGTH)
|
|
- throw new StringOverflow(value.toString());
|
|
- } else if (value instanceof ClassSymbol) {
|
|
- ClassSymbol c = (ClassSymbol)value;
|
|
- if (c.owner.kind == TYP) pool.put(c.owner);
|
|
- poolbuf.appendByte(CONSTANT_Class);
|
|
- if (c.type.hasTag(ARRAY)) {
|
|
- poolbuf.appendChar(pool.put(typeSig(c.type)));
|
|
- } else {
|
|
- poolbuf.appendChar(pool.put(names.fromUtf(externalize(c.flatname))));
|
|
- enterInner(c);
|
|
- }
|
|
- } else if (value instanceof NameAndType) {
|
|
- NameAndType nt = (NameAndType)value;
|
|
- poolbuf.appendByte(CONSTANT_NameandType);
|
|
- poolbuf.appendChar(pool.put(nt.name));
|
|
- poolbuf.appendChar(pool.put(typeSig(nt.uniqueType.type)));
|
|
- } else if (value instanceof Integer) {
|
|
- poolbuf.appendByte(CONSTANT_Integer);
|
|
- poolbuf.appendInt(((Integer)value).intValue());
|
|
- } else if (value instanceof Long) {
|
|
- poolbuf.appendByte(CONSTANT_Long);
|
|
- poolbuf.appendLong(((Long)value).longValue());
|
|
- i++;
|
|
- } else if (value instanceof Float) {
|
|
- poolbuf.appendByte(CONSTANT_Float);
|
|
- poolbuf.appendFloat(((Float)value).floatValue());
|
|
- } else if (value instanceof Double) {
|
|
- poolbuf.appendByte(CONSTANT_Double);
|
|
- poolbuf.appendDouble(((Double)value).doubleValue());
|
|
- i++;
|
|
- } else if (value instanceof String) {
|
|
- poolbuf.appendByte(CONSTANT_String);
|
|
- poolbuf.appendChar(pool.put(names.fromString((String)value)));
|
|
- } else if (value instanceof UniqueType) {
|
|
- Type type = ((UniqueType)value).type;
|
|
- if (type.hasTag(METHOD)) {
|
|
- poolbuf.appendByte(CONSTANT_MethodType);
|
|
- poolbuf.appendChar(pool.put(typeSig((MethodType)type)));
|
|
- } else {
|
|
- Assert.check(type.hasTag(ARRAY));
|
|
- poolbuf.appendByte(CONSTANT_Class);
|
|
- poolbuf.appendChar(pool.put(xClassName(type)));
|
|
- }
|
|
- } else if (value instanceof MethodHandle) {
|
|
- MethodHandle ref = (MethodHandle)value;
|
|
- poolbuf.appendByte(CONSTANT_MethodHandle);
|
|
- poolbuf.appendByte(ref.refKind);
|
|
- poolbuf.appendChar(pool.put(ref.refSym));
|
|
- } else if (value instanceof ModuleSymbol) {
|
|
- ModuleSymbol m = (ModuleSymbol)value;
|
|
- poolbuf.appendByte(CONSTANT_Module);
|
|
- poolbuf.appendChar(pool.put(m.name));
|
|
- } else if (value instanceof PackageSymbol) {
|
|
- PackageSymbol m = (PackageSymbol)value;
|
|
- poolbuf.appendByte(CONSTANT_Package);
|
|
- poolbuf.appendChar(pool.put(names.fromUtf(externalize(m.fullname))));
|
|
- } else {
|
|
- Assert.error("writePool " + value);
|
|
- }
|
|
- i++;
|
|
- }
|
|
- if (pool.pp > Pool.MAX_ENTRIES)
|
|
- throw new PoolOverflow();
|
|
- putChar(poolbuf, poolCountIdx, pool.pp);
|
|
- }
|
|
-
|
|
- /** Given a symbol, return its name-and-type.
|
|
- */
|
|
- NameAndType nameType(Symbol sym) {
|
|
- return new NameAndType(sym.name, sym.externalType(types), types);
|
|
- // the NameAndType is generated from a symbol reference, and the
|
|
- // adjustment of adding an additional this$n parameter needs to be made.
|
|
- }
|
|
-
|
|
/******************************************************************
|
|
* Writing Attributes
|
|
******************************************************************/
|
|
@@ -520,7 +276,8 @@ public class ClassWriter extends ClassFile {
|
|
* position past attribute length index.
|
|
*/
|
|
int writeAttr(Name attrName) {
|
|
- databuf.appendChar(pool.put(attrName));
|
|
+ int index = poolWriter.putName(attrName);
|
|
+ databuf.appendChar(index);
|
|
databuf.appendInt(0);
|
|
return databuf.length;
|
|
}
|
|
@@ -567,8 +324,8 @@ public class ClassWriter extends ClassFile {
|
|
|| c.owner.kind != MTH) // or member init
|
|
? null
|
|
: (MethodSymbol)c.owner;
|
|
- databuf.appendChar(pool.put(enclClass));
|
|
- databuf.appendChar(enclMethod == null ? 0 : pool.put(nameType(c.owner)));
|
|
+ databuf.appendChar(poolWriter.putClass(enclClass));
|
|
+ databuf.appendChar(enclMethod == null ? 0 : poolWriter.putNameAndType(c.owner));
|
|
endAttr(alenIdx);
|
|
return 1;
|
|
}
|
|
@@ -594,11 +351,11 @@ public class ClassWriter extends ClassFile {
|
|
if ((flags & (SYNTHETIC | BRIDGE)) != SYNTHETIC &&
|
|
(flags & ANONCONSTR) == 0 &&
|
|
(!types.isSameType(sym.type, sym.erasure(types)) ||
|
|
- signatureGen.hasTypeVar(sym.type.getThrownTypes()))) {
|
|
+ poolWriter.signatureGen.hasTypeVar(sym.type.getThrownTypes()))) {
|
|
// note that a local class with captured variables
|
|
// will get a signature attribute
|
|
int alenIdx = writeAttr(names.Signature);
|
|
- databuf.appendChar(pool.put(typeSig(sym.type)));
|
|
+ databuf.appendChar(poolWriter.putSignature(sym));
|
|
endAttr(alenIdx);
|
|
acount++;
|
|
}
|
|
@@ -621,7 +378,7 @@ public class ClassWriter extends ClassFile {
|
|
final int flags =
|
|
((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
|
|
((int) m.flags() & SYNTHETIC);
|
|
- databuf.appendChar(pool.put(s.name));
|
|
+ databuf.appendChar(poolWriter.putName(s.name));
|
|
databuf.appendChar(flags);
|
|
}
|
|
// Now write the real parameters
|
|
@@ -629,7 +386,7 @@ public class ClassWriter extends ClassFile {
|
|
final int flags =
|
|
((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
|
|
((int) m.flags() & SYNTHETIC);
|
|
- databuf.appendChar(pool.put(s.name));
|
|
+ databuf.appendChar(poolWriter.putName(s.name));
|
|
databuf.appendChar(flags);
|
|
}
|
|
// Now write the captured locals
|
|
@@ -637,7 +394,7 @@ public class ClassWriter extends ClassFile {
|
|
final int flags =
|
|
((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
|
|
((int) m.flags() & SYNTHETIC);
|
|
- databuf.appendChar(pool.put(s.name));
|
|
+ databuf.appendChar(poolWriter.putName(s.name));
|
|
databuf.appendChar(flags);
|
|
}
|
|
endAttr(attrIndex);
|
|
@@ -803,50 +560,51 @@ public class ClassWriter extends ClassFile {
|
|
*/
|
|
class AttributeWriter implements Attribute.Visitor {
|
|
public void visitConstant(Attribute.Constant _value) {
|
|
- Object value = _value.value;
|
|
- switch (_value.type.getTag()) {
|
|
- case BYTE:
|
|
- databuf.appendByte('B');
|
|
- break;
|
|
- case CHAR:
|
|
- databuf.appendByte('C');
|
|
- break;
|
|
- case SHORT:
|
|
- databuf.appendByte('S');
|
|
- break;
|
|
- case INT:
|
|
- databuf.appendByte('I');
|
|
- break;
|
|
- case LONG:
|
|
- databuf.appendByte('J');
|
|
- break;
|
|
- case FLOAT:
|
|
- databuf.appendByte('F');
|
|
- break;
|
|
- case DOUBLE:
|
|
- databuf.appendByte('D');
|
|
- break;
|
|
- case BOOLEAN:
|
|
- databuf.appendByte('Z');
|
|
- break;
|
|
- case CLASS:
|
|
- Assert.check(value instanceof String);
|
|
+ if (_value.type.getTag() == CLASS) {
|
|
+ Assert.check(_value.value instanceof String);
|
|
+ String s = (String)_value.value;
|
|
databuf.appendByte('s');
|
|
- value = names.fromString(value.toString()); // CONSTANT_Utf8
|
|
- break;
|
|
- default:
|
|
- throw new AssertionError(_value.type);
|
|
+ databuf.appendChar(poolWriter.putName(names.fromString(s)));
|
|
+ } else {
|
|
+ switch (_value.type.getTag()) {
|
|
+ case BYTE:
|
|
+ databuf.appendByte('B');
|
|
+ break;
|
|
+ case CHAR:
|
|
+ databuf.appendByte('C');
|
|
+ break;
|
|
+ case SHORT:
|
|
+ databuf.appendByte('S');
|
|
+ break;
|
|
+ case INT:
|
|
+ databuf.appendByte('I');
|
|
+ break;
|
|
+ case LONG:
|
|
+ databuf.appendByte('J');
|
|
+ break;
|
|
+ case FLOAT:
|
|
+ databuf.appendByte('F');
|
|
+ break;
|
|
+ case DOUBLE:
|
|
+ databuf.appendByte('D');
|
|
+ break;
|
|
+ case BOOLEAN:
|
|
+ databuf.appendByte('Z');
|
|
+ break;
|
|
+ default:
|
|
+ throw new AssertionError(_value.type);
|
|
+ }
|
|
+ databuf.appendChar(poolWriter.putConstant(_value.value));
|
|
}
|
|
- databuf.appendChar(pool.put(value));
|
|
}
|
|
public void visitEnum(Attribute.Enum e) {
|
|
databuf.appendByte('e');
|
|
- databuf.appendChar(pool.put(typeSig(e.value.type)));
|
|
- databuf.appendChar(pool.put(e.value.name));
|
|
+ databuf.appendChar(poolWriter.putDescriptor(e.value.type));
|
|
+ databuf.appendChar(poolWriter.putName(e.value.name));
|
|
}
|
|
public void visitClass(Attribute.Class clazz) {
|
|
databuf.appendByte('c');
|
|
- databuf.appendChar(pool.put(typeSig(types.erasure(clazz.classType))));
|
|
+ databuf.appendChar(poolWriter.putDescriptor(clazz.classType));
|
|
}
|
|
public void visitCompound(Attribute.Compound compound) {
|
|
databuf.appendByte('@');
|
|
@@ -867,10 +625,10 @@ public class ClassWriter extends ClassFile {
|
|
|
|
/** Write a compound attribute excluding the '@' marker. */
|
|
void writeCompoundAttribute(Attribute.Compound c) {
|
|
- databuf.appendChar(pool.put(typeSig(c.type)));
|
|
+ databuf.appendChar(poolWriter.putDescriptor(c.type));
|
|
databuf.appendChar(c.values.length());
|
|
for (Pair<Symbol.MethodSymbol,Attribute> p : c.values) {
|
|
- databuf.appendChar(pool.put(p.fst.name));
|
|
+ databuf.appendChar(poolWriter.putName(p.fst.name));
|
|
p.snd.accept(awriter);
|
|
}
|
|
}
|
|
@@ -974,9 +732,9 @@ public class ClassWriter extends ClassFile {
|
|
|
|
int alenIdx = writeAttr(names.Module);
|
|
|
|
- databuf.appendChar(pool.put(m));
|
|
+ databuf.appendChar(poolWriter.putModule(m));
|
|
databuf.appendChar(ModuleFlags.value(m.flags)); // module_flags
|
|
- databuf.appendChar(m.version != null ? pool.put(m.version) : 0);
|
|
+ databuf.appendChar(m.version != null ? poolWriter.putName(m.version) : 0);
|
|
|
|
ListBuffer<RequiresDirective> requires = new ListBuffer<>();
|
|
for (RequiresDirective r: m.requires) {
|
|
@@ -985,22 +743,22 @@ public class ClassWriter extends ClassFile {
|
|
}
|
|
databuf.appendChar(requires.size());
|
|
for (RequiresDirective r: requires) {
|
|
- databuf.appendChar(pool.put(r.module));
|
|
+ databuf.appendChar(poolWriter.putModule(r.module));
|
|
databuf.appendChar(RequiresFlag.value(r.flags));
|
|
- databuf.appendChar(r.module.version != null ? pool.put(r.module.version) : 0);
|
|
+ databuf.appendChar(r.module.version != null ? poolWriter.putName(r.module.version) : 0);
|
|
}
|
|
|
|
List<ExportsDirective> exports = m.exports;
|
|
databuf.appendChar(exports.size());
|
|
for (ExportsDirective e: exports) {
|
|
- databuf.appendChar(pool.put(e.packge));
|
|
+ databuf.appendChar(poolWriter.putPackage(e.packge));
|
|
databuf.appendChar(ExportsFlag.value(e.flags));
|
|
if (e.modules == null) {
|
|
databuf.appendChar(0);
|
|
} else {
|
|
databuf.appendChar(e.modules.size());
|
|
for (ModuleSymbol msym: e.modules) {
|
|
- databuf.appendChar(pool.put(msym));
|
|
+ databuf.appendChar(poolWriter.putModule(msym));
|
|
}
|
|
}
|
|
}
|
|
@@ -1008,14 +766,14 @@ public class ClassWriter extends ClassFile {
|
|
List<OpensDirective> opens = m.opens;
|
|
databuf.appendChar(opens.size());
|
|
for (OpensDirective o: opens) {
|
|
- databuf.appendChar(pool.put(o.packge));
|
|
+ databuf.appendChar(poolWriter.putPackage(o.packge));
|
|
databuf.appendChar(OpensFlag.value(o.flags));
|
|
if (o.modules == null) {
|
|
databuf.appendChar(0);
|
|
} else {
|
|
databuf.appendChar(o.modules.size());
|
|
for (ModuleSymbol msym: o.modules) {
|
|
- databuf.appendChar(pool.put(msym));
|
|
+ databuf.appendChar(poolWriter.putModule(msym));
|
|
}
|
|
}
|
|
}
|
|
@@ -1023,7 +781,7 @@ public class ClassWriter extends ClassFile {
|
|
List<UsesDirective> uses = m.uses;
|
|
databuf.appendChar(uses.size());
|
|
for (UsesDirective s: uses) {
|
|
- databuf.appendChar(pool.put(s.service));
|
|
+ databuf.appendChar(poolWriter.putClass(s.service));
|
|
}
|
|
|
|
// temporary fix to merge repeated provides clause for same service;
|
|
@@ -1035,9 +793,9 @@ public class ClassWriter extends ClassFile {
|
|
}
|
|
databuf.appendChar(mergedProvides.size());
|
|
mergedProvides.forEach((srvc, impls) -> {
|
|
- databuf.appendChar(pool.put(srvc));
|
|
+ databuf.appendChar(poolWriter.putClass(srvc));
|
|
databuf.appendChar(impls.size());
|
|
- impls.forEach(impl -> databuf.appendChar(pool.put(impl)));
|
|
+ impls.forEach(impl -> databuf.appendChar(poolWriter.putClass(impl)));
|
|
});
|
|
|
|
endAttr(alenIdx);
|
|
@@ -1048,46 +806,12 @@ public class ClassWriter extends ClassFile {
|
|
* Writing Objects
|
|
**********************************************************************/
|
|
|
|
- /** Enter an inner class into the `innerClasses' set/queue.
|
|
- */
|
|
- void enterInner(ClassSymbol c) {
|
|
- if (c.type.isCompound()) {
|
|
- throw new AssertionError("Unexpected intersection type: " + c.type);
|
|
- }
|
|
- try {
|
|
- c.complete();
|
|
- } catch (CompletionFailure ex) {
|
|
- System.err.println("error: " + c + ": " + ex.getMessage());
|
|
- throw ex;
|
|
- }
|
|
- if (!c.type.hasTag(CLASS)) return; // arrays
|
|
- if (pool != null && // pool might be null if called from xClassName
|
|
- c.owner.enclClass() != null &&
|
|
- (innerClasses == null || !innerClasses.contains(c))) {
|
|
-// log.errWriter.println("enter inner " + c);//DEBUG
|
|
- enterInner(c.owner.enclClass());
|
|
- pool.put(c);
|
|
- if (c.name != names.empty)
|
|
- pool.put(c.name);
|
|
- if (innerClasses == null) {
|
|
- innerClasses = new HashSet<>();
|
|
- innerClassesQueue = new ListBuffer<>();
|
|
- pool.put(names.InnerClasses);
|
|
- }
|
|
- innerClasses.add(c);
|
|
- innerClassesQueue.append(c);
|
|
- }
|
|
- }
|
|
-
|
|
/** Write "inner classes" attribute.
|
|
*/
|
|
void writeInnerClasses() {
|
|
int alenIdx = writeAttr(names.InnerClasses);
|
|
- databuf.appendChar(innerClassesQueue.length());
|
|
- for (List<ClassSymbol> l = innerClassesQueue.toList();
|
|
- l.nonEmpty();
|
|
- l = l.tail) {
|
|
- ClassSymbol inner = l.head;
|
|
+ databuf.appendChar(poolWriter.innerClasses.size());
|
|
+ for (ClassSymbol inner : poolWriter.innerClasses) {
|
|
inner.markAbstractIfNeeded(types);
|
|
char flags = (char) adjustFlags(inner.flags_field);
|
|
if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT
|
|
@@ -1097,11 +821,11 @@ public class ClassWriter extends ClassFile {
|
|
pw.println("INNERCLASS " + inner.name);
|
|
pw.println("---" + flagNames(flags));
|
|
}
|
|
- databuf.appendChar(pool.get(inner));
|
|
+ databuf.appendChar(poolWriter.putClass(inner));
|
|
databuf.appendChar(
|
|
- inner.owner.kind == TYP && !inner.name.isEmpty() ? pool.get(inner.owner) : 0);
|
|
+ inner.owner.kind == TYP && !inner.name.isEmpty() ? poolWriter.putClass((ClassSymbol)inner.owner) : 0);
|
|
databuf.appendChar(
|
|
- !inner.name.isEmpty() ? pool.get(inner.name) : 0);
|
|
+ !inner.name.isEmpty() ? poolWriter.putName(inner.name) : 0);
|
|
databuf.appendChar(flags);
|
|
}
|
|
endAttr(alenIdx);
|
|
@@ -1111,14 +835,14 @@ public class ClassWriter extends ClassFile {
|
|
* Write NestMembers attribute (if needed)
|
|
*/
|
|
int writeNestMembersIfNeeded(ClassSymbol csym) {
|
|
- ListBuffer<Symbol> nested = new ListBuffer<>();
|
|
+ ListBuffer<ClassSymbol> nested = new ListBuffer<>();
|
|
listNested(csym, nested);
|
|
- Set<Symbol> nestedUnique = new LinkedHashSet<>(nested);
|
|
+ Set<ClassSymbol> nestedUnique = new LinkedHashSet<>(nested);
|
|
if (csym.owner.kind == PCK && !nestedUnique.isEmpty()) {
|
|
int alenIdx = writeAttr(names.NestMembers);
|
|
databuf.appendChar(nestedUnique.size());
|
|
- for (Symbol s : nestedUnique) {
|
|
- databuf.appendChar(pool.put(s));
|
|
+ for (ClassSymbol s : nestedUnique) {
|
|
+ databuf.appendChar(poolWriter.putClass(s));
|
|
}
|
|
endAttr(alenIdx);
|
|
return 1;
|
|
@@ -1132,14 +856,14 @@ public class ClassWriter extends ClassFile {
|
|
int writeNestHostIfNeeded(ClassSymbol csym) {
|
|
if (csym.owner.kind != PCK) {
|
|
int alenIdx = writeAttr(names.NestHost);
|
|
- databuf.appendChar(pool.put(csym.outermostClass()));
|
|
+ databuf.appendChar(poolWriter.putClass(csym.outermostClass()));
|
|
endAttr(alenIdx);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
- private void listNested(Symbol sym, ListBuffer<Symbol> seen) {
|
|
+ private void listNested(Symbol sym, ListBuffer<ClassSymbol> seen) {
|
|
if (sym.kind != TYP) return;
|
|
ClassSymbol csym = (ClassSymbol)sym;
|
|
if (csym.owner.kind != PCK) {
|
|
@@ -1161,17 +885,16 @@ public class ClassWriter extends ClassFile {
|
|
*/
|
|
void writeBootstrapMethods() {
|
|
int alenIdx = writeAttr(names.BootstrapMethods);
|
|
- databuf.appendChar(bootstrapMethods.size());
|
|
- for (Map.Entry<DynamicMethod.BootstrapMethodsKey, DynamicMethod.BootstrapMethodsValue> entry : bootstrapMethods.entrySet()) {
|
|
- DynamicMethod.BootstrapMethodsKey bsmKey = entry.getKey();
|
|
+ databuf.appendChar(poolWriter.bootstrapMethods.size());
|
|
+ for (BsmKey bsmKey : poolWriter.bootstrapMethods.keySet()) {
|
|
//write BSM handle
|
|
- databuf.appendChar(pool.get(entry.getValue().mh));
|
|
- Object[] uniqueArgs = bsmKey.getUniqueArgs();
|
|
+ databuf.appendChar(poolWriter.putConstant(bsmKey.bsm));
|
|
+ LoadableConstant[] uniqueArgs = bsmKey.staticArgs;
|
|
//write static args length
|
|
databuf.appendChar(uniqueArgs.length);
|
|
//write static args array
|
|
- for (Object o : uniqueArgs) {
|
|
- databuf.appendChar(pool.get(o));
|
|
+ for (LoadableConstant arg : uniqueArgs) {
|
|
+ databuf.appendChar(poolWriter.putConstant(arg));
|
|
}
|
|
}
|
|
endAttr(alenIdx);
|
|
@@ -1187,13 +910,13 @@ public class ClassWriter extends ClassFile {
|
|
pw.println("FIELD " + v.name);
|
|
pw.println("---" + flagNames(v.flags()));
|
|
}
|
|
- databuf.appendChar(pool.put(v.name));
|
|
- databuf.appendChar(pool.put(typeSig(v.erasure(types))));
|
|
+ databuf.appendChar(poolWriter.putName(v.name));
|
|
+ databuf.appendChar(poolWriter.putDescriptor(v));
|
|
int acountIdx = beginAttrs();
|
|
int acount = 0;
|
|
if (v.getConstValue() != null) {
|
|
int alenIdx = writeAttr(names.ConstantValue);
|
|
- databuf.appendChar(pool.put(v.getConstValue()));
|
|
+ databuf.appendChar(poolWriter.putConstant(v.getConstValue()));
|
|
endAttr(alenIdx);
|
|
acount++;
|
|
}
|
|
@@ -1211,8 +934,8 @@ public class ClassWriter extends ClassFile {
|
|
pw.println("METHOD " + m.name);
|
|
pw.println("---" + flagNames(m.flags()));
|
|
}
|
|
- databuf.appendChar(pool.put(m.name));
|
|
- databuf.appendChar(pool.put(typeSig(m.externalType(types))));
|
|
+ databuf.appendChar(poolWriter.putName(m.name));
|
|
+ databuf.appendChar(poolWriter.putDescriptor(m));
|
|
int acountIdx = beginAttrs();
|
|
int acount = 0;
|
|
if (m.code != null) {
|
|
@@ -1227,7 +950,7 @@ public class ClassWriter extends ClassFile {
|
|
int alenIdx = writeAttr(names.Exceptions);
|
|
databuf.appendChar(thrown.length());
|
|
for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
|
|
- databuf.appendChar(pool.put(l.head.tsym));
|
|
+ databuf.appendChar(poolWriter.putClass(l.head));
|
|
endAttr(alenIdx);
|
|
acount++;
|
|
}
|
|
@@ -1303,9 +1026,8 @@ public class ClassWriter extends ClassFile {
|
|
&& (r.start_pc + r.length) <= code.cp);
|
|
databuf.appendChar(r.length);
|
|
VarSymbol sym = var.sym;
|
|
- databuf.appendChar(pool.put(sym.name));
|
|
- Type vartype = sym.erasure(types);
|
|
- databuf.appendChar(pool.put(typeSig(vartype)));
|
|
+ databuf.appendChar(poolWriter.putName(sym.name));
|
|
+ databuf.appendChar(poolWriter.putDescriptor(sym));
|
|
databuf.appendChar(var.reg);
|
|
if (needsLocalVariableTypeEntry(var.sym.type)) {
|
|
nGenericVars++;
|
|
@@ -1329,8 +1051,8 @@ public class ClassWriter extends ClassFile {
|
|
// write variable info
|
|
databuf.appendChar(r.start_pc);
|
|
databuf.appendChar(r.length);
|
|
- databuf.appendChar(pool.put(sym.name));
|
|
- databuf.appendChar(pool.put(typeSig(sym.type)));
|
|
+ databuf.appendChar(poolWriter.putName(sym.name));
|
|
+ databuf.appendChar(poolWriter.putSignature(sym));
|
|
databuf.appendChar(var.reg);
|
|
count++;
|
|
}
|
|
@@ -1457,14 +1179,10 @@ public class ClassWriter extends ClassFile {
|
|
break;
|
|
case CLASS:
|
|
case ARRAY:
|
|
- if (debugstackmap) System.out.print("object(" + t + ")");
|
|
- databuf.appendByte(7);
|
|
- databuf.appendChar(pool.put(t));
|
|
- break;
|
|
case TYPEVAR:
|
|
if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
|
|
databuf.appendByte(7);
|
|
- databuf.appendChar(pool.put(types.erasure(t).tsym));
|
|
+ databuf.appendChar(poolWriter.putClass(types.erasure(t)));
|
|
break;
|
|
case UNINITIALIZED_THIS:
|
|
if (debugstackmap) System.out.print("uninit_this");
|
|
@@ -1763,11 +1481,6 @@ public class ClassWriter extends ClassFile {
|
|
Assert.check((c.flags() & COMPOUND) == 0);
|
|
databuf.reset();
|
|
poolbuf.reset();
|
|
- signatureGen.reset();
|
|
- pool = c.pool;
|
|
- innerClasses = null;
|
|
- innerClassesQueue = null;
|
|
- bootstrapMethods = new LinkedHashMap<>();
|
|
|
|
Type supertype = types.supertype(c.type);
|
|
List<Type> interfaces = types.interfaces(c.type);
|
|
@@ -1793,14 +1506,14 @@ public class ClassWriter extends ClassFile {
|
|
|
|
if (c.owner.kind == MDL) {
|
|
PackageSymbol unnamed = ((ModuleSymbol) c.owner).unnamedPackage;
|
|
- databuf.appendChar(pool.put(new ClassSymbol(0, names.module_info, unnamed)));
|
|
+ databuf.appendChar(poolWriter.putClass(new ClassSymbol(0, names.module_info, unnamed)));
|
|
} else {
|
|
- databuf.appendChar(pool.put(c));
|
|
+ databuf.appendChar(poolWriter.putClass(c));
|
|
}
|
|
- databuf.appendChar(supertype.hasTag(CLASS) ? pool.put(supertype.tsym) : 0);
|
|
+ databuf.appendChar(supertype.hasTag(CLASS) ? poolWriter.putClass((ClassSymbol)supertype.tsym) : 0);
|
|
databuf.appendChar(interfaces.length());
|
|
for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
|
|
- databuf.appendChar(pool.put(l.head.tsym));
|
|
+ databuf.appendChar(poolWriter.putClass((ClassSymbol)l.head.tsym));
|
|
int fieldsCount = 0;
|
|
int methodsCount = 0;
|
|
for (Symbol sym : c.members().getSymbols(NON_RECURSIVE)) {
|
|
@@ -1808,14 +1521,14 @@ public class ClassWriter extends ClassFile {
|
|
case VAR: fieldsCount++; break;
|
|
case MTH: if ((sym.flags() & HYPOTHETICAL) == 0) methodsCount++;
|
|
break;
|
|
- case TYP: enterInner((ClassSymbol)sym); break;
|
|
+ case TYP: poolWriter.enterInner((ClassSymbol)sym); break;
|
|
default : Assert.error();
|
|
}
|
|
}
|
|
|
|
if (c.trans_local != null) {
|
|
for (ClassSymbol local : c.trans_local) {
|
|
- enterInner(local);
|
|
+ poolWriter.enterInner(local);
|
|
}
|
|
}
|
|
|
|
@@ -1833,12 +1546,7 @@ public class ClassWriter extends ClassFile {
|
|
sigReq = l.head.allparams().length() != 0;
|
|
if (sigReq) {
|
|
int alenIdx = writeAttr(names.Signature);
|
|
- if (typarams.length() != 0) signatureGen.assembleParamsSig(typarams);
|
|
- signatureGen.assembleSig(supertype);
|
|
- for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
|
|
- signatureGen.assembleSig(l.head);
|
|
- databuf.appendChar(pool.put(signatureGen.toName()));
|
|
- signatureGen.reset();
|
|
+ databuf.appendChar(poolWriter.putSignature(c));
|
|
endAttr(alenIdx);
|
|
acount++;
|
|
}
|
|
@@ -1848,9 +1556,8 @@ public class ClassWriter extends ClassFile {
|
|
// WHM 6/29/1999: Strip file path prefix. We do it here at
|
|
// the last possible moment because the sourcefile may be used
|
|
// elsewhere in error diagnostics. Fixes 4241573.
|
|
- //databuf.appendChar(c.pool.put(c.sourcefile));
|
|
String simpleName = PathFileObject.getSimpleName(c.sourcefile);
|
|
- databuf.appendChar(c.pool.put(names.fromString(simpleName)));
|
|
+ databuf.appendChar(poolWriter.putName(names.fromString(simpleName)));
|
|
endAttr(alenIdx);
|
|
acount++;
|
|
}
|
|
@@ -1858,12 +1565,12 @@ public class ClassWriter extends ClassFile {
|
|
if (genCrt) {
|
|
// Append SourceID attribute
|
|
int alenIdx = writeAttr(names.SourceID);
|
|
- databuf.appendChar(c.pool.put(names.fromString(Long.toString(getLastModified(c.sourcefile)))));
|
|
+ databuf.appendChar(poolWriter.putName(names.fromString(Long.toString(getLastModified(c.sourcefile)))));
|
|
endAttr(alenIdx);
|
|
acount++;
|
|
// Append CompilationID attribute
|
|
alenIdx = writeAttr(names.CompilationID);
|
|
- databuf.appendChar(c.pool.put(names.fromString(Long.toString(System.currentTimeMillis()))));
|
|
+ databuf.appendChar(poolWriter.putName(names.fromString(Long.toString(System.currentTimeMillis()))));
|
|
endAttr(alenIdx);
|
|
acount++;
|
|
}
|
|
@@ -1893,24 +1600,24 @@ public class ClassWriter extends ClassFile {
|
|
}
|
|
}
|
|
|
|
- writePool(c.pool);
|
|
-
|
|
- if (innerClasses != null) {
|
|
- writeInnerClasses();
|
|
+ if (!poolWriter.bootstrapMethods.isEmpty()) {
|
|
+ writeBootstrapMethods();
|
|
acount++;
|
|
}
|
|
|
|
- if (!bootstrapMethods.isEmpty()) {
|
|
- writeBootstrapMethods();
|
|
+ if (!poolWriter.innerClasses.isEmpty()) {
|
|
+ writeInnerClasses();
|
|
acount++;
|
|
}
|
|
|
|
endAttrs(acountIdx, acount);
|
|
|
|
- poolbuf.appendBytes(databuf.elems, 0, databuf.length);
|
|
out.write(poolbuf.elems, 0, poolbuf.length);
|
|
|
|
- pool = c.pool = null; // to conserve space
|
|
+ poolWriter.writePool(out);
|
|
+ poolWriter.reset(); // to save space
|
|
+
|
|
+ out.write(databuf.elems, 0, databuf.length);
|
|
}
|
|
|
|
/**Allows subclasses to write additional class attributes
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java
|
|
index fb21dcba9..408ef0eb4 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java
|
|
@@ -27,15 +27,27 @@ package com.sun.tools.javac.jvm;
|
|
|
|
import com.sun.tools.javac.code.*;
|
|
import com.sun.tools.javac.code.Symbol.*;
|
|
-import com.sun.tools.javac.code.Types.UniqueType;
|
|
import com.sun.tools.javac.resources.CompilerProperties.Errors;
|
|
-import com.sun.tools.javac.tree.JCTree;
|
|
import com.sun.tools.javac.util.*;
|
|
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
|
|
|
+import java.util.function.ToIntBiFunction;
|
|
+import java.util.function.ToIntFunction;
|
|
+
|
|
import static com.sun.tools.javac.code.TypeTag.BOT;
|
|
import static com.sun.tools.javac.code.TypeTag.INT;
|
|
import static com.sun.tools.javac.jvm.ByteCodes.*;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Double;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Fieldref;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Float;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Integer;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_InterfaceMethodref;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Long;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodHandle;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodType;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Methodref;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_String;
|
|
import static com.sun.tools.javac.jvm.UninitializedType.*;
|
|
import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame;
|
|
|
|
@@ -72,6 +84,7 @@ public class Code {
|
|
|
|
final Types types;
|
|
final Symtab syms;
|
|
+ final PoolWriter poolWriter;
|
|
|
|
/*---------- classfile fields: --------------- */
|
|
|
|
@@ -177,10 +190,6 @@ public class Code {
|
|
*/
|
|
Position.LineMap lineMap;
|
|
|
|
- /** The constant pool of the current class.
|
|
- */
|
|
- final Pool pool;
|
|
-
|
|
final MethodSymbol meth;
|
|
|
|
/** Construct a code object, given the settings of the fatcode,
|
|
@@ -195,7 +204,7 @@ public class Code {
|
|
CRTable crt,
|
|
Symtab syms,
|
|
Types types,
|
|
- Pool pool) {
|
|
+ PoolWriter poolWriter) {
|
|
this.meth = meth;
|
|
this.fatcode = fatcode;
|
|
this.lineMap = lineMap;
|
|
@@ -204,6 +213,7 @@ public class Code {
|
|
this.crt = crt;
|
|
this.syms = syms;
|
|
this.types = types;
|
|
+ this.poolWriter = poolWriter;
|
|
this.debugCode = debugCode;
|
|
this.stackMap = stackMap;
|
|
switch (stackMap) {
|
|
@@ -216,7 +226,6 @@ public class Code {
|
|
}
|
|
state = new State();
|
|
lvar = new LocalVar[20];
|
|
- this.pool = pool;
|
|
}
|
|
|
|
|
|
@@ -387,12 +396,13 @@ public class Code {
|
|
|
|
/** Emit a ldc (or ldc_w) instruction, taking into account operand size
|
|
*/
|
|
- public void emitLdc(int od) {
|
|
+ public void emitLdc(LoadableConstant constant) {
|
|
+ int od = poolWriter.putConstant(constant);
|
|
if (od <= 255) {
|
|
- emitop1(ldc1, od);
|
|
+ emitop1(ldc1, od, constant);
|
|
}
|
|
else {
|
|
- emitop2(ldc2, od);
|
|
+ emitop2(ldc2, od, constant);
|
|
}
|
|
}
|
|
|
|
@@ -429,11 +439,11 @@ public class Code {
|
|
|
|
/** Emit an invokeinterface instruction.
|
|
*/
|
|
- public void emitInvokeinterface(int meth, Type mtype) {
|
|
+ public void emitInvokeinterface(Symbol member, Type mtype) {
|
|
int argsize = width(mtype.getParameterTypes());
|
|
emitop(invokeinterface);
|
|
if (!alive) return;
|
|
- emit2(meth);
|
|
+ emit2(poolWriter.putMember(member));
|
|
emit1(argsize + 1);
|
|
emit1(0);
|
|
state.pop(argsize + 1);
|
|
@@ -442,14 +452,13 @@ public class Code {
|
|
|
|
/** Emit an invokespecial instruction.
|
|
*/
|
|
- public void emitInvokespecial(int meth, Type mtype) {
|
|
+ public void emitInvokespecial(Symbol member, Type mtype) {
|
|
int argsize = width(mtype.getParameterTypes());
|
|
emitop(invokespecial);
|
|
if (!alive) return;
|
|
- emit2(meth);
|
|
- Symbol sym = (Symbol)pool.pool[meth];
|
|
+ emit2(poolWriter.putMember(member));
|
|
state.pop(argsize);
|
|
- if (sym.isConstructor())
|
|
+ if (member.isConstructor())
|
|
state.markInitialized((UninitializedType)state.peek());
|
|
state.pop(1);
|
|
state.push(mtype.getReturnType());
|
|
@@ -457,33 +466,33 @@ public class Code {
|
|
|
|
/** Emit an invokestatic instruction.
|
|
*/
|
|
- public void emitInvokestatic(int meth, Type mtype) {
|
|
+ public void emitInvokestatic(Symbol member, Type mtype) {
|
|
int argsize = width(mtype.getParameterTypes());
|
|
emitop(invokestatic);
|
|
if (!alive) return;
|
|
- emit2(meth);
|
|
+ emit2(poolWriter.putMember(member));
|
|
state.pop(argsize);
|
|
state.push(mtype.getReturnType());
|
|
}
|
|
|
|
/** Emit an invokevirtual instruction.
|
|
*/
|
|
- public void emitInvokevirtual(int meth, Type mtype) {
|
|
+ public void emitInvokevirtual(Symbol member, Type mtype) {
|
|
int argsize = width(mtype.getParameterTypes());
|
|
emitop(invokevirtual);
|
|
if (!alive) return;
|
|
- emit2(meth);
|
|
+ emit2(poolWriter.putMember(member));
|
|
state.pop(argsize + 1);
|
|
state.push(mtype.getReturnType());
|
|
}
|
|
|
|
/** Emit an invokedynamic instruction.
|
|
*/
|
|
- public void emitInvokedynamic(int desc, Type mtype) {
|
|
+ public void emitInvokedynamic(DynamicMethodSymbol dynMember, Type mtype) {
|
|
int argsize = width(mtype.getParameterTypes());
|
|
emitop(invokedynamic);
|
|
if (!alive) return;
|
|
- emit2(desc);
|
|
+ emit2(poolWriter.putDynamic(dynMember));
|
|
emit2(0);
|
|
state.pop(argsize);
|
|
state.push(mtype.getReturnType());
|
|
@@ -894,6 +903,10 @@ public class Code {
|
|
/** Emit an opcode with a one-byte operand field.
|
|
*/
|
|
public void emitop1(int op, int od) {
|
|
+ emitop1(op, od, null);
|
|
+ }
|
|
+
|
|
+ public void emitop1(int op, int od, PoolConstant data) {
|
|
emitop(op);
|
|
if (!alive) return;
|
|
emit1(od);
|
|
@@ -902,7 +915,7 @@ public class Code {
|
|
state.push(syms.intType);
|
|
break;
|
|
case ldc1:
|
|
- state.push(typeForPool(pool.pool[od]));
|
|
+ state.push(types.constantType((LoadableConstant)data));
|
|
break;
|
|
default:
|
|
throw new AssertionError(mnem(op));
|
|
@@ -910,25 +923,6 @@ public class Code {
|
|
postop();
|
|
}
|
|
|
|
- /** The type of a constant pool entry. */
|
|
- private Type typeForPool(Object o) {
|
|
- if (o instanceof Integer) return syms.intType;
|
|
- if (o instanceof Float) return syms.floatType;
|
|
- if (o instanceof String) return syms.stringType;
|
|
- if (o instanceof Long) return syms.longType;
|
|
- if (o instanceof Double) return syms.doubleType;
|
|
- if (o instanceof ClassSymbol) return syms.classType;
|
|
- if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
|
|
- if (o instanceof UniqueType) return typeForPool(((UniqueType)o).type);
|
|
- if (o instanceof Type) {
|
|
- Type ty = (Type) o;
|
|
-
|
|
- if (ty instanceof Type.ArrayType) return syms.classType;
|
|
- if (ty instanceof Type.MethodType) return syms.methodTypeType;
|
|
- }
|
|
- throw new AssertionError("Invalid type of constant pool entry: " + o.getClass());
|
|
- }
|
|
-
|
|
/** Emit an opcode with a one-byte operand field;
|
|
* widen if field does not fit in a byte.
|
|
*/
|
|
@@ -1001,29 +995,31 @@ public class Code {
|
|
|
|
/** Emit an opcode with a two-byte operand field.
|
|
*/
|
|
+ public <P extends PoolConstant> void emitop2(int op, P constant, ToIntBiFunction<PoolWriter, P> poolFunc) {
|
|
+ int od = poolFunc.applyAsInt(poolWriter, constant);
|
|
+ emitop2(op, od, constant);
|
|
+ }
|
|
+
|
|
public void emitop2(int op, int od) {
|
|
+ emitop2(op, od, null);
|
|
+ }
|
|
+
|
|
+ public void emitop2(int op, int od, PoolConstant data) {
|
|
emitop(op);
|
|
if (!alive) return;
|
|
emit2(od);
|
|
switch (op) {
|
|
case getstatic:
|
|
- state.push(((Symbol)(pool.pool[od])).erasure(types));
|
|
+ state.push(((Symbol)data).erasure(types));
|
|
break;
|
|
case putstatic:
|
|
- state.pop(((Symbol)(pool.pool[od])).erasure(types));
|
|
- break;
|
|
- case new_:
|
|
- Symbol sym;
|
|
- if (pool.pool[od] instanceof UniqueType) {
|
|
- // Required by change in Gen.makeRef to allow
|
|
- // annotated types.
|
|
- // TODO: is this needed anywhere else?
|
|
- sym = ((UniqueType)(pool.pool[od])).type.tsym;
|
|
- } else {
|
|
- sym = (Symbol)(pool.pool[od]);
|
|
- }
|
|
- state.push(uninitializedObject(sym.erasure(types), cp-3));
|
|
+ state.pop(((Symbol)data).erasure(types));
|
|
break;
|
|
+ case new_: {
|
|
+ Type t = (Type)data;
|
|
+ state.push(uninitializedObject(t.tsym.erasure(types), cp-3));
|
|
+ break;
|
|
+ }
|
|
case sipush:
|
|
state.push(syms.intType);
|
|
break;
|
|
@@ -1051,30 +1047,27 @@ public class Code {
|
|
markDead();
|
|
break;
|
|
case putfield:
|
|
- state.pop(((Symbol)(pool.pool[od])).erasure(types));
|
|
+ state.pop(((Symbol)data).erasure(types));
|
|
state.pop(1); // object ref
|
|
break;
|
|
case getfield:
|
|
state.pop(1); // object ref
|
|
- state.push(((Symbol)(pool.pool[od])).erasure(types));
|
|
+ state.push(((Symbol)data).erasure(types));
|
|
break;
|
|
case checkcast: {
|
|
state.pop(1); // object ref
|
|
- Object o = pool.pool[od];
|
|
- Type t = (o instanceof Symbol)
|
|
- ? ((Symbol)o).erasure(types)
|
|
- : types.erasure((((UniqueType)o).type));
|
|
+ Type t = types.erasure((Type)data);
|
|
state.push(t);
|
|
break; }
|
|
case ldc2w:
|
|
- state.push(typeForPool(pool.pool[od]));
|
|
+ state.push(types.constantType((LoadableConstant)data));
|
|
break;
|
|
case instanceof_:
|
|
state.pop(1);
|
|
state.push(syms.intType);
|
|
break;
|
|
case ldc2:
|
|
- state.push(typeForPool(pool.pool[od]));
|
|
+ state.push(types.constantType((LoadableConstant)data));
|
|
break;
|
|
case jsr:
|
|
break;
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
|
|
index 5650ba5cc..004ce027d 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
|
|
@@ -25,6 +25,7 @@
|
|
|
|
package com.sun.tools.javac.jvm;
|
|
|
|
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
|
|
import com.sun.tools.javac.tree.TreeInfo.PosKind;
|
|
import com.sun.tools.javac.util.*;
|
|
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
|
@@ -93,9 +94,9 @@ public class Gen extends JCTree.Visitor {
|
|
return instance;
|
|
}
|
|
|
|
- /** Constant pool, reset by genClass.
|
|
+ /** Constant pool writer, set by genClass.
|
|
*/
|
|
- private final Pool pool;
|
|
+ final PoolWriter poolWriter;
|
|
|
|
protected Gen(Context context) {
|
|
context.put(genKey, this);
|
|
@@ -127,7 +128,7 @@ public class Gen extends JCTree.Visitor {
|
|
debugCode = options.isSet("debug.code");
|
|
allowBetterNullChecks = target.hasObjects();
|
|
disableVirtualizedPrivateInvoke = options.isSet("disableVirtualizedPrivateInvoke");
|
|
- pool = new Pool(types);
|
|
+ poolWriter = new PoolWriter(types, names);
|
|
|
|
// ignore cldc because we cannot have both stackmap formats
|
|
this.stackMap = StackMapFormat.JSR202;
|
|
@@ -254,17 +255,17 @@ public class Gen extends JCTree.Visitor {
|
|
* @param type The type for which a reference is inserted.
|
|
*/
|
|
int makeRef(DiagnosticPosition pos, Type type) {
|
|
- checkDimension(pos, type);
|
|
- if (type.isAnnotated()) {
|
|
- return pool.put((Object)type);
|
|
- } else {
|
|
- return pool.put(type.hasTag(CLASS) ? (Object)type.tsym : (Object)type);
|
|
- }
|
|
+ return poolWriter.putClass(checkDimension(pos, type));
|
|
}
|
|
|
|
/** Check if the given type is an array with too many dimensions.
|
|
*/
|
|
- private void checkDimension(DiagnosticPosition pos, Type t) {
|
|
+ private Type checkDimension(DiagnosticPosition pos, Type t) {
|
|
+ checkDimensionInternal(pos, t);
|
|
+ return t;
|
|
+ }
|
|
+
|
|
+ private void checkDimensionInternal(DiagnosticPosition pos, Type t) {
|
|
switch (t.getTag()) {
|
|
case METHOD:
|
|
checkDimension(pos, t.getReturnType());
|
|
@@ -518,7 +519,7 @@ public class Gen extends JCTree.Visitor {
|
|
if (nerrs != 0 || // only complain about a long string once
|
|
constValue == null ||
|
|
!(constValue instanceof String) ||
|
|
- ((String)constValue).length() < Pool.MAX_STRING_LENGTH)
|
|
+ ((String)constValue).length() < PoolWriter.MAX_STRING_LENGTH)
|
|
return;
|
|
log.error(pos, Errors.LimitString);
|
|
nerrs++;
|
|
@@ -772,7 +773,7 @@ public class Gen extends JCTree.Visitor {
|
|
@Override
|
|
public void visitIdent(JCIdent tree) {
|
|
if (tree.sym.owner instanceof ClassSymbol) {
|
|
- pool.put(tree.sym.owner);
|
|
+ poolWriter.putClass((ClassSymbol)tree.sym.owner);
|
|
}
|
|
}
|
|
|
|
@@ -973,8 +974,8 @@ public class Gen extends JCTree.Visitor {
|
|
: null,
|
|
syms,
|
|
types,
|
|
- pool);
|
|
- items = new Items(pool, code, syms, types);
|
|
+ poolWriter);
|
|
+ items = new Items(poolWriter, code, syms, types);
|
|
if (code.debugCode) {
|
|
System.err.println(meth + " for body " + tree);
|
|
}
|
|
@@ -1741,7 +1742,7 @@ public class Gen extends JCTree.Visitor {
|
|
Assert.check(tree.encl == null && tree.def == null);
|
|
setTypeAnnotationPositions(tree.pos);
|
|
|
|
- code.emitop2(new_, makeRef(tree.pos(), tree.type));
|
|
+ code.emitop2(new_, checkDimension(tree.pos(), tree.type), PoolWriter::putClass);
|
|
code.emitop0(dup);
|
|
|
|
// Generate code for all arguments, where the expected types are
|
|
@@ -2022,7 +2023,7 @@ public class Gen extends JCTree.Visitor {
|
|
if (!tree.clazz.type.isPrimitive() &&
|
|
!types.isSameType(tree.expr.type, tree.clazz.type) &&
|
|
types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
|
|
- code.emitop2(checkcast, makeRef(tree.pos(), tree.clazz.type));
|
|
+ code.emitop2(checkcast, checkDimension(tree.pos(), tree.clazz.type), PoolWriter::putClass);
|
|
}
|
|
}
|
|
|
|
@@ -2081,7 +2082,7 @@ public class Gen extends JCTree.Visitor {
|
|
Symbol sym = tree.sym;
|
|
|
|
if (tree.name == names._class) {
|
|
- code.emitLdc(makeRef(tree.pos(), tree.selected.type));
|
|
+ code.emitLdc((LoadableConstant)checkDimension(tree.pos(), tree.selected.type));
|
|
result = items.makeStackItem(pt);
|
|
return;
|
|
}
|
|
@@ -2162,7 +2163,7 @@ public class Gen extends JCTree.Visitor {
|
|
letExprDepth--;
|
|
}
|
|
|
|
- private void generateReferencesToPrunedTree(ClassSymbol classSymbol, Pool pool) {
|
|
+ private void generateReferencesToPrunedTree(ClassSymbol classSymbol) {
|
|
List<JCTree> prunedInfo = lower.prunedTree.get(classSymbol);
|
|
if (prunedInfo != null) {
|
|
for (JCTree prunedTree: prunedInfo) {
|
|
@@ -2188,12 +2189,10 @@ public class Gen extends JCTree.Visitor {
|
|
ClassSymbol c = cdef.sym;
|
|
this.toplevel = env.toplevel;
|
|
this.endPosTable = toplevel.endPositions;
|
|
- c.pool = pool;
|
|
- pool.reset();
|
|
/* method normalizeDefs() can add references to external classes into the constant pool
|
|
*/
|
|
cdef.defs = normalizeDefs(cdef.defs, c);
|
|
- generateReferencesToPrunedTree(c, pool);
|
|
+ generateReferencesToPrunedTree(c);
|
|
Env<GenContext> localEnv = new Env<>(cdef, new GenContext());
|
|
localEnv.toplevel = env.toplevel;
|
|
localEnv.enclClass = cdef;
|
|
@@ -2201,7 +2200,7 @@ public class Gen extends JCTree.Visitor {
|
|
for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
|
|
genDef(l.head, localEnv);
|
|
}
|
|
- if (pool.numEntries() > Pool.MAX_ENTRIES) {
|
|
+ if (poolWriter.size() > PoolWriter.MAX_ENTRIES) {
|
|
log.error(cdef.pos(), Errors.LimitPool);
|
|
nerrs++;
|
|
}
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java
|
|
index 3e1d7c68e..19a3d9be4 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java
|
|
@@ -29,6 +29,8 @@ import com.sun.tools.javac.code.*;
|
|
import com.sun.tools.javac.code.Symbol.*;
|
|
import com.sun.tools.javac.code.Type.*;
|
|
import com.sun.tools.javac.jvm.Code.*;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant.BasicConstant;
|
|
import com.sun.tools.javac.tree.JCTree;
|
|
import com.sun.tools.javac.util.Assert;
|
|
|
|
@@ -50,9 +52,9 @@ import static com.sun.tools.javac.jvm.ByteCodes.*;
|
|
*/
|
|
public class Items {
|
|
|
|
- /** The current constant pool.
|
|
+ /** The current constant pool writer.
|
|
*/
|
|
- Pool pool;
|
|
+ PoolWriter poolWriter;
|
|
|
|
/** The current code buffer.
|
|
*/
|
|
@@ -72,9 +74,9 @@ public class Items {
|
|
private final Item superItem;
|
|
private final Item[] stackItem = new Item[TypeCodeCount];
|
|
|
|
- public Items(Pool pool, Code code, Symtab syms, Types types) {
|
|
+ public Items(PoolWriter poolWriter, Code code, Symtab syms, Types types) {
|
|
this.code = code;
|
|
- this.pool = pool;
|
|
+ this.poolWriter = poolWriter;
|
|
this.types = types;
|
|
voidItem = new Item(VOIDcode) {
|
|
public String toString() { return "void"; }
|
|
@@ -444,18 +446,18 @@ public class Items {
|
|
}
|
|
|
|
Item load() {
|
|
- code.emitop2(getstatic, pool.put(member));
|
|
+ code.emitop2(getstatic, member, PoolWriter::putMember);
|
|
return stackItem[typecode];
|
|
}
|
|
|
|
void store() {
|
|
- code.emitop2(putstatic, pool.put(member));
|
|
+ code.emitop2(putstatic, member, PoolWriter::putMember);
|
|
}
|
|
|
|
Item invoke() {
|
|
MethodType mtype = (MethodType)member.erasure(types);
|
|
int rescode = Code.typecode(mtype.restype);
|
|
- code.emitInvokestatic(pool.put(member), mtype);
|
|
+ code.emitInvokestatic(member, mtype);
|
|
return stackItem[rescode];
|
|
}
|
|
|
|
@@ -484,7 +486,7 @@ public class Items {
|
|
// assert target.hasNativeInvokeDynamic();
|
|
MethodType mtype = (MethodType)member.erasure(types);
|
|
int rescode = Code.typecode(mtype.restype);
|
|
- code.emitInvokedynamic(pool.put(member), mtype);
|
|
+ code.emitInvokedynamic((DynamicMethodSymbol)member, mtype);
|
|
return stackItem[rescode];
|
|
}
|
|
|
|
@@ -512,23 +514,23 @@ public class Items {
|
|
}
|
|
|
|
Item load() {
|
|
- code.emitop2(getfield, pool.put(member));
|
|
+ code.emitop2(getfield, member, PoolWriter::putMember);
|
|
return stackItem[typecode];
|
|
}
|
|
|
|
void store() {
|
|
- code.emitop2(putfield, pool.put(member));
|
|
+ code.emitop2(putfield, member, PoolWriter::putMember);
|
|
}
|
|
|
|
Item invoke() {
|
|
MethodType mtype = (MethodType)member.externalType(types);
|
|
int rescode = Code.typecode(mtype.restype);
|
|
if ((member.owner.flags() & Flags.INTERFACE) != 0 && !nonvirtual) {
|
|
- code.emitInvokeinterface(pool.put(member), mtype);
|
|
+ code.emitInvokeinterface(member, mtype);
|
|
} else if (nonvirtual) {
|
|
- code.emitInvokespecial(pool.put(member), mtype);
|
|
+ code.emitInvokespecial(member, mtype);
|
|
} else {
|
|
- code.emitInvokevirtual(pool.put(member), mtype);
|
|
+ code.emitInvokevirtual(member, mtype);
|
|
}
|
|
return stackItem[rescode];
|
|
}
|
|
@@ -560,26 +562,50 @@ public class Items {
|
|
|
|
/** The literal's value.
|
|
*/
|
|
- Object value;
|
|
+ final LoadableConstant value;
|
|
|
|
ImmediateItem(Type type, Object value) {
|
|
super(Code.typecode(type));
|
|
- this.value = value;
|
|
+ switch (typecode) {
|
|
+ case BYTEcode:
|
|
+ case SHORTcode:
|
|
+ case CHARcode:
|
|
+ case INTcode:
|
|
+ this.value = LoadableConstant.Int((int)value);
|
|
+ break;
|
|
+ case LONGcode:
|
|
+ this.value = LoadableConstant.Long((long)value);
|
|
+ break;
|
|
+ case FLOATcode:
|
|
+ this.value = LoadableConstant.Float((float)value);
|
|
+ break;
|
|
+ case DOUBLEcode:
|
|
+ this.value = LoadableConstant.Double((double)value);
|
|
+ break;
|
|
+ case OBJECTcode:
|
|
+ this.value = LoadableConstant.String((String)value);
|
|
+ break;
|
|
+ default:
|
|
+ throw new UnsupportedOperationException("unsupported tag: " + typecode);
|
|
+ }
|
|
}
|
|
|
|
private void ldc() {
|
|
- int idx = pool.put(value);
|
|
if (typecode == LONGcode || typecode == DOUBLEcode) {
|
|
- code.emitop2(ldc2w, idx);
|
|
+ code.emitop2(ldc2w, value, PoolWriter::putConstant);
|
|
} else {
|
|
- code.emitLdc(idx);
|
|
+ code.emitLdc(value);
|
|
}
|
|
}
|
|
|
|
+ private Number numericValue() {
|
|
+ return (Number)((BasicConstant)value).data;
|
|
+ }
|
|
+
|
|
Item load() {
|
|
switch (typecode) {
|
|
case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
|
|
- int ival = ((Number)value).intValue();
|
|
+ int ival = numericValue().intValue();
|
|
if (-1 <= ival && ival <= 5)
|
|
code.emitop0(iconst_0 + ival);
|
|
else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
|
|
@@ -590,14 +616,14 @@ public class Items {
|
|
ldc();
|
|
break;
|
|
case LONGcode:
|
|
- long lval = ((Number)value).longValue();
|
|
+ long lval = numericValue().longValue();
|
|
if (lval == 0 || lval == 1)
|
|
code.emitop0(lconst_0 + (int)lval);
|
|
else
|
|
ldc();
|
|
break;
|
|
case FLOATcode:
|
|
- float fval = ((Number)value).floatValue();
|
|
+ float fval = numericValue().floatValue();
|
|
if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
|
|
code.emitop0(fconst_0 + (int)fval);
|
|
else {
|
|
@@ -605,7 +631,7 @@ public class Items {
|
|
}
|
|
break;
|
|
case DOUBLEcode:
|
|
- double dval = ((Number)value).doubleValue();
|
|
+ double dval = numericValue().doubleValue();
|
|
if (isPosZero(dval) || dval == 1.0)
|
|
code.emitop0(dconst_0 + (int)dval);
|
|
else
|
|
@@ -632,7 +658,7 @@ public class Items {
|
|
}
|
|
|
|
CondItem mkCond() {
|
|
- int ival = ((Number)value).intValue();
|
|
+ int ival = numericValue().intValue();
|
|
return makeCondItem(ival != 0 ? goto_ : dontgoto);
|
|
}
|
|
|
|
@@ -647,31 +673,31 @@ public class Items {
|
|
else
|
|
return new ImmediateItem(
|
|
syms.intType,
|
|
- ((Number)value).intValue());
|
|
+ numericValue().intValue());
|
|
case LONGcode:
|
|
return new ImmediateItem(
|
|
syms.longType,
|
|
- ((Number)value).longValue());
|
|
+ numericValue().longValue());
|
|
case FLOATcode:
|
|
return new ImmediateItem(
|
|
syms.floatType,
|
|
- ((Number)value).floatValue());
|
|
+ numericValue().floatValue());
|
|
case DOUBLEcode:
|
|
return new ImmediateItem(
|
|
syms.doubleType,
|
|
- ((Number)value).doubleValue());
|
|
+ numericValue().doubleValue());
|
|
case BYTEcode:
|
|
return new ImmediateItem(
|
|
syms.byteType,
|
|
- (int)(byte)((Number)value).intValue());
|
|
+ (int)(byte)numericValue().intValue());
|
|
case CHARcode:
|
|
return new ImmediateItem(
|
|
syms.charType,
|
|
- (int)(char)((Number)value).intValue());
|
|
+ (int)(char)numericValue().intValue());
|
|
case SHORTcode:
|
|
return new ImmediateItem(
|
|
syms.shortType,
|
|
- (int)(short)((Number)value).intValue());
|
|
+ (int)(short)numericValue().intValue());
|
|
default:
|
|
return super.coerce(targetcode);
|
|
}
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java
|
|
index a2c6acb40..1badd42dc 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java
|
|
@@ -24,6 +24,9 @@
|
|
*/
|
|
package com.sun.tools.javac.jvm;
|
|
|
|
+import com.sun.tools.javac.util.ByteBuffer;
|
|
+import com.sun.tools.javac.util.Name.NameMapper;
|
|
+
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.nio.file.Files;
|
|
@@ -56,16 +59,15 @@ public class ModuleNameReader {
|
|
|
|
/** The buffer containing the currently read class file.
|
|
*/
|
|
- private byte[] buf = new byte[INITIAL_BUFFER_SIZE];
|
|
+ private ByteBuffer buf = new ByteBuffer(INITIAL_BUFFER_SIZE);
|
|
|
|
/** The current input pointer.
|
|
*/
|
|
private int bp;
|
|
|
|
- /** For every constant pool entry, an index into buf where the
|
|
- * defining section of the entry is found.
|
|
+ /** The constant pool reader.
|
|
*/
|
|
- private int[] poolIdx;
|
|
+ private PoolReader reader;
|
|
|
|
public ModuleNameReader() {
|
|
}
|
|
@@ -84,7 +86,8 @@ public class ModuleNameReader {
|
|
|
|
public String readModuleName(InputStream in) throws IOException, BadClassFile {
|
|
bp = 0;
|
|
- buf = readInputStream(buf, in);
|
|
+ buf.reset();
|
|
+ buf.appendStream(in);
|
|
|
|
int magic = nextInt();
|
|
if (magic != JAVA_MAGIC)
|
|
@@ -95,7 +98,8 @@ public class ModuleNameReader {
|
|
if (majorVersion < 53)
|
|
throw new BadClassFile("bad major version number for module: " + majorVersion);
|
|
|
|
- indexPool();
|
|
+ reader = new PoolReader(buf);
|
|
+ bp = reader.readPool(buf, bp);
|
|
|
|
int access_flags = nextChar();
|
|
if (access_flags != 0x8000)
|
|
@@ -111,8 +115,8 @@ public class ModuleNameReader {
|
|
for (int i = 0; i < attributes_count; i++) {
|
|
int attr_name = nextChar();
|
|
int attr_length = nextInt();
|
|
- if (getUtf8Value(attr_name, false).equals("Module") && attr_length > 2) {
|
|
- return getModuleName(nextChar());
|
|
+ if (reader.peekName(attr_name, utf8Mapper(false)).equals("Module") && attr_length > 2) {
|
|
+ return reader.peekModuleName(nextChar(), utf8Mapper(true));
|
|
} else {
|
|
// skip over unknown attributes
|
|
bp += attr_length;
|
|
@@ -126,118 +130,27 @@ public class ModuleNameReader {
|
|
throw new BadClassFile("invalid " + name + " for module: " + count);
|
|
}
|
|
|
|
- /** Extract a character at position bp from buf.
|
|
- */
|
|
- char getChar(int bp) {
|
|
- return
|
|
- (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF));
|
|
- }
|
|
-
|
|
/** Read a character.
|
|
*/
|
|
char nextChar() {
|
|
- return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
|
|
+ char res = buf.getChar(bp);
|
|
+ bp += 2;
|
|
+ return res;
|
|
}
|
|
|
|
/** Read an integer.
|
|
*/
|
|
int nextInt() {
|
|
- return
|
|
- ((buf[bp++] & 0xFF) << 24) +
|
|
- ((buf[bp++] & 0xFF) << 16) +
|
|
- ((buf[bp++] & 0xFF) << 8) +
|
|
- (buf[bp++] & 0xFF);
|
|
+ int res = buf.getInt(bp);
|
|
+ bp += 4;
|
|
+ return res;
|
|
}
|
|
|
|
- /** Index all constant pool entries, writing their start addresses into
|
|
- * poolIdx.
|
|
- */
|
|
- void indexPool() throws BadClassFile {
|
|
- poolIdx = new int[nextChar()];
|
|
- int i = 1;
|
|
- while (i < poolIdx.length) {
|
|
- poolIdx[i++] = bp;
|
|
- byte tag = buf[bp++];
|
|
- switch (tag) {
|
|
- case CONSTANT_Utf8: case CONSTANT_Unicode: {
|
|
- int len = nextChar();
|
|
- bp = bp + len;
|
|
- break;
|
|
- }
|
|
- case CONSTANT_Class:
|
|
- case CONSTANT_String:
|
|
- case CONSTANT_MethodType:
|
|
- case CONSTANT_Module:
|
|
- case CONSTANT_Package:
|
|
- bp = bp + 2;
|
|
- break;
|
|
- case CONSTANT_MethodHandle:
|
|
- bp = bp + 3;
|
|
- break;
|
|
- case CONSTANT_Fieldref:
|
|
- case CONSTANT_Methodref:
|
|
- case CONSTANT_InterfaceMethodref:
|
|
- case CONSTANT_NameandType:
|
|
- case CONSTANT_Integer:
|
|
- case CONSTANT_Float:
|
|
- case CONSTANT_InvokeDynamic:
|
|
- bp = bp + 4;
|
|
- break;
|
|
- case CONSTANT_Long:
|
|
- case CONSTANT_Double:
|
|
- bp = bp + 8;
|
|
- i++;
|
|
- break;
|
|
- default:
|
|
- throw new BadClassFile("malformed constant pool");
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- String getUtf8Value(int index, boolean internalize) throws BadClassFile {
|
|
- int utf8Index = poolIdx[index];
|
|
- if (buf[utf8Index] == CONSTANT_Utf8) {
|
|
- int len = getChar(utf8Index + 1);
|
|
- int start = utf8Index + 3;
|
|
- if (internalize) {
|
|
- return Convert.utf2string(ClassFile.internalize(buf, start, len));
|
|
- } else {
|
|
- return Convert.utf2string(buf, start, len);
|
|
- }
|
|
- }
|
|
- throw new BadClassFile("bad name at index " + index);
|
|
- }
|
|
-
|
|
- String getModuleName(int index) throws BadClassFile {
|
|
- int infoIndex = poolIdx[index];
|
|
- if (buf[infoIndex] == CONSTANT_Module) {
|
|
- return getUtf8Value(getChar(infoIndex + 1), true);
|
|
- } else {
|
|
- throw new BadClassFile("bad module name at index " + index);
|
|
- }
|
|
- }
|
|
-
|
|
- private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
|
|
- try {
|
|
- buf = ensureCapacity(buf, s.available());
|
|
- int r = s.read(buf);
|
|
- int bp = 0;
|
|
- while (r != -1) {
|
|
- bp += r;
|
|
- buf = ensureCapacity(buf, bp);
|
|
- r = s.read(buf, bp, buf.length - bp);
|
|
- }
|
|
- return buf;
|
|
- } finally {
|
|
- try {
|
|
- s.close();
|
|
- } catch (IOException e) {
|
|
- /* Ignore any errors, as this stream may have already
|
|
- * thrown a related exception which is the one that
|
|
- * should be reported.
|
|
- */
|
|
- }
|
|
- }
|
|
+ NameMapper<String> utf8Mapper(boolean internalize) {
|
|
+ return internalize ?
|
|
+ (buf, offset, len) ->
|
|
+ Convert.utf2string(ClassFile.internalize(buf, offset, len)) :
|
|
+ Convert::utf2string;
|
|
}
|
|
|
|
/*
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java
|
|
deleted file mode 100644
|
|
index 1611b6946..000000000
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java
|
|
+++ /dev/null
|
|
@@ -1,372 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
|
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
- *
|
|
- * This code is free software; you can redistribute it and/or modify it
|
|
- * under the terms of the GNU General Public License version 2 only, as
|
|
- * published by the Free Software Foundation. Oracle designates this
|
|
- * particular file as subject to the "Classpath" exception as provided
|
|
- * by Oracle in the LICENSE file that accompanied this code.
|
|
- *
|
|
- * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
- * version 2 for more details (a copy is included in the LICENSE file that
|
|
- * accompanied this code).
|
|
- *
|
|
- * You should have received a copy of the GNU General Public License version
|
|
- * 2 along with this work; if not, write to the Free Software Foundation,
|
|
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
- *
|
|
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
- * or visit www.oracle.com if you need additional information or have any
|
|
- * questions.
|
|
- */
|
|
-
|
|
-package com.sun.tools.javac.jvm;
|
|
-
|
|
-import com.sun.tools.javac.code.Symbol;
|
|
-import com.sun.tools.javac.code.Symbol.*;
|
|
-import com.sun.tools.javac.code.TypeTag;
|
|
-import com.sun.tools.javac.code.Type;
|
|
-import com.sun.tools.javac.code.Types;
|
|
-import com.sun.tools.javac.code.Types.UniqueType;
|
|
-
|
|
-import com.sun.tools.javac.util.ArrayUtils;
|
|
-import com.sun.tools.javac.util.Assert;
|
|
-import com.sun.tools.javac.util.Filter;
|
|
-import com.sun.tools.javac.util.Name;
|
|
-
|
|
-import java.util.*;
|
|
-
|
|
-import com.sun.tools.javac.util.DefinedBy;
|
|
-import com.sun.tools.javac.util.DefinedBy.Api;
|
|
-
|
|
-import static com.sun.tools.javac.code.Kinds.*;
|
|
-import static com.sun.tools.javac.code.Kinds.Kind.*;
|
|
-
|
|
-/** An internal structure that corresponds to the constant pool of a classfile.
|
|
- *
|
|
- * <p><b>This is NOT part of any supported API.
|
|
- * If you write code that depends on this, you do so at your own risk.
|
|
- * This code and its internal interfaces are subject to change or
|
|
- * deletion without notice.</b>
|
|
- */
|
|
-public class Pool {
|
|
-
|
|
- public static final int MAX_ENTRIES = 0xFFFF;
|
|
- public static final int MAX_STRING_LENGTH = 0xFFFF;
|
|
-
|
|
- /** Index of next constant to be entered.
|
|
- */
|
|
- int pp;
|
|
-
|
|
- /** The initial pool buffer.
|
|
- */
|
|
- Object[] pool;
|
|
-
|
|
- /** A hashtable containing all constants in the pool.
|
|
- */
|
|
- Map<Object,Integer> indices;
|
|
-
|
|
- Types types;
|
|
-
|
|
- /** Construct a pool with given number of elements and element array.
|
|
- */
|
|
- public Pool(int pp, Object[] pool, Types types) {
|
|
- this.pp = pp;
|
|
- this.pool = pool;
|
|
- this.types = types;
|
|
- this.indices = new HashMap<>(pool.length);
|
|
- for (int i = 1; i < pp; i++) {
|
|
- if (pool[i] != null) indices.put(pool[i], i);
|
|
- }
|
|
- }
|
|
-
|
|
- /** Construct an empty pool.
|
|
- */
|
|
- public Pool(Types types) {
|
|
- this(1, new Object[64], types);
|
|
- }
|
|
-
|
|
- /** Return the number of entries in the constant pool.
|
|
- */
|
|
- public int numEntries() {
|
|
- return pp;
|
|
- }
|
|
-
|
|
- /** Remove everything from this pool.
|
|
- */
|
|
- public void reset() {
|
|
- pp = 1;
|
|
- indices.clear();
|
|
- }
|
|
-
|
|
- /** Place an object in the pool, unless it is already there.
|
|
- * If object is a symbol also enter its owner unless the owner is a
|
|
- * package. Return the object's index in the pool.
|
|
- */
|
|
- public int put(Object value) {
|
|
- value = makePoolValue(value);
|
|
- Assert.check(!(value instanceof Type.TypeVar));
|
|
- Assert.check(!(value instanceof Types.UniqueType &&
|
|
- ((UniqueType) value).type instanceof Type.TypeVar));
|
|
- Integer index = indices.get(value);
|
|
- if (index == null) {
|
|
- index = pp;
|
|
- indices.put(value, index);
|
|
- pool = ArrayUtils.ensureCapacity(pool, pp);
|
|
- pool[pp++] = value;
|
|
- if (value instanceof Long || value instanceof Double) {
|
|
- pool = ArrayUtils.ensureCapacity(pool, pp);
|
|
- pool[pp++] = null;
|
|
- }
|
|
- }
|
|
- return index.intValue();
|
|
- }
|
|
-
|
|
- Object makePoolValue(Object o) {
|
|
- if (o instanceof DynamicMethodSymbol) {
|
|
- return new DynamicMethod((DynamicMethodSymbol)o, types);
|
|
- } else if (o instanceof MethodSymbol) {
|
|
- return new Method((MethodSymbol)o, types);
|
|
- } else if (o instanceof VarSymbol) {
|
|
- return new Variable((VarSymbol)o, types);
|
|
- } else if (o instanceof Type) {
|
|
- Type t = (Type)o;
|
|
- // ClassRefs can come from ClassSymbols or from Types.
|
|
- // Return the symbol for these types to avoid duplicates
|
|
- // in the constant pool
|
|
- if (t.hasTag(TypeTag.CLASS))
|
|
- return t.tsym;
|
|
- else
|
|
- return new UniqueType(t, types);
|
|
- } else {
|
|
- return o;
|
|
- }
|
|
- }
|
|
-
|
|
- /** Return the given object's index in the pool,
|
|
- * or -1 if object is not in there.
|
|
- */
|
|
- public int get(Object o) {
|
|
- Integer n = indices.get(o);
|
|
- return n == null ? -1 : n.intValue();
|
|
- }
|
|
-
|
|
- static class Method extends DelegatedSymbol<MethodSymbol> {
|
|
- UniqueType uniqueType;
|
|
- Method(MethodSymbol m, Types types) {
|
|
- super(m);
|
|
- this.uniqueType = new UniqueType(m.type, types);
|
|
- }
|
|
- @DefinedBy(Api.LANGUAGE_MODEL)
|
|
- public boolean equals(Object any) {
|
|
- if (!(any instanceof Method)) return false;
|
|
- MethodSymbol o = ((Method)any).other;
|
|
- MethodSymbol m = this.other;
|
|
- return
|
|
- o.name == m.name &&
|
|
- o.owner == m.owner &&
|
|
- ((Method)any).uniqueType.equals(uniqueType);
|
|
- }
|
|
- @DefinedBy(Api.LANGUAGE_MODEL)
|
|
- public int hashCode() {
|
|
- MethodSymbol m = this.other;
|
|
- return
|
|
- m.name.hashCode() * 33 +
|
|
- m.owner.hashCode() * 9 +
|
|
- uniqueType.hashCode();
|
|
- }
|
|
- }
|
|
-
|
|
- public static class DynamicMethod extends Method {
|
|
- public Object[] uniqueStaticArgs;
|
|
-
|
|
- public DynamicMethod(DynamicMethodSymbol m, Types types) {
|
|
- super(m, types);
|
|
- uniqueStaticArgs = getUniqueTypeArray(m.staticArgs, types);
|
|
- }
|
|
-
|
|
- @Override @DefinedBy(Api.LANGUAGE_MODEL)
|
|
- public boolean equals(Object any) {
|
|
- return equalsImpl(any, true);
|
|
- }
|
|
-
|
|
- protected boolean equalsImpl(Object any, boolean includeDynamicArgs) {
|
|
- if (includeDynamicArgs && !super.equals(any)) return false;
|
|
- if (!(any instanceof DynamicMethod)) return false;
|
|
- DynamicMethodSymbol dm1 = (DynamicMethodSymbol)other;
|
|
- DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)any).other;
|
|
- return dm1.bsm == dm2.bsm &&
|
|
- dm1.bsmKind == dm2.bsmKind &&
|
|
- Arrays.equals(uniqueStaticArgs,
|
|
- ((DynamicMethod)any).uniqueStaticArgs);
|
|
- }
|
|
-
|
|
- @Override @DefinedBy(Api.LANGUAGE_MODEL)
|
|
- public int hashCode() {
|
|
- return hashCodeImpl(true);
|
|
- }
|
|
-
|
|
- protected int hashCodeImpl(boolean includeDynamicArgs) {
|
|
- int hash = includeDynamicArgs ? super.hashCode() : 0;
|
|
- DynamicMethodSymbol dm = (DynamicMethodSymbol)other;
|
|
- hash += dm.bsmKind * 7 +
|
|
- dm.bsm.hashCode() * 11;
|
|
- for (int i = 0; i < dm.staticArgs.length; i++) {
|
|
- hash += (uniqueStaticArgs[i].hashCode() * 23);
|
|
- }
|
|
- return hash;
|
|
- }
|
|
-
|
|
- private Object[] getUniqueTypeArray(Object[] objects, Types types) {
|
|
- Object[] result = new Object[objects.length];
|
|
- for (int i = 0; i < objects.length; i++) {
|
|
- if (objects[i] instanceof Type) {
|
|
- result[i] = new UniqueType((Type)objects[i], types);
|
|
- } else {
|
|
- result[i] = objects[i];
|
|
- }
|
|
- }
|
|
- return result;
|
|
- }
|
|
-
|
|
- static class BootstrapMethodsKey extends DynamicMethod {
|
|
- BootstrapMethodsKey(DynamicMethodSymbol m, Types types) {
|
|
- super(m, types);
|
|
- }
|
|
-
|
|
- @Override @DefinedBy(Api.LANGUAGE_MODEL)
|
|
- public boolean equals(Object any) {
|
|
- return equalsImpl(any, false);
|
|
- }
|
|
-
|
|
- @Override @DefinedBy(Api.LANGUAGE_MODEL)
|
|
- public int hashCode() {
|
|
- return hashCodeImpl(false);
|
|
- }
|
|
-
|
|
- Object[] getUniqueArgs() {
|
|
- return uniqueStaticArgs;
|
|
- }
|
|
- }
|
|
-
|
|
- static class BootstrapMethodsValue {
|
|
- final MethodHandle mh;
|
|
- final int index;
|
|
-
|
|
- public BootstrapMethodsValue(MethodHandle mh, int index) {
|
|
- this.mh = mh;
|
|
- this.index = index;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- static class Variable extends DelegatedSymbol<VarSymbol> {
|
|
- UniqueType uniqueType;
|
|
- Variable(VarSymbol v, Types types) {
|
|
- super(v);
|
|
- this.uniqueType = new UniqueType(v.type, types);
|
|
- }
|
|
- @DefinedBy(Api.LANGUAGE_MODEL)
|
|
- public boolean equals(Object any) {
|
|
- if (!(any instanceof Variable)) return false;
|
|
- VarSymbol o = ((Variable)any).other;
|
|
- VarSymbol v = other;
|
|
- return
|
|
- o.name == v.name &&
|
|
- o.owner == v.owner &&
|
|
- ((Variable)any).uniqueType.equals(uniqueType);
|
|
- }
|
|
- @DefinedBy(Api.LANGUAGE_MODEL)
|
|
- public int hashCode() {
|
|
- VarSymbol v = other;
|
|
- return
|
|
- v.name.hashCode() * 33 +
|
|
- v.owner.hashCode() * 9 +
|
|
- uniqueType.hashCode();
|
|
- }
|
|
- }
|
|
-
|
|
- public static class MethodHandle {
|
|
-
|
|
- /** Reference kind - see ClassFile */
|
|
- int refKind;
|
|
-
|
|
- /** Reference symbol */
|
|
- Symbol refSym;
|
|
-
|
|
- UniqueType uniqueType;
|
|
-
|
|
- public MethodHandle(int refKind, Symbol refSym, Types types) {
|
|
- this.refKind = refKind;
|
|
- this.refSym = refSym;
|
|
- this.uniqueType = new UniqueType(this.refSym.type, types);
|
|
- checkConsistent();
|
|
- }
|
|
- public boolean equals(Object other) {
|
|
- if (!(other instanceof MethodHandle)) return false;
|
|
- MethodHandle mr = (MethodHandle) other;
|
|
- if (mr.refKind != refKind) return false;
|
|
- Symbol o = mr.refSym;
|
|
- return
|
|
- o.name == refSym.name &&
|
|
- o.owner == refSym.owner &&
|
|
- ((MethodHandle)other).uniqueType.equals(uniqueType);
|
|
- }
|
|
- public int hashCode() {
|
|
- return
|
|
- refKind * 65 +
|
|
- refSym.name.hashCode() * 33 +
|
|
- refSym.owner.hashCode() * 9 +
|
|
- uniqueType.hashCode();
|
|
- }
|
|
-
|
|
- /**
|
|
- * Check consistency of reference kind and symbol (see JVMS 4.4.8)
|
|
- */
|
|
- @SuppressWarnings("fallthrough")
|
|
- private void checkConsistent() {
|
|
- boolean staticOk = false;
|
|
- Kind expectedKind = null;
|
|
- Filter<Name> nameFilter = nonInitFilter;
|
|
- boolean interfaceOwner = false;
|
|
- switch (refKind) {
|
|
- case ClassFile.REF_getStatic:
|
|
- case ClassFile.REF_putStatic:
|
|
- staticOk = true;
|
|
- case ClassFile.REF_getField:
|
|
- case ClassFile.REF_putField:
|
|
- expectedKind = VAR;
|
|
- break;
|
|
- case ClassFile.REF_newInvokeSpecial:
|
|
- nameFilter = initFilter;
|
|
- expectedKind = MTH;
|
|
- break;
|
|
- case ClassFile.REF_invokeInterface:
|
|
- interfaceOwner = true;
|
|
- expectedKind = MTH;
|
|
- break;
|
|
- case ClassFile.REF_invokeStatic:
|
|
- interfaceOwner = true;
|
|
- staticOk = true;
|
|
- case ClassFile.REF_invokeVirtual:
|
|
- expectedKind = MTH;
|
|
- break;
|
|
- case ClassFile.REF_invokeSpecial:
|
|
- interfaceOwner = true;
|
|
- expectedKind = MTH;
|
|
- break;
|
|
- }
|
|
- Assert.check(!refSym.isStatic() || staticOk);
|
|
- Assert.check(refSym.kind == expectedKind);
|
|
- Assert.check(nameFilter.accepts(refSym.name));
|
|
- Assert.check(!refSym.owner.isInterface() || interfaceOwner);
|
|
- }
|
|
- //where
|
|
- Filter<Name> nonInitFilter = n -> (n != n.table.names.init && n != n.table.names.clinit);
|
|
-
|
|
- Filter<Name> initFilter = n -> n == n.table.names.init;
|
|
- }
|
|
-}
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolConstant.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolConstant.java
|
|
new file mode 100644
|
|
index 000000000..0fc2cb76a
|
|
--- /dev/null
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolConstant.java
|
|
@@ -0,0 +1,224 @@
|
|
+/*
|
|
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
|
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
+ *
|
|
+ * This code is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 only, as
|
|
+ * published by the Free Software Foundation. Oracle designates this
|
|
+ * particular file as subject to the "Classpath" exception as provided
|
|
+ * by Oracle in the LICENSE file that accompanied this code.
|
|
+ *
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
|
+ * accompanied this code).
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License version
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
|
+ * questions.
|
|
+ */
|
|
+
|
|
+package com.sun.tools.javac.jvm;
|
|
+
|
|
+import com.sun.tools.javac.code.Type;
|
|
+import com.sun.tools.javac.code.Types;
|
|
+import com.sun.tools.javac.code.Types.UniqueType;
|
|
+import com.sun.tools.javac.util.List;
|
|
+import com.sun.tools.javac.util.Name;
|
|
+import com.sun.tools.javac.util.Pair;
|
|
+
|
|
+import java.util.Objects;
|
|
+import java.util.stream.Stream;
|
|
+
|
|
+/**
|
|
+ * This interface models all javac entities that can be used to represent constant pool entries.
|
|
+ * A pool constant entity must (i) be associated with a constant pool entry tag and have a function
|
|
+ * which generates a key for the desired pool entry (so as to avoid duplicate entries when writing the
|
|
+ * constant pool).
|
|
+ */
|
|
+public interface PoolConstant {
|
|
+
|
|
+ /**
|
|
+ * The constant pool entry key.
|
|
+ */
|
|
+ default Object poolKey(Types types) { return this; }
|
|
+
|
|
+ /**
|
|
+ * The constant pool entry tag.
|
|
+ */
|
|
+ int poolTag();
|
|
+
|
|
+ /**
|
|
+ * The root of pool constants that can be loaded (e.g. with {@code ldc}, or appear as static
|
|
+ * arguments to a bootstrap method.
|
|
+ */
|
|
+ interface LoadableConstant extends PoolConstant {
|
|
+
|
|
+ /**
|
|
+ * Create a pool constant describing a given {@code int} value.
|
|
+ */
|
|
+ static LoadableConstant Int(int i) {
|
|
+ return new BasicConstant(ClassFile.CONSTANT_Integer, i);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Create a pool constant describing a given {@code float} value.
|
|
+ */
|
|
+ static LoadableConstant Float(float f) {
|
|
+ return new BasicConstant(ClassFile.CONSTANT_Float, f);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Create a pool constant describing a given {@code long} value.
|
|
+ */
|
|
+ static LoadableConstant Long(long l) {
|
|
+ return new BasicConstant(ClassFile.CONSTANT_Long, l);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Create a pool constant describing a given {@code double} value.
|
|
+ */
|
|
+ static LoadableConstant Double(double d) {
|
|
+ return new BasicConstant(ClassFile.CONSTANT_Double, d);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Create a pool constant describing a given {@code String} value.
|
|
+ */
|
|
+ static LoadableConstant String(String s) {
|
|
+ return new BasicConstant(ClassFile.CONSTANT_String, s);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * This class models a pool constant of given basic type, one of {@code int}, {@code float},
|
|
+ * {@code long}, {@code double} or {@code String}.
|
|
+ */
|
|
+ class BasicConstant implements LoadableConstant {
|
|
+ int tag;
|
|
+ Object data;
|
|
+
|
|
+ private BasicConstant(int tag, Object data) {
|
|
+ this.tag = tag;
|
|
+ this.data = data;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int poolTag() {
|
|
+ return tag;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Object poolKey(Types types) {
|
|
+ return data;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * This interface models a dynamic pool constant (either of kind {@code InvokeDynamic} or
|
|
+ * {@code ConstantDynamic}). In addition to the functionalities provided by the base interface,
|
|
+ * a dynamic pool constant must expose its dynamic type, bootstrap method and static argument list.
|
|
+ * Finally, a dynamic constant must have a way to compute a bootstrap method key - that is,
|
|
+ * a unique key for the bootstrap method entry it refers to, to avoid duplicates when writing
|
|
+ * the {@code BootstrapMethods} attribute.
|
|
+ */
|
|
+ interface Dynamic extends PoolConstant {
|
|
+
|
|
+ /**
|
|
+ * The dynamic constant's dynamic type.
|
|
+ */
|
|
+ PoolConstant dynamicType();
|
|
+
|
|
+ /**
|
|
+ * The dynamic constant's static argument list.
|
|
+ */
|
|
+ LoadableConstant[] staticArgs();
|
|
+
|
|
+ /**
|
|
+ * The dynamic constant's bootstrap method.
|
|
+ */
|
|
+ LoadableConstant bootstrapMethod();
|
|
+
|
|
+ default BsmKey bsmKey(Types types) {
|
|
+ return new BsmKey(types, bootstrapMethod(), staticArgs());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ default Object poolKey(Types types) {
|
|
+ return new Pair<>(bsmKey(types), dynamicType().poolKey(types));
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * A class modelling a bootstrap method key.
|
|
+ */
|
|
+ class BsmKey {
|
|
+ /**
|
|
+ * The key's bootstrap method constant.
|
|
+ */
|
|
+ public final LoadableConstant bsm;
|
|
+
|
|
+ /**
|
|
+ * The key's static argument list.
|
|
+ */
|
|
+ public final LoadableConstant[] staticArgs;
|
|
+
|
|
+ private final Object bsmKey;
|
|
+ private final List<?> staticArgKeys;
|
|
+
|
|
+ private BsmKey(Types types, LoadableConstant bsm, LoadableConstant[] staticArgs) {
|
|
+ this.bsm = bsm;
|
|
+ this.bsmKey = bsm.poolKey(types);
|
|
+ this.staticArgs = staticArgs;
|
|
+ this.staticArgKeys = Stream.of(staticArgs)
|
|
+ .map(p -> p.poolKey(types))
|
|
+ .collect(List.collector());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int hashCode() {
|
|
+ return bsmKey.hashCode() +
|
|
+ staticArgKeys.hashCode();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean equals(Object obj) {
|
|
+ if (obj instanceof BsmKey) {
|
|
+ BsmKey other = (BsmKey)obj;
|
|
+ return Objects.equals(bsmKey, other.bsmKey) &&
|
|
+ Objects.equals(staticArgKeys, other.staticArgKeys);
|
|
+ } else {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * A pool constant implememntation describing a name and type pool entry.
|
|
+ */
|
|
+ final class NameAndType implements PoolConstant {
|
|
+
|
|
+ final Name name;
|
|
+ final Type type;
|
|
+
|
|
+ NameAndType(Name name, Type type) {
|
|
+ this.name = name;
|
|
+ this.type = type;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int poolTag() {
|
|
+ return ClassFile.CONSTANT_NameandType;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Object poolKey(Types types) {
|
|
+ return new Pair<>(name, new UniqueType(type, types));
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java
|
|
new file mode 100644
|
|
index 000000000..0a1e37ee7
|
|
--- /dev/null
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java
|
|
@@ -0,0 +1,329 @@
|
|
+/*
|
|
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
|
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
+ *
|
|
+ * This code is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 only, as
|
|
+ * published by the Free Software Foundation. Oracle designates this
|
|
+ * particular file as subject to the "Classpath" exception as provided
|
|
+ * by Oracle in the LICENSE file that accompanied this code.
|
|
+ *
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
|
+ * accompanied this code).
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License version
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
|
+ * questions.
|
|
+ */
|
|
+
|
|
+package com.sun.tools.javac.jvm;
|
|
+
|
|
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
|
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
|
|
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
|
|
+import com.sun.tools.javac.code.Symtab;
|
|
+import com.sun.tools.javac.code.Type;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
|
|
+import com.sun.tools.javac.util.ByteBuffer;
|
|
+import com.sun.tools.javac.util.Name;
|
|
+import com.sun.tools.javac.util.Name.NameMapper;
|
|
+import com.sun.tools.javac.util.Names;
|
|
+
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Double;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Dynamic;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Fieldref;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Float;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Integer;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_InterfaceMethodref;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_InvokeDynamic;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Long;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodHandle;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Methodref;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodType;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Module;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_NameandType;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Package;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_String;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Utf8;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.internalize;
|
|
+
|
|
+/**
|
|
+ * Pool interface towards {@code ClassReader}. Exposes methods to decode and read javac entities
|
|
+ * from the constant pool.
|
|
+ *
|
|
+ * <p><b>This is NOT part of any supported API.
|
|
+ * If you write code that depends on this, you do so at your own risk.
|
|
+ * This code and its internal interfaces are subject to change or
|
|
+ * deletion without notice.</b>
|
|
+ */
|
|
+public class PoolReader {
|
|
+
|
|
+ private final ClassReader reader;
|
|
+ private final ByteBuffer buf;
|
|
+ private final Names names;
|
|
+ private final Symtab syms;
|
|
+
|
|
+ private ImmutablePoolHelper pool;
|
|
+
|
|
+ PoolReader(ByteBuffer buf) {
|
|
+ this(null, buf, null, null);
|
|
+ }
|
|
+
|
|
+ PoolReader(ClassReader reader, Names names, Symtab syms) {
|
|
+ this(reader, reader.buf, names, syms);
|
|
+ }
|
|
+
|
|
+ PoolReader(ClassReader reader, ByteBuffer buf, Names names, Symtab syms) {
|
|
+ this.reader = reader;
|
|
+ this.buf = buf;
|
|
+ this.names = names;
|
|
+ this.syms = syms;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get a class symbol from the pool at given index.
|
|
+ */
|
|
+ ClassSymbol getClass(int index) {
|
|
+ return pool.readIfNeeded(index);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get class name without resolving
|
|
+ */
|
|
+ <Z> Z peekClassName(int index, NameMapper<Z> mapper) {
|
|
+ return peekName(buf.getChar(pool.offset(index)), mapper);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get package name without resolving
|
|
+ */
|
|
+ <Z> Z peekPackageName(int index, NameMapper<Z> mapper) {
|
|
+ return peekName(buf.getChar(pool.offset(index)), mapper);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get module name without resolving
|
|
+ */
|
|
+ <Z> Z peekModuleName(int index, NameMapper<Z> mapper) {
|
|
+ return peekName(buf.getChar(pool.offset(index)), mapper);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get a module symbol from the pool at given index.
|
|
+ */
|
|
+ ModuleSymbol getModule(int index) {
|
|
+ return pool.readIfNeeded(index);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get a module symbol from the pool at given index.
|
|
+ */
|
|
+ PackageSymbol getPackage(int index) {
|
|
+ return pool.readIfNeeded(index);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Peek a name from the pool at given index without resolving.
|
|
+ */
|
|
+ <Z> Z peekName(int index, Name.NameMapper<Z> mapper) {
|
|
+ return getUtf8(index, mapper);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get a name from the pool at given index.
|
|
+ */
|
|
+ Name getName(int index) {
|
|
+ return pool.readIfNeeded(index);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get a type from the pool at given index.
|
|
+ */
|
|
+ Type getType(int index) {
|
|
+ return getName(index).map(reader::sigToType);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get a name and type pair from the pool at given index.
|
|
+ */
|
|
+ NameAndType getNameAndType(int index) {
|
|
+ return pool.readIfNeeded(index);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get a class symbol from the pool at given index.
|
|
+ */
|
|
+ Object getConstant(int index) {
|
|
+ return pool.readIfNeeded(index);
|
|
+ }
|
|
+
|
|
+ boolean hasTag(int index, int tag) {
|
|
+ return pool.tag(index) == tag;
|
|
+ }
|
|
+
|
|
+ private <Z> Z getUtf8(int index, NameMapper<Z> mapper) {
|
|
+ int tag = pool.tag(index);
|
|
+ if (tag == CONSTANT_Utf8) {
|
|
+ int offset = pool.offset(index);
|
|
+ int len = pool.poolbuf.getChar(offset);
|
|
+ return mapper.map(pool.poolbuf.elems, offset + 2, len);
|
|
+ } else {
|
|
+ throw new AssertionError("Unexpected constant tag: " + tag);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private Object resolve(ByteBuffer poolbuf, int tag, int offset) {
|
|
+ switch (tag) {
|
|
+ case CONSTANT_Utf8: {
|
|
+ int len = poolbuf.getChar(offset);
|
|
+ return names.fromUtf(poolbuf.elems, offset + 2, len);
|
|
+ }
|
|
+ case CONSTANT_Class: {
|
|
+ int index = poolbuf.getChar(offset);
|
|
+ Name name = names.fromUtf(getName(index).map(ClassFile::internalize));
|
|
+ return syms.enterClass(reader.currentModule, name);
|
|
+ }
|
|
+ case CONSTANT_NameandType: {
|
|
+ Name name = getName(poolbuf.getChar(offset));
|
|
+ Type type = getType(poolbuf.getChar(offset + 2));
|
|
+ return new NameAndType(name, type);
|
|
+ }
|
|
+ case CONSTANT_Integer:
|
|
+ return poolbuf.getInt(offset);
|
|
+ case CONSTANT_Float:
|
|
+ return poolbuf.getFloat(offset);
|
|
+ case CONSTANT_Long:
|
|
+ return poolbuf.getLong(offset);
|
|
+ case CONSTANT_Double:
|
|
+ return poolbuf.getDouble(offset);
|
|
+ case CONSTANT_String:
|
|
+ return getName(poolbuf.getChar(offset)).toString();
|
|
+ case CONSTANT_Package: {
|
|
+ Name name = getName(poolbuf.getChar(offset));
|
|
+ return syms.enterPackage(reader.currentModule, names.fromUtf(internalize(name)));
|
|
+ }
|
|
+ case CONSTANT_Module: {
|
|
+ Name name = getName(poolbuf.getChar(offset));
|
|
+ return syms.enterModule(name);
|
|
+ }
|
|
+ default:
|
|
+ throw new AssertionError("Unexpected constant tag: " + tag);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Parse all constant pool entries, and keep track of their offsets. For performance and laziness
|
|
+ * reasons, it would be unwise to eagerly turn all pool entries into corresponding javac
|
|
+ * entities. First, not all entries are actually going to be read/used by javac; secondly,
|
|
+ * there are cases where creating a symbol too early might result in issues (hence methods like
|
|
+ * {@link PoolReader#peekClassName(int, NameMapper)}.
|
|
+ */
|
|
+ int readPool(ByteBuffer poolbuf, int offset) {
|
|
+ int poolSize = poolbuf.getChar(offset);
|
|
+ int index = 1;
|
|
+ offset += 2;
|
|
+ int[] offsets = new int[poolSize];
|
|
+ while (index < poolSize) {
|
|
+ byte tag = poolbuf.getByte(offset++);
|
|
+ offsets[index] = offset;
|
|
+ switch (tag) {
|
|
+ case CONSTANT_Utf8: {
|
|
+ int len = poolbuf.getChar(offset);
|
|
+ offset += 2 + len;
|
|
+ break;
|
|
+ }
|
|
+ case CONSTANT_Class:
|
|
+ case CONSTANT_String:
|
|
+ case CONSTANT_Module:
|
|
+ case CONSTANT_Package:
|
|
+ case CONSTANT_MethodType:
|
|
+ offset += 2;
|
|
+ break;
|
|
+ case CONSTANT_MethodHandle:
|
|
+ offset += 3;
|
|
+ break;
|
|
+ case CONSTANT_Fieldref:
|
|
+ case CONSTANT_Methodref:
|
|
+ case CONSTANT_InterfaceMethodref:
|
|
+ case CONSTANT_NameandType:
|
|
+ case CONSTANT_Integer:
|
|
+ case CONSTANT_Float:
|
|
+ case CONSTANT_Dynamic:
|
|
+ case CONSTANT_InvokeDynamic:
|
|
+ offset += 4;
|
|
+ break;
|
|
+ case CONSTANT_Long:
|
|
+ case CONSTANT_Double:
|
|
+ offset += 8;
|
|
+ break;
|
|
+ default:
|
|
+ throw reader.badClassFile("bad.const.pool.tag.at",
|
|
+ Byte.toString(tag),
|
|
+ Integer.toString(offset - 1));
|
|
+ }
|
|
+ index += sizeof(tag);
|
|
+ }
|
|
+ pool = new ImmutablePoolHelper(poolbuf, offsets);
|
|
+ return offset;
|
|
+ }
|
|
+
|
|
+ private int sizeof(int tag) {
|
|
+ switch (tag) {
|
|
+ case ClassFile.CONSTANT_Double: case ClassFile.CONSTANT_Long:
|
|
+ return 2;
|
|
+ default:
|
|
+ return 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ class ImmutablePoolHelper {
|
|
+
|
|
+ final Object[] values;
|
|
+ final int[] offsets;
|
|
+ final ByteBuffer poolbuf;
|
|
+
|
|
+ public ImmutablePoolHelper(ByteBuffer poolbuf, int[] offsets) {
|
|
+ this.offsets = offsets;
|
|
+ this.values = new Object[offsets.length];
|
|
+ this.poolbuf = poolbuf;
|
|
+ }
|
|
+
|
|
+ private int checkIndex(int index) {
|
|
+ if (index <= 0 || index >= offsets.length) {
|
|
+ //pool index is outside valid range.
|
|
+ throw reader.badClassFile("bad.const.pool.index", reader.currentClassFile,
|
|
+ index, offsets.length);
|
|
+ } else {
|
|
+ return index;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ int offset(int index) {
|
|
+ return offsets[checkIndex(index)];
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("unchecked")
|
|
+ <P> P readIfNeeded(int index) {
|
|
+ Object v = values[checkIndex(index)];
|
|
+ if (v != null) {
|
|
+ return (P)v;
|
|
+ } else {
|
|
+ P p = (P)resolve(poolbuf, tag(index), offset(index));
|
|
+ values[index] = p;
|
|
+ return p;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ int tag(int index) {
|
|
+ return poolbuf.elems[offset(index) - 1];
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java
|
|
new file mode 100644
|
|
index 000000000..e9d9499dc
|
|
--- /dev/null
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java
|
|
@@ -0,0 +1,506 @@
|
|
+/*
|
|
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
|
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
+ *
|
|
+ * This code is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 only, as
|
|
+ * published by the Free Software Foundation. Oracle designates this
|
|
+ * particular file as subject to the "Classpath" exception as provided
|
|
+ * by Oracle in the LICENSE file that accompanied this code.
|
|
+ *
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
|
+ * accompanied this code).
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License version
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
|
+ * questions.
|
|
+ */
|
|
+
|
|
+package com.sun.tools.javac.jvm;
|
|
+
|
|
+import com.sun.tools.javac.code.Kinds.Kind;
|
|
+import com.sun.tools.javac.code.Symbol;
|
|
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
|
+import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
|
|
+import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
|
|
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
|
|
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
|
|
+import com.sun.tools.javac.code.Type;
|
|
+import com.sun.tools.javac.code.Types;
|
|
+import com.sun.tools.javac.jvm.ClassWriter.PoolOverflow;
|
|
+import com.sun.tools.javac.jvm.ClassWriter.StringOverflow;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant.BasicConstant;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.Dynamic;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.Dynamic.BsmKey;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
|
|
+import com.sun.tools.javac.util.ByteBuffer;
|
|
+import com.sun.tools.javac.util.List;
|
|
+import com.sun.tools.javac.util.Name;
|
|
+import com.sun.tools.javac.util.Names;
|
|
+
|
|
+import java.io.IOException;
|
|
+import java.io.OutputStream;
|
|
+import java.util.ArrayDeque;
|
|
+import java.util.HashMap;
|
|
+import java.util.LinkedHashMap;
|
|
+import java.util.LinkedHashSet;
|
|
+import java.util.Map;
|
|
+
|
|
+import static com.sun.tools.javac.code.Kinds.Kind.TYP;
|
|
+import static com.sun.tools.javac.code.TypeTag.ARRAY;
|
|
+import static com.sun.tools.javac.code.TypeTag.CLASS;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodType;
|
|
+import static com.sun.tools.javac.jvm.ClassFile.externalize;
|
|
+
|
|
+/**
|
|
+ * Pool interface towards {@code ClassWriter}. Exposes methods to encode and write javac entities
|
|
+ * into the constant pool.
|
|
+ *
|
|
+ * <p><b>This is NOT part of any supported API.
|
|
+ * If you write code that depends on this, you do so at your own risk.
|
|
+ * This code and its internal interfaces are subject to change or
|
|
+ * deletion without notice.</b>
|
|
+ */
|
|
+public class PoolWriter {
|
|
+
|
|
+ /** Max number of constant pool entries. */
|
|
+ public static final int MAX_ENTRIES = 0xFFFF;
|
|
+
|
|
+ /** Max number of char in a string constant. */
|
|
+ public static final int MAX_STRING_LENGTH = 0xFFFF;
|
|
+
|
|
+ private static final int POOL_BUF_SIZE = 0x7fff;
|
|
+
|
|
+ private final Types types;
|
|
+
|
|
+ private final Names names;
|
|
+
|
|
+ /** Pool helper **/
|
|
+ final WriteablePoolHelper pool;
|
|
+
|
|
+ /** Sole signature generator */
|
|
+ final SharedSignatureGenerator signatureGen;
|
|
+
|
|
+ /** The inner classes to be written, as an ordered set (enclosing first). */
|
|
+ LinkedHashSet<ClassSymbol> innerClasses = new LinkedHashSet<>();
|
|
+
|
|
+ /** The list of entries in the BootstrapMethods attribute. */
|
|
+ Map<BsmKey, Integer> bootstrapMethods = new LinkedHashMap<>();
|
|
+
|
|
+ public PoolWriter(Types types, Names names) {
|
|
+ this.types = types;
|
|
+ this.names = names;
|
|
+ this.signatureGen = new SharedSignatureGenerator(types);
|
|
+ this.pool = new WriteablePoolHelper();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Puts a class symbol into the pool and return its index.
|
|
+ */
|
|
+ int putClass(ClassSymbol csym) {
|
|
+ return putClass(csym.type);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Puts a type into the pool and return its index. The type could be either a class, a type variable
|
|
+ * or an array type.
|
|
+ */
|
|
+ int putClass(Type t) {
|
|
+ return pool.writeIfNeeded(types.erasure(t));
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Puts a member reference into the constant pool. Valid members are either field or method symbols.
|
|
+ */
|
|
+ int putMember(Symbol s) {
|
|
+ return pool.writeIfNeeded(s);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Puts a dynamic reference into the constant pool and return its index.
|
|
+ */
|
|
+ int putDynamic(DynamicMethodSymbol d) {
|
|
+ return pool.writeIfNeeded(d);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Puts a field or method descriptor into the constant pool and return its index.
|
|
+ */
|
|
+ int putDescriptor(Type t) {
|
|
+ return putName(typeSig(types.erasure(t)));
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Puts a field or method descriptor into the constant pool and return its index.
|
|
+ */
|
|
+ int putDescriptor(Symbol s) {
|
|
+ return putDescriptor(descriptorType(s));
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Puts a signature (see {@code Signature} attribute in JVMS 4.4) into the constant pool and
|
|
+ * return its index.
|
|
+ */
|
|
+ int putSignature(Symbol s) {
|
|
+ if (s.kind == TYP) {
|
|
+ return putName(classSig(s.type));
|
|
+ } else {
|
|
+ return putName(typeSig(s.type));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Puts a constant value into the pool and return its index. Supported values are int, float, long,
|
|
+ * double and String.
|
|
+ */
|
|
+ int putConstant(Object o) {
|
|
+ if (o instanceof Integer) {
|
|
+ return putConstant(LoadableConstant.Int((int)o));
|
|
+ } else if (o instanceof Float) {
|
|
+ return putConstant(LoadableConstant.Float((float)o));
|
|
+ } else if (o instanceof Long) {
|
|
+ return putConstant(LoadableConstant.Long((long)o));
|
|
+ } else if (o instanceof Double) {
|
|
+ return putConstant(LoadableConstant.Double((double)o));
|
|
+ } else if (o instanceof String) {
|
|
+ return putConstant(LoadableConstant.String((String)o));
|
|
+ } else {
|
|
+ throw new AssertionError("unexpected constant: " + o);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Puts a constant into the pool and return its index.
|
|
+ */
|
|
+ int putConstant(LoadableConstant c) {
|
|
+ switch (c.poolTag()) {
|
|
+ case CONSTANT_Class:
|
|
+ return putClass((Type)c);
|
|
+ case CONSTANT_MethodType:
|
|
+ return pool.writeIfNeeded(types.erasure((Type)c));
|
|
+ default:
|
|
+ return pool.writeIfNeeded(c);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ int putName(Name name) {
|
|
+ return pool.writeIfNeeded(name);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Puts a name and type pair into the pool and returns its index.
|
|
+ */
|
|
+ int putNameAndType(Symbol s) {
|
|
+ return pool.writeIfNeeded(new NameAndType(s.name, descriptorType(s)));
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Puts a package entry into the pool and returns its index.
|
|
+ */
|
|
+ int putPackage(PackageSymbol pkg) {
|
|
+ return pool.writeIfNeeded(pkg);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Puts a module entry into the pool and returns its index.
|
|
+ */
|
|
+ int putModule(ModuleSymbol mod) {
|
|
+ return pool.writeIfNeeded(mod);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Enter an inner class into the `innerClasses' set.
|
|
+ */
|
|
+ void enterInner(ClassSymbol c) {
|
|
+ if (c.type.isCompound()) {
|
|
+ throw new AssertionError("Unexpected intersection type: " + c.type);
|
|
+ }
|
|
+ c.complete();
|
|
+ if (c.owner.enclClass() != null && !innerClasses.contains(c)) {
|
|
+ enterInner(c.owner.enclClass());
|
|
+ innerClasses.add(c);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Create a new Utf8 entry representing a descriptor for given (member) symbol.
|
|
+ */
|
|
+ private Type descriptorType(Symbol s) {
|
|
+ return s.kind == Kind.MTH ? s.externalType(types) : s.erasure(types);
|
|
+ }
|
|
+
|
|
+ private int makeBoostrapEntry(Dynamic dynamic) {
|
|
+ BsmKey bsmKey = dynamic.bsmKey(types);
|
|
+
|
|
+ // Figure out the index for existing BSM; create a new BSM if no key
|
|
+ Integer index = bootstrapMethods.get(bsmKey);
|
|
+ if (index == null) {
|
|
+ index = bootstrapMethods.size();
|
|
+ bootstrapMethods.put(bsmKey, index);
|
|
+ }
|
|
+
|
|
+ return index;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Write pool contents into given byte buffer.
|
|
+ */
|
|
+ void writePool(OutputStream out) throws IOException, PoolOverflow {
|
|
+ if (pool.overflowString != null) {
|
|
+ throw new StringOverflow(pool.overflowString);
|
|
+ }
|
|
+ int size = size();
|
|
+ if (size > MAX_ENTRIES) {
|
|
+ throw new PoolOverflow();
|
|
+ }
|
|
+ out.write(size >> 8);
|
|
+ out.write(size);
|
|
+ out.write(pool.poolbuf.elems, 0, pool.poolbuf.length);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Signature Generation
|
|
+ */
|
|
+ class SharedSignatureGenerator extends Types.SignatureGenerator {
|
|
+
|
|
+ /**
|
|
+ * An output buffer for type signatures.
|
|
+ */
|
|
+ ByteBuffer sigbuf = new ByteBuffer();
|
|
+
|
|
+ SharedSignatureGenerator(Types types) {
|
|
+ super(types);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Assemble signature of given type in string buffer.
|
|
+ * Check for uninitialized types before calling the general case.
|
|
+ */
|
|
+ @Override
|
|
+ public void assembleSig(Type type) {
|
|
+ switch (type.getTag()) {
|
|
+ case UNINITIALIZED_THIS:
|
|
+ case UNINITIALIZED_OBJECT:
|
|
+ // we don't yet have a spec for uninitialized types in the
|
|
+ // local variable table
|
|
+ assembleSig(types.erasure(((UninitializedType)type).qtype));
|
|
+ break;
|
|
+ default:
|
|
+ super.assembleSig(type);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void append(char ch) {
|
|
+ sigbuf.appendByte(ch);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void append(byte[] ba) {
|
|
+ sigbuf.appendBytes(ba);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void append(Name name) {
|
|
+ sigbuf.appendName(name);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void classReference(ClassSymbol c) {
|
|
+ enterInner(c);
|
|
+ }
|
|
+
|
|
+ protected void reset() {
|
|
+ sigbuf.reset();
|
|
+ }
|
|
+
|
|
+ protected Name toName() {
|
|
+ return sigbuf.toName(names);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ class WriteablePoolHelper {
|
|
+
|
|
+ /** Pool entries. */
|
|
+ private final Map<Object, Integer> keysToPos = new HashMap<>(64);
|
|
+
|
|
+ final ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE);
|
|
+
|
|
+ int currentIndex = 1;
|
|
+
|
|
+ ArrayDeque<PoolConstant> todo = new ArrayDeque<>();
|
|
+
|
|
+ String overflowString = null;
|
|
+
|
|
+ private <P extends PoolConstant> int writeIfNeeded(P p) {
|
|
+ Object key = p.poolKey(types);
|
|
+ Integer index = keysToPos.get(key);
|
|
+ if (index == null) {
|
|
+ keysToPos.put(key, index = currentIndex++);
|
|
+ boolean first = todo.isEmpty();
|
|
+ todo.addLast(p);
|
|
+ if (first) {
|
|
+ while (!todo.isEmpty()) {
|
|
+ writeConstant(todo.peekFirst());
|
|
+ todo.removeFirst();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return index;
|
|
+ }
|
|
+
|
|
+ void writeConstant(PoolConstant c) {
|
|
+ int tag = c.poolTag();
|
|
+ switch (tag) {
|
|
+ case ClassFile.CONSTANT_Class: {
|
|
+ Type ct = (Type)c;
|
|
+ Name name = ct.hasTag(ARRAY) ?
|
|
+ typeSig(ct) :
|
|
+ names.fromUtf(externalize(ct.tsym.flatName()));
|
|
+ poolbuf.appendByte(tag);
|
|
+ poolbuf.appendChar(putName(name));
|
|
+ if (ct.hasTag(CLASS)) {
|
|
+ enterInner((ClassSymbol)ct.tsym);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ case ClassFile.CONSTANT_Utf8: {
|
|
+ Name name = (Name)c;
|
|
+ poolbuf.appendByte(tag);
|
|
+ byte[] bs = name.toUtf();
|
|
+ poolbuf.appendChar(bs.length);
|
|
+ poolbuf.appendBytes(bs, 0, bs.length);
|
|
+ if (overflowString == null && bs.length > MAX_STRING_LENGTH) {
|
|
+ //report error only once
|
|
+ overflowString = new String(bs);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ case ClassFile.CONSTANT_InterfaceMethodref:
|
|
+ case ClassFile.CONSTANT_Methodref:
|
|
+ case ClassFile.CONSTANT_Fieldref: {
|
|
+ Symbol sym = (Symbol)c;
|
|
+ poolbuf.appendByte(tag);
|
|
+ poolbuf.appendChar(putClass((ClassSymbol)sym.owner));
|
|
+ poolbuf.appendChar(putNameAndType(sym));
|
|
+ break;
|
|
+ }
|
|
+ case ClassFile.CONSTANT_Package: {
|
|
+ PackageSymbol pkg = (PackageSymbol)c;
|
|
+ Name pkgName = names.fromUtf(externalize(pkg.flatName()));
|
|
+ poolbuf.appendByte(tag);
|
|
+ poolbuf.appendChar(putName(pkgName));
|
|
+ break;
|
|
+ }
|
|
+ case ClassFile.CONSTANT_Module: {
|
|
+ ModuleSymbol mod = (ModuleSymbol)c;
|
|
+ int modName = putName(mod.name);
|
|
+ poolbuf.appendByte(mod.poolTag());
|
|
+ poolbuf.appendChar(modName);
|
|
+ break;
|
|
+ }
|
|
+ case ClassFile.CONSTANT_Integer:
|
|
+ poolbuf.appendByte(tag);
|
|
+ poolbuf.appendInt((int)((BasicConstant)c).data);
|
|
+ break;
|
|
+ case ClassFile.CONSTANT_Float:
|
|
+ poolbuf.appendByte(tag);
|
|
+ poolbuf.appendFloat((float)((BasicConstant)c).data);
|
|
+ break;
|
|
+ case ClassFile.CONSTANT_Long:
|
|
+ currentIndex++;
|
|
+ poolbuf.appendByte(tag);
|
|
+ poolbuf.appendLong((long)((BasicConstant)c).data);
|
|
+ break;
|
|
+ case ClassFile.CONSTANT_Double:
|
|
+ currentIndex++;
|
|
+ poolbuf.appendByte(tag);
|
|
+ poolbuf.appendDouble((double)((BasicConstant)c).data);
|
|
+ break;
|
|
+ case ClassFile.CONSTANT_MethodHandle: {
|
|
+ MethodHandleSymbol h = (MethodHandleSymbol)c;
|
|
+ poolbuf.appendByte(tag);
|
|
+ poolbuf.appendByte(h.referenceKind());
|
|
+ poolbuf.appendChar(putMember(h.baseSymbol()));
|
|
+ break;
|
|
+ }
|
|
+ case ClassFile.CONSTANT_MethodType: {
|
|
+ Type.MethodType mt = (Type.MethodType)c;
|
|
+ poolbuf.appendByte(tag);
|
|
+ poolbuf.appendChar(putDescriptor(mt.baseType()));
|
|
+ break;
|
|
+ }
|
|
+ case ClassFile.CONSTANT_String: {
|
|
+ Name utf = names.fromString((String)((BasicConstant)c).data);
|
|
+ poolbuf.appendByte(tag);
|
|
+ poolbuf.appendChar(putName(utf));
|
|
+ break;
|
|
+ }
|
|
+ case ClassFile.CONSTANT_NameandType: {
|
|
+ NameAndType nt = (NameAndType)c;
|
|
+ poolbuf.appendByte(tag);
|
|
+ poolbuf.appendChar(putName(nt.name));
|
|
+ poolbuf.appendChar(putDescriptor(nt.type));
|
|
+ break;
|
|
+ }
|
|
+ case ClassFile.CONSTANT_InvokeDynamic: {
|
|
+ DynamicMethodSymbol d = (DynamicMethodSymbol)c;
|
|
+ poolbuf.appendByte(tag);
|
|
+ poolbuf.appendChar(makeBoostrapEntry(d));
|
|
+ poolbuf.appendChar(putNameAndType(d));
|
|
+ break;
|
|
+ }
|
|
+ default:
|
|
+ throw new AssertionError("Unexpected constant tag: " + tag);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ void reset() {
|
|
+ keysToPos.clear();
|
|
+ currentIndex = 1;
|
|
+ todo.clear();
|
|
+ overflowString = null;
|
|
+ poolbuf.reset();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ int size() {
|
|
+ return pool.currentIndex;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Return signature of given type
|
|
+ */
|
|
+ private Name typeSig(Type type) {
|
|
+ signatureGen.reset();
|
|
+ signatureGen.assembleSig(type);
|
|
+ return signatureGen.toName();
|
|
+ }
|
|
+
|
|
+ private Name classSig(Type t) {
|
|
+ signatureGen.reset();
|
|
+ List<Type> typarams = t.getTypeArguments();
|
|
+ if (typarams.nonEmpty()) {
|
|
+ signatureGen.assembleParamsSig(typarams);
|
|
+ }
|
|
+ signatureGen.assembleSig(types.supertype(t));
|
|
+ for (Type i : types.interfaces(t))
|
|
+ signatureGen.assembleSig(i);
|
|
+ return signatureGen.toName();
|
|
+ }
|
|
+
|
|
+ void reset() {
|
|
+ innerClasses.clear();
|
|
+ bootstrapMethods.clear();
|
|
+ pool.reset();
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java
|
|
index 4ade741a5..f11054d73 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java
|
|
@@ -26,7 +26,9 @@
|
|
package com.sun.tools.javac.jvm;
|
|
|
|
import com.sun.tools.javac.code.*;
|
|
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
|
import com.sun.tools.javac.comp.Resolve;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
|
|
import com.sun.tools.javac.tree.JCTree;
|
|
import com.sun.tools.javac.tree.TreeInfo;
|
|
import com.sun.tools.javac.tree.TreeMaker;
|
|
@@ -222,7 +224,7 @@ public abstract class StringConcat {
|
|
|
|
private JCDiagnostic.DiagnosticPosition newStringBuilder(JCTree tree) {
|
|
JCDiagnostic.DiagnosticPosition pos = tree.pos();
|
|
- gen.getCode().emitop2(new_, gen.makeRef(pos, syms.stringBuilderType));
|
|
+ gen.getCode().emitop2(new_, gen.makeRef(pos, syms.stringBuilderType), syms.stringBuilderType);
|
|
gen.getCode().emitop0(dup);
|
|
gen.callMethod(pos, syms.stringBuilderType, names.init, List.nil(), false);
|
|
return pos;
|
|
@@ -378,10 +380,9 @@ public abstract class StringConcat {
|
|
|
|
Symbol.DynamicMethodSymbol dynSym = new Symbol.DynamicMethodSymbol(names.makeConcat,
|
|
syms.noSymbol,
|
|
- ClassFile.REF_invokeStatic,
|
|
- (Symbol.MethodSymbol)bsm,
|
|
+ ((MethodSymbol)bsm).asHandle(),
|
|
indyType,
|
|
- List.nil().toArray());
|
|
+ List.nil().toArray(new LoadableConstant[0]));
|
|
|
|
Items.Item item = gen.getItems().makeDynamicItem(dynSym);
|
|
item.invoke();
|
|
@@ -416,7 +417,7 @@ public abstract class StringConcat {
|
|
|
|
StringBuilder recipe = new StringBuilder(t.size());
|
|
ListBuffer<Type> dynamicArgs = new ListBuffer<>();
|
|
- ListBuffer<Object> staticArgs = new ListBuffer<>();
|
|
+ ListBuffer<LoadableConstant> staticArgs = new ListBuffer<>();
|
|
|
|
for (JCTree arg : t) {
|
|
Object constVal = arg.type.constValue();
|
|
@@ -431,7 +432,7 @@ public abstract class StringConcat {
|
|
String a = arg.type.stringValue();
|
|
if (a.indexOf(TAG_CONST) != -1 || a.indexOf(TAG_ARG) != -1) {
|
|
recipe.append(TAG_CONST);
|
|
- staticArgs.add(a);
|
|
+ staticArgs.add(LoadableConstant.String(a));
|
|
} else {
|
|
recipe.append(a);
|
|
}
|
|
@@ -463,7 +464,7 @@ public abstract class StringConcat {
|
|
}
|
|
|
|
/** Produce the actual invokedynamic call to StringConcatFactory */
|
|
- private void doCall(Type type, JCDiagnostic.DiagnosticPosition pos, String recipe, List<Object> staticArgs, List<Type> dynamicArgTypes) {
|
|
+ private void doCall(Type type, JCDiagnostic.DiagnosticPosition pos, String recipe, List<LoadableConstant> staticArgs, List<Type> dynamicArgTypes) {
|
|
Type.MethodType indyType = new Type.MethodType(dynamicArgTypes,
|
|
type,
|
|
List.nil(),
|
|
@@ -474,8 +475,8 @@ public abstract class StringConcat {
|
|
make.at(pos);
|
|
|
|
ListBuffer<Type> constTypes = new ListBuffer<>();
|
|
- ListBuffer<Object> constants = new ListBuffer<>();
|
|
- for (Object t : staticArgs) {
|
|
+ ListBuffer<LoadableConstant> constants = new ListBuffer<>();
|
|
+ for (LoadableConstant t : staticArgs) {
|
|
constants.add(t);
|
|
constTypes.add(syms.stringType);
|
|
}
|
|
@@ -495,10 +496,10 @@ public abstract class StringConcat {
|
|
|
|
Symbol.DynamicMethodSymbol dynSym = new Symbol.DynamicMethodSymbol(names.makeConcatWithConstants,
|
|
syms.noSymbol,
|
|
- ClassFile.REF_invokeStatic,
|
|
- (Symbol.MethodSymbol)bsm,
|
|
+ ((MethodSymbol)bsm).asHandle(),
|
|
indyType,
|
|
- List.<Object>of(recipe).appendList(constants).toArray());
|
|
+ List.of(LoadableConstant.String(recipe))
|
|
+ .appendList(constants).toArray(new LoadableConstant[constants.size()]));
|
|
|
|
Items.Item item = gen.getItems().makeDynamicItem(dynSym);
|
|
item.invoke();
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
|
|
index e24a7253e..b05f9e508 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
|
|
@@ -2122,6 +2122,11 @@ compiler.misc.bad.const.pool.entry=\
|
|
bad constant pool entry in {0}\n\
|
|
expected {1} at index {2}
|
|
|
|
+# 0: file name, 1: number (constant pool index), 2: number (constant pool size)
|
|
+compiler.misc.bad.const.pool.index=\
|
|
+ bad constant pool index in {0}\n\
|
|
+ index {1} is not within pool size {2}.
|
|
+
|
|
# 0: file name, 1: message segment
|
|
compiler.misc.bad.class.file.header=\
|
|
bad class file: {0}\n\
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ByteBuffer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ByteBuffer.java
|
|
index 65a8c3690..842a42ea0 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ByteBuffer.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ByteBuffer.java
|
|
@@ -147,6 +147,90 @@ public class ByteBuffer {
|
|
appendBytes(name.getByteArray(), name.getByteOffset(), name.getByteLength());
|
|
}
|
|
|
|
+ /** Append the content of a given input stream.
|
|
+ */
|
|
+ public void appendStream(InputStream is) throws IOException {
|
|
+ try {
|
|
+ int start = length;
|
|
+ int initialSize = is.available();
|
|
+ elems = ArrayUtils.ensureCapacity(elems, length + initialSize);
|
|
+ int r = is.read(elems, start, initialSize);
|
|
+ int bp = start;
|
|
+ while (r != -1) {
|
|
+ bp += r;
|
|
+ elems = ArrayUtils.ensureCapacity(elems, bp);
|
|
+ r = is.read(elems, bp, elems.length - bp);
|
|
+ }
|
|
+ } finally {
|
|
+ try {
|
|
+ is.close();
|
|
+ } catch (IOException e) {
|
|
+ /* Ignore any errors, as this stream may have already
|
|
+ * thrown a related exception which is the one that
|
|
+ * should be reported.
|
|
+ */
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /** Extract an integer at position bp from elems.
|
|
+ */
|
|
+ public int getInt(int bp) {
|
|
+ return
|
|
+ ((elems[bp] & 0xFF) << 24) +
|
|
+ ((elems[bp+1] & 0xFF) << 16) +
|
|
+ ((elems[bp+2] & 0xFF) << 8) +
|
|
+ (elems[bp+3] & 0xFF);
|
|
+ }
|
|
+
|
|
+
|
|
+ /** Extract a long integer at position bp from elems.
|
|
+ */
|
|
+ public long getLong(int bp) {
|
|
+ DataInputStream elemsin =
|
|
+ new DataInputStream(new ByteArrayInputStream(elems, bp, 8));
|
|
+ try {
|
|
+ return elemsin.readLong();
|
|
+ } catch (IOException e) {
|
|
+ throw new AssertionError(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /** Extract a float at position bp from elems.
|
|
+ */
|
|
+ public float getFloat(int bp) {
|
|
+ DataInputStream elemsin =
|
|
+ new DataInputStream(new ByteArrayInputStream(elems, bp, 4));
|
|
+ try {
|
|
+ return elemsin.readFloat();
|
|
+ } catch (IOException e) {
|
|
+ throw new AssertionError(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /** Extract a double at position bp from elems.
|
|
+ */
|
|
+ public double getDouble(int bp) {
|
|
+ DataInputStream elemsin =
|
|
+ new DataInputStream(new ByteArrayInputStream(elems, bp, 8));
|
|
+ try {
|
|
+ return elemsin.readDouble();
|
|
+ } catch (IOException e) {
|
|
+ throw new AssertionError(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /** Extract a character at position bp from elems.
|
|
+ */
|
|
+ public char getChar(int bp) {
|
|
+ return
|
|
+ (char)(((elems[bp] & 0xFF) << 8) + (elems[bp+1] & 0xFF));
|
|
+ }
|
|
+
|
|
+ public byte getByte(int bp) {
|
|
+ return elems[bp];
|
|
+ }
|
|
+
|
|
/** Reset to zero length.
|
|
*/
|
|
public void reset() {
|
|
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java
|
|
index b1321f8c5..0ff4ea320 100644
|
|
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java
|
|
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java
|
|
@@ -25,6 +25,8 @@
|
|
|
|
package com.sun.tools.javac.util;
|
|
|
|
+import com.sun.tools.javac.jvm.ClassFile;
|
|
+import com.sun.tools.javac.jvm.PoolConstant;
|
|
import com.sun.tools.javac.util.DefinedBy.Api;
|
|
|
|
/** An abstraction for internal compiler strings. They are stored in
|
|
@@ -36,7 +38,7 @@ import com.sun.tools.javac.util.DefinedBy.Api;
|
|
* This code and its internal interfaces are subject to change or
|
|
* deletion without notice.</b>
|
|
*/
|
|
-public abstract class Name implements javax.lang.model.element.Name {
|
|
+public abstract class Name implements javax.lang.model.element.Name, PoolConstant {
|
|
|
|
public final Table table;
|
|
|
|
@@ -52,6 +54,11 @@ public abstract class Name implements javax.lang.model.element.Name {
|
|
return toString().equals(cs.toString());
|
|
}
|
|
|
|
+ @Override
|
|
+ public int poolTag() {
|
|
+ return ClassFile.CONSTANT_Utf8;
|
|
+ }
|
|
+
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@@ -188,6 +195,14 @@ public abstract class Name implements javax.lang.model.element.Name {
|
|
*/
|
|
public abstract int getByteOffset();
|
|
|
|
+ public interface NameMapper<X> {
|
|
+ X map(byte[] bytes, int offset, int len);
|
|
+ }
|
|
+
|
|
+ public <X> X map(NameMapper<X> mapper) {
|
|
+ return mapper.map(getByteArray(), getByteOffset(), getByteLength());
|
|
+ }
|
|
+
|
|
/** An abstraction for the hash table used to create unique Name instances.
|
|
*/
|
|
public static abstract class Table {
|
|
diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java
|
|
index 456225f64..5705219ad 100644
|
|
--- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java
|
|
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java
|
|
@@ -59,7 +59,7 @@ public class AnnotatedExtendsTest {
|
|
.classes(classPath.toString())
|
|
.run()
|
|
.getOutput(Task.OutputKind.DIRECT);
|
|
- if (!javapOut.contains("0: #21(): CLASS_EXTENDS, type_index=65535"))
|
|
+ if (!javapOut.contains("0: #22(): CLASS_EXTENDS, type_index=65535"))
|
|
throw new AssertionError("Expected output missing: " + javapOut);
|
|
}
|
|
}
|
|
\ No newline at end of file
|
|
diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java
|
|
index 5d154a4fc..0ec1a790d 100644
|
|
--- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java
|
|
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java
|
|
@@ -74,14 +74,14 @@ public class BridgeShouldHaveNoInteriorAnnotationsTest
|
|
// Expected output can't be directly encoded into NestedLambdasCastedTest !!!
|
|
static class OutputExpectedOnceHolder {
|
|
public String[] outputs = {
|
|
- "0: #61(): CAST, offset=1, type_index=0, location=[TYPE_ARGUMENT(0)]",
|
|
- "1: #61(): LOCAL_VARIABLE, {start_pc=5, length=2, index=1}, location=[TYPE_ARGUMENT(0)]",
|
|
+ "0: #120(): CAST, offset=1, type_index=0, location=[TYPE_ARGUMENT(0)]",
|
|
+ "1: #120(): LOCAL_VARIABLE, {start_pc=5, length=2, index=1}, location=[TYPE_ARGUMENT(0)]",
|
|
};
|
|
}
|
|
|
|
static class OutputExpectedTwiceHolder {
|
|
public String[] outputs = {
|
|
- "0: #61(): METHOD_RETURN, location=[TYPE_ARGUMENT(0)]",
|
|
+ "0: #120(): METHOD_RETURN, location=[TYPE_ARGUMENT(0)]",
|
|
};
|
|
}
|
|
|
|
diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/NestedLambdasCastedTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/NestedLambdasCastedTest.java
|
|
index bf25b739f..94f7a6cb2 100644
|
|
--- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/NestedLambdasCastedTest.java
|
|
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/NestedLambdasCastedTest.java
|
|
@@ -53,10 +53,10 @@ public class NestedLambdasCastedTest {
|
|
"private static strictfp void lambda$main$2();",
|
|
"private static strictfp void lambda$main$1();",
|
|
"private static strictfp void lambda$main$0();",
|
|
- "0: #62(#63=s#64): CAST, offset=5, type_index=0",
|
|
- "0: #62(#63=s#69): CAST, offset=5, type_index=0",
|
|
- "0: #62(#63=s#72): CAST, offset=5, type_index=0",
|
|
- "0: #62(#63=s#75): CAST, offset=5, type_index=0"
|
|
+ "0: #111(#112=s#113): CAST, offset=5, type_index=0",
|
|
+ "0: #111(#112=s#119): CAST, offset=5, type_index=0",
|
|
+ "0: #111(#112=s#122): CAST, offset=5, type_index=0",
|
|
+ "0: #111(#112=s#125): CAST, offset=5, type_index=0"
|
|
};
|
|
}
|
|
|
|
diff --git a/test/langtools/tools/javac/api/lazy/LoadParameterNamesLazily.java b/test/langtools/tools/javac/api/lazy/LoadParameterNamesLazily.java
|
|
new file mode 100644
|
|
index 000000000..b8173fa24
|
|
--- /dev/null
|
|
+++ b/test/langtools/tools/javac/api/lazy/LoadParameterNamesLazily.java
|
|
@@ -0,0 +1,138 @@
|
|
+/*
|
|
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
|
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
+ *
|
|
+ * This code is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 only, as
|
|
+ * published by the Free Software Foundation.
|
|
+ *
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
|
+ * accompanied this code).
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License version
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
|
+ * questions.
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * @test
|
|
+ * @bug 8217047
|
|
+ * @summary Verify the parameter names can be injected using ParameterNameProvider.
|
|
+ * @library /tools/lib
|
|
+ * @modules jdk.compiler/com.sun.tools.javac.api
|
|
+ * jdk.compiler/com.sun.tools.javac.main
|
|
+ * @build toolbox.JavacTask toolbox.TestRunner toolbox.ToolBox
|
|
+ * @run main LoadParameterNamesLazily
|
|
+ */
|
|
+
|
|
+import java.io.IOException;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+
|
|
+import javax.lang.model.element.ExecutableElement;
|
|
+import javax.lang.model.element.Name;
|
|
+import javax.lang.model.element.TypeElement;
|
|
+import javax.lang.model.util.ElementFilter;
|
|
+
|
|
+import com.sun.source.util.*;
|
|
+
|
|
+import toolbox.JavacTask;
|
|
+import toolbox.Task;
|
|
+import toolbox.TestRunner;
|
|
+import toolbox.ToolBox;
|
|
+
|
|
+public class LoadParameterNamesLazily extends TestRunner {
|
|
+
|
|
+ public static void main(String... args) throws Exception {
|
|
+ LoadParameterNamesLazily t = new LoadParameterNamesLazily();
|
|
+ t.runTests();
|
|
+ }
|
|
+
|
|
+ private static final String libClass =
|
|
+ "package lib;" +
|
|
+ "/**Lib javadoc.*/" +
|
|
+ "public class Lib {" +
|
|
+ " /**Lib method javadoc.*/" +
|
|
+ " public static void m(int param, int other) {}" +
|
|
+ "}";
|
|
+ private final ToolBox tb = new ToolBox();
|
|
+
|
|
+ LoadParameterNamesLazily() throws IOException {
|
|
+ super(System.err);
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void testLoadTreesLazily() throws IOException {
|
|
+ Path libSrc = Paths.get("lib-src");
|
|
+ tb.writeJavaFiles(libSrc, libClass);
|
|
+ Path libClasses = Paths.get("lib-classes");
|
|
+ Files.createDirectories(libClasses);
|
|
+
|
|
+ new JavacTask(tb)
|
|
+ .outdir(libClasses)
|
|
+ .options()
|
|
+ .files(tb.findJavaFiles(libSrc))
|
|
+ .run(Task.Expect.SUCCESS)
|
|
+ .writeAll();
|
|
+
|
|
+ Path src = Paths.get("src");
|
|
+ tb.writeJavaFiles(src,
|
|
+ "class Use {" +
|
|
+ " lib.Lib lib;" +
|
|
+ "}");
|
|
+ Path classes = Paths.get("classes");
|
|
+ Files.createDirectories(classes);
|
|
+
|
|
+ new JavacTask(tb)
|
|
+ .outdir(classes)
|
|
+ .options("-classpath", libClasses.toString())
|
|
+ .files(tb.findJavaFiles(src))
|
|
+ .callback(task -> {
|
|
+ task.setParameterNameProvider(parameter -> {
|
|
+ ExecutableElement method = (ExecutableElement) parameter.getEnclosingElement();
|
|
+ TypeElement clazz =
|
|
+ (TypeElement) method.getEnclosingElement();
|
|
+ if (clazz.getQualifiedName().contentEquals("lib.Lib")) {
|
|
+ if (method.getParameters().indexOf(parameter) == 0) {
|
|
+ return "testName";
|
|
+ } else {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+ return null;
|
|
+ });
|
|
+ task.addTaskListener(new TaskListener() {
|
|
+ @Override
|
|
+ public void finished(TaskEvent e) {
|
|
+ if (e.getKind() == TaskEvent.Kind.ANALYZE) {
|
|
+ TypeElement lib = task.getElements().getTypeElement("lib.Lib");
|
|
+ lib.getClass(); //not null
|
|
+ ExecutableElement method =
|
|
+ ElementFilter.methodsIn(lib.getEnclosedElements()).get(0);
|
|
+ Name paramName0 = method.getParameters().get(0).getSimpleName();
|
|
+ if (!paramName0.contentEquals("testName")) {
|
|
+ throw new IllegalStateException("Unexpected parameter name: " +
|
|
+ paramName0);
|
|
+ }
|
|
+ Name paramName1 = method.getParameters().get(1).getSimpleName();
|
|
+ if (!paramName1.contentEquals("arg1")) {
|
|
+ throw new IllegalStateException("Unexpected parameter name: " +
|
|
+ paramName1);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ });
|
|
+ })
|
|
+ .run(Task.Expect.SUCCESS)
|
|
+ .writeAll();
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/test/langtools/tools/javac/diags/examples.not-yet.txt b/test/langtools/tools/javac/diags/examples.not-yet.txt
|
|
index a415219c7..f4191be1e 100644
|
|
--- a/test/langtools/tools/javac/diags/examples.not-yet.txt
|
|
+++ b/test/langtools/tools/javac/diags/examples.not-yet.txt
|
|
@@ -47,6 +47,7 @@ compiler.err.unsupported.cross.fp.lit # Scanner: host system d
|
|
compiler.misc.bad.class.signature # bad class file
|
|
compiler.misc.bad.const.pool.tag # bad class file
|
|
compiler.misc.bad.const.pool.tag.at # bad class file
|
|
+compiler.misc.bad.const.pool.index # bad class file
|
|
compiler.misc.bad.constant.range # bad class file
|
|
compiler.misc.bad.constant.value # bad class file
|
|
compiler.misc.bad.enclosing.class # bad class file
|
|
diff --git a/test/langtools/tools/javac/lambda/TestBootstrapMethodsCount.java b/test/langtools/tools/javac/lambda/TestBootstrapMethodsCount.java
|
|
index 27501dad4..a3d71d524 100644
|
|
--- a/test/langtools/tools/javac/lambda/TestBootstrapMethodsCount.java
|
|
+++ b/test/langtools/tools/javac/lambda/TestBootstrapMethodsCount.java
|
|
@@ -61,6 +61,7 @@ import com.sun.tools.javac.code.Symbol;
|
|
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
|
import com.sun.tools.javac.code.Symtab;
|
|
import com.sun.tools.javac.code.Types;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
|
|
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
|
|
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
|
import com.sun.tools.javac.tree.JCTree.JCIdent;
|
|
@@ -190,7 +191,7 @@ public class TestBootstrapMethodsCount {
|
|
Symbol oldSym = ident.sym;
|
|
if (!oldSym.isConstructor()) {
|
|
ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name,
|
|
- oldSym.owner, REF_invokeStatic, bsm, oldSym.type, new Object[0]);
|
|
+ oldSym.owner, bsm.asHandle(), oldSym.type, new LoadableConstant[0]);
|
|
}
|
|
return null;
|
|
}
|
|
diff --git a/test/langtools/tools/javac/lambda/TestInvokeDynamic.java b/test/langtools/tools/javac/lambda/TestInvokeDynamic.java
|
|
index 683900765..d8943686c 100644
|
|
--- a/test/langtools/tools/javac/lambda/TestInvokeDynamic.java
|
|
+++ b/test/langtools/tools/javac/lambda/TestInvokeDynamic.java
|
|
@@ -60,26 +60,23 @@ import com.sun.tools.classfile.Instruction;
|
|
import com.sun.tools.classfile.LineNumberTable_attribute;
|
|
import com.sun.tools.classfile.Method;
|
|
|
|
-import com.sun.tools.javac.api.JavacTaskImpl;
|
|
import com.sun.tools.javac.code.Symbol;
|
|
-import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
|
+import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
|
|
import com.sun.tools.javac.code.Symtab;
|
|
+import com.sun.tools.javac.code.Type.ClassType;
|
|
+import com.sun.tools.javac.code.Type.MethodType;
|
|
import com.sun.tools.javac.code.Types;
|
|
-import com.sun.tools.javac.jvm.Pool;
|
|
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
|
|
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
|
|
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
|
import com.sun.tools.javac.tree.JCTree.JCIdent;
|
|
-import com.sun.tools.javac.util.Context;
|
|
import com.sun.tools.javac.util.Names;
|
|
|
|
import combo.ComboParameter;
|
|
-import combo.ComboTask;
|
|
import combo.ComboTestHelper;
|
|
import combo.ComboInstance;
|
|
import combo.ComboTask.Result;
|
|
|
|
-import static com.sun.tools.javac.jvm.ClassFile.*;
|
|
-
|
|
public class TestInvokeDynamic extends ComboInstance<TestInvokeDynamic> {
|
|
|
|
enum StaticArgumentKind implements ComboParameter {
|
|
@@ -168,21 +165,24 @@ public class TestInvokeDynamic extends ComboInstance<TestInvokeDynamic> {
|
|
|
|
abstract boolean check(CPInfo cpInfo) throws Exception;
|
|
|
|
- Object getValue(Symtab syms, Names names, Types types) {
|
|
+ LoadableConstant getValue(Symtab syms) {
|
|
switch (this) {
|
|
case STRING:
|
|
+ return LoadableConstant.String((String)value);
|
|
case INTEGER:
|
|
+ return LoadableConstant.Int((Integer)value);
|
|
case LONG:
|
|
+ return LoadableConstant.Long((Long)value);
|
|
case FLOAT:
|
|
+ return LoadableConstant.Float((Float)value);
|
|
case DOUBLE:
|
|
- return value;
|
|
+ return LoadableConstant.Double((Double)value);
|
|
case CLASS:
|
|
- return syms.stringType.tsym;
|
|
+ return (ClassType)syms.stringType;
|
|
case METHOD_HANDLE:
|
|
- return new Pool.MethodHandle(REF_invokeVirtual,
|
|
- syms.arrayCloneMethod, types);
|
|
+ return syms.arrayCloneMethod.asHandle();
|
|
case METHOD_TYPE:
|
|
- return syms.arrayCloneMethod.type;
|
|
+ return ((MethodType)syms.arrayCloneMethod.type);
|
|
default:
|
|
throw new AssertionError();
|
|
}
|
|
@@ -394,7 +394,7 @@ public class TestInvokeDynamic extends ComboInstance<TestInvokeDynamic> {
|
|
|
|
class Indifier extends TreeScanner<Void, Void> implements TaskListener {
|
|
|
|
- MethodSymbol bsm;
|
|
+ MethodHandleSymbol bsm;
|
|
Symtab syms;
|
|
Names names;
|
|
Types types;
|
|
@@ -424,12 +424,12 @@ public class TestInvokeDynamic extends ComboInstance<TestInvokeDynamic> {
|
|
JCIdent ident = (JCIdent)apply.meth;
|
|
Symbol oldSym = ident.sym;
|
|
if (!oldSym.isConstructor()) {
|
|
- Object[] staticArgs = new Object[arity.arity];
|
|
+ LoadableConstant[] staticArgs = new LoadableConstant[arity.arity];
|
|
for (int i = 0; i < arity.arity ; i++) {
|
|
- staticArgs[i] = saks[i].getValue(syms, names, types);
|
|
+ staticArgs[i] = saks[i].getValue(syms);
|
|
}
|
|
ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name,
|
|
- oldSym.owner, REF_invokeStatic, bsm, oldSym.type, staticArgs);
|
|
+ oldSym.owner, bsm, oldSym.type, staticArgs);
|
|
}
|
|
return null;
|
|
}
|
|
@@ -438,7 +438,7 @@ public class TestInvokeDynamic extends ComboInstance<TestInvokeDynamic> {
|
|
public Void visitMethod(MethodTree node, Void p) {
|
|
super.visitMethod(node, p);
|
|
if (node.getName().toString().equals("bsm")) {
|
|
- bsm = ((JCMethodDecl)node).sym;
|
|
+ bsm = ((JCMethodDecl)node).sym.asHandle();
|
|
}
|
|
return null;
|
|
}
|
|
diff --git a/test/langtools/tools/javac/modules/T8159439/NPEForModuleInfoWithNonZeroSuperClassTest.out b/test/langtools/tools/javac/modules/T8159439/NPEForModuleInfoWithNonZeroSuperClassTest.out
|
|
index d5ce62bc1..ff725b7e3 100644
|
|
--- a/test/langtools/tools/javac/modules/T8159439/NPEForModuleInfoWithNonZeroSuperClassTest.out
|
|
+++ b/test/langtools/tools/javac/modules/T8159439/NPEForModuleInfoWithNonZeroSuperClassTest.out
|
|
@@ -1,2 +1,2 @@
|
|
-- compiler.err.cant.access: <error>.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.module.name.mismatch: mod/module-info, <error>))
|
|
+- compiler.err.cant.access: <error>.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.bad.const.pool.index: module-info.class, 15, 10))
|
|
1 error
|
|
diff --git a/test/langtools/tools/javac/nestmates/CheckNestmateAttrs.java b/test/langtools/tools/javac/nestmates/CheckNestmateAttrs.java
|
|
index 786ffe287..a56d294f9 100644
|
|
--- a/test/langtools/tools/javac/nestmates/CheckNestmateAttrs.java
|
|
+++ b/test/langtools/tools/javac/nestmates/CheckNestmateAttrs.java
|
|
@@ -90,8 +90,8 @@ public class CheckNestmateAttrs {
|
|
"NestHost: class CheckNestmateAttrs",
|
|
"0: aload_0",
|
|
"1: getfield #1 // Field this$1:LCheckNestmateAttrs$Inner;",
|
|
- "4: getfield #3 // Field CheckNestmateAttrs$Inner.this$0:LCheckNestmateAttrs;",
|
|
- "7: invokevirtual #4 // Method CheckNestmateAttrs.test:()V",
|
|
+ "4: getfield #13 // Field CheckNestmateAttrs$Inner.this$0:LCheckNestmateAttrs;",
|
|
+ "7: invokevirtual #19 // Method CheckNestmateAttrs.test:()V",
|
|
"10: return"
|
|
});
|
|
|
|
diff --git a/test/langtools/tools/javap/AnnoTest.java b/test/langtools/tools/javap/AnnoTest.java
|
|
index 4ed952122..7d78d163e 100644
|
|
--- a/test/langtools/tools/javap/AnnoTest.java
|
|
+++ b/test/langtools/tools/javap/AnnoTest.java
|
|
@@ -49,50 +49,50 @@ public class AnnoTest {
|
|
|
|
expect(out,
|
|
"RuntimeVisibleAnnotations:\n" +
|
|
- " 0: #18(#19=B#20)\n" +
|
|
+ " 0: #21(#22=B#23)\n" +
|
|
" AnnoTest$ByteAnno(\n" +
|
|
" value=(byte) 42\n" +
|
|
" )\n" +
|
|
- " 1: #23(#19=S#24)\n" +
|
|
+ " 1: #24(#22=S#25)\n" +
|
|
" AnnoTest$ShortAnno(\n" +
|
|
" value=(short) 3\n" +
|
|
" )");
|
|
expect(out,
|
|
"RuntimeInvisibleAnnotations:\n" +
|
|
- " 0: #28(#19=[J#29,J#31,J#33,J#35,J#37])\n" +
|
|
+ " 0: #27(#22=[J#28,J#30,J#32,J#34,J#36])\n" +
|
|
" AnnoTest$ArrayAnno(\n" +
|
|
" value=[1l,2l,3l,4l,5l]\n" +
|
|
" )\n" +
|
|
- " 1: #41(#19=Z#42)\n" +
|
|
+ " 1: #38(#22=Z#39)\n" +
|
|
" AnnoTest$BooleanAnno(\n" +
|
|
" value=false\n" +
|
|
" )\n" +
|
|
- " 2: #45(#46=c#47)\n" +
|
|
+ " 2: #40(#41=c#42)\n" +
|
|
" AnnoTest$ClassAnno(\n" +
|
|
" type=class Ljava/lang/Object;\n" +
|
|
" )\n" +
|
|
- " 3: #50(#51=e#52.#53)\n" +
|
|
+ " 3: #43(#44=e#45.#46)\n" +
|
|
" AnnoTest$EnumAnno(\n" +
|
|
" kind=Ljavax/lang/model/element/ElementKind;.PACKAGE\n" +
|
|
" )\n" +
|
|
- " 4: #56(#19=I#57)\n" +
|
|
+ " 4: #47(#22=I#48)\n" +
|
|
" AnnoTest$IntAnno(\n" +
|
|
" value=2\n" +
|
|
" )\n" +
|
|
- " 5: #60()\n" +
|
|
+ " 5: #49()\n" +
|
|
" AnnoTest$IntDefaultAnno\n" +
|
|
- " 6: #63(#64=s#65)\n" +
|
|
+ " 6: #50(#51=s#52)\n" +
|
|
" AnnoTest$NameAnno(\n" +
|
|
" name=\"NAME\"\n" +
|
|
" )\n" +
|
|
- " 7: #68(#69=D#70,#72=F#73)\n" +
|
|
+ " 7: #53(#54=D#55,#57=F#58)\n" +
|
|
" AnnoTest$MultiAnno(\n" +
|
|
" d=3.14159d\n" +
|
|
" f=2.71828f\n" +
|
|
" )\n" +
|
|
- " 8: #76()\n" +
|
|
+ " 8: #59()\n" +
|
|
" AnnoTest$SimpleAnno\n" +
|
|
- " 9: #79(#19=@#56(#19=I#80))\n" +
|
|
+ " 9: #60(#22=@#47(#22=I#61))\n" +
|
|
" AnnoTest$AnnoAnno(\n" +
|
|
" value=@AnnoTest$IntAnno(\n" +
|
|
" value=5\n" +
|
|
@@ -100,7 +100,7 @@ public class AnnoTest {
|
|
" )");
|
|
expect(out,
|
|
"RuntimeInvisibleTypeAnnotations:\n" +
|
|
- " 0: #84(): CLASS_EXTENDS, type_index=0\n" +
|
|
+ " 0: #63(): CLASS_EXTENDS, type_index=0\n" +
|
|
" AnnoTest$TypeAnno");
|
|
|
|
if (errors > 0)
|
|
diff --git a/test/langtools/tools/javap/typeAnnotations/AnnotationDefaultNewlineTest.java b/test/langtools/tools/javap/typeAnnotations/AnnotationDefaultNewlineTest.java
|
|
index 68fccab87..c7cecec12 100644
|
|
--- a/test/langtools/tools/javap/typeAnnotations/AnnotationDefaultNewlineTest.java
|
|
+++ b/test/langtools/tools/javap/typeAnnotations/AnnotationDefaultNewlineTest.java
|
|
@@ -51,7 +51,7 @@ public class AnnotationDefaultNewlineTest {
|
|
|
|
private static final String ExpectedSubstring =
|
|
" AnnotationDefault:\n" +
|
|
- " default_value: I#7\n";
|
|
+ " default_value: I#9\n";
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
ToolBox tb = new ToolBox();
|
|
diff --git a/test/langtools/tools/javap/typeAnnotations/InvisibleParameterAnnotationsTest.java b/test/langtools/tools/javap/typeAnnotations/InvisibleParameterAnnotationsTest.java
|
|
index 284144cca..06ecf1dc0 100644
|
|
--- a/test/langtools/tools/javap/typeAnnotations/InvisibleParameterAnnotationsTest.java
|
|
+++ b/test/langtools/tools/javap/typeAnnotations/InvisibleParameterAnnotationsTest.java
|
|
@@ -62,11 +62,11 @@ public class InvisibleParameterAnnotationsTest {
|
|
" RuntimeVisibleParameterAnnotations:\n" +
|
|
" parameter 0:\n" +
|
|
" parameter 1:\n" +
|
|
- " 0: #16()\n" +
|
|
+ " 0: #14()\n" +
|
|
" Sample$VisAnno\n" +
|
|
" RuntimeInvisibleParameterAnnotations:\n" +
|
|
" parameter 0:\n" +
|
|
- " 0: #18()\n" +
|
|
+ " 0: #16()\n" +
|
|
" Sample$InvisAnno\n" +
|
|
" parameter 1:";
|
|
|