diff --git a/transpiler/java/com/google/j2cl/transpiler/ast/DeclaredTypeDescriptor.java b/transpiler/java/com/google/j2cl/transpiler/ast/DeclaredTypeDescriptor.java index 70cc467d8d..5ae80df594 100644 --- a/transpiler/java/com/google/j2cl/transpiler/ast/DeclaredTypeDescriptor.java +++ b/transpiler/java/com/google/j2cl/transpiler/ast/DeclaredTypeDescriptor.java @@ -399,7 +399,7 @@ public MethodDescriptor getIsInstanceMethodDescriptor() { .setEnclosingTypeDescriptor(getMetadataTypeDeclaration().toUnparameterizedTypeDescriptor()) .setParameterTypeDescriptors(TypeDescriptors.getUnknownType()) .setReturnTypeDescriptor(PrimitiveTypes.BOOLEAN) - .setOrigin(MethodOrigin.INSTANCE_OF_SUPPORT_METHOD) + .setOrigin(MethodOrigin.SYNTHETIC_INSTANCE_OF_SUPPORT_METHOD) .setStatic(true) .build(); } @@ -412,7 +412,7 @@ public MethodDescriptor getMarkImplementorMethodDescriptor() { .setEnclosingTypeDescriptor(getMetadataTypeDeclaration().toUnparameterizedTypeDescriptor()) .setParameterTypeDescriptors(TypeDescriptors.get().nativeFunction) .setReturnTypeDescriptor(PrimitiveTypes.VOID) - .setOrigin(MethodOrigin.INSTANCE_OF_SUPPORT_METHOD) + .setOrigin(MethodOrigin.SYNTHETIC_INSTANCE_OF_SUPPORT_METHOD) .setStatic(true) .build(); } @@ -424,7 +424,7 @@ public FieldDescriptor getIsInstanceMarkerField() { .setName(isJsFunctionImplementation() ? "$is" : "$implements") .setEnclosingTypeDescriptor(this) .setTypeDescriptor(PrimitiveTypes.BOOLEAN) - .setOrigin(FieldOrigin.INSTANCE_OF_SUPPORT_FIELD) + .setOrigin(FieldOrigin.SYNTHETIC_INSTANCE_OF_SUPPORT_FIELD) .build(); } @@ -440,7 +440,7 @@ public MethodDescriptor getCopyMethodDescriptor() { .setParameterTypeDescriptors( TypeDescriptors.getUnknownType(), TypeDescriptors.getUnknownType()) .setReturnTypeDescriptor(PrimitiveTypes.VOID) - .setOrigin(MethodOrigin.INSTANCE_OF_SUPPORT_METHOD) + .setOrigin(MethodOrigin.SYNTHETIC_INSTANCE_OF_SUPPORT_METHOD) .setStatic(true) .build(); } diff --git a/transpiler/java/com/google/j2cl/transpiler/ast/FieldDescriptor.java b/transpiler/java/com/google/j2cl/transpiler/ast/FieldDescriptor.java index f43899bcbd..16a8ea88bb 100644 --- a/transpiler/java/com/google/j2cl/transpiler/ast/FieldDescriptor.java +++ b/transpiler/java/com/google/j2cl/transpiler/ast/FieldDescriptor.java @@ -54,7 +54,7 @@ public enum FieldOrigin implements MemberDescriptor.Origin { SYNTHETIC_CAPTURE_FIELD("$captured_"), SYNTHETIC_BACKING_FIELD("$static_"), SYNTHETIC_ORDINAL_FIELD("$ordinal_"), - INSTANCE_OF_SUPPORT_FIELD(""), + SYNTHETIC_INSTANCE_OF_SUPPORT_FIELD(""), ; private final String prefix; @@ -69,8 +69,8 @@ public String getPrefix() { } @Override - public boolean isInstanceOfSupportMember() { - return this == INSTANCE_OF_SUPPORT_FIELD; + public boolean isSyntheticInstanceOfSupportMember() { + return this == SYNTHETIC_INSTANCE_OF_SUPPORT_FIELD; } } diff --git a/transpiler/java/com/google/j2cl/transpiler/ast/MemberDescriptor.java b/transpiler/java/com/google/j2cl/transpiler/ast/MemberDescriptor.java index ea7badffc0..975b8a9ec3 100644 --- a/transpiler/java/com/google/j2cl/transpiler/ast/MemberDescriptor.java +++ b/transpiler/java/com/google/j2cl/transpiler/ast/MemberDescriptor.java @@ -34,7 +34,7 @@ public interface Origin { String getPrefix(); /** Returns whether this member is supporting the implementation of the instanceof operation. */ - boolean isInstanceOfSupportMember(); + boolean isSyntheticInstanceOfSupportMember(); } /** Return JsInfo from the member's annotation. */ diff --git a/transpiler/java/com/google/j2cl/transpiler/ast/MethodDescriptor.java b/transpiler/java/com/google/j2cl/transpiler/ast/MethodDescriptor.java index f2a1e1c42d..64cc9b71cc 100644 --- a/transpiler/java/com/google/j2cl/transpiler/ast/MethodDescriptor.java +++ b/transpiler/java/com/google/j2cl/transpiler/ast/MethodDescriptor.java @@ -121,7 +121,7 @@ public enum MethodOrigin implements MemberDescriptor.Origin { SYNTHETIC_LAMBDA_ADAPTOR_CONSTRUCTOR(""), SYNTHETIC_CLASS_LITERAL_GETTER, SYNTHETIC_STRING_LITERAL_GETTER, - INSTANCE_OF_SUPPORT_METHOD, + SYNTHETIC_INSTANCE_OF_SUPPORT_METHOD, GENERALIZING_BRIDGE, // Bridges a more general signature to a more specific one. SPECIALIZING_BRIDGE, // Bridges a more specific signature to a more general one. DEFAULT_METHOD_BRIDGE, // Bridges to a default method interface. @@ -169,8 +169,8 @@ public String getPrefix() { } @Override - public boolean isInstanceOfSupportMember() { - return this == INSTANCE_OF_SUPPORT_METHOD; + public boolean isSyntheticInstanceOfSupportMember() { + return this == SYNTHETIC_INSTANCE_OF_SUPPORT_METHOD; } } @@ -676,7 +676,7 @@ public String getMangledName() { return getSimpleJsName(); } - if (getOrigin().isInstanceOfSupportMember()) { + if (getOrigin().isSyntheticInstanceOfSupportMember()) { // Class support methods, like $isInstance and $markImplementor, should not be mangled. return getName(); } diff --git a/transpiler/java/com/google/j2cl/transpiler/backend/closure/ImportGatherer.java b/transpiler/java/com/google/j2cl/transpiler/backend/closure/ImportGatherer.java index 6f09c0784d..a7758a43a3 100644 --- a/transpiler/java/com/google/j2cl/transpiler/backend/closure/ImportGatherer.java +++ b/transpiler/java/com/google/j2cl/transpiler/backend/closure/ImportGatherer.java @@ -373,8 +373,8 @@ private ImportCategory getImplicitImportCategory() { return ImportCategory.LOADTIME; } - if (getCurrentMember().getDescriptor().getOrigin().isInstanceOfSupportMember()) { - // InstanceOf support members, e.g. $isInstance, might not call $clinit hence all the + if (getCurrentMember().getDescriptor().getOrigin().isSyntheticInstanceOfSupportMember()) { + // Synthetic instanceOf support members, do not call $clinit hence all the // types used in their implementation need to be imported as LOADTIME. return ImportCategory.LOADTIME; } diff --git a/transpiler/java/com/google/j2cl/transpiler/backend/libraryinfo/LibraryInfoBuilder.java b/transpiler/java/com/google/j2cl/transpiler/backend/libraryinfo/LibraryInfoBuilder.java index fc03a9bb8a..a0c7f184b6 100644 --- a/transpiler/java/com/google/j2cl/transpiler/backend/libraryinfo/LibraryInfoBuilder.java +++ b/transpiler/java/com/google/j2cl/transpiler/backend/libraryinfo/LibraryInfoBuilder.java @@ -103,10 +103,10 @@ public void addType( continue; } - if (memberDescriptor.getOrigin().isInstanceOfSupportMember()) { - // InstanceOf support members should not be considered methods that are prunable if there - // are no references, since the references are hidden by the runtime. In the end - // InstanceOf support members are live whenever the type is live. + if (memberDescriptor.getOrigin().isSyntheticInstanceOfSupportMember()) { + // Synthetic instanceof support members should not be considered methods that are prunable + // if there are no references, since the references are hidden by the runtime. In the end + // instanceof support members are live whenever the type is live. continue; } @@ -202,6 +202,10 @@ private static MemberInfo.Builder createMemberInfo( private void collectReferencedTypesAndMethodInvocations( Member member, MemberInfo.Builder memberInfoBuilder) { + // Setters and getters share the same member info for rta purposes but are traversed separately + // so when collecting references for the current member, a member info might already have + // been constructed for the corresponding accessor and its information is passed in the + // memberInfoBuilder. Set invokedMethods = new LinkedHashSet<>(memberInfoBuilder.getInvokedMethodsList()); @@ -279,6 +283,14 @@ public void exitInvocation(Invocation node) { return; } + if (target.getOrigin().isSyntheticInstanceOfSupportMember()) { + // Don't record calls to synthetic instance of support members since these are not + // kept in the library info. + // NOTE: Explicit calls to `$isInstance` are part of the translation of the + // 'instanceof' operator; and because static calls have the type as a qualifier, the + // type will be considered referenced. + return; + } // Only record a $clinit call if it is from a clinit itself. All other clinit calls are // from the entry points of the class and doesn't need recording since RapidTypeAnalyser // will make the clinit alive when it arrives to an entry point. diff --git a/transpiler/java/com/google/j2cl/transpiler/passes/NormalizeInstanceOfs.java b/transpiler/java/com/google/j2cl/transpiler/passes/NormalizeInstanceOfs.java index f9ef383539..1f717d73c1 100644 --- a/transpiler/java/com/google/j2cl/transpiler/passes/NormalizeInstanceOfs.java +++ b/transpiler/java/com/google/j2cl/transpiler/passes/NormalizeInstanceOfs.java @@ -16,7 +16,6 @@ package com.google.j2cl.transpiler.passes; import static com.google.common.base.Preconditions.checkState; -import static com.google.j2cl.transpiler.ast.MethodDescriptor.IS_INSTANCE_METHOD_NAME; import com.google.j2cl.transpiler.ast.AbstractRewriter; import com.google.j2cl.transpiler.ast.ArrayTypeDescriptor; @@ -24,16 +23,12 @@ import com.google.j2cl.transpiler.ast.DeclaredTypeDescriptor; import com.google.j2cl.transpiler.ast.Expression; import com.google.j2cl.transpiler.ast.InstanceOfExpression; -import com.google.j2cl.transpiler.ast.JsInfo; import com.google.j2cl.transpiler.ast.MethodCall; -import com.google.j2cl.transpiler.ast.MethodDescriptor; import com.google.j2cl.transpiler.ast.Node; import com.google.j2cl.transpiler.ast.NumberLiteral; import com.google.j2cl.transpiler.ast.PrimitiveTypeDescriptor; -import com.google.j2cl.transpiler.ast.PrimitiveTypes; import com.google.j2cl.transpiler.ast.RuntimeMethods; import com.google.j2cl.transpiler.ast.TypeDescriptor; -import com.google.j2cl.transpiler.ast.TypeDescriptors; /** Replaces instanceof expression with corresponding $isInstance method call. */ public class NormalizeInstanceOfs extends NormalizationPass { @@ -60,21 +55,11 @@ public Node rewriteInstanceOfExpression(InstanceOfExpression expression) { private static Node rewriteRegularInstanceOfExpression( InstanceOfExpression instanceOfExpression) { - TypeDescriptor checkTypeDescriptor = instanceOfExpression.getTestTypeDescriptor(); - - MethodDescriptor isInstanceMethodDescriptor = - MethodDescriptor.newBuilder() - .setOriginalJsInfo(JsInfo.RAW) - .setStatic(true) - .setEnclosingTypeDescriptor( - checkTypeDescriptor.getMetadataTypeDeclaration().toUnparameterizedTypeDescriptor()) - .setName(IS_INSTANCE_METHOD_NAME) - .setParameterTypeDescriptors(TypeDescriptors.get().javaLangObject) - .setReturnTypeDescriptor(PrimitiveTypes.BOOLEAN) - .build(); + DeclaredTypeDescriptor checkTypeDescriptor = + (DeclaredTypeDescriptor) instanceOfExpression.getTestTypeDescriptor(); // TypeName.$isInstance(expr); - return MethodCall.Builder.from(isInstanceMethodDescriptor) + return MethodCall.Builder.from(checkTypeDescriptor.getIsInstanceMethodDescriptor()) .setArguments(instanceOfExpression.getExpression()) .build(); }