aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsundar <none@none>2014-05-07 14:07:19 +0530
committersundar <none@none>2014-05-07 14:07:19 +0530
commit74a64b08b7b1c775b9d1fbe38fe3493b61ce9c67 (patch)
tree95e62180727434ccd83213d51a03566120f11f2f /src
parent1253d94766badbb642f55704274cfa45f9d34199 (diff)
downloadnashorn-74a64b08b7b1c775b9d1fbe38fe3493b61ce9c67.tar.gz
8041697: CompiledScript slower when eval with binding
Reviewed-by: lagergren, attila, hannesw
Diffstat (limited to 'src')
-rw-r--r--src/jdk/nashorn/api/scripting/NashornScriptEngine.java55
-rw-r--r--src/jdk/nashorn/internal/runtime/Context.java61
-rw-r--r--src/jdk/nashorn/tools/Shell.java2
3 files changed, 100 insertions, 18 deletions
diff --git a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
index dbdd6ee6..7ebe5c91 100644
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
+++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
@@ -525,6 +525,31 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt));
}
+ private Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
+ final Global oldGlobal = Context.getGlobal();
+ final boolean globalChanged = (oldGlobal != ctxtGlobal);
+ try {
+ if (globalChanged) {
+ Context.setGlobal(ctxtGlobal);
+ }
+
+ final ScriptFunction script = mgcs.getFunction(ctxtGlobal);
+
+ // set ScriptContext variables if ctxt is non-null
+ if (ctxt != null) {
+ setContextVariables(ctxtGlobal, ctxt);
+ }
+ return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
+ } catch (final Exception e) {
+ throwAsScriptException(e, ctxtGlobal);
+ throw new AssertionError("should not reach here");
+ } finally {
+ if (globalChanged) {
+ Context.setGlobal(oldGlobal);
+ }
+ }
+ }
+
private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
if (script == null) {
return null;
@@ -571,18 +596,38 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
private CompiledScript asCompiledScript(final Source source) throws ScriptException {
- final ScriptFunction func = compileImpl(source, context);
+ final Context.MultiGlobalCompiledScript mgcs;
+ final ScriptFunction func;
+ final Global oldGlobal = Context.getGlobal();
+ final Global newGlobal = getNashornGlobalFrom(context);
+ final boolean globalChanged = (oldGlobal != newGlobal);
+ try {
+ if (globalChanged) {
+ Context.setGlobal(newGlobal);
+ }
+
+ mgcs = nashornContext.compileScript(source);
+ func = mgcs.getFunction(newGlobal);
+ } catch (final Exception e) {
+ throwAsScriptException(e, newGlobal);
+ throw new AssertionError("should not reach here");
+ } finally {
+ if (globalChanged) {
+ Context.setGlobal(oldGlobal);
+ }
+ }
+
return new CompiledScript() {
@Override
public Object eval(final ScriptContext ctxt) throws ScriptException {
final Global globalObject = getNashornGlobalFrom(ctxt);
- // Are we running the script in the correct global?
+ // Are we running the script in the same global in which it was compiled?
if (func.getScope() == globalObject) {
return evalImpl(func, ctxt, globalObject);
}
- // ScriptContext with a different global. Compile again!
- // Note that we may still hit per-global compilation cache.
- return evalImpl(compileImpl(source, ctxt), ctxt, globalObject);
+
+ // different global
+ return evalImpl(mgcs, ctxt, globalObject);
}
@Override
public ScriptEngine getEngine() {
diff --git a/src/jdk/nashorn/internal/runtime/Context.java b/src/jdk/nashorn/internal/runtime/Context.java
index 10a516e4..9f2c521d 100644
--- a/src/jdk/nashorn/internal/runtime/Context.java
+++ b/src/jdk/nashorn/internal/runtime/Context.java
@@ -491,6 +491,39 @@ public final class Context {
}
/**
+ * Interface to represent compiled code that can be re-used across many
+ * global scope instances
+ */
+ public static interface MultiGlobalCompiledScript {
+ /**
+ * Obtain script function object for a specific global scope object.
+ *
+ * @param newGlobal global scope for which function object is obtained
+ * @return script function for script level expressions
+ */
+ public ScriptFunction getFunction(final Global newGlobal);
+ }
+
+ /**
+ * Compile a top level script.
+ *
+ * @param source the script source
+ * @return reusable compiled script across many global scopes.
+ */
+ public MultiGlobalCompiledScript compileScript(final Source source) {
+ final Class<?> clazz = compile(source, this.errors, this._strict);
+ final MethodHandle runMethodHandle = getRunScriptHandle(clazz);
+ final boolean strict = isStrict(clazz);
+
+ return new MultiGlobalCompiledScript() {
+ @Override
+ public ScriptFunction getFunction(final Global newGlobal) {
+ return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, newGlobal, strict);
+ }
+ };
+ }
+
+ /**
* Entry point for {@code eval}
*
* @param initialScope The scope of this eval call
@@ -950,14 +983,8 @@ public final class Context {
return ScriptRuntime.apply(script, thiz);
}
- private static ScriptFunction getRunScriptFunction(final Class<?> script, final ScriptObject scope) {
- if (script == null) {
- return null;
- }
-
- // Get run method - the entry point to the script
- final MethodHandle runMethodHandle =
- MH.findStatic(
+ private static MethodHandle getRunScriptHandle(final Class<?> script) {
+ return MH.findStatic(
MethodHandles.lookup(),
script,
RUN_SCRIPT.symbolName(),
@@ -965,14 +992,24 @@ public final class Context {
Object.class,
ScriptFunction.class,
Object.class));
+ }
- boolean strict;
-
+ private static boolean isStrict(final Class<?> script) {
try {
- strict = script.getField(STRICT_MODE.symbolName()).getBoolean(null);
+ return script.getField(STRICT_MODE.symbolName()).getBoolean(null);
} catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
- strict = false;
+ return false;
}
+ }
+
+ private static ScriptFunction getRunScriptFunction(final Class<?> script, final ScriptObject scope) {
+ if (script == null) {
+ return null;
+ }
+
+ // Get run method - the entry point to the script
+ final MethodHandle runMethodHandle = getRunScriptHandle(script);
+ boolean strict = isStrict(script);
// Package as a JavaScript function and pass function back to shell.
return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict);
diff --git a/src/jdk/nashorn/tools/Shell.java b/src/jdk/nashorn/tools/Shell.java
index e5cde5fa..33e0afd7 100644
--- a/src/jdk/nashorn/tools/Shell.java
+++ b/src/jdk/nashorn/tools/Shell.java
@@ -453,7 +453,7 @@ public class Shell {
}
} finally {
if (globalChanged) {
- Context.setGlobal(global);
+ Context.setGlobal(oldGlobal);
}
}