From 59c04bd4cf38b503825c7d8174e1d8094337fdab Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Wed, 18 Sep 2013 15:41:12 +0400 Subject: [PATCH] Do direct call to local functions, inplace closures, and callable references (not via bridge method) --- .../jet/codegen/ExpressionCodegen.java | 24 ++++------------ .../jet/codegen/state/JetTypeMapper.java | 28 +++++++++++++++---- .../jet/lang/resolve/calls/CallResolver.java | 5 ++-- .../util/ExpressionAsFunctionDescriptor.java | 11 +++++++- .../BasicExpressionTypingVisitor.java | 9 ++++-- 5 files changed, 46 insertions(+), 31 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 74a886b823e..776ef846f0c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -2095,22 +2095,11 @@ public class ExpressionCodegen extends JetVisitor implem } private boolean isCallAsFunctionObject(FunctionDescriptor fd) { - if (fd.getContainingDeclaration() instanceof ScriptDescriptor) { - JetNamedFunction psi = (JetNamedFunction) descriptorToDeclaration(bindingContext, fd); - assert psi != null; - return !JetPsiUtil.isScriptDeclaration(psi); - } - else if (fd instanceof ExpressionAsFunctionDescriptor) { - return true; - } - else if (fd instanceof SimpleFunctionDescriptor && - (fd.getContainingDeclaration() instanceof FunctionDescriptor || - fd.getContainingDeclaration() instanceof ScriptDescriptor)) { - return true; - } - else { - return false; + if (fd instanceof ExpressionAsFunctionDescriptor) { + JetExpression deparenthesize = JetPsiUtil.deparenthesize(((ExpressionAsFunctionDescriptor) fd).getExpression()); + return !(deparenthesize instanceof JetCallableReferenceExpression || deparenthesize instanceof JetFunctionLiteralExpression); } + return false; } @@ -2134,9 +2123,6 @@ public class ExpressionCodegen extends JetVisitor implem if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); receiver.put(receiver.type, v); - if (calleeType != null) { - StackValue.onStack(receiver.type).put(boxType(receiver.type), v); - } } pushArgumentsAndInvoke(resolvedCall, callableMethod); @@ -3037,7 +3023,7 @@ public class ExpressionCodegen extends JetVisitor implem private StackValue invokeOperation(JetOperationExpression expression, FunctionDescriptor op, CallableMethod callable) { int functionLocalIndex = lookupLocalIndex(op); if (functionLocalIndex >= 0) { - stackValueForLocal(op, functionLocalIndex).put(getFunctionImplClassName(op).getAsmType(), v); + stackValueForLocal(op, functionLocalIndex).put(callable.getOwner().getAsmType(), v); } ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java index 8d4e64ad9b5..eb4fcb77b44 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java @@ -31,13 +31,12 @@ import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind; import org.jetbrains.jet.codegen.signature.JvmMethodParameterSignature; import org.jetbrains.jet.codegen.signature.JvmMethodSignature; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall; -import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor; import org.jetbrains.jet.lang.resolve.java.*; import org.jetbrains.jet.lang.resolve.java.mapping.KotlinToJavaTypesMap; import org.jetbrains.jet.lang.resolve.name.Name; @@ -55,6 +54,7 @@ import static org.jetbrains.jet.codegen.AsmUtil.getTraitImplThisParameterType; import static org.jetbrains.jet.codegen.CodegenUtil.*; import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionTraitClassName; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; +import static org.jetbrains.jet.codegen.binding.CodegenBinding.classNameForAnonymousClass; public class JetTypeMapper extends BindingTraceAware { @@ -487,7 +487,25 @@ public class JetTypeMapper extends BindingTraceAware { JvmClassName ownerForDefaultParam; int invokeOpcode; JvmClassName thisClass; - if (functionParent instanceof NamespaceDescriptor) { + Type calleeType = null; + + if (isLocalNamedFun(functionDescriptor) || functionDescriptor instanceof ExpressionAsFunctionDescriptor) { + if (functionDescriptor instanceof ExpressionAsFunctionDescriptor) { + JetExpression expression = JetPsiUtil.deparenthesize(((ExpressionAsFunctionDescriptor) functionDescriptor).getExpression()); + if (expression instanceof JetFunctionLiteralExpression) { + expression = ((JetFunctionLiteralExpression) expression).getFunctionLiteral(); + } + functionDescriptor = bindingContext.get(BindingContext.FUNCTION, expression); + } + functionDescriptor = functionDescriptor.getOriginal(); + + owner = classNameForAnonymousClass(bindingContext, functionDescriptor); + ownerForDefaultImpl = ownerForDefaultParam = thisClass = owner; + invokeOpcode = INVOKEVIRTUAL; + descriptor = mapSignature("invoke", functionDescriptor, true, kind); + calleeType = owner.getAsmType(); + } + else if (functionParent instanceof NamespaceDescriptor) { assert !superCall; owner = jvmClassNameForNamespace((NamespaceDescriptor) functionParent, functionDescriptor, isInsideModule); ownerForDefaultImpl = ownerForDefaultParam = owner; @@ -571,7 +589,7 @@ public class JetTypeMapper extends BindingTraceAware { } return new CallableMethod( owner, ownerForDefaultImpl, ownerForDefaultParam, descriptor, invokeOpcode, - thisClass, receiverParameterType, null); + thisClass, receiverParameterType, calleeType); } public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 86656683bf5..5af3f85a9ed 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -56,8 +56,7 @@ import java.util.List; import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER; import static org.jetbrains.jet.lang.diagnostics.Errors.*; -import static org.jetbrains.jet.lang.resolve.BindingContext.NON_DEFAULT_EXPRESSION_DATA_FLOW; -import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLUTION_SCOPE; +import static org.jetbrains.jet.lang.resolve.BindingContext.*; import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS; import static org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults.Code.*; import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER; @@ -245,7 +244,7 @@ public class CallResolver { return checkArgumentTypesAndFail(context); } - FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), Name.special("")); + FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), Name.special(""), calleeExpression); FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER_PARAMETER, Modality.FINAL, Visibilities.LOCAL); ResolutionCandidate resolutionCandidate = ResolutionCandidate.create(functionDescriptor, JetPsiUtil.isSafeCall(context.call)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/util/ExpressionAsFunctionDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/util/ExpressionAsFunctionDescriptor.java index acc8f15fb24..db5ec4d956a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/util/ExpressionAsFunctionDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/util/ExpressionAsFunctionDescriptor.java @@ -20,13 +20,18 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorImpl; +import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.resolve.name.Name; import java.util.Collections; public class ExpressionAsFunctionDescriptor extends FunctionDescriptorImpl { - public ExpressionAsFunctionDescriptor(DeclarationDescriptor containingDeclaration, Name name) { + + private final JetExpression expression; + + public ExpressionAsFunctionDescriptor(DeclarationDescriptor containingDeclaration, Name name, JetExpression expression) { super(containingDeclaration, Collections.emptyList(), name, Kind.DECLARATION); + this.expression = expression; } @Override @@ -39,4 +44,8 @@ public class ExpressionAsFunctionDescriptor extends FunctionDescriptorImpl { public FunctionDescriptor copy(DeclarationDescriptor newOwner, Modality modality, Visibility visibility, Kind kind, boolean copyOverrides) { throw new IllegalStateException(); } + + public JetExpression getExpression() { + return expression; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 2fa9a9fc115..f2b794b0970 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -26,6 +26,7 @@ import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.lang.PlatformToKotlinClassMap; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.*; @@ -507,13 +508,15 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { receiverParameter != null ); - ExpressionAsFunctionDescriptor functionDescriptor = new ExpressionAsFunctionDescriptor( + AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor( context.scope.getContainingDeclaration(), - Name.special("") - ); + Collections.emptyList(), + CallableMemberDescriptor.Kind.DECLARATION); + FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, type, null, Modality.FINAL, Visibilities.PUBLIC); context.trace.record(CALLABLE_REFERENCE, expression, functionDescriptor); + context.trace.record(FUNCTION, expression, functionDescriptor); return type; }