JS: fix strict mode null pointer check with inlining

This commit is contained in:
Alexey Andreev 2022-05-19 11:14:15 +03:00
parent be259f1667
commit 98490e92f6
6 changed files with 38 additions and 16 deletions

View File

@ -339,11 +339,17 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
}
}
@Override
public void beforeInlining(Program program, MethodReader method) {
if (strict) {
nullCheckInsertion.transformProgram(program, method.getReference());
}
}
@Override
public void beforeOptimizations(Program program, MethodReader method) {
if (strict) {
boundCheckInsertion.transformProgram(program, method.getReference());
nullCheckInsertion.transformProgram(program, method.getReference());
}
}

View File

@ -31,6 +31,7 @@ public class DefaultInliningStrategy implements InliningStrategy {
private final int depthThreshold;
private final int totalComplexityThreshold;
private final boolean onceUsedOnly;
private int getComplexityDepth;
public DefaultInliningStrategy(int complexityThreshold, int depthThreshold, int totalComplexityThreshold,
boolean onceUsedOnly) {
@ -52,7 +53,7 @@ public class DefaultInliningStrategy implements InliningStrategy {
return new InliningStepImpl(complexityHolder);
}
private static Complexity getComplexity(ProgramReader program, InliningContext context) {
private Complexity getComplexity(ProgramReader program, InliningContext context) {
int complexity = 0;
ComplexityCounter counter = new ComplexityCounter(context);
for (int i = 0; i < program.basicBlockCount(); ++i) {
@ -101,7 +102,7 @@ public class DefaultInliningStrategy implements InliningStrategy {
int complexity;
}
static class ComplexityCounter extends AbstractInstructionReader {
class ComplexityCounter extends AbstractInstructionReader {
InliningContext context;
int complexity;
boolean callsToUsedOnceMethods;
@ -132,10 +133,12 @@ public class DefaultInliningStrategy implements InliningStrategy {
}
private boolean isTrivialCall(ProgramReader program) {
if (program == null) {
if (program == null || getComplexityDepth > 10) {
return false;
}
getComplexityDepth++;
Complexity complexity = getComplexity(program, context);
getComplexityDepth--;
return complexity.score <= 1 && !complexity.callsToUsedOnceMethods;
}

View File

@ -27,7 +27,6 @@ import org.teavm.model.instructions.AbstractInstructionVisitor;
import org.teavm.model.instructions.ArrayLengthInstruction;
import org.teavm.model.instructions.AssignInstruction;
import org.teavm.model.instructions.BinaryInstruction;
import org.teavm.model.instructions.BoundCheckInstruction;
import org.teavm.model.instructions.CastInstruction;
import org.teavm.model.instructions.CastIntegerInstruction;
import org.teavm.model.instructions.CastNumberInstruction;
@ -45,7 +44,6 @@ import org.teavm.model.instructions.InvokeInstruction;
import org.teavm.model.instructions.IsInstanceInstruction;
import org.teavm.model.instructions.LongConstantInstruction;
import org.teavm.model.instructions.NegateInstruction;
import org.teavm.model.instructions.NullCheckInstruction;
import org.teavm.model.instructions.NullConstantInstruction;
import org.teavm.model.instructions.StringConstantInstruction;
import org.teavm.model.instructions.UnwrapArrayInstruction;
@ -256,15 +254,5 @@ public class UnusedVariableElimination implements MethodOptimization {
public void visit(IsInstanceInstruction insn) {
requestUsage(insn.getReceiver());
}
@Override
public void visit(NullCheckInstruction insn) {
requestUsage(insn.getReceiver());
}
@Override
public void visit(BoundCheckInstruction insn) {
requestUsage(insn.getReceiver());
}
}
}

View File

@ -119,6 +119,19 @@ public final class VariableEscapeAnalyzer {
if (insn.getArray() != null) {
escaping[insn.getArray().getIndex()] = true;
}
if (insn.getReceiver() != null) {
escaping[insn.getReceiver().getIndex()] = true;
}
}
@Override
public void visit(NullCheckInstruction insn) {
if (insn.getValue() != null) {
escaping[insn.getValue().getIndex()] = true;
}
if (insn.getReceiver() != null) {
escaping[insn.getReceiver().getIndex()] = true;
}
}
}
}

View File

@ -467,6 +467,14 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
target.setController(targetController);
for (String className : classSet.getClassNames()) {
ClassHolder cls = classSet.get(className);
for (MethodHolder method : cls.getMethods()) {
if (method.getProgram() != null) {
target.beforeInlining(method.getProgram(), method);
}
}
}
inline(classSet);
if (wasCancelled()) {
return null;
@ -979,6 +987,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
missingItemsProcessor.processMethod(method.getReference(), program);
linker.link(method, program);
clinitInsertion.apply(method, program);
target.beforeInlining(program, method);
program = optimizeMethodCacheMiss(method, program);
Program finalProgram = program;
programCache.store(method.getReference(), finalProgram,

View File

@ -40,6 +40,9 @@ public interface TeaVMTarget {
void contributeDependencies(DependencyAnalyzer dependencyAnalyzer);
default void beforeInlining(Program program, MethodReader method) {
}
default void analyzeBeforeOptimizations(ListableClassReaderSource classSource) {
}