changeset 49702:b852d4277a21 condy-folding-new

bulk push of the current condy-folding development
author vromero
date Thu, 05 Apr 2018 12:28:38 -0400
parents e27c4e4e760e
children 644839061317
files make/BuildNashorn.gmk make/CompileJavaModules.gmk make/common/JavaCompilation.gmk src/java.base/share/classes/java/lang/Class.java src/java.base/share/classes/java/lang/Double.java src/java.base/share/classes/java/lang/Enum.java src/java.base/share/classes/java/lang/Float.java src/java.base/share/classes/java/lang/Integer.java src/java.base/share/classes/java/lang/Long.java src/java.base/share/classes/java/lang/String.java src/java.base/share/classes/java/lang/invoke/BootstrapCallInfo.java src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java src/java.base/share/classes/java/lang/invoke/ConstantGroup.java src/java.base/share/classes/java/lang/invoke/Intrinsics.java src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java src/java.base/share/classes/java/lang/invoke/MethodHandle.java src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java src/java.base/share/classes/java/lang/invoke/MethodType.java src/java.base/share/classes/java/lang/invoke/VarHandle.java src/java.base/share/classes/java/lang/invoke/VarHandles.java src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template src/java.base/share/classes/java/lang/invoke/constant/AsTypeMethodHandleRef.java src/java.base/share/classes/java/lang/invoke/constant/ClassRef.java src/java.base/share/classes/java/lang/invoke/constant/Constable.java src/java.base/share/classes/java/lang/invoke/constant/ConstantClassRef.java src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodHandleRef.java src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodTypeRef.java src/java.base/share/classes/java/lang/invoke/constant/ConstantRef.java src/java.base/share/classes/java/lang/invoke/constant/ConstantRefs.java src/java.base/share/classes/java/lang/invoke/constant/DynamicCallSiteRef.java src/java.base/share/classes/java/lang/invoke/constant/DynamicConstantRef.java src/java.base/share/classes/java/lang/invoke/constant/EnumRef.java src/java.base/share/classes/java/lang/invoke/constant/MethodHandleRef.java src/java.base/share/classes/java/lang/invoke/constant/MethodTypeRef.java src/java.base/share/classes/java/lang/invoke/constant/PrimitiveClassRef.java src/java.base/share/classes/java/lang/invoke/constant/RefBootstraps.java src/java.base/share/classes/java/lang/invoke/constant/VarHandleRef.java src/java.base/share/classes/java/lang/invoke/constant/package-info.java src/java.base/share/classes/java/lang/invoke/package-info.java src/java.base/share/classes/jdk/internal/lang/annotation/Foldable.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Attribute.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassVisitor.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Condy.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Constants.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Context.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/CurrentFrame.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Edge.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldVisitor.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/FieldWriter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Frame.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Handle.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Handler.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Item.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Label.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleVisitor.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/ModuleWriter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Symbol.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/SymbolTable.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/Type.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypePath.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypeReference.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnnotationRemapper.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/FieldRemapper.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/MethodRemapper.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleHashesAttribute.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleRemapper.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleResolutionAttribute.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ModuleTargetAttribute.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SignatureRemapper.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SimpleRemapper.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TableSwitchGenerator.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureReader.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AbstractInsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldInsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/FrameNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/IincInsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InnerClassNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/IntInsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InvokeDynamicInsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/JumpInsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LabelNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LdcInsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LineNumberNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableAnnotationNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LocalVariableNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/LookupSwitchInsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleExportNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleOpenNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleProvideNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ModuleRequireNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/MultiANewArrayInsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/ParameterNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TableSwitchInsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TryCatchBlockNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/TypeInsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/UnsupportedClassVersionException.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/Util.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/VarInsnNode.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Analyzer.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicInterpreter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicValue.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/BasicVerifier.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Interpreter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SimpleVerifier.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SmallSet.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceInterpreter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/SourceValue.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Subroutine.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Value.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifiable.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckAnnotationAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckModuleAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckSignatureAdapter.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifiable.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceAnnotationVisitor.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceFieldVisitor.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceMethodVisitor.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceModuleVisitor.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/version.txt src/java.base/share/classes/module-info.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstFold.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstablesVisitor.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties src/jdk.compiler/share/classes/com/sun/tools/javac/util/Constables.java src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java test/jdk/java/lang/invoke/CallSiteTest.java test/jdk/java/lang/invoke/CallStaticInitOrder.java test/jdk/java/lang/invoke/ConstantRefBootstrapsTest.java test/jdk/java/lang/invoke/InvokeDynamicPrintArgs.java test/jdk/java/lang/invoke/MethodHandleConstants.java test/jdk/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template test/jdk/java/lang/invoke/condy/CondyBSMInvocation.java test/jdk/java/lang/invoke/condy/CondyNestedTest_Code.jcod test/jdk/java/lang/invoke/constant/ClassRefTest.java test/jdk/java/lang/invoke/constant/CondyRefTest.java test/jdk/java/lang/invoke/constant/IndyRefTest.java test/jdk/java/lang/invoke/constant/IntrinsifiedRefTest.java test/jdk/java/lang/invoke/constant/MethodHandleRefTest.java test/jdk/java/lang/invoke/constant/MethodTypeRefTest.java test/jdk/java/lang/invoke/constant/SymbolicRefTest.java test/jdk/java/lang/invoke/indify/Indify.java test/langtools/jdk/javadoc/doclet/testClassTree/TestClassTree.java test/langtools/jdk/jshell/TypeNameTest.java test/langtools/tools/javac/T8019486/WrongLNTForLambdaTest.java test/langtools/tools/javac/T8187978/FilterOutCandidatesForDiagnosticsTest.out test/langtools/tools/javac/condy/CheckCondyGeneratedForLambdaTest.java test/langtools/tools/javac/condy/CheckForCondyDuplicatesTest.java test/langtools/tools/javac/condy/LambdaSerializationTest.java test/langtools/tools/javac/diags/examples.not-yet.txt test/langtools/tools/javac/generics/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.out test/langtools/tools/javac/lib/combo/ComboTask.java test/langtools/tools/javac/lib/combo/ComboTestHelper.java test/langtools/tools/javac/specialConstantFolding/CallClassLiteralMethodTest.java test/langtools/tools/javac/specialConstantFolding/CapturingAnnoInnerClassTest.java test/langtools/tools/javac/specialConstantFolding/CheckConstablesVSLookupAPITest.java test/langtools/tools/javac/specialConstantFolding/CheckForCorrectMRefTest.java test/langtools/tools/javac/specialConstantFolding/CondyCodeGenerationTest.java test/langtools/tools/javac/specialConstantFolding/CrashWithPrimitiveArgumentsTest.java test/langtools/tools/javac/specialConstantFolding/DontCompileIfSymbolCantBeFoundTest.java test/langtools/tools/javac/specialConstantFolding/DontCompileIfSymbolCantBeFoundTest.out test/langtools/tools/javac/specialConstantFolding/EffectivelyFinalTestNeg.java test/langtools/tools/javac/specialConstantFolding/EffectivelyFinalTestNeg.out test/langtools/tools/javac/specialConstantFolding/IndyCodeGenerationTest.java test/langtools/tools/javac/specialConstantFolding/IndyCrashTest.java test/langtools/tools/javac/specialConstantFolding/IndyCrashTest.out test/langtools/tools/javac/specialConstantFolding/IndyLinkageErrorTest.java test/langtools/tools/javac/specialConstantFolding/IndyLinkageErrorTest.out test/langtools/tools/javac/specialConstantFolding/IndyNegativeTest01.java test/langtools/tools/javac/specialConstantFolding/IndyNegativeTest01.out test/langtools/tools/javac/specialConstantFolding/IndyPositiveTest01.java test/langtools/tools/javac/specialConstantFolding/IntrinsicsTest.java test/langtools/tools/javac/specialConstantFolding/LDCNegativeTest.java test/langtools/tools/javac/specialConstantFolding/LDCNegativeTest.out test/langtools/tools/javac/specialConstantFolding/MultipleBSMEntriesTest.java test/langtools/tools/javac/specialConstantFolding/ReflectiveErrorTest.java test/langtools/tools/javac/specialConstantFolding/ReflectiveErrorTest.out test/langtools/tools/javac/specialConstantFolding/ReportIncorrectMHForIndyTest.java test/langtools/tools/javac/specialConstantFolding/ReportIncorrectMHForIndyTest.out test/langtools/tools/javac/specialConstantFolding/TwoVisitsAreNeededCauseOfForwardRefTest.java test/langtools/tools/javac/specialConstantFolding/checkMethodTypeShape/MethodTypeNegTest.java test/langtools/tools/javac/specialConstantFolding/checkMethodTypeShape/MethodTypeNegTest.out test/langtools/tools/javac/specialConstantFolding/dead_code_elimination/DontDoDCEOfConstableTest.java test/langtools/tools/javac/specialConstantFolding/harness/ConstantFoldingHarness.java test/langtools/tools/javac/specialConstantFolding/harness/HarnessAnnotations.java test/langtools/tools/javac/specialConstantFolding/harness/tests/ConstantDefinitions.java test/langtools/tools/javac/specialConstantFolding/harness/tests/ConstantFoldingOfMethodTypeDiffContextsTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/ConstantFoldingTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/ConstantPropagationTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/ConstantsUser.java test/langtools/tools/javac/specialConstantFolding/harness/tests/EffectivelyFinalTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindConstructorTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindGetterTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindMethodWithGenericArgumentsTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindSetterTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindStaticGetterTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindStaticSetterTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindStaticTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindVirtualTest01.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindVirtualTest02.java test/langtools/tools/javac/specialConstantFolding/harness/tests/InstanceTrackableMethodsTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/StringFoldingTest.java test/langtools/tools/javac/specialConstantFolding/warningNotFoundOrIncorrect/WarningIfClassOrMemberNotFound.java test/langtools/tools/javac/specialConstantFolding/warningNotFoundOrIncorrect/WarningIfClassOrMemberNotFound.out test/langtools/tools/javac/specialConstantFolding/warningNotFoundOrIncorrect/WarningIfClassOrMemberNotFound2.java test/langtools/tools/javac/specialConstantFolding/warningNotFoundOrIncorrect/WarningIfClassOrMemberNotFound2.out test/langtools/tools/javac/specialConstantFolding/warningNotFoundOrIncorrect/WarningIfClassOrMemberNotFound3.java test/langtools/tools/javac/specialConstantFolding/warningNotFoundOrIncorrect/WarningIfClassOrMemberNotFound3.out test/langtools/tools/javac/specialConstantFolding/warningNotFoundOrIncorrect/WarningIfMemberIncorrect.java test/langtools/tools/javac/specialConstantFolding/warningNotFoundOrIncorrect/WarningIfMemberIncorrect.out test/langtools/tools/javac/varargs/6806876/T6806876.out test/langtools/tools/lib/toolbox/Task.java
diffstat 298 files changed, 55089 insertions(+), 45260 deletions(-) [+]
line wrap: on
line diff
--- a/make/BuildNashorn.gmk	Thu Apr 05 11:08:37 2018 -0400
+++ b/make/BuildNashorn.gmk	Thu Apr 05 12:28:38 2018 -0400
@@ -41,7 +41,7 @@
 $(eval $(call SetupJavaCompiler, GENERATE_NEWBYTECODE_DEBUG, \
     JVM := $(JAVA_JAVAC), \
     JAVAC := $(NEW_JAVAC), \
-    FLAGS := -g -source 10 -target 10 --upgrade-module-path "$(JDK_OUTPUTDIR)/modules/" \
+    FLAGS := -g -source 11 -target 11 --upgrade-module-path "$(JDK_OUTPUTDIR)/modules/" \
          --system none --module-source-path $(call GetModuleSrcPath), \
     SERVER_DIR := $(SJAVAC_SERVER_DIR), \
     SERVER_JVM := $(SJAVAC_SERVER_JAVA)))
--- a/make/CompileJavaModules.gmk	Thu Apr 05 11:08:37 2018 -0400
+++ b/make/CompileJavaModules.gmk	Thu Apr 05 12:28:38 2018 -0400
@@ -268,7 +268,7 @@
 
 ################################################################################
 
-java.rmi_ADD_JAVAC_FLAGS += -Xdoclint:all/protected '-Xdoclint/package:java.*,javax.*'
+java.rmi_ADD_JAVAC_FLAGS += -Xdoclint:all/protected '-Xdoclint/package:java.*,javax.*' -XDforNonCapturingLambda=generateIndy
 java.rmi_CLEAN_FILES += $(wildcard \
     $(TOPDIR)/src/java.rmi/share/classes/sun/rmi/registry/resources/*.properties \
     $(TOPDIR)/src/java.rmi/share/classes/sun/rmi/server/resources/*.properties)
--- a/make/common/JavaCompilation.gmk	Thu Apr 05 11:08:37 2018 -0400
+++ b/make/common/JavaCompilation.gmk	Thu Apr 05 12:28:38 2018 -0400
@@ -195,6 +195,7 @@
   ifneq ($$($1_DEBUG_SYMBOLS), false)
     $1_FLAGS := -g
   endif
+  # remove this option once ASM knows how to deal with condy
   $1_FLAGS += $$($$($1_SETUP)_FLAGS) $$($1_ADD_JAVAC_FLAGS) $(JAVAC_FLAGS)
   ifneq ($$($1_CLASSPATH), )
     $1_FLAGS += -cp $$(call PathList, $$($1_CLASSPATH))
--- a/src/java.base/share/classes/java/lang/Class.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/Class.java	Thu Apr 05 12:28:38 2018 -0400
@@ -26,6 +26,7 @@
 package java.lang;
 
 import java.lang.annotation.Annotation;
+import java.lang.invoke.MethodHandles;
 import java.lang.module.ModuleReader;
 import java.lang.ref.SoftReference;
 import java.io.IOException;
@@ -46,6 +47,8 @@
 import java.lang.reflect.Proxy;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
+import java.lang.invoke.constant.ClassRef;
+import java.lang.invoke.constant.Constable;
 import java.net.URL;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -58,19 +61,20 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.StringJoiner;
 
 import jdk.internal.HotSpotIntrinsicCandidate;
 import jdk.internal.loader.BootLoader;
 import jdk.internal.loader.BuiltinClassLoader;
 import jdk.internal.misc.Unsafe;
-import jdk.internal.misc.VM;
 import jdk.internal.module.Resources;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.ConstantPool;
 import jdk.internal.reflect.Reflection;
 import jdk.internal.reflect.ReflectionFactory;
 import jdk.internal.vm.annotation.ForceInline;
+import sun.invoke.util.Wrapper;
 import sun.reflect.generics.factory.CoreReflectionFactory;
 import sun.reflect.generics.factory.GenericsFactory;
 import sun.reflect.generics.repository.ClassRepository;
@@ -129,7 +133,8 @@
 public final class Class<T> implements java.io.Serializable,
                               GenericDeclaration,
                               Type,
-                              AnnotatedElement {
+                              AnnotatedElement,
+                              Constable<Class<T>> {
     private static final int ANNOTATION= 0x00002000;
     private static final int ENUM      = 0x00004000;
     private static final int SYNTHETIC = 0x00001000;
@@ -254,6 +259,29 @@
     }
 
     /**
+     * Produces a bytecode descriptor representation of the class.
+     * <p>
+     * Note that this is not a strict inverse of {@link #forName};
+     * two distinct classes which share a common name but have different class loaders
+     * will appear identical when viewed within descriptor strings.
+     * <p>
+     * This method is included for the benefit of applications that must
+     * generate bytecode.
+     *
+     * @return the bytecode type descriptor representation
+     */
+    public String toDescriptorString() {
+        if (isPrimitive())
+            return new String(new char[] {Wrapper.forPrimitiveType(this).basicTypeChar()});
+        else if (isArray()) {
+            return "[" + componentType.toDescriptorString();
+        }
+        else {
+            return "L" + getName().replace('.', '/') + ";";
+        }
+    }
+
+    /**
      * Returns the {@code Class} object associated with the class or
      * interface with the given string name.  Invoking this method is
      * equivalent to:
@@ -3824,4 +3852,14 @@
     public AnnotatedType[] getAnnotatedInterfaces() {
          return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this);
     }
+
+    @Override
+    public Optional<ClassRef> toConstantRef(MethodHandles.Lookup lookup) {
+        try {
+            return Optional.of(ClassRef.ofDescriptor(lookup.accessClass(this).toDescriptorString()));
+        }
+        catch (IllegalAccessException e) {
+            return Optional.empty();
+        }
+    }
 }
--- a/src/java.base/share/classes/java/lang/Double.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/Double.java	Thu Apr 05 12:28:38 2018 -0400
@@ -25,6 +25,11 @@
 
 package java.lang;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
+import java.util.Optional;
+
 import jdk.internal.math.FloatingDecimal;
 import jdk.internal.math.DoubleConsts;
 import jdk.internal.HotSpotIntrinsicCandidate;
@@ -46,7 +51,8 @@
  * @author  Joseph D. Darcy
  * @since 1.0
  */
-public final class Double extends Number implements Comparable<Double> {
+public final class Double extends Number
+        implements Comparable<Double>, ConstantRef<Double>, Constable<Double> {
     /**
      * A constant holding the positive infinity of type
      * {@code double}. It is equal to the value returned by
@@ -1070,6 +1076,30 @@
         return Math.min(a, b);
     }
 
+    /**
+     * Returns a symbolic constant reference for this instance, which is
+     * the instance itself.
+     *
+     * @param lookup ignored
+     * @return the {@linkplain Double} instance
+     */
+    @Override
+    public Optional<ConstantRef<Double>> toConstantRef(MethodHandles.Lookup lookup) {
+        return Optional.of(this);
+    }
+
+    /**
+     * Resolve this instance as a {@link ConstantRef}, the result of which is
+     * the instance itself.
+     *
+     * @param lookup ignored
+     * @return the {@linkplain Double} instance
+     */
+    @Override
+    public Double resolveConstantRef(MethodHandles.Lookup lookup) {
+        return this;
+    }
+
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     private static final long serialVersionUID = -9172774392245257468L;
 }
--- a/src/java.base/share/classes/java/lang/Enum.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/Enum.java	Thu Apr 05 12:28:38 2018 -0400
@@ -30,6 +30,10 @@
 import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.ObjectStreamException;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.EnumRef;
+import java.util.Optional;
 
 /**
  * This is the common base class of all Java language enumeration types.
@@ -55,7 +59,7 @@
 @SuppressWarnings("serial") // No serialVersionUID needed due to
                             // special-casing of enum types.
 public abstract class Enum<E extends Enum<E>>
-        implements Comparable<E>, Serializable {
+        implements Constable<E>, Comparable<E>, Serializable {
     /**
      * The name of this enum constant, as declared in the enum declaration.
      * Most programmers should use the {@link #toString} method rather than
@@ -202,6 +206,13 @@
         return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
     }
 
+    @Override
+    public Optional<EnumRef<E>> toConstantRef(MethodHandles.Lookup lookup) {
+        return getDeclaringClass()
+                .toConstantRef(lookup)
+                .map(c -> EnumRef.of(c, name));
+    }
+
     /**
      * Returns the enum constant of the specified enum type with the
      * specified name.  The name must match exactly an identifier used
--- a/src/java.base/share/classes/java/lang/Float.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/Float.java	Thu Apr 05 12:28:38 2018 -0400
@@ -25,6 +25,11 @@
 
 package java.lang;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
+import java.util.Optional;
+
 import jdk.internal.math.FloatingDecimal;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
@@ -45,7 +50,8 @@
  * @author  Joseph D. Darcy
  * @since 1.0
  */
-public final class Float extends Number implements Comparable<Float> {
+public final class Float extends Number
+        implements Comparable<Float>, ConstantRef<Float>, Constable<Float> {
     /**
      * A constant holding the positive infinity of type
      * {@code float}. It is equal to the value returned by
@@ -982,6 +988,30 @@
         return Math.min(a, b);
     }
 
+    /**
+     * Returns a symbolic constant reference for this instance, which is
+     * the instance itself.
+     *
+     * @param lookup ignored
+     * @return the {@linkplain Float} instance
+     */
+    @Override
+    public Optional<ConstantRef<Float>> toConstantRef(MethodHandles.Lookup lookup) {
+        return Optional.of(this);
+    }
+
+    /**
+     * Resolve this instance as a {@link ConstantRef}, the result of which is
+     * the instance itself.
+     *
+     * @param lookup ignored
+     * @return the {@linkplain Float} instance
+     */
+    @Override
+    public Float resolveConstantRef(MethodHandles.Lookup lookup) {
+        return this;
+    }
+
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     private static final long serialVersionUID = -2671257302660747028L;
 }
--- a/src/java.base/share/classes/java/lang/Integer.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/Integer.java	Thu Apr 05 12:28:38 2018 -0400
@@ -26,7 +26,12 @@
 package java.lang;
 
 import java.lang.annotation.Native;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
 import java.util.Objects;
+import java.util.Optional;
+
 import jdk.internal.HotSpotIntrinsicCandidate;
 import jdk.internal.misc.VM;
 
@@ -56,7 +61,8 @@
  * @author  Joseph D. Darcy
  * @since 1.0
  */
-public final class Integer extends Number implements Comparable<Integer> {
+public final class Integer extends Number
+        implements Comparable<Integer>, ConstantRef<Integer>, Constable<Integer> {
     /**
      * A constant holding the minimum value an {@code int} can
      * have, -2<sup>31</sup>.
@@ -1823,6 +1829,30 @@
         return Math.min(a, b);
     }
 
+    /**
+     * Returns a symbolic constant reference for this instance, which is
+     * the instance itself.
+     *
+     * @param lookup ignored
+     * @return the {@linkplain Integer} instance
+     */
+    @Override
+    public Optional<ConstantRef<Integer>> toConstantRef(MethodHandles.Lookup lookup) {
+        return Optional.of(this);
+    }
+
+    /**
+     * Resolve this instance as a {@link ConstantRef}, the result of which is
+     * the instance itself.
+     *
+     * @param lookup ignored
+     * @return the {@linkplain Integer} instance
+     */
+    @Override
+    public Integer resolveConstantRef(MethodHandles.Lookup lookup) {
+        return this;
+    }
+
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     @Native private static final long serialVersionUID = 1360826667806852920L;
 }
--- a/src/java.base/share/classes/java/lang/Long.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/Long.java	Thu Apr 05 12:28:38 2018 -0400
@@ -26,8 +26,13 @@
 package java.lang;
 
 import java.lang.annotation.Native;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
 import java.math.*;
 import java.util.Objects;
+import java.util.Optional;
+
 import jdk.internal.HotSpotIntrinsicCandidate;
 
 import static java.lang.String.COMPACT_STRINGS;
@@ -56,7 +61,8 @@
  * @author  Joseph D. Darcy
  * @since   1.0
  */
-public final class Long extends Number implements Comparable<Long> {
+public final class Long extends Number
+        implements Comparable<Long>, ConstantRef<Long>, Constable<Long> {
     /**
      * A constant holding the minimum value a {@code long} can
      * have, -2<sup>63</sup>.
@@ -1972,6 +1978,30 @@
         return Math.min(a, b);
     }
 
+    /**
+     * Returns a symbolic constant reference for this instance, which is
+     * the instance itself.
+     *
+     * @param lookup ignored
+     * @return the {@linkplain Long} instance
+     */
+    @Override
+    public Optional<ConstantRef<Long>> toConstantRef(MethodHandles.Lookup lookup) {
+        return Optional.of(this);
+    }
+
+    /**
+     * Resolve this instance as a {@link ConstantRef}, the result of which is
+     * the instance itself.
+     *
+     * @param lookup ignored
+     * @return the {@linkplain Long} instance
+     */
+    @Override
+    public Long resolveConstantRef(MethodHandles.Lookup lookup) {
+        return this;
+    }
+
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     @Native private static final long serialVersionUID = 4290774380558885855L;
 }
--- a/src/java.base/share/classes/java/lang/String.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/String.java	Thu Apr 05 12:28:38 2018 -0400
@@ -28,6 +28,9 @@
 import java.io.ObjectStreamField;
 import java.io.UnsupportedEncodingException;
 import java.lang.annotation.Native;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -35,6 +38,7 @@
 import java.util.Formatter;
 import java.util.Locale;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Spliterator;
 import java.util.StringJoiner;
 import java.util.regex.Matcher;
@@ -122,7 +126,8 @@
  */
 
 public final class String
-    implements java.io.Serializable, Comparable<String>, CharSequence {
+    implements java.io.Serializable, Comparable<String>, CharSequence,
+               ConstantRef<String>, Constable<String> {
 
     /**
      * The value is used for character storage.
@@ -1779,7 +1784,7 @@
      * @param   src         the characters being searched.
      * @param   srcCoder    coder handles the mapping between bytes/chars
      * @param   srcCount    count of the source string.
-     * @param   tgt         the characters being searched for.
+     * @param   tgtStr      the characters being searched for.
      * @param   fromIndex   the index to begin searching from.
      */
     static int lastIndexOf(byte[] src, byte srcCoder, int srcCount,
@@ -3181,4 +3186,29 @@
         throw new IllegalArgumentException(
             format("Not a valid Unicode code point: 0x%X", codePoint));
     }
+
+    /**
+     * Returns a symbolic constant reference for this instance, which is
+     * the instance itself.
+     *
+     * @param lookup ignored
+     * @return the {@linkplain String} instance
+     */
+    @Override
+    public Optional<ConstantRef<String>> toConstantRef(MethodHandles.Lookup lookup) {
+        return Optional.of(this);
+    }
+
+    /**
+     * Resolve this instance as a {@link ConstantRef}, the result of which is
+     * the instance itself.
+     *
+     * @param lookup ignored
+     * @return the {@linkplain String} instance
+     */
+    @Override
+    public String resolveConstantRef(MethodHandles.Lookup lookup) {
+        return this;
+    }
+
 }
--- a/src/java.base/share/classes/java/lang/invoke/BootstrapCallInfo.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/BootstrapCallInfo.java	Thu Apr 05 12:28:38 2018 -0400
@@ -26,6 +26,8 @@
 package java.lang.invoke;
 
 import java.lang.invoke.MethodHandles.Lookup;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * An interface providing full static information about a particular
@@ -73,7 +75,7 @@
   args.add(bsci.invocationName());
   args.add(bsci.invocationType());
   MethodHandle bsm = (MethodHandle) bsci.get(0);
-  List<Object> restOfArgs = bsci.asList().subList(1, bsci.size();
+  List<Object> restOfArgs = bsci.asList().subList(1, bsci.size());
   // the next line eagerly resolves all remaining static arguments:
   args.addAll(restOfArgs);
   return bsm.invokeWithArguments(args);
@@ -96,16 +98,148 @@
 static Object genericBSM(Lookup lookup, String name, Object type,
                          MethodHandle bsm, Object... args)
     throws Throwable {
-  ConstantGroup cons = ConstantGroup.makeConstantGroup(Arrays.asList(args));
-  BootstrapCallInfo<Object> bsci = makeBootstrapCallInfo(bsm, name, type, cons);
+  BootstrapCallInfo<Object> bsci = makeBootstrapCallInfo(bsm, name, type, args);
   return bsm.invoke(lookup, bsci);
 }
  * }</pre></blockquote>
  *
- * @since 1.10
+ * @since 11
  */
-// public
+public
 interface BootstrapCallInfo<T> extends ConstantGroup {
+
+    /// Access
+
+    /**
+     * Returns the number of static arguments.
+     * @return the number of static arguments
+     */
+    int size();
+
+    /**
+     * Returns the selected static argument, resolving it if necessary.
+     * Throws a linkage error if resolution proves impossible.
+     * @param index which static argument to select
+     * @return the selected static argument
+     * @throws LinkageError if the selected static argument needs resolution
+     * and cannot be resolved
+     */
+    Object get(int index) throws LinkageError;
+
+    /**
+     * Returns the selected static argument,
+     * or the given sentinel value if there is none available.
+     * If the static argument cannot be resolved, the sentinel will be returned.
+     * If the static argument can (perhaps) be resolved, but has not yet been resolved,
+     * then the sentinel <em>may</em> be returned, at the implementation's discretion.
+     * To force resolution (and a possible exception), call {@link #get(int)}.
+     * @param index the selected constant
+     * @param ifNotPresent the sentinel value to return if the static argument is not present
+     * @return the selected static argument, if available, else the sentinel value
+     */
+    Object get(int index, Object ifNotPresent);
+
+    /**
+     * Returns an indication of whether a static argument may be available.
+     * If it returns {@code true}, it will always return true in the future,
+     * and a call to {@link #get(int)} will never throw an exception.
+     * <p>
+     * After a normal return from {@link #get(int)} or a present
+     * value is reported from {@link #get(int,Object)}, this method
+     * must always return true.
+     * <p>
+     * If this method returns {@code false}, nothing in particular
+     * can be inferred, since the query only concerns the internal
+     * logic of the {@code BootstrapCallInfo} object which ensures that a
+     * successful query to a constant will always remain successful.
+     * The only way to force a permanent decision about whether
+     * a static argument is available is to call {@link #get(int)} and
+     * be ready for an exception if the constant is unavailable.
+     * @param index the selected constant
+     * @return {@code true} if the selected static argument is known by
+     *     this object to be present, {@code false} if it is known
+     *     not to be present or
+     */
+    boolean isPresent(int index);
+
+
+    /// Views
+
+    /**
+     * Create a view on the static arguments as a {@link List} view.
+     * Any request for a static argument through this view will
+     * force resolution.
+     * @return a {@code List} view on the static arguments which will force resolution
+     */
+    default List<Object> asList() {
+        return new AbstractConstantGroup.AsList(this, 0, size());
+    }
+
+    /**
+     * Create a view on the static argument as a {@link List} view.
+     * Any request for a static argument through this view will
+     * return the given sentinel value, if the corresponding
+     * call to {@link #get(int,Object)} would do so.
+     * @param ifNotPresent the sentinel value to return if a static argument is not present
+     * @return a {@code List} view on the static arguments which will not force resolution
+     */
+    default List<Object> asList(Object ifNotPresent) {
+        return new AbstractConstantGroup.AsList(this, 0, size(), ifNotPresent);
+    }
+
+
+    /// Bulk operations
+
+    /**
+     * Copy a sequence of static arguments into a given buffer.
+     * This is equivalent to {@code end-offset} separate calls to {@code get},
+     * for each index in the range from {@code offset} up to but not including {@code end}.
+     * For the first static argument that cannot be resolved,
+     * a {@code LinkageError} is thrown, but only after
+     * preceding static arguments have been stored.
+     * @param start index of first static argument to retrieve
+     * @param end limiting index of static arguments to retrieve
+     * @param buf array to receive the requested static arguments
+     * @param pos position in the array to offset storing the static arguments
+     * @return the limiting index, {@code end}
+     * @throws LinkageError if a static argument cannot be resolved
+     */
+    default int copyArguments(int start, int end,
+                              Object[] buf, int pos)
+            throws LinkageError
+    {
+        int bufBase = pos - start;  // buf[bufBase + i] = get(i)
+        for (int i = start; i < end; i++) {
+            buf[bufBase + i] = get(i);
+        }
+        return end;
+    }
+
+    /**
+     * Copy a sequence of static arguments into a given buffer.
+     * This is equivalent to {@code end-offset} separate calls to {@code get},
+     * for each index in the range from {@code offset} up to but not including {@code end}.
+     * Any static arguments that cannot be resolved are replaced by the
+     * given sentinel value.
+     * @param start index of first static argument to retrieve
+     * @param end limiting index of static arguments to retrieve
+     * @param buf array to receive the requested values
+     * @param pos position in the array to offset storing the static arguments
+     * @param ifNotPresent sentinel value to store if a static argument is not available
+     * @return the limiting index, {@code end}
+     * @throws LinkageError if {@code resolve} is true and a static argument cannot be resolved
+     */
+    default int copyConstants(int start, int end,
+                              Object[] buf, int pos,
+                              Object ifNotPresent) {
+        int bufBase = pos - start;  // buf[bufBase + i] = get(i)
+        for (int i = start; i < end; i++) {
+            buf[bufBase + i] = get(i, ifNotPresent);
+        }
+        return end;
+    }
+
+
     /** Returns the bootstrap method for this call.
      * @return the bootstrap method
      */
@@ -126,17 +260,126 @@
      * @param bsm bootstrap method
      * @param name invocation name
      * @param type invocation type
-     * @param constants the additional static arguments for the bootstrap method
+     * @param args the additional static arguments for the bootstrap method
      * @param <T> the type of the invocation type, either {@link MethodHandle} or {@link Class}
      * @return a new bootstrap call descriptor with the given components
      */
     static <T> BootstrapCallInfo<T> makeBootstrapCallInfo(MethodHandle bsm,
                                                           String name,
                                                           T type,
-                                                          ConstantGroup constants) {
-        AbstractConstantGroup.BSCIWithCache<T> bsci = new AbstractConstantGroup.BSCIWithCache<>(bsm, name, type, constants.size());
+                                                          Object... args) {
+        AbstractConstantGroup.BSCIWithCache<T> bsci = new AbstractConstantGroup.BSCIWithCache<>(bsm, name, type, args.length);
         final Object NP = AbstractConstantGroup.BSCIWithCache.NOT_PRESENT;
-        bsci.initializeCache(constants.asList(NP), NP);
+        bsci.initializeCache(Arrays.asList(args), NP);
         return bsci;
     }
+
+    /**
+     * Invoke a bootstrap method handle with arguments obtained by resolving
+     * the sequence of constants supplied by a given bootstrap call descriptor,
+     * {@code bci}.
+     * The first argument to the method will be {@code lookup}.
+     * The second argument will be the invocation name of {@code bci}.
+     * The third argument will be the invocation type of {@code bci}.
+     * The fourth and subsequent arguments (if any) will be the resolved
+     * constants, in order, supplied by {@code bci}.
+     * <p>
+     * @apiNote
+     * This method behaves like the following but may be more optimal:
+     * <blockquote><pre>{@code
+     *   ArrayList<Object> args = new ArrayList<>();
+     *   args.add(lookup);
+     *   args.add(bsci.invocationName());
+     *   args.add(bsci.invocationType());
+     *   List<Object> constantArgs = bsci.asList();
+     *   args.addAll(constantArgs);
+     *   return handle.invokeWithArguments(args);
+     * }</pre></blockquote>
+     *
+     * @param handle the bootstrap method handle to be invoked with resolved
+     *        constants supplied by {@code bci}
+     * @param lookup the lookup
+     * @param bsci the bootstrap call descriptor
+     * @return the result of invocation
+     * @throws Throwable if an error occurs when resolving the constants from
+     *         the bootstrap call descriptor or invoking the method handle
+     */
+    // @@@ More stuff to add as api note
+    // This method is static so that it's possible to look it up and bind
+    // to a method handle, thereby viewing that method handle as if accepts
+    // a BootstrapCallInfo
+    static Object invokeFromCallInfoToArguments(MethodHandle handle,
+                                                MethodHandles.Lookup lookup,
+                                                BootstrapCallInfo<?> bsci) throws Throwable {
+        int argc = bsci.size();
+        switch (argc) {
+            case 0:
+                return handle.invoke(lookup, bsci.invocationName(), bsci.invocationType());
+            case 1:
+                return handle.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
+                                     bsci.get(0));
+            case 2:
+                return handle.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
+                                     bsci.get(0), bsci.get(1));
+            case 3:
+                return handle.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
+                                     bsci.get(0), bsci.get(1), bsci.get(2));
+            case 4:
+                return handle.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
+                                     bsci.get(0), bsci.get(1), bsci.get(2), bsci.get(3));
+            case 5:
+                return handle.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
+                                     bsci.get(0), bsci.get(1), bsci.get(2), bsci.get(3), bsci.get(4));
+            case 6:
+                return handle.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
+                                     bsci.get(0), bsci.get(1), bsci.get(2), bsci.get(3), bsci.get(4), bsci.get(5));
+            default:
+                final int NON_SPREAD_ARG_COUNT = 3;  // (lookup, name, type)
+                final int MAX_SAFE_SIZE = MethodType.MAX_MH_ARITY / 2 - NON_SPREAD_ARG_COUNT;
+                if (argc >= MAX_SAFE_SIZE) {
+                    // to be on the safe side, use invokeWithArguments which handles jumbo lists
+                    Object[] newargv = new Object[NON_SPREAD_ARG_COUNT + argc];
+                    newargv[0] = lookup;
+                    newargv[1] = bsci.invocationName();
+                    newargv[2] = bsci.invocationType();
+                    bsci.copyArguments(0, argc, newargv, NON_SPREAD_ARG_COUNT);
+                    return handle.invokeWithArguments(newargv);
+                }
+                MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argc);
+                MethodHandle typedBSM = handle.asType(invocationType);
+                MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT);
+                Object[] argv = new Object[argc];
+                bsci.copyArguments(0, argc, argv, 0);
+                return spreader.invokeExact(typedBSM, (Object) lookup, (Object) bsci.invocationName(), bsci.invocationType(), argv);
+        }
+    }
+
+    /**
+     * Invoke a bootstrap method handle with a bootstrap call descriptor
+     * argument composed from a given sequence of arguments.
+     * <p>
+     * @apiNote
+     * This method behaves like the following but may be more optimal:
+     * <blockquote><pre>{@code
+     *   BootstrapCallInfo<Object> bsci = makeBootstrapCallInfo(handle, name, type, args);
+     *   return handle.invoke(lookup, bsci);
+     * }</pre></blockquote>
+     *
+     * @param handle the bootstrap method handle to be invoked with a bootstrap
+     *        call descriptor composed from the sequence of arguments
+     * @param lookup the lookup
+     * @param name the method name or constant name
+     * @param type the method type or constant type
+     * @param args the sequence of arguments
+     * @return the result of invocation
+     * @throws Throwable if an error occurs when invoking the method handle
+     */
+    static Object invokeFromArgumentsToCallInfo(MethodHandle handle,
+                                                MethodHandles.Lookup lookup,
+                                                String name,
+                                                Object type,
+                                                Object... args) throws Throwable {
+        BootstrapCallInfo<?> bsci = makeBootstrapCallInfo(handle, name, type, args);
+        return handle.invoke(lookup, bsci);
+    }
 }
--- a/src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java	Thu Apr 05 12:28:38 2018 -0400
@@ -29,8 +29,6 @@
 import java.lang.invoke.AbstractConstantGroup.BSCIWithCache;
 import java.util.Arrays;
 
-import static java.lang.invoke.BootstrapCallInfo.makeBootstrapCallInfo;
-import static java.lang.invoke.ConstantGroup.makeConstantGroup;
 import static java.lang.invoke.MethodHandleNatives.*;
 import static java.lang.invoke.MethodHandleStatics.TRACE_METHOD_LINKAGE;
 import static java.lang.invoke.MethodHandles.Lookup;
@@ -360,7 +358,7 @@
 
         @Override Object fillCache(int i) {
             Object[] buf = { null };
-            copyConstants(i, i+1, buf, 0);
+            copyArguments(i, i + 1, buf, 0);
             Object res = wrapNull(buf[0]);
             cache[i] = res;
             int next = i + 1;
@@ -369,7 +367,7 @@
             return res;
         }
 
-        @Override public int copyConstants(int start, int end,
+        @Override public int copyArguments(int start, int end,
                                            Object[] buf, int pos) {
             int i = start, bufi = pos;
             while (i < end) {
@@ -448,23 +446,12 @@
 
     /*non-public*/ static final
     class PushAdapter {
-        // skeleton for push-mode BSM which wraps a pull-mode BSM:
-        static Object pushToBootstrapMethod(MethodHandle pullModeBSM,
-                                            MethodHandles.Lookup lookup, String name, Object type,
-                                            Object... arguments) throws Throwable {
-            ConstantGroup cons = makeConstantGroup(Arrays.asList(arguments));
-            BootstrapCallInfo<?> bsci = makeBootstrapCallInfo(pullModeBSM, name, type, cons);
-            if (TRACE_METHOD_LINKAGE)
-                System.out.println("pull-mode BSM gets pushed arguments from fake BSCI");
-            return pullModeBSM.invoke(lookup, bsci);
-        }
+        static final MethodHandle MH_pushToBootstrapMethod;
 
-        static final MethodHandle MH_pushToBootstrapMethod;
         static {
-            final Class<?> THIS_CLASS = PushAdapter.class;
             try {
                 MH_pushToBootstrapMethod = IMPL_LOOKUP
-                    .findStatic(THIS_CLASS, "pushToBootstrapMethod",
+                    .findStatic(BootstrapCallInfo.class, "invokeFromArgumentsToCallInfo",
                                 MethodType.methodType(Object.class, MethodHandle.class,
                                         Lookup.class, String.class, Object.class, Object[].class));
             } catch (Throwable ex) {
@@ -475,63 +462,14 @@
 
     /*non-public*/ static final
     class PullAdapter {
-        // skeleton for pull-mode BSM which wraps a push-mode BSM:
-        static Object pullFromBootstrapMethod(MethodHandle pushModeBSM,
-                                              MethodHandles.Lookup lookup,
-                                              BootstrapCallInfo<?> bsci)
-                throws Throwable {
-            int argc = bsci.size();
-            switch (argc) {
-                case 0:
-                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType());
-                case 1:
-                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
-                            bsci.get(0));
-                case 2:
-                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
-                            bsci.get(0), bsci.get(1));
-                case 3:
-                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
-                            bsci.get(0), bsci.get(1), bsci.get(2));
-                case 4:
-                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
-                            bsci.get(0), bsci.get(1), bsci.get(2), bsci.get(3));
-                case 5:
-                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
-                            bsci.get(0), bsci.get(1), bsci.get(2), bsci.get(3), bsci.get(4));
-                case 6:
-                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
-                            bsci.get(0), bsci.get(1), bsci.get(2), bsci.get(3), bsci.get(4), bsci.get(5));
-                default:
-                    final int NON_SPREAD_ARG_COUNT = 3;  // (lookup, name, type)
-                    final int MAX_SAFE_SIZE = MethodType.MAX_MH_ARITY / 2 - NON_SPREAD_ARG_COUNT;
-                    if (argc >= MAX_SAFE_SIZE) {
-                        // to be on the safe side, use invokeWithArguments which handles jumbo lists
-                        Object[] newargv = new Object[NON_SPREAD_ARG_COUNT + argc];
-                        newargv[0] = lookup;
-                        newargv[1] = bsci.invocationName();
-                        newargv[2] = bsci.invocationType();
-                        bsci.copyConstants(0, argc, newargv, NON_SPREAD_ARG_COUNT);
-                        return pushModeBSM.invokeWithArguments(newargv);
-                    }
-                    MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argc);
-                    MethodHandle typedBSM = pushModeBSM.asType(invocationType);
-                    MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT);
-                    Object[] argv = new Object[argc];
-                    bsci.copyConstants(0, argc, argv, 0);
-                    return spreader.invokeExact(typedBSM, (Object) lookup, (Object) bsci.invocationName(), bsci.invocationType(), argv);
-                }
-        }
-
         static final MethodHandle MH_pullFromBootstrapMethod;
 
         static {
-            final Class<?> THIS_CLASS = PullAdapter.class;
             try {
                 MH_pullFromBootstrapMethod = IMPL_LOOKUP
-                    .findStatic(THIS_CLASS, "pullFromBootstrapMethod",
+                    .findStatic(BootstrapCallInfo.class, "invokeFromCallInfoToArguments",
                                 MethodType.methodType(Object.class, MethodHandle.class,
-                                        Lookup.class, BootstrapCallInfo.class));
+                                                      Lookup.class, BootstrapCallInfo.class));
             } catch (Throwable ex) {
                 throw new InternalError(ex);
             }
--- a/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java	Thu Apr 05 12:28:38 2018 -0400
@@ -42,13 +42,36 @@
 public final class ConstantBootstraps {
     // implements the upcall from the JVM, MethodHandleNatives.linkDynamicConstant:
     /*non-public*/
-    static Object makeConstant(MethodHandle bootstrapMethod,
-                               // Callee information:
-                               String name, Class<?> type,
-                               // Extra arguments for BSM, if any:
-                               Object info,
-                               // Caller information:
-                               Class<?> callerClass) {
+    /**
+     * (temporarily public)
+     * makeConstant
+     *
+     * @param bootstrapMethod doc
+     * @param name doc
+     * @param type doc
+     * @param info doc
+     * @param callerClass doc
+     * @return doc
+     */
+    /* @@@ */ public static Object makeConstant(MethodHandle bootstrapMethod,
+                                      // Callee information:
+                                      String name, Class<?> type,
+                                      // Extra arguments for BSM, if any:
+                                      Object info,
+                                      // Caller information:
+                                      Class<?> callerClass) {
+        // Restrict bootstrap methods to those whose first parameter is Lookup
+        // The motivation here is, in the future, to possibly support BSMs
+        // that do not accept the meta-data of lookup/name/type, thereby
+        // allowing the co-opting of existing methods to be used as BSMs as
+        // long as the static arguments can be passed as method arguments
+        MethodType mt = bootstrapMethod.type();
+        if (mt.parameterCount() < 2 ||
+            !MethodHandles.Lookup.class.isAssignableFrom(mt.parameterType(0))) {
+            throw new BootstrapMethodError(
+                    "Invalid bootstrap method declared for resolving a dynamic constant: " + bootstrapMethod);
+        }
+
         // BSMI.invoke handles all type checking and exception translation.
         // If type is not a reference type, the JVM is expecting a boxed
         // version, and will manage unboxing on the other side.
--- a/src/java.base/share/classes/java/lang/invoke/ConstantGroup.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/ConstantGroup.java	Thu Apr 05 12:28:38 2018 -0400
@@ -90,9 +90,9 @@
  * a resolved from an unresolved constant in the group.
  * The most reliable sentinel is a privately created object,
  * or perhaps the {@code ConstantGroup} itself.
- * @since 1.10
+ *
+ * @since 11
  */
-// public
 interface ConstantGroup {
     /// Access
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/Intrinsics.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017, 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 java.lang.invoke;
+
+import java.lang.invoke.constant.ConstantRef;
+import java.lang.invoke.constant.DynamicCallSiteRef;
+
+/**
+ * Intrinsics
+ *
+ * @author Brian Goetz
+ */
+public final class Intrinsics {
+    /**
+     * Instructs the compiler to generate an {@code ldc} instruction for the given
+     * {@code Constable} instance. A compiler error will be issued if it cannot
+     * be proved that the argument is a constant
+     * @param <T> the type to which this constant pool entry resolves
+     * @param constant a constant to be ldc'ed
+     * @return the constant wrapped inside the {@code Constable} object
+     */
+    public static <T> T ldc(ConstantRef<T> constant) {
+        throw new UnsupportedOperationException("no reflective access");
+    }
+
+    /**
+     * Instructs the compiler to generate an {@code invokedynamic} instruction given
+     * a {@code BootstrapSpecifier} and arguments. The compiler should be able to
+     * prove that the given {@code BootstrapSpecifier} is a constant, in other case
+     * an error should be issued.
+     * @param indy the bootstrap specifier
+     * @param args the arguments
+     * @return the result of invoking the indy
+     * @throws java.lang.Throwable the targeted method can throw any exception
+     */
+    public static Object invokedynamic(DynamicCallSiteRef indy,
+                                       Object... args)
+            throws Throwable {
+        throw new UnsupportedOperationException("no reflective access");
+    }
+}
--- a/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java	Thu Apr 05 12:28:38 2018 -0400
@@ -324,6 +324,74 @@
     }
 
     /**
+     * Special-case case version of {@link LambdaMetafactory#metafactory(MethodHandles.Lookup, String, Class, MethodType, MethodHandle, MethodType)}
+     * that is restricted to non-capturing lambdas.  Rather than returning a
+     * {@link CallSite}, the function object itself is returned.
+     * Typically used as a <em>bootstrap method</em> for {@code Dynamic}
+     * constants, to support the <em>lambda expression</em> and <em>method
+     * reference expression</em> features of the Java Programming Language.
+     *
+     * <p>The function object returned is an instance of a class which
+     * implements the interface named by {@code functionalInterface},
+     * declares a method with the name given by {@code invokedName} and the
+     * signature given by {@code samMethodType}.  It may also override additional
+     * methods from {@code Object}.
+     *
+     * @param caller Represents a lookup context with the accessibility
+     *               privileges of the caller.  When used with {@code invokedynamic},
+     *               this is stacked automatically by the VM.
+     * @param invokedName The name of the method to implement.  When used with
+     *                    {@code Dynamic} constants, this is provided by the
+     *                    {@code NameAndType} of the {@code InvokeDynamic}
+     *                    structure and is stacked automatically by the VM.
+     * @param functionalInterface The functional interface the function object
+     *                            should implement.  When used with {@code invokedynamic},
+     *                            this is provided by the {@code NameAndType} of
+     *                            the {@code InvokeDynamic} structure and is
+     *                            stacked automatically by the VM. In the event
+     *                            that the implementation method is an instance
+     *                            method and this signature has any parameters,
+     *                            the first parameter in the invocation signature
+     *                            must correspond to the receiver.
+     * @param samMethodType Signature and return type of method to be implemented
+     *                      by the function object.
+     * @param implMethod A direct method handle describing the implementation
+     *                   method which should be called (with suitable adaptation
+     *                   of argument types, return types, and with captured
+     *                   arguments prepended to the invocation arguments) at
+     *                   invocation time.
+     * @param instantiatedMethodType The signature and return type that should
+     *                               be enforced dynamically at invocation time.
+     *                               This may be the same as {@code samMethodType},
+     *                               or may be a specialization of it.
+     * @return a CallSite whose target can be used to perform capture, generating
+     *         instances of the interface named by {@code invokedType}
+     * @throws LambdaConversionException If any of the linkage invariants
+     *                                   described {@link LambdaMetafactory above}
+     *                                   are violated
+     */
+    public static Object metafactory(MethodHandles.Lookup caller,
+                                     String invokedName,
+                                     Class<?> functionalInterface,
+                                     MethodType samMethodType,
+                                     MethodHandle implMethod,
+                                     MethodType instantiatedMethodType)
+            throws LambdaConversionException {
+        try {
+            return metafactory(caller, invokedName, MethodType.methodType(functionalInterface),
+                               samMethodType, implMethod, instantiatedMethodType).getTarget().invoke();
+        }
+        catch (LambdaConversionException | LinkageError e) {
+            throw e;
+        }
+        catch (Throwable e) {
+            throw new LambdaConversionException("Exception invoking lambda metafactory", e);
+        }
+    }
+
+    // @@@ Special case version of altMetafactory, supporting FLAG_METHODREF
+
+    /**
      * Facilitates the creation of simple "function objects" that implement one
      * or more interfaces by delegation to a provided {@link MethodHandle},
      * after appropriate type adaptation and partial evaluation of arguments.
@@ -497,4 +565,61 @@
         mf.validateMetafactoryArgs();
         return mf.buildCallSite();
     }
+
+    /**
+     * Special-case case version of {@link LambdaMetafactory#altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}.
+     * Rather than returning a {@link CallSite}, the function object itself is returned.
+     * Typically used as a <em>bootstrap method</em> for {@code Dynamic}
+     * constants, to support the <em>lambda expression</em> and <em>method
+     * reference expression</em> features of the Java Programming Language.
+     *
+     * <p>The function object returned is an instance of a class which
+     * implements the interface named by {@code functionalInterface},
+     * declares a method with the name given by {@code invokedName} and the
+     * signature given by {@code samMethodType}.  It may also override additional
+     * methods from {@code Object}.
+     *
+     * @param caller              Represents a lookup context with the accessibility
+     *                            privileges of the caller.  When used with {@code invokedynamic},
+     *                            this is stacked automatically by the VM.
+     * @param invokedName         The name of the method to implement.  When used with
+     *                            {@code Dynamic} constants, this is provided by the
+     *                            {@code NameAndType} of the {@code InvokeDynamic}
+     *                            structure and is stacked automatically by the VM.
+     * @param functionalInterface The functional interface the function object
+     *                            should implement.  When used with {@code invokedynamic},
+     *                            this is provided by the {@code NameAndType} of
+     *                            the {@code InvokeDynamic} structure and is
+     *                            stacked automatically by the VM. In the event
+     *                            that the implementation method is an instance
+     *                            method and this signature has any parameters,
+     *                            the first parameter in the invocation signature
+     *                            must correspond to the receiver.
+     * @param args                An {@code Object[]} array containing the required
+     *                            arguments {@code samMethodType}, {@code implMethod},
+     *                            {@code instantiatedMethodType}, {@code flags}, and any
+     *                            optional arguments, as described
+     *                            {@link #altMetafactory(MethodHandles.Lookup, String, functionalInterface, Object...)} above}
+     * @return a function object which is an instance of a class which implements the interface named
+     *         by {@code functionalInterface}
+     * @throws LambdaConversionException If any of the linkage invariants
+     *                                   described {@link LambdaMetafactory above}
+     *                                   are violated
+     */
+    public static Object altMetafactory(MethodHandles.Lookup caller,
+                                          String invokedName,
+                                          Class<?> functionalInterface,
+                                          Object... args)
+            throws LambdaConversionException {
+        try {
+            return altMetafactory(caller, invokedName,
+                    MethodType.methodType(functionalInterface), args).getTarget().invoke();
+        }
+        catch (LambdaConversionException | LinkageError e) {
+            throw e;
+        }
+        catch (Throwable e) {
+            throw new LambdaConversionException("Exception invoking lambda metafactory", e);
+        }
+    }
 }
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Thu Apr 05 12:28:38 2018 -0400
@@ -28,9 +28,15 @@
 
 import jdk.internal.HotSpotIntrinsicCandidate;
 
+import java.lang.invoke.constant.ClassRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.MethodHandleRef;
+import java.lang.invoke.constant.MethodTypeRef;
 import java.util.Arrays;
 import java.util.Objects;
+import java.util.Optional;
 
+import static java.lang.invoke.MethodHandleInfo.*;
 import static java.lang.invoke.MethodHandleStatics.*;
 
 /**
@@ -425,7 +431,7 @@
  * @author John Rose, JSR 292 EG
  * @since 1.7
  */
-public abstract class MethodHandle {
+public abstract class MethodHandle implements Constable<MethodHandle> {
 
     /**
      * Internal marker interface which distinguishes (to the Java compiler)
@@ -1508,6 +1514,46 @@
         return bindArgumentL(0, x);
     }
 
+    @Override
+    public Optional<MethodHandleRef> toConstantRef(MethodHandles.Lookup lookup) {
+        MethodHandleInfo info;
+        ClassRef owner;
+        String name;
+        MethodTypeRef type;
+        try {
+            info = lookup.revealDirect(this);
+            owner = info.getDeclaringClass().toConstantRef(lookup).orElseThrow();
+            type = info.getMethodType().toConstantRef(lookup).orElseThrow();
+            name = info.getName();
+        }
+        catch (Exception e) {
+            return Optional.empty();
+        }
+
+        switch (info.getReferenceKind()) {
+            case REF_getField:
+                return Optional.of(MethodHandleRef.ofField(MethodHandleRef.Kind.GETTER, owner, name, type.returnType()));
+            case REF_putField:
+                return Optional.of(MethodHandleRef.ofField(MethodHandleRef.Kind.SETTER, owner, name, type.parameterType(0)));
+            case REF_getStatic:
+                return Optional.of(MethodHandleRef.ofField(MethodHandleRef.Kind.STATIC_GETTER, owner, name, type.returnType()));
+            case REF_putStatic:
+                return Optional.of(MethodHandleRef.ofField(MethodHandleRef.Kind.STATIC_SETTER, owner, name, type.parameterType(0)));
+            case REF_invokeVirtual:
+                return Optional.of(MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, owner, name, type));
+            case REF_invokeStatic:
+                return Optional.of(MethodHandleRef.of(MethodHandleRef.Kind.STATIC, owner, name, type));
+            case REF_invokeSpecial:
+                return Optional.of(MethodHandleRef.of(MethodHandleRef.Kind.SPECIAL, owner, name, type));
+            case REF_invokeInterface:
+                return Optional.of(MethodHandleRef.of(MethodHandleRef.Kind.INTERFACE_VIRTUAL, owner, name, type));
+            case REF_newInvokeSpecial:
+                return Optional.of(MethodHandleRef.of(MethodHandleRef.Kind.CONSTRUCTOR, owner, name, type));
+            default:
+                return Optional.empty();
+        }
+    }
+
     /**
      * Returns a string representation of the method handle,
      * starting with the string {@code "MethodHandle"} and
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Thu Apr 05 12:28:38 2018 -0400
@@ -364,8 +364,7 @@
      * replaced with currently commented out code.
      */
     static boolean isPullModeBSM(MethodHandle bsm) {
-        return false;
-//        return bsm.type().parameterCount() == 2 && !bsm.isVarargsCollector();
+        return bsm.type().parameterCount() == 2 && !bsm.isVarargsCollector();
     }
 
     /**
--- a/src/java.base/share/classes/java/lang/invoke/MethodType.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java	Thu Apr 05 12:28:38 2018 -0400
@@ -30,13 +30,20 @@
 import java.lang.ref.WeakReference;
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
+import java.lang.invoke.constant.ClassRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.MethodTypeRef;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.NoSuchElementException;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.StringJoiner;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Stream;
+
 import sun.invoke.util.BytecodeDescriptor;
 import static java.lang.invoke.MethodHandleStatics.*;
 import sun.invoke.util.VerifyType;
@@ -91,7 +98,7 @@
  * @since 1.7
  */
 public final
-class MethodType implements java.io.Serializable {
+class MethodType implements Constable<MethodType>, java.io.Serializable {
     private static final long serialVersionUID = 292L;  // {rtype, {ptype...}}
 
     // The rtype and ptypes fields define the structural identity of the method type:
@@ -1163,6 +1170,19 @@
         return BytecodeDescriptor.unparse(cls);
     }
 
+    @Override
+    public Optional<MethodTypeRef> toConstantRef(MethodHandles.Lookup lookup) {
+        try {
+            return Optional.of(MethodTypeRef.of(returnType().toConstantRef(lookup).orElseThrow(),
+                                                Stream.of(parameterArray())
+                                                      .map(p -> p.toConstantRef(lookup).orElseThrow())
+                                                      .toArray(ClassRef[]::new)));
+        }
+        catch (NoSuchElementException e) {
+            return Optional.empty();
+        }
+    }
+
     /// Serialization.
 
     /**
--- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Thu Apr 05 12:28:38 2018 -0400
@@ -30,14 +30,17 @@
 import jdk.internal.vm.annotation.ForceInline;
 import jdk.internal.vm.annotation.Stable;
 
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.VarHandleRef;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
 import java.util.function.BiFunction;
 import java.util.function.Function;
 
 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
-import static java.lang.invoke.MethodHandleStatics.newInternalError;
 
 /**
  * A VarHandle is a dynamically strongly typed reference to a variable, or to a
@@ -437,7 +440,7 @@
  * @see MethodType
  * @since 9
  */
-public abstract class VarHandle {
+public abstract class VarHandle implements Constable<VarHandle> {
     final VarForm vform;
 
     VarHandle(VarForm vform) {
@@ -1855,6 +1858,37 @@
         }
     }
 
+    @Override
+    public final boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        VarHandle that = (VarHandle) o;
+        return accessModeType(AccessMode.GET).equals(that.accessModeType(AccessMode.GET)) &&
+               internalEquals(that);
+    }
+
+    boolean internalEquals(VarHandle vh) {
+        return true;
+    }
+
+    @Override
+    public final int hashCode() {
+        return 31 * accessModeType(AccessMode.GET).hashCode() + internalHashCode();
+    }
+
+    int internalHashCode() {
+        return 0;
+    }
+
+    @Override
+    public final String toString() {
+        // @@@ defer to concrete type for additional description
+        return String.format("VarHandle[varType=%s, cooordType=%s]",
+                             varType().getName(),
+                             coordinateTypes());
+    }
+
     /**
      * Returns the variable type of variables referenced by this VarHandle.
      *
@@ -1949,6 +1983,12 @@
         }
     }
 
+    @Override
+    public Optional<VarHandleRef> toConstantRef(MethodHandles.Lookup lookup) {
+        // partial function for field and array only
+        return Optional.empty();
+    }
+
     @Stable
     TypesAndInvokers typesAndInvokers;
 
--- a/src/java.base/share/classes/java/lang/invoke/VarHandles.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandles.java	Thu Apr 05 12:28:38 2018 -0400
@@ -25,6 +25,9 @@
 
 package java.lang.invoke;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
 
 final class VarHandles {
@@ -144,6 +147,38 @@
         }
     }
 
+    // Required by instance field handles
+    static Field getFieldFromRecieverAndOffset(Class<?> receiverType,
+                                               long offset,
+                                               Class<?> fieldType) {
+        for (Field f : receiverType.getDeclaredFields()) {
+            if (Modifier.isStatic(f.getModifiers())) continue;
+
+            if (offset == UNSAFE.objectFieldOffset(f)) {
+                assert f.getType() == fieldType;
+                return f;
+            }
+        }
+        throw new InternalError("Field not found at offset");
+    }
+
+    // Required by instance static field handles
+    static Field getStaticFieldFromBaseAndOffset(Object base,
+                                                 long offset,
+                                                 Class<?> fieldType) {
+        // @@@ This is a little fragile assuming the base is the class
+        Class<?> receiverType = (Class<?>) base;
+        for (Field f : receiverType.getDeclaredFields()) {
+            if (!Modifier.isStatic(f.getModifiers())) continue;
+
+            if (offset == UNSAFE.staticFieldOffset(f)) {
+                assert f.getType() == fieldType;
+                return f;
+            }
+        }
+        throw new InternalError("Static field not found at offset");
+    }
+
     static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
         if (!arrayClass.isArray())
             throw new IllegalArgumentException("not an array: " + arrayClass);
--- a/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template	Thu Apr 05 12:28:38 2018 -0400
@@ -27,7 +27,9 @@
 import jdk.internal.util.Preconditions;
 import jdk.internal.vm.annotation.ForceInline;
 
+import java.lang.invoke.constant.VarHandleRef;
 import java.util.Objects;
+import java.util.Optional;
 
 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
 
@@ -61,6 +63,29 @@
             return accessMode.at.accessModeType(receiverType, {#if[Object]?fieldType:$type$.class});
         }
 
+        @Override
+        final boolean internalEquals(VarHandle vh) {
+            FieldInstanceReadOnly that = (FieldInstanceReadOnly) vh;
+            return fieldOffset == that.fieldOffset;
+        }
+
+        @Override
+        final int internalHashCode() {
+            return Long.hashCode(fieldOffset);
+        }
+
+        @Override
+        public Optional<VarHandleRef> toConstantRef(MethodHandles.Lookup lookup) {
+            var receiverTypeRef = receiverType.toConstantRef(lookup);
+            var fieldTypeRef = {#if[Object]?fieldType:$type$.class}.toConstantRef(lookup);
+            if (!receiverTypeRef.isPresent() || !fieldTypeRef.isPresent())
+                return Optional.empty();
+
+            String name = VarHandles.getFieldFromRecieverAndOffset(
+                receiverType, fieldOffset, {#if[Object]?fieldType:$type$.class}).getName();
+            return Optional.of(VarHandleRef.ofField(receiverTypeRef.get(), name, fieldTypeRef.get()));
+        }
+
         @ForceInline
         static $type$ get(FieldInstanceReadOnly handle, Object holder) {
             return UNSAFE.get$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
@@ -324,6 +349,31 @@
         }
 
         @Override
+        final boolean internalEquals(VarHandle vh) {
+            FieldStaticReadOnly that = (FieldStaticReadOnly) vh;
+            return base == that.base && fieldOffset == that.fieldOffset;
+        }
+
+        @Override
+        final int internalHashCode() {
+            return 31 * Long.hashCode(fieldOffset) + base.hashCode();
+        }
+
+        @Override
+        public Optional<VarHandleRef> toConstantRef(MethodHandles.Lookup lookup) {
+            var fieldTypeRef = {#if[Object]?fieldType:$type$.class}.toConstantRef(lookup);
+            if (!fieldTypeRef.isPresent())
+                return Optional.empty();
+
+            var staticField = VarHandles.getStaticFieldFromBaseAndOffset(
+                base, fieldOffset, {#if[Object]?fieldType:$type$.class});
+            var receiverTypeRef = staticField.getDeclaringClass().toConstantRef(lookup);
+            if (!receiverTypeRef.isPresent())
+                return Optional.empty();
+            return Optional.of(VarHandleRef.ofStaticField(receiverTypeRef.get(), staticField.getName(), fieldTypeRef.get()));
+        }
+
+        @Override
         final MethodType accessModeTypeUncached(AccessMode accessMode) {
             return accessMode.at.accessModeType(null, {#if[Object]?fieldType:$type$.class});
         }
@@ -588,6 +638,15 @@
         }
 
         @Override
+        public Optional<VarHandleRef> toConstantRef(MethodHandles.Lookup lookup) {
+            var arrayTypeRef = {#if[Object]?arrayType:$type$[].class}.toConstantRef(lookup);
+            if (!arrayTypeRef.isPresent())
+                return Optional.empty();
+
+            return Optional.of(VarHandleRef.ofArray(arrayTypeRef.get()));
+        }
+
+        @Override
         final MethodType accessModeTypeUncached(AccessMode accessMode) {
             return accessMode.at.accessModeType({#if[Object]?arrayType:$type$[].class}, {#if[Object]?arrayType.getComponentType():$type$.class}, int.class);
         }
--- a/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template	Thu Apr 05 12:28:38 2018 -0400
@@ -67,6 +67,17 @@
             super(form);
             this.be = be;
         }
+
+        @Override
+        final boolean internalEquals(VarHandle vh) {
+            ByteArrayViewVarHandle that = (ByteArrayViewVarHandle) vh;
+            return be == that.be;
+        }
+
+        @Override
+        final int internalHashCode() {
+            return Boolean.hashCode(be);
+        }
     }
 
     static final class ArrayHandle extends ByteArrayViewVarHandle {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/AsTypeMethodHandleRef.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Optional;
+
+import static java.lang.invoke.constant.ConstantRefs.BSM_INVOKE;
+import static java.lang.invoke.constant.ConstantRefs.CR_MethodHandle;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * AsTypeMethodHandleRef
+ *
+ * @author Brian Goetz
+ */
+final class AsTypeMethodHandleRef extends DynamicConstantRef<MethodHandle>
+        implements MethodHandleRef {
+
+    private final MethodHandleRef underlying;
+    private final MethodTypeRef type;
+
+    AsTypeMethodHandleRef(MethodHandleRef underlying, MethodTypeRef type) {
+        super(BSM_INVOKE, "_", CR_MethodHandle,
+              ConstantRefs.MHR_METHODHANDLE_ASTYPE, underlying, type);
+        // Any type checking we can do?
+        this.underlying = requireNonNull(underlying);
+        this.type = requireNonNull(type);
+    }
+
+    @Override
+    @Foldable
+    public MethodTypeRef methodType() {
+        return type;
+    }
+
+    @Override
+    public MethodHandle resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+        MethodHandle handle = underlying.resolveConstantRef(lookup);
+        MethodType methodType = type.resolveConstantRef(lookup);
+        return handle.asType(methodType);
+    }
+
+    @Override
+    public Optional<? extends ConstantRef<? super ConstantRef<MethodHandle>>> toConstantRef(MethodHandles.Lookup lookup) {
+        return DynamicConstantRef.symbolizeHelper(lookup, ConstantRefs.MHR_METHODHANDLEREF_ASTYPE, ConstantRefs.CR_MethodHandleRef,
+                                                  underlying, type);
+    }
+
+    @Override
+    public String toString() {
+        return underlying.toString() + String.format(".asType%s", type.simpleDescriptor());
+    }
+
+    // @@@ canonical?
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ClassRef.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.util.stream.Stream;
+
+import sun.invoke.util.Wrapper;
+
+import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.joining;
+
+/**
+ * A nominal reference for a {@link Class}.
+ */
+public interface ClassRef extends ConstantRef<Class<?>>, Constable<ConstantRef<Class<?>>> {
+    /**
+     * Create a {@linkplain ClassRef} from a fully-qualified, dot-separated
+     * class name
+     *
+     * @param name the fully qualified class name, dot-separated
+     * @return a {@linkplain ClassRef} describing the desired class
+     * @throws IllegalArgumentException if the name string does not
+     * describe a valid class name
+     */
+    @Foldable
+    static ClassRef of(String name) {
+        return ClassRef.ofDescriptor("L" + name.replace('.', '/') + ";");
+    }
+
+    /**
+     * Create a {@linkplain ClassRef} from a dot-separated package name and an
+     * unqualified class name
+     *
+     * @param packageName the package name, dot-separated
+     * @param className the unqualified class name
+     * @return a {@linkplain ClassRef} describing the desired class
+     * @throws IllegalArgumentException if the package name or class name are
+     * not in the correct format
+     */
+    @Foldable
+    static ClassRef of(String packageName, String className) {
+        if (className.contains("."))
+            throw new IllegalArgumentException(className);
+        return ofDescriptor("L" + packageName.replace('.', '/')
+                            + (packageName.length() > 0 ? "/" : "")
+                            + className + ";");
+    }
+
+    /**
+     * Create a {@linkplain ClassRef} from a descriptor string for a class
+     *
+     * @param descriptor the descriptor string
+     * @return a {@linkplain ClassRef} describing the desired class
+     * @throws NullPointerException if the descriptor string is null
+     * @throws IllegalArgumentException if the descriptor string is not
+     * a valid class descriptor
+     */
+    @Foldable
+    static ClassRef ofDescriptor(String descriptor) {
+        requireNonNull(descriptor);
+        return (descriptor.length() == 1)
+               ? new PrimitiveClassRef(descriptor)
+               : new ConstantClassRef(descriptor);
+    }
+
+    /**
+     * Create a {@linkplain ClassRef} describing an array of the type
+     * described by this {@linkplain ClassRef}
+     *
+     * @return a {@linkplain ClassRef} describing the array type
+     */
+    @Foldable
+    default ClassRef array() {
+        return ClassRef.ofDescriptor("[" + descriptorString());
+    }
+
+    /**
+     * Create a {@linkplain ClassRef} describing an inner class of the
+     * non-array reference type described by this {@linkplain ClassRef}
+     * @param innerName the name of the inner class
+     * @return a {@linkplain ClassRef} describing the inner class
+     */
+    @Foldable
+    default ClassRef inner(String innerName) {
+        if (!descriptorString().startsWith("L"))
+            throw new IllegalStateException("Outer class is not a non-array reference type");
+        return ClassRef.ofDescriptor(descriptorString().substring(0, descriptorString().length() - 1) + "$" + innerName + ";");
+    }
+
+    /**
+     * Create a {@linkplain ClassRef} describing a multiply nested inner class of the
+     * non-array reference type described by this {@linkplain ClassRef}
+     *
+     * @param firstInnerName the name of the first level of inner class
+     * @param moreInnerNames the name(s) of the remaining levels of inner class
+     * @return a {@linkplain ClassRef} describing the inner class
+     */
+    @Foldable
+    default ClassRef inner(String firstInnerName, String... moreInnerNames) {
+        if (!descriptorString().startsWith("L"))
+            throw new IllegalStateException("Outer class is not a non-array reference type");
+        return moreInnerNames.length == 0
+               ? inner(firstInnerName)
+               : ClassRef.ofDescriptor(descriptorString().substring(0, descriptorString().length() - 1) + "$" + firstInnerName
+                                       + Stream.of(moreInnerNames).collect(joining("$", "$", "")) + ";");
+    }
+
+    /**
+     * Returns whether this {@linkplain ClassRef} describes an array type
+     *
+     * @return whether this {@linkplain ClassRef} describes an array type
+     */
+    default boolean isArray() {
+        return descriptorString().startsWith("[");
+    }
+
+    /**
+     * Returns whether this {@linkplain ClassRef} describes a primitive type
+     *
+     * @return whether this {@linkplain ClassRef} describes a primitive type
+     */
+    default boolean isPrimitive() {
+        return descriptorString().length() == 1;
+    }
+
+    /**
+     * Returns the component type of this {@linkplain ClassRef}, if it describes
+     * an array type
+     *
+     * @return a {@linkplain ClassRef} describing the component type
+     * @throws IllegalStateException if this {@linkplain ClassRef} does not
+     * describe an array type
+     */
+    @Foldable
+    default ClassRef componentType() {
+        if (!isArray())
+            throw new IllegalStateException();
+        return ClassRef.ofDescriptor(descriptorString().substring(1));
+    }
+
+    /**
+     * Returns a human-readable name for the type described by this descriptor
+     *
+     * @return a human-readable name for the type described by this descriptor
+     */
+    default String simpleName() {
+        if (descriptorString().length() == 1)
+            return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveSimpleName();
+        else if (descriptorString().startsWith("L")) {
+            return descriptorString().substring(Math.max(1, descriptorString().lastIndexOf('/') + 1),
+                                                descriptorString().length() - 1);
+        }
+        else if (descriptorString().startsWith(("["))) {
+            int depth=arrayDepth();
+            ClassRef c = this;
+            for (int i=0; i<depth; i++)
+                c = c.componentType();
+            String name = c.simpleName();
+            StringBuilder sb = new StringBuilder(name.length() + 2*depth);
+            sb.append(name);
+            for (int i=0; i<depth; i++)
+                sb.append("[]");
+            return sb.toString();
+        }
+        else
+            throw new IllegalStateException(descriptorString());
+    }
+
+    private int arrayDepth() {
+        int depth = 0;
+        while (descriptorString().charAt(depth) == '[')
+            depth++;
+        return depth;
+    }
+
+    /**
+     * Return the type descriptor string
+     * @return the type descriptor string
+     */
+    @Foldable
+    String descriptorString();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/Constable.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+import java.util.Optional;
+
+/**
+ * Represents a type which is <em>constable</em>.  A constable type is one whose
+ * values can be represented in the constant pool of a Java classfile.
+ *
+ * <p>The basic constable types are types whose values have a native representation
+ * in the constant pool: ({@link String}, {@link Integer}, {@link Long}, {@link Float},
+ * {@link Double}, {@link Class}, {@link MethodType}, and {@link MethodHandle}).
+ *
+ * <p>Other reference types can be constable if their instances can describe
+ * themselves in nominal form as a {@link ConstantRef}. Examples in the Java SE
+ * Platform API are types that support Java language features, such as {@link Enum},
+ * and runtime support classes, such as {@link VarHandle}.
+ *
+ * <p>The nominal form of an instance of a constable type is obtained via
+ * {@link #toConstantRef(MethodHandles.Lookup)}. A {@linkplain Constable} need
+ * not be able to (or may choose not to) render all its instances in the form of
+ * a {@link ConstantRef}; this method returns an {@link Optional} to indicate
+ * whether a nominal reference could be created for a particular instance. (For
+ * example, {@link MethodHandle} will produce nominal references for direct
+ * method handles, but not necessarily for method handles resulting from method
+ * handle combinators such as {@link MethodHandle#asType(MethodType)}.)
+ *
+ * @param <T> the type of the class implementing {@linkplain Constable}
+ */
+public interface Constable<T> {
+    /**
+     * Return a nominal reference for this instance, if one can be
+     * constructed.
+     *
+     * @implSpec This method behaves as if {@link #toConstantRef(MethodHandles.Lookup)}
+     * were called with a lookup parameter of {@code MethodHandles.publicLookup()}.
+     *
+     * @return An {@link Optional} describing the resulting nominal reference,
+     * or an empty {@link Optional} if one cannot be constructed
+     */
+    default Optional<? extends ConstantRef<? super T>> toConstantRef() {
+        return toConstantRef(MethodHandles.publicLookup());
+    }
+
+    /**
+     * Return a nominal reference for this instance, if one can be
+     * constructed.  This object (and any classes needed to construct its
+     * nominal description) must be accessible from the class described by the
+     * {@code lookup} parameter.
+     *
+     * @param lookup A {@link MethodHandles.Lookup} to be used to perform
+     *               access control determinations
+     * @return An {@link Optional} describing the resulting nominal reference,
+     * or an empty {@link Optional} if one cannot be constructed or this object
+     * is not accessible from {@code lookup}
+     */
+    Optional<? extends ConstantRef<? super T>> toConstantRef(MethodHandles.Lookup lookup);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantClassRef.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Array;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.regex.Pattern;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_ClassRef;
+
+/**
+ * ConstantClassRef
+ *
+ * @author Brian Goetz
+ */
+public class ConstantClassRef implements ClassRef {
+    private static final Pattern TYPE_DESC = Pattern.compile("(\\[*)(V|I|J|S|B|C|F|D|Z|L[^/.\\[;][^.\\[;]*;)");
+
+    private final String descriptor;
+
+    /**
+     * Create a {@linkplain ClassRef} from a descriptor string for a reference
+     * type
+     *
+     * @param descriptor the descriptor string
+     * @throws IllegalArgumentException if the descriptor string does not
+     * describe a valid reference type name
+     */
+    ConstantClassRef(String descriptor) {
+        // @@@ Replace validation with a lower-overhead mechanism than regex
+        // Follow the trail from MethodType.fromMethodDescriptorString to
+        // parsing code in sun/invoke/util/BytecodeDescriptor.java which could
+        // be extracted and/or shared
+        if (descriptor == null
+            || !TYPE_DESC.matcher(descriptor).matches())
+            throw new IllegalArgumentException(String.format("%s is not a valid type descriptor", descriptor));
+        this.descriptor = descriptor;
+    }
+
+    @Override
+    public String descriptorString() {
+        return descriptor;
+    }
+
+    private int arrayDepth() {
+        int depth = 0;
+        while (descriptorString().charAt(depth) == '[')
+            depth++;
+        return depth;
+    }
+
+    @Override
+    public Class<?> resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+        ClassRef c = this;
+        int depth = arrayDepth();
+        for (int i=0; i<depth; i++)
+            c = c.componentType();
+
+        if (c.descriptorString().length() == 1)
+            return Class.forName(descriptorString(), true, lookup.lookupClass().getClassLoader());
+        else {
+            Class<?> clazz = Class.forName(c.descriptorString().substring(1, c.descriptorString().length() - 1)
+                                            .replace('/', '.'), true, lookup.lookupClass().getClassLoader());
+            for (int i = 0; i < depth; i++)
+                clazz = Array.newInstance(clazz, 0).getClass();
+            return clazz;
+        }
+    }
+
+    @Override
+    public Optional<? extends ConstantRef<? super ConstantRef<Class<?>>>> toConstantRef(MethodHandles.Lookup lookup) {
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_CLASSREF, CR_ClassRef).withArgs(descriptor));
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ClassRef constant = (ClassRef) o;
+        return Objects.equals(descriptor, constant.descriptorString());
+    }
+
+    @Override
+    public int hashCode() {
+        return descriptor != null ? descriptor.hashCode() : 0;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("ClassRef[%s]", simpleName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodHandleRef.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Objects;
+import java.util.Optional;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_MethodTypeRef;
+import static java.lang.invoke.constant.MethodHandleRef.Kind.CONSTRUCTOR;
+import static java.lang.invoke.constant.ConstantRefs.CR_MethodHandleRef;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * DirectMethodHandleRef
+ *
+ * @author Brian Goetz
+ */
+public class ConstantMethodHandleRef implements MethodHandleRef {
+
+    private final Kind kind;
+    private final ClassRef owner;
+    private final String name;
+    private final MethodTypeRef type;
+
+    /**
+     * Construct a {@linkplain ConstantMethodHandleRef} from a kind, owner, name, and type
+     * @param kind the kind of the method handle
+     * @param owner the declaring class for the method
+     * @param name the name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
+     * @param type the type of the method
+     * @throws NullPointerException if any non-ignored argument is null
+     * @throws IllegalArgumentException if {@code kind} describes a field accessor,
+     * and {@code type} is not consistent with that kind of field accessor
+     */
+    ConstantMethodHandleRef(Kind kind, ClassRef owner, String name, MethodTypeRef type) {
+        super();
+        if (kind == CONSTRUCTOR)
+            name = "<init>";
+
+        requireNonNull(kind);
+        requireNonNull(owner);
+        requireNonNull(name);
+        requireNonNull(type);
+
+        switch (kind) {
+            case CONSTRUCTOR: validateConstructor(type); break;
+            case GETTER: validateFieldType(type, false, true); break;
+            case SETTER: validateFieldType(type, true, true); break;
+            case STATIC_GETTER: validateFieldType(type, false, false); break;
+            case STATIC_SETTER: validateFieldType(type, true, false); break;
+        }
+
+        this.kind = kind;
+        this.owner = owner;
+        this.name = name;
+        this.type = type;
+    }
+
+    private static void validateFieldType(MethodTypeRef type, boolean isSetter, boolean isVirtual) {
+        boolean isVoid = type.returnType().descriptorString().equals("V");
+        int expectedParams = (isSetter ? 1 : 0) + (isVirtual ? 1 : 0);
+        if (isVoid != isSetter
+            || type.parameterCount() != expectedParams
+            || (isVirtual && type.parameterType(0).isPrimitive())) {
+            String expectedType = String.format("(%s%s)%s", (isVirtual ? "R" : ""),
+                                                (isSetter ? "T" : ""), (isSetter ? "V" : "T"));
+            throw new IllegalArgumentException(String.format("Expected type of %s for getter, found %s", expectedType, type));
+        }
+    }
+
+    private static void validateConstructor(MethodTypeRef type) {
+        if (!type.returnType().descriptorString().equals("V")) {
+            throw new IllegalArgumentException(String.format("Expected type of (T)V for constructor, found %s", type));
+        }
+    }
+
+    /**
+     * Return the {@code refKind} of the method handle described by this nominal reference,
+     * as defined by {@link MethodHandleInfo}
+     * @return the reference kind
+     */
+    @Foldable
+    public int refKind() { return kind.refKind; }
+
+    /**
+     * Return the {@code kind} of the method handle described by this nominal reference
+     * @return the {@link Kind}
+     */
+    @Foldable
+    public Kind kind() { return kind; }
+
+    /**
+     * Return the class which declares the method or field described by
+     * this nominal reference
+     *
+     * @return the class in which the method or field is declared
+     */
+    @Foldable
+    public ClassRef owner() {
+        return owner;
+    }
+
+    /**
+     * Return the name of the method described by this nominal reference
+     *
+     * @return the name of the method
+     */
+    @Foldable
+    public String methodName() {
+        return name;
+    }
+
+    /**
+     * Return the type of the method described by this nominal reference
+     * @return the method type
+     */
+    @Foldable
+    public MethodTypeRef methodType() {
+        return type;
+    }
+
+    public MethodHandle resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+        Class<?> resolvedOwner = owner.resolveConstantRef(lookup);
+        MethodType resolvedType = this.type.resolveConstantRef(lookup);
+        switch (kind) {
+            case STATIC:
+                return lookup.findStatic(resolvedOwner, name, resolvedType);
+            case INTERFACE_VIRTUAL:
+            case VIRTUAL:
+                return lookup.findVirtual(resolvedOwner, name, resolvedType);
+            case SPECIAL:
+                return lookup.findSpecial(resolvedOwner, name, resolvedType, lookup.lookupClass());
+            case CONSTRUCTOR:
+                return lookup.findConstructor(resolvedOwner, resolvedType);
+            case GETTER:
+                return lookup.findGetter(resolvedOwner, name, resolvedType.returnType());
+            case STATIC_GETTER:
+                return lookup.findStaticGetter(resolvedOwner, name, resolvedType.returnType());
+            case SETTER:
+                return lookup.findSetter(resolvedOwner, name, resolvedType.parameterType(1));
+            case STATIC_SETTER:
+                return lookup.findStaticSetter(resolvedOwner, name, resolvedType.parameterType(0));
+            default:
+                throw new IllegalStateException(kind.name());
+        }
+    }
+
+    @Override
+    public Optional<? extends ConstantRef<? super ConstantRef<MethodHandle>>> toConstantRef(MethodHandles.Lookup lookup) {
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_METHODHANDLEREF, CR_MethodHandleRef)
+                                             .withArgs(kind.toString(), owner.descriptorString(), name, type.descriptorString()));
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ConstantMethodHandleRef ref = (ConstantMethodHandleRef) o;
+        return kind == ref.kind &&
+               Objects.equals(owner, ref.owner) &&
+               Objects.equals(name, ref.name) &&
+               Objects.equals(type, ref.type);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(kind, owner, name, type);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("MethodHandleRef[%s/%s::%s%s]", kind, owner.simpleName(), name, type.simpleDescriptor());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodTypeRef.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_ClassRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_MethodTypeRef;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * ConstantMethodTypeRef
+ *
+ * @author Brian Goetz
+ */
+public final class ConstantMethodTypeRef implements MethodTypeRef {
+
+    private static final Pattern TYPE_DESC = Pattern.compile("(\\[*)(V|I|J|S|B|C|F|D|Z|L[^/.\\[;][^.\\[;]*;)");
+    private static final Pattern pattern = Pattern.compile("\\((.*)\\)(.*)");
+
+    private final ClassRef returnType;
+    private final ClassRef[] argTypes;
+
+    /**
+     * Construct a {@linkplain MethodTypeRef} with the specified return type
+     * and parameter types
+     *
+     * @param returnType a {@link ClassRef} describing the return type
+     * @param argTypes {@link ClassRef}s describing the parameter types
+     */
+    ConstantMethodTypeRef(ClassRef returnType, ClassRef[] argTypes) {
+        this.returnType = requireNonNull(returnType);
+        this.argTypes = requireNonNull(argTypes);
+
+        for (ClassRef cr : argTypes)
+            if (cr.isPrimitive() && cr.descriptorString().equals("V"))
+                throw new IllegalArgumentException("Void parameters not permitted");
+    }
+
+    /**
+     * Create a {@linkplain ConstantMethodTypeRef} from a method descriptor string
+     *
+     * @param descriptor the method descriptor string
+     * @return a {@linkplain ConstantMethodTypeRef} describing the desired method type
+     * @throws IllegalArgumentException if the descriptor string is not a valid
+     * method descriptor
+     */
+    @Foldable
+    static MethodTypeRef ofDescriptor(String descriptor) {
+        // @@@ Replace validation with a lower-overhead mechanism than regex
+        // Follow the trail from MethodType.fromMethodDescriptorString to
+        // parsing code in sun/invoke/util/BytecodeDescriptor.java which could
+        // be extracted and/or shared
+        Matcher matcher = pattern.matcher(descriptor);
+        if (!matcher.matches())
+            throw new IllegalArgumentException(String.format("%s is not a valid method descriptor", descriptor));
+        String paramTypes = matcher.group(1);
+        String returnType = matcher.group(2);
+        if (!TYPE_DESC.matcher(returnType).matches())
+            throw new IllegalArgumentException(String.format("Invalid return type %s", returnType));
+        List<String> params = new ArrayList<>();
+        matcher = TYPE_DESC.matcher(paramTypes);
+        while (matcher.regionStart() < paramTypes.length()) {
+            if (matcher.lookingAt()) {
+                params.add(matcher.group());
+                matcher.region(matcher.end(), matcher.regionEnd());
+            }
+            else
+                throw new IllegalArgumentException(String.format("Invalid parameter type: %s", paramTypes.substring(matcher.regionStart(), matcher.regionEnd())));
+        }
+        return new ConstantMethodTypeRef(ClassRef.ofDescriptor(returnType), params.stream().map(ClassRef::ofDescriptor).toArray(ClassRef[]::new));
+    }
+
+    @Foldable
+    @Override
+    public ClassRef returnType() {
+        return returnType;
+    }
+
+    @Foldable
+    @Override
+    public int parameterCount() {
+        return argTypes.length;
+    }
+
+    @Foldable
+    @Override
+    public ClassRef parameterType(int index) {
+        return argTypes[index];
+    }
+
+    @Override
+    public List<ClassRef> parameterList() {
+        return List.of(argTypes);
+    }
+
+    @Override
+    public ClassRef[] parameterArray() {
+        return argTypes.clone();
+    }
+
+    @Foldable
+    @Override
+    public MethodTypeRef changeReturnType(ClassRef returnType) {
+        return MethodTypeRef.of(returnType, argTypes);
+    }
+
+    @Foldable
+    @Override
+    public MethodTypeRef changeParameterType(int index, ClassRef paramType) {
+        ClassRef[] newArgs = argTypes.clone();
+        newArgs[index] = paramType;
+        return MethodTypeRef.of(returnType, newArgs);
+    }
+
+    @Foldable
+    @Override
+    public MethodTypeRef dropParameterTypes(int start, int end) {
+        if (start < 0 || start >= argTypes.length || end < 0 || end > argTypes.length)
+            throw new IndexOutOfBoundsException();
+        else if (start > end)
+            throw new IllegalArgumentException(String.format("Range (%d, %d) not valid for size %d", start, end, argTypes.length));
+        ClassRef[] newArgs = new ClassRef[argTypes.length - (end - start)];
+        System.arraycopy(argTypes, 0, newArgs, 0, start);
+        System.arraycopy(argTypes, end, newArgs, start, argTypes.length - end);
+        return MethodTypeRef.of(returnType, newArgs);
+    }
+
+    @Foldable
+    @Override
+    public MethodTypeRef insertParameterTypes(int pos, ClassRef... paramTypes) {
+        if (pos < 0 || pos > argTypes.length)
+            throw new IndexOutOfBoundsException(pos);
+        ClassRef[] newArgs = new ClassRef[argTypes.length + paramTypes.length];
+        System.arraycopy(argTypes, 0, newArgs, 0, pos);
+        System.arraycopy(paramTypes, 0, newArgs, pos, paramTypes.length);
+        System.arraycopy(argTypes, pos, newArgs, pos+paramTypes.length, argTypes.length - pos);
+        return MethodTypeRef.of(returnType, newArgs);
+    }
+
+    @Override
+    public MethodType resolveConstantRef(MethodHandles.Lookup lookup) {
+        return MethodType.fromMethodDescriptorString(descriptorString(), lookup.lookupClass().getClassLoader());
+    }
+
+    @Override
+    public Optional<? extends ConstantRef<? super ConstantRef<MethodType>>> toConstantRef(MethodHandles.Lookup lookup) {
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_METHODTYPEREF, CR_MethodTypeRef).withArgs(descriptorString()));
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ConstantMethodTypeRef constant = (ConstantMethodTypeRef) o;
+
+        return returnType.equals(constant.returnType)
+               && Arrays.equals(argTypes, constant.argTypes);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = returnType.hashCode();
+        result = 31 * result + Arrays.hashCode(argTypes);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("MethodTypeRef[%s]", simpleDescriptor());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantRef.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import java.lang.invoke.Intrinsics;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+/**
+ * A nominal reference to a loadable constant value, as defined in JVMS 4.4.
+ * Such a nominal reference can be stored in the constant pool of a classfile
+ * and resolved to yield the constant value itself.
+ *
+ * <p>Static constants that are expressible natively in the constant pool ({@link String},
+ * {@link Integer}, {@link Long}, {@link Float}, and {@link Double}) implement
+ * {@link ConstantRef}, serve as nominal references for themselves.
+ * Native linkable constants ({@link Class}, {@link MethodType}, and
+ * {@link MethodHandle}) have counterpart {@linkplain ConstantRef} types:
+ * {@link ClassRef}, {@link MethodTypeRef}, and {@link MethodHandleRef}.
+ * Other constants are represented by subtypes of {@link DynamicConstantRef}.
+ *
+ * <p>Non-platform classes should not implement {@linkplain ConstantRef} directly.
+ * Instead, they should extend {@link DynamicConstantRef} (as {@link EnumRef}
+ * and {@link VarHandleRef} do.)
+ *
+ * <p>Constants can be reflectively resolved via {@link ConstantRef#resolveConstantRef(MethodHandles.Lookup)}.
+ *
+ * <p>Constants describing various useful nominal references (such as {@link ClassRef}
+ * instances for platform classes) can be found in {@link ConstantRefs}.
+ *
+ * <p>APIs that perform generation or parsing of bytecode are encouraged to use
+ * {@linkplain ConstantRef} to describe the operand of an {@code ldc} instruction
+ * (including dynamic constants), the static bootstrap arguments of
+ * dynamic constants and {@code invokedynamic} instructions, and other
+ * bytecodes or classfile structures that make use of the constant pool.
+ *
+ * <p>The {@linkplain ConstantRef} types are also used by {@link Intrinsics}
+ * to express {@code ldc} instructions.
+ *
+ * <p>Implementations of {@linkplain ConstantRef} must be
+ * <a href="../doc-files/ValueBased.html">value-based</a> classes.
+ *
+ * @apiNote In the future, if the Java language permits, {@linkplain ConstantRef}
+ * may become a {@code sealed} interface, which would prohibit subclassing except by
+ * explicitly permitted types.  Bytecode libraries can assume that the following
+ * is an exhaustive set of direct subtypes: {@link String}, {@link Integer},
+ * {@link Long}, {@link Float}, {@link Double}, {@link ClassRef},
+ * {@link MethodTypeRef}, {@link MethodHandleRef}, and {@link DynamicConstantRef}.
+ *
+ * @see Constable
+ * @see ConstantRef
+ * @see Intrinsics
+ * @see ConstantRefs
+ *
+ */
+public interface ConstantRef<T> {
+    /**
+     * Resolve this reference reflectively, using a {@link MethodHandles.Lookup}
+     * to resolve any type names into classes.
+     *
+     * @param lookup The {@link MethodHandles.Lookup} to be used in name resolution
+     * @return the resolved object
+     * @throws ReflectiveOperationException if this nominal reference refers
+     * (directly or indirectly) to a class, method, or field that cannot be
+     * resolved
+     */
+    T resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantRefs.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantBootstraps;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Predefined constants for common nominal references to constants.  Includes
+ * class references for primitive types and common platform types, and method
+ * handle references for standard bootstrap methods.
+ *
+ * @see ConstantRef
+ */
+public final class ConstantRefs {
+    // No instances
+    private ConstantRefs() { }
+
+    // Don't change the order of these declarations!
+
+    /** {@link ClassRef} representing {@link Object} */
+    @Foldable
+    public static final ClassRef CR_Object = ClassRef.of("java.lang.Object");
+
+    /** {@link ClassRef} representing {@link String} */
+    @Foldable
+    public static final ClassRef CR_String = ClassRef.of("java.lang.String");
+
+    /** {@link ClassRef} representing {@link Class} */
+    @Foldable
+    public static final ClassRef CR_Class = ClassRef.of("java.lang.Class");
+
+    /** {@link ClassRef} representing {@link Number} */
+    @Foldable
+    public static final ClassRef CR_Number = ClassRef.of("java.lang.Number");
+
+    /** {@link ClassRef} representing {@link Integer} */
+    @Foldable
+    public static final ClassRef CR_Integer = ClassRef.of("java.lang.Integer");
+
+    /** {@link ClassRef} representing {@link Long} */
+    @Foldable
+    public static final ClassRef CR_Long = ClassRef.of("java.lang.Long");
+
+    /** {@link ClassRef} representing {@link Float} */
+    @Foldable
+    public static final ClassRef CR_Float = ClassRef.of("java.lang.Float");
+
+    /** {@link ClassRef} representing {@link Double} */
+    @Foldable
+    public static final ClassRef CR_Double = ClassRef.of("java.lang.Double");
+
+    /** {@link ClassRef} representing {@link Short} */
+    @Foldable
+    public static final ClassRef CR_Short = ClassRef.of("java.lang.Short");
+
+    /** {@link ClassRef} representing {@link Byte} */
+    @Foldable
+    public static final ClassRef CR_Byte = ClassRef.of("java.lang.Byte");
+
+    /** {@link ClassRef} representing {@link Character} */
+    @Foldable
+    public static final ClassRef CR_Character = ClassRef.of("java.lang.Character");
+
+    /** {@link ClassRef} representing {@link Boolean} */
+    @Foldable
+    public static final ClassRef CR_Boolean = ClassRef.of("java.lang.Boolean");
+
+    /** {@link ClassRef} representing {@link Void} */
+    @Foldable
+    public static final ClassRef CR_Void = ClassRef.of("java.lang.Void");
+
+    /** {@link ClassRef} representing {@link Throwable} */
+    @Foldable
+    public static final ClassRef CR_Throwable = ClassRef.of("java.lang.Throwable");
+
+    /** {@link ClassRef} representing {@link Exception} */
+    @Foldable
+    public static final ClassRef CR_Exception = ClassRef.of("java.lang.Exception");
+
+    /** {@link ClassRef} representing {@link Enum} */
+    @Foldable
+    public static final ClassRef CR_Enum = ClassRef.of("java.lang.Enum");
+
+    /** {@link ClassRef} representing {@link VarHandle} */
+    @Foldable
+    public static final ClassRef CR_VarHandle = ClassRef.of("java.lang.invoke.VarHandle");
+
+    /** {@link ClassRef} representing {@link MethodHandles} */
+    @Foldable
+    public static final ClassRef CR_MethodHandles = ClassRef.of("java.lang.invoke.MethodHandles");
+
+    /** {@link ClassRef} representing {@link MethodHandles.Lookup} */
+    @Foldable
+    public static final ClassRef CR_MethodHandles_Lookup = CR_MethodHandles.inner("Lookup");
+
+    /** {@link ClassRef} representing {@link MethodHandle} */
+    @Foldable
+    public static final ClassRef CR_MethodHandle = ClassRef.of("java.lang.invoke.MethodHandle");
+
+    /** {@link ClassRef} representing {@link MethodType} */
+    @Foldable
+    public static final ClassRef CR_MethodType = ClassRef.of("java.lang.invoke.MethodType");
+
+    /** {@link ClassRef} representing {@link CallSite} */
+    @Foldable
+    public static final ClassRef CR_CallSite = ClassRef.of("java.lang.invoke.CallSite");
+
+    /** {@link ClassRef} representing {@link Collection} */
+    @Foldable
+    public static final ClassRef CR_Collection = ClassRef.of("java.util.Collection");
+
+    /** {@link ClassRef} representing {@link List} */
+    @Foldable
+    public static final ClassRef CR_List = ClassRef.of("java.util.List");
+
+    /** {@link ClassRef} representing {@link Set} */
+    @Foldable
+    public static final ClassRef CR_Set = ClassRef.of("java.util.Set");
+
+    /** {@link ClassRef} representing {@link Map} */
+    @Foldable
+    public static final ClassRef CR_Map = ClassRef.of("java.util.Map");
+
+    /** {@link ClassRef} representing {@link ConstantRef} */
+    @Foldable
+    static final ClassRef CR_ConstantRef = ClassRef.of("java.lang.invoke.constant.ConstantRef");
+
+    /** {@link ClassRef} representing {@link ClassRef} */
+    @Foldable
+    static final ClassRef CR_ClassRef = ClassRef.of("java.lang.invoke.constant.ClassRef");
+
+    /** {@link ClassRef} representing {@link EnumRef} */
+    @Foldable
+    static final ClassRef CR_EnumRef = ClassRef.of("java.lang.invoke.constant.EnumRef");
+
+    /** {@link ClassRef} representing {@link MethodTypeRef} */
+    @Foldable
+    static final ClassRef CR_MethodTypeRef = ClassRef.of("java.lang.invoke.constant.MethodTypeRef");
+
+    /** {@link ClassRef} representing {@link MethodHandleRef} */
+    @Foldable
+    static final ClassRef CR_MethodHandleRef = ClassRef.of("java.lang.invoke.constant.MethodHandleRef");
+
+    /** {@link ClassRef} representing {@link VarHandleRef} */
+    @Foldable
+    static final ClassRef CR_VarHandleRef = ClassRef.of("java.lang.invoke.constant.VarHandleRef");
+
+    /** {@link ClassRef} representing {@link MethodHandleRef.Kind} */
+    @Foldable
+    static final ClassRef CR_MethodHandleRef_Kind = CR_MethodHandleRef.inner("Kind");
+
+    /** {@link ClassRef} representing {@link DynamicConstantRef} */
+    @Foldable
+    static final ClassRef CR_DynamicConstantRef = ClassRef.of("java.lang.invoke.constant.DynamicConstantRef");
+
+    /** {@link ClassRef} representing {@link DynamicCallSiteRef} */
+    @Foldable
+    static final ClassRef CR_DynamicCallSiteRef = ClassRef.of("java.lang.invoke.constant.DynamicCallSiteRef");
+
+    /** {@link ClassRef} representing {@link ConstantBootstraps} */
+    @Foldable
+    static final ClassRef CR_ConstantBootstraps = ClassRef.of("java.lang.invoke.ConstantBootstraps");
+
+    // Used by MethodHandleRef, but initialized here before reference to
+    // MethodHandleRef to avoid static initalization circularities
+    static final ClassRef[] INDY_BOOTSTRAP_ARGS = {
+            ConstantRefs.CR_MethodHandles_Lookup,
+            ConstantRefs.CR_String,
+            ConstantRefs.CR_MethodType };
+
+    static final ClassRef[] CONDY_BOOTSTRAP_ARGS = {
+            ConstantRefs.CR_MethodHandles_Lookup,
+            ConstantRefs.CR_String,
+            ConstantRefs.CR_Class };
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#primitiveClass(Lookup, String, Class)} */
+    @Foldable
+    public static final MethodHandleRef BSM_PRIMITIVE_CLASS
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "primitiveClass", CR_Class);
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#enumConstant(Lookup, String, Class)} */
+    @Foldable
+    public static final MethodHandleRef BSM_ENUM_CONSTANT
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "enumConstant", CR_Enum);
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#nullConstant(Lookup, String, Class)} */
+    @Foldable
+    public static final MethodHandleRef BSM_NULL_CONSTANT
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "nullConstant", ConstantRefs.CR_Object);
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#fieldVarHandle(Lookup, String, Class, Class, Class)} */
+    @Foldable
+    public static final MethodHandleRef BSM_VARHANDLE_FIELD
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "fieldVarHandle", CR_VarHandle, CR_Class, CR_Class);
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#staticFieldVarHandle(Lookup, String, Class, Class, Class)} */
+    @Foldable
+    public static final MethodHandleRef BSM_VARHANDLE_STATIC_FIELD
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "staticFieldVarHandle", CR_VarHandle, CR_Class, CR_Class);
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#arrayVarHandle(Lookup, String, Class, Class)} */
+    @Foldable
+    public static final MethodHandleRef BSM_VARHANDLE_ARRAY
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "arrayVarHandle", CR_VarHandle, CR_Class);
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#invoke(Lookup, String, Class, MethodHandle, Object...)} */
+    @Foldable
+    public static final MethodHandleRef BSM_INVOKE
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "invoke", CR_Object, CR_MethodHandle, CR_Object.array());
+
+    /** {@link ClassRef} representing the primitive type {@code int} */
+    @Foldable
+    public static final ClassRef CR_int = ClassRef.ofDescriptor("I");
+
+    /** {@link ClassRef} representing the primitive type {@code long} */
+    @Foldable
+    public static final ClassRef CR_long = ClassRef.ofDescriptor("J");
+
+    /** {@link ClassRef} representing the primitive type {@code float} */
+    @Foldable
+    public static final ClassRef CR_float = ClassRef.ofDescriptor("F");
+
+    /** {@link ClassRef} representing the primitive type {@code double} */
+    @Foldable
+    public static final ClassRef CR_double = ClassRef.ofDescriptor("D");
+
+    /** {@link ClassRef} representing the primitive type {@code short} */
+    @Foldable
+    public static final ClassRef CR_short = ClassRef.ofDescriptor("S");
+
+    /** {@link ClassRef} representing the primitive type {@code byte} */
+    @Foldable
+    public static final ClassRef CR_byte = ClassRef.ofDescriptor("B");
+
+    /** {@link ClassRef} representing the primitive type {@code char} */
+    @Foldable
+    public static final ClassRef CR_char = ClassRef.ofDescriptor("C");
+
+    /** {@link ClassRef} representing the primitive type {@code boolean} */
+    @Foldable
+    public static final ClassRef CR_boolean = ClassRef.ofDescriptor("Z");
+
+    /** {@link ClassRef} representing the primitive type {@code void} */
+    @Foldable
+    public static final ClassRef CR_void = ClassRef.ofDescriptor("V");
+
+    /** Nominal reference representing the constant {@code null} */
+    @Foldable
+    public static final ConstantRef<?> NULL = DynamicConstantRef.of(ConstantRefs.BSM_NULL_CONSTANT, ConstantRefs.CR_Object);
+
+    // Used by XxxRef classes, but need to be hear to avoid bootstrap cycles
+    static final MethodHandleRef MHR_METHODTYPEREF_FACTORY
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_MethodTypeRef, "ofDescriptor", CR_MethodTypeRef, CR_String);
+
+    static final MethodHandleRef MHR_CLASSREF_FACTORY
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_ClassRef, "ofDescriptor", CR_ClassRef, CR_String);
+
+    static final MethodHandleRef MHR_METHODHANDLEREF_FACTORY
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_MethodHandleRef, "of",
+                                 CR_MethodHandleRef, CR_MethodHandleRef_Kind, CR_ClassRef, CR_String, CR_MethodTypeRef);
+
+    static final MethodHandleRef MHR_METHODHANDLE_ASTYPE
+            = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_MethodHandle, "asType", CR_MethodHandle, CR_MethodType);
+
+    static final MethodHandleRef MHR_METHODHANDLEREF_ASTYPE
+            = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_MethodHandleRef, "asType", CR_MethodHandleRef, CR_MethodTypeRef);
+
+    static final MethodHandleRef MHR_DYNAMICCONSTANTREF_FACTORY
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_DynamicConstantRef, "of",
+                                 CR_DynamicConstantRef, CR_MethodHandleRef, CR_String, CR_ClassRef);
+
+    static final MethodHandleRef MHR_DYNAMICCONSTANTREF_WITHARGS
+            = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_DynamicConstantRef, "withArgs",
+                                 CR_DynamicConstantRef, CR_ConstantRef.array());
+
+    static final MethodHandleRef MHR_ENUMREF_FACTORY
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_EnumRef, "of", CR_EnumRef, CR_ClassRef, CR_String);
+
+    static final MethodHandleRef MHR_VARHANDLEREF_OFFIELD
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_VarHandleRef, "ofField",
+                                 CR_VarHandleRef, CR_ClassRef, CR_String, CR_ClassRef);
+
+    static final MethodHandleRef MHR_VARHANDLEREF_OFSTATIC
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_VarHandleRef, "ofStaticField",
+                                 CR_VarHandleRef, CR_ClassRef, CR_String, CR_ClassRef);
+
+    static final MethodHandleRef MHR_VARHANDLEREF_OFARRAY
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_VarHandleRef, "ofArray",
+                                 CR_VarHandleRef, CR_ClassRef);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/DynamicCallSiteRef.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 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 java.lang.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_String;
+import static java.util.stream.Collectors.joining;
+
+/**
+ * A nominal reference for an {@code invokedynamic} call site.
+ */
+@SuppressWarnings("rawtypes")
+public final class DynamicCallSiteRef {
+    private static final ConstantRef<?>[] EMPTY_ARGS = new ConstantRef<?>[0];
+
+    private final ConstantMethodHandleRef bootstrapMethod;
+    private final ConstantRef<?>[] bootstrapArgs;
+    private final String name;
+    private final MethodTypeRef type;
+
+    /**
+     * Construct a nominal reference for an {@code invokedynamic} call site
+     *
+     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param type The invocation type that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @throws NullPointerException if any parameter is null
+     * @throws IllegalArgumentException if the bootstrap method is not a
+     * {@link ConstantMethodHandleRef}
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    private DynamicCallSiteRef(MethodHandleRef bootstrapMethod,
+                               String name,
+                               MethodTypeRef type,
+                               ConstantRef<?>[] bootstrapArgs) {
+        if (!(bootstrapMethod instanceof ConstantMethodHandleRef))
+            throw new IllegalArgumentException("bootstrap method must be a ConstantMethodHandleRef");
+        this.name = Objects.requireNonNull(name);
+        this.type = Objects.requireNonNull(type);
+        this.bootstrapMethod = (ConstantMethodHandleRef) Objects.requireNonNull(bootstrapMethod);
+        this.bootstrapArgs = Objects.requireNonNull(bootstrapArgs.clone());
+        if (name.length() == 0)
+            throw new IllegalArgumentException("Illegal invocation name: " + name);
+    }
+
+    /**
+     * Return a nominal reference for an {@code invokedynamic} call site.  If
+     * the bootstrap method corresponds to a well-known bootstrap, for which a
+     * more specific nominal reference type exists, the more specific nominal
+     * reference type is returned.
+     *
+     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param type The invocation type that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @return the nominal reference
+     * @throws NullPointerException if any parameter is null
+     */
+    @Foldable
+    public static DynamicCallSiteRef ofCanonical(MethodHandleRef bootstrapMethod, String name, MethodTypeRef type, ConstantRef<?>... bootstrapArgs) {
+        DynamicCallSiteRef ref = new DynamicCallSiteRef(bootstrapMethod, name, type, bootstrapArgs);
+        return ref.canonicalize();
+    }
+
+    /**
+     * Return a nominal reference for an {@code invokedynamic} call site.
+     *
+     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param type The invocation type that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @return the nominal reference
+     * @throws NullPointerException if any parameter is null
+     */
+    @Foldable
+    public static DynamicCallSiteRef of(MethodHandleRef bootstrapMethod, String name, MethodTypeRef type, ConstantRef<?>... bootstrapArgs) {
+        return new DynamicCallSiteRef(bootstrapMethod, name, type, bootstrapArgs);
+    }
+
+    /**
+     * Return a nominal reference for an {@code invokedynamic} call site whose
+     * bootstrap method has no static arguments.
+     *
+     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param type The invocation type that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @return the nominal reference
+     * @throws NullPointerException if any parameter is null
+     */
+    @Foldable
+    public static DynamicCallSiteRef of(MethodHandleRef bootstrapMethod, String name, MethodTypeRef type) {
+        return new DynamicCallSiteRef(bootstrapMethod, name, type, EMPTY_ARGS);
+    }
+
+    /**
+     * Return a nominal reference for an {@code invokedynamic} call site whose
+     * bootstrap method has no static arguments and whose name parameter is ignored.
+     *
+     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
+     * @param type The invocation type that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @return the nominal reference
+     * @throws NullPointerException if any parameter is null
+     */
+    @Foldable
+    public static DynamicCallSiteRef of(MethodHandleRef bootstrapMethod, MethodTypeRef type) {
+        return of(bootstrapMethod, "_", type);
+    }
+
+    /**
+     * Return a nominal reference for an {@code invokedynamic} call site whose
+     * bootstrap method, name, and invocation type are the same as this one, but
+     * with the specified bootstrap arguments.
+     *
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @return the nominal reference
+     * @throws NullPointerException if any parameter is null
+     */
+    @Foldable
+    public DynamicCallSiteRef withArgs(ConstantRef<?>... bootstrapArgs) {
+        return new DynamicCallSiteRef(bootstrapMethod, name, type, bootstrapArgs);
+    }
+
+    /**
+     * Return a nominal reference for an {@code invokedynamic} call site whose
+     * bootstrap and bootstrap arguments are the same as this one, but with the
+     * specified name and invocation type
+     *
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param type The invocation type that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @return the nominal reference
+     * @throws NullPointerException if any parameter is null
+     */
+    @Foldable
+    public DynamicCallSiteRef withNameAndType(String name, MethodTypeRef type) {
+        return new DynamicCallSiteRef(bootstrapMethod, name, type, bootstrapArgs);
+    }
+
+    private DynamicCallSiteRef canonicalize() {
+        // @@@ MethodRef
+        return this;
+    }
+
+    /**
+     * Returns the invocation name that would appear in the {@code NameAndType} operand
+     * of the {@code invokedynamic}
+     * @return the invocation name
+     */
+    @Foldable
+    public String name() {
+        return name;
+    }
+
+    /**
+     * Returns the invocation type that would appear in the {@code NameAndType} operand
+     * of the {@code invokedynamic}
+     * @return the invocation type
+     */
+    @Foldable
+    public MethodTypeRef type() {
+        return type;
+    }
+
+    /**
+     * Returns the bootstrap method for the {@code invokedynamic}
+     * @return the bootstrap method for the {@code invokedynamic}
+     */
+    @Foldable
+    public MethodHandleRef bootstrapMethod() { return bootstrapMethod; }
+
+    /**
+     * Returns the bootstrap arguments for the {@code invokedynamic}
+     * @return the bootstrap arguments for the {@code invokedynamic}
+     */
+    public ConstantRef<?>[] bootstrapArgs() { return bootstrapArgs.clone(); }
+
+    /**
+     * Reflectively invokes the bootstrap method, and returns a dynamic invoker
+     * {@link MethodHandle} for the returned {@link CallSite}
+     *
+     * @param lookup The {@link MethodHandles.Lookup} used to resolve class names
+     * @return the dynamic invoker
+     * @throws Throwable if any exception is thrown by the bootstrap method
+     *
+     * @see CallSite#dynamicInvoker()
+     */
+    public MethodHandle dynamicInvoker(MethodHandles.Lookup lookup) throws Throwable {
+        assert bootstrapMethod.methodType().parameterType(1).equals(CR_String);
+        MethodHandle bsm = bootstrapMethod.resolveConstantRef(lookup);
+        Object[] args = new Object[bootstrapArgs.length + 3];
+        args[0] = lookup;
+        args[1] = name;
+        args[2] = type.resolveConstantRef(lookup);
+        System.arraycopy(bootstrapArgs, 0, args, 3, bootstrapArgs.length);
+        CallSite callSite = (CallSite) bsm.invokeWithArguments(args);
+        return callSite.dynamicInvoker();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        DynamicCallSiteRef specifier = (DynamicCallSiteRef) o;
+        return Objects.equals(bootstrapMethod, specifier.bootstrapMethod) &&
+               Arrays.equals(bootstrapArgs, specifier.bootstrapArgs) &&
+               Objects.equals(name, specifier.name) &&
+               Objects.equals(type, specifier.type);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = Objects.hash(bootstrapMethod, name, type);
+        result = 31 * result + Arrays.hashCode(bootstrapArgs);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("DynamicCallSiteRef[%s::%s(%s%s):%s]",
+                             bootstrapMethod.owner().simpleName(),
+                             bootstrapMethod.methodName(),
+                             name.equals("_") ? "" : name + "/",
+                             Stream.of(bootstrapArgs).map(Object::toString).collect(joining(",")),
+                             type.simpleDescriptor());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/DynamicConstantRef.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.ConstantBootstraps;
+import java.lang.invoke.MethodHandles;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_DynamicConstantRef;
+import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.joining;
+
+/**
+ * A nominal reference for a dynamic constant (one described in the constant
+ * pool with {@code Constant_Dynamic_info}.)
+ *
+ * <p>Concrete subtypes of {@linkplain DynamicConstantRef} must be
+ * <a href="../doc-files/ValueBased.html">value-based</a>.
+ *
+ * @param <T> the type of the dynamic constant
+ */
+public abstract class DynamicConstantRef<T> implements ConstantRef<T>, Constable<ConstantRef<T>> {
+    private final ConstantMethodHandleRef bootstrapMethod;
+    private final ConstantRef<?>[] bootstrapArgs;
+    private final String name;
+    private final ClassRef type;
+
+    @SuppressWarnings("rawtypes")
+    private static final Map<MethodHandleRef, Function<DynamicConstantRef, ConstantRef<?>>> canonicalMap
+            = Map.ofEntries(Map.entry(ConstantRefs.BSM_PRIMITIVE_CLASS, d -> ClassRef.ofDescriptor(d.name)),
+                            Map.entry(ConstantRefs.BSM_ENUM_CONSTANT, d -> EnumRef.of(d.type, d.name)),
+                            Map.entry(ConstantRefs.BSM_NULL_CONSTANT, d -> ConstantRefs.NULL),
+                            Map.entry(ConstantRefs.BSM_VARHANDLE_STATIC_FIELD,
+                                      d -> VarHandleRef.ofStaticField((ClassRef) d.bootstrapArgs[0],
+                                                                      (String) d.bootstrapArgs[1],
+                                                                      (ClassRef) d.bootstrapArgs[2])),
+                            Map.entry(ConstantRefs.BSM_VARHANDLE_FIELD,
+                                      d -> VarHandleRef.ofField((ClassRef) d.bootstrapArgs[0],
+                                                                (String) d.bootstrapArgs[1],
+                                                                (ClassRef) d.bootstrapArgs[2])),
+                            Map.entry(ConstantRefs.BSM_VARHANDLE_ARRAY,
+                                      d -> VarHandleRef.ofArray((ClassRef) d.bootstrapArgs[0]))
+    );
+
+    /**
+     * Construct a nominal reference for a dynamic constant
+     *
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param type The type that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if the bootstrap method is not a
+     * {@link ConstantMethodHandleRef}
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    protected DynamicConstantRef(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>... bootstrapArgs) {
+        requireNonNull(bootstrapMethod);
+        if (!(bootstrapMethod instanceof ConstantMethodHandleRef))
+            throw new IllegalArgumentException("bootstrap method must be a ConstantMethodHandleRef");
+        this.bootstrapMethod = (ConstantMethodHandleRef) bootstrapMethod;
+        this.name = requireNonNull(name);
+        this.type = requireNonNull(type);
+        this.bootstrapArgs = requireNonNull(bootstrapArgs).clone();
+
+        if (name.length() == 0)
+            throw new IllegalArgumentException("Illegal invocation name: " + name);
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant whose bootstrap, invocation
+     * name, and invocation type are the same as this one, but with the specified
+     * bootstrap arguments
+     *
+     * @param bootstrapArgs the bootstrap arguments
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     */
+    @Foldable
+    public DynamicConstantRef<T> withArgs(ConstantRef<?>... bootstrapArgs) {
+        return new DynamicConstantRefImpl<>(bootstrapMethod, name, type, bootstrapArgs);
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant.  If  the bootstrap
+     * corresponds to a well-known bootstrap, for which a more specific nominal
+     * reference type (e.g., ClassRef) is available, then the more specific
+     * nominal reference will be returned.
+     *
+     * @param <T> the type of the dynamic constant
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param type The type that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    @Foldable
+    public static<T> ConstantRef<T> ofCanonical(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>[] bootstrapArgs) {
+        DynamicConstantRef<T> dcr = new DynamicConstantRefImpl<>(bootstrapMethod, name, type, bootstrapArgs);
+        return dcr.canonicalize();
+    }
+
+    private ConstantRef<T> canonicalize() {
+        // @@@ Existing map-based approach is cute but not very robust; need to add more checking of target DCRef
+        @SuppressWarnings("rawtypes")
+        Function<DynamicConstantRef, ConstantRef<?>> f = canonicalMap.get(bootstrapMethod);
+        if (f != null) {
+            @SuppressWarnings("unchecked")
+            ConstantRef<T> converted = (ConstantRef<T>) f.apply(this);
+            return converted;
+        }
+        return this;
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant.
+     *
+     * @param <T> the type of the dynamic constant
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param type The type that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    @Foldable
+    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>[] bootstrapArgs) {
+        return new DynamicConstantRefImpl<>(bootstrapMethod, name, type, bootstrapArgs);
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant whose bootstrap has
+     * no static arguments.
+     *
+     * @param <T> the type of the dynamic constant
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param type The type that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    @Foldable
+    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod, String name, ClassRef type) {
+        return new DynamicConstantRefImpl<>(bootstrapMethod, name, type);
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant whose bootstrap has
+     * no static arguments, and whose name parameter is ignored by the bootstrap
+     *
+     * @param <T> the type of the dynamic constant
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @param type The type that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    @Foldable
+    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod, ClassRef type) {
+        return of(bootstrapMethod, "_", type);
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant whose bootstrap has
+     * no static arguments, and whose type parameter is always the same as the
+     * bootstrap method return type.
+     *
+     * @param <T> the type of the dynamic constant
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    @Foldable
+    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod, String name) {
+        return of(bootstrapMethod, name, bootstrapMethod.methodType().returnType());
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant whose bootstrap has
+     * no static arguments, whose name parameter is ignored, and whose type
+     * parameter is always the same as the bootstrap method return type.
+     *
+     * @param <T> the type of the dynamic constant
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    @Foldable
+    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod) {
+        return of(bootstrapMethod, "_");
+    }
+
+    /**
+     * returns The name that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @return the name
+     */
+    @Foldable
+    public String constantName() {
+        return name;
+    }
+
+    /**
+     * returns The type that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @return the type
+     */
+    @Foldable
+    public ClassRef constantType() {
+        return type;
+    }
+
+    /**
+     * Returns the bootstrap method for this constant
+     * @return the bootstrap method
+     */
+    @Foldable
+    public MethodHandleRef bootstrapMethod() { return bootstrapMethod; }
+
+    /**
+     * Returns the bootstrap arguments for this constant
+     * @return the bootstrap arguments
+     */
+    public ConstantRef<?>[] bootstrapArgs() { return bootstrapArgs.clone(); }
+
+    private static Object[] resolveArgs(MethodHandles.Lookup lookup, ConstantRef<?>[] args)
+            throws ReflectiveOperationException {
+        try {
+            return Stream.of(args)
+                    .map(arg -> {
+                        try {
+                            return arg.resolveConstantRef(lookup);
+                        }
+                        catch (ReflectiveOperationException e) {
+                            throw new RuntimeException(e);
+                        }
+                    })
+                    .toArray();
+        }
+        catch (RuntimeException e) {
+            if (e.getCause() instanceof ReflectiveOperationException) {
+                throw (ReflectiveOperationException) e.getCause();
+            }
+            else {
+                throw e;
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public T resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+        return (T) ConstantBootstraps.makeConstant(bootstrapMethod.resolveConstantRef(lookup),
+                                                   name,
+                                                   type.resolveConstantRef(lookup),
+                                                   resolveArgs(lookup, bootstrapArgs),
+                                                   // TODO pass lookup
+                                                   lookup.lookupClass());
+    }
+
+    @Override
+    public Optional<? extends ConstantRef<? super ConstantRef<T>>> toConstantRef(MethodHandles.Lookup lookup) {
+        ConstantRef<?>[] args = new ConstantRef<?>[bootstrapArgs.length + 5];
+        args[0] = bootstrapMethod.owner().descriptorString();
+        args[1] = bootstrapMethod.methodName();
+        args[2] = bootstrapMethod.methodType().descriptorString();
+        args[3] = name;
+        args[4] = type.descriptorString();
+        System.arraycopy(bootstrapArgs, 0, args, 5, bootstrapArgs.length);
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_DYNAMICCONSTANTREF, "_", CR_DynamicConstantRef, args));
+    }
+
+    /**
+     * Produce a {@linkplain DynamicConstantRef} describing the invocation of
+     * the specified bootstrap with the specified arguments.
+     *
+     * @param bootstrap nominal reference for the bootstrap method
+     * @param type nominal reference for the type of the resulting constant
+     * @param args nominal references for the bootstrap arguments
+     * @param <T> the type of the resulting constant
+     * @return the dynamic constant reference
+     */
+    protected static<T> DynamicConstantRef<T> ofInvoke(MethodHandleRef bootstrap,
+                                                       ClassRef type,
+                                                       ConstantRef<?>... args) {
+        ConstantRef<?>[] quotedArgs = new ConstantRef<?>[args.length + 1];
+        quotedArgs[0] = bootstrap;
+        System.arraycopy(args, 0, quotedArgs, 1, args.length);
+        return DynamicConstantRef.of(ConstantRefs.BSM_INVOKE, "_", type, quotedArgs);
+    }
+
+    /**
+     * Produce an {@code Optional<DynamicConstantRef<T>>} describing the invocation
+     * of the specified bootstrap with the specified arguments.  The arguments will
+     * be converted to nominal references using the provided lookup.
+     *
+     * @param lookup A {@link MethodHandles.Lookup} to be used to perform
+     *               access control determinations
+     * @param bootstrap nominal reference for the bootstrap method
+     * @param type nominal reference for the type of the resulting constant
+     * @param args nominal references for the bootstrap arguments
+     * @param <T> the type of the resulting constant
+     * @return the dynamic constant reference
+     */
+    static<T> Optional<DynamicConstantRef<T>> symbolizeHelper(MethodHandles.Lookup lookup,
+                                                              MethodHandleRef bootstrap,
+                                                              ClassRef type,
+                                                              Constable<?>... args) {
+        try {
+            ConstantRef<?>[] quotedArgs = new ConstantRef<?>[args.length + 1];
+            quotedArgs[0] = bootstrap;
+            for (int i=0; i<args.length; i++)
+                quotedArgs[i+1] = args[i].toConstantRef(lookup).orElseThrow();
+            return Optional.of(DynamicConstantRef.of(ConstantRefs.BSM_INVOKE, "_", type, quotedArgs));
+        }
+        catch (NoSuchElementException e) {
+            return Optional.empty();
+        }
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof DynamicConstantRef)) return false;
+        DynamicConstantRef<?> ref = (DynamicConstantRef<?>) o;
+        return Objects.equals(bootstrapMethod, ref.bootstrapMethod) &&
+               Arrays.equals(bootstrapArgs, ref.bootstrapArgs) &&
+               Objects.equals(name, ref.name) &&
+               Objects.equals(type, ref.type);
+    }
+
+    @Override
+    public final int hashCode() {
+        int result = Objects.hash(bootstrapMethod, name, type);
+        result = 31 * result + Arrays.hashCode(bootstrapArgs);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("DynamicConstantRef[%s::%s(%s%s)%s]",
+                             bootstrapMethod.owner().simpleName(),
+                             bootstrapMethod.methodName(),
+                             name.equals("_") ? "" : name + "/",
+                             Stream.of(bootstrapArgs).map(Object::toString).collect(joining(",")),
+                             type.simpleName());
+    }
+
+    private static final class DynamicConstantRefImpl<T> extends DynamicConstantRef<T> {
+        DynamicConstantRefImpl(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>... bootstrapArgs) {
+            super(bootstrapMethod, name, type, bootstrapArgs);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/EnumRef.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandles;
+import java.util.Optional;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_ClassRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_EnumRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_String;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A symbolic reference for an {@code enum} constant.
+ *
+ * @param <E> the type of the enum constant
+ */
+public final class EnumRef<E extends Enum<E>> extends DynamicConstantRef<E> {
+
+    /**
+     * Construct a symbolic reference for the specified enum class and name
+     *
+     * @param constantType the enum class
+     * @param constantName the name of the enum constant
+     * @throws NullPointerException if any argument is null
+     */
+    private EnumRef(ClassRef constantType, String constantName) {
+        super(ConstantRefs.BSM_ENUM_CONSTANT, requireNonNull(constantName), requireNonNull(constantType));
+    }
+
+    /**
+     * Return a symbolic reference for the specified enum class and name
+     *
+     * @param <E> the type of the enum constant
+     * @param enumClass the enum class
+     * @param constantName the name of the enum constant
+     * @return the symbolic reference
+     * @throws NullPointerException if any argument is null
+     */
+    @Foldable
+    public static<E extends Enum<E>> EnumRef<E> of(ClassRef enumClass, String constantName) {
+        return new EnumRef<>(enumClass, constantName);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public E resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+        return Enum.valueOf((Class<E>) constantType().resolveConstantRef(lookup), constantName());
+    }
+
+    @Override
+    public Optional<? extends ConstantRef<? super ConstantRef<E>>> toConstantRef(MethodHandles.Lookup lookup) {
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_ENUMREF, CR_EnumRef).withArgs(constantType().descriptorString(), constantName()));
+    }
+
+    @Override
+    public String toString() {
+        return String.format("EnumRef[%s.%s]", constantType().simpleName(), constantName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/MethodHandleRef.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
+import java.lang.invoke.MethodType;
+
+import static java.lang.invoke.MethodHandleInfo.REF_getField;
+import static java.lang.invoke.MethodHandleInfo.REF_getStatic;
+import static java.lang.invoke.MethodHandleInfo.REF_invokeInterface;
+import static java.lang.invoke.MethodHandleInfo.REF_invokeSpecial;
+import static java.lang.invoke.MethodHandleInfo.REF_invokeStatic;
+import static java.lang.invoke.MethodHandleInfo.REF_invokeVirtual;
+import static java.lang.invoke.MethodHandleInfo.REF_newInvokeSpecial;
+import static java.lang.invoke.MethodHandleInfo.REF_putField;
+import static java.lang.invoke.MethodHandleInfo.REF_putStatic;
+import static java.lang.invoke.constant.MethodHandleRef.Kind.STATIC;
+import static java.lang.invoke.constant.ConstantRefs.CR_void;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A symbolic reference for a {@link MethodHandle} constant.
+ */
+public interface MethodHandleRef
+        extends ConstantRef<MethodHandle>, Constable<ConstantRef<MethodHandle>> {
+    /**
+     * Kinds of method handle refs
+     */
+    enum Kind {
+        /** A method handle for a method invoked as with {@code invokestatic} */
+        @Foldable STATIC(REF_invokeStatic),
+        /** A method handle for a method invoked as with {@code invokevirtual} */
+        @Foldable VIRTUAL(REF_invokeVirtual),
+        /** A method handle for a method invoked as with {@code invokeinterface} */
+        @Foldable INTERFACE_VIRTUAL(REF_invokeInterface),
+        /** A method handle for a method invoked as with {@code invokespecial} */
+        @Foldable SPECIAL(REF_invokeSpecial),
+        /** A method handle for a constructor */
+        @Foldable CONSTRUCTOR(REF_newInvokeSpecial),
+        /** A method handle for a read accessor for an instance field  */
+        @Foldable GETTER(REF_getField),
+        /** A method handle for a write accessor for an instance field  */
+        @Foldable SETTER(REF_putField),
+        /** A method handle for a read accessor for a static field  */
+        @Foldable STATIC_GETTER(REF_getStatic),
+        /** A method handle for a write accessor for a static field  */
+        @Foldable STATIC_SETTER(REF_putStatic);
+
+        /** The corresponding {@code refKind} value for this kind of method handle,
+         * as defined by {@link MethodHandleInfo}
+         */
+        public final int refKind;
+
+        Kind(int refKind) {
+            this.refKind = refKind;
+        }
+    }
+
+
+    /**
+     * Return a {@code MethodHandleRef} corresponding to an invocation of a
+     * declared method or an accessor for a field
+     *
+     * @param kind The kind of method handle to be described
+     * @param clazz the class declaring the method
+     * @param name the name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
+     * @param type the method type of the method
+     * @return the {@code MethodHandleRef}
+     * @throws NullPointerException if any of the non-ignored arguments are null
+     */
+    @Foldable
+    static ConstantMethodHandleRef of(Kind kind, ClassRef clazz, String name, MethodTypeRef type) {
+        return new ConstantMethodHandleRef(kind, clazz, name, type);
+    }
+
+    /**
+     * Return a {@code MethodHandleRef} corresponding to an invocation of a
+     * declared method or an accessor for a field
+     *
+     * @param kind The kind of method handle to be described
+     * @param clazz the class declaring the method
+     * @param name the name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
+     * @param descriptorString descriptor string of the method
+     * @return the {@code MethodHandleRef}
+     * @throws NullPointerException if any of the non-ignored arguments are null
+     */
+    @Foldable
+    static ConstantMethodHandleRef of(Kind kind, ClassRef clazz, String name, String descriptorString) {
+        return of(kind, clazz, name, MethodTypeRef.ofDescriptor(descriptorString));
+    }
+
+    /**
+     * Return a {@code MethodHandleRef} corresponding to an invocation of a
+     * declared method or an accessor for a field
+     *
+     * @param kind The kind of method handle to be described
+     * @param clazz the class declaring the method
+     * @param name the name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
+     * @param returnType the return type of the method
+     * @param paramTypes the parameter types of the method
+     * @return the {@code MethodHandleRef}
+     * @throws NullPointerException if any of the non-ignored arguments are null
+     */
+    @Foldable
+    static ConstantMethodHandleRef of(Kind kind, ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
+        return of(kind, clazz, name, MethodTypeRef.of(returnType, paramTypes));
+    }
+
+    /**
+     * Return a {@code MethodHandleRef} corresponding to a bootstrap method for
+     * an {@code invokedynamic} callsite, which is a static method whose leading
+     * parameter types are {@code Lookup}, {@code String}, and {@code MethodType}
+     * @param clazz the class declaring the method
+     * @param name the name of the method
+     * @param returnType the return type of the method
+     * @param paramTypes the parameter types of the method that follow the three
+     *                   standard leading arguments, if any
+     * @return the {@code MethodHandleRef}
+     * @throws NullPointerException if any of the arguments are null
+     */
+    @Foldable
+    static ConstantMethodHandleRef ofDynamicCallsite(ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
+        return of(STATIC, clazz, name, MethodTypeRef.of(returnType, paramTypes).insertParameterTypes(0, ConstantRefs.INDY_BOOTSTRAP_ARGS));
+    }
+
+    /**
+     * Return a {@code MethodHandleRef} corresponding to a bootstrap method for a
+     * dynamic constant, which is a static method whose leading arguments are
+     * {@code Lookup}, {@code String}, and {@code Class}
+     * @param clazz the class declaring the method
+     * @param name the name of the method
+     * @param returnType the return type of the method
+     * @param paramTypes the parameter types of the method that follow the three
+     *                   standard leading arguments, if any
+     * @return the {@code MethodHandleRef}
+     * @throws NullPointerException if any of the arguments are null
+     */
+    @Foldable
+    static ConstantMethodHandleRef ofDynamicConstant(ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
+        return of(STATIC, clazz, name, MethodTypeRef.of(returnType, paramTypes).insertParameterTypes(0, ConstantRefs.CONDY_BOOTSTRAP_ARGS));
+    }
+
+    /**
+     * Return a {@code MethodHandleRef} corresponding to accessing a field
+     * @param kind the kind of the method handle; must be one of {@code GETTER},
+     *             {@code SETTER}, {@code STATIC_GETTER}, or {@code STATIC_SETTER}
+     * @param clazz the class declaring the field
+     * @param name the name of the field
+     * @param type the type of the field
+     * @return the {@code MethodHandleRef}
+     * @throws NullPointerException if any of the arguments are null
+     */
+    @Foldable
+    static ConstantMethodHandleRef ofField(Kind kind, ClassRef clazz, String name, ClassRef type) {
+        MethodTypeRef mtr;
+        switch (kind) {
+            case GETTER: mtr = MethodTypeRef.of(type, clazz); break;
+            case SETTER: mtr = MethodTypeRef.of(CR_void, clazz, type); break;
+            case STATIC_GETTER: mtr = MethodTypeRef.of(type); break;
+            case STATIC_SETTER: mtr = MethodTypeRef.of(CR_void, type); break;
+            default:
+                throw new IllegalArgumentException(kind.toString());
+        }
+        return new ConstantMethodHandleRef(kind, clazz, name, mtr);
+    }
+
+    /**
+     * Return the type of the method described by this symbolic reference
+     * @return the method type
+     */
+    @Foldable
+    MethodTypeRef methodType();
+
+    /**
+     * Return a {@linkplain MethodHandleRef} that describes this method handle
+     * adapted to a different type, as if by {@link MethodHandle#asType(MethodType)}.
+     *
+     * @param type the new type
+     * @return the adapted method handle reference
+     */
+    @Foldable
+    default MethodHandleRef asType(MethodTypeRef type) {
+        return (methodType().equals(type)) ? this : new AsTypeMethodHandleRef(this, type);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/MethodTypeRef.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A symbolic reference for a {@linkplain MethodType} constant.
+ */
+public interface MethodTypeRef extends ConstantRef<MethodType>, Constable<ConstantRef<MethodType>> {
+    /**
+     * Create a {@linkplain MethodTypeRef} from a method descriptor string
+     *
+     * @param descriptor the method descriptor string
+     * @return a {@linkplain MethodTypeRef} describing the desired method type
+     * @throws IllegalArgumentException if the descriptor string is not a valid
+     * method descriptor
+     */
+    @Foldable
+    static MethodTypeRef ofDescriptor(String descriptor) {
+        return ConstantMethodTypeRef.ofDescriptor(descriptor);
+    }
+
+    /**
+     * Returns a {@linkplain MethodTypeRef} for the specified return type and
+     * parameter types.
+     *
+     * @param returnDescriptor a {@linkplain ClassRef} describing the return type
+     * @param paramDescriptors {@linkplain ClassRef}s describing the argument types
+     * @return a {@linkplain MethodTypeRef} describing the desired method type
+     */
+    @Foldable
+    static MethodTypeRef of(ClassRef returnDescriptor, ClassRef... paramDescriptors) {
+        return new ConstantMethodTypeRef(returnDescriptor, paramDescriptors);
+    }
+
+    /**
+     * Get the return type of the method type described by this {@linkplain MethodTypeRef}
+     * @return the return type
+     */
+    @Foldable
+    ClassRef returnType();
+
+    /**
+     * Get the number of parameters of the method type described by
+     * this {@linkplain MethodTypeRef}
+     * @return the number of parameters
+     */
+    @Foldable
+    int parameterCount();
+
+    /**
+     * Get the parameter type of the {@code index}'th parameter of the method type
+     * described by this {@linkplain MethodTypeRef}
+     *
+     * @param index the index of the parameter to retrieve
+     * @return the parameter type
+     * @throws IndexOutOfBoundsException if the index is outside the half-open
+     * range {[0, parameterCount())}
+     */
+    @Foldable
+    ClassRef parameterType(int index);
+
+    /**
+     * Get the parameter types as a {@link List}
+     *
+     * @return the parameter types
+     */
+    List<ClassRef> parameterList();
+
+    /**
+     * Get the parameter types as an array
+     *
+     * @return the parameter types
+     */
+    ClassRef[] parameterArray();
+
+    /**
+     * Return a {@linkplain MethodTypeRef} that is identical to
+     * this one, except with the specified return type
+     *
+     * @param returnType the new return type
+     * @return the new method type descriptor
+     */
+    @Foldable
+    MethodTypeRef changeReturnType(ClassRef returnType);
+
+    /**
+     * Return a {@linkplain MethodTypeRef} that is identical to this one,
+     * except that a single parameter type has been changed to the provided
+     * value
+     *
+     * @param index the index of the parameter to change
+     * @param paramType the new parameter type
+     * @return the new method type descriptor
+     * @throws IndexOutOfBoundsException if the index is outside the half-open
+     * range {[0, parameterCount)}
+     */
+    @Foldable
+    MethodTypeRef changeParameterType(int index, ClassRef paramType);
+
+    /**
+     * Return a {@linkplain MethodTypeRef} that is identical to this one,
+     * except that a range of parameter types have been removed
+     *
+     * @param start the index of the first parameter to remove
+     * @param end the index after the last parameter to remove
+     * @return the new method type descriptor
+     * @throws IndexOutOfBoundsException if {@code start} is outside the half-open
+     * range {[0, parameterCount)}, or {@code end} is outside the closed range
+     * {@code [0, parameterCount]}
+     */
+    @Foldable
+    MethodTypeRef dropParameterTypes(int start, int end);
+
+    /**
+     * Return a {@linkplain MethodTypeRef} that is identical to this one,
+     * except that a range of additional parameter types have been inserted
+     *
+     * @param pos the index at which to insert the first inserted parameter
+     * @param paramTypes the new parameter types to insert
+     * @return the new method type descriptor
+     * @throws IndexOutOfBoundsException if {@code pos} is outside the closed
+     * range {[0, parameterCount]}
+     */
+    @Foldable
+    MethodTypeRef insertParameterTypes(int pos, ClassRef... paramTypes);
+
+    /**
+     * Return the method type descriptor string
+     * @return the method type descriptor string
+     */
+    default String descriptorString() {
+        return String.format("(%s)%s",
+                             Stream.of(parameterArray())
+                                   .map(ClassRef::descriptorString)
+                                   .collect(Collectors.joining()),
+                             returnType().descriptorString());
+    }
+
+    /**
+     * Return a human-readable descriptor for this method type, using the
+     * canonical names for parameter and return types
+     * @return the human-readable descriptor for this method type
+     */
+    default String simpleDescriptor() {
+        return String.format("(%s)%s",
+                             Stream.of(parameterArray())
+                                   .map(ClassRef::simpleName)
+                                   .collect(Collectors.joining(",")),
+                             returnType().simpleName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/PrimitiveClassRef.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import java.lang.invoke.MethodHandles;
+import java.util.Optional;
+
+import sun.invoke.util.Wrapper;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * PrimitiveClassRef
+ *
+ * @author Brian Goetz
+ */
+final class PrimitiveClassRef extends DynamicConstantRef<Class<?>> implements ClassRef {
+    private final String descriptor;
+
+    /**
+     * Create a {@linkplain ClassRef} from a descriptor string for a primitive type
+     *
+     * @param descriptor the descriptor string
+     * @throws IllegalArgumentException if the descriptor string does not
+     * describe a valid primitive type
+     */
+    PrimitiveClassRef(String descriptor) {
+        super(ConstantRefs.BSM_PRIMITIVE_CLASS, requireNonNull(descriptor), ConstantRefs.CR_Class);
+        if (descriptor.length() != 1
+            || "VIJCSBFDZ".indexOf(descriptor.charAt(0)) < 0)
+            throw new IllegalArgumentException(String.format("%s is not a valid primitive type descriptor", descriptor));
+        this.descriptor = descriptor;
+    }
+
+    @Override
+    public String descriptorString() {
+        return descriptor;
+    }
+
+    @Override
+    public Class<?> resolveConstantRef(MethodHandles.Lookup lookup) {
+        return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveType();
+    }
+
+    @Override
+    public Optional<? extends ConstantRef<? super ConstantRef<Class<?>>>> toConstantRef(MethodHandles.Lookup lookup) {
+        return DynamicConstantRef.symbolizeHelper(lookup, ConstantRefs.MHR_CLASSREF_FACTORY, ConstantRefs.CR_ClassRef, descriptorString());
+    }
+
+    @Override
+    public String toString() {
+        return String.format("PrimitiveClassRef[%s]", simpleName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/RefBootstraps.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandles;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_ClassRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_ConstantRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_DynamicConstantRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_EnumRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_MethodHandleRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_MethodTypeRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_String;
+
+/**
+ * RefBoostraps
+ *
+ * @author Brian Goetz
+ */
+public final class RefBootstraps {
+    private RefBootstraps() { }
+
+    @Foldable
+    private static final ClassRef THIS_CLASS = ClassRef.of("java.lang.invoke.constant.RefBootstraps");
+
+    /** Bootstrap for ClassRef */
+    @Foldable
+    public static final MethodHandleRef BSM_CLASSREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "classRef", CR_ClassRef,
+                                                                                         CR_String);
+
+    /** Bootstrap for MethodTypeRef */
+    @Foldable
+    public static final MethodHandleRef BSM_METHODTYPEREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "methodTypeRef", CR_MethodTypeRef,
+                                                                                              CR_String);
+
+    /** Bootstrap for MethodHandleRef */
+    @Foldable
+    public static final MethodHandleRef BSM_METHODHANDLEREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "methodHandleRef", CR_MethodHandleRef,
+                                                                                                CR_String, CR_String, CR_String, CR_String);
+
+    /** Bootstrap for DynamicConstantRef */
+    @Foldable
+    public static final MethodHandleRef BSM_DYNAMICCONSTANTREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "dynamicConstantRef", CR_DynamicConstantRef,
+                                                                                                   CR_String, CR_String, CR_String, CR_String, CR_String,
+
+                                                                                                   CR_ConstantRef.array());
+
+    /** Bootstrap for ClassRef */
+    @Foldable
+    public static final MethodHandleRef BSM_ENUMREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "enumRef", CR_EnumRef,
+                                                                                        CR_String, CR_String);
+    /**
+     * Bootstrap for ClassRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param descriptor descriptor for class
+     * @return the ClassRef
+     */
+    public static ClassRef classRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                    String descriptor) {
+        // @@@ Can fold descriptor into name channel, with encoding from BytecodeName
+        return ClassRef.ofDescriptor(descriptor);
+    }
+
+    /**
+     * Bootstrap for MethodTypeRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param descriptor descriptor for method
+     * @return the MethodTypeRef
+     */
+    public static MethodTypeRef methodTypeRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                              String descriptor) {
+        // @@@ Can fold descriptor into name channel, with encoding from BytecodeName
+        return MethodTypeRef.ofDescriptor(descriptor);
+    }
+
+    /**
+     * Bootstrap for MethodHandleRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param bsmKindName kind
+     * @param bsmOwner owner
+     * @param bsmName name
+     * @param bsmDesc desc
+     * @return the MethodHandleRef
+     */
+    public static MethodHandleRef methodHandleRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                                  String bsmKindName, String bsmOwner, String bsmName, String bsmDesc) {
+        return MethodHandleRef.of(MethodHandleRef.Kind.valueOf(bsmKindName), ClassRef.ofDescriptor(bsmOwner), bsmName, MethodTypeRef.ofDescriptor(bsmDesc));
+    }
+
+    /**
+     * Bootstrap for DynamicConstantRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param bsmOwner owner
+     * @param bsmName name
+     * @param bsmDesc desc
+     * @param invName invName
+     * @param invType invType
+     * @param args bsm args
+     * @return the DynamicConstantRef
+     */
+    public static DynamicConstantRef<?> dynamicConstantRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                                           String bsmOwner, String bsmName, String bsmDesc,
+                                                           String invName, String invType,
+                                                           ConstantRef<?>... args) {
+        return DynamicConstantRef.of(MethodHandleRef.of(MethodHandleRef.Kind.STATIC, ClassRef.ofDescriptor(bsmOwner), bsmName, MethodTypeRef.ofDescriptor(bsmDesc)),
+                                     invName, ClassRef.ofDescriptor(invType), args);
+
+    }
+
+    /**
+     * Bootstrap for EnumRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param classDescriptor enum class
+     * @param constantName enum constant
+     * @return the EnumRef
+     */
+    public static EnumRef<?> enumRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                     String classDescriptor, String constantName) {
+        return EnumRef.of(ClassRef.ofDescriptor(classDescriptor), constantName);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/VarHandleRef.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 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 java.lang.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Optional;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_ClassRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_String;
+import static java.lang.invoke.constant.ConstantRefs.CR_VarHandleRef;
+
+/**
+ * A symbolic reference for a {@link VarHandle} constant.
+ */
+public final class VarHandleRef extends DynamicConstantRef<VarHandle>
+        implements Constable<ConstantRef<VarHandle>> {
+
+    private static final ConstantRef<?>[] EMPTY_ARGS = new ConstantRef<?>[0];
+
+    /**
+     * Kinds of variable handle refs
+     */
+    private enum Kind {
+        @Foldable
+        FIELD(ConstantRefs.BSM_VARHANDLE_FIELD, ConstantRefs.MHR_VARHANDLEREF_OFFIELD),
+        @Foldable
+        STATIC_FIELD(ConstantRefs.BSM_VARHANDLE_STATIC_FIELD, ConstantRefs.MHR_VARHANDLEREF_OFSTATIC),
+        @Foldable
+        ARRAY(ConstantRefs.BSM_VARHANDLE_ARRAY, ConstantRefs.MHR_VARHANDLEREF_OFARRAY);
+
+        final MethodHandleRef bootstrapMethod;
+        final MethodHandleRef refFactory;
+
+        Kind(MethodHandleRef bootstrapMethod, MethodHandleRef refFactory) {
+            this.bootstrapMethod = bootstrapMethod;
+            this.refFactory = refFactory;
+        }
+
+        List<ConstantRef<?>> toBSMArgs(ClassRef declaringClass, String name, ClassRef varType) {
+            switch (this) {
+                case FIELD:
+                case STATIC_FIELD:
+                    return List.of(declaringClass, name, varType);
+                case ARRAY:
+                    return List.of(declaringClass);
+                default:
+                    throw new InternalError("Cannot reach here");
+            }
+        }
+    }
+
+    private final Kind kind;
+    private final ClassRef declaringClass;
+    private final ClassRef varType;
+
+    /**
+     * Construct a {@linkplain VarHandleRef}
+     *
+     * @param kind the kind of of the var handle
+     * @param name the name of the field, for field var handles
+     * @param declaringClass the name of the declaring class, for field var handles
+     * @param varType the type of the variable
+     * @throws NullPointerException if any required argument is null
+     */
+    private VarHandleRef(Kind kind, String name, ClassRef declaringClass, ClassRef varType) {
+        super(kind.bootstrapMethod, name,
+              ConstantRefs.CR_VarHandle,
+              kind.toBSMArgs(declaringClass, name, varType).toArray(EMPTY_ARGS));
+        this.kind = kind;
+        this.declaringClass = declaringClass;
+        this.varType = varType;
+    }
+
+    /**
+     * Returns a {@code VarHandleRef} corresponding to a {@link VarHandle}
+     * for an instance field.
+     *
+     * @param declaringClass the class in which the field is declared
+     * @param name the name of the field
+     * @param fieldType the type of the field
+     * @return the {@code VarHandleRef}
+     * @throws NullPointerException if any of the arguments are null
+     */
+    @Foldable
+    public static VarHandleRef ofField(ClassRef declaringClass, String name, ClassRef fieldType) {
+        Objects.requireNonNull(declaringClass);
+        Objects.requireNonNull(name);
+        Objects.requireNonNull(fieldType);
+        return new VarHandleRef(Kind.FIELD, name, declaringClass, fieldType);
+    }
+
+    /**
+     * Returns a {@code VarHandleRef} corresponding to a {@link VarHandle}
+     * for a static field.
+     *
+     * @param declaringClass the class in which the field is declared
+     * @param name the name of the field
+     * @param fieldType the type of the field
+     * @return the {@code VarHandleRef}
+     * @throws NullPointerException if any of the arguments are null
+     */
+    @Foldable
+    public static VarHandleRef ofStaticField(ClassRef declaringClass, String name, ClassRef fieldType) {
+        Objects.requireNonNull(declaringClass);
+        Objects.requireNonNull(name);
+        Objects.requireNonNull(fieldType);
+        return new VarHandleRef(Kind.STATIC_FIELD, name, declaringClass, fieldType);
+    }
+
+    /**
+     * Returns a {@code VarHandleRef} corresponding to a {@link VarHandle}
+     * for for an array type.
+     *
+     * @param arrayClass the type of the array
+     * @return the {@code VarHandleRef}
+     * @throws NullPointerException if any of the arguments are null
+     */
+    @Foldable
+    public static VarHandleRef ofArray(ClassRef arrayClass) {
+        Objects.requireNonNull(arrayClass);
+        if (!arrayClass.isArray())
+            throw new IllegalArgumentException("Array class argument not an array: " + arrayClass);
+        return new VarHandleRef(Kind.ARRAY, "_", arrayClass, arrayClass.componentType());
+    }
+
+    /**
+     * Returns the type of the variable described by this symbolic reference.
+     *
+     * @return the variable type
+     */
+    @Foldable
+    public ClassRef varType() { return varType; }
+
+    // @@@ should this be the of co-ordinate types? there by better mirroring
+    // VarHandle this makes it slightly more involved since the array VH has
+    // to inject it's index
+    /**
+     * Returns the declaring class of the variable described by this symbolic
+     * reference.
+     *
+     * <p>If the declaring class is an array type then the declaring class
+     * will be the component type of the array type.
+     *
+     * @return the declaring class
+     */
+    @Foldable
+    public ClassRef declaringClass() { return declaringClass; }
+
+    /* @@@
+    MethodTypeRef accessModeTypeRef(AccessMode accessMode)
+     */
+
+    /* @@@
+    MethodHandleRef toMethodHandleRef(AccessMode accessMode)
+     */
+
+    @Override
+    public VarHandle resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+        switch (kind) {
+            case FIELD:
+                return lookup.findVarHandle(declaringClass.resolveConstantRef(lookup),
+                                            constantName(),
+                                            varType.resolveConstantRef(lookup));
+            case STATIC_FIELD:
+                return lookup.findStaticVarHandle(declaringClass.resolveConstantRef(lookup),
+                                                  constantName(),
+                                                  varType.resolveConstantRef(lookup));
+            case ARRAY:
+                return MethodHandles.arrayElementVarHandle(declaringClass.resolveConstantRef(lookup));
+            default:
+                throw new InternalError("Cannot reach here");
+        }
+    }
+
+    @Override
+    public Optional<ConstantRef<ConstantRef<VarHandle>>> toConstantRef(MethodHandles.Lookup lookup) {
+        try {
+            ArrayList<ConstantRef<?>> args = new ArrayList<>();
+            args.add(declaringClass.toConstantRef(lookup).orElseThrow());
+            if (kind != Kind.ARRAY) {
+                args.add(constantName());
+                args.add(varType.toConstantRef(lookup).orElseThrow());
+            }
+            return Optional.of(DynamicConstantRef.ofInvoke(kind.refFactory, CR_VarHandleRef,
+                                                           args.toArray(EMPTY_ARGS)));
+        } catch (NoSuchElementException e) {
+            return Optional.empty();
+        }
+    }
+
+    @Override
+    public String toString() {
+        switch (kind) {
+            case FIELD:
+            case STATIC_FIELD:
+                return String.format("VarHandleRef[%s%s.%s:%s]",
+                                     (kind == Kind.STATIC_FIELD) ? "static " : "",
+                                     declaringClass.simpleName(), constantName(), varType.simpleName());
+            case ARRAY:
+                return String.format("VarHandleRef[%s[]]", declaringClass.simpleName());
+            default:
+                throw new InternalError("Cannot reach here");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/package-info.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * Classes and interfaces to represent <em>nominal references</em> to run-time
+ * entities such as classes or method handles and classfile entities such as
+ * constant pool entries or {@code invokedynamic} call sites.  These classes
+ * are suitable for use in bytecode reading and writing APIs, {@code invokedynamic}
+ * bootstraps, bytecode intrinsic APIs (such as {@link java.lang.invoke.Intrinsics#ldc(java.lang.invoke.constant.ConstantRef)}),
+ * or compile- and link-time program analysis.
+ *
+ * <p>Every API that reads and writes bytecode instructions needs to model the
+ * operands to these instructions, or other classfile structures such as entries
+ * in the bootstrap methods table or stack maps, which frequently correspond to
+ * entries in the classfile constant pool. Such entries can denote values of
+ * fundamental types, such as strings or integers; parts of a program, such as
+ * classes or method handles; or values of arbitrary user-defined types.  The
+ * {@link java.lang.invoke.constant.ConstantRef} hierarchy provides a representation of
+ * constant pool entries in nominal form that is convenient for APIs to model
+ * operands of bytecode instructions.
+ *
+ * <p>A {@link java.lang.invoke.constant.ConstantRef} is a description of a constant
+ * value.  Such a description is the <em>nominal form</em> of the constant value;
+ * it is not hte value itself, but rather a "recipe" for storing the value in
+ * a constant pool entry, or reconstituting the value given a class loading
+ * context.  Every {@link java.lang.invoke.constant.ConstantRef} knows how to <em>resolve</em>
+ * itself -- compute the value that it describes -- via the
+ * {@link java.lang.invoke.constant.ConstantRef#resolveConstantRef(java.lang.invoke.MethodHandles.Lookup)}
+ * method.  This allows an API which accepts {@link java.lang.invoke.constant.ConstantRef}
+ * objects to evaluate them reflectively, provided that the classes and methods
+ * referenced in their nominal description are present and accessible.
+ *
+ * <p>The subtypes of of {@link java.lang.invoke.constant.ConstantRef} describe various kinds
+ * of constant values.  For each type of constant pool entry defined in JVMS 4.4,
+ * there is a corresponding subtype of {@link java.lang.invoke.constant.ConstantRef}:
+ * {@code ConstantClassRef}, {@code ConstantMethodTypeRef},
+ * {@code ConstantMethodHandleRef}, {@code String}, {@code Integer}, {@code Long},
+ * {@code Float}, {@code Double}, and {@code DynamicConstantRef}.  These classes
+ * provides accessor methods to extrac the information needed to store a value
+ * in the constant pool.  When a bytecode-writing API encounters a {@link java.lang.invoke.constant.ConstantRef},
+ * it should case over these types to represent it in the constant pool.
+ * When a bytecode-reading API encounters a constant pool entry, it can
+ * convert it to the appropriate type of nominal reference.  For dynamic
+ * constants, bytecode-reading APIs may wish to use the factory
+ * {@link java.lang.invoke.constant.DynamicConstantRef#ofCanonical(java.lang.invoke.constant.MethodHandleRef, java.lang.String, java.lang.invoke.constant.ClassRef, java.lang.invoke.constant.ConstantRef[])},
+ * which will inspect the bootstrap and, for well-known bootstraps, instantiate
+ * a more specific subtype of {@link java.lang.invoke.constant.DynamicConstantRef}, such as
+ * {@link java.lang.invoke.constant.EnumRef}.
+ *
+ * <p>Another way to obtain the nominal description of a value is to ask the value
+ * itself.  A {@link java.lang.invoke.constant.Constable} is a type whose values can describe
+ * themselves in nominal form as a {@link java.lang.invoke.constant.ConstantRef}.  Fundamental
+ * types such as {@link java.lang.String} and {@link java.lang.Class} implement
+ * {@link java.lang.invoke.constant.Constable}, and every instance of these classes can
+ * provide itself in nominal form.  User-defined classes can also implement
+ * {@link java.lang.invoke.constant.Constable}.
+ *
+ * <p>This package also includes the {@link java.lang.invoke.constant.DynamicCallSiteRef}
+ * class, which is a representation of a constant pool entry that is never an
+ * argument to bytecode instructions.  Instead, it is a description of the
+ * bootstrap method, invocation name and type, and static arguments associated
+ * with an {@code invokedynamic} instruction, and is used by the
+ * {@link java.lang.invoke.Intrinsics#invokedynamic(java.lang.invoke.constant.DynamicCallSiteRef, java.lang.Object...)}
+ * API for expressing {@code invokedynamic} call sites in Java source files.
+ *
+ */
+package java.lang.invoke.constant;
+
--- a/src/java.base/share/classes/java/lang/invoke/package-info.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/package-info.java	Thu Apr 05 12:28:38 2018 -0400
@@ -122,8 +122,11 @@
  * On success the call site then becomes permanently linked to the {@code invokedynamic}
  * instruction.
  * <p>
- * For a dynamically-computed constant, the result of the bootstrap method is cached
- * as the resolved constant value.
+ * For a dynamically-computed constant, the first parameter of the bootstrap
+ * method must be assignable to {@code MethodHandles.Lookup}. If this condition
+ * is not met, a {@code BootstrapMethodError} is thrown.
+ * On success the result of the bootstrap method is cached as the resolved
+ * constant value.
  * <p>
  * If an exception, {@code E} say, occurs during execution of the bootstrap method, then
  * resolution fails and terminates abnormally. {@code E} is rethrown if the type of
@@ -171,16 +174,25 @@
  * <h2>Types of bootstrap methods</h2>
  * For a dynamically-computed call site, the bootstrap method is invoked with parameter
  * types {@code MethodHandles.Lookup}, {@code String}, {@code MethodType}, and the types
- * of any static arguments; the return type is {@code CallSite}. For a
- * dynamically-computed constant, the bootstrap method is invoked with parameter types
+ * of any static arguments; the return type is {@code CallSite}.
+ * <p>
+ * For a dynamically-computed constant, the bootstrap method is invoked with parameter types
  * {@code MethodHandles.Lookup}, {@code String}, {@code Class}, and the types of any
  * static arguments; the return type is the type represented by the {@code Class}.
- *
+ * <p>
  * Because {@link java.lang.invoke.MethodHandle#invoke MethodHandle.invoke} allows for
- * adaptations between the invoked method type and the method handle's method type,
+ * adaptations between the invoked method type and the bootstrap method handle's method type,
  * there is flexibility in the declaration of the bootstrap method.
- * For example, the first argument could be {@code Object}
- * instead of {@code MethodHandles.Lookup}, and the return type
+ * For a dynamically-computed constant the first parameter type of the bootstrap method handle
+ * must be assignable to {@code MethodHandles.Lookup}, other than that constraint the same degree
+ * of flexibility applies to bootstrap methods of dynamically-computed call sites and
+ * dynamically-computed constants. This constraint allows for the future possibility
+ * where the bootstrap method is invoked with just the parameter types of static arguments,
+ * thereby supporting a wider range of methods compatible with the static arguments
+ * (such as methods that don't declare or require the lookup, name, and type meta-data
+ * parameters).
+ * <p> For example, for dynamically-computed call site, a the first argument
+ * could be {@code Object} instead of {@code MethodHandles.Lookup}, and the return type
  * could also be {@code Object} instead of {@code CallSite}.
  * (Note that the types and number of the stacked arguments limit
  * the legal kinds of bootstrap methods to appropriately typed
@@ -227,7 +239,10 @@
  * {@code String} and {@code Integer} (or {@code int}), respectively.
  * The second-to-last example assumes that all extra arguments are of type
  * {@code String}.
- * The other examples work with all types of extra arguments.
+ * The other examples work with all types of extra arguments.  Note that all
+ * the examples except the second and third also work with dynamically-computed
+ * constants if the return type is changed to be compatible with the
+ * constant's declared type (such as {@code Object}, which is always compatible).
  * <p>
  * Since dynamically-computed constants can be provided as static arguments to bootstrap
  * methods, there are no limitations on the types of bootstrap arguments.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/lang/annotation/Foldable.java	Thu Apr 05 12:28:38 2018 -0400
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017, 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 jdk.internal.lang.annotation;
+
+import java.lang.annotation.*;
+
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
+import java.lang.invoke.Intrinsics;
+
+/**
+ * Identifies a method that is a candidate for compile-time constant folding.
+ * Such a method must be a <em>pure function</em> of its inputs, all inputs
+ * (including the receiver, if applied to an instance method) must be value-based
+ * types, and the output must be a value-based type that is representable
+ * in the constant pool ({@link Constable} or {@link ConstantRef}).
+ *
+ * <p>For accesses of fields annotated as {@linkplain Foldable}, and invocations
+ * of methods annotated as {@linkplain Foldable} whose arguments (and, for instance
+ * methods, the receiver) are all constant expressions, the compiler may evaluate
+ * the expression reflectively at compile time and replace it with a constant
+ * load of the result, or track the result as a constant expression for possible
+ * intrinsification via methods in {@link Intrinsics}.
+ *
+ * @see Constable
+ * @see ConstantRef
+ * @see Intrinsics
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ ElementType.METHOD, ElementType.FIELD })
+public @interface Foldable { }
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationVisitor.java	Thu Apr 05 12:28:38 2018 -0400
@@ -1,198 +1,172 @@
-/*
- * 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.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file:
- *
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// 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.
+//
+// This file is available under and governed by the GNU General Public
+// License version 2 only, as published by the Free Software Foundation.
+// However, the following notice accompanied the original version of this
+// file:
+//
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the copyright holders nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
 package jdk.internal.org.objectweb.asm;
 
 /**
- * A visitor to visit a Java annotation. The methods of this class must be
- * called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |
- * <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.
+ * A visitor to visit a Java annotation. The methods of this class must be called in the following
+ * order: ( <tt>visit</tt> | <tt>visitEnum</tt> | <tt>visitAnnotation</tt> | <tt>visitArray</tt> )*
+ * <tt>visitEnd</tt>.
  *
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
 public abstract class AnnotationVisitor {
 
-    /**
-     * The ASM API version implemented by this visitor. The value of this field
-     * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
-     */
-    protected final int api;
+  /**
+   * The ASM API version implemented by this visitor. The value of this field must be one of {@link
+   * Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
+   */
+  protected final int api;
 
-    /**
-     * The annotation visitor to which this visitor must delegate method calls.
-     * May be null.
-     */
-    protected AnnotationVisitor av;
+  /** The annotation visitor to which this visitor must delegate method calls. May be null. */
+  protected AnnotationVisitor av;
 
-    /**
-     * Constructs a new {@link AnnotationVisitor}.
-     *
-     * @param api
-     *            the ASM API version implemented by this visitor. Must be one
-     *            of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
-     */
-    public AnnotationVisitor(final int api) {
-        this(api, null);
+  /**
+   * Constructs a new {@link AnnotationVisitor}.
+   *
+   * @param api the ASM API version implemented by this visitor. Must be one of {@link
+   *     Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
+   */
+  public AnnotationVisitor(final int api) {
+    this(api, null);
+  }
+
+  /**
+   * Constructs a new {@link AnnotationVisitor}.
+   *
+   * @param api the ASM API version implemented by this visitor. Must be one of {@link
+   *     Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
+   * @param annotationVisitor the annotation visitor to which this visitor must delegate method
+   *     calls. May be null.
+   */
+  public AnnotationVisitor(final int api, final AnnotationVisitor annotationVisitor) {
+    if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
+      throw new IllegalArgumentException();
     }
+    this.api = api;
+    this.av = annotationVisitor;
+  }
 
-    /**
-     * Constructs a new {@link AnnotationVisitor}.
-     *
-     * @param api
-     *            the ASM API version implemented by this visitor. Must be one
-     *            of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
-     * @param av
-     *            the annotation visitor to which this visitor must delegate
-     *            method calls. May be null.
-     */
-    public AnnotationVisitor(final int api, final AnnotationVisitor av) {
-        if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
-            throw new IllegalArgumentException();
-        }
-        this.api = api;
-        this.av = av;
+  /**
+   * Visits a primitive value of the annotation.
+   *
+   * @param name the value name.
+   * @param value the actual value, whose type must be {@link Byte}, {@link Boolean}, {@link
+   *     Character}, {@link Short}, {@link Integer} , {@link Long}, {@link Float}, {@link Double},
+   *     {@link String} or {@link Type} of {@link Type#OBJECT} or {@link Type#ARRAY} sort. This
+   *     value can also be an array of byte, boolean, short, char, int, long, float or double values
+   *     (this is equivalent to using {@link #visitArray} and visiting each array element in turn,
+   *     but is more convenient).
+   */
+  public void visit(final String name, final Object value) {
+    if (av != null) {
+      av.visit(name, value);
     }
+  }
 
-    /**
-     * Visits a primitive value of the annotation.
-     *
-     * @param name
-     *            the value name.
-     * @param value
-     *            the actual value, whose type must be {@link Byte},
-     *            {@link Boolean}, {@link Character}, {@link Short},
-     *            {@link Integer} , {@link Long}, {@link Float}, {@link Double},
-     *            {@link String} or {@link Type} of OBJECT or ARRAY sort. This
-     *            value can also be an array of byte, boolean, short, char, int,
-     *            long, float or double values (this is equivalent to using
-     *            {@link #visitArray visitArray} and visiting each array element
-     *            in turn, but is more convenient).
-     */
-    public void visit(String name, Object value) {
-        if (av != null) {
-            av.visit(name, value);
-        }
+  /**
+   * Visits an enumeration value of the annotation.
+   *
+   * @param name the value name.
+   * @param descriptor the class descriptor of the enumeration class.
+   * @param value the actual enumeration value.
+   */
+  public void visitEnum(final String name, final String descriptor, final String value) {
+    if (av != null) {
+      av.visitEnum(name, descriptor, value);
     }
+  }
 
-    /**
-     * Visits an enumeration value of the annotation.
-     *
-     * @param name
-     *            the value name.
-     * @param desc
-     *            the class descriptor of the enumeration class.
-     * @param value
-     *            the actual enumeration value.
-     */
-    public void visitEnum(String name, String desc, String value) {
-        if (av != null) {
-            av.visitEnum(name, desc, value);
-        }
+  /**
+   * Visits a nested annotation value of the annotation.
+   *
+   * @param name the value name.
+   * @param descriptor the class descriptor of the nested annotation class.
+   * @return a visitor to visit the actual nested annotation value, or <tt>null</tt> if this visitor
+   *     is not interested in visiting this nested annotation. <i>The nested annotation value must
+   *     be fully visited before calling other methods on this annotation visitor</i>.
+   */
+  public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
+    if (av != null) {
+      return av.visitAnnotation(name, descriptor);
     }
+    return null;
+  }
 
-    /**
-     * Visits a nested annotation value of the annotation.
-     *
-     * @param name
-     *            the value name.
-     * @param desc
-     *            the class descriptor of the nested annotation class.
-     * @return a visitor to visit the actual nested annotation value, or
-     *         <tt>null</tt> if this visitor is not interested in visiting this
-     *         nested annotation. <i>The nested annotation value must be fully
-     *         visited before calling other methods on this annotation
-     *         visitor</i>.
-     */
-    public AnnotationVisitor visitAnnotation(String name, String desc) {
-        if (av != null) {
-            return av.visitAnnotation(name, desc);
-        }
-        return null;
+  /**
+   * Visits an array value of the annotation. Note that arrays of primitive types (such as byte,
+   * boolean, short, char, int, long, float or double) can be passed as value to {@link #visit
+   * visit}. This is what {@link ClassReader} does.
+   *
+   * @param name the value name.
+   * @return a visitor to visit the actual array value elements, or <tt>null</tt> if this visitor is
+   *     not interested in visiting these values. The 'name' parameters passed to the methods of
+   *     this visitor are ignored. <i>All the array values must be visited before calling other
+   *     methods on this annotation visitor</i>.
+   */
+  public AnnotationVisitor visitArray(final String name) {
+    if (av != null) {
+      return av.visitArray(name);
     }
+    return null;
+  }
 
-    /**
-     * Visits an array value of the annotation. Note that arrays of primitive
-     * types (such as byte, boolean, short, char, int, long, float or double)
-     * can be passed as value to {@link #visit visit}. This is what
-     * {@link ClassReader} does.
-     *
-     * @param name
-     *            the value name.
-     * @return a visitor to visit the actual array value elements, or
-     *         <tt>null</tt> if this visitor is not interested in visiting these
-     *         values. The 'name' parameters passed to the methods of this
-     *         visitor are ignored. <i>All the array values must be visited
-     *         before calling other methods on this annotation visitor</i>.
-     */
-    public AnnotationVisitor visitArray(String name) {
-        if (av != null) {
-            return av.visitArray(name);
-        }
-        return null;
+  /** Visits the end of the annotation. */
+  public void visitEnd() {
+    if (av != null) {
+      av.visitEnd();
     }
-
-    /**
-     * Visits the end of the annotation.
-     */
-    public void visitEnd() {
-        if (av != null) {
-            av.visitEnd();
-        }
-    }
+  }
 }
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/AnnotationWriter.java	Thu Apr 05 12:28:38 2018 -0400
@@ -1,400 +1,445 @@
-/*
- * 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.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file:
- *
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// 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.
+//
+// This file is available under and governed by the GNU General Public
+// License version 2 only, as published by the Free Software Foundation.
+// However, the following notice accompanied the original version of this
+// file:
+//
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the copyright holders nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
 package jdk.internal.org.objectweb.asm;
 
 /**
- * An {@link AnnotationVisitor} that generates annotations in bytecode form.
+ * An {@link AnnotationVisitor} that generates a corresponding 'annotation' or 'type_annotation'
+ * structure, as defined in the Java Virtual Machine Specification (JVMS). AnnotationWriter
+ * instances can be chained in a doubly linked list, from which Runtime[In]Visible[Type]Annotations
+ * attributes can be generated with the {@link #putAnnotations} method. Similarly, arrays of such
+ * lists can be used to generate Runtime[In]VisibleParameterAnnotations attributes.
  *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16">JVMS
+ *     4.7.16</a>
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20">JVMS
+ *     4.7.20</a>
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
 final class AnnotationWriter extends AnnotationVisitor {
 
-    /**
-     * The class writer to which this annotation must be added.
-     */
-    private final ClassWriter cw;
+  /** Where the constants used in this AnnotationWriter must be stored. */
+  private final SymbolTable symbolTable;
 
-    /**
-     * The number of values in this annotation.
-     */
-    private int size;
+  /**
+   * Whether values are named or not. AnnotationWriter instances used for annotation default and
+   * annotation arrays use unnamed values (i.e. they generate an 'element_value' structure for each
+   * value, instead of an element_name_index followed by an element_value).
+   */
+  private final boolean useNamedValues;
 
-    /**
-     * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
-     * writers used for annotation default and annotation arrays use unnamed
-     * values.
-     */
-    private final boolean named;
+  /**
+   * The 'annotation' or 'type_annotation' JVMS structure corresponding to the annotation values
+   * visited so far. All the fields of these structures, except the last one - the
+   * element_value_pairs array, must be set before this ByteVector is passed to the constructor
+   * (num_element_value_pairs can be set to 0, it is reset to the correct value in {@link
+   * #visitEnd()}). The element_value_pairs array is filled incrementally in the various visit()
+   * methods.
+   *
+   * <p>Note: as an exception to the above rules, for AnnotationDefault attributes (which contain a
+   * single element_value by definition), this ByteVector is initially empty when passed to the
+   * constructor, and {@link #numElementValuePairsOffset} is set to -1.
+   */
+  private final ByteVector annotation;
 
-    /**
-     * The annotation values in bytecode form. This byte vector only contains
-     * the values themselves, i.e. the number of values must be stored as a
-     * unsigned short just before these bytes.
-     */
-    private final ByteVector bv;
+  /**
+   * The offset in {@link #annotation} where {@link #numElementValuePairs} must be stored (or -1 for
+   * the case of AnnotationDefault attributes).
+   */
+  private final int numElementValuePairsOffset;
 
-    /**
-     * The byte vector to be used to store the number of values of this
-     * annotation. See {@link #bv}.
-     */
-    private final ByteVector parent;
+  /** The number of element value pairs visited so far. */
+  private int numElementValuePairs;
 
-    /**
-     * Where the number of values of this annotation must be stored in
-     * {@link #parent}.
-     */
-    private final int offset;
+  /**
+   * The previous AnnotationWriter. This field is used to store the list of annotations of a
+   * Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations
+   * (annotation values of annotation type), or for AnnotationDefault attributes.
+   */
+  private final AnnotationWriter previousAnnotation;
 
-    /**
-     * Next annotation writer. This field is used to store annotation lists.
-     */
-    AnnotationWriter next;
+  /**
+   * The next AnnotationWriter. This field is used to store the list of annotations of a
+   * Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations
+   * (annotation values of annotation type), or for AnnotationDefault attributes.
+   */
+  private AnnotationWriter nextAnnotation;
 
-    /**
-     * Previous annotation writer. This field is used to store annotation lists.
-     */
-    AnnotationWriter prev;
+  // -----------------------------------------------------------------------------------------------
+  // Constructors
+  // -----------------------------------------------------------------------------------------------
 
-    // ------------------------------------------------------------------------
-    // Constructor
-    // ------------------------------------------------------------------------
+  /**
+   * Constructs a new {@link AnnotationWriter}.
+   *
+   * @param symbolTable where the constants used in this AnnotationWriter must be stored.
+   * @param useNamedValues whether values are named or not. AnnotationDefault and annotation arrays
+   *     use unnamed values.
+   * @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to
+   *     the visited content must be stored. This ByteVector must already contain all the fields of
+   *     the structure except the last one (the element_value_pairs array).
+   * @param previousAnnotation the previously visited annotation of the
+   *     Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in
+   *     other cases (e.g. nested or array annotations).
+   */
+  AnnotationWriter(
+      final SymbolTable symbolTable,
+      final boolean useNamedValues,
+      final ByteVector annotation,
+      final AnnotationWriter previousAnnotation) {
+    super(Opcodes.ASM6);
+    this.symbolTable = symbolTable;
+    this.useNamedValues = useNamedValues;
+    this.annotation = annotation;
+    // By hypothesis, num_element_value_pairs is stored in the last unsigned short of 'annotation'.
+    this.numElementValuePairsOffset = annotation.length == 0 ? -1 : annotation.length - 2;
+    this.previousAnnotation = previousAnnotation;
+    if (previousAnnotation != null) {
+      previousAnnotation.nextAnnotation = this;
+    }
+  }
 
-    /**
-     * Constructs a new {@link AnnotationWriter}.
-     *
-     * @param cw
-     *            the class writer to which this annotation must be added.
-     * @param named
-     *            <tt>true<tt> if values are named, <tt>false</tt> otherwise.
-     * @param bv
-     *            where the annotation values must be stored.
-     * @param parent
-     *            where the number of annotation values must be stored.
-     * @param offset
-     *            where in <tt>parent</tt> the number of annotation values must
-     *            be stored.
-     */
-    AnnotationWriter(final ClassWriter cw, final boolean named,
-            final ByteVector bv, final ByteVector parent, final int offset) {
-        super(Opcodes.ASM6);
-        this.cw = cw;
-        this.named = named;
-        this.bv = bv;
-        this.parent = parent;
-        this.offset = offset;
+  /**
+   * Constructs a new {@link AnnotationWriter} using named values.
+   *
+   * @param symbolTable where the constants used in this AnnotationWriter must be stored.
+   * @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to
+   *     the visited content must be stored. This ByteVector must already contain all the fields of
+   *     the structure except the last one (the element_value_pairs array).
+   * @param previousAnnotation the previously visited annotation of the
+   *     Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in
+   *     other cases (e.g. nested or array annotations).
+   */
+  AnnotationWriter(
+      final SymbolTable symbolTable,
+      final ByteVector annotation,
+      final AnnotationWriter previousAnnotation) {
+    this(symbolTable, /* useNamedValues = */ true, annotation, previousAnnotation);
+  }
+
+  // -----------------------------------------------------------------------------------------------
+  // Implementation of the AnnotationVisitor abstract class
+  // -----------------------------------------------------------------------------------------------
+
+  @Override
+  public void visit(final String name, final Object value) {
+    // Case of an element_value with a const_value_index, class_info_index or array_index field.
+    // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
+    ++numElementValuePairs;
+    if (useNamedValues) {
+      annotation.putShort(symbolTable.addConstantUtf8(name));
     }
+    if (value instanceof String) {
+      annotation.put12('s', symbolTable.addConstantUtf8((String) value));
+    } else if (value instanceof Byte) {
+      annotation.put12('B', symbolTable.addConstantInteger(((Byte) value).byteValue()).index);
+    } else if (value instanceof Boolean) {
+      int booleanValue = ((Boolean) value).booleanValue() ? 1 : 0;
+      annotation.put12('Z', symbolTable.addConstantInteger(booleanValue).index);
+    } else if (value instanceof Character) {
+      annotation.put12('C', symbolTable.addConstantInteger(((Character) value).charValue()).index);
+    } else if (value instanceof Short) {
+      annotation.put12('S', symbolTable.addConstantInteger(((Short) value).shortValue()).index);
+    } else if (value instanceof Type) {
+      annotation.put12('c', symbolTable.addConstantUtf8(((Type) value).getDescriptor()));
+    } else if (value instanceof byte[]) {
+      byte[] byteArray = (byte[]) value;
+      annotation.put12('[', byteArray.length);
+      for (byte byteValue : byteArray) {
+        annotation.put12('B', symbolTable.addConstantInteger(byteValue).index);
+      }
+    } else if (value instanceof boolean[]) {
+      boolean[] booleanArray = (boolean[]) value;
+      annotation.put12('[', booleanArray.length);
+      for (boolean booleanValue : booleanArray) {
+        annotation.put12('Z', symbolTable.addConstantInteger(booleanValue ? 1 : 0).index);
+      }
+    } else if (value instanceof short[]) {
+      short[] shortArray = (short[]) value;
+      annotation.put12('[', shortArray.length);
+      for (short shortValue : shortArray) {
+        annotation.put12('S', symbolTable.addConstantInteger(shortValue).index);
+      }
+    } else if (value instanceof char[]) {
+      char[] charArray = (char[]) value;
+      annotation.put12('[', charArray.length);
+      for (char charValue : charArray) {
+        annotation.put12('C', symbolTable.addConstantInteger(charValue).index);
+      }
+    } else if (value instanceof int[]) {
+      int[] intArray = (int[]) value;
+      annotation.put12('[', intArray.length);
+      for (int intValue : intArray) {
+        annotation.put12('I', symbolTable.addConstantInteger(intValue).index);
+      }
+    } else if (value instanceof long[]) {
+      long[] longArray = (long[]) value;
+      annotation.put12('[', longArray.length);
+      for (long longValue : longArray) {
+        annotation.put12('J', symbolTable.addConstantLong(longValue).index);
+      }
+    } else if (value instanceof float[]) {
+      float[] floatArray = (float[]) value;
+      annotation.put12('[', floatArray.length);
+      for (float floatValue : floatArray) {
+        annotation.put12('F', symbolTable.addConstantFloat(floatValue).index);
+      }
+    } else if (value instanceof double[]) {
+      double[] doubleArray = (double[]) value;
+      annotation.put12('[', doubleArray.length);
+      for (double doubleValue : doubleArray) {
+        annotation.put12('D', symbolTable.addConstantDouble(doubleValue).index);
+      }
+    } else {
+      Symbol symbol = symbolTable.addConstant(value);
+      annotation.put12(".s.IFJDCS".charAt(symbol.tag), symbol.index);
+    }
+  }
 
-    // ------------------------------------------------------------------------
-    // Implementation of the AnnotationVisitor abstract class
-    // ------------------------------------------------------------------------
+  @Override
+  public void visitEnum(final String name, final String descriptor, final String value) {
+    // Case of an element_value with an enum_const_value field.
+    // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
+    ++numElementValuePairs;
+    if (useNamedValues) {
+      annotation.putShort(symbolTable.addConstantUtf8(name));
+    }
+    annotation
+        .put12('e', symbolTable.addConstantUtf8(descriptor))
+        .putShort(symbolTable.addConstantUtf8(value));
+  }
 
-    @Override
-    public void visit(final String name, final Object value) {
-        ++size;
-        if (named) {
-            bv.putShort(cw.newUTF8(name));
-        }
-        if (value instanceof String) {
-            bv.put12('s', cw.newUTF8((String) value));
-        } else if (value instanceof Byte) {
-            bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
-        } else if (value instanceof Boolean) {
-            int v = ((Boolean) value).booleanValue() ? 1 : 0;
-            bv.put12('Z', cw.newInteger(v).index);
-        } else if (value instanceof Character) {
-            bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
-        } else if (value instanceof Short) {
-            bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
-        } else if (value instanceof Type) {
-            bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
-        } else if (value instanceof byte[]) {
-            byte[] v = (byte[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('B', cw.newInteger(v[i]).index);
-            }
-        } else if (value instanceof boolean[]) {
-            boolean[] v = (boolean[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
-            }
-        } else if (value instanceof short[]) {
-            short[] v = (short[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('S', cw.newInteger(v[i]).index);
-            }
-        } else if (value instanceof char[]) {
-            char[] v = (char[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('C', cw.newInteger(v[i]).index);
-            }
-        } else if (value instanceof int[]) {
-            int[] v = (int[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('I', cw.newInteger(v[i]).index);
-            }
-        } else if (value instanceof long[]) {
-            long[] v = (long[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('J', cw.newLong(v[i]).index);
-            }
-        } else if (value instanceof float[]) {
-            float[] v = (float[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('F', cw.newFloat(v[i]).index);
-            }
-        } else if (value instanceof double[]) {
-            double[] v = (double[]) value;
-            bv.put12('[', v.length);
-            for (int i = 0; i < v.length; i++) {
-                bv.put12('D', cw.newDouble(v[i]).index);
-            }
-        } else {
-            Item i = cw.newConstItem(value);
-            bv.put12(".s.IFJDCS".charAt(i.type), i.index);
-        }
+  @Override
+  public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
+    // Case of an element_value with an annotation_value field.
+    // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
+    ++numElementValuePairs;
+    if (useNamedValues) {
+      annotation.putShort(symbolTable.addConstantUtf8(name));
     }
+    // Write tag and type_index, and reserve 2 bytes for num_element_value_pairs.
+    annotation.put12('@', symbolTable.addConstantUtf8(descriptor)).putShort(0);
+    return new AnnotationWriter(symbolTable, annotation, null);
+  }
 
-    @Override
-    public void visitEnum(final String name, final String desc,
-            final String value) {
-        ++size;
-        if (named) {
-            bv.putShort(cw.newUTF8(name));
-        }
-        bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
+  @Override
+  public AnnotationVisitor visitArray(final String name) {
+    // Case of an element_value with an array_value field.
+    // https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1
+    ++numElementValuePairs;
+    if (useNamedValues) {
+      annotation.putShort(symbolTable.addConstantUtf8(name));
     }
+    // Write tag, and reserve 2 bytes for num_values. Here we take advantage of the fact that the
+    // end of an element_value of array type is similar to the end of an 'annotation' structure: an
+    // unsigned short num_values followed by num_values element_value, versus an unsigned short
+    // num_element_value_pairs, followed by num_element_value_pairs { element_name_index,
+    // element_value } tuples. This allows us to use an AnnotationWriter with unnamed values to
+    // visit the array elements. Its num_element_value_pairs will correspond to the number of array
+    // elements and will be stored in what is in fact num_values.
+    annotation.put12('[', 0);
+    return new AnnotationWriter(symbolTable, /* useNamedValues = */ false, annotation, null);
+  }
 
-    @Override
-    public AnnotationVisitor visitAnnotation(final String name,
-            final String desc) {
-        ++size;
-        if (named) {
-            bv.putShort(cw.newUTF8(name));
-        }
-        // write tag and type, and reserve space for values count
-        bv.put12('@', cw.newUTF8(desc)).putShort(0);
-        return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
+  @Override
+  public void visitEnd() {
+    if (numElementValuePairsOffset != -1) {
+      byte[] data = annotation.data;
+      data[numElementValuePairsOffset] = (byte) (numElementValuePairs >>> 8);
+      data[numElementValuePairsOffset + 1] = (byte) numElementValuePairs;
     }
+  }
 
-    @Override
-    public AnnotationVisitor visitArray(final String name) {
-        ++size;
-        if (named) {
-            bv.putShort(cw.newUTF8(name));
-        }
-        // write tag, and reserve space for array size
-        bv.put12('[', 0);
-        return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
+  // -----------------------------------------------------------------------------------------------
+  // Utility methods
+  // -----------------------------------------------------------------------------------------------
+
+  /**
+   * Returns the size of a Runtime[In]Visible[Type]Annotations attribute containing this annotation
+   * and all its <i>predecessors</i> (see {@link #previousAnnotation}. Also adds the attribute name
+   * to the constant pool of the class (if not null).
+   *
+   * @param attributeName one of "Runtime[In]Visible[Type]Annotations", or null.
+   * @return the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing this
+   *     annotation and all its predecessors. This includes the size of the attribute_name_index and
+   *     attribute_length fields.
+   */
+  int computeAnnotationsSize(final String attributeName) {
+    if (attributeName != null) {
+      symbolTable.addConstantUtf8(attributeName);
     }
+    // The attribute_name_index, attribute_length and num_annotations fields use 8 bytes.
+    int attributeSize = 8;
+    AnnotationWriter annotationWriter = this;
+    while (annotationWriter != null) {
+      attributeSize += annotationWriter.annotation.length;
+      annotationWriter = annotationWriter.previousAnnotation;
+    }
+    return attributeSize;
+  }
 
-    @Override
-    public void visitEnd() {
-        if (parent != null) {
-            byte[] data = parent.data;
-            data[offset] = (byte) (size >>> 8);
-            data[offset + 1] = (byte) size;
-        }
+  /**
+   * Puts a Runtime[In]Visible[Type]Annotations attribute containing this annotations and all its
+   * <i>predecessors</i> (see {@link #previousAnnotation} in the given ByteVector. Annotations are
+   * put in the same order they have been visited.
+   *
+   * @param attributeNameIndex the constant pool index of the attribute name (one of
+   *     "Runtime[In]Visible[Type]Annotations").
+   * @param output where the attribute must be put.
+   */
+  void putAnnotations(final int attributeNameIndex, final ByteVector output) {
+    int attributeLength = 2; // For num_annotations.
+    int numAnnotations = 0;
+    AnnotationWriter annotationWriter = this;
+    AnnotationWriter firstAnnotation = null;
+    while (annotationWriter != null) {
+      // In case the user forgot to call visitEnd().
+      annotationWriter.visitEnd();
+      attributeLength += annotationWriter.annotation.length;
+      numAnnotations++;
+      firstAnnotation = annotationWriter;
+      annotationWriter = annotationWriter.previousAnnotation;
     }
+    output.putShort(attributeNameIndex);
+    output.putInt(attributeLength);
+    output.putShort(numAnnotations);
+    annotationWriter = firstAnnotation;
+    while (annotationWriter != null) {
+      output.putByteArray(annotationWriter.annotation.data, 0, annotationWriter.annotation.length);
+      annotationWriter = annotationWriter.nextAnnotation;
+    }
+  }
 
-    // ------------------------------------------------------------------------
-    // Utility methods
-    // ------------------------------------------------------------------------
+  /**
+   * Returns the size of a Runtime[In]VisibleParameterAnnotations attribute containing all the
+   * annotation lists from the given AnnotationWriter sub-array. Also adds the attribute name to the
+   * constant pool of the class.
+   *
+   * @param attributeName one of "Runtime[In]VisibleParameterAnnotations".
+   * @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i>
+   *     element).
+   * @param annotableParameterCount the number of elements in annotationWriters to take into account
+   *     (elements [0..annotableParameterCount[ are taken into account).
+   * @return the size in bytes of a Runtime[In]VisibleParameterAnnotations attribute corresponding
+   *     to the given sub-array of AnnotationWriter lists. This includes the size of the
+   *     attribute_name_index and attribute_length fields.
+   */
+  static int computeParameterAnnotationsSize(
+      final String attributeName,
+      final AnnotationWriter[] annotationWriters,
+      final int annotableParameterCount) {
+    // Note: attributeName is added to the constant pool by the call to computeAnnotationsSize
+    // below. This assumes that there is at least one non-null element in the annotationWriters
+    // sub-array (which is ensured by the lazy instantiation of this array in MethodWriter).
+    // The attribute_name_index, attribute_length and num_parameters fields use 7 bytes, and each
+    // element of the parameter_annotations array uses 2 bytes for its num_annotations field.
+    int attributeSize = 7 + 2 * annotableParameterCount;
+    for (int i = 0; i < annotableParameterCount; ++i) {
+      AnnotationWriter annotationWriter = annotationWriters[i];
+      attributeSize +=
+          annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(attributeName) - 8;
+    }
+    return attributeSize;
+  }
 
-    /**
-     * Returns the size of this annotation writer list.
-     *
-     * @return the size of this annotation writer list.
-     */
-    int getSize() {
-        int size = 0;
-        AnnotationWriter aw = this;
-        while (aw != null) {
-            size += aw.bv.length;
-            aw = aw.next;
-        }
-        return size;
+  /**
+   * Puts a Runtime[In]VisibleParameterAnnotations attribute containing all the annotation lists
+   * from the given AnnotationWriter sub-array in the given ByteVector.
+   *
+   * @param attributeNameIndex constant pool index of the attribute name (one of
+   *     Runtime[In]VisibleParameterAnnotations).
+   * @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i>
+   *     element).
+   * @param annotableParameterCount the number of elements in annotationWriters to put (elements
+   *     [0..annotableParameterCount[ are put).
+   * @param output where the attribute must be put.
+   */
+  static void putParameterAnnotations(
+      final int attributeNameIndex,
+      final AnnotationWriter[] annotationWriters,
+      final int annotableParameterCount,
+      final ByteVector output) {
+    // The num_parameters field uses 1 byte, and each element of the parameter_annotations array
+    // uses 2 bytes for its num_annotations field.
+    int attributeLength = 1 + 2 * annotableParameterCount;
+    for (int i = 0; i < annotableParameterCount; ++i) {
+      AnnotationWriter annotationWriter = annotationWriters[i];
+      attributeLength +=
+          annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(null) - 8;
     }
-
-    /**
-     * Puts the annotations of this annotation writer list into the given byte
-     * vector.
-     *
-     * @param out
-     *            where the annotations must be put.
-     */
-    void put(final ByteVector out) {
-        int n = 0;
-        int size = 2;
-        AnnotationWriter aw = this;
-        AnnotationWriter last = null;
-        while (aw != null) {
-            ++n;
-            size += aw.bv.length;
-            aw.visitEnd(); // in case user forgot to call visitEnd
-            aw.prev = last;
-            last = aw;
-            aw = aw.next;
-        }
-        out.putInt(size);
-        out.putShort(n);
-        aw = last;
-        while (aw != null) {
-            out.putByteArray(aw.bv.data, 0, aw.bv.length);
-            aw = aw.prev;
-        }
+    output.putShort(attributeNameIndex);
+    output.putInt(attributeLength);
+    output.putByte(annotableParameterCount);
+    for (int i = 0; i < annotableParameterCount; ++i) {
+      AnnotationWriter annotationWriter = annotationWriters[i];
+      AnnotationWriter firstAnnotation = null;
+      int numAnnotations = 0;
+      while (annotationWriter != null) {
+        // In case user the forgot to call visitEnd().
+        annotationWriter.visitEnd();
+        numAnnotations++;
+        firstAnnotation = annotationWriter;
+        annotationWriter = annotationWriter.previousAnnotation;
+      }
+      output.putShort(numAnnotations);
+      annotationWriter = firstAnnotation;
+      while (annotationWriter != null) {
+        output.putByteArray(
+            annotationWriter.annotation.data, 0, annotationWriter.annotation.length);
+        annotationWriter = annotationWriter.nextAnnotation;
+      }
     }
-
-    /**
-     * Puts the given annotation lists into the given byte vector.
-     *
-     * @param panns
-     *            an array of annotation writer lists.
-     * @param off
-     *            index of the first annotation to be written.
-     * @param out
-     *            where the annotations must be put.
-     */
-    static void put(final AnnotationWriter[] panns, final int off,
-            final ByteVector out) {
-        int size = 1 + 2 * (panns.length - off);
-        for (int i = off; i < panns.length; ++i) {
-            size += panns[i] == null ? 0 : panns[i].getSize();
-        }
-        out.putInt(size).putByte(panns.length - off);
-        for (int i = off; i < panns.length; ++i) {
-            AnnotationWriter aw = panns[i];
-            AnnotationWriter last = null;
-            int n = 0;
-            while (aw != null) {
-                ++n;
-                aw.visitEnd(); // in case user forgot to call visitEnd
-                aw.prev = last;
-                last = aw;
-                aw = aw.next;
-            }
-            out.putShort(n);
-            aw = last;
-            while (aw != null) {
-                out.putByteArray(aw.bv.data, 0, aw.bv.length);
-                aw = aw.prev;
-            }
-        }
-    }
-
-    /**
-     * Puts the given type reference and type path into the given bytevector.
-     * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
-     *
-     * @param typeRef
-     *            a reference to the annotated type. See {@link TypeReference}.
-     * @param typePath
-     *            the path to the annotated type argument, wildcard bound, array
-     *            element type, or static inner type within 'typeRef'. May be
-     *            <tt>null</tt> if the annotation targets 'typeRef' as a whole.
-     * @param out
-     *            where the type reference and type path must be put.
-     */
-    static void putTarget(int typeRef, TypePath typePath, ByteVector out) {
-        switch (typeRef >>> 24) {
-        case 0x00: // CLASS_TYPE_PARAMETER
-        case 0x01: // METHOD_TYPE_PARAMETER
-        case 0x16: // METHOD_FORMAL_PARAMETER
-            out.putShort(typeRef >>> 16);
-            break;
-        case 0x13: // FIELD
-        case 0x14: // METHOD_RETURN
-        case 0x15: // METHOD_RECEIVER
-            out.putByte(typeRef >>> 24);
-            break;
-        case 0x47: // CAST
-        case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
-        case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
-        case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
-        case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
-            out.putInt(typeRef);
-            break;
-        // case 0x10: // CLASS_EXTENDS
-        // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
-        // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
-        // case 0x17: // THROWS
-        // case 0x42: // EXCEPTION_PARAMETER
-        // case 0x43: // INSTANCEOF
-        // case 0x44: // NEW
-        // case 0x45: // CONSTRUCTOR_REFERENCE
-        // case 0x46: // METHOD_REFERENCE
-        default:
-            out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);
-            break;
-        }
-        if (typePath == null) {
-            out.putByte(0);
-        } else {
-            int length = typePath.b[typePath.offset] * 2 + 1;
-            out.putByteArray(typePath.b, typePath.offset, length);
-        }
-    }
+  }
 }
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Attribute.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Attribute.java	Thu Apr 05 12:28:38 2018 -0400
@@ -1,284 +1,350 @@
-/*
- * 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.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file:
- *
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// 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.
+//
+// This file is available under and governed by the GNU General Public
+// License version 2 only, as published by the Free Software Foundation.
+// However, the following notice accompanied the original version of this
+// file:
+//
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the copyright holders nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
 package jdk.internal.org.objectweb.asm;
 
 /**
- * A non standard class, field, method or code attribute.
+ * A non standard class, field, method or code attribute, as defined in the Java Virtual Machine
+ * Specification (JVMS).
  *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7">JVMS
+ *     4.7</a>
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.3">JVMS
+ *     4.7.3</a>
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
 public class Attribute {
 
-    /**
-     * The type of this attribute.
-     */
-    public final String type;
+  /** The type of this attribute, also called its name in the JVMS. */
+  public final String type;
 
-    /**
-     * The raw value of this attribute, used only for unknown attributes.
-     */
-    byte[] value;
+  /**
+   * The raw content of this attribute, only used for unknown attributes (see {@link #isUnknown()}).
+   * The 6 header bytes of the attribute (attribute_name_index and attribute_length) are <i>not</i>
+   * included.
+   */
+  private byte[] content;
 
-    /**
-     * The next attribute in this attribute list. May be <tt>null</tt>.
-     */
-    Attribute next;
+  /**
+   * The next attribute in this attribute list (Attribute instances can be linked via this field to
+   * store a list of class, field, method or code attributes). May be <tt>null</tt>.
+   */
+  Attribute nextAttribute;
 
-    /**
-     * Constructs a new empty attribute.
-     *
-     * @param type
-     *            the type of the attribute.
-     */
-    protected Attribute(final String type) {
-        this.type = type;
+  /**
+   * Constructs a new empty attribute.
+   *
+   * @param type the type of the attribute.
+   */
+  protected Attribute(final String type) {
+    this.type = type;
+  }
+
+  /**
+   * Returns <tt>true</tt> if this type of attribute is unknown. This means that the attribute
+   * content can't be parsed to extract constant pool references, labels, etc. Instead, the
+   * attribute content is read as an opaque byte array, and written back as is. This can lead to
+   * invalid attributes, if the content actually contains constant pool references, labels, or other
+   * symbolic references that need to be updated when there are changes to the constant pool, the
+   * method bytecode, etc. The default implementation of this method always returns <tt>true</tt>.
+   *
+   * @return <tt>true</tt> if this type of attribute is unknown.
+   */
+  public boolean isUnknown() {
+    return true;
+  }
+
+  /**
+   * Returns <tt>true</tt> if this type of attribute is a code attribute.
+   *
+   * @return <tt>true</tt> if this type of attribute is a code attribute.
+   */
+  public boolean isCodeAttribute() {
+    return false;
+  }
+
+  /**
+   * Returns the labels corresponding to this attribute.
+   *
+   * @return the labels corresponding to this attribute, or <tt>null</tt> if this attribute is not a
+   *     code attribute that contains labels.
+   */
+  protected Label[] getLabels() {
+    return new Label[0];
+  }
+
+  /**
+   * Reads a {@link #type} attribute. This method must return a <i>new</i> {@link Attribute} object,
+   * of type {@link #type}, corresponding to the 'length' bytes starting at 'offset', in the given
+   * ClassReader.
+   *
+   * @param classReader the class that contains the attribute to be read.
+   * @param offset index of the first byte of the attribute's content in {@link ClassReader#b}. The
+   *     6 attribute header bytes (attribute_name_index and attribute_length) are not taken into
+   *     account here.
+   * @param length the length of the attribute's content (excluding the 6 attribute header bytes).
+   * @param charBuffer the buffer to be used to call the ClassReader methods requiring a
+   *     'charBuffer' parameter.
+   * @param codeAttributeOffset index of the first byte of content of the enclosing Code attribute
+   *     in {@link ClassReader#b}, or -1 if the attribute to be read is not a code attribute. The 6
+   *     attribute header bytes (attribute_name_index and attribute_length) are not taken into
+   *     account here.
+   * @param labels the labels of the method's code, or <tt>null</tt> if the attribute to be read is
+   *     not a code attribute.
+   * @return a <i>new</i> {@link Attribute} object corresponding to the specified bytes.
+   */
+  protected Attribute read(
+      final ClassReader classReader,
+      final int offset,
+      final int length,
+      final char[] charBuffer,
+      final int codeAttributeOffset,
+      final Label[] labels) {
+    Attribute attribute = new Attribute(type);
+    attribute.content = new byte[length];
+    System.arraycopy(classReader.b, offset, attribute.content, 0, length);
+    return attribute;
+  }
+
+  /**
+   * Returns the byte array form of the content of this attribute. The 6 header bytes
+   * (attribute_name_index and attribute_length) must <i>not</i> be added in the returned
+   * ByteVector.
+   *
+   * @param classWriter the class to which this attribute must be added. This parameter can be used
+   *     to add the items that corresponds to this attribute to the constant pool of this class.
+   * @param code the bytecode of the method corresponding to this code attribute, or <tt>null</tt>
+   *     if this attribute is not a code attribute. Corresponds to the 'code' field of the Code
+   *     attribute.
+   * @param codeLength the length of the bytecode of the method corresponding to this code
+   *     attribute, or 0 if this attribute is not a code attribute. Corresponds to the 'code_length'
+   *     field of the Code attribute.
+   * @param maxStack the maximum stack size of the method corresponding to this code attribute, or
+   *     -1 if this attribute is not a code attribute.
+   * @param maxLocals the maximum number of local variables of the method corresponding to this code
+   *     attribute, or -1 if this attribute is not a code attribute.
+   * @return the byte array form of this attribute.
+   */
+  protected ByteVector write(
+      final ClassWriter classWriter,
+      final byte[] code,
+      final int codeLength,
+      final int maxStack,
+      final int maxLocals) {
+    return new ByteVector(content);
+  }
+
+  /**
+   * Returns the number of attributes of the attribute list that begins with this attribute.
+   *
+   * @return the number of attributes of the attribute list that begins with this attribute.
+   */
+  final int getAttributeCount() {
+    int count = 0;
+    Attribute attribute = this;
+    while (attribute != null) {
+      count += 1;
+      attribute = attribute.nextAttribute;
+    }
+    return count;
+  }
+
+  /**
+   * Returns the total size in bytes of all the attributes in the attribute list that begins with
+   * this attribute. This size includes the 6 header bytes (attribute_name_index and
+   * attribute_length) per attribute. Also adds the attribute type names to the constant pool.
+   *
+   * @param symbolTable where the constants used in the attributes must be stored.
+   * @return the size of all the attributes in this attribute list. This size includes the size of
+   *     the attribute headers.
+   */
+  final int computeAttributesSize(final SymbolTable symbolTable) {
+    final byte[] code = null;
+    final int codeLength = 0;
+    final int maxStack = -1;
+    final int maxLocals = -1;
+    return computeAttributesSize(symbolTable, code, codeLength, maxStack, maxLocals);
+  }
+
+  /**
+   * Returns the total size in bytes of all the attributes in the attribute list that begins with
+   * this attribute. This size includes the 6 header bytes (attribute_name_index and
+   * attribute_length) per attribute. Also adds the attribute type names to the constant pool.
+   *
+   * @param symbolTable where the constants used in the attributes must be stored.
+   * @param code the bytecode of the method corresponding to these code attributes, or <tt>null</tt>
+   *     if they are not code attributes. Corresponds to the 'code' field of the Code attribute.
+   * @param codeLength the length of the bytecode of the method corresponding to these code
+   *     attributes, or 0 if they are not code attributes. Corresponds to the 'code_length' field of
+   *     the Code attribute.
+   * @param maxStack the maximum stack size of the method corresponding to these code attributes, or
+   *     -1 if they are not code attributes.
+   * @param maxLocals the maximum number of local variables of the method corresponding to these
+   *     code attributes, or -1 if they are not code attribute.
+   * @return the size of all the attributes in this attribute list. This size includes the size of
+   *     the attribute headers.
+   */
+  final int computeAttributesSize(
+      final SymbolTable symbolTable,
+      final byte[] code,
+      final int codeLength,
+      final int maxStack,
+      final int maxLocals) {
+    final ClassWriter classWriter = symbolTable.classWriter;
+    int size = 0;
+    Attribute attribute = this;
+    while (attribute != null) {
+      symbolTable.addConstantUtf8(attribute.type);
+      size += 6 + attribute.write(classWriter, code, codeLength, maxStack, maxLocals).length;
+      attribute = attribute.nextAttribute;
+    }
+    return size;
+  }
+
+  /**
+   * Puts all the attributes of the attribute list that begins with this attribute, in the given
+   * byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per
+   * attribute.
+   *
+   * @param symbolTable where the constants used in the attributes must be stored.
+   * @param output where the attributes must be written.
+   */
+  final void putAttributes(final SymbolTable symbolTable, final ByteVector output) {
+    final byte[] code = null;
+    final int codeLength = 0;
+    final int maxStack = -1;
+    final int maxLocals = -1;
+    putAttributes(symbolTable, code, codeLength, maxStack, maxLocals, output);
+  }
+
+  /**
+   * Puts all the attributes of the attribute list that begins with this attribute, in the given
+   * byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per
+   * attribute.
+   *
+   * @param symbolTable where the constants used in the attributes must be stored.
+   * @param code the bytecode of the method corresponding to these code attributes, or <tt>null</tt>
+   *     if they are not code attributes. Corresponds to the 'code' field of the Code attribute.
+   * @param codeLength the length of the bytecode of the method corresponding to these code
+   *     attributes, or 0 if they are not code attributes. Corresponds to the 'code_length' field of
+   *     the Code attribute.
+   * @param maxStack the maximum stack size of the method corresponding to these code attributes, or
+   *     -1 if they are not code attributes.
+   * @param maxLocals the maximum number of local variables of the method corresponding to these
+   *     code attributes, or -1 if they are not code attribute.
+   * @param output where the attributes must be written.
+   */
+  final void putAttributes(
+      final SymbolTable symbolTable,
+      final byte[] code,
+      final int codeLength,
+      final int maxStack,
+      final int maxLocals,
+      final ByteVector output) {
+    final ClassWriter classWriter = symbolTable.classWriter;
+    Attribute attribute = this;
+    while (attribute != null) {
+      ByteVector attributeContent =
+          attribute.write(classWriter, code, codeLength, maxStack, maxLocals);
+      // Put attribute_name_index and attribute_length.
+      output.putShort(symbolTable.addConstantUtf8(attribute.type)).putInt(attributeContent.length);
+      output.putByteArray(attributeContent.data, 0, attributeContent.length);
+      attribute = attribute.nextAttribute;
+    }
+  }
+
+  /** A set of attribute prototypes (attributes with the same type are considered equal). */
+  static final class Set {
+
+    private static final int SIZE_INCREMENT = 6;
+
+    private int size;
+    private Attribute[] data = new Attribute[SIZE_INCREMENT];
+
+    void addAttributes(final Attribute attributeList) {
+      Attribute attribute = attributeList;
+      while (attribute != null) {
+        if (!contains(attribute)) {
+          add(attribute);
+        }
+        attribute = attribute.nextAttribute;
+      }
     }
 
-    /**
-     * Returns <tt>true</tt> if this type of attribute is unknown. The default
-     * implementation of this method always returns <tt>true</tt>.
-     *
-     * @return <tt>true</tt> if this type of attribute is unknown.
-     */
-    public boolean isUnknown() {
-        return true;
+    Attribute[] toArray() {
+      Attribute[] result = new Attribute[size];
+      System.arraycopy(data, 0, result, 0, size);
+      return result;
     }
 
-    /**
-     * Returns <tt>true</tt> if this type of attribute is a code attribute.
-     *
-     * @return <tt>true</tt> if this type of attribute is a code attribute.
-     */
-    public boolean isCodeAttribute() {
-        return false;
+    private boolean contains(final Attribute attribute) {
+      for (int i = 0; i < size; ++i) {
+        if (data[i].type.equals(attribute.type)) {
+          return true;
+        }
+      }
+      return false;
     }
 
-    /**
-     * Returns the labels corresponding to this attribute.
-     *
-     * @return the labels corresponding to this attribute, or <tt>null</tt> if
-     *         this attribute is not a code attribute that contains labels.
-     */
-    protected Label[] getLabels() {
-        return null;
+    private void add(final Attribute attribute) {
+      if (size >= data.length) {
+        Attribute[] newData = new Attribute[data.length + SIZE_INCREMENT];
+        System.arraycopy(data, 0, newData, 0, size);
+        data = newData;
+      }
+      data[size++] = attribute;
     }
-
-    /**
-     * Reads a {@link #type type} attribute. This method must return a
-     * <i>new</i> {@link Attribute} object, of type {@link #type type},
-     * corresponding to the <tt>len</tt> bytes starting at the given offset, in
-     * the given class reader.
-     *
-     * @param cr
-     *            the class that contains the attribute to be read.
-     * @param off
-     *            index of the first byte of the attribute's content in
-     *            {@link ClassReader#b cr.b}. The 6 attribute header bytes,
-     *            containing the type and the length of the attribute, are not
-     *            taken into account here.
-     * @param len
-     *            the length of the attribute's content.
-     * @param buf
-     *            buffer to be used to call {@link ClassReader#readUTF8
-     *            readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}
-     *            or {@link ClassReader#readConst readConst}.
-     * @param codeOff
-     *            index of the first byte of code's attribute content in
-     *            {@link ClassReader#b cr.b}, or -1 if the attribute to be read
-     *            is not a code attribute. The 6 attribute header bytes,
-     *            containing the type and the length of the attribute, are not
-     *            taken into account here.
-     * @param labels
-     *            the labels of the method's code, or <tt>null</tt> if the
-     *            attribute to be read is not a code attribute.
-     * @return a <i>new</i> {@link Attribute} object corresponding to the given
-     *         bytes.
-     */
-    protected Attribute read(final ClassReader cr, final int off,
-            final int len, final char[] buf, final int codeOff,
-            final Label[] labels) {
-        Attribute attr = new Attribute(type);
-        attr.value = new byte[len];
-        System.arraycopy(cr.b, off, attr.value, 0, len);
-        return attr;
-    }
-
-    /**
-     * Returns the byte array form of this attribute.
-     *
-     * @param cw
-     *            the class to which this attribute must be added. This
-     *            parameter can be used to add to the constant pool of this
-     *            class the items that corresponds to this attribute.
-     * @param code
-     *            the bytecode of the method corresponding to this code
-     *            attribute, or <tt>null</tt> if this attribute is not a code
-     *            attributes.
-     * @param len
-     *            the length of the bytecode of the method corresponding to this
-     *            code attribute, or <tt>null</tt> if this attribute is not a
-     *            code attribute.
-     * @param maxStack
-     *            the maximum stack size of the method corresponding to this
-     *            code attribute, or -1 if this attribute is not a code
-     *            attribute.
-     * @param maxLocals
-     *            the maximum number of local variables of the method
-     *            corresponding to this code attribute, or -1 if this attribute
-     *            is not a code attribute.
-     * @return the byte array form of this attribute.
-     */
-    protected ByteVector write(final ClassWriter cw, final byte[] code,
-            final int len, final int maxStack, final int maxLocals) {
-        ByteVector v = new ByteVector();
-        v.data = value;
-        v.length = value.length;
-        return v;
-    }
-
-    /**
-     * Returns the length of the attribute list that begins with this attribute.
-     *
-     * @return the length of the attribute list that begins with this attribute.
-     */
-    final int getCount() {
-        int count = 0;
-        Attribute attr = this;
-        while (attr != null) {
-            count += 1;
-            attr = attr.next;
-        }
-        return count;
-    }
-
-    /**
-     * Returns the size of all the attributes in this attribute list.
-     *
-     * @param cw
-     *            the class writer to be used to convert the attributes into
-     *            byte arrays, with the {@link #write write} method.
-     * @param code
-     *            the bytecode of the method corresponding to these code
-     *            attributes, or <tt>null</tt> if these attributes are not code
-     *            attributes.
-     * @param len
-     *            the length of the bytecode of the method corresponding to
-     *            these code attributes, or <tt>null</tt> if these attributes
-     *            are not code attributes.
-     * @param maxStack
-     *            the maximum stack size of the method corresponding to these
-     *            code attributes, or -1 if these attributes are not code
-     *            attributes.
-     * @param maxLocals
-     *            the maximum number of local variables of the method
-     *            corresponding to these code attributes, or -1 if these
-     *            attributes are not code attributes.
-     * @return the size of all the attributes in this attribute list. This size
-     *         includes the size of the attribute headers.
-     */
-    final int getSize(final ClassWriter cw, final byte[] code, final int len,
-            final int maxStack, final int maxLocals) {
-        Attribute attr = this;
-        int size = 0;
-        while (attr != null) {
-            cw.newUTF8(attr.type);
-            size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
-            attr = attr.next;
-        }
-        return size;
-    }
-
-    /**
-     * Writes all the attributes of this attribute list in the given byte
-     * vector.
-     *
-     * @param cw
-     *            the class writer to be used to convert the attributes into
-     *            byte arrays, with the {@link #write write} method.
-     * @param code
-     *            the bytecode of the method corresponding to these code
-     *            attributes, or <tt>null</tt> if these attributes are not code
-     *            attributes.
-     * @param len
-     *            the length of the bytecode of the method corresponding to
-     *            these code attributes, or <tt>null</tt> if these attributes
-     *            are not code attributes.
-     * @param maxStack
-     *            the maximum stack size of the method corresponding to these
-     *            code attributes, or -1 if these attributes are not code
-     *            attributes.
-     * @param maxLocals
-     *            the maximum number of local variables of the method
-     *            corresponding to these code attributes, or -1 if these
-     *            attributes are not code attributes.
-     * @param out
-     *            where the attributes must be written.
-     */
-    final void put(final ClassWriter cw, final byte[] code, final int len,
-            final int maxStack, final int maxLocals, final ByteVector out) {
-        Attribute attr = this;
-        while (attr != null) {
-            ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
-            out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
-            out.putByteArray(b.data, 0, b.length);
-            attr = attr.next;
-        }
-    }
+  }
 }
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java	Thu Apr 05 12:28:38 2018 -0400
@@ -1,368 +1,387 @@
-/*
- * 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.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file:
- *
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// 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.
+//
+// This file is available under and governed by the GNU General Public
+// License version 2 only, as published by the Free Software Foundation.
+// However, the following notice accompanied the original version of this
+// file:
+//
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the copyright holders nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
 package jdk.internal.org.objectweb.asm;
 
 /**
- * A dynamically extensible vector of bytes. This class is roughly equivalent to
- * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
+ * A dynamically extensible vector of bytes. This class is roughly equivalent to a DataOutputStream
+ * on top of a ByteArrayOutputStream, but is more efficient.
  *
  * @author Eric Bruneton
  */
 public class ByteVector {
 
-    /**
-     * The content of this vector.
-     */
-    byte[] data;
+  /** The content of this vector. Only the first {@link #length} bytes contain real data. */
+  byte[] data;
 
-    /**
-     * Actual number of bytes in this vector.
-     */
-    int length;
+  /** The actual number of bytes in this vector. */
+  int length;
 
-    /**
-     * Constructs a new {@link ByteVector ByteVector} with a default initial
-     * size.
-     */
-    public ByteVector() {
-        data = new byte[64];
+  /** Constructs a new {@link ByteVector} with a default initial capacity. */
+  public ByteVector() {
+    data = new byte[64];
+  }
+
+  /**
+   * Constructs a new {@link ByteVector} with the given initial capacity.
+   *
+   * @param initialCapacity the initial capacity of the byte vector to be constructed.
+   */
+  public ByteVector(final int initialCapacity) {
+    data = new byte[initialCapacity];
+  }
+
+  /**
+   * Constructs a new {@link ByteVector} from the given initial data.
+   *
+   * @param data the initial data of the new byte vector.
+   */
+  ByteVector(final byte[] data) {
+    this.data = data;
+    this.length = data.length;
+  }
+
+  /**
+   * Puts a byte into this byte vector. The byte vector is automatically enlarged if necessary.
+   *
+   * @param byteValue a byte.
+   * @return this byte vector.
+   */
+  public ByteVector putByte(final int byteValue) {
+    int currentLength = length;
+    if (currentLength + 1 > data.length) {
+      enlarge(1);
     }
+    data[currentLength++] = (byte) byteValue;
+    length = currentLength;
+    return this;
+  }
 
-    /**
-     * Constructs a new {@link ByteVector ByteVector} with the given initial
-     * size.
-     *
-     * @param initialSize
-     *            the initial size of the byte vector to be constructed.
-     */
-    public ByteVector(final int initialSize) {
-        data = new byte[initialSize];
+  /**
+   * Puts two bytes into this byte vector. The byte vector is automatically enlarged if necessary.
+   *
+   * @param byteValue1 a byte.
+   * @param byteValue2 another byte.
+   * @return this byte vector.
+   */
+  final ByteVector put11(final int byteValue1, final int byteValue2) {
+    int currentLength = length;
+    if (currentLength + 2 > data.length) {
+      enlarge(2);
     }
+    byte[] currentData = data;
+    currentData[currentLength++] = (byte) byteValue1;
+    currentData[currentLength++] = (byte) byteValue2;
+    length = currentLength;
+    return this;
+  }
 
-    /**
-     * Puts a byte into this byte vector. The byte vector is automatically
-     * enlarged if necessary.
-     *
-     * @param b
-     *            a byte.
-     * @return this byte vector.
-     */
-    public ByteVector putByte(final int b) {
-        int length = this.length;
-        if (length + 1 > data.length) {
-            enlarge(1);
-        }
-        data[length++] = (byte) b;
-        this.length = length;
-        return this;
+  /**
+   * Puts a short into this byte vector. The byte vector is automatically enlarged if necessary.
+   *
+   * @param shortValue a short.
+   * @return this byte vector.
+   */
+  public ByteVector putShort(final int shortValue) {
+    int currentLength = length;
+    if (currentLength + 2 > data.length) {
+      enlarge(2);
     }
+    byte[] currentData = data;
+    currentData[currentLength++] = (byte) (shortValue >>> 8);
+    currentData[currentLength++] = (byte) shortValue;
+    length = currentLength;
+    return this;
+  }
 
-    /**
-     * Puts two bytes into this byte vector. The byte vector is automatically
-     * enlarged if necessary.
-     *
-     * @param b1
-     *            a byte.
-     * @param b2
-     *            another byte.
-     * @return this byte vector.
-     */
-    ByteVector put11(final int b1, final int b2) {
-        int length = this.length;
-        if (length + 2 > data.length) {
-            enlarge(2);
-        }
-        byte[] data = this.data;
-        data[length++] = (byte) b1;
-        data[length++] = (byte) b2;
-        this.length = length;
-        return this;
+  /**
+   * Puts a byte and a short into this byte vector. The byte vector is automatically enlarged if
+   * necessary.
+   *
+   * @param byteValue a byte.
+   * @param shortValue a short.
+   * @return this byte vector.
+   */
+  final ByteVector put12(final int byteValue, final int shortValue) {
+    int currentLength = length;
+    if (currentLength + 3 > data.length) {
+      enlarge(3);
     }
+    byte[] currentData = data;
+    currentData[currentLength++] = (byte) byteValue;
+    currentData[currentLength++] = (byte) (shortValue >>> 8);
+    currentData[currentLength++] = (byte) shortValue;
+    length = currentLength;
+    return this;
+  }
 
-    /**
-     * Puts a short into this byte vector. The byte vector is automatically
-     * enlarged if necessary.
-     *
-     * @param s
-     *            a short.
-     * @return this byte vector.
-     */
-    public ByteVector putShort(final int s) {
-        int length = this.length;
-        if (length + 2 > data.length) {
-            enlarge(2);
-        }
-        byte[] data = this.data;
-        data[length++] = (byte) (s >>> 8);
-        data[length++] = (byte) s;
-        this.length = length;
-        return this;
+  /**
+   * Puts two bytes and a short into this byte vector. The byte vector is automatically enlarged if
+   * necessary.
+   *
+   * @param byteValue1 a byte.
+   * @param byteValue2 another byte.
+   * @param shortValue a short.
+   * @return this byte vector.
+   */
+  final ByteVector put112(final int byteValue1, final int byteValue2, final int shortValue) {
+    int currentLength = length;
+    if (currentLength + 4 > data.length) {
+      enlarge(4);
     }
+    byte[] currentData = data;
+    currentData[currentLength++] = (byte) byteValue1;
+    currentData[currentLength++] = (byte) byteValue2;
+    currentData[currentLength++] = (byte) (shortValue >>> 8);
+    currentData[currentLength++] = (byte) shortValue;
+    length = currentLength;
+    return this;
+  }
 
-    /**
-     * Puts a byte and a short into this byte vector. The byte vector is
-     * automatically enlarged if necessary.
-     *
-     * @param b
-     *            a byte.
-     * @param s
-     *            a short.
-     * @return this byte vector.
-     */
-    ByteVector put12(final int b, final int s) {
-        int length = this.length;
-        if (length + 3 > data.length) {
-            enlarge(3);
-        }
-        byte[] data = this.data;
-        data[length++] = (byte) b;
-        data[length++] = (byte) (s >>> 8);
-        data[length++] = (byte) s;
-        this.length = length;
-        return this;
+  /**
+   * Puts an int into this byte vector. The byte vector is automatically enlarged if necessary.
+   *
+   * @param intValue an int.
+   * @return this byte vector.
+   */
+  public ByteVector putInt(final int intValue) {
+    int currentLength = length;
+    if (currentLength + 4 > data.length) {
+      enlarge(4);
     }
+    byte[] currentData = data;
+    currentData[currentLength++] = (byte) (intValue >>> 24);
+    currentData[currentLength++] = (byte) (intValue >>> 16);
+    currentData[currentLength++] = (byte) (intValue >>> 8);
+    currentData[currentLength++] = (byte) intValue;
+    length = currentLength;
+    return this;
+  }
 
-    /**
-     * Puts an int into this byte vector. The byte vector is automatically
-     * enlarged if necessary.
-     *
-     * @param i
-     *            an int.
-     * @return this byte vector.
-     */
-    public ByteVector putInt(final int i) {
-        int length = this.length;
-        if (length + 4 > data.length) {
-            enlarge(4);
-        }
-        byte[] data = this.data;
-        data[length++] = (byte) (i >>> 24);
-        data[length++] = (byte) (i >>> 16);
-        data[length++] = (byte) (i >>> 8);
-        data[length++] = (byte) i;
-        this.length = length;
-        return this;
+  /**
+   * Puts one byte and two shorts into this byte vector. The byte vector is automatically enlarged
+   * if necessary.
+   *
+   * @param byteValue a byte.
+   * @param shortValue1 a short.
+   * @param shortValue2 another short.
+   * @return this byte vector.
+   */
+  final ByteVector put122(final int byteValue, final int shortValue1, final int shortValue2) {
+    int currentLength = length;
+    if (currentLength + 5 > data.length) {
+      enlarge(5);
     }
+    byte[] currentData = data;
+    currentData[currentLength++] = (byte) byteValue;
+    currentData[currentLength++] = (byte) (shortValue1 >>> 8);
+    currentData[currentLength++] = (byte) shortValue1;
+    currentData[currentLength++] = (byte) (shortValue2 >>> 8);
+    currentData[currentLength++] = (byte) shortValue2;
+    length = currentLength;
+    return this;
+  }
 
-    /**
-     * Puts a long into this byte vector. The byte vector is automatically
-     * enlarged if necessary.
-     *
-     * @param l
-     *            a long.
-     * @return this byte vector.
-     */
-    public ByteVector putLong(final long l) {
-        int length = this.length;
-        if (length + 8 > data.length) {
-            enlarge(8);
-        }
-        byte[] data = this.data;
-        int i = (int) (l >>> 32);
-        data[length++] = (byte) (i >>> 24);
-        data[length++] = (byte) (i >>> 16);
-        data[length++] = (byte) (i >>> 8);
-        data[length++] = (byte) i;
-        i = (int) l;
-        data[length++] = (byte) (i >>> 24);
-        data[length++] = (byte) (i >>> 16);
-        data[length++] = (byte) (i >>> 8);
-        data[length++] = (byte) i;
-        this.length = length;
-        return this;
+  /**
+   * Puts a long into this byte vector. The byte vector is automatically enlarged if necessary.
+   *
+   * @param longValue a long.
+   * @return this byte vector.
+   */
+  public ByteVector putLong(final long longValue) {
+    int currentLength = length;
+    if (currentLength + 8 > data.length) {
+      enlarge(8);
     }
+    byte[] currentData = data;
+    int intValue = (int) (longValue >>> 32);
+    currentData[currentLength++] = (byte) (intValue >>> 24);
+    currentData[currentLength++] = (byte) (intValue >>> 16);
+    currentData[currentLength++] = (byte) (intValue >>> 8);
+    currentData[currentLength++] = (byte) intValue;
+    intValue = (int) longValue;
+    currentData[currentLength++] = (byte) (intValue >>> 24);
+    currentData[currentLength++] = (byte) (intValue >>> 16);
+    currentData[currentLength++] = (byte) (intValue >>> 8);
+    currentData[currentLength++] = (byte) intValue;
+    length = currentLength;
+    return this;
+  }
 
-    /**
-     * Puts an UTF8 string into this byte vector. The byte vector is
-     * automatically enlarged if necessary.
-     *
-     * @param s
-     *            a String whose UTF8 encoded length must be less than 65536.
-     * @return this byte vector.
-     */
-    public ByteVector putUTF8(final String s) {
-        int charLength = s.length();
-        if (charLength > 65535) {
-            throw new IllegalArgumentException();
-        }
-        int len = length;
-        if (len + 2 + charLength > data.length) {
-            enlarge(2 + charLength);
-        }
-        byte[] data = this.data;
-        // optimistic algorithm: instead of computing the byte length and then
-        // serializing the string (which requires two loops), we assume the byte
-        // length is equal to char length (which is the most frequent case), and
-        // we start serializing the string right away. During the serialization,
-        // if we find that this assumption is wrong, we continue with the
-        // general method.
-        data[len++] = (byte) (charLength >>> 8);
-        data[len++] = (byte) charLength;
-        for (int i = 0; i < charLength; ++i) {
-            char c = s.charAt(i);
-            if (c >= '\001' && c <= '\177') {
-                data[len++] = (byte) c;
-            } else {
-                length = len;
-                return encodeUTF8(s, i, 65535);
-            }
-        }
-        length = len;
-        return this;
+  /**
+   * Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if
+   * necessary.
+   *
+   * @param stringValue a String whose UTF8 encoded length must be less than 65536.
+   * @return this byte vector.
+   */
+  public ByteVector putUTF8(final String stringValue) {
+    int charLength = stringValue.length();
+    if (charLength > 65535) {
+      throw new IllegalArgumentException();
     }
+    int currentLength = length;
+    if (currentLength + 2 + charLength > data.length) {
+      enlarge(2 + charLength);
+    }
+    byte[] currentData = data;
+    // Optimistic algorithm: instead of computing the byte length and then serializing the string
+    // (which requires two loops), we assume the byte length is equal to char length (which is the
+    // most frequent case), and we start serializing the string right away. During the
+    // serialization, if we find that this assumption is wrong, we continue with the general method.
+    currentData[currentLength++] = (byte) (charLength >>> 8);
+    currentData[currentLength++] = (byte) charLength;
+    for (int i = 0; i < charLength; ++i) {
+      char charValue = stringValue.charAt(i);
+      if (charValue >= '\u0001' && charValue <= '\u007F') {
+        currentData[currentLength++] = (byte) charValue;
+      } else {
+        length = currentLength;
+        return encodeUTF8(stringValue, i, 65535);
+      }
+    }
+    length = currentLength;
+    return this;
+  }
 
-    /**
-     * Puts an UTF8 string into this byte vector. The byte vector is
-     * automatically enlarged if necessary. The string length is encoded in two
-     * bytes before the encoded characters, if there is space for that (i.e. if
-     * this.length - i - 2 >= 0).
-     *
-     * @param s
-     *            the String to encode.
-     * @param i
-     *            the index of the first character to encode. The previous
-     *            characters are supposed to have already been encoded, using
-     *            only one byte per character.
-     * @param maxByteLength
-     *            the maximum byte length of the encoded string, including the
-     *            already encoded characters.
-     * @return this byte vector.
-     */
-    ByteVector encodeUTF8(final String s, int i, int maxByteLength) {
-        int charLength = s.length();
-        int byteLength = i;
-        char c;
-        for (int j = i; j < charLength; ++j) {
-            c = s.charAt(j);
-            if (c >= '\001' && c <= '\177') {
-                byteLength++;
-            } else if (c > '\u07FF') {
-                byteLength += 3;
-            } else {
-                byteLength += 2;
-            }
-        }
-        if (byteLength > maxByteLength) {
-            throw new IllegalArgumentException();
-        }
-        int start = length - i - 2;
-        if (start >= 0) {
-          data[start] = (byte) (byteLength >>> 8);
-          data[start + 1] = (byte) byteLength;
-        }
-        if (length + byteLength - i > data.length) {
-            enlarge(byteLength - i);
-        }
-        int len = length;
-        for (int j = i; j < charLength; ++j) {
-            c = s.charAt(j);
-            if (c >= '\001' && c <= '\177') {
-                data[len++] = (byte) c;
-            } else if (c > '\u07FF') {
-                data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
-                data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
-                data[len++] = (byte) (0x80 | c & 0x3F);
-            } else {
-                data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
-                data[len++] = (byte) (0x80 | c & 0x3F);
-            }
-        }
-        length = len;
-        return this;
+  /**
+   * Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if
+   * necessary. The string length is encoded in two bytes before the encoded characters, if there is
+   * space for that (i.e. if this.length - offset - 2 &gt;= 0).
+   *
+   * @param stringValue the String to encode.
+   * @param offset the index of the first character to encode. The previous characters are supposed
+   *     to have already been encoded, using only one byte per character.
+   * @param maxByteLength the maximum byte length of the encoded string, including the already
+   *     encoded characters.
+   * @return this byte vector.
+   */
+  final ByteVector encodeUTF8(final String stringValue, final int offset, final int maxByteLength) {
+    int charLength = stringValue.length();
+    int byteLength = offset;
+    for (int i = offset; i < charLength; ++i) {
+      char charValue = stringValue.charAt(i);
+      if (charValue >= '\u0001' && charValue <= '\u007F') {
+        byteLength++;
+      } else if (charValue <= '\u07FF') {
+        byteLength += 2;
+      } else {
+        byteLength += 3;
+      }
     }
+    if (byteLength > maxByteLength) {
+      throw new IllegalArgumentException();
+    }
+    // Compute where 'byteLength' must be stored in 'data', and store it at this location.
+    int byteLengthOffset = length - offset - 2;
+    if (byteLengthOffset >= 0) {
+      data[byteLengthOffset] = (byte) (byteLength >>> 8);
+      data[byteLengthOffset + 1] = (byte) byteLength;
+    }
+    if (length + byteLength - offset > data.length) {
+      enlarge(byteLength - offset);
+    }
+    int currentLength = length;
+    for (int i = offset; i < charLength; ++i) {
+      char charValue = stringValue.charAt(i);
+      if (charValue >= '\u0001' && charValue <= '\u007F') {
+        data[currentLength++] = (byte) charValue;
+      } else if (charValue <= '\u07FF') {
+        data[currentLength++] = (byte) (0xC0 | charValue >> 6 & 0x1F);
+        data[currentLength++] = (byte) (0x80 | charValue & 0x3F);
+      } else {
+        data[currentLength++] = (byte) (0xE0 | charValue >> 12 & 0xF);
+        data[currentLength++] = (byte) (0x80 | charValue >> 6 & 0x3F);
+        data[currentLength++] = (byte) (0x80 | charValue & 0x3F);
+      }
+    }
+    length = currentLength;
+    return this;
+  }
 
-    /**
-     * Puts an array of bytes into this byte vector. The byte vector is
-     * automatically enlarged if necessary.
-     *
-     * @param b
-     *            an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
-     *            null bytes into this byte vector.
-     * @param off
-     *            index of the fist byte of b that must be copied.
-     * @param len
-     *            number of bytes of b that must be copied.
-     * @return this byte vector.
-     */
-    public ByteVector putByteArray(final byte[] b, final int off, final int len) {
-        if (length + len > data.length) {
-            enlarge(len);
-        }
-        if (b != null) {
-            System.arraycopy(b, off, data, length, len);
-        }
-        length += len;
-        return this;
+  /**
+   * Puts an array of bytes into this byte vector. The byte vector is automatically enlarged if
+   * necessary.
+   *
+   * @param byteArrayValue an array of bytes. May be <tt>null</tt> to put <tt>byteLength</tt> null
+   *     bytes into this byte vector.
+   * @param byteOffset index of the first byte of byteArrayValue that must be copied.
+   * @param byteLength number of bytes of byteArrayValue that must be copied.
+   * @return this byte vector.
+   */
+  public ByteVector putByteArray(
+      final byte[] byteArrayValue, final int byteOffset, final int byteLength) {
+    if (length + byteLength > data.length) {
+      enlarge(byteLength);
     }
+    if (byteArrayValue != null) {
+      System.arraycopy(byteArrayValue, byteOffset, data, length, byteLength);
+    }
+    length += byteLength;
+    return this;
+  }
 
-    /**
-     * Enlarge this byte vector so that it can receive n more bytes.
-     *
-     * @param size
-     *            number of additional bytes that this byte vector should be
-     *            able to receive.
-     */
-    private void enlarge(final int size) {
-        int length1 = 2 * data.length;
-        int length2 = length + size;
-        byte[] newData = new byte[length1 > length2 ? length1 : length2];
-        System.arraycopy(data, 0, newData, 0, length);
-        data = newData;
-    }
+  /**
+   * Enlarges this byte vector so that it can receive 'size' more bytes.
+   *
+   * @param size number of additional bytes that this byte vector should be able to receive.
+   */
+  private void enlarge(final int size) {
+    int doubleCapacity = 2 * data.length;
+    int minimalCapacity = length + size;
+    byte[] newData = new byte[doubleCapacity > minimalCapacity ? doubleCapacity : minimalCapacity];
+    System.arraycopy(data, 0, newData, 0, length);
+    data = newData;
+  }
 }
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java	Thu Apr 05 11:08:37 2018 -0400
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java	Thu Apr 05 12:28:38 2018 -0400
@@ -1,2789 +1,3577 @@
-/*
- * 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.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file:
- *
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000-2011 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
+// 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.
+//
+// This file is available under and governed by the GNU General Public
+// License version 2 only, as published by the Free Software Foundation.
+// However, the following notice accompanied the original version of this
+// file:
+//
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the copyright holders nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
 package jdk.internal.org.objectweb.asm;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
 /**
- * A Java class parser to make a {@link ClassVisitor} visit an existing class.
- * This class parses a byte array conforming to the Java class file format and
- * calls the appropriate visit methods of a given class visitor for each field,
- * method and bytecode instruction encountered.
+ * A parser to make a {@link ClassVisitor} visit a ClassFile structure, as defined in the Java
+ * Virtual Machine Specification (JVMS). This class parses the ClassFile content and calls the
+ * appropriate visit methods of a given {@link ClassVisitor} for each field, method and bytecode
+ * instruction encountered.
  *
+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html">JVMS 4</a>
  * @author Eric Bruneton
  * @author Eugene Kuleshov
  */
 public class ClassReader {
 
-    /**
-     * Flag to skip method code. If this class is set <code>CODE</code>
-     * attribute won't be visited. This can be used, for example, to retrieve
-     * annotations for methods and method parameters.
-     */
-    public static final int SKIP_CODE = 1;
+  /**
+   * A flag to skip the Code attributes. If this flag is set the Code attributes are neither parsed
+   * nor visited.
+   */
+  public static final int SKIP_CODE = 1;
 
-    /**
-     * Flag to skip the debug information in the class. If this flag is set the
-     * debug information of the class is not visited, i.e. the
-     * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
-     * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
-     * called.
-     */
-    public static final int SKIP_DEBUG = 2;
+  /**
+   * A flag to skip the SourceFile, SourceDebugExtension, LocalVariableTable, LocalVariableTypeTable
+   * and LineNumberTable attributes. If this flag is set these attributes are neither parsed nor
+   * visited (i.e. {@link ClassVisitor#visitSource}, {@link MethodVisitor#visitLocalVariable} and
+   * {@link MethodVisitor#visitLineNumber} are not called).
+   */
+  public static final int SKIP_DEBUG = 2;
 
-    /**
-     * Flag to skip the stack map frames in the class. If this flag is set the
-     * stack map frames of the class is not visited, i.e. the
-     * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
-     * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
-     * used: it avoids visiting frames that will be ignored and recomputed from
-     * scratch in the class writer.
-     */
-    public static final int SKIP_FRAMES = 4;
+  /**
+   * A flag to skip the StackMap and StackMapTable attributes. If this flag is set these attributes
+   * are neither parsed nor visited (i.e. {@link MethodVisitor#visitFrame} is not called). This flag
+   * is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is used: it avoids visiting frames
+   * that will be ignored and recomputed from scratch.
+   */
+  public static final int SKIP_FRAMES = 4;
 
-    /**
-     * Flag to expand the stack map frames. By default stack map frames are
-     * visited in their original format (i.e. "expanded" for classes whose
-     * version is less than V1_6, and "compressed" for the other classes). If
-     * this flag is set, stack map frames are always visited in expanded format
-     * (this option adds a decompression/recompression step in ClassReader and
-     * ClassWriter which degrades performances quite a lot).
-     */
-    public static final int EXPAND_FRAMES = 8;
+  /**
+   * A flag to expand the stack map frames. By default stack map frames are visited in their
+   * original format (i.e. "expanded" for classes whose version is less than V1_6, and "compressed"
+   * for the other classes). If this flag is set, stack map frames are always visited in expanded
+   * format (this option adds a decompression/compression step in ClassReader and ClassWriter which
+   * degrades performance quite a lot).
+   */
+  public static final int EXPAND_FRAMES = 8;
 
-    /**
-     * Flag to expand the ASM pseudo instructions into an equivalent sequence of
-     * standard bytecode instructions. When resolving a forward jump it may
-     * happen that the signed 2 bytes offset reserved for it is not sufficient
-     * to store the bytecode offset. In this case the jump instruction is
-     * replaced with a temporary ASM pseudo instruction using an unsigned 2
-     * bytes offset (see Label#resolve). This internal flag is used to re-read
-     * classes containing such instructions, in order to replace them with
-     * standard instructions. In addition, when this flag is used, GOTO_W and
-     * JSR_W are <i>not</i> converted into GOTO and JSR, to make sure that
-     * infinite loops where a GOTO_W is replaced with a GOTO in ClassReader and
-     * converted back to a GOTO_W in ClassWriter cannot occur.
-     */
-    static final int EXPAND_ASM_INSNS = 256;
+  /**
+   * A flag to expand the ASM specific instructions into an equivalent sequence of standard bytecode
+   * instructions. When resolving a forward jump it may happen that the signed 2 bytes offset
+   * reserved for it is not sufficient to store the bytecode offset. In this case the jump
+   * instruction is replaced with a temporary ASM specific instruction using an unsigned 2 bytes
+   * offset (see {@link Label#resolve}). This internal flag is used to re-read classes containing
+   * such instructions, in order to replace them with standard instructions. In addition, when this
+   * flag is used, goto_w and jsr_w are <i>not</i> converted into goto and jsr, to make sure that
+   * infinite loops where a goto_w is replaced with a goto in ClassReader and converted back to a
+   * goto_w in ClassWriter cannot occur.
+   */
+  static final int EXPAND_ASM_INSNS = 256;
 
-    /**
-     * The class to be parsed. <i>The content of this array must not be
-     * modified. This field is intended for {@link Attribute} sub classes, and
-     * is normally not needed by class generators or adapters.</i>
-     */
-    public final byte[] b;
+  /**
+   * A byte array containing the JVMS ClassFile structure to be parsed. <i>The content of this array
+   * must not be modified. This field is intended for {@link Attribute} sub classes, and is normally
+   * not needed by class visitors.</i>
+   *
+   * <p>NOTE: the ClassFile structure can start at any offset within this array, i.e. it does not
+   * necessarily start at offset 0. Use {@link #getItem} and {@link #header} to get correct
+   * ClassFile element offsets within this byte array.
+   */
+  public final byte[] b;
 
-    /**
-     * The start index of each constant pool item in {@link #b b}, plus one. The
-     * one byte offset skips the constant pool item tag that indicates its type.
-     */
-    private final int[] items;
+  /**
+   * The offset in bytes, in {@link #b}, of each cp_info entry of the ClassFile's constant_pool
+   * array, <i>plus one</i>. In other words, the offset of constant pool entry i is given by
+   * cpInfoOffsets[i] - 1, i.e. its cp_info's tag field is given by b[cpInfoOffsets[i] - 1].
+   */
+  private final int[] cpInfoOffsets;
 
-    /**
-     * The String objects corresponding to the CONSTANT_Utf8 items. This cache
-     * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
-     * which GREATLY improves performances (by a factor 2 to 3). This caching
-     * strategy could be extended to all constant pool items, but its benefit
-     * would not be so great for these items (because they are much less
-     * expensive to parse than CONSTANT_Utf8 items).
-     */
-    private final String[] strings;
+  /**
+   * The String or Condy objects respectively corresponding to the CONSTANT_Utf8 and
+   * CONSTANT_Dynamic items. This cache avoids multiple parsing of those constant pool items.
+   */
+  private final Object[] cacheValues;
 
-    /**
-     * Maximum length of the strings contained in the constant pool of the
-     * class.
-     */
-    private final int maxStringLength;
+  /**
+   * The start offsets in {@link ClassReader#b} of each element of the bootstrap_methods array (in
+   * the BootstrapMethod attribute).
+   *
+   * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.23">JVMS
+   *     4.7.23</a>
+   */
+  int[] bootstrapMethodOffsets;
 
-    /**
-     * Start index of the class header information (access, name...) in
-     * {@link #b b}.
-     */
-    public final int header;
+  /**
+   * A conservative estimate of the maximum length of the strings contained in the constant pool of
+   * the class.
+   */
+  private final int maxStringLength;
 
-    // ------------------------------------------------------------------------
-    // Constructors
-    // ------------------------------------------------------------------------
+  /** The offset in bytes, in {@link #b}, of the ClassFile's access_flags field. */
+  public final int header;
 
-    /**
-     * Constructs a new {@link ClassReader} object.
-     *
-     * @param b
-     *            the bytecode of the class to be read.
-     */
-    public ClassReader(final byte[] b) {
-        this(b, 0, b.length);
+  // -----------------------------------------------------------------------------------------------
+  // Constructors
+  // -----------------------------------------------------------------------------------------------
+
+  /**
+   * Constructs a new {@link ClassReader} object.
+   *
+   * @param classFile the JVMS ClassFile structure to be read.
+   */
+  public ClassReader(final byte[] classFile) {
+    this(classFile, 0, classFile.length);
+  }
+
+  /**
+   * Constructs a new {@link ClassReader} object.
+   *
+   * @param classFileBuffer a byte array containing the JVMS ClassFile structure to be read.
+   * @param classFileOffset the offset in byteBuffer of the first byte of the ClassFile to be read.
+   * @param classFileLength the length in bytes of the ClassFile to be read.
+   */
+  public ClassReader(
+      final byte[] classFileBuffer, final int classFileOffset, final int classFileLength) {
+    this(classFileBuffer, classFileOffset, /* checkClassVersion = */ true);
+  }
+
+  /**
+   * Constructs a new {@link ClassReader} object. <i>This internal constructor must not be exposed
+   * as a public API</i>.
+   *
+   * @param classFileBuffer a byte array containing the JVMS ClassFile structure to be read.
+   * @param classFileOffset the offset in byteBuffer of the first byte of the ClassFile to be read.
+   * @param checkClassVersion whether to check the class version or not.
+   */
+  ClassReader(
+      final byte[] classFileBuffer, final int classFileOffset, final boolean checkClassVersion) {
+    this.b = classFileBuffer;
+    // Check the class' major_version. This field is after the magic and minor_version fields, which
+    // use 4 and 2 bytes respectively.
+    if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V11) {
+      throw new IllegalArgumentException(
+          "Unsupported class file major version " + readShort(classFileOffset + 6));
+    }
+    // Create the constant pool arrays. The constant_pool_count field is after the magic,
+    // minor_version and major_version fields, which use 4, 2 and 2 bytes respectively.
+    int constantPoolCount = readUnsignedShort(classFileOffset + 8);
+    cpInfoOffsets = new int[constantPoolCount];
+    cacheValues = new Object[constantPoolCount];
+    // Compute the offset of each constant pool entry, as well as a conservative estimate of the
+    // maximum length of the constant pool strings. The first constant pool entry is after the
+    // magic, minor_version, major_version and constant_pool_count fields, which use 4, 2, 2 and 2
+    // bytes respectively.
+    int currentCpInfoIndex = 1;
+    int currentCpInfoOffset = classFileOffset + 10;
+    int currentMaxStringLength = 0;
+    // The offset of the other entries depend on the total size of all the previous entries.
+    while (currentCpInfoIndex < constantPoolCount) {
+      cpInfoOffsets[currentCpInfoIndex++] = currentCpInfoOffset + 1;
+      int cpInfoSize;
+      switch (classFileBuffer[currentCpInfoOffset]) {
+        case Symbol.CONSTANT_FIELDREF_TAG:
+        case Symbol.CONSTANT_METHODREF_TAG:
+        case Symbol.CONSTANT_INTERFACE_METHODREF_TAG:
+        case Symbol.CONSTANT_INTEGER_TAG:
+        case Symbol.CONSTANT_FLOAT_TAG:
+        case Symbol.CONSTANT_NAME_AND_TYPE_TAG:
+        case Symbol.CONSTANT_INVOKE_DYNAMIC_TAG:
+        case Symbol.CONSTANT_DYNAMIC_TAG:
+          cpInfoSize = 5;
+          break;
+        case Symbol.CONSTANT_LONG_TAG:
+        case Symbol.CONSTANT_DOUBLE_TAG:
+          cpInfoSize = 9;
+          currentCpInfoIndex++;
+          break;
+        case Symbol.CONSTANT_UTF8_TAG:
+          cpInfoSize = 3 + readUnsignedShort(currentCpInfoOffset + 1);
+          if (cpInfoSize > currentMaxStringLength) {
+            // The size in bytes of this CONSTANT_Utf8 structure provides a conservative estimate
+            // of the length in characters of the corresponding string, and is much cheaper to
+            // compute than this exact length.
+            currentMaxStringLength = cpInfoSize;
+          }
+          break;
+        case Symbol.CONSTANT_METHOD_HANDLE_TAG:
+          cpInfoSize = 4;
+          break;
+        case Symbol.CONSTANT_CLASS_TAG:
+        case Symbol.CONSTANT_STRING_TAG:
+        case Symbol.CONSTANT_METHOD_TYPE_TAG:
+        case Symbol.CONSTANT_PACKAGE_TAG:
+        case Symbol.CONSTANT_MODULE_TAG:
+          cpInfoSize = 3;
+          break;
+        default:
+          throw new IllegalArgumentException();
+      }
+      currentCpInfoOffset += cpInfoSize;
+    }
+    this.maxStringLength = currentMaxStringLength;
+    // The Classfile's access_flags field is just after the last constant pool entry.
+    this.header = currentCpInfoOffset;
+  }
+
+  /**
+   * Constructs a new {@link ClassReader} object.
+   *
+   * @param inputStream an input stream of the JVMS ClassFile structure to be read. This input
+   *     stream must contain nothing more than the ClassFile structure itself. It is read from its
+   *     current position to its end.
+   * @throws IOException if a problem occurs during reading.
+   */
+  public ClassReader(final InputStream inputStream) throws IOException {
+    this(readStream(inputStream, false));
+  }
+
+  /**
+   * Constructs a new {@link ClassReader} object.
+   *
+   * @param className the fully qualified name of the class to be read. The ClassFile structure is
+   *     retrieved with the current class loader's {@link ClassLoader#getSystemResourceAsStream}.
+   * @throws IOException if an exception occurs during reading.
+   */
+  public ClassReader(final String className) throws IOException {
+    this(
+        readStream(
+            ClassLoader.getSystemResourceAsStream(className.replace('.', '/') + ".class"), true));
+  }
+
+  /**
+   * Reads the given input stream and returns its content as a byte array.
+   *
+   * @param inputStream an input stream.
+   * @param close true to close the input stream after reading.
+   * @return the content of the given input stream.
+   * @throws IOException if a problem occurs during reading.
+   */
+  private static byte[] readStream(final InputStream inputStream, final boolean close)
+      throws IOException {
+    if (inputStream == null) {
+      throw new IOException("Class not found");
+    }
+    try {
+      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+      byte[] data = new byte[inputStream.available()];
+      int bytesRead;
+      while ((bytesRead = inputStream.read(data, 0, data.length)) != -1) {
+        outputStream.write(data, 0, bytesRead);
+      }
+      outputStream.flush();
+      return outputStream.toByteArray();
+    } finally {
+      if (close) {
+        inputStream.close();
+      }
+    }
+  }
+
+  // -----------------------------------------------------------------------------------------------
+  // Accessors
+  // -----------------------------------------------------------------------------------------------
+
+  /**
+   * Returns the class's access flags (see {@link Opcodes}). This value may not reflect Deprecated
+   * and Synthetic flags when bytecode is before 1.5 and those flags are represented by attributes.
+   *
+   * @return the class access flags.
+   * @see ClassVisitor#visit(int, int, String, String, String, String[])
+   */
+  public int getAccess() {
+    return readUnsignedShort(header);
+  }
+
+  /**
+   * Returns the internal name of the class (see {@link Type#getInternalName()}).
+   *
+   * @return the internal class name.
+   * @see ClassVisitor#visit(int, int, String, String, String, String[])
+   */
+  public String getClassName() {
+    // this_class is just after the access_flags field (using 2 bytes).
+    return readClass(header + 2, new char[maxStringLength]);
+  }
+
+  /**
+   * Returns the internal of name of the super class (see {@link Type#getInternalName()}). For
+   * interfaces, the super class is {@link Object}.
+   *
+   * @return the internal name of the super class, or <tt>null</tt> for {@link Object} class.
+   * @see ClassVisitor#visit(int, int, String, String, String, String[])
+   */
+  public String getSuperName() {
+    // super_class is after the access_flags and this_class fields (2 bytes each).
+    return readClass(header + 4, new char[maxStringLength]);
+  }
+
+  /**
+   * Returns the internal names of the implemented interfaces (see {@link Type#getInternalName()}).
+   *
+   * @return the internal names of the directly implemented interfaces. Inherited implemented
+   *     interfaces are not returned.
+   * @see ClassVisitor#visit(int, int, String, String, String, String[])
+   */
+  public String[] getInterfaces() {
+    // interfaces_count is after the access_flags, this_class and super_class fields (2 bytes each).
+    int currentOffset = header + 6;
+    int interfacesCount = readUnsignedShort(currentOffset);
+    String[] interfaces = new String[interfacesCount];
+    if (interfacesCount > 0) {
+      char[] charBuffer = new char[maxStringLength];
+      for (int i = 0; i < interfacesCount; ++i) {
+        currentOffset += 2;
+        interfaces[i] = readClass(currentOffset, charBuffer);
+      }
+    }
+    return interfaces;
+  }
+
+  // -----------------------------------------------------------------------------------------------
+  // Public methods
+  // -----------------------------------------------------------------------------------------------
+
+  /**
+   * Makes the given visitor visit the JVMS ClassFile structure passed to the constructor of this
+   * {@link ClassReader}.
+   *
+   * @param classVisitor the visitor that must visit this class.
+   * @param parsingOptions the options to use to parse this class. One or more of {@link
+   *     #SKIP_CODE}, {@link #SKIP_DEBUG}, {@link #SKIP_FRAMES} or {@link #EXPAND_FRAMES}.
+   */
+  public void accept(final ClassVisitor classVisitor, final int parsingOptions) {
+    accept(classVisitor, new Attribute[0], parsingOptions);
+  }
+
+  /**
+   * Makes the given visitor visit the JVMS ClassFile structure passed to the constructor of this
+   * {@link ClassReader}.
+   *
+   * @param classVisitor the visitor that must visit this class.
+   * @param attributePrototypes prototypes of the attributes that must be parsed during the visit of
+   *     the class. Any attribute whose type is not equal to the type of one the prototypes will not
+   *     be parsed: its byte array value will be passed unchanged to the ClassWriter. <i>This may
+   *     corrupt it if this value contains references to the constant pool, or has syntactic or
+   *     semantic links with a class element that has been transformed by a class adapter between
+   *     the reader and the writer</i>.
+   * @param parsingOptions the options to use to parse this class. One or more of {@link
+   *     #SKIP_CODE}, {@link #SKIP_DEBUG}, {@link #SKIP_FRAMES} or {@link #EXPAND_FRAMES}.
+   */
+  public void accept(
+      final ClassVisitor classVisitor,
+      final Attribute[] attributePrototypes,
+      final int parsingOptions) {
+    Context context = new Context();
+    context.attributePrototypes = attributePrototypes;
+    context.parsingOptions = parsingOptions;
+    context.charBuffer = new char[maxStringLength];
+
+    // Read the access_flags, this_class, super_class, interface_count and interfaces fields.
+    char[] charBuffer = context.charBuffer;
+    int currentOffset = header;
+    int accessFlags = readUnsignedShort(currentOffset);
+    String thisClass = readClass(currentOffset + 2, charBuffer);
+    String superClass = readClass(currentOffset + 4, charBuffer);
+    String[] interfaces = new String[readUnsignedShort(currentOffset + 6)];
+    currentOffset += 8;
+    for (int i = 0; i < interfaces.length; ++i) {
+      interfaces[i] = readClass(currentOffset, charBuffer);
+      currentOffset += 2;
     }
 
-    /**
-     * Constructs a new {@link ClassReader} object.
-     *
-     * @param b
-     *            the bytecode of the class to be read.
-     * @param off
-     *            the start offset of the class data.
-     * @param len
-     *            the length of the class data.
-     */
-    public ClassReader(final byte[] b, final int off, final int len) {
-        this.b = b;
-        // checks the class version
-        if (readShort(off + 6) > Opcodes.V11) {
-            throw new IllegalArgumentException();
+    // Read the class attributes (the variables are ordered as in Section 4.7 of the JVMS).
+    // Attribute offsets exclude the attribute_name_index and attribute_length fields.
+    // - The offset of the InnerClasses attribute, or 0.
+    int innerClassesOffset = 0;
+    // - The offset of the EnclosingMethod attribute, or 0.
+    int enclosingMethodOffset = 0;
+    // - The string corresponding to the Signature attribute, or null.
+    String signature = null;
+    // - The string corresponding to the SourceFile attribute, or null.
+    String sourceFile = null;
+    // - The string corresponding to the SourceDebugExtension attribute, or null.
+    String sourceDebugExtension = null;
+    // - The offset of the RuntimeVisibleAnnotations attribute, or 0.
+    int runtimeVisibleAnnotationsOffset = 0;
+    // - The offset of the RuntimeInvisibleAnnotations attribute, or 0.
+    int runtimeInvisibleAnnotationsOffset = 0;
+    // - The offset of the RuntimeVisibleTypeAnnotations attribute, or 0.
+    int runtimeVisibleTypeAnnotationsOffset = 0;
+    // - The offset of the RuntimeInvisibleTypeAnnotations attribute, or 0.
+    int runtimeInvisibleTypeAnnotationsOffset = 0;
+    // - The offset of the Module attribute, or 0.
+    int moduleOffset = 0;
+    // - The offset of the ModulePackages attribute, or 0.
+    int modulePackagesOffset = 0;
+    // - The string corresponding to the ModuleMainClass attribute, or null.
+    String moduleMainClass = null;
+    // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
+    //   This list in the <i>reverse order</i> or their order in the ClassFile structure.
+    Attribute attributes = null;
+
+    int currentAttributeOffset = getFirstAttributeOffset();
+    for (int i = readUnsignedShort(currentAttributeOffset - 2); i > 0; --i) {
+      // Read the attribute_info's attribute_name and attribute_length fields.
+      String attributeName = readUTF8(currentAttributeOffset, charBuffer);
+      int attributeLength = readInt(currentAttributeOffset + 2);
+      currentAttributeOffset += 6;
+      // The tests are sorted in decreasing frequency order (based on frequencies observed on
+      // typical classes).
+      if (Constants.SOURCE_FILE.equals(attributeName)) {
+        sourceFile = readUTF8(currentAttributeOffset, charBuffer);
+      } else if (Constants.INNER_CLASSES.equals(attributeName)) {
+        innerClassesOffset = currentAttributeOffset;
+      } else if (Constants.ENCLOSING_METHOD.equals(attributeName)) {
+        enclosingMethodOffset = currentAttributeOffset;
+      } else if (Constants.SIGNATURE.equals(attributeName)) {
+        signature = readUTF8(currentAttributeOffset, charBuffer);
+      } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
+        runtimeVisibleAnnotationsOffset = currentAttributeOffset;
+      } else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
+        runtimeVisibleTypeAnnotationsOffset = currentAttributeOffset;
+      } else if (Constants.DEPRECATED.equals(attributeName)) {
+        accessFlags |= Opcodes.ACC_DEPRECATED;
+      } else if (Constants.SYNTHETIC.equals(attributeName)) {
+        accessFlags |= Opcodes.ACC_SYNTHETIC;
+      } else if (Constants.SOURCE_DEBUG_EXTENSION.equals(attributeName)) {
+        sourceDebugExtension =
+            readUTF(currentAttributeOffset, attributeLength, new char[attributeLength]);
+      } else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) {
+        runtimeInvisibleAnnotationsOffset = currentAttributeOffset;
+      } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
+        runtimeInvisibleTypeAnnotationsOffset = currentAttributeOffset;
+      } else if (Constants.MODULE.equals(attributeName)) {
+        moduleOffset = currentAttributeOffset;
+      } else if (Constants.MODULE_MAIN_CLASS.equals(attributeName)) {
+        moduleMainClass = readClass(currentAttributeOffset, charBuffer);
+      } else if (Constants.MODULE_PACKAGES.equals(attributeName)) {
+        modulePackagesOffset = currentAttributeOffset;
+      } else if (Constants.BOOTSTRAP_METHODS.equals(attributeName)) {
+        // Read the num_bootstrap_methods field and create an array of this size.
+        int[] bootstrapMethodOffsets = new int[readUnsignedShort(currentAttributeOffset)];
+        // Compute and store the offset of each 'bootstrap_methods' array field entry.
+        int currentBootstrapMethodOffset = currentAttributeOffset + 2;
+        for (int j = 0; j < bootstrapMethodOffsets.length; ++j) {
+          bootstrapMethodOffsets[j] = currentBootstrapMethodOffset;
+          // Skip the bootstrap_method_ref and num_bootstrap_arguments fields (2 bytes each),
+          // as well as the bootstrap_arguments array field (of size num_bootstrap_arguments * 2).
+          currentBootstrapMethodOffset +=
+              4 + readUnsignedShort(currentBootstrapMethodOffset + 2) * 2;
         }
-        // parses the constant pool
-        items = new int[readUnsignedShort(off + 8)];
-        int n = items.length;
-        strings = new String[n];
-        int max = 0;
-        int index = off + 10;
-        for (int i = 1; i < n; ++i) {
-            items[i] = index + 1;
-            int size;
-            switch (b[index]) {
-            case ClassWriter.FIELD:
-            case ClassWriter.METH:
-            case ClassWriter.IMETH:
-            case ClassWriter.INT:
-            case ClassWriter.FLOAT:
-            case ClassWriter.NAME_TYPE:
-            case ClassWriter.INDY:
-            // @@@ ClassWriter.CONDY
-            // Enables MethodHandles.lookup().defineClass to function correctly
-            // when it reads the class name
-            case 17:
-                size = 5;
-                break;
-            case ClassWriter.LONG:
-            case ClassWriter.DOUBLE:
-                size = 9;
-                ++i;
-                break;
-            case ClassWriter.UTF8:
-                size = 3 + readUnsignedShort(index + 1);
-                if (size > max) {