Move local fun callee generation to pushArgumentsWithCallReceiver.
Local fun callee generation via resolvedCall.resultingDescriptor not call
This commit is contained in:
@@ -1657,11 +1657,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = lookupLocalIndex(descriptor);
|
|
||||||
if (index >= 0) {
|
|
||||||
return stackValueForLocal(descriptor, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descriptor instanceof PropertyDescriptor) {
|
if (descriptor instanceof PropertyDescriptor) {
|
||||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||||
|
|
||||||
@@ -1708,26 +1703,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
return StackValue.onStack(OBJECT_TYPE);
|
return StackValue.onStack(OBJECT_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
StackValue value = context.lookupInContext(descriptor, StackValue.local(0, OBJECT_TYPE), state, false);
|
StackValue localOrCaptured = findLocalOrCapturedValue(descriptor);
|
||||||
if (value != null) {
|
if (localOrCaptured != null) {
|
||||||
if (context.isSpecialStackValue(value)) {
|
return localOrCaptured;
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value instanceof StackValue.Composed) {
|
|
||||||
StackValue.Composed composed = (StackValue.Composed) value;
|
|
||||||
composed.prefix.put(OBJECT_TYPE, v);
|
|
||||||
value = composed.suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value instanceof StackValue.FieldForSharedVar) {
|
|
||||||
StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value;
|
|
||||||
Type sharedType = StackValue.sharedTypeForType(value.type);
|
|
||||||
v.visitFieldInsn(GETFIELD, fieldForSharedVar.owner.getInternalName(), fieldForSharedVar.name,
|
|
||||||
sharedType.getDescriptor());
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor instanceof ValueParameterDescriptor && descriptor.getContainingDeclaration() instanceof ScriptDescriptor) {
|
if (descriptor instanceof ValueParameterDescriptor && descriptor.getContainingDeclaration() instanceof ScriptDescriptor) {
|
||||||
@@ -1744,6 +1722,37 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
|
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public StackValue findLocalOrCapturedValue(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
int index = lookupLocalIndex(descriptor);
|
||||||
|
if (index >= 0) {
|
||||||
|
return stackValueForLocal(descriptor, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
StackValue value = context.lookupInContext(descriptor, StackValue.local(0, OBJECT_TYPE), state, false);
|
||||||
|
if (value == null) return null;
|
||||||
|
|
||||||
|
if (context.isSpecialStackValue(value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value instanceof StackValue.Composed) {
|
||||||
|
StackValue.Composed composed = (StackValue.Composed) value;
|
||||||
|
composed.prefix.put(OBJECT_TYPE, v);
|
||||||
|
value = composed.suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value instanceof StackValue.FieldForSharedVar) {
|
||||||
|
StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value;
|
||||||
|
Type sharedType = StackValue.sharedTypeForType(value.type);
|
||||||
|
v.visitFieldInsn(GETFIELD, fieldForSharedVar.owner.getInternalName(), fieldForSharedVar.name,
|
||||||
|
sharedType.getDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) {
|
private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) {
|
||||||
if (descriptor instanceof VariableDescriptor) {
|
if (descriptor instanceof VariableDescriptor) {
|
||||||
Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
||||||
@@ -2010,25 +2019,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
Callable callable = resolveToCallable(accessibleFunctionDescriptor(fd), superCall);
|
Callable callable = resolveToCallable(accessibleFunctionDescriptor(fd), superCall);
|
||||||
|
|
||||||
if (callable instanceof CallableMethod) {
|
|
||||||
CallableMethod callableMethod = (CallableMethod) callable;
|
|
||||||
Type calleeType = callableMethod.getGenerateCalleeType();
|
|
||||||
if (calleeType != null) {
|
|
||||||
assert !callableMethod.isNeedsThis() : "Method should have a receiver: " + resolvedCall.getResultingDescriptor();
|
|
||||||
gen(call.getCalleeExpression(), calleeType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return invokeFunctionWithCalleeOnStack(call, receiver, resolvedCall, callable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private StackValue invokeFunctionWithCalleeOnStack(
|
|
||||||
@NotNull Call call,
|
|
||||||
@NotNull StackValue receiver,
|
|
||||||
@NotNull ResolvedCall<?> resolvedCall,
|
|
||||||
@NotNull Callable callable
|
|
||||||
) {
|
|
||||||
if (callable instanceof CallableMethod) {
|
if (callable instanceof CallableMethod) {
|
||||||
CallableMethod callableMethod = (CallableMethod) callable;
|
CallableMethod callableMethod = (CallableMethod) callable;
|
||||||
invokeMethodWithArguments(call, callableMethod, resolvedCall, receiver);
|
invokeMethodWithArguments(call, callableMethod, resolvedCall, receiver);
|
||||||
@@ -2287,6 +2277,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
) {
|
) {
|
||||||
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
|
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
|
||||||
|
|
||||||
|
//generate callee for local function
|
||||||
|
Type calleeType = callableMethod.getGenerateCalleeType();
|
||||||
|
if (calleeType != null) {
|
||||||
|
StackValue value = findLocalOrCapturedValue(descriptor.getOriginal());
|
||||||
|
assert value != null : "Local fun should be found in locals or in captured params: " + resolvedCall;
|
||||||
|
value.put(calleeType, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
//generate this (absent for local fun) and receiver
|
||||||
if (!(descriptor instanceof ConstructorDescriptor)) { // otherwise already
|
if (!(descriptor 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);
|
||||||
@@ -2530,12 +2529,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments);
|
Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments);
|
||||||
Callable callable = codegen.resolveToCallable(codegen.accessibleFunctionDescriptor(referencedFunction), false);
|
result = codegen.invokeFunction(call, StackValue.none(), fakeResolvedCall);
|
||||||
StackValue receiver = generateCallee(codegen, callable);
|
|
||||||
if (extensionReceiver.exists()) {
|
|
||||||
receiver = StackValue.composed(receiver, receiverParameterStackValue(signature));
|
|
||||||
}
|
|
||||||
result = codegen.invokeFunctionWithCalleeOnStack(call, receiver, fakeResolvedCall, callable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionAdapter v = codegen.v;
|
InstructionAdapter v = codegen.v;
|
||||||
@@ -2543,33 +2537,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
v.areturn(returnType);
|
v.areturn(returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private StackValue generateCallee(@NotNull ExpressionCodegen codegen, @NotNull Callable callable) {
|
|
||||||
if (!(callable instanceof CallableMethod) || ((CallableMethod) callable).getGenerateCalleeType() == null) {
|
|
||||||
return StackValue.none();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If referenced method is a CallableMethod with generateCalleeType != null, this means it's some kind of a closure
|
|
||||||
// (e.g. a local named function) and a non-trivial callee should be generated before calling invoke()
|
|
||||||
|
|
||||||
BindingContext bindingContext = codegen.bindingContext;
|
|
||||||
ClassDescriptor closureClassOfReferenced = bindingContext.get(CLASS_FOR_FUNCTION, referencedFunction);
|
|
||||||
MutableClosure closureOfReferenced = bindingContext.get(CLOSURE, closureClassOfReferenced);
|
|
||||||
assert closureOfReferenced != null :
|
|
||||||
"Function mapped to CallableMethod with generateCalleeType != null must be a closure: " + referencedFunction;
|
|
||||||
if (isConst(closureOfReferenced)) {
|
|
||||||
// This is an optimization: we can obtain an instance of a const closure simply by GETSTATIC ...$instance
|
|
||||||
// (instead of passing this instance to the constructor and storing as a field)
|
|
||||||
Type asmType = asmTypeForAnonymousClass(bindingContext, referencedFunction);
|
|
||||||
codegen.v.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor());
|
|
||||||
return StackValue.onStack(asmType);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Type asmCallRefType = asmTypeForAnonymousClass(bindingContext, callableDescriptor);
|
|
||||||
return codegen.context.lookupInContext(referencedFunction, StackValue.local(0, asmCallRefType), state, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JetCallExpression constructFakeFunctionCall() {
|
private JetCallExpression constructFakeFunctionCall() {
|
||||||
StringBuilder fakeFunctionCall = new StringBuilder("callableReferenceFakeCall(");
|
StringBuilder fakeFunctionCall = new StringBuilder("callableReferenceFakeCall(");
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
class T(val value: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun local() : Int {
|
||||||
|
|
||||||
|
fun T.get(s: Int): Int {
|
||||||
|
return s * this.value
|
||||||
|
}
|
||||||
|
|
||||||
|
var t = T(11)
|
||||||
|
return t[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
if (local() != 22) return "fail1 ${local()} "
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -2966,6 +2966,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest("compiler/testData/codegen/box/functions/localFunctions/kt4777.kt");
|
doTest("compiler/testData/codegen/box/functions/localFunctions/kt4777.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt4783.kt")
|
||||||
|
public void testKt4783() throws Exception {
|
||||||
|
doTest("compiler/testData/codegen/box/functions/localFunctions/kt4783.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("localFunctionInConstructor.kt")
|
@TestMetadata("localFunctionInConstructor.kt")
|
||||||
public void testLocalFunctionInConstructor() throws Exception {
|
public void testLocalFunctionInConstructor() throws Exception {
|
||||||
doTest("compiler/testData/codegen/box/functions/localFunctions/localFunctionInConstructor.kt");
|
doTest("compiler/testData/codegen/box/functions/localFunctions/localFunctionInConstructor.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user