diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationMethodVisitor.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationMethodVisitor.java index 1a3cde3710d..7a3f18d1785 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationMethodVisitor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationMethodVisitor.java @@ -36,7 +36,7 @@ public class OptimizationMethodVisitor extends MethodVisitor { private static final int MEMORY_LIMIT_BY_METHOD_MB = 50; private static final MethodTransformer[] TRANSFORMERS = new MethodTransformer[]{ new RedundantNullCheckMethodTransformer(), new RedundantBoxingMethodTransformer(), - new RedundantGotoMethodTransformer() + new RedundantGotoMethodTransformer(), new StoreStackBeforeInlineMethodTransformer() }; private final MethodNode methodNode; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/StoreStackBeforeInlineMethodTransformer.kt b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/StoreStackBeforeInlineMethodTransformer.kt new file mode 100644 index 00000000000..d1fae7c8ae4 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/StoreStackBeforeInlineMethodTransformer.kt @@ -0,0 +1,218 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.codegen.optimization + +import org.jetbrains.jet.codegen.optimization.transformer.MethodTransformer +import org.jetbrains.jet.codegen.optimization.common.OptimizationBasicInterpreter +import org.jetbrains.jet.codegen.inline.InlineCodegenUtil + +import org.jetbrains.org.objectweb.asm.tree.MethodNode +import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode +import org.jetbrains.org.objectweb.asm.tree.analysis.Frame +import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue +import org.jetbrains.org.objectweb.asm.tree.VarInsnNode +import org.jetbrains.org.objectweb.asm.Type +import com.intellij.util.containers.Stack + +class StoreStackBeforeInlineMethodTransformer : MethodTransformer() { + override fun transform(internalClassName: String, methodNode: MethodNode) { + val frames = MethodTransformer.analyze(internalClassName, methodNode, OptimizationBasicInterpreter()) + if (needToProcess(methodNode, frames)) { + process(methodNode, frames) + } + else { + removeInlineMarkers(methodNode) + } + } +} + +private fun needToProcess(node: MethodNode, frames: Array?>): Boolean { + val insns = node.instructions.toArray() + var balance = 0 + var isThereAnyInlineMarker = false + + for ((insn, frame) in insns.zip(frames)) { + if (isInlineMarker(insn)) { + isThereAnyInlineMarker = true + + // inline marker is not available + if (frame == null) return false + } + + if (isBeforeInlineMarker(insn)) { + balance++ + } + else if(isAfterInlineMarker(insn)) { + balance-- + } + + if (balance < 0) return false + } + + return balance == 0 && isThereAnyInlineMarker +} + +private fun isBeforeInlineMarker(insn: AbstractInsnNode) = isInlineMarker(insn, InlineCodegenUtil.INLINE_MARKER_BEFORE_METHOD_NAME) + +private fun isAfterInlineMarker(insn: AbstractInsnNode) = isInlineMarker(insn, InlineCodegenUtil.INLINE_MARKER_AFTER_METHOD_NAME) + +private fun isInlineMarker(insn: AbstractInsnNode, markerName: String? = null): Boolean { + return insn.getOpcode() == Opcodes.INVOKESTATIC && + insn is MethodInsnNode && + insn.owner == InlineCodegenUtil.INLINE_MARKER_CLASS_NAME && + if (markerName != null) markerName == insn.name else true +} + +private fun process(methodNode: MethodNode, frames: Array?>) { + val insns = methodNode.instructions.toArray() + + val storedValuesDescriptorsStack = Stack() + var firstAvailableVarIndex = methodNode.maxLocals + var currentStoredValuesCount = 0 + + for ((insn, frame) in insns.zip(frames)) { + if (isBeforeInlineMarker(insn)) { + frame ?: throw AssertionError("process method shouldn't be called if frame is null before inline marker") + + val desc = storeStackValues(methodNode, frame, insn, firstAvailableVarIndex, currentStoredValuesCount) + + firstAvailableVarIndex += desc.storedStackSize + currentStoredValuesCount += desc.storedValuesCount + storedValuesDescriptorsStack.push(desc) + } + else if (isAfterInlineMarker(insn)) { + frame ?: throw AssertionError("process method shouldn't be called if frame is null before inline marker") + + val desc = storedValuesDescriptorsStack.pop() ?: + throw AssertionError("should be non null becase markers are balanced") + + loadStackValues(methodNode, frame, insn, desc) + firstAvailableVarIndex -= desc.storedStackSize + currentStoredValuesCount -= desc.storedValuesCount + } + + if (isInlineMarker(insn)) { + methodNode.instructions.remove(insn) + } + } +} + +private class StoredStackValuesDescriptor( + val values: List, + val firstVariableIndex: Int, + val storedStackSize: Int, + alreadyStoredValuesCount: Int +) { + val nextFreeVarIndex : Int get() = firstVariableIndex + storedStackSize + val storedValuesCount: Int get() = values.size + val isStored: Boolean get() = storedValuesCount > 0 + val totalValuesCountOnStackBeforeInline = alreadyStoredValuesCount + storedValuesCount +} + +private fun removeInlineMarkers(node: MethodNode) { + for (insn in node.instructions.toArray()) { + if (isInlineMarker(insn)) { + node.instructions.remove(insn) + } + } +} + +private fun storeStackValues( + node: MethodNode, + frame: Frame, + beforeInlineMarker: AbstractInsnNode, + firstAvailableVarIndex: Int, + alreadyStoredValuesCount: Int +) : StoredStackValuesDescriptor { + var stackSize = 0 + + val values = frame.getStackValuesStartingFrom(alreadyStoredValuesCount) + + for (value in values.reverse()) { + node.instructions.insertBefore( + beforeInlineMarker, + VarInsnNode( + value.getType()!!.getOpcode(Opcodes.ISTORE), + firstAvailableVarIndex + stackSize + ) + ) + stackSize += value.getSize() + } + + node.updateMaxLocals(firstAvailableVarIndex + stackSize) + + return StoredStackValuesDescriptor(values, firstAvailableVarIndex, stackSize, alreadyStoredValuesCount) +} + +private fun loadStackValues( + node: MethodNode, + frame: Frame, + afterInlineMarker: AbstractInsnNode, + desc: StoredStackValuesDescriptor +) { + if (!desc.isStored) return + + val insns = node.instructions + var returnValueVarIndex = -1 + var returnType : Type? = null + + if (frame.getStackSize() != desc.totalValuesCountOnStackBeforeInline) { + // only returned value + assert( + (frame.getStackSize() - desc.totalValuesCountOnStackBeforeInline) == 1, + "Stack sizes should not differ by more than 1 (returned value)" + ) + + returnValueVarIndex = desc.nextFreeVarIndex + returnType = frame.getStack(frame.getStackSize() - 1)!!.getType() + node.updateMaxLocals(returnValueVarIndex + returnType!!.getSize()) + + insns.insertBefore( + afterInlineMarker, + VarInsnNode(returnType!!.getOpcode(Opcodes.ISTORE), returnValueVarIndex) + ) + } + + var currentVarIndex = desc.firstVariableIndex + desc.storedStackSize + + for (value in desc.values) { + currentVarIndex -= value.getSize() + insns.insertBefore( + afterInlineMarker, + VarInsnNode( + value.getType()!!.getOpcode(Opcodes.ILOAD), + currentVarIndex + ) + ) + } + + if (returnValueVarIndex != -1) { + insns.insertBefore( + afterInlineMarker, + VarInsnNode(returnType!!.getOpcode(Opcodes.ILOAD), returnValueVarIndex) + ) + } +} + +private fun Frame.getStackValuesStartingFrom(from: Int): List = + IntRange(from, getStackSize() - 1).map { getStack(it) }.requireNoNulls() + +private fun MethodNode.updateMaxLocals(newMaxLocals: Int) { + maxLocals = Math.max(maxLocals, newMaxLocals) +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/transformer/MethodTransformer.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/transformer/MethodTransformer.java index 2de3633cef4..c95fe66a95d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/transformer/MethodTransformer.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/transformer/MethodTransformer.java @@ -16,12 +16,15 @@ package org.jetbrains.jet.codegen.optimization.transformer; +import kotlin.jvm.KotlinSignature; import org.jetbrains.annotations.NotNull; import org.jetbrains.org.objectweb.asm.tree.MethodNode; import org.jetbrains.org.objectweb.asm.tree.analysis.*; public abstract class MethodTransformer { + @KotlinSignature("fun runAnalyzer(analyzer: Analyzer, internalClassName: String, node: MethodNode): Array?>") + @NotNull protected static Frame[] runAnalyzer( @NotNull Analyzer analyzer, @NotNull String internalClassName, @@ -34,6 +37,9 @@ public abstract class MethodTransformer { throw new RuntimeException(e); } } + + @KotlinSignature("fun analyze(internalClassName: String, node: MethodNode, interpreter: Interpreter): Array?>") + @NotNull protected static Frame[] analyze( @NotNull String internalClassName, @NotNull MethodNode node, diff --git a/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/differentTypes.kt b/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/differentTypes.kt new file mode 100644 index 00000000000..c41967e3ed5 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/differentTypes.kt @@ -0,0 +1,14 @@ +import kotlin.test.assertEquals + +inline fun bar(x: Int, y: Long, z: Byte, s: String) = x.toString() + y.toString() + z.toString() + s + +fun foobar(x: Int, y: Long, s: String, z: Byte) = x.toString() + y.toString() + s + z.toString() + +fun foo() : String { + return foobar(1, 2L, bar(3, 4L, 5.toByte(), "6"), 7.toByte()) +} + +fun box() : String { + assertEquals("1234567", foo()) + return "OK" +} diff --git a/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/primitiveMerge.kt b/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/primitiveMerge.kt new file mode 100644 index 00000000000..749ef9ea6f4 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/primitiveMerge.kt @@ -0,0 +1,16 @@ +import kotlin.test.assertEquals + +fun bar() : Boolean = true + +fun foobar1(x: Boolean, y: String, z: String) = x.toString() + y + z +fun foobar2(x: Any, y: String, z: String) = x.toString() + y + z + +inline fun foo() = "-" + +fun box(): String { + val result1 = foobar1(if (1 == 1) true else bar(), foo(), "OK") + val result2 = foobar2(if (1 == 1) "true" else array("false"), foo(), "OK") + assertEquals("true-OK", result1) + assertEquals("true-OK", result2) + return "OK" +} diff --git a/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/simple.kt b/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/simple.kt new file mode 100644 index 00000000000..23867793db6 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/simple.kt @@ -0,0 +1,16 @@ +import kotlin.test.assertEquals + +inline fun bar(x: Int) : Int { + return x +} + +fun foobar(x: Int, y: Int, z: Int) = x + y + z + +fun foo() : Int { + return foobar(1, bar(2), 3) +} + +fun box() : String { + assertEquals(6, foo()) + return "OK" +} diff --git a/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/unreachableMarker.kt b/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/unreachableMarker.kt new file mode 100644 index 00000000000..e2b0aa8d959 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/unreachableMarker.kt @@ -0,0 +1,24 @@ +import kotlin.test.assertEquals + +inline fun bar(block: () -> String) : String { + return block() +} + +inline fun bar2() : String { + return bar { return "def" } +} + +fun foobar(x: String, y: String, z: String) = x + y + z + +fun foo() : String { + return foobar( + "abc", + bar2(), + "ghi" + ) +} + +fun box() : String { + assertEquals("abcdefghi", foo()) + return "OK" +} diff --git a/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/withLambda.kt b/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/withLambda.kt new file mode 100644 index 00000000000..4c229244e47 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/withLambda.kt @@ -0,0 +1,13 @@ +import kotlin.test.assertEquals + +inline fun bar(x: String, block: (String) -> String) = "def" + block(x) +fun foobar(x: String, y: String, z: String) = x + y + z + +fun foo() : String { + return foobar("abc", bar("ghi") { x -> x + "jkl" }, "mno") +} + +fun box() : String { + assertEquals("abcdefghijklmno", foo()) + return "OK" +} diff --git a/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/differentTypes.kt b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/differentTypes.kt new file mode 100644 index 00000000000..2cf80131a0f --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/differentTypes.kt @@ -0,0 +1,16 @@ +inline fun bar(x: Int, y: Long, z: Byte, s: String) = x.toString() + y.toString() + z.toString() + s + +fun foobar(x: Int, y: Long, s: String, z: Byte) = x.toString() + y.toString() + s + z.toString() + +fun foo() : String { + return foobar(1, 2L, bar(3, 4L, 5.toByte(), "6"), 7.toByte()) +} + +// 3 ISTORE +// 11 ILOAD +// 2 ASTORE +// 8 ALOAD +// 2 LSTORE +// 6 LLOAD +// 1 MAXLOCALS = 9 +// 0 InlineMarker diff --git a/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/primitiveMerge.kt b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/primitiveMerge.kt new file mode 100644 index 00000000000..bcc8d2b0eba --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/primitiveMerge.kt @@ -0,0 +1,16 @@ +fun bar() : Boolean = true + +fun foobar(x: Boolean, y: String, z: String) = x.toString() + y + z + +inline fun foo() = "-" + +fun box() { + val result = foobar(if (1 == 1) true else bar(), foo(), "OK") +} + +// 1 ISTORE +// 3 ILOAD +// 2 ASTORE +// 7 ALOAD +// 3 MAXLOCALS = 3 +// 0 InlineMarker diff --git a/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/simple.kt b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/simple.kt new file mode 100644 index 00000000000..97026c2e4f8 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/simple.kt @@ -0,0 +1,14 @@ + +inline fun bar(x: Int) : Int { + return x +} + +fun foobar(x: Int, y: Int, z: Int) = x + y + z + +fun foo() : Int { + return foobar(1, bar(2), 3) +} + +// 3 ISTORE +// 11 ILOAD +// 0 InlineMarker diff --git a/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/unreachableMarker.kt b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/unreachableMarker.kt new file mode 100644 index 00000000000..0b68ac9f93b --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/unreachableMarker.kt @@ -0,0 +1,21 @@ +inline fun bar(block: () -> String) : String { + return block() +} + +inline fun bar2() : String { + return bar { return "def" } +} + +fun foobar(x: String, y: String, z: String) = x + y + z + +fun foo() : String { + return foobar( + "abc", + bar2(), + "ghi" + ) +} + +// 12 ALOAD +// 0 ASTORE +// 0 InlineMarker diff --git a/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/withLambda.kt b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/withLambda.kt new file mode 100644 index 00000000000..30394ac1a02 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/withLambda.kt @@ -0,0 +1,11 @@ +inline fun bar(x: String, block: (String) -> String) = "def" + block(x) +fun foobar(x: String, y: String, z: String) = x + y + z + +fun foo() : String { + return foobar("abc", bar("ghi") { x -> x + "jkl" }, "mno") +} + +// 6 ASTORE +// 21 ALOAD +// 1 MAXLOCALS = 5 +// 0 InlineMarker diff --git a/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java index a6da24aa337..55e9436aac8 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java @@ -32,7 +32,7 @@ import java.util.regex.Pattern; @SuppressWarnings("all") @TestMetadata("compiler/testData/codegen/bytecodeText") @TestDataPath("$PROJECT_ROOT") -@InnerTestClasses({BytecodeTextTestGenerated.BoxingOptimization.class, BytecodeTextTestGenerated.Constants.class, BytecodeTextTestGenerated.DirectInvoke.class, BytecodeTextTestGenerated.Statements.class, BytecodeTextTestGenerated.When.class, BytecodeTextTestGenerated.WhenEnumOptimization.class, BytecodeTextTestGenerated.WhenStringOptimization.class}) +@InnerTestClasses({BytecodeTextTestGenerated.BoxingOptimization.class, BytecodeTextTestGenerated.Constants.class, BytecodeTextTestGenerated.DirectInvoke.class, BytecodeTextTestGenerated.Statements.class, BytecodeTextTestGenerated.StoreStackBeforeInline.class, BytecodeTextTestGenerated.When.class, BytecodeTextTestGenerated.WhenEnumOptimization.class, BytecodeTextTestGenerated.WhenStringOptimization.class}) @RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class) public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { @TestMetadata("accessorForProtected.kt") @@ -373,6 +373,46 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { } + @TestMetadata("compiler/testData/codegen/bytecodeText/storeStackBeforeInline") + @TestDataPath("$PROJECT_ROOT") + @RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class) + public static class StoreStackBeforeInline extends AbstractBytecodeTextTest { + public void testAllFilesPresentInStoreStackBeforeInline() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/storeStackBeforeInline"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("differentTypes.kt") + public void testDifferentTypes() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/storeStackBeforeInline/differentTypes.kt"); + doTest(fileName); + } + + @TestMetadata("primitiveMerge.kt") + public void testPrimitiveMerge() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/storeStackBeforeInline/primitiveMerge.kt"); + doTest(fileName); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/storeStackBeforeInline/simple.kt"); + doTest(fileName); + } + + @TestMetadata("unreachableMarker.kt") + public void testUnreachableMarker() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/storeStackBeforeInline/unreachableMarker.kt"); + doTest(fileName); + } + + @TestMetadata("withLambda.kt") + public void testWithLambda() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/storeStackBeforeInline/withLambda.kt"); + doTest(fileName); + } + + } + @TestMetadata("compiler/testData/codegen/bytecodeText/when") @TestDataPath("$PROJECT_ROOT") @RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 461acc1d2b0..d3b714f32db 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -32,7 +32,7 @@ import java.util.regex.Pattern; @SuppressWarnings("all") @TestMetadata("compiler/testData/codegen/boxWithStdlib") @TestDataPath("$PROJECT_ROOT") -@InnerTestClasses({BlackBoxWithStdlibCodegenTestGenerated.Annotations.class, BlackBoxWithStdlibCodegenTestGenerated.Arrays.class, BlackBoxWithStdlibCodegenTestGenerated.BoxingOptimization.class, BlackBoxWithStdlibCodegenTestGenerated.CallableReference.class, BlackBoxWithStdlibCodegenTestGenerated.Casts.class, BlackBoxWithStdlibCodegenTestGenerated.DataClasses.class, BlackBoxWithStdlibCodegenTestGenerated.DefaultArguments.class, BlackBoxWithStdlibCodegenTestGenerated.Evaluate.class, BlackBoxWithStdlibCodegenTestGenerated.FullJdk.class, BlackBoxWithStdlibCodegenTestGenerated.HashPMap.class, BlackBoxWithStdlibCodegenTestGenerated.JdkAnnotations.class, BlackBoxWithStdlibCodegenTestGenerated.PlatformNames.class, BlackBoxWithStdlibCodegenTestGenerated.PlatformStatic.class, BlackBoxWithStdlibCodegenTestGenerated.Ranges.class, BlackBoxWithStdlibCodegenTestGenerated.Reflection.class, BlackBoxWithStdlibCodegenTestGenerated.Regressions.class, BlackBoxWithStdlibCodegenTestGenerated.Strings.class, BlackBoxWithStdlibCodegenTestGenerated.ToArray.class, BlackBoxWithStdlibCodegenTestGenerated.Vararg.class, BlackBoxWithStdlibCodegenTestGenerated.When.class, BlackBoxWithStdlibCodegenTestGenerated.WhenEnumOptimization.class, BlackBoxWithStdlibCodegenTestGenerated.WhenStringOptimization.class}) +@InnerTestClasses({BlackBoxWithStdlibCodegenTestGenerated.Annotations.class, BlackBoxWithStdlibCodegenTestGenerated.Arrays.class, BlackBoxWithStdlibCodegenTestGenerated.BoxingOptimization.class, BlackBoxWithStdlibCodegenTestGenerated.CallableReference.class, BlackBoxWithStdlibCodegenTestGenerated.Casts.class, BlackBoxWithStdlibCodegenTestGenerated.DataClasses.class, BlackBoxWithStdlibCodegenTestGenerated.DefaultArguments.class, BlackBoxWithStdlibCodegenTestGenerated.Evaluate.class, BlackBoxWithStdlibCodegenTestGenerated.FullJdk.class, BlackBoxWithStdlibCodegenTestGenerated.HashPMap.class, BlackBoxWithStdlibCodegenTestGenerated.JdkAnnotations.class, BlackBoxWithStdlibCodegenTestGenerated.PlatformNames.class, BlackBoxWithStdlibCodegenTestGenerated.PlatformStatic.class, BlackBoxWithStdlibCodegenTestGenerated.Ranges.class, BlackBoxWithStdlibCodegenTestGenerated.Reflection.class, BlackBoxWithStdlibCodegenTestGenerated.Regressions.class, BlackBoxWithStdlibCodegenTestGenerated.StoreStackBeforeInline.class, BlackBoxWithStdlibCodegenTestGenerated.Strings.class, BlackBoxWithStdlibCodegenTestGenerated.ToArray.class, BlackBoxWithStdlibCodegenTestGenerated.Vararg.class, BlackBoxWithStdlibCodegenTestGenerated.When.class, BlackBoxWithStdlibCodegenTestGenerated.WhenEnumOptimization.class, BlackBoxWithStdlibCodegenTestGenerated.WhenStringOptimization.class}) @RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class) public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInBoxWithStdlib() throws Exception { @@ -2339,6 +2339,46 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode } + @TestMetadata("compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline") + @TestDataPath("$PROJECT_ROOT") + @RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class) + public static class StoreStackBeforeInline extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInStoreStackBeforeInline() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("differentTypes.kt") + public void testDifferentTypes() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/differentTypes.kt"); + doTestWithStdlib(fileName); + } + + @TestMetadata("primitiveMerge.kt") + public void testPrimitiveMerge() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/primitiveMerge.kt"); + doTestWithStdlib(fileName); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/simple.kt"); + doTestWithStdlib(fileName); + } + + @TestMetadata("unreachableMarker.kt") + public void testUnreachableMarker() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/unreachableMarker.kt"); + doTestWithStdlib(fileName); + } + + @TestMetadata("withLambda.kt") + public void testWithLambda() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline/withLambda.kt"); + doTestWithStdlib(fileName); + } + + } + @TestMetadata("compiler/testData/codegen/boxWithStdlib/strings") @TestDataPath("$PROJECT_ROOT") @RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)