Get rid of superCall fields in class/closure codegen

Because their semantics looks wrong in case of secondary constructors.
Use resolved delegation call instead.
This commit is contained in:
Denis Zharkov
2015-02-27 12:22:20 +03:00
parent 4c26d037d9
commit 31be68de0a
7 changed files with 32 additions and 61 deletions
@@ -64,6 +64,7 @@ import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject;
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant;
import org.jetbrains.kotlin.resolve.constants.evaluate.EvaluatePackage;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
import org.jetbrains.kotlin.types.Approximation;
@@ -1428,7 +1429,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
pushClosureOnStack(classDescriptor, true, defaultCallGenerator);
ResolvedCall<ConstructorDescriptor> superCall = bindingContext.get(CLOSURE, classDescriptor).getSuperCall();
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
assert primaryConstructor != null : "There should be primary constructor for object literal";
ResolvedCall<ConstructorDescriptor> superCall = getDelegationConstructorCall(bindingContext, primaryConstructor);
if (superCall != null) {
// For an anonymous object, we should also generate all non-default arguments that it captures for its super call
ConstructorDescriptor superConstructor = superCall.getResultingDescriptor();
@@ -1496,10 +1499,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
callGenerator.putCapturedValueOnStack(capturedVar, sharedVarType, paramIndex++);
}
ResolvedCall<ConstructorDescriptor> superCall = closure.getSuperCall();
if (superCall != null) {
ClassDescriptor superClass = DescriptorUtilPackage.getSuperClassNotAny(classDescriptor);
if (superClass != null) {
pushClosureOnStack(
superCall.getResultingDescriptor().getContainingDeclaration(),
superClass,
putThis && closure.getCaptureThis() == null,
callGenerator
);
@@ -52,6 +52,7 @@ import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
@@ -85,7 +86,6 @@ import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class ImplementationBodyCodegen extends ClassBodyCodegen {
private static final String ENUM_VALUES_FIELD_NAME = "$VALUES";
private JetDelegatorToSuperCall superCall;
private Type superClassAsmType;
@Nullable // null means java/lang/Object
private JetType superClassType;
@@ -346,7 +346,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (!isInterface(superClassDescriptor)) {
superClassType = superType;
superClassAsmType = typeMapper.mapClass(superClassDescriptor);
superCall = (JetDelegatorToSuperCall) specifier;
}
}
}
@@ -1117,12 +1116,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
if (superCall == null) {
genSimpleSuperCall(iv);
}
else {
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor);
}
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor);
if (isNonDefaultObject(descriptor)) {
StackValue.singleton(descriptor, typeMapper).store(StackValue.LOCAL_0, iv);
@@ -1329,15 +1323,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
if (superCall != null) {
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCallWithAssert(superCall, bindingContext);
ClassDescriptor superClass = ((ConstructorDescriptor) resolvedCall.getResultingDescriptor()).getContainingDeclaration();
ClassDescriptor superClass = DescriptorUtilPackage.getSuperClassNotAny(descriptor);
if (superClass != null) {
if (superClass.isInner()) {
constructorContext.lookupInContext(superClass.getContainingDeclaration(), StackValue.LOCAL_0, state, true);
}
if (!isAnonymousObject(descriptor)) {
JetValueArgumentList argumentList = superCall.getValueArgumentList();
ResolvedCall<ConstructorDescriptor> delegationCall =
getDelegationConstructorCall(bindingContext, descriptor.getUnsubstitutedPrimaryConstructor());
JetValueArgumentList argumentList = delegationCall != null ? delegationCall.getCall().getValueArgumentList() : null;
if (argumentList != null) {
argumentList.accept(visitor);
}
@@ -1419,9 +1414,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@NotNull ExpressionCodegen codegen,
@NotNull ConstructorDescriptor constructorDescriptor
) {
ResolvedCall<?> resolvedCall = getDelegationConstructorCall(bindingContext, constructorDescriptor);
if (resolvedCall == null) {
genSimpleSuperCall(iv);
return;
}
iv.load(0, OBJECT_TYPE);
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCallWithAssert(superCall, bindingContext);
ConstructorDescriptor superConstructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor);
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.InlineDescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
import org.jetbrains.kotlin.types.JetType;
@@ -236,4 +237,12 @@ public class JvmCodegenUtil {
declaration.getParent() instanceof JetFunctionLiteralExpression &&
InlineDescriptorUtils.isInlineLambda((JetFunctionLiteralExpression) declaration.getParent(), bindingContext, false);
}
@Nullable
public static ResolvedCall<ConstructorDescriptor> getDelegationConstructorCall(
@NotNull BindingContext bindingContext,
@NotNull ConstructorDescriptor constructorDescriptor
) {
return bindingContext.get(BindingContext.CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructorDescriptor);
}
}
@@ -31,9 +31,6 @@ import java.util.List;
import java.util.Map;
public interface CalculatedClosure {
@Nullable
ResolvedCall<ConstructorDescriptor> getSuperCall();
@Nullable
ClassDescriptor getCaptureThis();
@@ -162,7 +162,7 @@ public class CodegenBinding {
JetElement element = (JetElement) descriptorToDeclaration(classDescriptor);
assert element != null : "No source element for " + classDescriptor;
MutableClosure closure = new MutableClosure(classDescriptor, findSuperCall(trace.getBindingContext(), element), enclosing);
MutableClosure closure = new MutableClosure(classDescriptor, enclosing);
if (classDescriptor.isInner()) {
closure.setCaptureThis();
@@ -271,31 +271,6 @@ public class CodegenBinding {
return type;
}
@Nullable
private static ResolvedCall<ConstructorDescriptor> findSuperCall(
@NotNull BindingContext bindingContext,
@NotNull JetElement classOrObject
) {
if (!(classOrObject instanceof JetClassOrObject)) return null;
if (classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait()) return null;
for (JetDelegationSpecifier specifier : ((JetClassOrObject) classOrObject).getDelegationSpecifiers()) {
if (!(specifier instanceof JetDelegatorToSuperCall)) continue;
ResolvedCall<?> resolvedCall = getResolvedCall(specifier, bindingContext);
if (resolvedCall == null) continue;
CallableDescriptor constructor = resolvedCall.getResultingDescriptor();
if (constructor instanceof ConstructorDescriptor && !isInterface(constructor.getContainingDeclaration())) {
//noinspection unchecked
return (ResolvedCall<ConstructorDescriptor>) resolvedCall;
}
}
return null;
}
@NotNull
public static Collection<ClassDescriptor> getAllInnerClasses(
@NotNull BindingContext bindingContext, @NotNull ClassDescriptor outermostClass
@@ -30,8 +30,6 @@ import java.util.*;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.getDirectMember;
public final class MutableClosure implements CalculatedClosure {
private final ResolvedCall<ConstructorDescriptor> superCall;
private final ClassDescriptor enclosingClass;
private final CallableDescriptor enclosingFunWithReceiverDescriptor;
@@ -41,13 +39,8 @@ public final class MutableClosure implements CalculatedClosure {
private Map<DeclarationDescriptor, EnclosedValueDescriptor> captureVariables;
private List<Pair<String, Type>> recordedFields;
MutableClosure(
@NotNull ClassDescriptor classDescriptor,
@Nullable ResolvedCall<ConstructorDescriptor> superCall,
@Nullable ClassDescriptor enclosingClass
) {
MutableClosure(@NotNull ClassDescriptor classDescriptor, @Nullable ClassDescriptor enclosingClass) {
this.enclosingClass = enclosingClass;
this.superCall = superCall;
this.enclosingFunWithReceiverDescriptor = enclosingExtensionMemberForClass(classDescriptor);
}
@@ -68,11 +61,6 @@ public final class MutableClosure implements CalculatedClosure {
return enclosingClass;
}
@Override
public ResolvedCall<ConstructorDescriptor> getSuperCall() {
return superCall;
}
@Override
public ClassDescriptor getCaptureThis() {
return captureThis ? enclosingClass : null;
@@ -896,7 +896,7 @@ public class JetTypeMapper {
}
}
ResolvedCall<ConstructorDescriptor> superCall = closure.getSuperCall();
ResolvedCall<ConstructorDescriptor> superCall = getDelegationConstructorCall(bindingContext, descriptor);
// We may generate a slightly wrong signature for a local class / anonymous object in light classes mode but we don't care,
// because such classes are not accessible from the outside world
if (superCall != null && classBuilderMode == ClassBuilderMode.FULL) {