mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
JS: add null check in strict mode
This commit is contained in:
parent
bffb50f0cd
commit
6f50eefaf9
|
@ -55,10 +55,10 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
|
||||||
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||||
switch (methodRef.getName()) {
|
switch (methodRef.getName()) {
|
||||||
case "newEmptyInstance":
|
case "newEmptyInstance":
|
||||||
context.getWriter().append("new ");
|
context.getWriter().append("new (");
|
||||||
context.writeExpr(context.getArgument(0), Precedence.MEMBER_ACCESS);
|
context.writeExpr(context.getArgument(0), Precedence.MEMBER_ACCESS);
|
||||||
context.getWriter().append('.').appendField(platformClassField);
|
context.getWriter().append('.').appendField(platformClassField);
|
||||||
context.getWriter().append("()");
|
context.getWriter().append(")");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,10 +109,11 @@ import org.teavm.model.lowlevel.Characteristics;
|
||||||
import org.teavm.model.lowlevel.ClassInitializerEliminator;
|
import org.teavm.model.lowlevel.ClassInitializerEliminator;
|
||||||
import org.teavm.model.lowlevel.ClassInitializerTransformer;
|
import org.teavm.model.lowlevel.ClassInitializerTransformer;
|
||||||
import org.teavm.model.lowlevel.ExportDependencyListener;
|
import org.teavm.model.lowlevel.ExportDependencyListener;
|
||||||
import org.teavm.model.lowlevel.NullCheckInsertion;
|
import org.teavm.model.lowlevel.LowLevelNullCheckFilter;
|
||||||
import org.teavm.model.lowlevel.NullCheckTransformation;
|
import org.teavm.model.lowlevel.NullCheckTransformation;
|
||||||
import org.teavm.model.lowlevel.ShadowStackTransformer;
|
import org.teavm.model.lowlevel.ShadowStackTransformer;
|
||||||
import org.teavm.model.transformation.ClassPatch;
|
import org.teavm.model.transformation.ClassPatch;
|
||||||
|
import org.teavm.model.transformation.NullCheckInsertion;
|
||||||
import org.teavm.model.util.AsyncMethodFinder;
|
import org.teavm.model.util.AsyncMethodFinder;
|
||||||
import org.teavm.runtime.Allocator;
|
import org.teavm.runtime.Allocator;
|
||||||
import org.teavm.runtime.CallSite;
|
import org.teavm.runtime.CallSite;
|
||||||
|
@ -220,7 +221,7 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||||
classInitializerEliminator = new ClassInitializerEliminator(controller.getUnprocessedClassSource());
|
classInitializerEliminator = new ClassInitializerEliminator(controller.getUnprocessedClassSource());
|
||||||
classInitializerTransformer = new ClassInitializerTransformer();
|
classInitializerTransformer = new ClassInitializerTransformer();
|
||||||
shadowStackTransformer = new ShadowStackTransformer(characteristics, !longjmpUsed);
|
shadowStackTransformer = new ShadowStackTransformer(characteristics, !longjmpUsed);
|
||||||
nullCheckInsertion = new NullCheckInsertion(characteristics);
|
nullCheckInsertion = new NullCheckInsertion(new LowLevelNullCheckFilter(characteristics));
|
||||||
nullCheckTransformation = new NullCheckTransformation();
|
nullCheckTransformation = new NullCheckTransformation();
|
||||||
|
|
||||||
controller.addVirtualMethods(VIRTUAL_METHODS::contains);
|
controller.addVirtualMethods(VIRTUAL_METHODS::contains);
|
||||||
|
|
|
@ -95,7 +95,9 @@ import org.teavm.model.instructions.InvocationType;
|
||||||
import org.teavm.model.instructions.InvokeInstruction;
|
import org.teavm.model.instructions.InvokeInstruction;
|
||||||
import org.teavm.model.instructions.RaiseInstruction;
|
import org.teavm.model.instructions.RaiseInstruction;
|
||||||
import org.teavm.model.instructions.StringConstantInstruction;
|
import org.teavm.model.instructions.StringConstantInstruction;
|
||||||
import org.teavm.model.lowlevel.BoundCheckInsertion;
|
import org.teavm.model.transformation.BoundCheckInsertion;
|
||||||
|
import org.teavm.model.transformation.NullCheckFilter;
|
||||||
|
import org.teavm.model.transformation.NullCheckInsertion;
|
||||||
import org.teavm.model.util.AsyncMethodFinder;
|
import org.teavm.model.util.AsyncMethodFinder;
|
||||||
import org.teavm.model.util.ProgramUtils;
|
import org.teavm.model.util.ProgramUtils;
|
||||||
import org.teavm.vm.BuildTarget;
|
import org.teavm.vm.BuildTarget;
|
||||||
|
@ -128,6 +130,8 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
private int topLevelNameLimit = 10000;
|
private int topLevelNameLimit = 10000;
|
||||||
private AstDependencyExtractor dependencyExtractor = new AstDependencyExtractor();
|
private AstDependencyExtractor dependencyExtractor = new AstDependencyExtractor();
|
||||||
private boolean strict;
|
private boolean strict;
|
||||||
|
private BoundCheckInsertion boundCheckInsertion = new BoundCheckInsertion();
|
||||||
|
private NullCheckInsertion nullCheckInsertion = new NullCheckInsertion(NullCheckFilter.EMPTY);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClassHolderTransformer> getTransformers() {
|
public List<ClassHolderTransformer> getTransformers() {
|
||||||
|
@ -339,7 +343,8 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
@Override
|
@Override
|
||||||
public void beforeOptimizations(Program program, MethodReader method) {
|
public void beforeOptimizations(Program program, MethodReader method) {
|
||||||
if (strict) {
|
if (strict) {
|
||||||
new BoundCheckInsertion().transformProgram(program, method.getReference());
|
boundCheckInsertion.transformProgram(program, method.getReference());
|
||||||
|
nullCheckInsertion.transformProgram(program, method.getReference());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ public enum Precedence {
|
||||||
ADDITION,
|
ADDITION,
|
||||||
MULTIPLICATION,
|
MULTIPLICATION,
|
||||||
UNARY,
|
UNARY,
|
||||||
|
NEW,
|
||||||
FUNCTION_CALL,
|
FUNCTION_CALL,
|
||||||
MEMBER_ACCESS,
|
MEMBER_ACCESS,
|
||||||
GROUPING;
|
GROUPING;
|
||||||
|
|
|
@ -1113,6 +1113,11 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
if (injector != null) {
|
if (injector != null) {
|
||||||
injector.generate(new InjectorContextImpl(expr.getArguments()), expr.getMethod());
|
injector.generate(new InjectorContextImpl(expr.getArguments()), expr.getMethod());
|
||||||
} else {
|
} else {
|
||||||
|
Precedence outerPrecedence = precedence;
|
||||||
|
if (outerPrecedence.ordinal() > Precedence.FUNCTION_CALL.ordinal()) {
|
||||||
|
writer.append('(');
|
||||||
|
}
|
||||||
|
|
||||||
if (expr.getType() == InvocationType.DYNAMIC) {
|
if (expr.getType() == InvocationType.DYNAMIC) {
|
||||||
precedence = Precedence.MEMBER_ACCESS;
|
precedence = Precedence.MEMBER_ACCESS;
|
||||||
expr.getArguments().get(0).acceptVisitor(this);
|
expr.getArguments().get(0).acceptVisitor(this);
|
||||||
|
@ -1184,6 +1189,10 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
if (shouldEraseCallSite) {
|
if (shouldEraseCallSite) {
|
||||||
lastCallSite = null;
|
lastCallSite = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (outerPrecedence.ordinal() > Precedence.FUNCTION_CALL.ordinal()) {
|
||||||
|
writer.append(')');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (expr.getLocation() != null) {
|
if (expr.getLocation() != null) {
|
||||||
popLocation();
|
popLocation();
|
||||||
|
@ -1224,14 +1233,14 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
Precedence outerPrecedence = precedence;
|
Precedence outerPrecedence = precedence;
|
||||||
if (outerPrecedence.ordinal() > Precedence.FUNCTION_CALL.ordinal()) {
|
if (outerPrecedence.ordinal() > Precedence.NEW.ordinal()) {
|
||||||
writer.append('(');
|
writer.append('(');
|
||||||
}
|
}
|
||||||
|
|
||||||
precedence = Precedence.FUNCTION_CALL;
|
precedence = Precedence.NEW;
|
||||||
|
|
||||||
writer.append("new ").appendClass(expr.getConstructedClass());
|
writer.append("new ").appendClass(expr.getConstructedClass());
|
||||||
if (outerPrecedence.ordinal() > Precedence.FUNCTION_CALL.ordinal()) {
|
if (outerPrecedence.ordinal() > Precedence.NEW.ordinal()) {
|
||||||
writer.append(')');
|
writer.append(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* 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.teavm.model.lowlevel;
|
||||||
|
|
||||||
|
import org.teavm.model.FieldReference;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.transformation.NullCheckFilter;
|
||||||
|
|
||||||
|
public class LowLevelNullCheckFilter implements NullCheckFilter {
|
||||||
|
private Characteristics characteristics;
|
||||||
|
|
||||||
|
public LowLevelNullCheckFilter(Characteristics characteristics) {
|
||||||
|
this.characteristics = characteristics;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(FieldReference field) {
|
||||||
|
return !characteristics.isStructure(field.getClassName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(MethodReference method) {
|
||||||
|
return characteristics.isManaged(method.getClassName()) && characteristics.isManaged(method);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2019 konsoletyper.
|
* Copyright 2019 Alexey Andreev.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.teavm.model.lowlevel;
|
package org.teavm.model.transformation;
|
||||||
|
|
||||||
import com.carrotsearch.hppc.IntArrayList;
|
import com.carrotsearch.hppc.IntArrayList;
|
||||||
import com.carrotsearch.hppc.IntHashSet;
|
import com.carrotsearch.hppc.IntHashSet;
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* 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.teavm.model.transformation;
|
||||||
|
|
||||||
|
import org.teavm.model.FieldReference;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
public interface NullCheckFilter {
|
||||||
|
boolean apply(FieldReference field);
|
||||||
|
|
||||||
|
boolean apply(MethodReference method);
|
||||||
|
|
||||||
|
NullCheckFilter EMPTY = new NullCheckFilter() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(FieldReference field) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(MethodReference method) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2018 Alexey Andreev.
|
* Copyright 2019 Alexey Andreev.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.teavm.model.lowlevel;
|
package org.teavm.model.transformation;
|
||||||
|
|
||||||
import com.carrotsearch.hppc.IntHashSet;
|
import com.carrotsearch.hppc.IntHashSet;
|
||||||
import com.carrotsearch.hppc.IntSet;
|
import com.carrotsearch.hppc.IntSet;
|
||||||
|
@ -39,14 +39,14 @@ import org.teavm.model.util.DominatorWalkerCallback;
|
||||||
import org.teavm.model.util.PhiUpdater;
|
import org.teavm.model.util.PhiUpdater;
|
||||||
|
|
||||||
public class NullCheckInsertion {
|
public class NullCheckInsertion {
|
||||||
private Characteristics characteristics;
|
private NullCheckFilter filter;
|
||||||
|
|
||||||
public NullCheckInsertion(Characteristics characteristics) {
|
public NullCheckInsertion(NullCheckFilter filter) {
|
||||||
this.characteristics = characteristics;
|
this.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void transformProgram(Program program, MethodReference methodReference) {
|
public void transformProgram(Program program, MethodReference methodReference) {
|
||||||
if (!characteristics.isManaged(methodReference) || program.basicBlockCount() == 0) {
|
if (!filter.apply(methodReference) || program.basicBlockCount() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,14 +99,14 @@ public class NullCheckInsertion {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(GetFieldInstruction insn) {
|
public void visit(GetFieldInstruction insn) {
|
||||||
if (!characteristics.isStructure(insn.getField().getClassName())) {
|
if (filter.apply(insn.getField())) {
|
||||||
addGuard(insn, GetFieldInstruction::getInstance, GetFieldInstruction::setInstance);
|
addGuard(insn, GetFieldInstruction::getInstance, GetFieldInstruction::setInstance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PutFieldInstruction insn) {
|
public void visit(PutFieldInstruction insn) {
|
||||||
if (!characteristics.isStructure(insn.getField().getClassName())) {
|
if (filter.apply(insn.getField())) {
|
||||||
addGuard(insn, PutFieldInstruction::getInstance, PutFieldInstruction::setInstance);
|
addGuard(insn, PutFieldInstruction::getInstance, PutFieldInstruction::setInstance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,8 +123,7 @@ public class NullCheckInsertion {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InvokeInstruction insn) {
|
public void visit(InvokeInstruction insn) {
|
||||||
if (!characteristics.isStructure(insn.getMethod().getClassName())
|
if (filter.apply(insn.getMethod())) {
|
||||||
&& characteristics.isManaged(insn.getMethod())) {
|
|
||||||
addGuard(insn, InvokeInstruction::getInstance, InvokeInstruction::setInstance);
|
addGuard(insn, InvokeInstruction::getInstance, InvokeInstruction::setInstance);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user