diff --git a/8205921-Optimizing-best_of_2-work-stealing-queue-selection.patch b/8205921-Optimizing-best_of_2-work-stealing-queue-selection.patch index 9035b81ded2d705234ebbaeeed67e83ad0415594..e608dec3d89481239927dc2e2c0ebb817dbf785e 100644 --- a/8205921-Optimizing-best_of_2-work-stealing-queue-selection.patch +++ b/8205921-Optimizing-best_of_2-work-stealing-queue-selection.patch @@ -84,7 +84,7 @@ index 5fc5ee8..708e92c 100644 }; @@ -5127,8 +5122,7 @@ void CMSRefProcTaskProxy::work(uint worker_id) { CMSIsAliveClosure is_alive_closure(_span, _mark_bit_map); - _task.work(worker_id, is_alive_closure, par_keep_alive, par_drain_stack); + _task.work(worker_id, is_alive_closure, par_keep_alive, enqueue, par_drain_stack); if (_task.marks_oops_alive()) { - do_work_steal(worker_id, &par_drain_stack, &par_keep_alive, - _collector->hash_seed(worker_id)); diff --git a/8222289-Overhaul-logic-for-reading-writing-constant-pool-entries.patch b/8222289-Overhaul-logic-for-reading-writing-constant-pool-entries.patch new file mode 100644 index 0000000000000000000000000000000000000000..8e32178d5a6ed22ed79643ff7725545c967a0a21 --- /dev/null +++ b/8222289-Overhaul-logic-for-reading-writing-constant-pool-entries.patch @@ -0,0 +1,5926 @@ +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 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}. ++ * ++ *

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. ++ */ ++public class MissingInfoHandler { ++ protected static final Context.Key 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. + */ +-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 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 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()); ++ } ++ } + // + + 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 dedupedLambdas; + +- private Map dynMethSyms = new HashMap<>(); ++ private Map 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 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 staticArgs, MethodType indyType) { ++ private void addDeserializationCase(MethodHandleSymbol refSym, Type targetType, MethodSymbol samSym, ++ DiagnosticPosition pos, List 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 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 indy_args) { ++ MethodHandleSymbol refSym, List indy_args) { + JCFunctionalExpression tree = context.tree; + //determine the static bsm args + MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.target.tsym); +- List staticArgs = List.of( ++ List 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 markers = new ListBuffer<>(); ++ ListBuffer markers = new ListBuffer<>(); + List 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 staticArgs, MethodType indyType, List indyArgs, +- Name methName) { ++ List staticArgs, MethodType indyType, List indyArgs, ++ Name methName) { + int prevPos = make.pos; + try { + make.at(pos); + List 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 bsmStaticArgToTypes(List args) { +- ListBuffer 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; +- } +- } +- } + + // + /** +@@ -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 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 readModuleFlags(int flags) { +@@ -767,7 +493,7 @@ public class ClassReader { + List argtypes = sigToTypes(')'); + Type restype = sigToType(); + List 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/Outer$Inner; +@@ -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 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 is = new ListBuffer<>(); + while (sigp != siglimit) is.append(sigToType()); +@@ -1226,7 +953,7 @@ public class ClassReader { + } + } else { + List 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 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 = readModuleFlags(nextChar()); + msym.flags.addAll(moduleFlags); +- msym.version = readName(nextChar()); ++ msym.version = optPoolEntry(nextChar(), poolReader::getName, null); + + ListBuffer 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 flags = readRequiresFlags(nextChar()); + if (rsym == syms.java_base && majorVersion >= V54.major) { + if (flags.contains(RequiresFlag.TRANSITIVE)) { +@@ -1378,8 +1105,7 @@ public class ClassReader { + ListBuffer 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 flags = readExportsFlags(nextChar()); + int nto = nextChar(); + List to; +@@ -1388,7 +1114,7 @@ public class ClassReader { + } else { + ListBuffer 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 flags = readOpensFlags(nextChar()); + int nto = nextChar(); + List to; +@@ -1411,7 +1136,7 @@ public class ClassReader { + } else { + ListBuffer 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 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 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 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> pairs = new ListBuffer<>(); + for (int i=0; i(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 optPoolEntry(int index, IntFunction 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 paramNames = List.nil(); ++ Set paramNames = new HashSet<>(); + ListBuffer 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 exclude) { ++ private VarSymbol parameter(int index, Type t, MethodSymbol owner, Set 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 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 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 innerClasses; +- +- /** The inner classes to be written, as a queue where +- * enclosing classes come first. +- */ +- ListBuffer innerClassesQueue; +- +- /** The bootstrap methods to be written in the corresponding class attribute +- * (one for each invokedynamic) +- */ +- Map 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 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 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 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 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 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 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 nested = new ListBuffer<>(); ++ ListBuffer nested = new ListBuffer<>(); + listNested(csym, nested); +- Set nestedUnique = new LinkedHashSet<>(nested); ++ Set 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 seen) { ++ private void listNested(Symbol sym, ListBuffer 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 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 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 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 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 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

void emitop2(int op, P constant, ToIntBiFunction 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 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 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 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 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. +- * +- *

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. +- */ +-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 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 { +- 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 { +- 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 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 nonInitFilter = n -> (n != n.table.names.init && n != n.table.names.clinit); +- +- Filter 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. ++ * ++ *

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. ++ */ ++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 peekClassName(int index, NameMapper mapper) { ++ return peekName(buf.getChar(pool.offset(index)), mapper); ++ } ++ ++ /** ++ * Get package name without resolving ++ */ ++ Z peekPackageName(int index, NameMapper mapper) { ++ return peekName(buf.getChar(pool.offset(index)), mapper); ++ } ++ ++ /** ++ * Get module name without resolving ++ */ ++ Z peekModuleName(int index, NameMapper 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 peekName(int index, Name.NameMapper 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 getUtf8(int index, NameMapper 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 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. ++ * ++ *

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. ++ */ ++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 innerClasses = new LinkedHashSet<>(); ++ ++ /** The list of entries in the BootstrapMethods attribute. */ ++ Map 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 keysToPos = new HashMap<>(64); ++ ++ final ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE); ++ ++ int currentIndex = 1; ++ ++ ArrayDeque todo = new ArrayDeque<>(); ++ ++ String overflowString = null; ++ ++ private

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 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 dynamicArgs = new ListBuffer<>(); +- ListBuffer staticArgs = new ListBuffer<>(); ++ ListBuffer 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 staticArgs, List dynamicArgTypes) { ++ private void doCall(Type type, JCDiagnostic.DiagnosticPosition pos, String recipe, List staticArgs, List dynamicArgTypes) { + Type.MethodType indyType = new Type.MethodType(dynamicArgTypes, + type, + List.nil(), +@@ -474,8 +475,8 @@ public abstract class StringConcat { + make.at(pos); + + ListBuffer constTypes = new ListBuffer<>(); +- ListBuffer constants = new ListBuffer<>(); +- for (Object t : staticArgs) { ++ ListBuffer 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.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. + */ +-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 map(byte[] bytes, int offset, int len); ++ } ++ ++ public X map(NameMapper 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 { + + enum StaticArgumentKind implements ComboParameter { +@@ -168,21 +165,24 @@ public class TestInvokeDynamic extends ComboInstance { + + 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 { + + class Indifier extends TreeScanner implements TaskListener { + +- MethodSymbol bsm; ++ MethodHandleSymbol bsm; + Symtab syms; + Names names; + Types types; +@@ -424,12 +424,12 @@ public class TestInvokeDynamic extends ComboInstance { + 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 { + 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: .module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.module.name.mismatch: mod/module-info, )) ++- compiler.err.cant.access: .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:"; + diff --git a/8224675-Late-GC-barrier-insertion-for-ZGC.patch b/8224675-Late-GC-barrier-insertion-for-ZGC.patch index ed66cbbe156f311c6332f3b7ce24763aeac7469d..95dc4c9534025966ef3685ce9256373b8bcb7e46 100644 --- a/8224675-Late-GC-barrier-insertion-for-ZGC.patch +++ b/8224675-Late-GC-barrier-insertion-for-ZGC.patch @@ -2764,9 +2764,9 @@ index 2f4b9faf0..10dd02f9f 100644 static int _file_count; networkStream *_stream; xmlStream *_xml; -@@ -97,10 +93,6 @@ class IdealGraphPrinter : public CHeapObj { - bool _traverse_outs; +@@ -98,10 +94,6 @@ class IdealGraphPrinter : public CHeapObj { Compile *C; + double _max_freq; - static void pre_node(Node* node, void *env); - static void post_node(Node* node, void *env); diff --git a/8225648-TESTBUG-java-lang-annotation-loaderLeak-Main.patch b/8225648-TESTBUG-java-lang-annotation-loaderLeak-Main.patch deleted file mode 100644 index 7645eaec0d8a17d4941f6c6132fb4652e0b6e7e5..0000000000000000000000000000000000000000 --- a/8225648-TESTBUG-java-lang-annotation-loaderLeak-Main.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 96ac09c507a663b853235c29a607aca2c1edfc10 Mon Sep 17 00:00:00 2001 -Date: Mon, 2 Dec 2019 17:42:17 +0000 -Subject: [PATCH] 8225648: [TESTBUG]java/lang/annotation/loaderLeak/Main.java - fails with -Xcomp - -Summary: : annotations cause memory leak -LLT: NA -Bug url: https://bugs.openjdk.java.net/browse/JDK-8225648 ---- - test/jdk/java/lang/annotation/loaderLeak/Main.java | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/test/jdk/java/lang/annotation/loaderLeak/Main.java b/test/jdk/java/lang/annotation/loaderLeak/Main.java -index 58bd63b..aedbc2e 100644 ---- a/test/jdk/java/lang/annotation/loaderLeak/Main.java -+++ b/test/jdk/java/lang/annotation/loaderLeak/Main.java -@@ -54,6 +54,7 @@ public class Main { - System.gc(); - System.gc(); - if (c.get() == null) throw new AssertionError(); -+ Reference.reachabilityFence(loader); - System.gc(); - System.gc(); - loader = null; --- -2.12.3 - diff --git a/8231441-2-AArch64-Initial-SVE-backend-support.patch b/8231441-2-AArch64-Initial-SVE-backend-support.patch index 4dfb8d605b67e77d636814485318181542b16b14..c7756c99dc9238e14bbf4c64e73aa3d1fb2d78f6 100755 --- a/8231441-2-AArch64-Initial-SVE-backend-support.patch +++ b/8231441-2-AArch64-Initial-SVE-backend-support.patch @@ -24,17 +24,17 @@ index b64919a62..64985e498 100644 reg_def R11 ( SOC, SOC, Op_RegI, 11, r11->as_VMReg() ); @@ -140,7 +144,7 @@ reg_def R31 ( NS, NS, Op_RegI, 31, r31_sp->as_VMReg() ); // sp reg_def R31_H ( NS, NS, Op_RegI, 31, r31_sp->as_VMReg()->next()); - + // ---------------------------- -// Float/Double Registers +// Float/Double/Vector Registers // ---------------------------- - + // Double Registers @@ -161,165 +165,317 @@ reg_def R31_H ( NS, NS, Op_RegI, 31, r31_sp->as_VMReg()->next()); // the platform ABI treats v8-v15 as callee save). float registers // v16-v31 are SOC as per the platform spec - + - reg_def V0 ( SOC, SOC, Op_RegF, 0, v0->as_VMReg() ); - reg_def V0_H ( SOC, SOC, Op_RegF, 0, v0->as_VMReg()->next() ); - reg_def V0_J ( SOC, SOC, Op_RegF, 0, v0->as_VMReg()->next(2) ); @@ -505,7 +505,7 @@ index b64919a62..64985e498 100644 +reg_def P6 (SOC, SOC, Op_RegVMask, 6, p6->as_VMReg()); +reg_def P7 (SOC, SOC, Op_RegVMask, 7, p7->as_VMReg()); + - + // ---------------------------- // Special Registers @@ -381,50 +536,64 @@ alloc_class chunk0( @@ -515,9 +515,9 @@ index b64919a62..64985e498 100644 + R8, R8_H, // rscratch1 + R9, R9_H, // rscratch2 ); - + alloc_class chunk1( - + // no save - V16, V16_H, V16_J, V16_K, - V17, V17_H, V17_J, V17_K, @@ -551,7 +551,7 @@ index b64919a62..64985e498 100644 + V29, V29_H, V29_J, V29_K, V29_L, V29_M, V29_N, V29_O, + V30, V30_H, V30_J, V30_K, V30_L, V30_M, V30_N, V30_O, + V31, V31_H, V31_J, V31_K, V31_L, V31_M, V31_N, V31_O, - + // arg registers - V0, V0_H, V0_J, V0_K, - V1, V1_H, V1_J, V1_K, @@ -569,7 +569,7 @@ index b64919a62..64985e498 100644 + V5, V5_H, V5_J, V5_K, V5_L, V5_M, V5_N, V5_O, + V6, V6_H, V6_J, V6_K, V6_L, V6_M, V6_N, V6_O, + V7, V7_H, V7_J, V7_K, V7_L, V7_M, V7_N, V7_O, - + // non-volatiles - V8, V8_H, V8_J, V8_K, - V9, V9_H, V9_J, V9_K, @@ -600,16 +600,16 @@ index b64919a62..64985e498 100644 + P7, + // Only use P0~P7 here for performance ); - + -alloc_class chunk2(RFLAGS); +alloc_class chunk3(RFLAGS); - + //----------Architecture Description Register Classes-------------------------- // Several register classes are automatically defined based upon information in @@ -865,6 +1034,42 @@ reg_class double_reg( V31, V31_H ); - + +// Class for all SVE vector registers. +reg_class vectora_reg ( + V0, V0_H, V0_J, V0_K, V0_L, V0_M, V0_N, V0_O, @@ -652,7 +652,7 @@ index b64919a62..64985e498 100644 @@ -1097,6 +1302,31 @@ reg_class v31_reg( V31, V31_H ); - + +// Class for all SVE predicate registers. +reg_class pr_reg ( + P0, @@ -680,30 +680,30 @@ index b64919a62..64985e498 100644 + // Singleton class for condition codes reg_class int_flags(RFLAGS); - + @@ -1862,7 +2092,7 @@ int MachEpilogNode::safepoint_offset() const { - + // Figure out which register class each belongs in: rc_int, rc_float or // rc_stack. -enum RC { rc_bad, rc_int, rc_float, rc_stack }; +enum RC { rc_bad, rc_int, rc_float, rc_predicate, rc_stack }; - + static enum RC rc_class(OptoReg::Name reg) { - + @@ -1870,20 +2100,25 @@ static enum RC rc_class(OptoReg::Name reg) { return rc_bad; } - + - // we have 30 int registers * 2 halves - // (rscratch1 and rscratch2 are omitted) - int slots_of_int_registers = RegisterImpl::max_slots_per_register * (RegisterImpl::number_of_registers - 2); + // we have 32 int registers * 2 halves + int slots_of_int_registers = RegisterImpl::max_slots_per_register * RegisterImpl::number_of_registers; - + if (reg < slots_of_int_registers) { return rc_int; } - + - // we have 32 float register * 4 halves - if (reg < slots_of_int_registers + FloatRegisterImpl::max_slots_per_register * FloatRegisterImpl::number_of_registers) { + // we have 32 float register * 8 halves @@ -711,7 +711,7 @@ index b64919a62..64985e498 100644 + if (reg < slots_of_int_registers + slots_of_float_registers) { return rc_float; } - + - // Between float regs & stack is the flags regs. + int slots_of_predicate_registers = PRegisterImpl::max_slots_per_register * PRegisterImpl::number_of_registers; + if (reg < slots_of_int_registers + slots_of_float_registers + slots_of_predicate_registers) { @@ -720,7 +720,7 @@ index b64919a62..64985e498 100644 + + // Between predicate regs & stack is the flags. assert(OptoReg::is_stack(reg), "blow up if spilling flags"); - + return rc_stack; @@ -1941,12 +2176,12 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo as_FloatRegister(Matcher::_regEncode[src_lo])); @@ -765,18 +765,18 @@ index b64919a62..64985e498 100644 + st->print("\t# spill size = %d", is64 ? 64 : 32); } } - + @@ -2204,7 +2454,7 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen) { } - + const bool Matcher::has_predicated_vectors(void) { - return false; + return UseSVE > 0; } - + const int Matcher::float_pressure(int default_pressure_threshold) { @@ -2240,7 +2490,8 @@ const bool Matcher::convL2FSupported(void) { - + // Vector width in bytes. const int Matcher::vector_width_in_bytes(BasicType bt) { - int size = MIN2(16,(int)MaxVectorSize); @@ -795,7 +795,7 @@ index b64919a62..64985e498 100644 + // Currently vector length less than SVE vector register size is not supported. + return max_size; + } else { -+ // For the moment limit the vector size to 8 bytes with NEON. ++ // For the moment limit the vector size to 8 bytes with NEON. int size = 8 / type2aelembytes(bt); if (size < 2) size = 2; return size; @@ -810,7 +810,7 @@ index b64919a62..64985e498 100644 +const int Matcher::scalable_vector_reg_size(const BasicType bt) { + return Matcher::max_vector_size(bt); } - + // Vector ideal reg. const uint Matcher::vector_ideal_reg(int len) { + if (UseSVE > 0 && 16 <= len && len <= 256) { @@ -821,7 +821,7 @@ index b64919a62..64985e498 100644 case 16: return Op_VecX; @@ -2270,6 +2539,9 @@ const uint Matcher::vector_ideal_reg(int len) { } - + const uint Matcher::vector_shift_count_ideal_reg(int size) { + if (UseSVE > 0 && 16 <= size && size <= 256) { + return Op_VecA; @@ -832,7 +832,7 @@ index b64919a62..64985e498 100644 @@ -4851,6 +5123,18 @@ operand vRegD() interface(REG_INTER); %} - + +// Generic vector class. This will be used for +// all vector operands, including NEON and SVE, +// but currently only used for SVE VecA. @@ -851,7 +851,7 @@ index b64919a62..64985e498 100644 @@ -5159,6 +5443,15 @@ operand vRegD_V31() interface(REG_INTER); %} - + +operand pRegGov() +%{ + constraint(ALLOC_IN_RC(gov_pr)); @@ -862,7 +862,7 @@ index b64919a62..64985e498 100644 +%} + // Flags register, used as output of signed compare instructions - + // note that on AArch64 we also use this register as the output for diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index 228b82660..6f4e75ff4 100644 @@ -871,7 +871,7 @@ index 228b82660..6f4e75ff4 100644 @@ -273,6 +273,14 @@ public: f(r->encoding_nocheck(), lsb + 4, lsb); } - + + void prf(PRegister r, int lsb) { + f(r->encoding_nocheck(), lsb + 3, lsb); + } @@ -912,7 +912,7 @@ index 36cbe3fee..3db8e8337 100644 @@ -33,6 +33,9 @@ const int ConcreteRegisterImpl::max_fpr = ConcreteRegisterImpl::max_gpr + FloatRegisterImpl::number_of_registers * FloatRegisterImpl::max_slots_per_register; - + +const int ConcreteRegisterImpl::max_pr + = ConcreteRegisterImpl::max_fpr + PRegisterImpl::number_of_registers; + @@ -945,12 +945,12 @@ index 20f549188..e7a9cee92 100644 + slots_per_neon_register = 4, + extra_save_slots_per_neon_register = slots_per_neon_register - save_slots_per_register }; - + // construction @@ -198,6 +199,79 @@ CONSTANT_REGISTER_DECLARATION(FloatRegister, v29 , (29)); CONSTANT_REGISTER_DECLARATION(FloatRegister, v30 , (30)); CONSTANT_REGISTER_DECLARATION(FloatRegister, v31 , (31)); - + +// SVE vector registers, shared with the SIMD&FP v0-v31. Vn maps to Zn[127:0]. +CONSTANT_REGISTER_DECLARATION(FloatRegister, z0 , ( 0)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, z1 , ( 1)); @@ -1028,19 +1028,19 @@ index 20f549188..e7a9cee92 100644 // Define a class that exports it. class ConcreteRegisterImpl : public AbstractRegisterImpl { @@ -210,12 +284,14 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl { - + number_of_registers = (RegisterImpl::max_slots_per_register * RegisterImpl::number_of_registers + FloatRegisterImpl::max_slots_per_register * FloatRegisterImpl::number_of_registers + + PRegisterImpl::max_slots_per_register * PRegisterImpl::number_of_registers + 1) // flags }; - + // added to make it compile static const int max_gpr; static const int max_fpr; + static const int max_pr; }; - + class RegSetIterator; diff --git a/src/hotspot/cpu/aarch64/register_definitions_aarch64.cpp b/src/hotspot/cpu/aarch64/register_definitions_aarch64.cpp index c18109087..15131ed32 100644 @@ -1055,7 +1055,7 @@ index c18109087..15131ed32 100644 * @@ -154,3 +154,45 @@ REGISTER_DEFINITION(Register, rthread); REGISTER_DEFINITION(Register, rheapbase); - + REGISTER_DEFINITION(Register, r31_sp); + +REGISTER_DEFINITION(FloatRegister, z0); @@ -1105,7 +1105,7 @@ index dbad48582..3bf7284a7 100644 +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -111,11 +111,28 @@ class RegisterSaver { }; - + OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) { + bool use_sve = false; + int sve_vector_size_in_bytes = 0; @@ -1135,7 +1135,7 @@ index dbad48582..3bf7284a7 100644 } #else @@ -158,8 +175,13 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ - + for (int i = 0; i < FloatRegisterImpl::number_of_registers; i++) { FloatRegister r = as_FloatRegister(i); - int sp_offset = save_vectors ? (FloatRegisterImpl::max_slots_per_register * i) : @@ -1166,7 +1166,7 @@ index c5d4383b4..dde7a7a91 100644 @@ -36,4 +36,8 @@ inline VMReg FloatRegisterImpl::as_VMReg() { ConcreteRegisterImpl::max_gpr); } - + +inline VMReg PRegisterImpl::as_VMReg() { + return VMRegImpl::as_VMReg(encoding() + ConcreteRegisterImpl::max_fpr); +} @@ -1179,7 +1179,7 @@ index 4a32af54e..0ef4d7f3e 100644 @@ -1121,6 +1121,14 @@ const int Matcher::vector_width_in_bytes(BasicType bt) { return MaxVectorSize; } - + +const bool Matcher::supports_scalable_vector() { + return false; +} @@ -1198,7 +1198,7 @@ index 36cbada53..7ee16a975 100644 @@ -2310,6 +2310,14 @@ const int Matcher::min_vector_size(const BasicType bt) { return max_vector_size(bt); // Same as max. } - + +const bool Matcher::supports_scalable_vector() { + return false; +} @@ -1217,7 +1217,7 @@ index 96c231b0a..ea09aaafc 100644 @@ -1573,6 +1573,14 @@ const int Matcher::min_vector_size(const BasicType bt) { return max_vector_size(bt); // Same as max. } - + +const bool Matcher::supports_scalable_vector() { + return false; +} @@ -1243,7 +1243,7 @@ index abdd7483d..76dd6addd 100644 @@ -1485,6 +1485,14 @@ const int Matcher::min_vector_size(const BasicType bt) { return MIN2(size,max_size); } - + +const bool Matcher::supports_scalable_vector() { + return false; +} @@ -1290,7 +1290,7 @@ index ba61aa4c0..9e41b2dc6 100644 @@ -939,6 +940,10 @@ const char *ArchDesc::getIdealType(const char *idealOp) { } } - + + if (strncmp(idealOp, "RegVMask", 8) == 0) { + return "Type::BOTTOM"; + } @@ -1360,7 +1360,7 @@ index 914dc43f6..710af9de8 100644 + } assert(n_type->isa_vect() == NULL || lrg._is_vector || ireg == Op_RegD || ireg == Op_RegL, "vector must be in vector registers"); - + @@ -912,6 +932,13 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { lrg.set_reg_pressure(1); #endif @@ -1378,7 +1378,7 @@ index 914dc43f6..710af9de8 100644 @@ -1358,6 +1385,46 @@ static bool is_legal_reg(LRG &lrg, OptoReg::Name reg, int chunk) { return false; } - + +static OptoReg::Name find_first_set(LRG &lrg, RegMask mask, int chunk) { + int num_regs = lrg.num_regs(); + OptoReg::Name assigned = mask.find_first_set(lrg, num_regs); @@ -1421,7 +1421,7 @@ index 914dc43f6..710af9de8 100644 + // Choose a color using the biasing heuristic OptoReg::Name PhaseChaitin::bias_color( LRG &lrg, int chunk ) { - + @@ -1391,7 +1458,7 @@ OptoReg::Name PhaseChaitin::bias_color( LRG &lrg, int chunk ) { RegMask tempmask = lrg.mask(); tempmask.AND(lrgs(copy_lrg).mask()); @@ -1438,12 +1438,12 @@ index 914dc43f6..710af9de8 100644 - return OptoReg::add(lrg.mask().find_first_set(lrg.num_regs()),chunk); + return OptoReg::add(find_first_set(lrg, lrg.mask(), chunk), chunk); } - + // CNC - Fun hack. Alternate 1st and 2nd selection. Enables post-allocate @@ -1455,7 +1522,6 @@ uint PhaseChaitin::Select( ) { LRG *lrg = &lrgs(lidx); _simplified = lrg->_next; - + - #ifndef PRODUCT if (trace_spilling()) { @@ -1455,7 +1455,7 @@ index 914dc43f6..710af9de8 100644 - goto retry_next_chunk; } - + @@ -1564,12 +1629,21 @@ uint PhaseChaitin::Select( ) { int n_regs = lrg->num_regs(); assert(!lrg->_is_vector || !lrg->_fat_proj, "sanity"); @@ -1505,7 +1505,7 @@ index e5be5b966..5408a24ef 100644 @@ -139,14 +141,37 @@ public: void clear_to_pairs() { _mask.clear_to_pairs(); debug_only(_msize_valid=0;) } void clear_to_sets() { _mask.clear_to_sets(_num_regs); debug_only(_msize_valid=0;) } - + - // Number of registers this live range uses when it colors private: + // Number of registers this live range uses when it colors @@ -1520,7 +1520,7 @@ index e5be5b966..5408a24ef 100644 public: int num_regs() const { return _num_regs; } void set_num_regs( int reg ) { assert( _num_regs == reg || !_num_regs, "" ); _num_regs = reg; } - + + uint scalable_reg_slots() { return _scalable_reg_slots; } + void set_scalable_reg_slots(uint slots) { + assert(_is_scalable, "scalable register"); @@ -1581,7 +1581,7 @@ index 4cc7580a8..4fb732161 100644 @@ -417,6 +420,8 @@ static RegMask *init_input_masks( uint size, RegMask &ret_adr, RegMask &fp ) { return rms; } - + +#define NOF_STACK_MASKS (3*6+6) + //---------------------------init_first_stack_mask----------------------------- @@ -1589,7 +1589,7 @@ index 4cc7580a8..4fb732161 100644 // Disallow any debug info in outgoing argument areas by setting the @@ -424,7 +429,12 @@ static RegMask *init_input_masks( uint size, RegMask &ret_adr, RegMask &fp ) { void Matcher::init_first_stack_mask() { - + // Allocate storage for spill masks as masks for the appropriate load type. - RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask) * (3*6+5)); + RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask) * NOF_STACK_MASKS); @@ -1598,13 +1598,13 @@ index 4cc7580a8..4fb732161 100644 + for (int i = 0; i < NOF_STACK_MASKS; i++) { + new (rms + i) RegMask(); + } - + idealreg2spillmask [Op_RegN] = &rms[0]; idealreg2spillmask [Op_RegI] = &rms[1]; @@ -447,11 +457,12 @@ void Matcher::init_first_stack_mask() { idealreg2mhdebugmask[Op_RegD] = &rms[16]; idealreg2mhdebugmask[Op_RegP] = &rms[17]; - + - idealreg2spillmask [Op_VecS] = &rms[18]; - idealreg2spillmask [Op_VecD] = &rms[19]; - idealreg2spillmask [Op_VecX] = &rms[20]; @@ -1616,15 +1616,15 @@ index 4cc7580a8..4fb732161 100644 + idealreg2spillmask [Op_VecX] = &rms[21]; + idealreg2spillmask [Op_VecY] = &rms[22]; + idealreg2spillmask [Op_VecZ] = &rms[23]; - + OptoReg::Name i; - + @@ -478,6 +489,7 @@ void Matcher::init_first_stack_mask() { // Keep spill masks aligned. aligned_stack_mask.clear_to_pairs(); assert(aligned_stack_mask.is_AllStack(), "should be infinite stack"); + RegMask scalable_stack_mask = aligned_stack_mask; - + *idealreg2spillmask[Op_RegP] = *idealreg2regmask[Op_RegP]; #ifdef _LP64 @@ -548,28 +560,48 @@ void Matcher::init_first_stack_mask() { @@ -1690,12 +1690,12 @@ index 4cc7580a8..4fb732161 100644 #endif - } + } - + // Make up debug masks. Any spill slot plus callee-save registers. // Caller-save registers are assumed to be trashable by the various @@ -872,6 +904,10 @@ void Matcher::init_spill_mask( Node *ret ) { idealreg2regmask[Op_RegP] = &spillP->out_RegMask(); - + // Vector regmasks. + if (Matcher::supports_scalable_vector()) { + MachNode *spillVectA = match_tree(new LoadVectorNode(NULL,mem,fp,atp,TypeVect::VECTA)); @@ -1707,11 +1707,11 @@ index 4cc7580a8..4fb732161 100644 @@ -1575,7 +1611,6 @@ Node* Matcher::Label_Root(const Node* n, State* svec, Node* control, Node*& mem) } } - + - // Call DFA to match this node, and return svec->DFA( n->Opcode(), n ); - + diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index 244e3d1f8..ed890f88e 100644 --- a/src/hotspot/share/opto/matcher.hpp @@ -1719,7 +1719,7 @@ index 244e3d1f8..ed890f88e 100644 @@ -333,6 +333,10 @@ public: Matcher::min_vector_size(bt) <= size); } - + + static const bool supports_scalable_vector(); + // Actual max scalable vector register length. + static const int scalable_vector_reg_size(const BasicType bt); @@ -1793,17 +1793,17 @@ index d572ac9fe..3514b37bc 100644 @@ -266,9 +266,9 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v Node *val = skip_copies(n->in(k)); if (val == x) return blk_adjust; // No progress? - + - int n_regs = RegMask::num_registers(val->ideal_reg()); uint val_idx = _lrg_map.live_range_id(val); OptoReg::Name val_reg = lrgs(val_idx).reg(); + int n_regs = RegMask::num_registers(val->ideal_reg(), lrgs(val_idx)); - + // See if it happens to already be in the correct register! // (either Phi's direct register, or the common case of the name @@ -305,8 +305,26 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v } - + Node *vv = value[reg]; + // For scalable register, number of registers may be inconsistent between + // "val_reg" and "reg". For example, when "val" resides in register @@ -1835,7 +1835,7 @@ index d572ac9fe..3514b37bc 100644 uint pidx = _lrg_map.live_range_id(phi); - OptoReg::Name preg = lrgs(_lrg_map.live_range_id(phi)).reg(); + OptoReg::Name preg = lrgs(pidx).reg(); - + // Remove copies remaining on edges. Check for junk phi. Node *u = NULL; @@ -619,7 +637,7 @@ void PhaseChaitin::post_allocate_copy_removal() { @@ -1858,7 +1858,7 @@ index d572ac9fe..3514b37bc 100644 if (!value[ureg_lo] && @@ -707,7 +725,7 @@ void PhaseChaitin::post_allocate_copy_removal() { } - + uint n_ideal_reg = n->ideal_reg(); - int n_regs = RegMask::num_registers(n_ideal_reg); + int n_regs = RegMask::num_registers(n_ideal_reg, lrgs(lidx)); @@ -1877,7 +1877,7 @@ index 2e04c42eb..dd9b5476b 100644 * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ - + #include "precompiled.hpp" #include "opto/ad.hpp" +#include "opto/chaitin.hpp" @@ -1885,14 +1885,14 @@ index 2e04c42eb..dd9b5476b 100644 #include "opto/matcher.hpp" #include "opto/node.hpp" @@ -116,30 +117,47 @@ const RegMask RegMask::Empty( - + //============================================================================= bool RegMask::is_vector(uint ireg) { - return (ireg == Op_VecS || ireg == Op_VecD || + return (ireg == Op_VecA || ireg == Op_VecS || ireg == Op_VecD || ireg == Op_VecX || ireg == Op_VecY || ireg == Op_VecZ ); } - + int RegMask::num_registers(uint ireg) { switch(ireg) { case Op_VecZ: @@ -1919,7 +1919,7 @@ index 2e04c42eb..dd9b5476b 100644 // Op_VecS and the rest ideal registers. return 1; } - + +int RegMask::num_registers(uint ireg, LRG &lrg) { + int n_regs = num_registers(ireg); + @@ -1939,7 +1939,7 @@ index 2e04c42eb..dd9b5476b 100644 @@ -238,14 +256,30 @@ int RegMask::is_bound_pair() const { return true; } - + +// Check that whether given reg number with size is valid +// for current regmask, where reg is the highest number. +bool RegMask::is_valid_reg(OptoReg::Name reg, const int size) const { @@ -2002,7 +2002,7 @@ index c64d08795..b733b87ad 100644 @@ -28,6 +28,8 @@ #include "code/vmreg.hpp" #include "opto/optoreg.hpp" - + +class LRG; + // Some fun naming (textual) substitutions: @@ -2020,13 +2020,13 @@ index c64d08795..b733b87ad 100644 - SlotsPerVecZ = 16 }; + SlotsPerVecZ = 16, + }; - + // A constructor only used by the ADLC output. All mask fields are filled // in directly. Calls to this look something like RM(1,2,3,4); @@ -204,10 +208,14 @@ public: return false; } - + + // Check that whether given reg number with size is valid + // for current regmask, where reg is the highest number. + bool is_valid_reg(OptoReg::Name reg, const int size) const; @@ -2036,15 +2036,15 @@ index c64d08795..b733b87ad 100644 // Assert that the mask contains only bit sets. - OptoReg::Name find_first_set(const int size) const; + OptoReg::Name find_first_set(LRG &lrg, const int size) const; - + // Clear out partial bits; leave only aligned adjacent bit sets of size. void clear_to_sets(const int size); @@ -226,6 +234,7 @@ public: - + static bool is_vector(uint ireg); static int num_registers(uint ireg); + static int num_registers(uint ireg, LRG &lrg); - + // Fast overlap test. Non-zero if any registers in common. int overlap( const RegMask &rm ) const { diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp @@ -2062,7 +2062,7 @@ index 223b7a1c6..1b46cb452 100644 @@ -655,6 +656,10 @@ void Type::Initialize_shared(Compile* current) { // get_zero_type() should not happen for T_CONFLICT _zero_type[T_CONFLICT]= NULL; - + + if (Matcher::supports_scalable_vector()) { + TypeVect::VECTA = TypeVect::make(T_BYTE, Matcher::scalable_vector_reg_size(T_BYTE)); + } @@ -2080,7 +2080,7 @@ index 223b7a1c6..1b46cb452 100644 mreg2type[Op_VecD] = TypeVect::VECTD; mreg2type[Op_VecX] = TypeVect::VECTX; @@ -990,6 +997,7 @@ const Type::TYPES Type::dual_type[Type::lastype] = { - + Bad, // Tuple - handled in v-call Bad, // Array - handled in v-call + Bad, // VectorA - handled in v-call @@ -2090,13 +2090,13 @@ index 223b7a1c6..1b46cb452 100644 @@ -1890,7 +1898,6 @@ const TypeTuple *TypeTuple::LONG_PAIR; const TypeTuple *TypeTuple::INT_CC_PAIR; const TypeTuple *TypeTuple::LONG_CC_PAIR; - + - //------------------------------make------------------------------------------- // Make a TypeTuple from the range of a method signature const TypeTuple *TypeTuple::make_range(ciSignature* sig) { @@ -2262,6 +2269,7 @@ bool TypeAry::ary_must_be_exact() const { - + //==============================TypeVect======================================= // Convenience common pre-built types. +const TypeVect *TypeVect::VECTA = NULL; // vector length agnostic @@ -2117,7 +2117,7 @@ index 223b7a1c6..1b46cb452 100644 return (TypeVect*)(new TypeVectS(elem, length))->hashcons(); case Op_RegL: @@ -2307,7 +2316,7 @@ const Type *TypeVect::xmeet( const Type *t ) const { - + default: // All else is a mistake typerr(t); - @@ -2138,13 +2138,6 @@ diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index a7eec281e..6787b947d 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 1997, 2020, 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 @@ -53,6 +53,7 @@ class TypeNarrowKlass; class TypeAry; class TypeTuple; @@ -2154,7 +2147,7 @@ index a7eec281e..6787b947d 100644 class TypeVectD; class TypeVectX; @@ -87,6 +88,7 @@ public: - + Tuple, // Method signature or object layout Array, // Array types + VectorA, // (Scalable) Vector types for vector length agnostic @@ -2164,7 +2157,7 @@ index a7eec281e..6787b947d 100644 @@ -758,6 +760,7 @@ public: virtual const Type *xmeet( const Type *t) const; virtual const Type *xdual() const; // Compute dual right now. - + + static const TypeVect *VECTA; static const TypeVect *VECTS; static const TypeVect *VECTD; @@ -2172,7 +2165,7 @@ index a7eec281e..6787b947d 100644 @@ -769,6 +772,11 @@ public: #endif }; - + +class TypeVectA : public TypeVect { + friend class TypeVect; + TypeVectA(const Type* elem, uint length) : TypeVect(VectorA, elem, length) {} @@ -2183,19 +2176,19 @@ index a7eec281e..6787b947d 100644 TypeVectS(const Type* elem, uint length) : TypeVect(VectorS, elem, length) {} @@ -1619,12 +1627,12 @@ inline const TypeAry *Type::is_ary() const { } - + inline const TypeVect *Type::is_vect() const { - assert( _base >= VectorS && _base <= VectorZ, "Not a Vector" ); + assert( _base >= VectorA && _base <= VectorZ, "Not a Vector" ); return (TypeVect*)this; } - + inline const TypeVect *Type::isa_vect() const { - return (_base >= VectorS && _base <= VectorZ) ? (TypeVect*)this : NULL; + return (_base >= VectorA && _base <= VectorZ) ? (TypeVect*)this : NULL; } - + inline const TypePtr *Type::is_ptr() const { --- +-- 2.19.1 diff --git a/8290705_fix_StringConcat_validate_mem_flow_asserts_with_unexpected_userStoreI.patch b/8290705_fix_StringConcat_validate_mem_flow_asserts_with_unexpected_userStoreI.patch deleted file mode 100644 index cfecb4278ce47e3f6525e1f81c41eb9539e68e00..0000000000000000000000000000000000000000 --- a/8290705_fix_StringConcat_validate_mem_flow_asserts_with_unexpected_userStoreI.patch +++ /dev/null @@ -1,145 +0,0 @@ -diff --git a/src/hotspot/share/opto/stringopts.cpp b/src/hotspot/share/opto/stringopts.cpp -index e8e493bce..91a3c998e 100644 ---- a/src/hotspot/share/opto/stringopts.cpp -+++ b/src/hotspot/share/opto/stringopts.cpp -@@ -1028,6 +1028,21 @@ bool StringConcat::validate_control_flow() { - fail = true; - break; - } else if (ptr->is_Proj() && ptr->in(0)->is_Initialize()) { -+ // Check for side effect between Initialize and the constructor -+ for (SimpleDUIterator iter(ptr); iter.has_next(); iter.next()) { -+ Node* use = iter.get(); -+ if (!use->is_CFG() && !use->is_CheckCastPP() && !use->is_Load()) { -+#ifndef PRODUCT -+ if (PrintOptimizeStringConcat) { -+ tty->print_cr("unexpected control use of Initialize"); -+ ptr->in(0)->dump(); // Initialize node -+ use->dump(1); -+ } -+#endif -+ fail = true; -+ break; -+ } -+ } - ptr = ptr->in(0)->in(0); - } else if (ptr->is_Region()) { - Node* copy = ptr->as_Region()->is_copy(); -diff --git a/test/hotspot/jtreg/compiler/stringopts/SideEffectBeforeConstructor.jasm b/test/hotspot/jtreg/compiler/stringopts/SideEffectBeforeConstructor.jasm -new file mode 100644 -index 000000000..cbc6d754b ---- /dev/null -+++ b/test/hotspot/jtreg/compiler/stringopts/SideEffectBeforeConstructor.jasm -@@ -0,0 +1,58 @@ -+/* -+ * Copyright (c) 2022, 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. -+ */ -+ -+super public class compiler/stringopts/SideEffectBeforeConstructor -+ version 51:0 -+{ -+ public static Field result:I; -+ -+ static Method "":"()V" -+ stack 2 locals 0 -+ { -+ iconst_0; -+ putstatic Field result:"I"; -+ return; -+ } -+ public Method "":"()V" -+ stack 1 locals 1 -+ { -+ aload_0; -+ invokespecial Method java/lang/Object."":"()V"; -+ return; -+ } -+ -+ public static Method test:"(Ljava/lang/String;)V" -+ stack 4 locals 1 -+ { -+ new class java/lang/StringBuffer; -+ dup; -+ getstatic Field result:"I"; -+ iconst_1; -+ iadd; -+ putstatic Field result:"I"; -+ aload_0; -+ invokespecial Method java/lang/StringBuffer."":"(Ljava/lang/String;)V"; -+ invokevirtual Method java/lang/StringBuffer.toString:"()Ljava/lang/String;"; -+ return; -+ } -+} -diff --git a/test/hotspot/jtreg/compiler/stringopts/TestSideEffectBeforeConstructor.java b/test/hotspot/jtreg/compiler/stringopts/TestSideEffectBeforeConstructor.java -new file mode 100644 -index 000000000..86c5eca1d ---- /dev/null -+++ b/test/hotspot/jtreg/compiler/stringopts/TestSideEffectBeforeConstructor.java -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (c) 2022, 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 8290705 -+ * @summary Test correctness of the string concatenation optimization with -+ * a store between StringBuffer allocation and constructor invocation. -+ * @compile SideEffectBeforeConstructor.jasm -+ * @run main/othervm -Xbatch compiler.stringopts.TestSideEffectBeforeConstructor -+ */ -+ -+package compiler.stringopts; -+ -+public class TestSideEffectBeforeConstructor { -+ -+ public static void main(String[] args) { -+ for (int i = 0; i < 100_000; ++i) { -+ try { -+ SideEffectBeforeConstructor.test(null); -+ } catch (NullPointerException npe) { -+ // Expected -+ } -+ } -+ if (SideEffectBeforeConstructor.result != 100_000) { -+ throw new RuntimeException("Unexpected result: " + SideEffectBeforeConstructor.result); -+ } -+ } -+} diff --git a/Add-KAE-implementation.patch b/Add-KAE-implementation.patch index 3006f64e91171c742a9e466fcda08e6883b3daaa..db5193ad1e4cc9000d4ab544cacccf47b1e0404b 100644 --- a/Add-KAE-implementation.patch +++ b/Add-KAE-implementation.patch @@ -220,7 +220,7 @@ index 41533e566..9fa545605 100644 + endif +endif + - ifeq ($(OPENJDK_TARGET_OS), windows) + ifeq ($(call isTargetOs, windows), true) PLATFORM_MODULES += jdk.crypto.mscapi endif @@ -228,6 +234,13 @@ ifeq ($(ENABLE_AOT), false) diff --git a/G1-iterate-region-by-bitmap-rather-than-obj-size-in.patch b/G1-iterate-region-by-bitmap-rather-than-obj-size-in.patch index 127168dbd09be67ac6877af3d5601d88dc208ac4..de07fd8e73579473af4c7060520a47bf3cb405e9 100755 --- a/G1-iterate-region-by-bitmap-rather-than-obj-size-in.patch +++ b/G1-iterate-region-by-bitmap-rather-than-obj-size-in.patch @@ -10,7 +10,7 @@ index 2cc9c87d0..a86046616 100644 @@ -171,25 +171,47 @@ void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_for_compaction(Hea } } - + -void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_no_moving_region(const HeapRegion* hr) { - const HeapRegion* current = hr; +void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_no_moving_region(HeapRegion* hr) { @@ -61,7 +61,7 @@ index 2cc9c87d0..a86046616 100644 } + assert(next_addr == limit, "Should stop the scan at the limit."); } - + void G1FullGCPrepareTask::prepare_serial_compaction() { diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp index 57b53c9dd..7f4a69e80 100644 @@ -73,7 +73,7 @@ index 57b53c9dd..7f4a69e80 100644 void reset_region_metadata(HeapRegion* hr); - void prepare_no_moving_region(const HeapRegion* hr); + void prepare_no_moving_region(HeapRegion* hr); - + public: G1CalculatePointersClosure(G1CMBitMap* bitmap, diff --git a/src/hotspot/share/gc/g1/g1MarkLiveWords.cpp b/src/hotspot/share/gc/g1/g1MarkLiveWords.cpp @@ -109,7 +109,7 @@ index 32da3800a..aec32f9e4 100644 + * questions. + * */ - + #include "gc/g1/g1MarkLiveWords.hpp" diff --git a/src/hotspot/share/gc/g1/g1MarkLiveWords.hpp b/src/hotspot/share/gc/g1/g1MarkLiveWords.hpp index a11a4ca52..e8632fe5d 100644 @@ -144,7 +144,7 @@ index a11a4ca52..e8632fe5d 100644 + * questions. + * */ - + #ifndef SHARE_VM_GC_G1_G1MARKLIVEWORDS_HPP diff --git a/src/hotspot/share/gc/g1/g1MarkRegionCache.cpp b/src/hotspot/share/gc/g1/g1MarkRegionCache.cpp index 37922e8cf..1fb6d9929 100644 @@ -179,7 +179,7 @@ index 37922e8cf..1fb6d9929 100644 + * questions. + * */ - + #include "gc/g1/g1MarkRegionCache.hpp" diff --git a/src/hotspot/share/gc/g1/g1MarkRegionCache.hpp b/src/hotspot/share/gc/g1/g1MarkRegionCache.hpp index 0615fcab6..00d2931a6 100644 @@ -214,7 +214,7 @@ index 0615fcab6..00d2931a6 100644 + * questions. + * */ - + #ifndef SHARE_VM_GC_G1_G1MARKREGIONCACHE_HPP diff --git a/test/hotspot/jtreg/compiler/c2/Test8217359.java b/test/hotspot/jtreg/compiler/c2/Test8217359.java index ca0d2cc75..533bdce4b 100644 @@ -290,9 +290,9 @@ index 94c79c9c2..780c09211 100644 /* - * Copyright (c) 2019, Huawei Technologies Co. Ltd. All rights reserved. + * Copyright (c) 2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2022, 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 diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestSearchAlignment.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestSearchAlignment.java index 37be01524..5242adb43 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestSearchAlignment.java @@ -337,7 +337,7 @@ index 2f892773b..2383c3a94 100644 + * questions. + * */ - + /* diff --git a/test/hotspot/jtreg/runtime/invokedynamic/DynamicConstantHelper.jasm b/test/hotspot/jtreg/runtime/invokedynamic/DynamicConstantHelper.jasm index 01ab0c9f1..4fa919e94 100644 @@ -367,4 +367,4 @@ index 000000000..85b49171c --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ -+11.0.17.0.13 ++11.0.19.0.13 diff --git a/delete_expired_certificates.patch b/delete_expired_certificates.patch index 2f9cd73af0c69bcff2de77fda6efc027b38ff729..340c9a19032ab3ed94cb301f4c449734d2aff333 100644 --- a/delete_expired_certificates.patch +++ b/delete_expired_certificates.patch @@ -120,14 +120,14 @@ index 122a01901..c131bd493 100644 + File.separator + "security" + File.separator + "cacerts"; // The numbers of certs now. -- private static final int COUNT = 89; -+ private static final int COUNT = 86; +- private static final int COUNT = 90; ++ private static final int COUNT = 87; // SHA-256 of cacerts, can be generated with // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95 private static final String CHECKSUM -- = "CC:AD:BB:49:70:97:3F:42:AD:73:91:A0:A2:C4:B8:AA:D1:95:59:F3:B3:22:09:2A:1F:2C:AB:04:47:08:EF:AA"; -+ = "89:78:5A:96:F4:B2:68:4C:91:C0:32:2C:ED:2D:6B:3B:26:B8:37:C3:07:DD:9E:50:87:53:53:7A:24:98:97:E0"; +- = "21:8C:35:29:4C:E2:49:D2:83:30:DF:8B:5E:39:F8:8C:D6:C5:2B:59:05:32:74:E5:79:A5:91:9F:3C:57:B9:E3"; ++ = "D5:5B:7A:BD:8F:4A:DA:19:75:90:28:61:E7:40:6D:A2:54:F5:64:C0:F0:30:29:16:FB:46:9B:57:D5:F7:04:D7"; // map of cert alias to SHA-256 fingerprint @SuppressWarnings("serial") diff --git a/jdk-updates-jdk11u-jdk-11.0.17-ga.tar.xz b/jdk-updates-jdk11u-jdk-11.0.19-ga.tar.gz similarity index 63% rename from jdk-updates-jdk11u-jdk-11.0.17-ga.tar.xz rename to jdk-updates-jdk11u-jdk-11.0.19-ga.tar.gz index b4825d78e3e1be0a59d15c085e7b85d2ae60d5d6..360f3a82edd09a7f20ac98f878f2b1bdd6566009 100644 Binary files a/jdk-updates-jdk11u-jdk-11.0.17-ga.tar.xz and b/jdk-updates-jdk11u-jdk-11.0.19-ga.tar.gz differ diff --git a/openjdk-11.spec b/openjdk-11.spec index be34e76221e123886c57c4f75594263779bd3de2..d9e896d93f73b32179c0ac8c575d8843f794c1e3 100644 --- a/openjdk-11.spec +++ b/openjdk-11.spec @@ -114,7 +114,7 @@ # New Version-String scheme-style defines %global majorver 11 -%global securityver 17 +%global securityver 19 # buildjdkver is usually same as %%{majorver}, # but in time of bootstrap of next jdk, it is majorver-1, # and this it is better to change it here, on single place @@ -130,12 +130,12 @@ %global origin_nice OpenJDK %global top_level_dir_name %{origin} %global minorver 0 -%global buildver 8 +%global buildver 7 %global patchver 0 %global project jdk-updates %global repo jdk11u -%global revision jdk-11.0.17-ga +%global revision jdk-11.0.19-ga %global full_revision %{project}-%{repo}-%{revision} # priority must be 7 digits in total # setting to 1, so debug ones can have 0 @@ -773,7 +773,7 @@ License: ASL 1.1 and ASL 2.0 and BSD and BSD with advertising and GPL+ and GPLv URL: http://openjdk.java.net/ -Source0: %{full_revision}.tar.xz +Source0: %{full_revision}.tar.gz # Use 'icedtea_sync.sh' to update the following # They are based on code contained in the IcedTea project (3.x). @@ -801,7 +801,6 @@ Patch1000: rh1648249-add_commented_out_nss_cfg_provider_to_java_security.patch # ############################################# -Patch2: 8225648-TESTBUG-java-lang-annotation-loaderLeak-Main.patch Patch5: Add-ability-to-configure-third-port-for-remote-JMX.patch Patch6: 8214527-AArch64-ZGC-for-Aarch64.patch Patch7: 8224675-Late-GC-barrier-insertion-for-ZGC.patch @@ -875,8 +874,9 @@ Patch89: downgrade-the-symver-of-memcpy-GLIBC_2.14-on-x86.patch # 11.0.16 Patch90: fix_Internal_and_external_code_inconsistency.patch -Patch91: 8290705_fix_StringConcat_validate_mem_flow_asserts_with_unexpected_userStoreI.patch +# 11.0.18 +Patch91: 8222289-Overhaul-logic-for-reading-writing-constant-pool-entries.patch BuildRequires: elfutils-extra BuildRequires: autoconf @@ -1109,7 +1109,6 @@ fi pushd %{top_level_dir_name} # OpenJDK patches -%patch2 -p1 %patch5 -p1 %patch6 -p1 %patch7 -p1 @@ -1678,6 +1677,18 @@ cjc.mainProgram(arg) %changelog +* Mon May 08 2023 wanghao - 1:11.0.19.7-0 +- update to 11.0.19+7(GA) +- deleted 8225648-TESTBUG-java-lang-annotation-loaderLeak-Main.patch +- modified Add-KAE-implementation.patch +- modified G1-iterate-region-by-bitmap-rather-than-obj-size-in.patch +- modified delete_expired_certificates.patch +- modified 8205921-Optimizing-best_of_2-work-stealing-queue-selection.patch +- add 8222289-Overhaul-logic-for-reading-writing-constant-pool-entries.patch +- modified 8224675-Late-GC-barrier-insertion-for-ZGC.patch +- modified 8231441-2-AArch64-Initial-SVE-backend-support.patch +- deleted 8290705_fix_StringConcat_validate_mem_flow_asserts_with_unexpected_userStoreI.patch + * Wed Oct 19 2022 DXwangg - 1:11.0.17.8-0 - update to 11.0.17+8(GA) - modified G1-iterate-region-by-bitmap-rather-than-obj-size-in.patch