Prevent JSBody from inlining if its argumet get used more than once

This commit is contained in:
Alexey Andreev 2015-12-25 21:48:32 +03:00
parent 0369d100c6
commit 03538071c4
3 changed files with 37 additions and 4 deletions

View File

@ -16,7 +16,9 @@
package org.teavm.jso.impl;
import java.io.IOException;
import org.mozilla.javascript.Node;
import org.mozilla.javascript.ast.AstNode;
import org.mozilla.javascript.ast.Block;
import org.teavm.codegen.SourceWriter;
import org.teavm.javascript.Precedence;
import org.teavm.javascript.spi.GeneratorContext;
@ -151,7 +153,14 @@ class JSBodyAstEmitter implements JSBodyEmitter {
astWriter.declareNameEmitter(parameterNames[i], prec -> writer.append(context.getParameterName(index)));
}
astWriter.hoist(ast);
astWriter.print(ast);
writer.softNewLine();
if (ast instanceof Block) {
for (Node child = ast.getFirstChild(); child != null; child = child.getNext()) {
astWriter.print((AstNode) child);
writer.softNewLine();
}
} else {
astWriter.print(ast);
writer.softNewLine();
}
}
}

View File

@ -115,7 +115,7 @@ final class JSBodyInlineUtil {
Name name = (Name) node;
if (!name.isLocalName()) {
String id = name.getIdentifier();
usages.put(id, getUsage(id));
usages.put(id, getUsage(id) + 1);
}
}
return true;

View File

@ -15,9 +15,10 @@
*/
package org.teavm.jso.test;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject;
/**
*
@ -35,4 +36,27 @@ public class ImplementationTest {
@JSBody(params = { "a", "b" }, script = "return a * b;")
static final native int mul(int a, int b);
@Test
public void inliningUsageCounterWorksProperly() {
ForInliningTest instance = ForInliningTest.create();
wrongInlineCandidate(instance.foo());
assertEquals(1, instance.counter);
}
@JSBody(params = { "a" }, script = "console.log(a, a);")
private static native void wrongInlineCandidate(JSObject a);
static class ForInliningTest implements JSObject {
public int counter = 0;
public ForInliningTest foo() {
++counter;
return this;
}
public static ForInliningTest create() {
return new ForInliningTest();
}
}
}