From ba9c3d73e77dc6808596383be86e35c52bd3d92b Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Sat, 2 Jun 2012 19:50:14 +0200 Subject: [PATCH] when calling extension function, correctly put receiver on top of stack if it was generated before the extension function object (KT-1918) --- .../org/jetbrains/jet/codegen/StackValue.java | 39 ++++++++++++++++--- .../testData/codegen/regressions/kt1918.kt | 20 ++++++++++ .../jetbrains/jet/codegen/ClassGenTest.java | 5 +++ 3 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/codegen/regressions/kt1918.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index c4b0f896131..5138d5dc855 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -61,6 +61,18 @@ public abstract class StackValue { public abstract void put(Type type, InstructionAdapter v); + /** + * This method is called to put the value on the top of the JVM stack if depth other values have been put on the + * JVM stack after this value was generated. + * + * @param type the type as which the value should be put + * @param v the visitor used to generate the instructions + * @param depth the number of new values put onto the stack + */ + public void moveToTopOfStack(Type type, InstructionAdapter v, int depth) { + put(type, v); + } + public void store(InstructionAdapter v) { throw new UnsupportedOperationException("cannot store to value " + this); } @@ -341,6 +353,22 @@ public abstract class StackValue { coerce(type, v); } } + + @Override + public void moveToTopOfStack(Type type, InstructionAdapter v, int depth) { + if (depth == 0) { + put(type, v); + } + else if (depth == 1) { + if (type.getSize() != 1) { + throw new UnsupportedOperationException("don't know how to move type " + type + " to top of stack"); + } + v.swap(); + } + else { + throw new UnsupportedOperationException("unsupported move-to-top depth " + depth); + } + } } public static class Constant extends StackValue { @@ -1132,20 +1160,21 @@ public abstract class StackValue { else { codegen.generateFromResolvedCall(thisObject, codegen.typeMapper.mapType(descriptor.getExpectedThisObject().getType(), MapTypeMode.VALUE)); } - genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter()); + genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter(), 1); } else { - genReceiver(v, thisObject, type, null); + genReceiver(v, thisObject, type, null, 0); } } else { if (receiverArgument.exists()) { - genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter()); + genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter(), 0); } } } - private void genReceiver(InstructionAdapter v, ReceiverDescriptor receiverArgument, Type type, ReceiverDescriptor receiverParameter) { + private void genReceiver(InstructionAdapter v, ReceiverDescriptor receiverArgument, Type type, + @Nullable ReceiverDescriptor receiverParameter, int depth) { if(receiver == StackValue.none()) { if(receiverParameter != null) { Type receiverType = codegen.typeMapper.mapType(receiverParameter.getType(), MapTypeMode.VALUE); @@ -1157,7 +1186,7 @@ public abstract class StackValue { } } else { - receiver.put(type, v); + receiver.moveToTopOfStack(type, v, depth); } } } diff --git a/compiler/testData/codegen/regressions/kt1918.kt b/compiler/testData/codegen/regressions/kt1918.kt new file mode 100644 index 00000000000..7dabde92a46 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt1918.kt @@ -0,0 +1,20 @@ +class Bar { +} + +trait Foo { + fun xyzzy(x: Any?): String +} + +fun buildFoo(bar: Bar.() -> Unit): Foo { + return object : Foo { + override fun xyzzy(x: Any?): String { + (x as? Bar)?.bar() + return "OK" + } + } +} + +fun box(): String { + val foo = buildFoo({}) + return foo.xyzzy(Bar()) +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 89dd8c7c6b8..d612376f659 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -386,4 +386,9 @@ public class ClassGenTest extends CodegenTestCase { createEnvironmentWithMockJdkAndIdeaAnnotations(CompilerSpecialMode.JDK_HEADERS); blackBoxFile("classes/resolveOrder.jet"); } + + public void testKt1918() throws Exception { + createEnvironmentWithMockJdkAndIdeaAnnotations(CompilerSpecialMode.JDK_HEADERS); + blackBoxFile("regressions/kt1918.kt"); + } }