diff --git a/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java b/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java index d9aaf0526e..a18e5a8ca4 100644 --- a/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java +++ b/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java @@ -984,8 +984,8 @@ private void generateExpression(Node node, Node parent) { case Token.NAME: { - cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); + cfw.addALoad(contextLocal); addDynamicInvoke("NAME:GET:" + node.getString(), Signatures.NAME_GET); } break; @@ -1473,8 +1473,8 @@ private void generateExpression(Node node, Node parent) { child = child.getNext(); } // Generate code for "ScriptRuntime.bind(varObj, "s")" - cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); + cfw.addALoad(contextLocal); addDynamicInvoke("NAME:BIND:" + node.getString(), Signatures.NAME_BIND); } break; @@ -2644,8 +2644,8 @@ private void generateFunctionAndThisObj(Node node, Node parent) { case Token.NAME: { String name = node.getString(); - cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); + cfw.addALoad(contextLocal); addDynamicInvoke("NAME:GETWITHTHIS:" + name, Signatures.NAME_GET_THIS); break; } diff --git a/rhino/src/main/java/org/mozilla/javascript/optimizer/DefaultLinker.java b/rhino/src/main/java/org/mozilla/javascript/optimizer/DefaultLinker.java index 7a26ef0338..cdeaa4c575 100644 --- a/rhino/src/main/java/org/mozilla/javascript/optimizer/DefaultLinker.java +++ b/rhino/src/main/java/org/mozilla/javascript/optimizer/DefaultLinker.java @@ -12,7 +12,10 @@ import jdk.dynalink.linker.GuardingDynamicLinker; import jdk.dynalink.linker.LinkRequest; import jdk.dynalink.linker.LinkerServices; +import org.mozilla.javascript.Callable; +import org.mozilla.javascript.Context; import org.mozilla.javascript.ScriptRuntime; +import org.mozilla.javascript.Scriptable; /** * This linker is the last one in the chain, and as such it must be able to link every type of @@ -125,18 +128,30 @@ private GuardedInvocation getNameInvocation( Operation op, String name) throws NoSuchMethodException, IllegalAccessException { + MethodType tt; MethodHandle mh = null; // Like above for properties, the name to handle is not on the Java stack, // but is something that we parsed from the name of the invokedynamic operation. if (RhinoOperation.BIND.equals(op)) { - mh = bindStringParameter(lookup, mType, ScriptRuntime.class, "bind", 2, name); + tt = + MethodType.methodType( + Scriptable.class, Context.class, Scriptable.class, String.class); + mh = lookup.findStatic(ScriptRuntime.class, "bind", tt); + mh = MethodHandles.insertArguments(mh, 2, name); + mh = MethodHandles.permuteArguments(mh, mType, 1, 0); } else if (StandardOperation.GET.equals(op)) { - mh = bindStringParameter(lookup, mType, ScriptRuntime.class, "name", 2, name); + tt = MethodType.methodType(Object.class, Context.class, Scriptable.class, String.class); + mh = lookup.findStatic(ScriptRuntime.class, "name", tt); + mh = MethodHandles.insertArguments(mh, 2, name); + mh = MethodHandles.permuteArguments(mh, mType, 1, 0); } else if (RhinoOperation.GETWITHTHIS.equals(op)) { - mh = - bindStringParameter( - lookup, mType, ScriptRuntime.class, "getNameFunctionAndThis", 0, name); + tt = + MethodType.methodType( + Callable.class, String.class, Context.class, Scriptable.class); + mh = lookup.findStatic(ScriptRuntime.class, "getNameFunctionAndThis", tt); + mh = MethodHandles.insertArguments(mh, 0, name); + mh = MethodHandles.permuteArguments(mh, mType, 1, 0); } else if (StandardOperation.SET.equals(op)) { mh = bindStringParameter(lookup, mType, ScriptRuntime.class, "setName", 4, name); } else if (RhinoOperation.SETSTRICT.equals(op)) { diff --git a/rhino/src/main/java/org/mozilla/javascript/optimizer/Signatures.java b/rhino/src/main/java/org/mozilla/javascript/optimizer/Signatures.java index 744b74005f..337b7c2ff8 100644 --- a/rhino/src/main/java/org/mozilla/javascript/optimizer/Signatures.java +++ b/rhino/src/main/java/org/mozilla/javascript/optimizer/Signatures.java @@ -5,7 +5,9 @@ * instructions in the bytecode. This helps us identify what each bytecode operation means, and what * the method signature should be. The method signatures here don't necessarily map 1:1 with * ScriptRuntime operations -- the runtime will insert the value of the "name" part of the operation - * name before making the call. + * name before making the call. Also, many of the "name" operations have a different signature than + * the ScriptRuntime equivalents because in these signatures we are trying to make the "target" of + * each operation the first argument to make future optimizations easier. */ interface Signatures { /** @@ -92,8 +94,8 @@ interface Signatures { * NAME:GET:{name}: Looks up a the named value from the scope. Falls back to ScriptRuntime.name. */ String NAME_GET = - "(Lorg/mozilla/javascript/Context;" - + "Lorg/mozilla/javascript/Scriptable;" + "(Lorg/mozilla/javascript/Scriptable;" + + "Lorg/mozilla/javascript/Context;" + ")Ljava/lang/Object;"; /** @@ -101,8 +103,8 @@ interface Signatures { * "last stored scriptable." Falls back to ScriptRuntime.getNameFunctionAndThis. */ String NAME_GET_THIS = - "(Lorg/mozilla/javascript/Context;" - + "Lorg/mozilla/javascript/Scriptable;" + "(Lorg/mozilla/javascript/Scriptable;" + + "Lorg/mozilla/javascript/Context;" + ")Lorg/mozilla/javascript/Callable;"; /** NAME:SET:{name}: Sets the named value in the scope. Falls back to ScriptRuntime.setName. */ @@ -118,8 +120,8 @@ interface Signatures { * ScriptRuntime.bind. */ String NAME_BIND = - "(Lorg/mozilla/javascript/Context;" - + "Lorg/mozilla/javascript/Scriptable;" + "(Lorg/mozilla/javascript/Scriptable;" + + "Lorg/mozilla/javascript/Context;" + ")Lorg/mozilla/javascript/Scriptable;"; /**