Do direct call to local functions, inplace closures, and callable references (not via bridge method)

This commit is contained in:
Mikhael Bogdanov
2013-09-18 15:41:12 +04:00
parent ebecc7b8ac
commit 59c04bd4cf
5 changed files with 46 additions and 31 deletions
@@ -2095,22 +2095,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
} }
private boolean isCallAsFunctionObject(FunctionDescriptor fd) { private boolean isCallAsFunctionObject(FunctionDescriptor fd) {
if (fd.getContainingDeclaration() instanceof ScriptDescriptor) { if (fd instanceof ExpressionAsFunctionDescriptor) {
JetNamedFunction psi = (JetNamedFunction) descriptorToDeclaration(bindingContext, fd); JetExpression deparenthesize = JetPsiUtil.deparenthesize(((ExpressionAsFunctionDescriptor) fd).getExpression());
assert psi != null; return !(deparenthesize instanceof JetCallableReferenceExpression || deparenthesize instanceof JetFunctionLiteralExpression);
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;
} }
return false;
} }
@@ -2134,9 +2123,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already
receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod);
receiver.put(receiver.type, v); receiver.put(receiver.type, v);
if (calleeType != null) {
StackValue.onStack(receiver.type).put(boxType(receiver.type), v);
}
} }
pushArgumentsAndInvoke(resolvedCall, callableMethod); pushArgumentsAndInvoke(resolvedCall, callableMethod);
@@ -3037,7 +3023,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
private StackValue invokeOperation(JetOperationExpression expression, FunctionDescriptor op, CallableMethod callable) { private StackValue invokeOperation(JetOperationExpression expression, FunctionDescriptor op, CallableMethod callable) {
int functionLocalIndex = lookupLocalIndex(op); int functionLocalIndex = lookupLocalIndex(op);
if (functionLocalIndex >= 0) { if (functionLocalIndex >= 0) {
stackValueForLocal(op, functionLocalIndex).put(getFunctionImplClassName(op).getAsmType(), v); stackValueForLocal(op, functionLocalIndex).put(callable.getOwner().getAsmType(), v);
} }
ResolvedCall<? extends CallableDescriptor> resolvedCall = ResolvedCall<? extends CallableDescriptor> resolvedCall =
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
@@ -31,13 +31,12 @@ import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
import org.jetbrains.jet.codegen.signature.JvmMethodParameterSignature; import org.jetbrains.jet.codegen.signature.JvmMethodParameterSignature;
import org.jetbrains.jet.codegen.signature.JvmMethodSignature; import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; 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.*;
import org.jetbrains.jet.lang.resolve.java.mapping.KotlinToJavaTypesMap; import org.jetbrains.jet.lang.resolve.java.mapping.KotlinToJavaTypesMap;
import org.jetbrains.jet.lang.resolve.name.Name; 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.CodegenUtil.*;
import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionTraitClassName; import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionTraitClassName;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.classNameForAnonymousClass;
public class JetTypeMapper extends BindingTraceAware { public class JetTypeMapper extends BindingTraceAware {
@@ -487,7 +487,25 @@ public class JetTypeMapper extends BindingTraceAware {
JvmClassName ownerForDefaultParam; JvmClassName ownerForDefaultParam;
int invokeOpcode; int invokeOpcode;
JvmClassName thisClass; 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; assert !superCall;
owner = jvmClassNameForNamespace((NamespaceDescriptor) functionParent, functionDescriptor, isInsideModule); owner = jvmClassNameForNamespace((NamespaceDescriptor) functionParent, functionDescriptor, isInsideModule);
ownerForDefaultImpl = ownerForDefaultParam = owner; ownerForDefaultImpl = ownerForDefaultParam = owner;
@@ -571,7 +589,7 @@ public class JetTypeMapper extends BindingTraceAware {
} }
return new CallableMethod( return new CallableMethod(
owner, ownerForDefaultImpl, ownerForDefaultParam, descriptor, invokeOpcode, owner, ownerForDefaultImpl, ownerForDefaultParam, descriptor, invokeOpcode,
thisClass, receiverParameterType, null); thisClass, receiverParameterType, calleeType);
} }
public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) { public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
@@ -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.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
import static org.jetbrains.jet.lang.diagnostics.Errors.*; 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.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLUTION_SCOPE;
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS; 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.calls.results.OverloadResolutionResults.Code.*;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER; import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
@@ -245,7 +244,7 @@ public class CallResolver {
return checkArgumentTypesAndFail(context); return checkArgumentTypesAndFail(context);
} }
FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), Name.special("<for expression " + calleeExpression.getText() + ">")); FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), Name.special("<for expression " + calleeExpression.getText() + ">"), calleeExpression);
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER_PARAMETER, Modality.FINAL, FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER_PARAMETER, Modality.FINAL,
Visibilities.LOCAL); Visibilities.LOCAL);
ResolutionCandidate<CallableDescriptor> resolutionCandidate = ResolutionCandidate.<CallableDescriptor>create(functionDescriptor, JetPsiUtil.isSafeCall(context.call)); ResolutionCandidate<CallableDescriptor> resolutionCandidate = ResolutionCandidate.<CallableDescriptor>create(functionDescriptor, JetPsiUtil.isSafeCall(context.call));
@@ -20,13 +20,18 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorImpl; import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorImpl;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Collections; import java.util.Collections;
public class ExpressionAsFunctionDescriptor extends FunctionDescriptorImpl { 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.<AnnotationDescriptor>emptyList(), name, Kind.DECLARATION); super(containingDeclaration, Collections.<AnnotationDescriptor>emptyList(), name, Kind.DECLARATION);
this.expression = expression;
} }
@Override @Override
@@ -39,4 +44,8 @@ public class ExpressionAsFunctionDescriptor extends FunctionDescriptorImpl {
public FunctionDescriptor copy(DeclarationDescriptor newOwner, Modality modality, Visibility visibility, Kind kind, boolean copyOverrides) { public FunctionDescriptor copy(DeclarationDescriptor newOwner, Modality modality, Visibility visibility, Kind kind, boolean copyOverrides) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
public JetExpression getExpression() {
return expression;
}
} }
@@ -26,6 +26,7 @@ import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.PlatformToKotlinClassMap; import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 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.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.*;
@@ -507,13 +508,15 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
receiverParameter != null receiverParameter != null
); );
ExpressionAsFunctionDescriptor functionDescriptor = new ExpressionAsFunctionDescriptor( AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
context.scope.getContainingDeclaration(), context.scope.getContainingDeclaration(),
Name.special("<callable-reference>") Collections.<AnnotationDescriptor>emptyList(),
); CallableMemberDescriptor.Kind.DECLARATION);
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, type, null, Modality.FINAL, Visibilities.PUBLIC); FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, type, null, Modality.FINAL, Visibilities.PUBLIC);
context.trace.record(CALLABLE_REFERENCE, expression, functionDescriptor); context.trace.record(CALLABLE_REFERENCE, expression, functionDescriptor);
context.trace.record(FUNCTION, expression, functionDescriptor);
return type; return type;
} }