8000518: Javac generates duplicate name_and_type constant pool entry for class BinaryOpValueExp.java
authorvromero
Sat, 15 Dec 2012 13:54:51 +0000
changeset 14949 45f43822bbde
parent 14948 6a2008d8e9ba
child 14950 c43973cca230
8000518: Javac generates duplicate name_and_type constant pool entry for class BinaryOpValueExp.java Reviewed-by: jjg, mcimadamore
langtools/src/share/classes/com/sun/tools/javac/code/Type.java
langtools/src/share/classes/com/sun/tools/javac/code/Types.java
langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
langtools/src/share/classes/com/sun/tools/javac/jvm/ClassFile.java
langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java
langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java
langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java
langtools/src/share/classes/com/sun/tools/javac/sym/CreateSymbols.java
langtools/test/tools/javac/8000518/DuplicateConstantPoolEntry.java
langtools/test/tools/javac/lambda/TestInvokeDynamic.java
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Fri Dec 14 11:16:46 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Sat Dec 15 13:54:51 2012 +0000
@@ -302,10 +302,12 @@
      * never complete classes. Where isSameType would complete a
      * class, equals assumes that the two types are different.
      */
+    @Override
     public boolean equals(Object t) {
         return super.equals(t);
     }
 
+    @Override
     public int hashCode() {
         return super.hashCode();
     }
@@ -996,34 +998,6 @@
             return "(" + argtypes + ")" + restype;
         }
 
-        public boolean equals(Object obj) {
-            if (this == obj)
-                return true;
-            if (!(obj instanceof MethodType))
-                return false;
-            MethodType m = (MethodType)obj;
-            List<Type> args1 = argtypes;
-            List<Type> args2 = m.argtypes;
-            while (!args1.isEmpty() && !args2.isEmpty()) {
-                if (!args1.head.equals(args2.head))
-                    return false;
-                args1 = args1.tail;
-                args2 = args2.tail;
-            }
-            if (!args1.isEmpty() || !args2.isEmpty())
-                return false;
-            return restype.equals(m.restype);
-        }
-
-        public int hashCode() {
-            int h = METHOD.ordinal();
-            for (List<Type> thisargs = this.argtypes;
-                 thisargs.tail != null; /*inlined: thisargs.nonEmpty()*/
-                 thisargs = thisargs.tail)
-                h = (h << 5) + thisargs.head.hashCode();
-            return (h << 5) + this.restype.hashCode();
-        }
-
         public List<Type>        getParameterTypes() { return argtypes; }
         public Type              getReturnType()     { return restype; }
         public List<Type>        getThrownTypes()    { return thrown; }
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Fri Dec 14 11:16:46 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Sat Dec 15 13:54:51 2012 +0000
@@ -1007,11 +1007,11 @@
                     if (!visit(supertype(t), supertype(s)))
                         return false;
 
-                    HashSet<SingletonType> set = new HashSet<SingletonType>();
+                    HashSet<UniqueType> set = new HashSet<UniqueType>();
                     for (Type x : interfaces(t))
-                        set.add(new SingletonType(x));
+                        set.add(new UniqueType(x, Types.this));
                     for (Type x : interfaces(s)) {
-                        if (!set.remove(new SingletonType(x)))
+                        if (!set.remove(new UniqueType(x, Types.this)))
                             return false;
                     }
                     return (set.isEmpty());
@@ -3137,7 +3137,7 @@
             }
             @Override
             public int hashCode() {
-                return 127 * Types.hashCode(t1) + Types.hashCode(t2);
+                return 127 * Types.this.hashCode(t1) + Types.this.hashCode(t2);
             }
             @Override
             public boolean equals(Object obj) {
@@ -3400,7 +3400,7 @@
     /**
      * Compute a hash code on a type.
      */
-    public static int hashCode(Type t) {
+    public int hashCode(Type t) {
         return hashCode.visit(t);
     }
     // where
@@ -3423,6 +3423,16 @@
             }
 
             @Override
+            public Integer visitMethodType(MethodType t, Void ignored) {
+                int h = METHOD.ordinal();
+                for (List<Type> thisargs = t.argtypes;
+                     thisargs.tail != null;
+                     thisargs = thisargs.tail)
+                    h = (h << 5) + visit(thisargs.head);
+                return (h << 5) + visit(t.restype);
+            }
+
+            @Override
             public Integer visitWildcardType(WildcardType t, Void ignored) {
                 int result = t.kind.hashCode();
                 if (t.type != null) {
@@ -4082,21 +4092,28 @@
     /**
      * A wrapper for a type that allows use in sets.
      */
-    class SingletonType {
-        final Type t;
-        SingletonType(Type t) {
-            this.t = t;
-        }
-        public int hashCode() {
-            return Types.hashCode(t);
+    public static class UniqueType {
+        public final Type type;
+        final Types types;
+
+        public UniqueType(Type type, Types types) {
+            this.type = type;
+            this.types = types;
         }
-        public boolean equals(Object obj) {
-            return (obj instanceof SingletonType) &&
-                isSameType(t, ((SingletonType)obj).t);
+
+        public int hashCode() {
+            return types.hashCode(type);
         }
+
+        public boolean equals(Object obj) {
+            return (obj instanceof UniqueType) &&
+                types.isSameType(type, ((UniqueType)obj).type);
+        }
+
         public String toString() {
-            return t.toString();
+            return type.toString();
         }
+
     }
     // </editor-fold>
 
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Dec 14 11:16:46 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Sat Dec 15 13:54:51 2012 +0000
@@ -692,8 +692,9 @@
         //determine the static bsm args
         Type mtype = makeFunctionalDescriptorType(targetType, true);
         List<Object> staticArgs = List.<Object>of(
-                new Pool.MethodHandle(ClassFile.REF_invokeInterface, types.findDescriptorSymbol(targetType.tsym)),
-                new Pool.MethodHandle(refKind, refSym),
+                new Pool.MethodHandle(ClassFile.REF_invokeInterface,
+                    types.findDescriptorSymbol(targetType.tsym), types),
+                new Pool.MethodHandle(refKind, refSym, types),
                 new MethodType(mtype.getParameterTypes(),
                         mtype.getReturnType(),
                         mtype.getThrownTypes(),
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Fri Dec 14 11:16:46 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Sat Dec 15 13:54:51 2012 +0000
@@ -26,6 +26,8 @@
 package com.sun.tools.javac.jvm;
 
 import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.code.Types.UniqueType;
 import com.sun.tools.javac.util.Name;
 
 
@@ -166,22 +168,29 @@
      */
     public static class NameAndType {
         Name name;
-        Type type;
+        UniqueType uniqueType;
+        Types types;
 
-        NameAndType(Name name, Type type) {
+        NameAndType(Name name, Type type, Types types) {
             this.name = name;
-            this.type = type;
+            this.uniqueType = new UniqueType(type, types);
+            this.types = types;
         }
 
-        public boolean equals(Object other) {
-            return
-                other instanceof NameAndType &&
-                name == ((NameAndType) other).name &&
-                type.equals(((NameAndType) other).type);
+        void setType(Type type) {
+            this.uniqueType = new UniqueType(type, types);
         }
 
+        @Override
+        public boolean equals(Object other) {
+            return (other instanceof NameAndType &&
+                    name == ((NameAndType) other).name &&
+                        uniqueType.equals(((NameAndType) other).uniqueType));
+        }
+
+        @Override
         public int hashCode() {
-            return name.hashCode() * type.hashCode();
+            return name.hashCode() * uniqueType.hashCode();
         }
     }
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri Dec 14 11:16:46 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Sat Dec 15 13:54:51 2012 +0000
@@ -488,20 +488,20 @@
         case CONSTANT_Fieldref: {
             ClassSymbol owner = readClassSymbol(getChar(index + 1));
             NameAndType nt = (NameAndType)readPool(getChar(index + 3));
-            poolObj[i] = new VarSymbol(0, nt.name, nt.type, owner);
+            poolObj[i] = new VarSymbol(0, nt.name, nt.uniqueType.type, owner);
             break;
         }
         case CONSTANT_Methodref:
         case CONSTANT_InterfaceMethodref: {
             ClassSymbol owner = readClassSymbol(getChar(index + 1));
             NameAndType nt = (NameAndType)readPool(getChar(index + 3));
-            poolObj[i] = new MethodSymbol(0, nt.name, nt.type, owner);
+            poolObj[i] = new MethodSymbol(0, nt.name, nt.uniqueType.type, owner);
             break;
         }
         case CONSTANT_NameandType:
             poolObj[i] = new NameAndType(
                 readName(getChar(index + 1)),
-                readType(getChar(index + 3)));
+                readType(getChar(index + 3)), types);
             break;
         case CONSTANT_Integer:
             poolObj[i] = getInt(index + 1);
@@ -1224,7 +1224,7 @@
         if (nt == null)
             return null;
 
-        MethodType type = nt.type.asMethodType();
+        MethodType type = nt.uniqueType.type.asMethodType();
 
         for (Scope.Entry e = scope.lookup(nt.name); e.scope != null; e = e.next())
             if (e.sym.kind == MTH && isSameBinaryType(e.sym.type.asMethodType(), type))
@@ -1236,16 +1236,16 @@
         if ((flags & INTERFACE) != 0)
             // no enclosing instance
             return null;
-        if (nt.type.getParameterTypes().isEmpty())
+        if (nt.uniqueType.type.getParameterTypes().isEmpty())
             // no parameters
             return null;
 
         // A constructor of an inner class.
         // Remove the first argument (the enclosing instance)
-        nt.type = new MethodType(nt.type.getParameterTypes().tail,
-                                 nt.type.getReturnType(),
-                                 nt.type.getThrownTypes(),
-                                 syms.methodClass);
+        nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail,
+                                 nt.uniqueType.type.getReturnType(),
+                                 nt.uniqueType.type.getThrownTypes(),
+                                 syms.methodClass));
         // Try searching again
         return findMethod(nt, scope, flags);
     }
@@ -1959,7 +1959,7 @@
 
         if (readAllOfClassFile) {
             for (int i = 1; i < poolObj.length; i++) readPool(i);
-            c.pool = new Pool(poolObj.length, poolObj);
+            c.pool = new Pool(poolObj.length, poolObj, types);
         }
 
         // reset and read rest of classinfo
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Fri Dec 14 11:16:46 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Sat Dec 15 13:54:51 2012 +0000
@@ -39,7 +39,12 @@
 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.code.Types.UniqueType;
 import com.sun.tools.javac.file.BaseFileObject;
+import com.sun.tools.javac.jvm.Pool.DynamicMethod;
+import com.sun.tools.javac.jvm.Pool.Method;
+import com.sun.tools.javac.jvm.Pool.MethodHandle;
+import com.sun.tools.javac.jvm.Pool.Variable;
 import com.sun.tools.javac.util.*;
 
 import static com.sun.tools.javac.code.BoundKind.*;
@@ -142,7 +147,7 @@
     /** The bootstrap methods to be written in the corresponding class attribute
      *  (one for each invokedynamic)
      */
-    Map<MethodSymbol, Pool.MethodHandle> bootstrapMethods;
+    Map<DynamicMethod, MethodHandle> bootstrapMethods;
 
     /** The log to use for verbose output.
      */
@@ -477,10 +482,10 @@
         while (i < pool.pp) {
             Object value = pool.pool[i];
             Assert.checkNonNull(value);
-            if (value instanceof Pool.Method)
-                value = ((Pool.Method)value).m;
-            else if (value instanceof Pool.Variable)
-                value = ((Pool.Variable)value).v;
+            if (value instanceof Method)
+                value = ((Method)value).m;
+            else if (value instanceof Variable)
+                value = ((Variable)value).v;
 
             if (value instanceof MethodSymbol) {
                 MethodSymbol m = (MethodSymbol)value;
@@ -493,8 +498,9 @@
                 } else {
                     //invokedynamic
                     DynamicMethodSymbol dynSym = (DynamicMethodSymbol)m;
-                    Pool.MethodHandle handle = new Pool.MethodHandle(dynSym.bsmKind, dynSym.bsm);
-                    bootstrapMethods.put(dynSym, handle);
+                    MethodHandle handle = new MethodHandle(dynSym.bsmKind, dynSym.bsm, types);
+                    DynamicMethod dynMeth = new DynamicMethod(dynSym, types);
+                    bootstrapMethods.put(dynMeth, handle);
                     //init cp entries
                     pool.put(names.BootstrapMethods);
                     pool.put(handle);
@@ -531,7 +537,7 @@
                 NameAndType nt = (NameAndType)value;
                 poolbuf.appendByte(CONSTANT_NameandType);
                 poolbuf.appendChar(pool.put(nt.name));
-                poolbuf.appendChar(pool.put(typeSig(nt.type)));
+                poolbuf.appendChar(pool.put(typeSig(nt.uniqueType.type)));
             } else if (value instanceof Integer) {
                 poolbuf.appendByte(CONSTANT_Integer);
                 poolbuf.appendInt(((Integer)value).intValue());
@@ -549,17 +555,18 @@
             } else if (value instanceof String) {
                 poolbuf.appendByte(CONSTANT_String);
                 poolbuf.appendChar(pool.put(names.fromString((String)value)));
-            } else if (value instanceof MethodType) {
-                MethodType mtype = (MethodType)value;
-                poolbuf.appendByte(CONSTANT_MethodType);
-                poolbuf.appendChar(pool.put(typeSig(mtype)));
-            } else if (value instanceof Type) {
-                Type type = (Type)value;
-                if (type.hasTag(CLASS)) enterInner((ClassSymbol)type.tsym);
-                poolbuf.appendByte(CONSTANT_Class);
-                poolbuf.appendChar(pool.put(xClassName(type)));
-            } else if (value instanceof Pool.MethodHandle) {
-                Pool.MethodHandle ref = (Pool.MethodHandle)value;
+            } else if (value instanceof UniqueType) {
+                Type type = ((UniqueType)value).type;
+                if (type instanceof MethodType) {
+                    poolbuf.appendByte(CONSTANT_MethodType);
+                    poolbuf.appendChar(pool.put(typeSig((MethodType)type)));
+                } else {
+                    if (type.hasTag(CLASS)) enterInner((ClassSymbol)type.tsym);
+                    poolbuf.appendByte(CONSTANT_Class);
+                    poolbuf.appendChar(pool.put(xClassName(type)));
+                }
+            } else if (value instanceof MethodHandle) {
+                MethodHandle ref = (MethodHandle)value;
                 poolbuf.appendByte(CONSTANT_MethodHandle);
                 poolbuf.appendByte(ref.refKind);
                 poolbuf.appendChar(pool.put(ref.refSym));
@@ -589,7 +596,7 @@
         return new NameAndType(fieldName(sym),
                                retrofit
                                ? sym.erasure(types)
-                               : sym.externalType(types));
+                               : sym.externalType(types), types);
         // if we retrofit, then the NameAndType has been read in as is
         // and no change is necessary. If we compile normally, the
         // NameAndType is generated from a symbol reference, and the
@@ -951,14 +958,16 @@
     void writeBootstrapMethods() {
         int alenIdx = writeAttr(names.BootstrapMethods);
         databuf.appendChar(bootstrapMethods.size());
-        for (Map.Entry<MethodSymbol, Pool.MethodHandle> entry : bootstrapMethods.entrySet()) {
-            DynamicMethodSymbol dsym = (DynamicMethodSymbol)entry.getKey();
+        for (Map.Entry<DynamicMethod, MethodHandle> entry : bootstrapMethods.entrySet()) {
+            DynamicMethod dmeth = entry.getKey();
+            DynamicMethodSymbol dsym = (DynamicMethodSymbol)dmeth.baseSymbol();
             //write BSM handle
             databuf.appendChar(pool.get(entry.getValue()));
             //write static args length
             databuf.appendChar(dsym.staticArgs.length);
             //write static args array
-            for (Object o : dsym.staticArgs) {
+            Object[] uniqueArgs = dmeth.uniqueStaticArgs;
+            for (Object o : uniqueArgs) {
                 databuf.appendChar(pool.get(o));
             }
         }
@@ -1534,7 +1543,7 @@
         pool = c.pool;
         innerClasses = null;
         innerClassesQueue = null;
-        bootstrapMethods = new LinkedHashMap<MethodSymbol, Pool.MethodHandle>();
+        bootstrapMethods = new LinkedHashMap<DynamicMethod, MethodHandle>();
 
         Type supertype = types.supertype(c.type);
         List<Type> interfaces = types.interfaces(c.type);
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java	Fri Dec 14 11:16:46 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java	Sat Dec 15 13:54:51 2012 +0000
@@ -27,6 +27,7 @@
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Types.UniqueType;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 
@@ -901,6 +902,7 @@
         if (o instanceof ClassSymbol) return syms.classType;
         if (o instanceof Type.ArrayType) return syms.classType;
         if (o instanceof Type.MethodType) return syms.methodTypeType;
+        if (o instanceof UniqueType) return typeForPool(((UniqueType)o).type);
         if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
         throw new AssertionError(o);
     }
@@ -1030,7 +1032,7 @@
             Object o = pool.pool[od];
             Type t = (o instanceof Symbol)
                 ? ((Symbol)o).erasure(types)
-                : types.erasure(((Type)o));
+                : types.erasure((((UniqueType)o).type));
             state.push(t);
             break; }
         case ldc2w:
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Fri Dec 14 11:16:46 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Sat Dec 15 13:54:51 2012 +0000
@@ -94,6 +94,10 @@
         return instance;
     }
 
+    /* Constant pool, reset by genClass.
+     */
+    private Pool pool;
+
     protected Gen(Context context) {
         context.put(genKey, this);
 
@@ -126,6 +130,7 @@
         genCrt = options.isSet(XJCOV);
         debugCode = options.isSet("debugcode");
         allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
+        pool = new Pool(types);
 
         generateIproxies =
             target.requiresIproxy() ||
@@ -174,10 +179,6 @@
      */
     private boolean useJsrLocally;
 
-    /* Constant pool, reset by genClass.
-     */
-    private Pool pool = new Pool();
-
     /** Code buffer, set by genMethod.
      */
     private Code code;
@@ -705,7 +706,7 @@
         }
         int startpc = code.curPc();
         genStat(tree, env);
-        if (tree.hasTag(BLOCK)) crtFlags |= CRT_BLOCK;
+        if (tree.hasTag(Tag.BLOCK)) crtFlags |= CRT_BLOCK;
         code.crt.put(tree, crtFlags, startpc, code.curPc());
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java	Fri Dec 14 11:16:46 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java	Sat Dec 15 13:54:51 2012 +0000
@@ -28,6 +28,9 @@
 import com.sun.tools.javac.code.Kinds;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.code.Types.UniqueType;
 
 import com.sun.tools.javac.util.ArrayUtils;
 import com.sun.tools.javac.util.Assert;
@@ -60,11 +63,14 @@
      */
     Map<Object,Integer> indices;
 
+    Types types;
+
     /** Construct a pool with given number of elements and element array.
      */
-    public Pool(int pp, Object[] pool) {
+    public Pool(int pp, Object[] pool, Types types) {
         this.pp = pp;
         this.pool = pool;
+        this.types = types;
         this.indices = new HashMap<Object,Integer>(pool.length);
         for (int i = 1; i < pp; i++) {
             if (pool[i] != null) indices.put(pool[i], i);
@@ -73,8 +79,8 @@
 
     /** Construct an empty pool.
      */
-    public Pool() {
-        this(1, new Object[64]);
+    public Pool(Types types) {
+        this(1, new Object[64], types);
     }
 
     /** Return the number of entries in the constant pool.
@@ -114,11 +120,13 @@
 
     Object makePoolValue(Object o) {
         if (o instanceof DynamicMethodSymbol) {
-            return new DynamicMethod((DynamicMethodSymbol)o);
+            return new DynamicMethod((DynamicMethodSymbol)o, types);
         } else if (o instanceof MethodSymbol) {
-            return new Method((MethodSymbol)o);
+            return new Method((MethodSymbol)o, types);
         } else if (o instanceof VarSymbol) {
-            return new Variable((VarSymbol)o);
+            return new Variable((VarSymbol)o, types);
+        } else if (o instanceof Type) {
+            return new UniqueType((Type)o, types);
         } else {
             return o;
         }
@@ -134,9 +142,11 @@
 
     static class Method extends DelegatedSymbol {
         MethodSymbol m;
-        Method(MethodSymbol m) {
+        UniqueType uniqueType;
+        Method(MethodSymbol m, Types types) {
             super(m);
             this.m = m;
+            this.uniqueType = new UniqueType(m.type, types);
         }
         public boolean equals(Object other) {
             if (!(other instanceof Method)) return false;
@@ -144,20 +154,22 @@
             return
                 o.name == m.name &&
                 o.owner == m.owner &&
-                o.type.equals(m.type);
+                ((Method)other).uniqueType.equals(uniqueType);
         }
         public int hashCode() {
             return
                 m.name.hashCode() * 33 +
                 m.owner.hashCode() * 9 +
-                m.type.hashCode();
+                uniqueType.hashCode();
         }
     }
 
     static class DynamicMethod extends Method {
+        public Object[] uniqueStaticArgs;
 
-        DynamicMethod(DynamicMethodSymbol m) {
-            super(m);
+        DynamicMethod(DynamicMethodSymbol m, Types types) {
+            super(m, types);
+            uniqueStaticArgs = getUniqueTypeArray(m.staticArgs, types);
         }
 
         @Override
@@ -168,7 +180,8 @@
             DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)other).m;
             return dm1.bsm == dm2.bsm &&
                         dm1.bsmKind == dm2.bsmKind &&
-                        Arrays.equals(dm1.staticArgs, dm2.staticArgs);
+                        Arrays.equals(uniqueStaticArgs,
+                            ((DynamicMethod)other).uniqueStaticArgs);
         }
 
         @Override
@@ -178,17 +191,31 @@
             hash += dm.bsmKind * 7 +
                     dm.bsm.hashCode() * 11;
             for (int i = 0; i < dm.staticArgs.length; i++) {
-                hash += (dm.staticArgs[i].hashCode() * 23);
+                hash += (uniqueStaticArgs[i].hashCode() * 23);
             }
             return hash;
         }
+
+        private Object[] getUniqueTypeArray(Object[] objects, Types types) {
+            Object[] result = new Object[objects.length];
+            for (int i = 0; i < objects.length; i++) {
+                if (objects[i] instanceof Type) {
+                    result[i] = new UniqueType((Type)objects[i], types);
+                } else {
+                    result[i] = objects[i];
+                }
+            }
+            return result;
+        }
     }
 
     static class Variable extends DelegatedSymbol {
         VarSymbol v;
-        Variable(VarSymbol v) {
+        UniqueType uniqueType;
+        Variable(VarSymbol v, Types types) {
             super(v);
             this.v = v;
+            this.uniqueType = new UniqueType(v.type, types);
         }
         public boolean equals(Object other) {
             if (!(other instanceof Variable)) return false;
@@ -196,13 +223,13 @@
             return
                 o.name == v.name &&
                 o.owner == v.owner &&
-                o.type.equals(v.type);
+                ((Variable)other).uniqueType.equals(uniqueType);
         }
         public int hashCode() {
             return
                 v.name.hashCode() * 33 +
                 v.owner.hashCode() * 9 +
-                v.type.hashCode();
+                uniqueType.hashCode();
         }
     }
 
@@ -214,9 +241,12 @@
         /** Reference symbol */
         Symbol refSym;
 
-        public MethodHandle(int refKind, Symbol refSym) {
+        UniqueType uniqueType;
+
+        public MethodHandle(int refKind, Symbol refSym, Types types) {
             this.refKind = refKind;
             this.refSym = refSym;
+            this.uniqueType = new UniqueType(this.refSym.type, types);
             checkConsistent();
         }
         public boolean equals(Object other) {
@@ -227,14 +257,14 @@
             return
                 o.name == refSym.name &&
                 o.owner == refSym.owner &&
-                o.type.equals(refSym.type);
+                ((MethodHandle)other).uniqueType.equals(uniqueType);
         }
         public int hashCode() {
             return
                 refKind * 65 +
                 refSym.name.hashCode() * 33 +
                 refSym.owner.hashCode() * 9 +
-                refSym.type.hashCode();
+                uniqueType.hashCode();
         }
 
         /**
--- a/langtools/src/share/classes/com/sun/tools/javac/sym/CreateSymbols.java	Fri Dec 14 11:16:46 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/sym/CreateSymbols.java	Sat Dec 15 13:54:51 2012 +0000
@@ -33,6 +33,7 @@
 import com.sun.tools.javac.code.Attribute;
 import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Types;
 import com.sun.tools.javac.jvm.ClassReader;
 import com.sun.tools.javac.jvm.ClassWriter;
 import com.sun.tools.javac.jvm.Pool;
@@ -173,7 +174,8 @@
                                    List.<Pair<Symbol.MethodSymbol,Attribute>>nil());
 
         Type.moreInfo = true;
-        Pool pool = new Pool();
+        Types types = Types.instance(task.getContext());
+        Pool pool = new Pool(types);
         for (JavaFileObject file : fm.list(jarLocation, "", EnumSet.of(CLASS), true)) {
             String className = fm.inferBinaryName(jarLocation, file);
             int index = className.lastIndexOf('.');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8000518/DuplicateConstantPoolEntry.java	Sat Dec 15 13:54:51 2012 +0000
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2002, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8000518
+ * @summary Javac generates duplicate name_and_type constant pool entry for
+ * class BinaryOpValueExp.java
+ * @run main DuplicateConstantPoolEntry
+ */
+
+import com.sun.source.util.JavacTask;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPoolException;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+
+/*
+ * This bug was reproduced having two classes B and C referenced from a class A
+ * class C should be compiled and generated in advance. Later class A and B should
+ * be compiled like this: javac A.java B.java
+ */
+
+public class DuplicateConstantPoolEntry {
+
+    public static void main(String args[]) throws Exception {
+        new DuplicateConstantPoolEntry().run();
+    }
+
+    void run() throws Exception {
+        generateFilesNeeded();
+        checkReference();
+    }
+
+    void generateFilesNeeded() throws Exception {
+
+        StringJavaFileObject[] CSource = new StringJavaFileObject[] {
+            new StringJavaFileObject("C.java",
+                "class C {C(String s) {}}"),
+        };
+
+        List<StringJavaFileObject> AandBSource = Arrays.asList(
+                new StringJavaFileObject("A.java",
+                    "class A {void test() {new B(null);new C(null);}}"),
+                new StringJavaFileObject("B.java",
+                    "class B {B(String s) {}}")
+        );
+
+        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+        JavacTask compileC = (JavacTask)tool.getTask(null, null, null, null, null,
+                Arrays.asList(CSource));
+        if (!compileC.call()) {
+            throw new AssertionError("Compilation error while compiling C.java sources");
+        }
+        JavacTask compileAB = (JavacTask)tool.getTask(null, null, null,
+                Arrays.asList("-cp", "."), null, AandBSource);
+        if (!compileAB.call()) {
+            throw new AssertionError("Compilation error while compiling A and B sources");
+        }
+    }
+
+    void checkReference() throws IOException, ConstantPoolException {
+        File file = new File("A.class");
+        ClassFile classFile = ClassFile.read(file);
+        for (int i = 1;
+                i < classFile.constant_pool.size() - 1;
+                i += classFile.constant_pool.get(i).size()) {
+            for (int j = i + classFile.constant_pool.get(i).size();
+                    j < classFile.constant_pool.size();
+                    j += classFile.constant_pool.get(j).size()) {
+                if (classFile.constant_pool.get(i).toString().
+                        equals(classFile.constant_pool.get(j).toString())) {
+                    throw new AssertionError(
+                            "Duplicate entries in the constant pool at positions " +
+                            i + " and " + j);
+                }
+            }
+        }
+    }
+
+    private static class StringJavaFileObject extends SimpleJavaFileObject {
+        StringJavaFileObject(String name, String text) {
+            super(URI.create(name), JavaFileObject.Kind.SOURCE);
+            this.text = text;
+        }
+        @Override
+        public CharSequence getCharContent(boolean b) {
+            return text;
+        }
+        private String text;
+    }
+}
--- a/langtools/test/tools/javac/lambda/TestInvokeDynamic.java	Fri Dec 14 11:16:46 2012 +0000
+++ b/langtools/test/tools/javac/lambda/TestInvokeDynamic.java	Sat Dec 15 13:54:51 2012 +0000
@@ -50,6 +50,7 @@
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
 import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Types;
 import com.sun.tools.javac.jvm.Pool;
 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
@@ -151,7 +152,7 @@
 
         abstract boolean check(CPInfo cpInfo) throws Exception;
 
-        Object getValue(Symtab syms, Names names) {
+        Object getValue(Symtab syms, Names names, Types types) {
             switch (this) {
                 case STRING:
                 case INTEGER:
@@ -162,7 +163,7 @@
                 case CLASS:
                     return syms.stringType.tsym;
                 case METHOD_HANDLE:
-                    return new Pool.MethodHandle(REF_invokeVirtual, syms.arrayCloneMethod);
+                    return new Pool.MethodHandle(REF_invokeVirtual, syms.arrayCloneMethod, types);
                 case METHOD_TYPE:
                     return syms.arrayCloneMethod.type;
                 default:
@@ -231,7 +232,8 @@
         Context context = ct.getContext();
         Symtab syms = Symtab.instance(context);
         Names names = Names.instance(context);
-        ct.addTaskListener(new Indifier(syms, names));
+        Types types = Types.instance(context);
+        ct.addTaskListener(new Indifier(syms, names, types));
         try {
             ct.generate();
         } catch (Throwable t) {
@@ -378,10 +380,12 @@
         MethodSymbol bsm;
         Symtab syms;
         Names names;
+        Types types;
 
-        Indifier(Symtab syms, Names names) {
+        Indifier(Symtab syms, Names names, Types types) {
             this.syms = syms;
             this.names = names;
+            this.types = types;
         }
 
         @Override
@@ -405,7 +409,7 @@
             if (!oldSym.isConstructor()) {
                 Object[] staticArgs = new Object[arity.arity];
                 for (int i = 0; i < arity.arity ; i++) {
-                    staticArgs[i] = saks[i].getValue(syms, names);
+                    staticArgs[i] = saks[i].getValue(syms, names, types);
                 }
                 ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name, oldSym.owner, REF_invokeStatic, bsm, oldSym.type, staticArgs);
             }