changeset 3514:a1f724d412b0

Enhancement: add compiler support for ConstantDynamic * add javac/javap support for CONSTANT_ConstantDynamic * add trivial use of constant dynamic for synthetizing primitive class literals (enabled with -XDdynamicClassConstants)
author mcimadamore
date Fri, 26 Aug 2016 14:19:48 +0100
parents 9204dd938160
children 7c372b827541
files src/jdk.compiler/share/classes/com/sun/tools/javac/code/Dynamic.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/comp/IndifierTranslator.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/SpecializeTypes.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.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/PoolReader.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassTranslator.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPool.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java test/tools/javac/lambda/ByteCodeTest.java test/tools/javac/lambda/TestBootstrapMethodsCount.java test/tools/javac/lambda/TestInvokeDynamic.java
diffstat 25 files changed, 493 insertions(+), 187 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Dynamic.java	Fri Aug 26 14:19:48 2016 +0100
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.code;
+
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Type.MethodType;
+import com.sun.tools.javac.code.Type.TypeVar;
+import com.sun.tools.javac.util.Assert;
+
+import java.util.Optional;
+
+public interface Dynamic {
+    /**
+     * A class representing a static argument in an indy call.
+     */
+    class BootstrapArgument<D> {
+
+        public static final int SPECIALIZABLE = 1;
+        public static final int NEEDS_ACCESSORS = 2;
+
+        public int flags = SPECIALIZABLE | NEEDS_ACCESSORS;
+
+        /**
+         * Static argument kind.
+         */
+        public enum Kind {
+            CLASS(ClassSymbol.class),
+            INT(Integer.class),
+            LONG(Long.class),
+            FLOAT(Float.class),
+            DOUBLE(Double.class),
+            STRING(String.class),
+            METHOD_HANDLE(MethodHandleSymbol.class),
+            METHOD_TYPE(MethodType.class),
+            TYPEVAR(TypeVar.class);
+
+            final Class<?> clazz;
+
+            Kind(Class<?> clazz) {
+                this.clazz = clazz;
+            }
+
+            public Type asType(Symtab syms) {
+                switch (this) {
+                    case CLASS:
+                        return syms.classType;
+                    case INT:
+                        return syms.intType;
+                    case LONG:
+                        return syms.longType;
+                    case FLOAT:
+                        return syms.floatType;
+                    case DOUBLE:
+                        return syms.doubleType;
+                    case TYPEVAR:
+                    case STRING:
+                        return syms.stringType;
+                    case METHOD_HANDLE:
+                        return syms.methodHandleType;
+                    case METHOD_TYPE:
+                        return syms.methodTypeType;
+                    default:
+                        Assert.error("Unexpected kind " + this);
+                        return null;
+                }
+            }
+        }
+
+        public final BootstrapArgument.Kind kind;
+        public final D data;
+
+        public BootstrapArgument(BootstrapArgument.Kind kind, D data) {
+            this.kind = kind;
+            this.data = data;
+            Assert.check(kind.clazz.isAssignableFrom(data.getClass()));
+        }
+
+        /**
+         * Map a static argument to a type (where possible).
+         */
+        public Optional<Type> asType() {
+            switch (kind) {
+                case METHOD_TYPE:
+                    return Optional.of(((MethodType)data));
+                case CLASS:
+                    return Optional.of(((Symbol)data).type);
+                case METHOD_HANDLE:
+                    return Optional.of(((MethodHandleSymbol)data).owner.type);
+                case TYPEVAR:
+                    return Optional.of(((TypeVar)data));
+                default:
+                    return Optional.empty();
+            }
+        }
+
+        /**
+         * Map a static argument to a symbol (where possible).
+         */
+        public Optional<Symbol> asSymbol() {
+            switch (kind) {
+                case CLASS:
+                    return Optional.of(((Symbol)data));
+                case METHOD_HANDLE:
+                    return Optional.of(((MethodHandleSymbol)data));
+                case TYPEVAR:
+                    return Optional.of(((TypeVar)data).tsym);
+                default:
+                    return Optional.empty();
+            }
+        }
+
+        //factory methods
+        public static BootstrapArgument<ClassSymbol> Class(ClassSymbol data) { return new BootstrapArgument<>(BootstrapArgument.Kind.CLASS, data); }
+        public static BootstrapArgument<Integer> Int(Integer data) { return new BootstrapArgument<>(BootstrapArgument.Kind.INT, data); }
+        public static BootstrapArgument<Float> Float(Float data) { return new BootstrapArgument<>(BootstrapArgument.Kind.FLOAT, data); }
+        public static BootstrapArgument<Double> Double(Double data) { return new BootstrapArgument<>(BootstrapArgument.Kind.DOUBLE, data); }
+        public static BootstrapArgument<String> String(String data) { return new BootstrapArgument<>(BootstrapArgument.Kind.STRING, data); }
+        public static BootstrapArgument<MethodHandleSymbol> MethodHandle(MethodSymbol data) { return new BootstrapArgument<>(BootstrapArgument.Kind.METHOD_HANDLE, data.asHandle()); }
+        public static BootstrapArgument<MethodType> MethodType(MethodType data) { return new BootstrapArgument<>(BootstrapArgument.Kind.METHOD_TYPE, data.asConstant()); }
+        public static BootstrapArgument<TypeVar> TypeVar(TypeVar data) { return new BootstrapArgument<>(BootstrapArgument.Kind.TYPEVAR, data); }
+    }
+
+    BootstrapArgument<?>[] getStaticArgs();
+    Symbol getBootstrapMethod();
+
+    interface DynamicConstant extends Dynamic {
+        Type getType();
+    }
+}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Fri Aug 26 14:19:48 2016 +0100
@@ -36,6 +36,7 @@
 import javax.lang.model.element.*;
 import javax.tools.JavaFileObject;
 
+import com.sun.tools.javac.code.Dynamic.BootstrapArgument;
 import com.sun.tools.javac.code.Types.AsSuperKind;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
 import com.sun.tools.javac.code.Scope.WriteableScope;
@@ -1875,121 +1876,10 @@
 
     /** A class for invokedynamic method calls.
      */
-    public static class DynamicMethodSymbol extends MethodSymbol {
-
-        /**
-         * A class representing a static argument in an indy call.
-         */
-        public static class BootstrapArgument<D> {
-
-            public static final int SPECIALIZABLE = 1;
-            public static final int NEEDS_ACCESSORS = 2;
-
-            public int flags = SPECIALIZABLE | NEEDS_ACCESSORS;
-
-            /**
-             * Static argument kind.
-             */
-            public enum Kind {
-                CLASS(ClassSymbol.class),
-                INT(Integer.class),
-                LONG(Long.class),
-                FLOAT(Float.class),
-                DOUBLE(Double.class),
-                STRING(String.class),
-                METHOD_HANDLE(MethodHandleSymbol.class),
-                METHOD_TYPE(MethodType.class),
-                TYPEVAR(TypeVar.class);
-
-                final Class<?> clazz;
-
-                Kind(Class<?> clazz) {
-                    this.clazz = clazz;
-                }
-
-                public Type asType(Symtab syms) {
-                    switch (this) {
-                        case CLASS:
-                            return syms.classType;
-                        case INT:
-                            return syms.intType;
-                        case LONG:
-                            return syms.longType;
-                        case FLOAT:
-                            return syms.floatType;
-                        case DOUBLE:
-                            return syms.doubleType;
-                        case TYPEVAR:
-                        case STRING:
-                            return syms.stringType;
-                        case METHOD_HANDLE:
-                            return syms.methodHandleType;
-                        case METHOD_TYPE:
-                            return syms.methodTypeType;
-                        default:
-                            Assert.error("Unexpected kind " + this);
-                            return null;
-                    }
-                }
-            }
-
-            public final Kind kind;
-            public final D data;
-
-            public BootstrapArgument(Kind kind, D data) {
-                this.kind = kind;
-                this.data = data;
-                Assert.check(kind.clazz.isAssignableFrom(data.getClass()));
-            }
-
-            /**
-             * Map a static argument to a type (where possible).
-             */
-            public Optional<Type> asType() {
-                switch (kind) {
-                    case METHOD_TYPE:
-                        return Optional.of(((MethodType)data));
-                    case CLASS:
-                        return Optional.of(((Symbol)data).type);
-                    case METHOD_HANDLE:
-                        return Optional.of(((MethodHandleSymbol)data).owner.type);
-                    case TYPEVAR:
-                        return Optional.of(((TypeVar)data));
-                    default:
-                        return Optional.empty();
-                }
-            }
-
-            /**
-             * Map a static argument to a symbol (where possible).
-             */
-            public Optional<Symbol> asSymbol() {
-                switch (kind) {
-                    case CLASS:
-                        return Optional.of(((Symbol)data));
-                    case METHOD_HANDLE:
-                        return Optional.of(((MethodHandleSymbol)data));
-                    case TYPEVAR:
-                        return Optional.of(((TypeVar)data).tsym);
-                    default:
-                        return Optional.empty();
-                }
-            }
-
-            //factory methods
-            public static BootstrapArgument<ClassSymbol> Class(ClassSymbol data) { return new BootstrapArgument<>(Kind.CLASS, data); }
-            public static BootstrapArgument<Integer> Int(Integer data) { return new BootstrapArgument<>(Kind.INT, data); }
-            public static BootstrapArgument<Float> Float(Float data) { return new BootstrapArgument<>(Kind.FLOAT, data); }
-            public static BootstrapArgument<Double> Double(Double data) { return new BootstrapArgument<>(Kind.DOUBLE, data); }
-            public static BootstrapArgument<String> String(String data) { return new BootstrapArgument<>(Kind.STRING, data); }
-            public static BootstrapArgument<MethodHandleSymbol> MethodHandle(MethodSymbol data) { return new BootstrapArgument<>(Kind.METHOD_HANDLE, data.asHandle()); }
-            public static BootstrapArgument<MethodType> MethodType(MethodType data) { return new BootstrapArgument<>(Kind.METHOD_TYPE, data.asConstant()); }
-            public static BootstrapArgument<TypeVar> TypeVar(TypeVar data) { return new BootstrapArgument<>(Kind.TYPEVAR, data); }
-        }
+    public static class DynamicMethodSymbol extends MethodSymbol implements Dynamic {
 
         public BootstrapArgument<?>[] staticArgs;
         public Symbol bsm;
-        public int bsmKind;
 
         public DynamicMethodSymbol(Name name, Symbol owner, MethodHandleSymbol bsm, Type type, BootstrapArgument<?>[] staticArgs) {
             super(0, name, type, owner);
@@ -2001,6 +1891,16 @@
         public boolean isDynamic() {
             return true;
         }
+
+        @Override
+        public BootstrapArgument<?>[] getStaticArgs() {
+            return staticArgs;
+        }
+
+        @Override
+        public Symbol getBootstrapMethod() {
+            return bsm;
+        }
     }
 
     /** A class for method handles.
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Fri Aug 26 14:19:48 2016 +0100
@@ -207,6 +207,7 @@
     public final Type genericStaticDispatch;
     public final Type virtualAccess;
     public final Type objectibleDispatch;
+    public final Type classConstantFactory;
 
     /** The symbol representing the length field of an array.
      */
@@ -332,6 +333,23 @@
         }
     }
 
+    public void synthesizeEmptyConstantBSMIfMissing(final Type type, final Type restype, List<Type> staticArgs) {
+        final Completer completer = type.tsym.completer;
+        if (completer != null) {
+            type.tsym.completer = new Completer() {
+                public void complete(Symbol sym) throws CompletionFailure {
+                    try {
+                        completer.complete(sym);
+                    } catch (CompletionFailure e) {
+                        sym.flags_field |= (PUBLIC | INTERFACE);
+                        ((ClassType) sym.type).supertype_field = objectType;
+                        sym.members().enter(new MethodSymbol(STATIC | PUBLIC, names.makeConstant, new MethodType(List.of(methodHandleLookupType, stringType, methodTypeType).appendList(staticArgs), restype, List.nil(), methodClass), sym));
+                    }
+                }
+            };
+        }
+    }
+
     public void synthesizeBoxTypeIfMissing(final Type type) {
         ClassSymbol sym = enterClass(boxedName[type.getTag().ordinal()]);
         final Completer completer = sym.completer;
@@ -541,6 +559,7 @@
         genericStaticDispatch = enterClass("java.lang.invoke.GenericStaticDispatch");
         virtualAccess = enterClass("java.lang.invoke.VirtualAccess");
         objectibleDispatch = enterClass("java.lang.invoke.ObjectibleDispatch");
+        classConstantFactory = enterClass("java.lang.invoke.ClassConstantFactory");
         //transitional
         synthesizeEmptyInterfaceIfMissing(varHandleType);
         synthesizeEmptyInterfaceIfMissing(fieldHandleType);
@@ -555,6 +574,7 @@
         synthesizeEmptyBSMIfMissing(genericStaticDispatch);
         synthesizeEmptyBSMIfMissing(virtualAccess);
         synthesizeEmptyBSMIfMissing(objectibleDispatch);
+        synthesizeEmptyConstantBSMIfMissing(classConstantFactory, classType, List.of(stringType));
         synthesizeEmptyInterfaceIfMissing(serializedLambdaType);
         synthesizeEmptyInterfaceIfMissing(stringConcatFactory);
         synthesizeBoxTypeIfMissing(doubleType);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/IndifierTranslator.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/IndifierTranslator.java	Fri Aug 26 14:19:48 2016 +0100
@@ -28,7 +28,7 @@
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
-import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument;
+import com.sun.tools.javac.code.Dynamic.BootstrapArgument;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 import com.sun.tools.javac.code.Symtab;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Aug 26 14:19:48 2016 +0100
@@ -28,7 +28,7 @@
 import com.sun.tools.javac.code.Attribute.TypeCompound;
 import com.sun.tools.javac.code.Kinds.KindSelector;
 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
-import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument;
+import com.sun.tools.javac.code.Dynamic.BootstrapArgument;
 import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
 import com.sun.tools.javac.code.Symbol.TypeVariableSymbol;
 import com.sun.tools.javac.code.Type.ForAll;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Fri Aug 26 14:19:48 2016 +0100
@@ -30,8 +30,8 @@
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Kinds.KindSelector;
 import com.sun.tools.javac.code.Scope.WriteableScope;
-import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument;
-import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument.Kind;
+import com.sun.tools.javac.code.Dynamic.BootstrapArgument;
+import com.sun.tools.javac.code.Dynamic.BootstrapArgument.Kind;
 import com.sun.tools.javac.comp.Resolve.StaticLevel;
 import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.main.Option.PkgInfo;
@@ -92,6 +92,7 @@
     private final Name dollarAssertionsDisabled;
     private final Name classDollar;
     private final Types types;
+    private final boolean dynamicClassConstants;
     private final boolean debugLower;
     private final boolean disableAccessors;
     private final PkgInfo pkginfoOpt;
@@ -119,6 +120,7 @@
 
         types = Types.instance(context);
         Options options = Options.instance(context);
+        dynamicClassConstants = options.isSet("dynamicClassConstants");
         debugLower = options.isSet("debuglower");
         pkginfoOpt = PkgInfo.get(options);
         disableAccessors = options.isSet("disableAccessors");
@@ -2193,19 +2195,29 @@
         return classOfType(types.erasure(clazz.type), clazz.type, clazz.pos());
     }
 
+    @SuppressWarnings("fallthrough")
     private JCExpression classOfType(Type type, Type unerased, DiagnosticPosition pos) {
         switch (type.getTag()) {
-        case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
-        case DOUBLE: case BOOLEAN: case VOID:
-            // replace with <BoxedClass>.TYPE
-            ClassSymbol c = types.boxedClass(type);
-            Symbol typeSym =
-                rs.accessBase(
-                    rs.findIdentInType(attrEnv, c.type, names.TYPE, KindSelector.VAR),
-                    pos, c.type, names.TYPE, true);
-            if (typeSym.kind == VAR)
-                ((VarSymbol)typeSym).getConstValue(); // ensure initializer is evaluated
-            return make.QualIdent(typeSym);
+            case BYTE:
+            case SHORT:
+            case CHAR:
+            case INT:
+            case LONG:
+            case FLOAT:
+            case DOUBLE:
+            case BOOLEAN:
+            case VOID:
+                if (!dynamicClassConstants) {
+                    // replace with <BoxedClass>.TYPE
+                    ClassSymbol c = types.boxedClass(type);
+                    Symbol typeSym =
+                            rs.accessBase(
+                                    rs.findIdentInType(attrEnv, c.type, names.TYPE, KindSelector.VAR),
+                                    pos, c.type, names.TYPE, true);
+                    if (typeSym.kind == VAR)
+                        ((VarSymbol)typeSym).getConstValue(); // ensure initializer is evaluated
+                    return make.QualIdent(typeSym);
+                }
         case CLASS: case ARRAY:
                 VarSymbol sym = new VarSymbol(
                         STATIC | PUBLIC | FINAL, names._class,
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Fri Aug 26 14:19:48 2016 +0100
@@ -30,8 +30,8 @@
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
-import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument;
-import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument.Kind;
+import com.sun.tools.javac.code.Dynamic.BootstrapArgument;
+import com.sun.tools.javac.code.Dynamic.BootstrapArgument.Kind;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
 import com.sun.tools.javac.code.Symbol.TypeVariableSymbol;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Fri Aug 26 14:19:48 2016 +0100
@@ -85,6 +85,7 @@
     public final static int CONSTANT_NameandType = 12;
     public final static int CONSTANT_MethodHandle = 15;
     public final static int CONSTANT_MethodType = 16;
+    public final static int CONSTANT_ConstantDynamic = 17;
     public final static int CONSTANT_InvokeDynamic = 18;
     public final static int CONSTANT_TypeVar = 19;
     public final static int CONSTANT_ParameterizedType = 20;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java	Fri Aug 26 14:19:48 2016 +0100
@@ -27,6 +27,7 @@
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.jvm.Pool.ConstantDynamic;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.jvm.Items.*;
@@ -41,6 +42,7 @@
 import static com.sun.tools.javac.code.TypeTag.INT;
 import static com.sun.tools.javac.jvm.ByteCodes.*;
 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_ConstantDynamic;
 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Double;
 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Fieldref;
 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Float;
@@ -1141,6 +1143,7 @@
             case CONSTANT_Class: return syms.classType;
             case CONSTANT_MethodHandle: return syms.methodHandleType;
             case CONSTANT_MethodType: return syms.methodTypeType;
+            case CONSTANT_ConstantDynamic: return (Type)((ConstantDynamic)e).type.data.get();
             default:
                 Type t = (Type)e.data.get();
                 switch (t.getTag()) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Fri Aug 26 14:19:48 2016 +0100
@@ -30,6 +30,7 @@
 import java.util.function.Function;
 import java.util.function.Predicate;
 
+import com.sun.tools.javac.code.Dynamic.DynamicConstant;
 import com.sun.tools.javac.code.Types.TypeVarContext;
 import com.sun.tools.javac.comp.Resolve.StaticLevel;
 import com.sun.tools.javac.util.*;
@@ -2433,11 +2434,49 @@
         }
     }
 
+    class DynamicClassType implements DynamicConstant {
+
+        Type constType;
+
+        DynamicClassType(Type constType) {
+            this.constType = constType;
+        }
+
+        @Override
+        public BootstrapArgument<?>[] getStaticArgs() {
+            return new BootstrapArgument<?>[] { BootstrapArgument.String(types.typeSig(constType).toString()) };
+        }
+
+        @Override
+        public Symbol getBootstrapMethod() {
+            Env<AttrContext> context = getAttrEnv();
+            return rs.resolveInternalMethod(context.enclClass,
+                    context,
+                    syms.classConstantFactory,
+                    names.makeConstant,
+                    List.of(syms.methodHandleLookupType,
+                            syms.stringType,
+                            syms.methodTypeType,
+                            syms.stringType),
+                    null).asHandle();
+        }
+
+        @Override
+        public Type getType() {
+            return syms.classType;
+        }
+    }
+
     public void visitSelect(JCFieldAccess tree) {
         Symbol sym = tree.sym;
 
         if (tree.name == names._class) {
-            code.emitLdc(makeRef(tree.pos(), tree.selected.type));
+            Type constType = tree.selected.type;
+            if (constType.isPrimitiveOrVoid()) {
+                code.emitLdc(pool.putConstant(new DynamicClassType(constType)));
+            } else {
+                code.emitLdc(makeRef(tree.pos(), constType));
+            }
             result = items.makeStackItem(pt);
             return;
        }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Fri Aug 26 14:19:48 2016 +0100
@@ -27,7 +27,7 @@
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument;
+import com.sun.tools.javac.code.Dynamic.BootstrapArgument;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.jvm.Code.*;
 import com.sun.tools.javac.jvm.Gen.Descriptor;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java	Fri Aug 26 14:19:48 2016 +0100
@@ -26,7 +26,6 @@
 package com.sun.tools.javac.jvm;
 
 import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
 import com.sun.tools.javac.code.Type;
 import com.sun.tools.javac.code.Type.ClassType;
@@ -330,6 +329,39 @@
     }
 
     /**
+     * Pool entry associated with dynamic constants.
+     */
+    static class ConstantDynamic extends Entry {
+
+        /** Index into BootstrapMethods attribute. */
+        int bsmIndex;
+
+        /** Constant type. */
+        Constant<Name> type;
+
+        ConstantDynamic(int bsmIndex, Constant<Name> type) {
+            super(ClassFile.CONSTANT_ConstantDynamic);
+            this.bsmIndex = bsmIndex;
+            this.type = type;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(bsmIndex, type);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof ConstantDynamic) {
+                ConstantDynamic that = (ConstantDynamic)obj;
+                return that.bsmIndex == bsmIndex && that.type.equals(type);
+            } else {
+                return false;
+            }
+        }
+    }
+
+    /**
      * Pool entry associated with method handles.
      */
     static class MethodHandle extends Entry {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java	Fri Aug 26 14:19:48 2016 +0100
@@ -45,6 +45,7 @@
 
 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_ArrayType;
 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_ConstantDynamic;
 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Double;
 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Fieldref;
 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Float;
@@ -468,6 +469,7 @@
                     offset += 8;
                     pool.put(new UnresolvedConstant(tag, start));
                     break;
+                case CONSTANT_ConstantDynamic:
                 case CONSTANT_InvokeDynamic:
                     offset += 4;
                     pool.put(new Skip(tag));
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java	Fri Aug 26 14:19:48 2016 +0100
@@ -25,12 +25,14 @@
 
 package com.sun.tools.javac.jvm;
 
+import com.sun.tools.javac.code.Dynamic;
+import com.sun.tools.javac.code.Dynamic.DynamicConstant;
 import com.sun.tools.javac.code.Flags;
 import com.sun.tools.javac.code.Kinds.Kind;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
-import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument;
+import com.sun.tools.javac.code.Dynamic.BootstrapArgument;
 import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
 import com.sun.tools.javac.code.Symbol.TypeSymbol;
@@ -49,6 +51,7 @@
 import com.sun.tools.javac.jvm.ClassWriter.StringOverflow;
 import com.sun.tools.javac.jvm.Gen.Descriptor;
 import com.sun.tools.javac.jvm.Pool.Constant;
+import com.sun.tools.javac.jvm.Pool.ConstantDynamic;
 import com.sun.tools.javac.jvm.Pool.InvokeDynamic;
 import com.sun.tools.javac.jvm.Pool.MemberRef;
 import com.sun.tools.javac.jvm.Pool.MethodDescriptor;
@@ -141,6 +144,19 @@
     }
 
     /**
+     * Puts a constant into the pool and returns the index of the resulting entry.
+     * Note: if a matching entry is already in the pool, no new entry is persisted.
+     */
+    @SuppressWarnings("unchecked")
+    int putConstant(DynamicConstant dc) {
+        int bsmIndex = makeBoostrapEntry(dc);
+        Type constType = dc.getType();
+        Constant<Name> type = (Constant<Name>)makeConstant(typeToSig(constType), constType);
+        Entry e = new ConstantDynamic(bsmIndex, type);
+        return pool.put(e).index;
+    }
+
+    /**
      * Puts a name and type pair into the pool and returns the index of the resulting entry.
      * Note: if a matching entry is already in the pool, no new entry is persisted.
      */
@@ -199,15 +215,18 @@
      * Create a new constant entry from given constant value.
      * Supported values are int, float, long, double, Name and String.
      */
+    private Entry makeConstant(Object o) {
+        return makeConstant(o, o);
+    }
     @SuppressWarnings("unchecked")
-    private Entry makeConstant(Object o) {
+    private Entry makeConstant(Object o, Object data) {
         if (o instanceof String) {
             Constant<Name> name = (Constant<Name>)makeConstant(types.names.fromString((String)o));
             Entry e = new StringRef(name, (String)o);
             return pool.put(e);
         } else {
             //assume it's some other constant
-            Entry e = new Constant<>(constantTag(o), o, o);
+            Entry e = new Constant<>(constantTag(o), o, data);
             return pool.put(e);
         }
     }
@@ -248,6 +267,57 @@
         return s.accept(symbolFactory, null);
     }
 
+    private int makeBoostrapEntry(Dynamic dynamic) {
+        MethodHandle handle = (MethodHandle)makeSymbol(dynamic.getBootstrapMethod()); //bsm
+
+        Entry[] staticArgs = Stream.of(dynamic.getStaticArgs())
+                .map(this::visitStaticIndyArg)
+                .toArray(Entry[]::new);
+
+        BootstrapMethodsKey key = new BootstrapMethodsKey(handle, staticArgs);
+
+        // Figure out the index for existing BSM; create a new BSM if no key
+        Tuple2<MethodHandle, Integer> val = bootstrapMethods.get(key);
+        if (val == null) {
+            int index = bootstrapMethods.size();
+            val = new Tuple2<>(handle, index);
+            bootstrapMethods.put(key, val);
+        }
+
+        return val.elem1;
+    }
+    //where
+        private Entry visitStaticIndyArg(BootstrapArgument<?> staticArg) {
+            switch (staticArg.kind) {
+                case DOUBLE:
+                case FLOAT:
+                case LONG:
+                case INT:
+                case STRING:
+                    return makeConstant(staticArg.data);
+                case METHOD_HANDLE: {
+                    Symbol s = staticArg.asSymbol().get();
+                    return makeSymbol(new MethodHandleSymbol(Descriptor.of(s, s.enclClass().type, types)));
+                }
+                case CLASS:
+                    return makeSymbol(staticArg.asSymbol().get());
+                case TYPEVAR:
+                    boolean prevTypeArgPos = genericTypeFactory.typeArgPosition;
+                    try {
+                        //temporary hack: create a string CP entry which points to a type-var
+                        genericTypeFactory.typeArgPosition = true;
+                        Entry e = makeType(staticArg.asType().get(), PoolWriter.this::typeToSig);
+                        return pool.put(new StringRef(e, typeToSig((Type)staticArg.data).toString()));
+                    } finally {
+                        genericTypeFactory.typeArgPosition = prevTypeArgPos;
+                    }
+                case METHOD_TYPE:
+                    return makeType(staticArg.asType().get(), PoolWriter.this::typeToSig);
+                default:
+                    throw new AssertionError("Cannot get here!");
+            }
+        }
+
     /**
      * Factory used to create entries from symbols.
      */
@@ -297,58 +367,11 @@
         }
         
         private Entry visitDynamicMethod(DynamicMethodSymbol dynSym) {
-            MethodHandle handle = (MethodHandle)makeSymbol(dynSym.bsm); //bsm
-
-            Entry[] staticArgs = Stream.of(dynSym.staticArgs)
-                    .map(this::visitStaticIndyArg)
-                    .toArray(Entry[]::new);
-
-            BootstrapMethodsKey key = new BootstrapMethodsKey(handle, staticArgs);
-
-            // Figure out the index for existing BSM; create a new BSM if no key
-            Tuple2<MethodHandle, Integer> val = bootstrapMethods.get(key);
-            if (val == null) {
-                int index = bootstrapMethods.size();
-                val = new Tuple2<>(handle, index);
-                bootstrapMethods.put(key, val);
-            }
-
-            int bsmIndex = val.elem1;
+            int bsmIndex = makeBoostrapEntry(dynSym);
             NameAndType nt = makeNameAndType(dynSym.name, dynSym.type);
             Entry e = new InvokeDynamic(bsmIndex, nt);
             return pool.put(e);
         }
-
-        private Entry visitStaticIndyArg(BootstrapArgument<?> staticArg) {
-            switch (staticArg.kind) {
-                case DOUBLE:
-                case FLOAT:
-                case LONG:
-                case INT:
-                case STRING:
-                    return makeConstant(staticArg.data);
-                case METHOD_HANDLE: {
-                    Symbol s = staticArg.asSymbol().get();
-                    return makeSymbol(new MethodHandleSymbol(Descriptor.of(s, s.enclClass().type, types)));
-                }
-                case CLASS:
-                    return makeSymbol(staticArg.asSymbol().get());
-                case TYPEVAR:
-                    boolean prevTypeArgPos = genericTypeFactory.typeArgPosition;
-                    try {
-                        //temporary hack: create a string CP entry which points to a type-var
-                        genericTypeFactory.typeArgPosition = true;
-                        Entry e = makeType(staticArg.asType().get(), PoolWriter.this::typeToSig);
-                        return pool.put(new StringRef(e, typeToSig((Type)staticArg.data).toString()));
-                    } finally {
-                        genericTypeFactory.typeArgPosition = prevTypeArgPos;
-                    }
-                case METHOD_TYPE:
-                    return makeType(staticArg.asType().get(), PoolWriter.this::typeToSig);
-                default:
-                    throw new AssertionError("Cannot get here!");
-            }
-        }
         
         private Entry visitHandle(MethodHandleSymbol handle) {
             MemberRef ref = (MemberRef)makeSymbol(handle.baseSymbol());
@@ -672,6 +695,10 @@
                     poolbuf.appendChar(((InvokeDynamic)e).bsmIndex);
                     poolbuf.appendChar(((InvokeDynamic)e).nt.index);
                     break;
+                case ClassFile.CONSTANT_ConstantDynamic:
+                    poolbuf.appendChar(((ConstantDynamic)e).bsmIndex);
+                    poolbuf.appendChar(((ConstantDynamic)e).type.index);
+                    break;
                 case ClassFile.CONSTANT_TypeVar:
                     poolbuf.appendByte(((TypeVariable)e).adr);
                     poolbuf.appendChar(((TypeVariable)e).erasure.index);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java	Fri Aug 26 14:19:48 2016 +0100
@@ -26,7 +26,7 @@
 package com.sun.tools.javac.jvm;
 
 import com.sun.tools.javac.code.*;
-import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument;
+import com.sun.tools.javac.code.Dynamic.BootstrapArgument;
 import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
 import com.sun.tools.javac.code.Type.MethodType;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Fri Aug 26 14:19:48 2016 +0100
@@ -194,6 +194,7 @@
     // string concat
     public final Name makeConcat;
     public final Name makeConcatWithConstants;
+    public final Name makeConstant;
 
     public final Name.Table table;
 
@@ -348,6 +349,7 @@
         // string concat
         makeConcat = fromString("makeConcat");
         makeConcatWithConstants = fromString("makeConcatWithConstants");
+        makeConstant = fromString("makeConstant");
     }
 
     protected Name.Table createTable(Options options) {
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassTranslator.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassTranslator.java	Fri Aug 26 14:19:48 2016 +0100
@@ -29,6 +29,7 @@
 
 import com.sun.tools.classfile.ConstantPool.CONSTANT_ArrayType_info;
 import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_ConstantDynamic_info;
 import com.sun.tools.classfile.ConstantPool.CONSTANT_Double_info;
 import com.sun.tools.classfile.ConstantPool.CONSTANT_Fieldref_info;
 import com.sun.tools.classfile.ConstantPool.CONSTANT_Float_info;
@@ -326,6 +327,20 @@
         return info;
     }
 
+    public CPInfo visitConstantDynamic(CONSTANT_ConstantDynamic_info info, Map<Object, Object> translations) {
+        CONSTANT_ConstantDynamic_info info2 = (CONSTANT_ConstantDynamic_info) translations.get(info);
+        if (info2 == null) {
+            ConstantPool cp2 = translate(info.cp, translations);
+            if (cp2 == info.cp) {
+                info2 = info;
+            } else {
+                info2 = new CONSTANT_ConstantDynamic_info(cp2, info.bootstrap_method_attr_index, info.type_index);
+            }
+            translations.put(info, info2);
+        }
+        return info;
+    }
+
     public CPInfo visitLong(CONSTANT_Long_info info, Map<Object, Object> translations) {
         CONSTANT_Long_info info2 = (CONSTANT_Long_info) translations.get(info);
         if (info2 == null) {
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java	Fri Aug 26 14:19:48 2016 +0100
@@ -271,6 +271,12 @@
             return 1;
         }
 
+        public Integer visitConstantDynamic(CONSTANT_ConstantDynamic_info info, ClassOutputStream out) {
+            out.writeShort(info.bootstrap_method_attr_index);
+            out.writeShort(info.type_index);
+            return 1;
+        }
+
         public Integer visitLong(CONSTANT_Long_info info, ClassOutputStream out) {
             out.writeLong(info.value);
             return 2;
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPool.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPool.java	Fri Aug 26 14:19:48 2016 +0100
@@ -122,6 +122,7 @@
     public static final int CONSTANT_NameAndType = 12;
     public static final int CONSTANT_MethodHandle = 15;
     public static final int CONSTANT_MethodType = 16;
+    public static final int CONSTANT_ConstantDynamic = 17;
     public static final int CONSTANT_InvokeDynamic = 18;
     public static final int CONSTANT_TypeVar = 19;
     public static final int CONSTANT_ParameterizedType = 20;
@@ -208,6 +209,10 @@
                 pool[i] = new CONSTANT_InvokeDynamic_info(this, cr);
                 break;
 
+            case CONSTANT_ConstantDynamic:
+                pool[i] = new CONSTANT_ConstantDynamic_info(this, cr);
+                break;
+
             case CONSTANT_Long:
                 pool[i] = new CONSTANT_Long_info(cr);
                 i++;
@@ -365,6 +370,7 @@
         R visitFloat(CONSTANT_Float_info info, P p);
         R visitInteger(CONSTANT_Integer_info info, P p);
         R visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, P p);
+        R visitConstantDynamic(CONSTANT_ConstantDynamic_info info, P p);
         R visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, P p);
         R visitLong(CONSTANT_Long_info info, P p);
         R visitNameAndType(CONSTANT_NameAndType_info info, P p);
@@ -416,6 +422,11 @@
         }
 
         @Override
+        public R visitConstantDynamic(CONSTANT_ConstantDynamic_info info, P p) {
+            return visitEntry(info, p);
+        }
+
+        @Override
         public R visitLong(CONSTANT_Long_info info, P p) {
             return visitEntry(info, p);
         }
@@ -775,6 +786,44 @@
         public final int name_and_type_index;
     }
 
+    public static class CONSTANT_ConstantDynamic_info extends CPInfo {
+        CONSTANT_ConstantDynamic_info(ConstantPool cp, ClassReader cr) throws IOException {
+            super(cp);
+            bootstrap_method_attr_index = cr.readUnsignedShort();
+            type_index = cr.readUnsignedShort();
+        }
+
+        public CONSTANT_ConstantDynamic_info(ConstantPool cp, int bootstrap_method_index, int type_index) {
+            super(cp);
+            this.bootstrap_method_attr_index = bootstrap_method_index;
+            this.type_index = type_index;
+        }
+
+        public int getTag() {
+            return CONSTANT_ConstantDynamic;
+        }
+
+        public int byteLength() {
+            return 5;
+        }
+
+        @Override
+        public String toString() {
+            return "CONSTANT_ConstantDynamic_info[bootstrap_method_index: " + bootstrap_method_attr_index + ", name_and_type_index: " + type_index + "]";
+        }
+
+        public <R, D> R accept(Visitor<R, D> visitor, D data) {
+            return visitor.visitConstantDynamic(this, data);
+        }
+
+        public CONSTANT_Utf8_info getUtf8Info() throws ConstantPoolException {
+            return cp.getUTF8Info(type_index);
+        }
+
+        public final int bootstrap_method_attr_index;
+        public final int type_index;
+    }
+
     public static class CONSTANT_Long_info extends CPInfo {
         CONSTANT_Long_info(ClassReader cr) throws IOException {
             value = cr.readLong();
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java	Fri Aug 26 14:19:48 2016 +0100
@@ -709,6 +709,11 @@
                 return null;
             }
 
+            @Override
+            public Void visitConstantDynamic(CONSTANT_ConstantDynamic_info info, Void aVoid) {
+                return null;
+            }
+
             public Void visitLong(CONSTANT_Long_info info, Void p) {
                 return null;
             }
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java	Fri Aug 26 14:19:48 2016 +0100
@@ -164,6 +164,11 @@
             return false;
         }
 
+        @Override
+        public Boolean visitConstantDynamic(CONSTANT_ConstantDynamic_info info, ConstantPool constantPool) {
+            return false;
+        }
+
         public Boolean visitLong(CONSTANT_Long_info info, ConstantPool cpool) {
             return false;
         }
--- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java	Fri Aug 26 14:19:48 2016 +0100
@@ -108,6 +108,13 @@
                 return 1;
             }
 
+            public Integer visitConstantDynamic(CONSTANT_ConstantDynamic_info info, Void p) {
+                print("#" + info.bootstrap_method_attr_index + ":#" + info.type_index);
+                tab();
+                println("// " + stringValue(info));
+                return 1;
+            }
+
             public Integer visitLong(CONSTANT_Long_info info, Void p) {
                 println(stringValue(info));
                 return 2;
@@ -273,6 +280,8 @@
                 return "InterfaceMethod";
             case CONSTANT_InvokeDynamic:
                 return "InvokeDynamic";
+            case CONSTANT_ConstantDynamic:
+                return "ConstantDynamic";
             case CONSTANT_NameAndType:
                 return "NameAndType";
             case CONSTANT_TypeVar:
@@ -349,6 +358,15 @@
             }
         }
 
+        public String visitConstantDynamic(CONSTANT_ConstantDynamic_info info, Void p) {
+            try {
+                String callee = stringValue(info.getUtf8Info());
+                return "#" + info.bootstrap_method_attr_index + ":" + callee;
+            } catch (ConstantPoolException e) {
+                return report(e);
+            }
+        }
+
         public String visitLong(CONSTANT_Long_info info, Void p) {
             return info.value + "l";
         }
--- a/test/tools/javac/lambda/ByteCodeTest.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/test/tools/javac/lambda/ByteCodeTest.java	Fri Aug 26 14:19:48 2016 +0100
@@ -541,6 +541,22 @@
         }
 
         @Override
+        public String visitConstantDynamic(CONSTANT_ConstantDynamic_info c, Integer p) {
+
+            String value = slist.get(p);
+            if (value == null) {
+                try {
+                    value = bsmMap.get(c.bootstrap_method_attr_index) + " "
+                            + visit(cfpool.get(c.type_index), c.type_index);
+                    slist.set(p, value);
+                } catch (ConstantPoolException ex) {
+                    ex.printStackTrace();
+                }
+            }
+            return value;
+        }
+
+        @Override
         public String visitLong(CONSTANT_Long_info c, Integer p) {
 
             String value = slist.get(p);
--- a/test/tools/javac/lambda/TestBootstrapMethodsCount.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/test/tools/javac/lambda/TestBootstrapMethodsCount.java	Fri Aug 26 14:19:48 2016 +0100
@@ -57,7 +57,7 @@
 
 import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument;
+import com.sun.tools.javac.code.Dynamic.BootstrapArgument;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
 import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.code.Types;
--- a/test/tools/javac/lambda/TestInvokeDynamic.java	Fri Aug 26 16:54:32 2016 +0530
+++ b/test/tools/javac/lambda/TestInvokeDynamic.java	Fri Aug 26 14:19:48 2016 +0100
@@ -63,8 +63,8 @@
 
 import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument;
-import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument.Kind;
+import com.sun.tools.javac.code.Dynamic.BootstrapArgument;
+import com.sun.tools.javac.code.Dynamic.BootstrapArgument.Kind;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
 import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.code.Types;