From 396376c0131ffebb73cbeb94a8f26c31cc99479b Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Sat, 12 Nov 2011 19:13:26 +0200 Subject: [PATCH] fix for broken test. (this, receiver) handling normalized --- .../jetbrains/jet/codegen/CallableMethod.java | 21 ++-- .../jetbrains/jet/codegen/ClosureCodegen.java | 11 ++ .../jetbrains/jet/codegen/CodegenUtil.java | 27 +++++ .../jet/codegen/ExpressionCodegen.java | 114 +++++++----------- .../jetbrains/jet/codegen/JetTypeMapper.java | 4 +- .../org/jetbrains/jet/codegen/StackValue.java | 21 ++++ 6 files changed, 121 insertions(+), 77 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java b/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java index fea60bcc202..0046ce0048a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java @@ -1,7 +1,9 @@ package org.jetbrains.jet.codegen; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; @@ -18,8 +20,9 @@ public class CallableMethod implements Callable { private final Method signature; private int invokeOpcode; private final List valueParameterTypes; - private DeclarationDescriptor thisClass = null; - private DeclarationDescriptor receiverClass = null; + private ClassDescriptor thisClass = null; + + private FunctionDescriptor receiverFunction = null; private Type generateCalleeType = null; public CallableMethod(String owner, Method signature, int invokeOpcode, List valueParameterTypes) { @@ -45,11 +48,11 @@ public class CallableMethod implements Callable { return valueParameterTypes; } - public void setNeedsReceiver(@Nullable DeclarationDescriptor receiverClass) { - this.receiverClass = receiverClass; + public void setNeedsReceiver(@Nullable FunctionDescriptor receiverClass) { + this.receiverFunction = receiverClass; } - public void setNeedsThis(@Nullable DeclarationDescriptor receiverClass) { + public void setNeedsThis(@Nullable ClassDescriptor receiverClass) { this.thisClass = receiverClass; } @@ -78,10 +81,14 @@ public class CallableMethod implements Callable { } public boolean isNeedsReceiver() { - return receiverClass != null; + return receiverFunction != null; } - public DeclarationDescriptor getThisClass() { + public ClassDescriptor getThisClass() { return thisClass; } + + public FunctionDescriptor getReceiverFunction() { + return receiverFunction; + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 9bf2ec44d19..cf31230500f 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -45,6 +45,17 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { return new Method("invoke", JetTypeMapper.TYPE_OBJECT, args); } + public static CallableMethod asCallableMethod(FunctionDescriptor fd) { + Method descriptor = erasedInvokeSignature(fd); + String owner = getInternalClassName(fd); + final CallableMethod result = new CallableMethod(owner, descriptor, INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes())); + if (fd.getReceiverParameter().exists()) { + result.setNeedsReceiver(fd); + } + result.requestGenerateCallee(Type.getObjectType(getInternalClassName(fd))); + return result; + } + public Method invokeSignature(FunctionDescriptor fd) { return state.getTypeMapper().mapSignature("invoke", fd); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index ef3f606f1e3..c0664b192a2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.codegen; import com.intellij.psi.util.PsiTreeUtil; +import gnu.trove.THashSet; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.JetClass; @@ -13,6 +14,7 @@ import org.jetbrains.jet.lang.types.JetType; import java.util.Collections; import java.util.List; +import java.util.Set; /** * @author abreslav @@ -142,4 +144,29 @@ public class CodegenUtil { Modality.FINAL, Visibility.PUBLIC); return invokeDescriptor; } + + public static boolean isSubclass(ClassDescriptor subClass, ClassDescriptor superClass) { + Set allSuperTypes = new THashSet(); + + addSuperTypes(subClass.getDefaultType(), allSuperTypes); + + final DeclarationDescriptor superOriginal = superClass.getOriginal(); + + for (JetType superType : allSuperTypes) { + final DeclarationDescriptor descriptor = superType.getConstructor().getDeclarationDescriptor(); + if (descriptor != null && superOriginal.equals(descriptor.getOriginal())) { + return true; + } + } + + return false; + } + + private static void addSuperTypes(JetType type, Set set) { + set.add(type); + + for (JetType jetType : type.getConstructor().getSupertypes()) { + addSuperTypes(jetType, set); + } + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 67857237d6b..cc0ab13431e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -4,7 +4,6 @@ import com.intellij.openapi.editor.Document; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; -import gnu.trove.THashSet; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod; import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods; @@ -15,7 +14,10 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.calls.*; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lexer.JetTokens; import org.objectweb.asm.Label; @@ -27,8 +29,6 @@ import org.objectweb.asm.commons.Method; import java.util.*; -import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; - /** * @author max * @author yole @@ -79,17 +79,6 @@ public class ExpressionCodegen extends JetVisitor { this.intrinsics = state.getIntrinsics(); } - private static CallableMethod asCallableMethod(FunctionDescriptor fd) { - Method descriptor = ClosureCodegen.erasedInvokeSignature(fd); - String owner = ClosureCodegen.getInternalClassName(fd); - final CallableMethod result = new CallableMethod(owner, descriptor, INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes())); - if (fd.getReceiverParameter().exists()) { - result.setNeedsReceiver(fd.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor()); - } - result.requestGenerateCallee(Type.getObjectType(ClosureCodegen.getInternalClassName(fd))); - return result; - } - public GenerationState getState() { return state; } @@ -1021,7 +1010,9 @@ public class ExpressionCodegen extends JetVisitor { if (expression.getParent() instanceof JetQualifiedExpression) { final JetExpression receiverExpression = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression(); if (receiverExpression instanceof JetSuperExpression) { + assert receiver == StackValue.none(); superCall = true; + receiver = StackValue.thisOrOuter(this, context.getThisDescriptor()); JetSuperExpression superExpression = (JetSuperExpression) receiverExpression; PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel()); ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement); @@ -1033,17 +1024,13 @@ public class ExpressionCodegen extends JetVisitor { } fd = c.getAccessor(fd); superCall = false; + receiver = StackValue.thisOrOuter(this, enclosed); } } } } - Callable callableMethod = resolveToCallable(fd, superCall); - return invokeCallable(fd, callableMethod, expression, receiver); - } - - @Nullable - private StackValue invokeCallable(DeclarationDescriptor fd, Callable callable, JetCallExpression expression, StackValue receiver) { + Callable callable = resolveToCallable(fd, superCall); if (callable instanceof CallableMethod) { final CallableMethod callableMethod = (CallableMethod) callable; invokeMethodWithArguments(callableMethod, expression, receiver); @@ -1079,11 +1066,11 @@ public class ExpressionCodegen extends JetVisitor { CallableMethod callableMethod; if (fd instanceof VariableAsFunctionDescriptor) { assert !superCall; - callableMethod = asCallableMethod((FunctionDescriptor) fd); + callableMethod = ClosureCodegen.asCallableMethod((FunctionDescriptor) fd); } else if (fd instanceof ExpressionAsFunctionDescriptor) { FunctionDescriptor invoke = CodegenUtil.createInvoke((ExpressionAsFunctionDescriptor) fd); - callableMethod = asCallableMethod(invoke); + callableMethod = ClosureCodegen.asCallableMethod(invoke); } else if (fd instanceof FunctionDescriptor) { callableMethod = typeMapper.mapToCallableMethod((FunctionDescriptor) fd, superCall, OwnerKind.IMPLEMENTATION); @@ -1108,17 +1095,30 @@ public class ExpressionCodegen extends JetVisitor { public void invokeMethodWithArguments(CallableMethod callableMethod, JetCallElement expression, StackValue receiver) { final Type calleeType = callableMethod.getGenerateCalleeType(); if (calleeType != null && expression instanceof JetCallExpression) { + assert !callableMethod.isNeedsThis(); gen(expression.getCalleeExpression(), calleeType); } + ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression()); + assert resolvedCall != null; + + FunctionDescriptor callableDescriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); + boolean hasThis = resolvedCall.getThisObject().exists(); + boolean hasReceiver = resolvedCall.getReceiverArgument().exists(); + if (callableMethod.isNeedsThis()) { if(callableMethod.isNeedsReceiver()) { - generateThisOrOuter((ClassDescriptor) callableMethod.getThisClass()).put(JetTypeMapper.TYPE_OBJECT, v); - receiver.put(JetTypeMapper.TYPE_OBJECT, v); + generateFromResolvedCall(resolvedCall.getThisObject()); + if(receiver == StackValue.none()) { + generateFromResolvedCall(resolvedCall.getReceiverArgument()); + } + else { + receiver.put(typeMapper.mapType(callableMethod.getReceiverFunction().getReceiverParameter().getType()), v); + } } else { if (receiver == StackValue.none()) { - generateThisOrOuter((ClassDescriptor) callableMethod.getThisClass()).put(JetTypeMapper.TYPE_OBJECT, v); + generateFromResolvedCall(resolvedCall.getThisObject()); } else { receiver.put(JetTypeMapper.TYPE_OBJECT, v); @@ -1128,13 +1128,13 @@ public class ExpressionCodegen extends JetVisitor { else { if (callableMethod.isNeedsReceiver()) { if (receiver == StackValue.none()) { - v.load(0, JetTypeMapper.TYPE_OBJECT); + generateFromResolvedCall(resolvedCall.getReceiverArgument()); } else receiver.put(callableMethod.getSignature().getArgumentTypes()[0], v); } } - + int mask = pushMethodArguments(expression, callableMethod.getValueParameterTypes()); pushTypeArguments(expression); if(mask == 0) @@ -1143,6 +1143,24 @@ public class ExpressionCodegen extends JetVisitor { callableMethod.invokeWithDefault(v, mask); } + private void generateFromResolvedCall(ReceiverDescriptor descriptor) { + if(descriptor instanceof ClassReceiver) { + ClassReceiver classReceiver = (ClassReceiver) descriptor; + generateThisOrOuter((ClassDescriptor) classReceiver.getDeclarationDescriptor()).put(typeMapper.mapType(descriptor.getType()), v); + } + else if(descriptor instanceof ExtensionReceiver) { + ExtensionReceiver extensionReceiver = (ExtensionReceiver) descriptor; + generateReceiver((FunctionDescriptor) extensionReceiver.getDeclarationDescriptor()).put(typeMapper.mapType(descriptor.getType()), v); + } + else if(descriptor instanceof ExpressionReceiver) { + ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor; + genToJVMStack(expressionReceiver.getExpression()); + } + else { + throw new UnsupportedOperationException(); + } + } + private static JetExpression getReceiverForSelector(PsiElement expression) { if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) { final JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent(); @@ -1151,31 +1169,6 @@ public class ExpressionCodegen extends JetVisitor { return null; } - private static boolean isSubclass(ClassDescriptor subClass, ClassDescriptor superClass) { - Set allSuperTypes = new THashSet(); - - addSuperTypes(subClass.getDefaultType(), allSuperTypes); - - final DeclarationDescriptor superOriginal = superClass.getOriginal(); - - for (JetType superType : allSuperTypes) { - final DeclarationDescriptor descriptor = superType.getConstructor().getDeclarationDescriptor(); - if (descriptor != null && superOriginal.equals(descriptor.getOriginal())) { - return true; - } - } - - return false; - } - - private static void addSuperTypes(JetType type, Set set) { - set.add(type); - - for (JetType jetType : type.getConstructor().getSupertypes()) { - addSuperTypes(jetType, set); - } - } - private StackValue generateReceiver(FunctionDescriptor descriptor) { assert context instanceof CodegenContext.FunctionContext; CodegenContext.FunctionContext cur = (CodegenContext.FunctionContext) context; @@ -1184,21 +1177,6 @@ public class ExpressionCodegen extends JetVisitor { } return context.lookupInContext(descriptor, v, StackValue.local(0, JetTypeMapper.TYPE_OBJECT)); -// assert context instanceof CodegenContext.FunctionContext; -// CodegenContext.FunctionContext cur = (CodegenContext.FunctionContext) context; -// -// StackValue result = StackValue.local(0, JetTypeMapper.TYPE_OBJECT); -// while (cur != null) { -// -// if (cur.getReceiverDescriptor() == descriptor) { -// return cur.getReceiverExpression(typeMapper); -// } -// -// result = cur.getOuterExpression(result); -// cur = cur.getOuterFunction(); -// } -// -// throw new UnsupportedOperationException("Don't know how to generate receiver for " + descriptor); } public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) { @@ -1209,7 +1187,7 @@ public class ExpressionCodegen extends JetVisitor { if(cur instanceof CodegenContext.MethodContext && !(cur instanceof CodegenContext.ConstructorContext)) cur = cur.getParentContext(); - if (isSubclass(cur.getThisDescriptor(), calleeContainingClass)) { + if (CodegenUtil.isSubclass(cur.getThisDescriptor(), calleeContainingClass)) { Type type = typeMapper.mapType(calleeContainingClass.getDefaultType()); result.put(JetTypeMapper.TYPE_OBJECT, v); return StackValue.onStack(type); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 6b32d78a506..9fd4a054e5b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -341,7 +341,7 @@ public class JetTypeMapper { if(isInterface && superCall) { descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, OwnerKind.TRAIT_IMPL); } - thisClass = containingClass; + thisClass = (ClassDescriptor) functionParent; } else { throw new UnsupportedOperationException("unknown function parent"); @@ -350,7 +350,7 @@ public class JetTypeMapper { final CallableMethod result = new CallableMethod(owner, descriptor, invokeOpcode, valueParameterTypes); result.setNeedsThis(thisClass); if(functionDescriptor.getReceiverParameter().exists()) { - result.setNeedsReceiver(functionDescriptor.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor()); + result.setNeedsReceiver(functionDescriptor); } return result; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 9c2431d3981..71f0f2e982a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.codegen; import com.intellij.psi.tree.IElementType; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lexer.JetTokens; import org.objectweb.asm.Label; @@ -239,6 +240,10 @@ public abstract class StackValue { return new Composed(prefix, suffix); } + public static StackValue thisOrOuter(ExpressionCodegen codegen, ClassDescriptor descriptor) { + return new ThisOuter(codegen, descriptor); + } + private static class None extends StackValue { public static None INSTANCE = new None(); private None() { @@ -817,4 +822,20 @@ public abstract class StackValue { suffix.store(v); } } + + private static class ThisOuter extends StackValue { + private ExpressionCodegen codegen; + private ClassDescriptor descriptor; + + public ThisOuter(ExpressionCodegen codegen, ClassDescriptor descriptor) { + super(JetTypeMapper.TYPE_OBJECT); + this.codegen = codegen; + this.descriptor = descriptor; + } + + @Override + public void put(Type type, InstructionAdapter v) { + codegen.generateThisOrOuter(descriptor); + } + } }