提交 2db8a51f 编写于 作者: V vromero

8000518: Javac generates duplicate name_and_type constant pool entry for class...

8000518: Javac generates duplicate name_and_type constant pool entry for class BinaryOpValueExp.java
Reviewed-by: jjg, mcimadamore
上级 f5e6ab65
...@@ -302,10 +302,12 @@ public class Type implements PrimitiveType { ...@@ -302,10 +302,12 @@ public class Type implements PrimitiveType {
* never complete classes. Where isSameType would complete a * never complete classes. Where isSameType would complete a
* class, equals assumes that the two types are different. * class, equals assumes that the two types are different.
*/ */
@Override
public boolean equals(Object t) { public boolean equals(Object t) {
return super.equals(t); return super.equals(t);
} }
@Override
public int hashCode() { public int hashCode() {
return super.hashCode(); return super.hashCode();
} }
...@@ -996,34 +998,6 @@ public class Type implements PrimitiveType { ...@@ -996,34 +998,6 @@ public class Type implements PrimitiveType {
return "(" + argtypes + ")" + restype; 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 List<Type> getParameterTypes() { return argtypes; }
public Type getReturnType() { return restype; } public Type getReturnType() { return restype; }
public List<Type> getThrownTypes() { return thrown; } public List<Type> getThrownTypes() { return thrown; }
......
...@@ -1007,11 +1007,11 @@ public class Types { ...@@ -1007,11 +1007,11 @@ public class Types {
if (!visit(supertype(t), supertype(s))) if (!visit(supertype(t), supertype(s)))
return false; return false;
HashSet<SingletonType> set = new HashSet<SingletonType>(); HashSet<UniqueType> set = new HashSet<UniqueType>();
for (Type x : interfaces(t)) for (Type x : interfaces(t))
set.add(new SingletonType(x)); set.add(new UniqueType(x, Types.this));
for (Type x : interfaces(s)) { for (Type x : interfaces(s)) {
if (!set.remove(new SingletonType(x))) if (!set.remove(new UniqueType(x, Types.this)))
return false; return false;
} }
return (set.isEmpty()); return (set.isEmpty());
...@@ -3137,7 +3137,7 @@ public class Types { ...@@ -3137,7 +3137,7 @@ public class Types {
} }
@Override @Override
public int hashCode() { public int hashCode() {
return 127 * Types.hashCode(t1) + Types.hashCode(t2); return 127 * Types.this.hashCode(t1) + Types.this.hashCode(t2);
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
...@@ -3400,7 +3400,7 @@ public class Types { ...@@ -3400,7 +3400,7 @@ public class Types {
/** /**
* Compute a hash code on a type. * Compute a hash code on a type.
*/ */
public static int hashCode(Type t) { public int hashCode(Type t) {
return hashCode.visit(t); return hashCode.visit(t);
} }
// where // where
...@@ -3422,6 +3422,16 @@ public class Types { ...@@ -3422,6 +3422,16 @@ public class Types {
return result; return result;
} }
@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 @Override
public Integer visitWildcardType(WildcardType t, Void ignored) { public Integer visitWildcardType(WildcardType t, Void ignored) {
int result = t.kind.hashCode(); int result = t.kind.hashCode();
...@@ -4082,21 +4092,28 @@ public class Types { ...@@ -4082,21 +4092,28 @@ public class Types {
/** /**
* A wrapper for a type that allows use in sets. * A wrapper for a type that allows use in sets.
*/ */
class SingletonType { public static class UniqueType {
final Type t; public final Type type;
SingletonType(Type t) { final Types types;
this.t = t;
public UniqueType(Type type, Types types) {
this.type = type;
this.types = types;
} }
public int hashCode() { public int hashCode() {
return Types.hashCode(t); return types.hashCode(type);
} }
public boolean equals(Object obj) { public boolean equals(Object obj) {
return (obj instanceof SingletonType) && return (obj instanceof UniqueType) &&
isSameType(t, ((SingletonType)obj).t); types.isSameType(type, ((UniqueType)obj).type);
} }
public String toString() { public String toString() {
return t.toString(); return type.toString();
} }
} }
// </editor-fold> // </editor-fold>
......
...@@ -692,8 +692,9 @@ public class LambdaToMethod extends TreeTranslator { ...@@ -692,8 +692,9 @@ public class LambdaToMethod extends TreeTranslator {
//determine the static bsm args //determine the static bsm args
Type mtype = makeFunctionalDescriptorType(targetType, true); Type mtype = makeFunctionalDescriptorType(targetType, true);
List<Object> staticArgs = List.<Object>of( List<Object> staticArgs = List.<Object>of(
new Pool.MethodHandle(ClassFile.REF_invokeInterface, types.findDescriptorSymbol(targetType.tsym)), new Pool.MethodHandle(ClassFile.REF_invokeInterface,
new Pool.MethodHandle(refKind, refSym), types.findDescriptorSymbol(targetType.tsym), types),
new Pool.MethodHandle(refKind, refSym, types),
new MethodType(mtype.getParameterTypes(), new MethodType(mtype.getParameterTypes(),
mtype.getReturnType(), mtype.getReturnType(),
mtype.getThrownTypes(), mtype.getThrownTypes(),
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
package com.sun.tools.javac.jvm; package com.sun.tools.javac.jvm;
import com.sun.tools.javac.code.Type; 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; import com.sun.tools.javac.util.Name;
...@@ -166,22 +168,29 @@ public class ClassFile { ...@@ -166,22 +168,29 @@ public class ClassFile {
*/ */
public static class NameAndType { public static class NameAndType {
Name name; Name name;
Type type; UniqueType uniqueType;
Types types;
NameAndType(Name name, Type type) { NameAndType(Name name, Type type, Types types) {
this.name = name; this.name = name;
this.type = type; this.uniqueType = new UniqueType(type, types);
this.types = types;
} }
void setType(Type type) {
this.uniqueType = new UniqueType(type, types);
}
@Override
public boolean equals(Object other) { public boolean equals(Object other) {
return return (other instanceof NameAndType &&
other instanceof NameAndType && name == ((NameAndType) other).name &&
name == ((NameAndType) other).name && uniqueType.equals(((NameAndType) other).uniqueType));
type.equals(((NameAndType) other).type);
} }
@Override
public int hashCode() { public int hashCode() {
return name.hashCode() * type.hashCode(); return name.hashCode() * uniqueType.hashCode();
} }
} }
} }
...@@ -488,20 +488,20 @@ public class ClassReader implements Completer { ...@@ -488,20 +488,20 @@ public class ClassReader implements Completer {
case CONSTANT_Fieldref: { case CONSTANT_Fieldref: {
ClassSymbol owner = readClassSymbol(getChar(index + 1)); ClassSymbol owner = readClassSymbol(getChar(index + 1));
NameAndType nt = (NameAndType)readPool(getChar(index + 3)); 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; break;
} }
case CONSTANT_Methodref: case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref: { case CONSTANT_InterfaceMethodref: {
ClassSymbol owner = readClassSymbol(getChar(index + 1)); ClassSymbol owner = readClassSymbol(getChar(index + 1));
NameAndType nt = (NameAndType)readPool(getChar(index + 3)); 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; break;
} }
case CONSTANT_NameandType: case CONSTANT_NameandType:
poolObj[i] = new NameAndType( poolObj[i] = new NameAndType(
readName(getChar(index + 1)), readName(getChar(index + 1)),
readType(getChar(index + 3))); readType(getChar(index + 3)), types);
break; break;
case CONSTANT_Integer: case CONSTANT_Integer:
poolObj[i] = getInt(index + 1); poolObj[i] = getInt(index + 1);
...@@ -1224,7 +1224,7 @@ public class ClassReader implements Completer { ...@@ -1224,7 +1224,7 @@ public class ClassReader implements Completer {
if (nt == null) if (nt == null)
return 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()) 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)) if (e.sym.kind == MTH && isSameBinaryType(e.sym.type.asMethodType(), type))
...@@ -1236,16 +1236,16 @@ public class ClassReader implements Completer { ...@@ -1236,16 +1236,16 @@ public class ClassReader implements Completer {
if ((flags & INTERFACE) != 0) if ((flags & INTERFACE) != 0)
// no enclosing instance // no enclosing instance
return null; return null;
if (nt.type.getParameterTypes().isEmpty()) if (nt.uniqueType.type.getParameterTypes().isEmpty())
// no parameters // no parameters
return null; return null;
// A constructor of an inner class. // A constructor of an inner class.
// Remove the first argument (the enclosing instance) // Remove the first argument (the enclosing instance)
nt.type = new MethodType(nt.type.getParameterTypes().tail, nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail,
nt.type.getReturnType(), nt.uniqueType.type.getReturnType(),
nt.type.getThrownTypes(), nt.uniqueType.type.getThrownTypes(),
syms.methodClass); syms.methodClass));
// Try searching again // Try searching again
return findMethod(nt, scope, flags); return findMethod(nt, scope, flags);
} }
...@@ -1959,7 +1959,7 @@ public class ClassReader implements Completer { ...@@ -1959,7 +1959,7 @@ public class ClassReader implements Completer {
if (readAllOfClassFile) { if (readAllOfClassFile) {
for (int i = 1; i < poolObj.length; i++) readPool(i); 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 // reset and read rest of classinfo
......
...@@ -39,7 +39,12 @@ import com.sun.tools.javac.code.*; ...@@ -39,7 +39,12 @@ import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Attribute.RetentionPolicy; import com.sun.tools.javac.code.Attribute.RetentionPolicy;
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.Type.*;
import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.file.BaseFileObject; 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 com.sun.tools.javac.util.*;
import static com.sun.tools.javac.code.BoundKind.*; import static com.sun.tools.javac.code.BoundKind.*;
...@@ -142,7 +147,7 @@ public class ClassWriter extends ClassFile { ...@@ -142,7 +147,7 @@ public class ClassWriter extends ClassFile {
/** The bootstrap methods to be written in the corresponding class attribute /** The bootstrap methods to be written in the corresponding class attribute
* (one for each invokedynamic) * (one for each invokedynamic)
*/ */
Map<MethodSymbol, Pool.MethodHandle> bootstrapMethods; Map<DynamicMethod, MethodHandle> bootstrapMethods;
/** The log to use for verbose output. /** The log to use for verbose output.
*/ */
...@@ -477,10 +482,10 @@ public class ClassWriter extends ClassFile { ...@@ -477,10 +482,10 @@ public class ClassWriter extends ClassFile {
while (i < pool.pp) { while (i < pool.pp) {
Object value = pool.pool[i]; Object value = pool.pool[i];
Assert.checkNonNull(value); Assert.checkNonNull(value);
if (value instanceof Pool.Method) if (value instanceof Method)
value = ((Pool.Method)value).m; value = ((Method)value).m;
else if (value instanceof Pool.Variable) else if (value instanceof Variable)
value = ((Pool.Variable)value).v; value = ((Variable)value).v;
if (value instanceof MethodSymbol) { if (value instanceof MethodSymbol) {
MethodSymbol m = (MethodSymbol)value; MethodSymbol m = (MethodSymbol)value;
...@@ -493,8 +498,9 @@ public class ClassWriter extends ClassFile { ...@@ -493,8 +498,9 @@ public class ClassWriter extends ClassFile {
} else { } else {
//invokedynamic //invokedynamic
DynamicMethodSymbol dynSym = (DynamicMethodSymbol)m; DynamicMethodSymbol dynSym = (DynamicMethodSymbol)m;
Pool.MethodHandle handle = new Pool.MethodHandle(dynSym.bsmKind, dynSym.bsm); MethodHandle handle = new MethodHandle(dynSym.bsmKind, dynSym.bsm, types);
bootstrapMethods.put(dynSym, handle); DynamicMethod dynMeth = new DynamicMethod(dynSym, types);
bootstrapMethods.put(dynMeth, handle);
//init cp entries //init cp entries
pool.put(names.BootstrapMethods); pool.put(names.BootstrapMethods);
pool.put(handle); pool.put(handle);
...@@ -531,7 +537,7 @@ public class ClassWriter extends ClassFile { ...@@ -531,7 +537,7 @@ public class ClassWriter extends ClassFile {
NameAndType nt = (NameAndType)value; NameAndType nt = (NameAndType)value;
poolbuf.appendByte(CONSTANT_NameandType); poolbuf.appendByte(CONSTANT_NameandType);
poolbuf.appendChar(pool.put(nt.name)); 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) { } else if (value instanceof Integer) {
poolbuf.appendByte(CONSTANT_Integer); poolbuf.appendByte(CONSTANT_Integer);
poolbuf.appendInt(((Integer)value).intValue()); poolbuf.appendInt(((Integer)value).intValue());
...@@ -549,17 +555,18 @@ public class ClassWriter extends ClassFile { ...@@ -549,17 +555,18 @@ public class ClassWriter extends ClassFile {
} else if (value instanceof String) { } else if (value instanceof String) {
poolbuf.appendByte(CONSTANT_String); poolbuf.appendByte(CONSTANT_String);
poolbuf.appendChar(pool.put(names.fromString((String)value))); poolbuf.appendChar(pool.put(names.fromString((String)value)));
} else if (value instanceof MethodType) { } else if (value instanceof UniqueType) {
MethodType mtype = (MethodType)value; Type type = ((UniqueType)value).type;
poolbuf.appendByte(CONSTANT_MethodType); if (type instanceof MethodType) {
poolbuf.appendChar(pool.put(typeSig(mtype))); poolbuf.appendByte(CONSTANT_MethodType);
} else if (value instanceof Type) { poolbuf.appendChar(pool.put(typeSig((MethodType)type)));
Type type = (Type)value; } else {
if (type.hasTag(CLASS)) enterInner((ClassSymbol)type.tsym); if (type.hasTag(CLASS)) enterInner((ClassSymbol)type.tsym);
poolbuf.appendByte(CONSTANT_Class); poolbuf.appendByte(CONSTANT_Class);
poolbuf.appendChar(pool.put(xClassName(type))); poolbuf.appendChar(pool.put(xClassName(type)));
} else if (value instanceof Pool.MethodHandle) { }
Pool.MethodHandle ref = (Pool.MethodHandle)value; } else if (value instanceof MethodHandle) {
MethodHandle ref = (MethodHandle)value;
poolbuf.appendByte(CONSTANT_MethodHandle); poolbuf.appendByte(CONSTANT_MethodHandle);
poolbuf.appendByte(ref.refKind); poolbuf.appendByte(ref.refKind);
poolbuf.appendChar(pool.put(ref.refSym)); poolbuf.appendChar(pool.put(ref.refSym));
...@@ -589,7 +596,7 @@ public class ClassWriter extends ClassFile { ...@@ -589,7 +596,7 @@ public class ClassWriter extends ClassFile {
return new NameAndType(fieldName(sym), return new NameAndType(fieldName(sym),
retrofit retrofit
? sym.erasure(types) ? sym.erasure(types)
: sym.externalType(types)); : sym.externalType(types), types);
// if we retrofit, then the NameAndType has been read in as is // if we retrofit, then the NameAndType has been read in as is
// and no change is necessary. If we compile normally, the // and no change is necessary. If we compile normally, the
// NameAndType is generated from a symbol reference, and the // NameAndType is generated from a symbol reference, and the
...@@ -951,14 +958,16 @@ public class ClassWriter extends ClassFile { ...@@ -951,14 +958,16 @@ public class ClassWriter extends ClassFile {
void writeBootstrapMethods() { void writeBootstrapMethods() {
int alenIdx = writeAttr(names.BootstrapMethods); int alenIdx = writeAttr(names.BootstrapMethods);
databuf.appendChar(bootstrapMethods.size()); databuf.appendChar(bootstrapMethods.size());
for (Map.Entry<MethodSymbol, Pool.MethodHandle> entry : bootstrapMethods.entrySet()) { for (Map.Entry<DynamicMethod, MethodHandle> entry : bootstrapMethods.entrySet()) {
DynamicMethodSymbol dsym = (DynamicMethodSymbol)entry.getKey(); DynamicMethod dmeth = entry.getKey();
DynamicMethodSymbol dsym = (DynamicMethodSymbol)dmeth.baseSymbol();
//write BSM handle //write BSM handle
databuf.appendChar(pool.get(entry.getValue())); databuf.appendChar(pool.get(entry.getValue()));
//write static args length //write static args length
databuf.appendChar(dsym.staticArgs.length); databuf.appendChar(dsym.staticArgs.length);
//write static args array //write static args array
for (Object o : dsym.staticArgs) { Object[] uniqueArgs = dmeth.uniqueStaticArgs;
for (Object o : uniqueArgs) {
databuf.appendChar(pool.get(o)); databuf.appendChar(pool.get(o));
} }
} }
...@@ -1534,7 +1543,7 @@ public class ClassWriter extends ClassFile { ...@@ -1534,7 +1543,7 @@ public class ClassWriter extends ClassFile {
pool = c.pool; pool = c.pool;
innerClasses = null; innerClasses = null;
innerClassesQueue = null; innerClassesQueue = null;
bootstrapMethods = new LinkedHashMap<MethodSymbol, Pool.MethodHandle>(); bootstrapMethods = new LinkedHashMap<DynamicMethod, MethodHandle>();
Type supertype = types.supertype(c.type); Type supertype = types.supertype(c.type);
List<Type> interfaces = types.interfaces(c.type); List<Type> interfaces = types.interfaces(c.type);
......
...@@ -27,6 +27,7 @@ package com.sun.tools.javac.jvm; ...@@ -27,6 +27,7 @@ package com.sun.tools.javac.jvm;
import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*; 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.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
...@@ -901,6 +902,7 @@ public class Code { ...@@ -901,6 +902,7 @@ public class Code {
if (o instanceof ClassSymbol) return syms.classType; if (o instanceof ClassSymbol) return syms.classType;
if (o instanceof Type.ArrayType) return syms.classType; if (o instanceof Type.ArrayType) return syms.classType;
if (o instanceof Type.MethodType) return syms.methodTypeType; 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; if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
throw new AssertionError(o); throw new AssertionError(o);
} }
...@@ -1030,7 +1032,7 @@ public class Code { ...@@ -1030,7 +1032,7 @@ public class Code {
Object o = pool.pool[od]; Object o = pool.pool[od];
Type t = (o instanceof Symbol) Type t = (o instanceof Symbol)
? ((Symbol)o).erasure(types) ? ((Symbol)o).erasure(types)
: types.erasure(((Type)o)); : types.erasure((((UniqueType)o).type));
state.push(t); state.push(t);
break; } break; }
case ldc2w: case ldc2w:
......
...@@ -94,6 +94,10 @@ public class Gen extends JCTree.Visitor { ...@@ -94,6 +94,10 @@ public class Gen extends JCTree.Visitor {
return instance; return instance;
} }
/* Constant pool, reset by genClass.
*/
private Pool pool;
protected Gen(Context context) { protected Gen(Context context) {
context.put(genKey, this); context.put(genKey, this);
...@@ -126,6 +130,7 @@ public class Gen extends JCTree.Visitor { ...@@ -126,6 +130,7 @@ public class Gen extends JCTree.Visitor {
genCrt = options.isSet(XJCOV); genCrt = options.isSet(XJCOV);
debugCode = options.isSet("debugcode"); debugCode = options.isSet("debugcode");
allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic"); allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
pool = new Pool(types);
generateIproxies = generateIproxies =
target.requiresIproxy() || target.requiresIproxy() ||
...@@ -174,10 +179,6 @@ public class Gen extends JCTree.Visitor { ...@@ -174,10 +179,6 @@ public class Gen extends JCTree.Visitor {
*/ */
private boolean useJsrLocally; private boolean useJsrLocally;
/* Constant pool, reset by genClass.
*/
private Pool pool = new Pool();
/** Code buffer, set by genMethod. /** Code buffer, set by genMethod.
*/ */
private Code code; private Code code;
...@@ -705,7 +706,7 @@ public class Gen extends JCTree.Visitor { ...@@ -705,7 +706,7 @@ public class Gen extends JCTree.Visitor {
} }
int startpc = code.curPc(); int startpc = code.curPc();
genStat(tree, env); 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()); code.crt.put(tree, crtFlags, startpc, code.curPc());
} }
......
...@@ -28,6 +28,9 @@ package com.sun.tools.javac.jvm; ...@@ -28,6 +28,9 @@ package com.sun.tools.javac.jvm;
import com.sun.tools.javac.code.Kinds; 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.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.ArrayUtils;
import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.Assert;
...@@ -60,11 +63,14 @@ public class Pool { ...@@ -60,11 +63,14 @@ public class Pool {
*/ */
Map<Object,Integer> indices; Map<Object,Integer> indices;
Types types;
/** Construct a pool with given number of elements and element array. /** 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.pp = pp;
this.pool = pool; this.pool = pool;
this.types = types;
this.indices = new HashMap<Object,Integer>(pool.length); this.indices = new HashMap<Object,Integer>(pool.length);
for (int i = 1; i < pp; i++) { for (int i = 1; i < pp; i++) {
if (pool[i] != null) indices.put(pool[i], i); if (pool[i] != null) indices.put(pool[i], i);
...@@ -73,8 +79,8 @@ public class Pool { ...@@ -73,8 +79,8 @@ public class Pool {
/** Construct an empty pool. /** Construct an empty pool.
*/ */
public Pool() { public Pool(Types types) {
this(1, new Object[64]); this(1, new Object[64], types);
} }
/** Return the number of entries in the constant pool. /** Return the number of entries in the constant pool.
...@@ -114,11 +120,13 @@ public class Pool { ...@@ -114,11 +120,13 @@ public class Pool {
Object makePoolValue(Object o) { Object makePoolValue(Object o) {
if (o instanceof DynamicMethodSymbol) { if (o instanceof DynamicMethodSymbol) {
return new DynamicMethod((DynamicMethodSymbol)o); return new DynamicMethod((DynamicMethodSymbol)o, types);
} else if (o instanceof MethodSymbol) { } else if (o instanceof MethodSymbol) {
return new Method((MethodSymbol)o); return new Method((MethodSymbol)o, types);
} else if (o instanceof VarSymbol) { } 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 { } else {
return o; return o;
} }
...@@ -134,9 +142,11 @@ public class Pool { ...@@ -134,9 +142,11 @@ public class Pool {
static class Method extends DelegatedSymbol { static class Method extends DelegatedSymbol {
MethodSymbol m; MethodSymbol m;
Method(MethodSymbol m) { UniqueType uniqueType;
Method(MethodSymbol m, Types types) {
super(m); super(m);
this.m = m; this.m = m;
this.uniqueType = new UniqueType(m.type, types);
} }
public boolean equals(Object other) { public boolean equals(Object other) {
if (!(other instanceof Method)) return false; if (!(other instanceof Method)) return false;
...@@ -144,20 +154,22 @@ public class Pool { ...@@ -144,20 +154,22 @@ public class Pool {
return return
o.name == m.name && o.name == m.name &&
o.owner == m.owner && o.owner == m.owner &&
o.type.equals(m.type); ((Method)other).uniqueType.equals(uniqueType);
} }
public int hashCode() { public int hashCode() {
return return
m.name.hashCode() * 33 + m.name.hashCode() * 33 +
m.owner.hashCode() * 9 + m.owner.hashCode() * 9 +
m.type.hashCode(); uniqueType.hashCode();
} }
} }
static class DynamicMethod extends Method { static class DynamicMethod extends Method {
public Object[] uniqueStaticArgs;
DynamicMethod(DynamicMethodSymbol m) { DynamicMethod(DynamicMethodSymbol m, Types types) {
super(m); super(m, types);
uniqueStaticArgs = getUniqueTypeArray(m.staticArgs, types);
} }
@Override @Override
...@@ -168,7 +180,8 @@ public class Pool { ...@@ -168,7 +180,8 @@ public class Pool {
DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)other).m; DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)other).m;
return dm1.bsm == dm2.bsm && return dm1.bsm == dm2.bsm &&
dm1.bsmKind == dm2.bsmKind && dm1.bsmKind == dm2.bsmKind &&
Arrays.equals(dm1.staticArgs, dm2.staticArgs); Arrays.equals(uniqueStaticArgs,
((DynamicMethod)other).uniqueStaticArgs);
} }
@Override @Override
...@@ -178,17 +191,31 @@ public class Pool { ...@@ -178,17 +191,31 @@ public class Pool {
hash += dm.bsmKind * 7 + hash += dm.bsmKind * 7 +
dm.bsm.hashCode() * 11; dm.bsm.hashCode() * 11;
for (int i = 0; i < dm.staticArgs.length; i++) { for (int i = 0; i < dm.staticArgs.length; i++) {
hash += (dm.staticArgs[i].hashCode() * 23); hash += (uniqueStaticArgs[i].hashCode() * 23);
} }
return hash; 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 { static class Variable extends DelegatedSymbol {
VarSymbol v; VarSymbol v;
Variable(VarSymbol v) { UniqueType uniqueType;
Variable(VarSymbol v, Types types) {
super(v); super(v);
this.v = v; this.v = v;
this.uniqueType = new UniqueType(v.type, types);
} }
public boolean equals(Object other) { public boolean equals(Object other) {
if (!(other instanceof Variable)) return false; if (!(other instanceof Variable)) return false;
...@@ -196,13 +223,13 @@ public class Pool { ...@@ -196,13 +223,13 @@ public class Pool {
return return
o.name == v.name && o.name == v.name &&
o.owner == v.owner && o.owner == v.owner &&
o.type.equals(v.type); ((Variable)other).uniqueType.equals(uniqueType);
} }
public int hashCode() { public int hashCode() {
return return
v.name.hashCode() * 33 + v.name.hashCode() * 33 +
v.owner.hashCode() * 9 + v.owner.hashCode() * 9 +
v.type.hashCode(); uniqueType.hashCode();
} }
} }
...@@ -214,9 +241,12 @@ public class Pool { ...@@ -214,9 +241,12 @@ public class Pool {
/** Reference symbol */ /** Reference symbol */
Symbol refSym; Symbol refSym;
public MethodHandle(int refKind, Symbol refSym) { UniqueType uniqueType;
public MethodHandle(int refKind, Symbol refSym, Types types) {
this.refKind = refKind; this.refKind = refKind;
this.refSym = refSym; this.refSym = refSym;
this.uniqueType = new UniqueType(this.refSym.type, types);
checkConsistent(); checkConsistent();
} }
public boolean equals(Object other) { public boolean equals(Object other) {
...@@ -227,14 +257,14 @@ public class Pool { ...@@ -227,14 +257,14 @@ public class Pool {
return return
o.name == refSym.name && o.name == refSym.name &&
o.owner == refSym.owner && o.owner == refSym.owner &&
o.type.equals(refSym.type); ((MethodHandle)other).uniqueType.equals(uniqueType);
} }
public int hashCode() { public int hashCode() {
return return
refKind * 65 + refKind * 65 +
refSym.name.hashCode() * 33 + refSym.name.hashCode() * 33 +
refSym.owner.hashCode() * 9 + refSym.owner.hashCode() * 9 +
refSym.type.hashCode(); uniqueType.hashCode();
} }
/** /**
......
...@@ -33,6 +33,7 @@ import com.sun.tools.javac.code.Symbol; ...@@ -33,6 +33,7 @@ import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type; 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.ClassReader;
import com.sun.tools.javac.jvm.ClassWriter; import com.sun.tools.javac.jvm.ClassWriter;
import com.sun.tools.javac.jvm.Pool; import com.sun.tools.javac.jvm.Pool;
...@@ -173,7 +174,8 @@ public class CreateSymbols extends AbstractProcessor { ...@@ -173,7 +174,8 @@ public class CreateSymbols extends AbstractProcessor {
List.<Pair<Symbol.MethodSymbol,Attribute>>nil()); List.<Pair<Symbol.MethodSymbol,Attribute>>nil());
Type.moreInfo = true; 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)) { for (JavaFileObject file : fm.list(jarLocation, "", EnumSet.of(CLASS), true)) {
String className = fm.inferBinaryName(jarLocation, file); String className = fm.inferBinaryName(jarLocation, file);
int index = className.lastIndexOf('.'); int index = className.lastIndexOf('.');
......
/*
* 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;
}
}
...@@ -50,6 +50,7 @@ import com.sun.tools.javac.api.JavacTool; ...@@ -50,6 +50,7 @@ import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symtab; 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.jvm.Pool;
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
...@@ -151,7 +152,7 @@ public class TestInvokeDynamic { ...@@ -151,7 +152,7 @@ public class TestInvokeDynamic {
abstract boolean check(CPInfo cpInfo) throws Exception; abstract boolean check(CPInfo cpInfo) throws Exception;
Object getValue(Symtab syms, Names names) { Object getValue(Symtab syms, Names names, Types types) {
switch (this) { switch (this) {
case STRING: case STRING:
case INTEGER: case INTEGER:
...@@ -162,7 +163,7 @@ public class TestInvokeDynamic { ...@@ -162,7 +163,7 @@ public class TestInvokeDynamic {
case CLASS: case CLASS:
return syms.stringType.tsym; return syms.stringType.tsym;
case METHOD_HANDLE: case METHOD_HANDLE:
return new Pool.MethodHandle(REF_invokeVirtual, syms.arrayCloneMethod); return new Pool.MethodHandle(REF_invokeVirtual, syms.arrayCloneMethod, types);
case METHOD_TYPE: case METHOD_TYPE:
return syms.arrayCloneMethod.type; return syms.arrayCloneMethod.type;
default: default:
...@@ -231,7 +232,8 @@ public class TestInvokeDynamic { ...@@ -231,7 +232,8 @@ public class TestInvokeDynamic {
Context context = ct.getContext(); Context context = ct.getContext();
Symtab syms = Symtab.instance(context); Symtab syms = Symtab.instance(context);
Names names = Names.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 { try {
ct.generate(); ct.generate();
} catch (Throwable t) { } catch (Throwable t) {
...@@ -378,10 +380,12 @@ public class TestInvokeDynamic { ...@@ -378,10 +380,12 @@ public class TestInvokeDynamic {
MethodSymbol bsm; MethodSymbol bsm;
Symtab syms; Symtab syms;
Names names; Names names;
Types types;
Indifier(Symtab syms, Names names) { Indifier(Symtab syms, Names names, Types types) {
this.syms = syms; this.syms = syms;
this.names = names; this.names = names;
this.types = types;
} }
@Override @Override
...@@ -405,7 +409,7 @@ public class TestInvokeDynamic { ...@@ -405,7 +409,7 @@ public class TestInvokeDynamic {
if (!oldSym.isConstructor()) { if (!oldSym.isConstructor()) {
Object[] staticArgs = new Object[arity.arity]; Object[] staticArgs = new Object[arity.arity];
for (int i = 0; i < arity.arity ; i++) { 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); ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name, oldSym.owner, REF_invokeStatic, bsm, oldSym.type, staticArgs);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册