JS: do not generate break for top level return during inline
This commit is contained in:
@@ -132,6 +132,13 @@ class FunctionInlineMutator private (private val call: JsInvocation, private val
|
|||||||
|
|
||||||
val visitor = ReturnReplacingVisitor(resultExpr as? JsNameRef, breakName.makeRef())
|
val visitor = ReturnReplacingVisitor(resultExpr as? JsNameRef, breakName.makeRef())
|
||||||
visitor.accept(body)
|
visitor.accept(body)
|
||||||
|
|
||||||
|
val statements = body.getStatements()
|
||||||
|
val last = statements.lastOrNull() as? JsBreak
|
||||||
|
|
||||||
|
if (last?.getLabel()?.getName() === breakLabel?.getName()) {
|
||||||
|
statements.remove(statements.lastIndex)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getResultReference(): JsNameRef? {
|
private fun getResultReference(): JsNameRef? {
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public fun collectNamedFunctions(scope: JsNode): IdentityHashMap<JsName, JsFunct
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun collectInstances<T : JsNode>(klass: Class<T>, scope: JsNode): List<T> {
|
public fun collectInstances<T : JsNode>(klass: Class<T>, scope: JsNode): List<T> {
|
||||||
return with(InstanceCollector(klass)) {
|
return with(InstanceCollector(klass, visitNestedDeclarations = false)) {
|
||||||
accept(scope)
|
accept(scope)
|
||||||
collected
|
collected
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-1
@@ -16,13 +16,27 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.inline.util.collectors
|
package org.jetbrains.kotlin.js.inline.util.collectors
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsFunction
|
||||||
import com.google.dart.compiler.backend.js.ast.JsNode
|
import com.google.dart.compiler.backend.js.ast.JsNode
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsObjectLiteral
|
||||||
import com.google.dart.compiler.backend.js.ast.RecursiveJsVisitor
|
import com.google.dart.compiler.backend.js.ast.RecursiveJsVisitor
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
class InstanceCollector<T : JsNode>(val klass: Class<T>) : RecursiveJsVisitor() {
|
class InstanceCollector<T : JsNode>(val klass: Class<T>, val visitNestedDeclarations: Boolean) : RecursiveJsVisitor() {
|
||||||
public val collected: MutableList<T> = ArrayList()
|
public val collected: MutableList<T> = ArrayList()
|
||||||
|
|
||||||
|
override fun visitFunction(x: JsFunction) {
|
||||||
|
if (visitNestedDeclarations) {
|
||||||
|
visitElement(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitObjectLiteral(x: JsObjectLiteral) {
|
||||||
|
if (visitNestedDeclarations) {
|
||||||
|
visitElement(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitElement(node: JsNode) {
|
override fun visitElement(node: JsNode) {
|
||||||
if (klass.isInstance(node)) {
|
if (klass.isInstance(node)) {
|
||||||
collected.add(klass.cast(node)!!)
|
collected.add(klass.cast(node)!!)
|
||||||
|
|||||||
+6
@@ -35,6 +35,12 @@ public class InlineSizeReductionTestGenerated extends AbstractInlineSizeReductio
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/inlineSizeReduction/cases"), Pattern.compile("^(.+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/inlineSizeReduction/cases"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lastBreak.kt")
|
||||||
|
public void testLastBreak() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/inlineSizeReduction/cases/lastBreak.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("oneTopLevelReturn.kt")
|
@TestMetadata("oneTopLevelReturn.kt")
|
||||||
public void testOneTopLevelReturn() throws Exception {
|
public void testOneTopLevelReturn() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/inlineSizeReduction/cases/oneTopLevelReturn.kt");
|
String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/inlineSizeReduction/cases/oneTopLevelReturn.kt");
|
||||||
|
|||||||
@@ -104,8 +104,8 @@ public class DirectiveTestUtils {
|
|||||||
String countStr = arguments.getNamedArgument("count");
|
String countStr = arguments.getNamedArgument("count");
|
||||||
int expectedCount = Integer.valueOf(countStr);
|
int expectedCount = Integer.valueOf(countStr);
|
||||||
|
|
||||||
JsNode scope = AstSearchUtil.getFunction(ast, functionName);
|
JsFunction function = AstSearchUtil.getFunction(ast, functionName);
|
||||||
List<T> nodes = collectInstances(klass, scope);
|
List<T> nodes = collectInstances(klass, function.getBody());
|
||||||
int actualCount = 0;
|
int actualCount = 0;
|
||||||
|
|
||||||
for (T node : nodes) {
|
for (T node : nodes) {
|
||||||
@@ -138,6 +138,8 @@ public class DirectiveTestUtils {
|
|||||||
|
|
||||||
private static final DirectiveHandler COUNT_VARS = new CountNodesDirective<JsVars.JsVar>("CHECK_VARS_COUNT", JsVars.JsVar.class);
|
private static final DirectiveHandler COUNT_VARS = new CountNodesDirective<JsVars.JsVar>("CHECK_VARS_COUNT", JsVars.JsVar.class);
|
||||||
|
|
||||||
|
private static final DirectiveHandler COUNT_BREAKS = new CountNodesDirective<JsBreak>("CHECK_BREAKS_COUNT", JsBreak.class);
|
||||||
|
|
||||||
private static final DirectiveHandler HAS_INLINE_METADATA = new DirectiveHandler("CHECK_HAS_INLINE_METADATA") {
|
private static final DirectiveHandler HAS_INLINE_METADATA = new DirectiveHandler("CHECK_HAS_INLINE_METADATA") {
|
||||||
@Override
|
@Override
|
||||||
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
|
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
|
||||||
@@ -166,6 +168,7 @@ public class DirectiveTestUtils {
|
|||||||
FUNCTIONS_HAVE_SAME_LINES,
|
FUNCTIONS_HAVE_SAME_LINES,
|
||||||
COUNT_LABELS,
|
COUNT_LABELS,
|
||||||
COUNT_VARS,
|
COUNT_VARS,
|
||||||
|
COUNT_BREAKS,
|
||||||
HAS_INLINE_METADATA,
|
HAS_INLINE_METADATA,
|
||||||
HAS_NO_INLINE_METADATA
|
HAS_NO_INLINE_METADATA
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
// CHECK_NOT_CALLED: f1
|
||||||
|
// CHECK_NOT_CALLED: f2
|
||||||
|
// CHECK_BREAKS_COUNT: function=test count=3
|
||||||
|
|
||||||
|
var even = arrayListOf<Int>()
|
||||||
|
var odd = arrayListOf<Int>()
|
||||||
|
|
||||||
|
inline fun f2(x: Int): Unit {
|
||||||
|
if (x % 2 == 0) {
|
||||||
|
even.add(x)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
odd.add(x)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun f1(x: Boolean, y: Int, z: Int): Unit {
|
||||||
|
if (x) {
|
||||||
|
return f2(y)
|
||||||
|
}
|
||||||
|
|
||||||
|
return f2(z)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(x: Boolean, y: Int, z: Int): Unit = f1(x, y, z)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
test(true, 2, 1)
|
||||||
|
test(false, 2, 1)
|
||||||
|
assertEquals(listOf(2), even)
|
||||||
|
assertEquals(listOf(1), odd)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user