Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8244227: [lworld] Explore an implementation where the reference projection and value projection types are backed by a single class symbol #375

Closed
wants to merge 11 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1225,7 +1225,7 @@ public TypeMirror getOriginalType(javax.lang.model.type.ErrorType errorType) {
ClassType ct = (ClassType) errorType;
return extraType2OriginalMap.computeIfAbsent(ct, tt ->
new ClassType(ct.getEnclosingType(), ct.typarams_field,
ct.tsym, ct.getMetadata()) {
ct.tsym, ct.getMetadata(), ct.isReferenceProjection()) {
@Override
public Type baseType() { return ct; }
@Override
@@ -234,6 +234,10 @@ public String visitClassType(ClassType t, Locale locale) {
buf.append(printAnnotations(t));
buf.append(className(t, true, locale));
}
if (t.isReferenceProjection()) {
buf.append('.');
buf.append(t.tsym.name.table.names.ref);
}
if (t.getTypeArguments().nonEmpty()) {
buf.append('<');
buf.append(visitTypes(t.getTypeArguments(), locale));
@@ -426,18 +426,10 @@ public boolean isReferenceProjection() {
}

/**
* Return the value projection IFF 'this' happens to be derived reference projection, null
* otherwise.
* If this is the symbol for a reference projection class, what is the class for which
* this is a projection ??
*/
public Symbol valueProjection() {
return null;
}

/**
* Return the reference projection IFF 'this' happens to be inline class, null
* otherwise.
*/
public Symbol referenceProjection() {
public ClassSymbol valueProjection() {
return null;
}

@@ -1328,12 +1320,6 @@ public static class ClassSymbol extends TypeSymbol implements TypeElement {
*/
private List<RecordComponent> recordComponents = List.nil();

/* the 'other' projection: If 'this' is an inline class then 'projection' is its reference projection
and vice versa.
*/
public ClassSymbol projection;


// sealed classes related fields
/** The classes, or interfaces, permitted to extend this class, or interface
*/
@@ -1393,7 +1379,8 @@ public Type erasure(Types types) {
if (erasure_field == null)
erasure_field = new ClassType(types.erasure(type.getEnclosingType()),
List.nil(), this,
type.getMetadata());
type.getMetadata(),
type.isReferenceProjection());
return erasure_field;
}

@@ -1663,65 +1650,6 @@ public boolean isRecord() {
return (flags_field & RECORD) != 0;
}

@Override
public boolean isReferenceProjection() {
return projection != null && projection.isPrimitiveClass();
}

@Override
public ClassSymbol valueProjection() {
return isReferenceProjection() ? projection : null;
}

@Override
public ClassSymbol referenceProjection() {
if (!isPrimitiveClass())
return null;

if (projection != null)
return projection;

ClassType ct = (ClassType) this.type;
ClassType projectedType = new ClassType(ct.getEnclosingType(), ct.typarams_field, null);
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 = ct;
ct.projection = projectedType;

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

projection = new ClassSymbol(projectionFlags, projectionName, projectedType, this.owner);
projection.members_field = WriteableScope.create(projection);
for (Symbol s : this.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);
valMethod.projection = refMethod;
refMethod.projection = valMethod;
clone = refMethod;
} else if (s.kind == VAR) {
VarSymbol valVar = (VarSymbol)s;
VarSymbol refVar = valVar.clone(projection);
valVar.projection = refVar;
refVar.projection = valVar;
clone = refVar;
}
projection.members_field.enter(clone);
}
projection.completer = Completer.NULL_COMPLETER;
projection.sourcefile = this.sourcefile;
projection.flatname = this.flatname.append('$', this.name.table.names.ref);
projection.permitted = List.of(this);
projection.projection = this;
projectedType.tsym = projection;
return projection;
}

@DefinedBy(Api.LANGUAGE_MODEL)
public List<Type> getPermittedSubclasses() {
return permitted.map(s -> s.type);
@@ -1748,11 +1676,6 @@ public static class VarSymbol extends Symbol implements VariableElement {
*/
public int adr = -1;

/* The 'other' projection: If 'this' is a field of an inline class, then 'projection' is the
its doppleganger in its referene projection class and vice versa.
*/
public VarSymbol projection;

/** Construct a variable symbol, given its flags, name, type and owner.
*/
public VarSymbol(long flags, Name name, Type type, Symbol owner) {
@@ -1785,7 +1708,6 @@ public Object poolKey(Types types) {
v.pos = pos;
v.adr = adr;
v.data = data;
v.projection = projection;
// System.out.println("clone " + v + " in " + newOwner);//DEBUG
return v;
}
@@ -1838,18 +1760,6 @@ public void setLazyConstValue(final Env<AttrContext> env,
setData((Callable<Object>)() -> attr.attribLazyConstantValue(env, variable, type));
}

@Override
public VarSymbol referenceProjection() {
return this.owner.isPrimitiveClass() ?
this.owner.referenceProjection() != null ? projection : null
: null;
}

@Override
public VarSymbol valueProjection() {
return projection != null ? projection.owner.isPrimitiveClass() ? projection : null: null;
}

/**
* The variable's constant value, if this is a constant.
* Before the constant value is evaluated, it points to an
@@ -2026,11 +1936,6 @@ public static class MethodSymbol extends Symbol implements ExecutableElement {
*/
public Attribute defaultValue = null;

/* The 'other' projection: If 'this' is a method of an inline class, then 'projection' is the
its doppleganger in its referene projection class and vice versa.
*/
public MethodSymbol projection;

/** Construct a method symbol, given its flags, name, type and owner.
*/
public MethodSymbol(long flags, Name name, Type type, Symbol owner) {
@@ -2053,7 +1958,6 @@ public Object poolKey(Types types) {
}
};
m.code = code;
m.projection = projection;
return m;
}

@@ -2138,7 +2042,7 @@ public boolean binaryOverrides(Symbol _other, TypeSymbol origin, Types types) {

// check for a direct implementation
if (other.isOverridableIn((TypeSymbol)owner) &&
types.asSuper(owner.type, other.owner) != null &&
types.asSuper(owner.type.referenceProjectionOrSelf(), other.owner) != null &&
types.isSameType(erasure(types), other.erasure(types)))
return true;

@@ -2202,24 +2106,12 @@ public boolean overrides(Symbol _other, TypeSymbol origin, Types types, boolean
boolean requireConcreteIfInherited) {
if (isConstructor() || _other.kind != MTH) return false;


/* If any inline types are involved, ask the same question in the reference universe,
where the hierarchy is navigable
*/
if (origin.isPrimitiveClass())
origin = (TypeSymbol) origin.referenceProjection();

if (this.owner.isPrimitiveClass()) {
return this.projection != null &&
this.projection.overrides(_other, origin, types, checkResult, requireConcreteIfInherited);
}

if (this == _other) return true;
MethodSymbol other = (MethodSymbol)_other;

// check for a direct implementation
if (other.isOverridableIn((TypeSymbol)owner) &&
types.asSuper(owner.type, other.owner) != null) {
types.asSuper(owner.type.referenceProjectionOrSelf(), other.owner) != null) {
sadayapalam marked this conversation as resolved.
Show resolved Hide resolved
Type mt = types.memberType(owner.type, this);
Type ot = types.memberType(owner.type, other);
if (types.isSubSignature(mt, ot)) {
@@ -2269,14 +2161,6 @@ private boolean isOverridableIn(TypeSymbol origin) {
@Override
public boolean isInheritedIn(Symbol clazz, Types types) {

/* If any inline types are involved, ask the same question in the reference universe,
where the hierarchy is navigable
*/
if (clazz.isPrimitiveClass())
clazz = clazz.referenceProjection();
if (this.owner.isPrimitiveClass())
return this.projection.isInheritedIn(clazz, types);

switch ((int)(flags_field & Flags.AccessFlags)) {
case PUBLIC:
return !this.owner.isInterface() ||
@@ -2291,18 +2175,6 @@ public boolean isLambdaMethod() {
return (flags() & LAMBDA_METHOD) == LAMBDA_METHOD;
}

@Override
public MethodSymbol referenceProjection() {
return this.owner.isPrimitiveClass() ?
this.owner.referenceProjection() != null ? projection : null
: null;
}

@Override
public MethodSymbol valueProjection() {
return projection != null ? projection.owner.isPrimitiveClass() ? projection : null : null;
}

/** override this method to point to the original enclosing method if this method symbol represents a synthetic
* lambda method
*/