From a8ca39754c76502a8d06d7d4c44ec0ea75d50d90 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 4 Nov 2014 11:38:28 +0400 Subject: [PATCH] Supported creating varargs of reified type parameter --- .../jet/codegen/ExpressionCodegen.java | 41 +++++++++++-------- .../jet/codegen/intrinsics/CopyToArray.java | 7 +++- .../boxWithStdlib/reified/copyToArray.kt | 15 +++++++ .../codegen/boxWithStdlib/reified/spreads.kt | 24 +++++++++++ .../codegen/boxWithStdlib/reified/varargs.kt | 26 ++++++++++++ ...lackBoxWithStdlibCodegenTestGenerated.java | 18 ++++++++ 6 files changed, 114 insertions(+), 17 deletions(-) create mode 100644 compiler/testData/codegen/boxWithStdlib/reified/copyToArray.kt create mode 100644 compiler/testData/codegen/boxWithStdlib/reified/spreads.kt create mode 100644 compiler/testData/codegen/boxWithStdlib/reified/varargs.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 9a1918b5d3c..559728500f3 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -373,10 +373,15 @@ public class ExpressionCodegen extends JetVisitor implem @NotNull public Type expressionType(JetExpression expression) { - JetType type = bindingContext.get(EXPRESSION_TYPE, expression); + JetType type = expressionJetType(expression); return type == null ? Type.VOID_TYPE : asmType(type); } + @Nullable + public JetType expressionJetType(JetExpression expression) { + return bindingContext.get(EXPRESSION_TYPE, expression); + } + @Override public StackValue visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, StackValue receiver) { return genQualified(receiver, expression.getExpression()); @@ -2525,14 +2530,14 @@ public class ExpressionCodegen extends JetVisitor implem } v.dup(); v.invokevirtual(owner, "size", "()I", false); - v.newarray(elementType); + newArrayInstruction(outType); v.invokevirtual(owner, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", false); v.checkcast(type); } } else { v.iconst(arguments.size()); - v.newarray(elementType); + newArrayInstruction(outType); for (int i = 0; i != size; ++i) { v.dup(); v.iconst(i); @@ -3460,19 +3465,8 @@ public class ExpressionCodegen extends JetVisitor implem throw new CompilationException("primitive array constructor requires one argument", null, expression); } - if (isArray) { - gen(args.get(0), Type.INT_TYPE); - putReifierMarkerIfTypeIsReifiedParameter( - arrayType.getArguments().get(0).getType(), - ReifiedTypeInliner.NEW_ARRAY_MARKER_METHOD_NAME - ); - v.newarray(boxType(asmType(arrayType.getArguments().get(0).getType()))); - } - else { - Type type = typeMapper.mapType(arrayType); - gen(args.get(0), Type.INT_TYPE); - v.newarray(correctElementType(type)); - } + gen(args.get(0), Type.INT_TYPE); + newArrayInstruction(arrayType); if (args.size() == 2) { int sizeIndex = myFrameMap.enterTemp(Type.INT_TYPE); @@ -3512,6 +3506,21 @@ public class ExpressionCodegen extends JetVisitor implem } } + public void newArrayInstruction(@NotNull JetType arrayType) { + if (KotlinBuiltIns.getInstance().isArray(arrayType)) { + JetType elementJetType = arrayType.getArguments().get(0).getType(); + putReifierMarkerIfTypeIsReifiedParameter( + elementJetType, + ReifiedTypeInliner.NEW_ARRAY_MARKER_METHOD_NAME + ); + v.newarray(boxType(asmType(elementJetType))); + } + else { + Type type = typeMapper.mapType(arrayType); + v.newarray(correctElementType(type)); + } + } + @Override public StackValue visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, StackValue receiver) { JetExpression array = expression.getArrayExpression(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/CopyToArray.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/CopyToArray.java index 836db85cced..d8eeddb1deb 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/CopyToArray.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/CopyToArray.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.codegen.intrinsics; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import org.jetbrains.jet.codegen.ExpressionCodegen; @@ -45,7 +46,11 @@ public class CopyToArray extends IntrinsicMethod { v.dup(); v.invokeinterface("java/util/Collection", "size", "()I"); - v.newarray(returnType.getElementType()); + assert element instanceof JetExpression; + JetType arrayType = codegen.expressionJetType((JetExpression) element); + assert arrayType != null; + + codegen.newArrayInstruction(arrayType); v.invokeinterface("java/util/Collection", "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;"); return getType(Object[].class); diff --git a/compiler/testData/codegen/boxWithStdlib/reified/copyToArray.kt b/compiler/testData/codegen/boxWithStdlib/reified/copyToArray.kt new file mode 100644 index 00000000000..a7eeae2b0c2 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/reified/copyToArray.kt @@ -0,0 +1,15 @@ +import kotlin.test.assertEquals + +inline fun copy(c: Collection): Array { + return c.copyToArray() +} + +fun box(): String { + val a: Array = copy(listOf("a", "b", "c")) + assertEquals("abc", a.join("")) + + val b: Array = copy(listOf(1,2,3)) + assertEquals("123", b.map { it.toString() }.join("")) + + return "OK" +} diff --git a/compiler/testData/codegen/boxWithStdlib/reified/spreads.kt b/compiler/testData/codegen/boxWithStdlib/reified/spreads.kt new file mode 100644 index 00000000000..fc378e6bd56 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/reified/spreads.kt @@ -0,0 +1,24 @@ +import kotlin.test.assertEquals + +fun foo(vararg a: T) = a.size + +inline fun bar(a: Array, block: () -> T): Array { + assertEquals(4, foo(*a, block(), block())) + + return array(*a, block(), block()) +} + +inline fun empty() = array() + +fun box(): String { + + var i = 0 + val a: Array = bar(array("1", "2")) { i++; i.toString() } + assertEquals("1234", a.join("")) + + i = 0 + val b: Array = bar(array(0, 1)) { i++ } + assertEquals("0123", b.map { it.toString() }.join("")) + + return "OK" +} diff --git a/compiler/testData/codegen/boxWithStdlib/reified/varargs.kt b/compiler/testData/codegen/boxWithStdlib/reified/varargs.kt new file mode 100644 index 00000000000..9b72bdb26c5 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/reified/varargs.kt @@ -0,0 +1,26 @@ +import kotlin.test.assertEquals + +fun foo(vararg a: T) = a.size + +inline fun bar(block: () -> T): Array { + assertEquals(2, foo(block(), block())) + + return array(block(), block(), block()) +} + +inline fun empty() = array() + +fun box(): String { + var i = 0 + val a: Array = bar() { i++; i.toString() } + assertEquals("345", a.join("")) + + i = 0 + val b: Array = bar() { i++ } + assertEquals("234", b.map { it.toString() }.join("")) + + val c: Array = empty() + assertEquals(0, c.size) + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index e549915cbbb..16d03f73cea 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -2471,6 +2471,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("copyToArray.kt") + public void testCopyToArray() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/copyToArray.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("defaultJavaClass.kt") public void testDefaultJavaClass() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/defaultJavaClass.kt"); @@ -2542,6 +2548,18 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/sameIndexRecursive.kt"); doTestWithStdlib(fileName); } + + @TestMetadata("spreads.kt") + public void testSpreads() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/spreads.kt"); + doTestWithStdlib(fileName); + } + + @TestMetadata("varargs.kt") + public void testVarargs() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/varargs.kt"); + doTestWithStdlib(fileName); + } } @TestMetadata("compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline")