Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Begin to use invokedynamic in the bytecode #1645

Merged
merged 7 commits into from
Oct 5, 2024
1 change: 1 addition & 0 deletions rhino/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
exports org.mozilla.javascript.xml;

requires java.compiler;
requires jdk.dynalink;
requires transitive java.desktop;
}
217 changes: 35 additions & 182 deletions rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java
Original file line number Diff line number Diff line change
Expand Up @@ -984,15 +984,9 @@ private void generateExpression(Node node, Node parent) {

case Token.NAME:
{
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
cfw.addPush(node.getString());
addScriptRuntimeInvoke(
"name",
"(Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ "Ljava/lang/String;"
+ ")Ljava/lang/Object;");
cfw.addALoad(contextLocal);
addDynamicInvoke("NAME:GET:" + node.getString(), Signatures.NAME_GET);
}
break;

Expand Down Expand Up @@ -1368,21 +1362,11 @@ private void generateExpression(Node node, Node parent) {
generateExpression(child, node); // object
generateExpression(child.getNext(), node); // id
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) {
addScriptRuntimeInvoke(
"getObjectIndex",
"(Ljava/lang/Object;D"
+ "Lorg/mozilla/javascript/Context;"
+ ")Ljava/lang/Object;");
addDynamicInvoke("PROP:GETINDEX", Signatures.PROP_GET_INDEX);
} else {
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"getObjectElem",
"(Ljava/lang/Object;"
+ "Ljava/lang/Object;"
+ "Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ ")Ljava/lang/Object;");
addDynamicInvoke("PROP:GETELEMENT", Signatures.PROP_GET_ELEMENT);
}
break;

Expand Down Expand Up @@ -1489,15 +1473,9 @@ private void generateExpression(Node node, Node parent) {
child = child.getNext();
}
// Generate code for "ScriptRuntime.bind(varObj, "s")"
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
cfw.addPush(node.getString());
addScriptRuntimeInvoke(
"bind",
"(Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ "Ljava/lang/String;"
+ ")Lorg/mozilla/javascript/Scriptable;");
cfw.addALoad(contextLocal);
addDynamicInvoke("NAME:BIND:" + node.getString(), Signatures.NAME_BIND);
}
break;

Expand Down Expand Up @@ -1686,14 +1664,11 @@ private void generateYieldPoint(Node node, boolean exprContext) {
if (unnestedYields.containsKey(node)) {
// Yield was previously moved up via the "nestedYield" code below.
if (exprContext) {
String name = unnestedYields.get(node);
cfw.addALoad(variableObjectLocal);
cfw.addLoadConstant(unnestedYields.get(node));
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"getObjectPropNoWarn",
"(Ljava/lang/Object;Ljava/lang/String;Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;)Ljava/lang/Object;");
addDynamicInvoke("PROP:GETNOWARN:" + name, Signatures.PROP_GET_NOWARN);
}
return;
}
Expand All @@ -1711,14 +1686,9 @@ private void generateYieldPoint(Node node, boolean exprContext) {
unnestedYieldCount++;
cfw.addALoad(variableObjectLocal);
cfw.add(ByteCode.SWAP);
cfw.addLoadConstant(nn);
cfw.add(ByteCode.SWAP);
cfw.addALoad(contextLocal);

addScriptRuntimeInvoke(
"setObjectProp",
"(Lorg/mozilla/javascript/Scriptable;Ljava/lang/String;Ljava/lang/Object;"
+ "Lorg/mozilla/javascript/Context;)Ljava/lang/Object;");
cfw.addALoad(variableObjectLocal);
addDynamicInvoke("PROP:SET:" + nn, Signatures.PROP_SET);
cfw.add(ByteCode.POP);

unnestedYields.put(nestedYield, nn);
Expand Down Expand Up @@ -2652,16 +2622,9 @@ private void generateFunctionAndThisObj(Node node, Node parent) {
Node id = target.getNext();
if (type == Token.GETPROP) {
String property = id.getString();
cfw.addPush(property);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"getPropFunctionAndThis",
"(Ljava/lang/Object;"
+ "Ljava/lang/String;"
+ "Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ ")Lorg/mozilla/javascript/Callable;");
addDynamicInvoke("PROP:GETWITHTHIS:" + property, Signatures.PROP_GET_THIS);
} else {
generateExpression(id, node); // id
if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) addDoubleWrap();
Expand All @@ -2681,15 +2644,9 @@ private void generateFunctionAndThisObj(Node node, Node parent) {
case Token.NAME:
{
String name = node.getString();
cfw.addPush(name);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"getNameFunctionAndThis",
"(Ljava/lang/String;"
+ "Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ ")Lorg/mozilla/javascript/Callable;");
cfw.addALoad(contextLocal);
addDynamicInvoke("NAME:GETWITHTHIS:" + name, Signatures.NAME_GET_THIS);
break;
}

Expand Down Expand Up @@ -3895,15 +3852,7 @@ private void visitSetName(Node node, Node child) {
}
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
cfw.addPush(name);
addScriptRuntimeInvoke(
"setName",
"(Lorg/mozilla/javascript/Scriptable;"
+ "Ljava/lang/Object;"
+ "Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ "Ljava/lang/String;"
+ ")Ljava/lang/Object;");
addDynamicInvoke("NAME:SET:" + name, Signatures.NAME_SET);
}

private void visitStrictSetName(Node node, Node child) {
Expand All @@ -3914,15 +3863,7 @@ private void visitStrictSetName(Node node, Node child) {
}
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
cfw.addPush(name);
addScriptRuntimeInvoke(
"strictSetName",
"(Lorg/mozilla/javascript/Scriptable;"
+ "Ljava/lang/Object;"
+ "Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ "Ljava/lang/String;"
+ ")Ljava/lang/Object;");
addDynamicInvoke("NAME:SETSTRICT:" + name, Signatures.NAME_SET_STRICT);
}

private void visitSetConst(Node node, Node child) {
Expand All @@ -3932,14 +3873,7 @@ private void visitSetConst(Node node, Node child) {
child = child.getNext();
}
cfw.addALoad(contextLocal);
cfw.addPush(name);
addScriptRuntimeInvoke(
"setConst",
"(Lorg/mozilla/javascript/Scriptable;"
+ "Ljava/lang/Object;"
+ "Lorg/mozilla/javascript/Context;"
+ "Ljava/lang/String;"
+ ")Ljava/lang/Object;");
addDynamicInvoke("NAME:SETCONST:" + name, Signatures.NAME_SET_CONST);
}

private void visitGetVar(Node node) {
Expand Down Expand Up @@ -4060,42 +3994,13 @@ private void visitSetConstVar(Node node, Node child, boolean needValue) {
private void visitGetProp(Node node, Node child) {
generateExpression(child, node); // object
Node nameChild = child.getNext();
generateExpression(nameChild, node); // the name
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);

if (node.getType() == Token.GETPROPNOWARN) {
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"getObjectPropNoWarn",
"(Ljava/lang/Object;"
+ "Ljava/lang/String;"
+ "Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ ")Ljava/lang/Object;");
return;
}
/*
for 'this.foo' we call getObjectProp(Scriptable...) which can
skip some casting overhead.
*/
int childType = child.getType();
if (childType == Token.THIS && nameChild.getType() == Token.STRING) {
cfw.addALoad(contextLocal);
addScriptRuntimeInvoke(
"getObjectProp",
"(Lorg/mozilla/javascript/Scriptable;"
+ "Ljava/lang/String;"
+ "Lorg/mozilla/javascript/Context;"
+ ")Ljava/lang/Object;");
addDynamicInvoke("PROP:GETNOWARN:" + nameChild.getString(), Signatures.PROP_GET_NOWARN);
} else {
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"getObjectProp",
"(Ljava/lang/Object;"
+ "Ljava/lang/String;"
+ "Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ ")Ljava/lang/Object;");
addDynamicInvoke("PROP:GET:" + nameChild.getString(), Signatures.PROP_GET);
}
}

Expand Down Expand Up @@ -4130,51 +4035,20 @@ private void visitGetPropOptional(Node node, Node child) {
}

private void visitSetProp(int type, Node node, Node child) {
Node objectChild = child;
generateExpression(child, node);
child = child.getNext();
Node nameChild = child;
if (type == Token.SETPROP_OP) {
cfw.add(ByteCode.DUP);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addDynamicInvoke("PROP:GET:" + nameChild.getString(), Signatures.PROP_GET);
}
Node nameChild = child;
generateExpression(child, node);
child = child.getNext();
if (type == Token.SETPROP_OP) {
// stack: ... object object name -> ... object name object name
cfw.add(ByteCode.DUP_X1);
// for 'this.foo += ...' we call thisGet which can skip some
// casting overhead.
if (objectChild.getType() == Token.THIS && nameChild.getType() == Token.STRING) {
cfw.addALoad(contextLocal);
addScriptRuntimeInvoke(
"getObjectProp",
"(Lorg/mozilla/javascript/Scriptable;"
+ "Ljava/lang/String;"
+ "Lorg/mozilla/javascript/Context;"
+ ")Ljava/lang/Object;");
} else {
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"getObjectProp",
"(Ljava/lang/Object;"
+ "Ljava/lang/String;"
+ "Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ ")Ljava/lang/Object;");
}
}
generateExpression(child, node);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"setObjectProp",
"(Ljava/lang/Object;"
+ "Ljava/lang/String;"
+ "Ljava/lang/Object;"
+ "Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ ")Ljava/lang/Object;");
addDynamicInvoke("PROP:SET:" + nameChild.getString(), Signatures.PROP_SET);
}

private void visitSetElem(int type, Node node, Node child) {
Expand All @@ -4193,48 +4067,23 @@ private void visitSetElem(int type, Node node, Node child) {
cfw.add(ByteCode.DUP2_X1);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"getObjectIndex",
"(Ljava/lang/Object;D"
+ "Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ ")Ljava/lang/Object;");
addDynamicInvoke("PROP:GETINDEX", Signatures.PROP_GET_INDEX);
} else {
// stack: ... object object indexObject
// -> ... object indexObject object indexObject
cfw.add(ByteCode.DUP_X1);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke(
"getObjectElem",
"(Ljava/lang/Object;"
+ "Ljava/lang/Object;"
+ "Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ ")Ljava/lang/Object;");
addDynamicInvoke("PROP:GETELEMENT", Signatures.PROP_GET_ELEMENT);
}
}
generateExpression(child, node);
cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
if (indexIsNumber) {
addScriptRuntimeInvoke(
"setObjectIndex",
"(Ljava/lang/Object;"
+ "D"
+ "Ljava/lang/Object;"
+ "Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ ")Ljava/lang/Object;");
addDynamicInvoke("PROP:SETINDEX", Signatures.PROP_SET_INDEX);
} else {
addScriptRuntimeInvoke(
"setObjectElem",
"(Ljava/lang/Object;"
+ "Ljava/lang/Object;"
+ "Ljava/lang/Object;"
+ "Lorg/mozilla/javascript/Context;"
+ "Lorg/mozilla/javascript/Scriptable;"
+ ")Ljava/lang/Object;");
addDynamicInvoke("PROP:SETELEMENT", Signatures.PROP_SET_ELEMENT);
}
}

Expand Down Expand Up @@ -4355,6 +4204,10 @@ private void addOptRuntimeInvoke(String methodName, String methodSignature) {
methodSignature);
}

private void addDynamicInvoke(String operation, String signature) {
cfw.addInvokeDynamic(operation, signature, Bootstrapper.BOOTSTRAP_HANDLE);
}

private void addJumpedBooleanWrap(int trueLabel, int falseLabel) {
cfw.markLabel(falseLabel);
int skip = cfw.acquireLabel();
Expand Down
Loading
Loading