Skip to content
Permalink
Browse files
8267597: [lworld] Withdraw all support for bifurcated class generatio…
…n for primitive classes

8268527: [lqagain] langtool tests need tweaks to run properly in an universe where -XDunifiedValRefClass is the default
  • Loading branch information
Srikanth Adayapalam committed Jun 10, 2021
1 parent 31e9967 commit d23562e422f2660c80b8a225d3d31aa1effb64de
Showing with 67 additions and 802 deletions.
  1. +1 −26 src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
  2. +2 −23 src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
  3. +0 −6 src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
  4. +37 −134 src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
  5. +3 −3 src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
  6. +4 −11 src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java
  7. +1 −7 src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/TransValues.java
  8. +4 −4 test/langtools/tools/javac/valhalla/lworld-values/ArrayCreationWithQuestion.java
  9. +2 −6 test/langtools/tools/javac/valhalla/lworld-values/AttributesTest.java
  10. +1 −1 test/langtools/tools/javac/valhalla/lworld-values/BoxValCastTest.java
  11. +4 −4 test/langtools/tools/javac/valhalla/lworld-values/CheckFieldDescriptors.java
  12. +0 −122 test/langtools/tools/javac/valhalla/lworld-values/CheckNeededCastInMemberAccess.java
  13. +1 −1 test/langtools/tools/javac/valhalla/lworld-values/ConsumeUnifiedClass.java
  14. +0 −57 test/langtools/tools/javac/valhalla/lworld-values/InlineNestingAttributesTest.java
  15. +0 −1 test/langtools/tools/javac/valhalla/lworld-values/NoUnnecessaryCast.java
  16. +2 −2 test/langtools/tools/javac/valhalla/lworld-values/ProjectedArrayDotClass.java
  17. +0 −49 test/langtools/tools/javac/valhalla/lworld-values/ProjectionSealed.java
  18. +1 −1 test/langtools/tools/javac/valhalla/lworld-values/RefDotClass.java
  19. +1 −7 test/langtools/tools/javac/valhalla/lworld-values/SignatureTest.java
  20. +0 −118 test/langtools/tools/javac/valhalla/lworld-values/SplitPrimitiveClassBytecodeTest.java
  21. +0 −73 test/langtools/tools/javac/valhalla/lworld-values/SplitPrimitiveClassInnerClassesTest.java
  22. +0 −104 test/langtools/tools/javac/valhalla/lworld-values/SplitPrimitiveClassNestHostTest.java
  23. +2 −11 test/langtools/tools/javac/valhalla/lworld-values/TopInterfaceTest.java
  24. +1 −28 test/langtools/tools/javac/valhalla/lworld-values/UnannotatedProjection.java
  25. +0 −1 test/langtools/tools/javac/valhalla/lworld-values/UnifiedPrimitiveClassBytecodeTest.java
  26. +0 −1 test/langtools/tools/javac/valhalla/lworld-values/UnifiedPrimitiveClassInnerClassesTest.java
  27. +0 −1 test/langtools/tools/javac/valhalla/lworld-values/UnifiedPrimitiveClassNestHostTest.java
@@ -420,21 +420,6 @@ public boolean isPrimitiveClass() {
return (flags() & PRIMITIVE_CLASS) != 0;
}

/**
* Is this a *derived* reference projection symbol ??
*/
public boolean isReferenceProjection() {
return false;
}

/**
* If this is the symbol for a reference projection class, what is the class for which
* this is a projection ??
*/
public ClassSymbol valueProjection() {
return null;
}

public boolean isPublic() {
return (flags_field & Flags.AccessFlags) == PUBLIC;
}
@@ -545,8 +530,6 @@ public ClassSymbol enclClass() {
}

/** The outermost class which indirectly owns this symbol.
* 'outermost' being a lexical construct, should transcend
* projections
*/
public ClassSymbol outermostClass() {
Symbol sym = this;
@@ -555,7 +538,7 @@ public ClassSymbol outermostClass() {
prev = sym;
sym = sym.owner;
}
return (ClassSymbol) (prev!= null && prev.isReferenceProjection() ? prev.valueProjection() : prev);
return (ClassSymbol) prev;
}

/** The package which indirectly owns this symbol.
@@ -1431,14 +1414,6 @@ public boolean isSubClass(Symbol base, Types types) {
return false;
}

/**
* Does `this' symbolize a primitive class that would, under the translation
* scheme in effect be lowered into two class files on a bifurcased basis ??
*/
public boolean isSplitPrimitiveClass(Types types) {
return types.splitPrimitiveClass && this.isPrimitiveClass();
}

/** Complete the elaboration of this symbol's definition.
*/
public void complete() throws CompletionFailure {
@@ -102,18 +102,6 @@ public class Types {
List<Warner> warnStack = List.nil();
final Name capturedName;

/**
* If true, the ClassWriter will split a primitive class declaration into two class files
* P.ref.class and P.val.class (P.class for pure primitive classes)
*
* This is the default behavior, can be eoverridden with -XDunifiedValRefClass
*
* If false, we emit a single class for a primtive class 'P' and the reference projection and
* value projection types are encoded in descriptors as LP; and QP; resperctively.
*/

public boolean splitPrimitiveClass;

public final Warner noWarnings;

// <editor-fold defaultstate="collapsed" desc="Instantiating">
@@ -139,7 +127,6 @@ protected Types(Context context) {
noWarnings = new Warner(null);
Options options = Options.instance(context);
allowValueBasedClasses = options.isSet("allowValueBasedClasses");
splitPrimitiveClass = false ; // options.isUnset("unifiedValRefClass"); // Temporarely forcing the default
}
// </editor-fold>

@@ -1880,7 +1867,7 @@ public Boolean visitClassType(ClassType t, Type s) {
// Sidecast
if (s.hasTag(CLASS)) {
if ((s.tsym.flags() & INTERFACE) != 0) {
return (dynamicTypeMayImplementAdditionalInterfaces(t.tsym))
return ((t.tsym.flags() & FINAL) == 0)
? sideCast(t, s, warnStack.head)
: sideCastFinal(t, s, warnStack.head);
} else if ((t.tsym.flags() & INTERFACE) != 0) {
@@ -4672,7 +4659,7 @@ private boolean sideCastFinal(Type from, Type to, Warner warn) {
to = from;
from = target;
}
Assert.check(!dynamicTypeMayImplementAdditionalInterfaces(from.tsym));
Assert.check((from.tsym.flags() & FINAL) != 0);
Type t1 = asSuper(from, to.tsym);
if (t1 == null) return false;
Type t2 = to;
@@ -4684,10 +4671,6 @@ private boolean sideCastFinal(Type from, Type to, Warner warn) {
return true;
}

private boolean dynamicTypeMayImplementAdditionalInterfaces(TypeSymbol tsym) {
return (tsym.flags() & FINAL) == 0 && !tsym.isReferenceProjection();
}

private boolean giveWarning(Type from, Type to) {
List<Type> bounds = to.isCompound() ?
directSupertypes(to) : List.of(to);
@@ -5366,10 +5349,6 @@ public void assembleClassSig(Type type) {
} else {
append(externalize(c.flatname));
}
if (types.splitPrimitiveClass && ct.isReferenceProjection()) {
append('$');
append(types.names.ref);
}
if (ct.getTypeArguments().nonEmpty()) {
append('<');
assembleSig(ct.getTypeArguments());
@@ -3106,12 +3106,6 @@ <T extends JCExpression> T applyPrimitiveConversionsAsNeeded(T tree, Type type)
boolean haveValue = tree.type.isPrimitiveClass();
if (haveValue == type.isPrimitiveClass())
return tree;
if (haveValue) {
// widening coversion is a NOP for the VM due to subtyping relationship at class file level
// where we bifurcate a primitive class into two class files.
if (types.splitPrimitiveClass)
return tree;
}
// For narrowing conversion, insert a cast which should trigger a null check
// For widening conversions, insert a cast if emitting a unified class file.
return (T) make.TypeCast(type, tree);
@@ -822,13 +822,11 @@ int writeModuleAttribute(ClassSymbol c) {
* Writing Objects
**********************************************************************/

/** Write "inner classes" attribute. If a primitive class happens to be an inner class,
* the reference projection class will also be an inner class.
/** Write "inner classes" attribute.
*/
void writeInnerClasses() {
int alenIdx = writeAttr(names.InnerClasses);
int icCountIdx = beginAttrs();
int icCount = 0;
databuf.appendChar(poolWriter.innerClasses.size());
for (ClassSymbol inner : poolWriter.innerClasses) {
inner.markAbstractIfNeeded(types);
char flags = (char) adjustFlags(inner.flags_field);
@@ -845,19 +843,7 @@ void writeInnerClasses() {
databuf.appendChar(
!inner.name.isEmpty() ? poolWriter.putName(inner.name) : 0);
databuf.appendChar(flags);
icCount++;
if (inner.isSplitPrimitiveClass(types)) {
databuf.appendChar(poolWriter.putClass(inner.type.referenceProjection()));
databuf.appendChar(
inner.owner.kind == TYP && !inner.name.isEmpty() ? poolWriter.putClass((ClassSymbol)inner.owner) : 0);
databuf.appendChar(
!inner.name.isEmpty() ? poolWriter.putName(inner.name.append('$', names.ref)) : 0);
flags = (char) ((flags & ~(ACC_PRIMITIVE | FINAL)) | ABSTRACT);
databuf.appendChar(flags);
icCount++;
}
}
endAttrs(icCountIdx, icCount);
endAttr(alenIdx);
}

@@ -882,33 +868,17 @@ int writeRecordAttribute(ClassSymbol csym) {
* Write NestMembers attribute (if needed)
*/
int writeNestMembersIfNeeded(ClassSymbol csym) {
Set<ClassSymbol> nestedUnique = new LinkedHashSet<>();
if (csym.owner.kind == PCK) {
if (csym.isSplitPrimitiveClass(types)) {
// reference projection is the host
} else if (csym.isReferenceProjection()) {
ClassSymbol valueProjection = csym.valueProjection();
nestedUnique.add(valueProjection);
listNested(valueProjection, nestedUnique);
} else {
listNested(csym, nestedUnique);
}
if (!nestedUnique.isEmpty()) {
int alenIdx = writeAttr(names.NestMembers);
int nmcIdx = beginAttrs();
int nmc = 0;
for (ClassSymbol s : nestedUnique) {
databuf.appendChar(poolWriter.putClass(s));
nmc++;
if (s.isSplitPrimitiveClass(types) && s.owner.kind != PCK) {
databuf.appendChar(poolWriter.putClass(s.type.referenceProjection()));
nmc++;
}
}
endAttrs(nmcIdx, nmc);
endAttr(alenIdx);
return 1;
ListBuffer<ClassSymbol> nested = new ListBuffer<>();
listNested(csym, nested);
Set<ClassSymbol> nestedUnique = new LinkedHashSet<>(nested);
if (csym.owner.kind == PCK && !nestedUnique.isEmpty()) {
int alenIdx = writeAttr(names.NestMembers);
databuf.appendChar(nestedUnique.size());
for (ClassSymbol s : nestedUnique) {
databuf.appendChar(poolWriter.putClass(s));
}
endAttr(alenIdx);
return 1;
}
return 0;
}
@@ -917,21 +887,16 @@ int writeNestMembersIfNeeded(ClassSymbol csym) {
* Write NestHost attribute (if needed)
*/
int writeNestHostIfNeeded(ClassSymbol csym) {
if (csym.owner.kind != PCK || csym.isSplitPrimitiveClass(types)) {
if (csym.owner.kind != PCK) {
int alenIdx = writeAttr(names.NestHost);
ClassSymbol outerMost = csym.outermostClass();
if (outerMost.isSplitPrimitiveClass(types)) {
databuf.appendChar(poolWriter.putClass(outerMost.type.referenceProjection()));
} else {
databuf.appendChar(poolWriter.putClass(outerMost));
}
databuf.appendChar(poolWriter.putClass(csym.outermostClass()));
endAttr(alenIdx);
return 1;
}
return 0;
}

private void listNested(Symbol sym, Set<ClassSymbol> seen) {
private void listNested(Symbol sym, ListBuffer<ClassSymbol> seen) {
if (sym.kind != TYP) return;
ClassSymbol csym = (ClassSymbol)sym;
if (csym.owner.kind != PCK) {
@@ -1531,67 +1496,9 @@ public JavaFileObject writeClass(ClassSymbol c)
throws IOException, PoolOverflow, StringOverflow
{
JavaFileObject javaFileObject = writeClassInternal(c);
if (c.isSplitPrimitiveClass(types)) {
writeClassInternal(getReferenceProjection(c));
}
return javaFileObject;
}

// where
private static ClassSymbol getReferenceProjection(ClassSymbol c) {

ClassSymbol projection;
ClassType projectedType;

ClassType ct = (ClassType) c.type;
/* Note, the class type associated with the Primitive$ref.class is NOT a reference projection type. A reference projection
* type gets created by using Primitive.ref notation in the source file or while reading in a descriptor of such a type
* from the class file. Here we are generating the Primitive$ref.class for the VM's benefit and it is a reference class.
*/
projectedType = new ClassType(ct.getEnclosingType(), ct.typarams_field, null, ct.getMetadata(), Flavor.L_TypeOf_L);
projectedType.allparams_field = ct.allparams_field;
projectedType.supertype_field = ct.supertype_field;

projectedType.interfaces_field = ct.interfaces_field;
projectedType.all_interfaces_field = ct.all_interfaces_field;
projectedType.projection = null;

Name projectionName = c.name.append('$', c.name.table.names.ref);
long projectionFlags = (c.flags() & ~(PRIMITIVE_CLASS | UNATTRIBUTED | FINAL)) | (ABSTRACT | SEALED);

projection = new ClassSymbol(projectionFlags, projectionName, projectedType, c.owner) {
@Override
public boolean isReferenceProjection() {
return true;
}

@Override
public ClassSymbol valueProjection() {
return c;
}
};
projection.members_field = WriteableScope.create(projection);
for (Symbol s : c.members().getSymbols(s->(s.kind == MTH || s.kind == VAR), NON_RECURSIVE)) {
Symbol clone = null;
if (s.kind == MTH) {
MethodSymbol valMethod = (MethodSymbol)s;
MethodSymbol refMethod = valMethod.clone(projection);
clone = refMethod;
} else if (s.kind == VAR) {
VarSymbol valVar = (VarSymbol)s;
VarSymbol refVar = valVar.clone(projection);
clone = refVar;
}
projection.members_field.enter(clone);
}
projection.completer = Completer.NULL_COMPLETER;
projection.sourcefile = c.sourcefile;
projection.flatname = c.flatname.append('$', c.name.table.names.ref);
projection.permitted = List.of(c);
projectedType.tsym = projection;
return projection;
}

private JavaFileObject writeClassInternal(ClassSymbol c)
throws IOException, PoolOverflow, StringOverflow
{
@@ -1636,8 +1543,8 @@ public void writeClassFile(OutputStream out, ClassSymbol c)
databuf.reset();
poolbuf.reset();

Type supertype = c.isSplitPrimitiveClass(types) ? c.type.referenceProjection() : types.supertype(c.type);
List<Type> interfaces = c.isSplitPrimitiveClass(types) ? List.nil() : types.interfaces(c.type);
Type supertype = types.supertype(c.type);
List<Type> interfaces = types.interfaces(c.type);
List<Type> typarams = c.type.getTypeArguments();

int flags;
@@ -1670,37 +1577,33 @@ public void writeClassFile(OutputStream out, ClassSymbol c)
databuf.appendChar(poolWriter.putClass((ClassSymbol)l.head.tsym));
int fieldsCount = 0;
int methodsCount = 0;
boolean referenceProjection = c.isReferenceProjection();
if (!referenceProjection) {
for (Symbol sym : c.members().getSymbols(NON_RECURSIVE)) {
switch (sym.kind) {
case VAR:
fieldsCount++;
break;
case MTH:
if ((sym.flags() & HYPOTHETICAL) == 0) methodsCount++;
break;
case TYP:
poolWriter.enterInner((ClassSymbol)sym);
break;
default:
Assert.error();
}

for (Symbol sym : c.members().getSymbols(NON_RECURSIVE)) {
switch (sym.kind) {
case VAR:
fieldsCount++;
break;
case MTH:
if ((sym.flags() & HYPOTHETICAL) == 0) methodsCount++;
break;
case TYP:
poolWriter.enterInner((ClassSymbol)sym);
break;
default:
Assert.error();
}
}

if (c.trans_local != null) {
for (ClassSymbol local : c.trans_local) {
poolWriter.enterInner(local);
}
if (c.trans_local != null) {
for (ClassSymbol local : c.trans_local) {
poolWriter.enterInner(local);
}
}

databuf.appendChar(fieldsCount);
if (!referenceProjection)
writeFields(c.members());
writeFields(c.members());
databuf.appendChar(methodsCount);
if (!referenceProjection)
writeMethods(c.members());
writeMethods(c.members());

int acountIdx = beginAttrs();
int acount = 0;
@@ -2271,10 +2271,10 @@ public void visitTypeCast(JCTypeCast tree) {
// which is not statically a supertype of the expression's type.
// For basic types, the coerce(...) in genExpr(...) will do
// the conversion.
// inline widening conversion is a nop when we bifurcate the primitive class, as the VM sees a subtyping relationship.
// inline widening conversion should not require a checkcast but we issue one per VM's request as of now (see || true below)
if (!tree.clazz.type.isPrimitive() &&
!types.isSameType(tree.expr.type, tree.clazz.type) &&
(!tree.clazz.type.isReferenceProjection() || !types.splitPrimitiveClass || !types.isSameType(tree.clazz.type.valueProjection(), tree.expr.type)) &&
(!tree.clazz.type.isReferenceProjection() || !types.isSameType(tree.clazz.type.valueProjection(), tree.expr.type) || true) &&
!types.isSubtype(tree.expr.type, tree.clazz.type)) {
checkDimension(tree.pos(), tree.clazz.type);
if (types.isPrimitiveClass(tree.clazz.type)) {
@@ -2344,7 +2344,7 @@ public void visitSelect(JCFieldAccess tree) {
Symbol sym = tree.sym;

if (tree.name == names._class) {
code.emitLdc((LoadableConstant) tree.selected.type, makeRef(tree.pos(), tree.selected.type, !types.splitPrimitiveClass && tree.selected.type.isPrimitiveClass()));
code.emitLdc((LoadableConstant) tree.selected.type, makeRef(tree.pos(), tree.selected.type, tree.selected.type.isPrimitiveClass()));
result = items.makeStackItem(pt);
return;
}

0 comments on commit d23562e

Please sign in to comment.