8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
Reviewed-by: jlaskey, hannesw
This commit is contained in:
parent
fd8e5653a0
commit
d12e5e7d29
@ -74,6 +74,7 @@ import java.util.Map;
|
||||
import java.util.RandomAccess;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
|
||||
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
|
||||
import jdk.nashorn.internal.codegen.RuntimeCallSite.SpecializedRuntimeNode;
|
||||
@ -2002,16 +2003,32 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
||||
final Expression lhs = args.get(0);
|
||||
final Expression rhs = args.get(1);
|
||||
|
||||
if (!rhs.getSymbol().isScope()) {
|
||||
final Symbol lhsSymbol = lhs.getSymbol();
|
||||
final Symbol rhsSymbol = rhs.getSymbol();
|
||||
|
||||
final Symbol undefinedSymbol = "undefined".equals(lhsSymbol.getName()) ? lhsSymbol : rhsSymbol;
|
||||
final Expression expr = undefinedSymbol == lhsSymbol ? rhs : lhs;
|
||||
|
||||
if (!undefinedSymbol.isScope()) {
|
||||
return false; //disallow undefined as local var or parameter
|
||||
}
|
||||
|
||||
if (lhsSymbol == undefinedSymbol && lhs.getType().isPrimitive()) {
|
||||
//we load the undefined first. never mind, because this will deoptimize anyway
|
||||
return false;
|
||||
}
|
||||
|
||||
if (compiler.getCompilationEnvironment().isCompileRestOf()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//make sure that undefined has not been overridden or scoped as a local var
|
||||
//between us and global
|
||||
final CompilationEnvironment env = compiler.getCompilationEnvironment();
|
||||
RecompilableScriptFunctionData data = env.getScriptFunctionData(lc.getCurrentFunction().getId());
|
||||
final RecompilableScriptFunctionData program = compiler.getCompilationEnvironment().getProgram();
|
||||
assert data != null;
|
||||
|
||||
while (data != program) {
|
||||
if (data.hasInternalSymbol("undefined")) {
|
||||
return false;
|
||||
@ -2019,11 +2036,11 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
||||
data = data.getParent();
|
||||
}
|
||||
|
||||
load(lhs);
|
||||
if (lhs.getType().isPrimitive()) {
|
||||
load(expr);
|
||||
|
||||
if (expr.getType().isPrimitive()) {
|
||||
method.pop(); //throw away lhs, but it still needs to be evaluated for side effects, even if not in scope, as it can be optimistic
|
||||
method.load(request == Request.IS_NOT_UNDEFINED);
|
||||
method.store(runtimeNode.getSymbol());
|
||||
} else {
|
||||
final Label isUndefined = new Label("ud_check_true");
|
||||
final Label notUndefined = new Label("ud_check_false");
|
||||
@ -2036,8 +2053,9 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
||||
method.label(isUndefined);
|
||||
method.load(request == Request.IS_UNDEFINED);
|
||||
method.label(end);
|
||||
method.store(runtimeNode.getSymbol());
|
||||
}
|
||||
|
||||
method.store(runtimeNode.getSymbol());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2139,7 +2157,6 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
||||
load(args.get(0));
|
||||
load(args.get(1));
|
||||
|
||||
|
||||
//if the request is a comparison, i.e. one that can be reversed
|
||||
//it keeps its semantic, but make sure that the object comes in
|
||||
//last
|
||||
|
@ -85,7 +85,7 @@ final class FinalizeTypes extends NodeOperatorVisitor<LexicalContext> {
|
||||
}
|
||||
|
||||
private static Node createIsUndefined(final Expression parent, final Expression lhs, final Expression rhs, final Request request) {
|
||||
if ("undefined".equals(rhs.getSymbol().getName())) {
|
||||
if ("undefined".equals(lhs.getSymbol().getName()) || "undefined".equals(rhs.getSymbol().getName())) {
|
||||
return new RuntimeNode(parent, request, lhs, rhs);
|
||||
}
|
||||
return parent;
|
||||
|
@ -135,3 +135,106 @@ print("18: " + g3("17") + " === true");
|
||||
print("19: " + g4("17") + " === true");
|
||||
print("20: " + g5("17") + " === true");
|
||||
|
||||
//h1 internals={} externals={undefined=0}
|
||||
function h1(x) {
|
||||
return undefined === x;
|
||||
}
|
||||
|
||||
//h2 internals={} externals=null
|
||||
function h2(x, undefined) {
|
||||
return undefined === x;
|
||||
}
|
||||
|
||||
//h3 internals={x=0} externals=null
|
||||
function h3(x) {
|
||||
//h3$f3_2 internals={} externals={x=0}
|
||||
function h3_2(undefined) {
|
||||
return undefined === x;
|
||||
}
|
||||
return h3_2(17);
|
||||
}
|
||||
|
||||
//h4 internals={x=0} externals=null
|
||||
function h4(x) {
|
||||
//h4$h4_2 internals={} externals={x=0}
|
||||
function h4_2() {
|
||||
var undefined = 17;
|
||||
return undefined === x;
|
||||
}
|
||||
return h4_2();
|
||||
}
|
||||
|
||||
//h5 internals={x=0, undefined=0} externals=null
|
||||
function h5(x) {
|
||||
var undefined = 17;
|
||||
//h5$h5_2 internals={} externals={x=0, undefined=0}
|
||||
function h5_2() {
|
||||
return undefined === x;
|
||||
}
|
||||
return h5_2();
|
||||
}
|
||||
|
||||
print("21: " + h1(17) + " === false");
|
||||
print("22: " + h2(17) + " === false");
|
||||
print("23: " + h3(17) + " === true");
|
||||
print("24: " + h4(17) + " === true");
|
||||
print("25: " + h5(17) + " === true");
|
||||
|
||||
//recompile
|
||||
print("26: " + h1("17") + " === false");
|
||||
print("27: " + h2("17") + " === false");
|
||||
print("28: " + h3("17") + " === false");
|
||||
print("29: " + h4("17") + " === false");
|
||||
print("30: " + h5("17") + " === false");
|
||||
|
||||
//i1 internals={} externals={undefined=0}
|
||||
function i1(x) {
|
||||
return undefined !== x;
|
||||
}
|
||||
|
||||
//i2 internals={} externals=null
|
||||
function i2(x, undefined) {
|
||||
return undefined !== x;
|
||||
}
|
||||
|
||||
//i3 internals={x=0} externals=null
|
||||
function i3(x) {
|
||||
//i3$f3_2 internals={} externals={x=0}
|
||||
function i3_2(undefined) {
|
||||
return undefined !== x;
|
||||
}
|
||||
return i3_2(17);
|
||||
}
|
||||
|
||||
//i4 internals={x=0} externals=null
|
||||
function i4(x) {
|
||||
//i4$i4_2 internals={} externals={x=0}
|
||||
function i4_2() {
|
||||
var undefined = 17;
|
||||
return undefined !== x;
|
||||
}
|
||||
return i4_2();
|
||||
}
|
||||
|
||||
//h5 internals={x=0, undefined=0} externals=null
|
||||
function i5(x) {
|
||||
var undefined = 17;
|
||||
//i5$i5_2 internals={} externals={x=0, undefined=0}
|
||||
function i5_2() {
|
||||
return undefined !== x;
|
||||
}
|
||||
return i5_2();
|
||||
}
|
||||
|
||||
print("31: " + i1(17) + " === true");
|
||||
print("32: " + i2(17) + " === true");
|
||||
print("33: " + i3(17) + " === false");
|
||||
print("34: " + i4(17) + " === false");
|
||||
print("35: " + i5(17) + " === false");
|
||||
|
||||
//recompile
|
||||
print("36: " + i1("17") + " === true");
|
||||
print("37: " + i2("17") + " === true");
|
||||
print("38: " + i3("17") + " === true");
|
||||
print("39: " + i4("17") + " === true");
|
||||
print("40: " + i5("17") + " === true");
|
||||
|
@ -18,3 +18,23 @@
|
||||
18: true === true
|
||||
19: true === true
|
||||
20: true === true
|
||||
21: false === false
|
||||
22: false === false
|
||||
23: true === true
|
||||
24: true === true
|
||||
25: true === true
|
||||
26: false === false
|
||||
27: false === false
|
||||
28: false === false
|
||||
29: false === false
|
||||
30: false === false
|
||||
31: true === true
|
||||
32: true === true
|
||||
33: false === false
|
||||
34: false === false
|
||||
35: false === false
|
||||
36: true === true
|
||||
37: true === true
|
||||
38: true === true
|
||||
39: true === true
|
||||
40: true === true
|
||||
|
Loading…
x
Reference in New Issue
Block a user