Wed, 12 Mar 2014 11:26:00 +0100
8021350: Share script classes between threads/globals within context
Reviewed-by: lagergren, sundar
1.1 --- a/make/build.xml Wed Mar 12 16:33:28 2014 +0100 1.2 +++ b/make/build.xml Wed Mar 12 11:26:00 2014 +0100 1.3 @@ -250,6 +250,10 @@ 1.4 <fileset dir="${test.src.dir}/jdk/nashorn/internal/runtime/resources"/> 1.5 </copy> 1.6 1.7 + <copy todir="${build.test.classes.dir}/jdk/nashorn/api/scripting/resources"> 1.8 + <fileset dir="${test.src.dir}/jdk/nashorn/api/scripting/resources"/> 1.9 + </copy> 1.10 + 1.11 <!-- tests that check nashorn internals and internal API --> 1.12 <jar jarfile="${nashorn.internal.tests.jar}"> 1.13 <fileset dir="${build.test.classes.dir}" excludes="**/api/**"/>
2.1 --- a/make/project.properties Wed Mar 12 16:33:28 2014 +0100 2.2 +++ b/make/project.properties Wed Mar 12 11:26:00 2014 +0100 2.3 @@ -202,7 +202,7 @@ 2.4 2.5 # test262 test frameworks 2.6 test262-test-sys-prop.test.js.framework=\ 2.7 - --class-cache-size=0 \ 2.8 + --class-cache-size=10 \ 2.9 --no-java \ 2.10 --no-typed-arrays \ 2.11 -timezone=PST \
3.1 --- a/src/jdk/nashorn/internal/codegen/Attr.java Wed Mar 12 16:33:28 2014 +0100 3.2 +++ b/src/jdk/nashorn/internal/codegen/Attr.java Wed Mar 12 11:26:00 2014 +0100 3.3 @@ -375,10 +375,11 @@ 3.4 * @return Symbol for given name or null for redefinition. 3.5 */ 3.6 private Symbol defineSymbol(final Block block, final String name, final int symbolFlags) { 3.7 - int flags = symbolFlags; 3.8 - Symbol symbol = findSymbol(block, name); // Locate symbol. 3.9 + int flags = symbolFlags; 3.10 + Symbol symbol = findSymbol(block, name); // Locate symbol. 3.11 + boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL; 3.12 3.13 - if ((flags & KINDMASK) == IS_GLOBAL) { 3.14 + if (isGlobal) { 3.15 flags |= IS_SCOPE; 3.16 } 3.17 3.18 @@ -414,6 +415,8 @@ 3.19 // Determine where to create it. 3.20 if ((flags & Symbol.KINDMASK) == IS_VAR && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) { 3.21 symbolBlock = block; //internal vars are always defined in the block closest to them 3.22 + } else if (isGlobal) { 3.23 + symbolBlock = lc.getOutermostFunction().getBody(); 3.24 } else { 3.25 symbolBlock = lc.getFunctionBody(function); 3.26 }
4.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Mar 12 16:33:28 2014 +0100 4.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Mar 12 11:26:00 2014 +0100 4.3 @@ -685,7 +685,7 @@ 4.4 private void scopeCall(final IdentNode node, final int flags) { 4.5 load(node, Type.OBJECT); // Type.OBJECT as foo() makes no sense if foo == 3 4.6 // ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly. 4.7 - method.loadNull(); //the 'this' 4.8 + method.loadUndefined(Type.OBJECT); //the 'this' object 4.9 method.dynamicCall(callNodeType, 2 + loadArgs(args), flags); 4.10 } 4.11 4.12 @@ -818,7 +818,7 @@ 4.13 protected boolean enterDefault(final Node node) { 4.14 // Load up function. 4.15 load(function, Type.OBJECT); //TODO, e.g. booleans can be used as functions 4.16 - method.loadNull(); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE 4.17 + method.loadUndefined(Type.OBJECT); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE 4.18 method.dynamicCall(callNodeType, 2 + loadArgs(args), getCallSiteFlags() | CALLSITE_SCOPE); 4.19 4.20 return false;
5.1 --- a/src/jdk/nashorn/internal/codegen/SharedScopeCall.java Wed Mar 12 16:33:28 2014 +0100 5.2 +++ b/src/jdk/nashorn/internal/codegen/SharedScopeCall.java Wed Mar 12 11:26:00 2014 +0100 5.3 @@ -156,7 +156,7 @@ 5.4 if (isCall) { 5.5 method.convert(Type.OBJECT); 5.6 // ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly. 5.7 - method.loadNull(); 5.8 + method.loadUndefined(Type.OBJECT); 5.9 int slot = 2; 5.10 for (final Type type : paramTypes) { 5.11 method.load(type, slot++);
6.1 --- a/src/jdk/nashorn/internal/ir/FunctionNode.java Wed Mar 12 16:33:28 2014 +0100 6.2 +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java Wed Mar 12 11:26:00 2014 +0100 6.3 @@ -164,11 +164,11 @@ 6.4 public static final int HAS_EVAL = 1 << 5; 6.5 6.6 /** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */ 6.7 - public static final int HAS_NESTED_EVAL = 1 << 6; 6.8 + public static final int HAS_NESTED_EVAL = 1 << 6; 6.9 6.10 /** Does this function have any blocks that create a scope? This is used to determine if the function needs to 6.11 * have a local variable slot for the scope symbol. */ 6.12 - public static final int HAS_SCOPE_BLOCK = 1 << 7; 6.13 + public static final int HAS_SCOPE_BLOCK = 1 << 7; 6.14 6.15 /** 6.16 * Flag this function as one that defines the identifier "arguments" as a function parameter or nested function 6.17 @@ -197,6 +197,9 @@ 6.18 /** Can this function be specialized? */ 6.19 public static final int CAN_SPECIALIZE = 1 << 14; 6.20 6.21 + /** Does this function use the "this" keyword? */ 6.22 + public static final int USES_THIS = 1 << 15; 6.23 + 6.24 /** Does this function or any nested functions contain an eval? */ 6.25 private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL; 6.26 6.27 @@ -591,6 +594,15 @@ 6.28 } 6.29 6.30 /** 6.31 + * Return {@code true} if this function makes use of the {@code this} object. 6.32 + * 6.33 + * @return true if function uses {@code this} object 6.34 + */ 6.35 + public boolean usesThis() { 6.36 + return getFlag(USES_THIS); 6.37 + } 6.38 + 6.39 + /** 6.40 * Get the identifier for this function, this is its symbol. 6.41 * @return the identifier as an IdentityNode 6.42 */
7.1 --- a/src/jdk/nashorn/internal/objects/Global.java Wed Mar 12 16:33:28 2014 +0100 7.2 +++ b/src/jdk/nashorn/internal/objects/Global.java Wed Mar 12 11:26:00 2014 +0100 7.3 @@ -33,11 +33,8 @@ 7.4 import java.io.PrintWriter; 7.5 import java.lang.invoke.MethodHandle; 7.6 import java.lang.invoke.MethodHandles; 7.7 -import java.lang.ref.ReferenceQueue; 7.8 -import java.lang.ref.SoftReference; 7.9 import java.lang.reflect.Field; 7.10 import java.util.Arrays; 7.11 -import java.util.LinkedHashMap; 7.12 import java.util.List; 7.13 import java.util.Map; 7.14 import java.util.concurrent.Callable; 7.15 @@ -59,10 +56,10 @@ 7.16 import jdk.nashorn.internal.runtime.Scope; 7.17 import jdk.nashorn.internal.runtime.ScriptEnvironment; 7.18 import jdk.nashorn.internal.runtime.ScriptFunction; 7.19 +import jdk.nashorn.internal.runtime.ScriptFunctionData; 7.20 import jdk.nashorn.internal.runtime.ScriptObject; 7.21 import jdk.nashorn.internal.runtime.ScriptRuntime; 7.22 import jdk.nashorn.internal.runtime.ScriptingFunctions; 7.23 -import jdk.nashorn.internal.runtime.Source; 7.24 import jdk.nashorn.internal.runtime.arrays.ArrayData; 7.25 import jdk.nashorn.internal.runtime.linker.Bootstrap; 7.26 import jdk.nashorn.internal.runtime.linker.InvokeByName; 7.27 @@ -373,9 +370,6 @@ 7.28 // Flag to indicate that a split method issued a return statement 7.29 private int splitState = -1; 7.30 7.31 - // class cache 7.32 - private ClassCache classCache; 7.33 - 7.34 // Used to store the last RegExp result to support deprecated RegExp constructor properties 7.35 private RegExpResult lastRegExpResult; 7.36 7.37 @@ -426,11 +420,6 @@ 7.38 super(checkAndGetMap(context)); 7.39 this.context = context; 7.40 this.setIsScope(); 7.41 - 7.42 - final int cacheSize = context.getEnv()._class_cache_size; 7.43 - if (cacheSize > 0) { 7.44 - classCache = new ClassCache(cacheSize); 7.45 - } 7.46 } 7.47 7.48 /** 7.49 @@ -488,7 +477,7 @@ 7.50 7.51 @Override 7.52 public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) { 7.53 - return new ScriptFunctionImpl(name, handle, scope, null, strict, false, true); 7.54 + return new ScriptFunctionImpl(name, handle, scope, null, strict ? ScriptFunctionData.IS_STRICT_CONSTRUCTOR : ScriptFunctionData.IS_CONSTRUCTOR); 7.55 } 7.56 7.57 @Override 7.58 @@ -664,62 +653,6 @@ 7.59 } 7.60 7.61 7.62 - /** 7.63 - * Cache for compiled script classes. 7.64 - */ 7.65 - @SuppressWarnings("serial") 7.66 - private static class ClassCache extends LinkedHashMap<Source, ClassReference> { 7.67 - private final int size; 7.68 - private final ReferenceQueue<Class<?>> queue; 7.69 - 7.70 - ClassCache(int size) { 7.71 - super(size, 0.75f, true); 7.72 - this.size = size; 7.73 - this.queue = new ReferenceQueue<>(); 7.74 - } 7.75 - 7.76 - void cache(final Source source, final Class<?> clazz) { 7.77 - put(source, new ClassReference(clazz, queue, source)); 7.78 - } 7.79 - 7.80 - @Override 7.81 - protected boolean removeEldestEntry(final Map.Entry<Source, ClassReference> eldest) { 7.82 - return size() > size; 7.83 - } 7.84 - 7.85 - @Override 7.86 - public ClassReference get(Object key) { 7.87 - for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) { 7.88 - remove(ref.source); 7.89 - } 7.90 - return super.get(key); 7.91 - } 7.92 - 7.93 - } 7.94 - 7.95 - private static class ClassReference extends SoftReference<Class<?>> { 7.96 - private final Source source; 7.97 - 7.98 - ClassReference(final Class<?> clazz, final ReferenceQueue<Class<?>> queue, final Source source) { 7.99 - super(clazz, queue); 7.100 - this.source = source; 7.101 - } 7.102 - } 7.103 - 7.104 - // Class cache management 7.105 - @Override 7.106 - public Class<?> findCachedClass(final Source source) { 7.107 - assert classCache != null : "Class cache used without being initialized"; 7.108 - ClassReference ref = classCache.get(source); 7.109 - return ref != null ? ref.get() : null; 7.110 - } 7.111 - 7.112 - @Override 7.113 - public void cacheClass(final Source source, final Class<?> clazz) { 7.114 - assert classCache != null : "Class cache used without being initialized"; 7.115 - classCache.cache(source, clazz); 7.116 - } 7.117 - 7.118 private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) { 7.119 final T obj = map.get(key); 7.120 if (obj != null) { 7.121 @@ -1838,7 +1771,7 @@ 7.122 anon.deleteOwnProperty(anon.getMap().findProperty("prototype")); 7.123 7.124 // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3 7.125 - this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, false, false, false); 7.126 + this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0); 7.127 typeErrorThrower.setPrototype(UNDEFINED); 7.128 // Non-constructor built-in functions do not have "prototype" property 7.129 typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
8.1 --- a/src/jdk/nashorn/internal/objects/NativeBoolean.java Wed Mar 12 16:33:28 2014 +0100 8.2 +++ b/src/jdk/nashorn/internal/objects/NativeBoolean.java Wed Mar 12 11:26:00 2014 +0100 8.3 @@ -30,6 +30,7 @@ 8.4 8.5 import java.lang.invoke.MethodHandle; 8.6 import java.lang.invoke.MethodHandles; 8.7 +import java.lang.invoke.MethodType; 8.8 import jdk.internal.dynalink.linker.GuardedInvocation; 8.9 import jdk.internal.dynalink.linker.LinkRequest; 8.10 import jdk.nashorn.internal.objects.annotations.Attribute; 8.11 @@ -50,7 +51,10 @@ 8.12 public final class NativeBoolean extends ScriptObject { 8.13 private final boolean value; 8.14 8.15 - final static MethodHandle WRAPFILTER = findWrapFilter(); 8.16 + // Method handle to create an object wrapper for a primitive boolean 8.17 + private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeBoolean.class, Object.class)); 8.18 + // Method handle to retrieve the Boolean prototype object 8.19 + private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class)); 8.20 8.21 // initialized by nasgen 8.22 private static PropertyMap $nasgenmap$; 8.23 @@ -164,7 +168,7 @@ 8.24 * @return Link to be invoked at call site. 8.25 */ 8.26 public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) { 8.27 - return PrimitiveLookup.lookupPrimitive(request, Boolean.class, new NativeBoolean((Boolean)receiver), WRAPFILTER); 8.28 + return PrimitiveLookup.lookupPrimitive(request, Boolean.class, new NativeBoolean((Boolean)receiver), WRAPFILTER, PROTOFILTER); 8.29 } 8.30 8.31 /** 8.32 @@ -178,7 +182,12 @@ 8.33 return new NativeBoolean((Boolean)receiver); 8.34 } 8.35 8.36 - private static MethodHandle findWrapFilter() { 8.37 - return MH.findStatic(MethodHandles.lookup(), NativeBoolean.class, "wrapFilter", MH.type(NativeBoolean.class, Object.class)); 8.38 + @SuppressWarnings("unused") 8.39 + private static Object protoFilter(final Object object) { 8.40 + return Global.instance().getBooleanPrototype(); 8.41 + } 8.42 + 8.43 + private static MethodHandle findOwnMH(final String name, final MethodType type) { 8.44 + return MH.findStatic(MethodHandles.lookup(), NativeBoolean.class, name, type); 8.45 } 8.46 }
9.1 --- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Wed Mar 12 16:33:28 2014 +0100 9.2 +++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Wed Mar 12 11:26:00 2014 +0100 9.3 @@ -622,7 +622,7 @@ 9.4 case "getMethod": 9.5 final FindProperty find = adaptee.findProperty(__call__, true); 9.6 if (find != null) { 9.7 - final Object value = getObjectValue(find); 9.8 + final Object value = find.getObjectValue(); 9.9 if (value instanceof ScriptFunction) { 9.10 final ScriptFunctionImpl func = (ScriptFunctionImpl)value; 9.11 // TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound 9.12 @@ -691,7 +691,7 @@ 9.13 final MethodType type = desc.getMethodType(); 9.14 if (findData != null) { 9.15 final String name = desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : null; 9.16 - final Object value = getObjectValue(findData); 9.17 + final Object value = findData.getObjectValue(); 9.18 if (value instanceof ScriptFunction) { 9.19 final ScriptFunction func = (ScriptFunction)value; 9.20
10.1 --- a/src/jdk/nashorn/internal/objects/NativeNumber.java Wed Mar 12 16:33:28 2014 +0100 10.2 +++ b/src/jdk/nashorn/internal/objects/NativeNumber.java Wed Mar 12 11:26:00 2014 +0100 10.3 @@ -34,6 +34,7 @@ 10.4 10.5 import java.lang.invoke.MethodHandle; 10.6 import java.lang.invoke.MethodHandles; 10.7 +import java.lang.invoke.MethodType; 10.8 import java.text.NumberFormat; 10.9 import java.util.Locale; 10.10 import jdk.internal.dynalink.linker.GuardedInvocation; 10.11 @@ -57,7 +58,10 @@ 10.12 @ScriptClass("Number") 10.13 public final class NativeNumber extends ScriptObject { 10.14 10.15 - static final MethodHandle WRAPFILTER = findWrapFilter(); 10.16 + // Method handle to create an object wrapper for a primitive number 10.17 + private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeNumber.class, Object.class)); 10.18 + // Method handle to retrieve the Number prototype object 10.19 + private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class)); 10.20 10.21 /** ECMA 15.7.3.2 largest positive finite value */ 10.22 @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT, where = Where.CONSTRUCTOR) 10.23 @@ -322,7 +326,7 @@ 10.24 * @return Link to be invoked at call site. 10.25 */ 10.26 public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) { 10.27 - return PrimitiveLookup.lookupPrimitive(request, Number.class, new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER); 10.28 + return PrimitiveLookup.lookupPrimitive(request, Number.class, new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER, PROTOFILTER); 10.29 } 10.30 10.31 @SuppressWarnings("unused") 10.32 @@ -330,6 +334,11 @@ 10.33 return new NativeNumber(((Number)receiver).doubleValue()); 10.34 } 10.35 10.36 + @SuppressWarnings("unused") 10.37 + private static Object protoFilter(final Object object) { 10.38 + return Global.instance().getNumberPrototype(); 10.39 + } 10.40 + 10.41 private static double getNumberValue(final Object self) { 10.42 if (self instanceof Number) { 10.43 return ((Number)self).doubleValue(); 10.44 @@ -378,7 +387,7 @@ 10.45 return str; 10.46 } 10.47 10.48 - private static MethodHandle findWrapFilter() { 10.49 - return MH.findStatic(MethodHandles.lookup(), NativeNumber.class, "wrapFilter", MH.type(NativeNumber.class, Object.class)); 10.50 + private static MethodHandle findOwnMH(final String name, final MethodType type) { 10.51 + return MH.findStatic(MethodHandles.lookup(), NativeNumber.class, name, type); 10.52 } 10.53 }
11.1 --- a/src/jdk/nashorn/internal/objects/NativeString.java Wed Mar 12 16:33:28 2014 +0100 11.2 +++ b/src/jdk/nashorn/internal/objects/NativeString.java Wed Mar 12 11:26:00 2014 +0100 11.3 @@ -32,6 +32,7 @@ 11.4 11.5 import java.lang.invoke.MethodHandle; 11.6 import java.lang.invoke.MethodHandles; 11.7 +import java.lang.invoke.MethodType; 11.8 import java.text.Collator; 11.9 import java.util.ArrayList; 11.10 import java.util.Arrays; 11.11 @@ -69,7 +70,10 @@ 11.12 11.13 private final CharSequence value; 11.14 11.15 - static final MethodHandle WRAPFILTER = findWrapFilter(); 11.16 + // Method handle to create an object wrapper for a primitive string 11.17 + private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeString.class, Object.class)); 11.18 + // Method handle to retrieve the String prototype object 11.19 + private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class)); 11.20 11.21 // initialized by nasgen 11.22 private static PropertyMap $nasgenmap$; 11.23 @@ -1199,7 +1203,7 @@ 11.24 */ 11.25 public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) { 11.26 final MethodHandle guard = NashornGuards.getInstanceOf2Guard(String.class, ConsString.class); 11.27 - return PrimitiveLookup.lookupPrimitive(request, guard, new NativeString((CharSequence)receiver), WRAPFILTER); 11.28 + return PrimitiveLookup.lookupPrimitive(request, guard, new NativeString((CharSequence)receiver), WRAPFILTER, PROTOFILTER); 11.29 } 11.30 11.31 @SuppressWarnings("unused") 11.32 @@ -1207,6 +1211,11 @@ 11.33 return new NativeString((CharSequence)receiver); 11.34 } 11.35 11.36 + @SuppressWarnings("unused") 11.37 + private static Object protoFilter(final Object object) { 11.38 + return Global.instance().getStringPrototype(); 11.39 + } 11.40 + 11.41 private static CharSequence getCharSequence(final Object self) { 11.42 if (self instanceof String || self instanceof ConsString) { 11.43 return (CharSequence)self; 11.44 @@ -1254,7 +1263,7 @@ 11.45 return key >= 0 && key < value.length(); 11.46 } 11.47 11.48 - private static MethodHandle findWrapFilter() { 11.49 - return MH.findStatic(MethodHandles.lookup(), NativeString.class, "wrapFilter", MH.type(NativeString.class, Object.class)); 11.50 + private static MethodHandle findOwnMH(final String name, final MethodType type) { 11.51 + return MH.findStatic(MethodHandles.lookup(), NativeString.class, name, type); 11.52 } 11.53 }
12.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Wed Mar 12 16:33:28 2014 +0100 12.2 +++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Wed Mar 12 11:26:00 2014 +0100 12.3 @@ -75,7 +75,7 @@ 12.4 private static final Object LAZY_PROTOTYPE = new Object(); 12.5 12.6 private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs, final Global global) { 12.7 - super(name, invokeHandle, getInitialMap(), null, specs, false, true, true); 12.8 + super(name, invokeHandle, getInitialMap(), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); 12.9 init(global); 12.10 } 12.11 12.12 @@ -92,7 +92,7 @@ 12.13 } 12.14 12.15 private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs, final Global global) { 12.16 - super(name, invokeHandle, map.addAll(getInitialMap()), null, specs, false, true, true); 12.17 + super(name, invokeHandle, map.addAll(getInitialMap()), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); 12.18 init(global); 12.19 } 12.20 12.21 @@ -109,8 +109,8 @@ 12.22 this(name, invokeHandle, map, specs, Global.instance()); 12.23 } 12.24 12.25 - private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor, final Global global) { 12.26 - super(name, methodHandle, getMap(global, isStrict), scope, specs, isStrict, isBuiltin, isConstructor); 12.27 + private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags, final Global global) { 12.28 + super(name, methodHandle, getMap(global, isStrict(flags)), scope, specs, flags); 12.29 init(global); 12.30 } 12.31 12.32 @@ -121,12 +121,10 @@ 12.33 * @param methodHandle handle for invocation 12.34 * @param scope scope object 12.35 * @param specs specialized versions of this method, if available, null otherwise 12.36 - * @param isStrict are we in strict mode 12.37 - * @param isBuiltin is this a built-in function 12.38 - * @param isConstructor can the function be used as a constructor (most can; some built-ins are restricted). 12.39 + * @param flags {@link ScriptFunctionData} flags 12.40 */ 12.41 - ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) { 12.42 - this(name, methodHandle, scope, specs, isStrict, isBuiltin, isConstructor, Global.instance()); 12.43 + ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags) { 12.44 + this(name, methodHandle, scope, specs, flags, Global.instance()); 12.45 } 12.46 12.47 private ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope, final Global global) { 12.48 @@ -173,6 +171,10 @@ 12.49 return newMap; 12.50 } 12.51 12.52 + private static boolean isStrict(final int flags) { 12.53 + return (flags & ScriptFunctionData.IS_STRICT) != 0; 12.54 + } 12.55 + 12.56 // Choose the map based on strict mode! 12.57 private static PropertyMap getMap(final Global global, final boolean strict) { 12.58 return strict ? getInitialStrictMap() : getInitialMap(); 12.59 @@ -211,7 +213,7 @@ 12.60 * @return new ScriptFunction 12.61 */ 12.62 static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) { 12.63 - final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, false, true, false); 12.64 + final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, ScriptFunctionData.IS_BUILTIN); 12.65 func.setPrototype(UNDEFINED); 12.66 // Non-constructor built-in functions do not have "prototype" property 12.67 func.deleteOwnProperty(func.getMap().findProperty("prototype"));
13.1 --- a/src/jdk/nashorn/internal/parser/Parser.java Wed Mar 12 16:33:28 2014 +0100 13.2 +++ b/src/jdk/nashorn/internal/parser/Parser.java Wed Mar 12 11:26:00 2014 +0100 13.3 @@ -1799,6 +1799,7 @@ 13.4 case THIS: 13.5 final String name = type.getName(); 13.6 next(); 13.7 + lc.setFlag(lc.getCurrentFunction(), FunctionNode.USES_THIS); 13.8 return new IdentNode(primaryToken, finish, name); 13.9 case IDENT: 13.10 final IdentNode ident = getIdent();
14.1 --- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java Wed Mar 12 16:33:28 2014 +0100 14.2 +++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java Wed Mar 12 11:26:00 2014 +0100 14.3 @@ -141,10 +141,12 @@ 14.4 private Class<?> currentType; 14.5 14.6 /** 14.7 - * Delegate constructor. This is used when adding properties to the Global scope, which 14.8 - * is necessary for outermost levels in a script (the ScriptObject is represented by 14.9 - * a JO-prefixed ScriptObject class, but the properties need to be in the Global scope 14.10 - * and are thus rebound with that as receiver 14.11 + * Delegate constructor for bound properties. This is used for properties created by 14.12 + * {@link ScriptRuntime#mergeScope} and the Nashorn {@code Object.bindProperties} method. 14.13 + * The former is used to add a script's defined globals to the current global scope while 14.14 + * still storing them in a JO-prefixed ScriptObject class. 14.15 + * 14.16 + * <p>All properties created by this constructor have the {@link #IS_BOUND} flag set.</p> 14.17 * 14.18 * @param property accessor property to rebind 14.19 * @param delegate delegate object to rebind receiver to 14.20 @@ -157,6 +159,8 @@ 14.21 this.objectGetter = bindTo(property.ensureObjectGetter(), delegate); 14.22 this.objectSetter = bindTo(property.ensureObjectSetter(), delegate); 14.23 14.24 + // Properties created this way are bound to a delegate 14.25 + this.flags |= IS_BOUND; 14.26 setCurrentType(property.getCurrentType()); 14.27 } 14.28
15.1 --- a/src/jdk/nashorn/internal/runtime/Context.java Wed Mar 12 16:33:28 2014 +0100 15.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java Wed Mar 12 11:26:00 2014 +0100 15.3 @@ -36,6 +36,8 @@ 15.4 import java.io.PrintWriter; 15.5 import java.lang.invoke.MethodHandle; 15.6 import java.lang.invoke.MethodHandles; 15.7 +import java.lang.ref.ReferenceQueue; 15.8 +import java.lang.ref.SoftReference; 15.9 import java.lang.reflect.Modifier; 15.10 import java.util.concurrent.atomic.AtomicLong; 15.11 import java.net.MalformedURLException; 15.12 @@ -47,6 +49,7 @@ 15.13 import java.security.Permissions; 15.14 import java.security.PrivilegedAction; 15.15 import java.security.ProtectionDomain; 15.16 +import java.util.LinkedHashMap; 15.17 import java.util.Map; 15.18 15.19 import jdk.internal.org.objectweb.asm.ClassReader; 15.20 @@ -156,6 +159,9 @@ 15.21 15.22 private static final ThreadLocal<ScriptObject> currentGlobal = new ThreadLocal<>(); 15.23 15.24 + // class cache 15.25 + private ClassCache classCache; 15.26 + 15.27 /** 15.28 * Get the current global scope 15.29 * @return the current global scope 15.30 @@ -349,6 +355,11 @@ 15.31 this.classPathLoader = null; 15.32 } 15.33 15.34 + final int cacheSize = env._class_cache_size; 15.35 + if (cacheSize > 0) { 15.36 + classCache = new ClassCache(cacheSize); 15.37 + } 15.38 + 15.39 // print version info if asked. 15.40 if (env._version) { 15.41 getErr().println("nashorn " + Version.version()); 15.42 @@ -660,7 +671,7 @@ 15.43 public static void checkPackageAccess(final String pkgName) { 15.44 final SecurityManager sm = System.getSecurityManager(); 15.45 if (sm != null) { 15.46 - checkPackageAccess(sm, pkgName.endsWith(".")? pkgName : pkgName + "."); 15.47 + checkPackageAccess(sm, pkgName.endsWith(".") ? pkgName : pkgName + "."); 15.48 } 15.49 } 15.50 15.51 @@ -926,16 +937,10 @@ 15.52 // start with no errors, no warnings. 15.53 errMan.reset(); 15.54 15.55 - GlobalObject global = null; 15.56 - Class<?> script; 15.57 - 15.58 - if (env._class_cache_size > 0) { 15.59 - global = (GlobalObject)Context.getGlobalTrusted(); 15.60 - script = global.findCachedClass(source); 15.61 - if (script != null) { 15.62 - Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile."); 15.63 - return script; 15.64 - } 15.65 + Class<?> script = findCachedClass(source); 15.66 + if (script != null) { 15.67 + Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile."); 15.68 + return script; 15.69 } 15.70 15.71 final FunctionNode functionNode = new Parser(env, source, errMan, strict).parse(); 15.72 @@ -964,10 +969,7 @@ 15.73 15.74 final FunctionNode newFunctionNode = compiler.compile(functionNode); 15.75 script = compiler.install(newFunctionNode); 15.76 - 15.77 - if (global != null) { 15.78 - global.cacheClass(source, script); 15.79 - } 15.80 + cacheClass(source, script); 15.81 15.82 return script; 15.83 } 15.84 @@ -989,4 +991,60 @@ 15.85 private long getUniqueScriptId() { 15.86 return uniqueScriptId.getAndIncrement(); 15.87 } 15.88 + 15.89 + /** 15.90 + * Cache for compiled script classes. 15.91 + */ 15.92 + @SuppressWarnings("serial") 15.93 + private static class ClassCache extends LinkedHashMap<Source, ClassReference> { 15.94 + private final int size; 15.95 + private final ReferenceQueue<Class<?>> queue; 15.96 + 15.97 + ClassCache(int size) { 15.98 + super(size, 0.75f, true); 15.99 + this.size = size; 15.100 + this.queue = new ReferenceQueue<>(); 15.101 + } 15.102 + 15.103 + void cache(final Source source, final Class<?> clazz) { 15.104 + put(source, new ClassReference(clazz, queue, source)); 15.105 + } 15.106 + 15.107 + @Override 15.108 + protected boolean removeEldestEntry(final Map.Entry<Source, ClassReference> eldest) { 15.109 + return size() > size; 15.110 + } 15.111 + 15.112 + @Override 15.113 + public ClassReference get(Object key) { 15.114 + for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) { 15.115 + remove(ref.source); 15.116 + } 15.117 + return super.get(key); 15.118 + } 15.119 + 15.120 + } 15.121 + 15.122 + private static class ClassReference extends SoftReference<Class<?>> { 15.123 + private final Source source; 15.124 + 15.125 + ClassReference(final Class<?> clazz, final ReferenceQueue<Class<?>> queue, final Source source) { 15.126 + super(clazz, queue); 15.127 + this.source = source; 15.128 + } 15.129 + } 15.130 + 15.131 + // Class cache management 15.132 + private Class<?> findCachedClass(final Source source) { 15.133 + ClassReference ref = classCache == null ? null : classCache.get(source); 15.134 + return ref != null ? ref.get() : null; 15.135 + } 15.136 + 15.137 + private void cacheClass(final Source source, final Class<?> clazz) { 15.138 + if (classCache != null) { 15.139 + classCache.cache(source, clazz); 15.140 + } 15.141 + } 15.142 + 15.143 + 15.144 }
16.1 --- a/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Wed Mar 12 16:33:28 2014 +0100 16.2 +++ b/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Wed Mar 12 11:26:00 2014 +0100 16.3 @@ -38,31 +38,27 @@ 16.4 /** 16.5 * Constructor - used for bind 16.6 * 16.7 - * @param name name 16.8 - * @param arity arity 16.9 - * @param functions precompiled code 16.10 - * @param isStrict strict 16.11 - * @param isBuiltin builtin 16.12 - * @param isConstructor constructor 16.13 + * @param name name 16.14 + * @param arity arity 16.15 + * @param functions precompiled code 16.16 + * @param flags {@link ScriptFunctionData} flags 16.17 */ 16.18 - FinalScriptFunctionData(final String name, int arity, CompiledFunctions functions, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) { 16.19 - super(name, arity, isStrict, isBuiltin, isConstructor); 16.20 + FinalScriptFunctionData(final String name, final int arity, final CompiledFunctions functions, final int flags) { 16.21 + super(name, arity, flags); 16.22 code.addAll(functions); 16.23 } 16.24 16.25 /** 16.26 - * Constructor - used from ScriptFunction. This assumes that we have code alraedy for the 16.27 + * Constructor - used from ScriptFunction. This assumes that we have code already for the 16.28 * method (typically a native method) and possibly specializations. 16.29 * 16.30 - * @param name name 16.31 - * @param mh method handle for generic version of method 16.32 - * @param specs specializations 16.33 - * @param isStrict strict 16.34 - * @param isBuiltin builtin 16.35 - * @param isConstructor constructor 16.36 + * @param name name 16.37 + * @param mh method handle for generic version of method 16.38 + * @param specs specializations 16.39 + * @param flags {@link ScriptFunctionData} flags 16.40 */ 16.41 - FinalScriptFunctionData(final String name, final MethodHandle mh, final MethodHandle[] specs, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) { 16.42 - super(name, arity(mh), isStrict, isBuiltin, isConstructor); 16.43 + FinalScriptFunctionData(final String name, final MethodHandle mh, final MethodHandle[] specs, final int flags) { 16.44 + super(name, arity(mh), flags); 16.45 16.46 addInvoker(mh); 16.47 if (specs != null) {
17.1 --- a/src/jdk/nashorn/internal/runtime/GlobalObject.java Wed Mar 12 16:33:28 2014 +0100 17.2 +++ b/src/jdk/nashorn/internal/runtime/GlobalObject.java Wed Mar 12 11:26:00 2014 +0100 17.3 @@ -211,22 +211,6 @@ 17.4 public Object getDefaultValue(ScriptObject sobj, Class<?> typeHint); 17.5 17.6 /** 17.7 - * Find the compiled Class for the given script source, if available 17.8 - * 17.9 - * @param source Source object of the script 17.10 - * @return compiled Class object or null 17.11 - */ 17.12 - public Class<?> findCachedClass(Source source); 17.13 - 17.14 - /** 17.15 - * Put the Source associated Class object in the Source-to-Class cache 17.16 - * 17.17 - * @param source Source of the script 17.18 - * @param clazz compiled Class object for the source 17.19 - */ 17.20 - public void cacheClass(Source source, Class<?> clazz); 17.21 - 17.22 - /** 17.23 * Get cached InvokeByName object for the given key 17.24 * @param key key to be associated with InvokeByName object 17.25 * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
18.1 --- a/src/jdk/nashorn/internal/runtime/Property.java Wed Mar 12 16:33:28 2014 +0100 18.2 +++ b/src/jdk/nashorn/internal/runtime/Property.java Wed Mar 12 11:26:00 2014 +0100 18.3 @@ -84,9 +84,13 @@ 18.4 /** Can this property be undefined? */ 18.5 public static final int CAN_BE_UNDEFINED = 1 << 8; 18.6 18.7 - /* Is this a function declaration property ? */ 18.8 + /** Is this a function declaration property ? */ 18.9 public static final int IS_FUNCTION_DECLARATION = 1 << 9; 18.10 18.11 + /** Is this property bound to a receiver? This means get/set operations will be delegated to 18.12 + * a statically defined object instead of the object passed as callsite parameter. */ 18.13 + public static final int IS_BOUND = 1 << 10; 18.14 + 18.15 /** Property key. */ 18.16 private final String key; 18.17 18.18 @@ -252,6 +256,16 @@ 18.19 } 18.20 18.21 /** 18.22 + * Is this property bound to a receiver? If this method returns {@code true} get and set operations 18.23 + * will be delegated to a statically bound object instead of the object passed as parameter. 18.24 + * 18.25 + * @return true if this is a bound property 18.26 + */ 18.27 + public boolean isBound() { 18.28 + return (flags & IS_BOUND) == IS_BOUND; 18.29 + } 18.30 + 18.31 + /** 18.32 * Does this property use any slots in the spill array described in 18.33 * {@link Property#isSpill}? In that case how many. Currently a property 18.34 * only uses max one spill slot, but this may change in future representations
19.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Mar 12 16:33:28 2014 +0100 19.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Mar 12 11:26:00 2014 +0100 19.3 @@ -103,9 +103,7 @@ 19.4 public RecompilableScriptFunctionData(final FunctionNode functionNode, final CodeInstaller<ScriptEnvironment> installer, final String allocatorClassName, final PropertyMap allocatorMap) { 19.5 super(functionName(functionNode), 19.6 functionNode.getParameters().size(), 19.7 - functionNode.isStrict(), 19.8 - false, 19.9 - true); 19.10 + getFlags(functionNode)); 19.11 19.12 this.functionNode = functionNode; 19.13 this.source = functionNode.getSource(); 19.14 @@ -129,10 +127,11 @@ 19.15 final StringBuilder sb = new StringBuilder(); 19.16 19.17 if (source != null) { 19.18 - sb.append(source.getName()) 19.19 - .append(':') 19.20 - .append(functionNode.getLineNumber()) 19.21 - .append(' '); 19.22 + sb.append(source.getName()); 19.23 + if (functionNode != null) { 19.24 + sb.append(':').append(functionNode.getLineNumber()); 19.25 + } 19.26 + sb.append(' '); 19.27 } 19.28 19.29 return sb.toString() + super.toString(); 19.30 @@ -159,6 +158,20 @@ 19.31 return Token.toDesc(TokenType.FUNCTION, position, length); 19.32 } 19.33 19.34 + private static int getFlags(final FunctionNode functionNode) { 19.35 + int flags = IS_CONSTRUCTOR; 19.36 + if (functionNode.isStrict()) { 19.37 + flags |= IS_STRICT; 19.38 + } 19.39 + if (functionNode.needsCallee()) { 19.40 + flags |= NEEDS_CALLEE; 19.41 + } 19.42 + if (functionNode.usesThis() || functionNode.hasEval()) { 19.43 + flags |= USES_THIS; 19.44 + } 19.45 + return flags; 19.46 + } 19.47 + 19.48 @Override 19.49 ScriptObject allocate(final PropertyMap map) { 19.50 try { 19.51 @@ -182,41 +195,42 @@ 19.52 return allocatorMap; 19.53 } 19.54 19.55 + 19.56 + @Override 19.57 + protected void ensureCompiled() { 19.58 + if (functionNode != null && functionNode.isLazy()) { 19.59 + Compiler.LOG.info("Trampoline hit: need to do lazy compilation of '", functionNode.getName(), "'"); 19.60 + final Compiler compiler = new Compiler(installer); 19.61 + functionNode = compiler.compile(functionNode); 19.62 + assert !functionNode.isLazy(); 19.63 + compiler.install(functionNode); 19.64 + flags = getFlags(functionNode); 19.65 + } 19.66 + } 19.67 + 19.68 @Override 19.69 protected synchronized void ensureCodeGenerated() { 19.70 - if (!code.isEmpty()) { 19.71 - return; // nothing to do, we have code, at least some. 19.72 - } 19.73 + if (!code.isEmpty()) { 19.74 + return; // nothing to do, we have code, at least some. 19.75 + } 19.76 19.77 - if (functionNode.isLazy()) { 19.78 - Compiler.LOG.info("Trampoline hit: need to do lazy compilation of '", functionNode.getName(), "'"); 19.79 - final Compiler compiler = new Compiler(installer); 19.80 - functionNode = compiler.compile(functionNode); 19.81 - assert !functionNode.isLazy(); 19.82 - compiler.install(functionNode); 19.83 + ensureCompiled(); 19.84 19.85 - /* 19.86 - * We don't need to update any flags - varArgs and needsCallee are instrincic 19.87 - * in the function world we need to get a destination node from the compile instead 19.88 - * and replace it with our function node. TODO 19.89 - */ 19.90 - } 19.91 + /* 19.92 + * We can't get to this program point unless we have bytecode, either from 19.93 + * eager compilation or from running a lazy compile on the lines above 19.94 + */ 19.95 19.96 - /* 19.97 - * We can't get to this program point unless we have bytecode, either from 19.98 - * eager compilation or from running a lazy compile on the lines above 19.99 - */ 19.100 + assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode); 19.101 19.102 - assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode); 19.103 + // code exists - look it up and add it into the automatically sorted invoker list 19.104 + addCode(functionNode); 19.105 19.106 - // code exists - look it up and add it into the automatically sorted invoker list 19.107 - addCode(functionNode); 19.108 - 19.109 - if (! functionNode.canSpecialize()) { 19.110 - // allow GC to claim IR stuff that is not needed anymore 19.111 - functionNode = null; 19.112 - installer = null; 19.113 - } 19.114 + if (! functionNode.canSpecialize()) { 19.115 + // allow GC to claim IR stuff that is not needed anymore 19.116 + functionNode = null; 19.117 + installer = null; 19.118 + } 19.119 } 19.120 19.121 private MethodHandle addCode(final FunctionNode fn) {
20.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Mar 12 16:33:28 2014 +0100 20.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Mar 12 11:26:00 2014 +0100 20.3 @@ -66,6 +66,8 @@ 20.4 20.5 private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", Object.class, Object.class); 20.6 20.7 + private static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class); 20.8 + 20.9 /** method handle to scope getter for this ScriptFunction */ 20.10 public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class); 20.11 20.12 @@ -91,9 +93,7 @@ 20.13 * @param map property map 20.14 * @param scope scope 20.15 * @param specs specialized version of this function - other method handles 20.16 - * @param strict is this a strict mode function? 20.17 - * @param builtin is this a built in function? 20.18 - * @param isConstructor is this a constructor? 20.19 + * @param flags {@link ScriptFunctionData} flags 20.20 */ 20.21 protected ScriptFunction( 20.22 final String name, 20.23 @@ -101,11 +101,9 @@ 20.24 final PropertyMap map, 20.25 final ScriptObject scope, 20.26 final MethodHandle[] specs, 20.27 - final boolean strict, 20.28 - final boolean builtin, 20.29 - final boolean isConstructor) { 20.30 + final int flags) { 20.31 20.32 - this(new FinalScriptFunctionData(name, methodHandle, specs, strict, builtin, isConstructor), map, scope); 20.33 + this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope); 20.34 } 20.35 20.36 /** 20.37 @@ -480,6 +478,13 @@ 20.38 return ((GlobalObject)Context.getGlobalTrusted()).wrapAsObject(obj); 20.39 } 20.40 20.41 + 20.42 + @SuppressWarnings("unused") 20.43 + private static Object globalFilter(final Object object) { 20.44 + // replace whatever we get with the current global object 20.45 + return Context.getGlobalTrusted(); 20.46 + } 20.47 + 20.48 /** 20.49 * dyn:call call site signature: (callee, thiz, [args...]) 20.50 * generated method signature: (callee, thiz, [args...]) 20.51 @@ -495,11 +500,11 @@ 20.52 @Override 20.53 protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) { 20.54 final MethodType type = desc.getMethodType(); 20.55 + final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc); 20.56 20.57 if (request.isCallSiteUnstable()) { 20.58 - // (this, callee, args...) => (this, callee, args[]) 20.59 - final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class, 20.60 - type.parameterCount() - 2); 20.61 + // (callee, this, args...) => (callee, this, args[]) 20.62 + final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class, type.parameterCount() - 2); 20.63 20.64 // If call site is statically typed to take a ScriptFunction, we don't need a guard, otherwise we need a 20.65 // generic "is this a ScriptFunction?" guard. 20.66 @@ -510,17 +515,12 @@ 20.67 MethodHandle boundHandle; 20.68 MethodHandle guard = null; 20.69 20.70 - final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc); 20.71 - 20.72 if (data.needsCallee()) { 20.73 final MethodHandle callHandle = getBestInvoker(type, request.getArguments()); 20.74 - if (scopeCall) { 20.75 + if (scopeCall && needsWrappedThis()) { 20.76 // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined 20.77 - // (callee, this, args...) => (callee, args...) 20.78 - boundHandle = MH.insertArguments(callHandle, 1, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED); 20.79 - // (callee, args...) => (callee, [this], args...) 20.80 - boundHandle = MH.dropArguments(boundHandle, 1, Object.class); 20.81 - 20.82 + // (callee, this, args...) => (callee, [this], args...) 20.83 + boundHandle = MH.filterArguments(callHandle, 1, GLOBALFILTER); 20.84 } else { 20.85 // It's already (callee, this, args...), just what we need 20.86 boundHandle = callHandle; 20.87 @@ -531,12 +531,12 @@ 20.88 // NOTE: the only built-in named "extend" is NativeJava.extend. As a special-case we're binding the 20.89 // current lookup as its "this" so it can do security-sensitive creation of adapter classes. 20.90 boundHandle = MH.dropArguments(MH.bindTo(callHandle, desc.getLookup()), 0, Object.class, Object.class); 20.91 - } else if (scopeCall) { 20.92 + } else if (scopeCall && needsWrappedThis()) { 20.93 // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined 20.94 - // (this, args...) => (args...) 20.95 - boundHandle = MH.bindTo(callHandle, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED); 20.96 - // (args...) => ([callee], [this], args...) 20.97 - boundHandle = MH.dropArguments(boundHandle, 0, Object.class, Object.class); 20.98 + // (this, args...) => ([this], args...) 20.99 + boundHandle = MH.filterArguments(callHandle, 0, GLOBALFILTER); 20.100 + // ([this], args...) => ([callee], [this], args...) 20.101 + boundHandle = MH.dropArguments(boundHandle, 0, Object.class); 20.102 } else { 20.103 // (this, args...) => ([callee], this, args...) 20.104 boundHandle = MH.dropArguments(callHandle, 0, Object.class);
21.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Mar 12 16:33:28 2014 +0100 21.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Mar 12 11:26:00 2014 +0100 21.3 @@ -47,33 +47,44 @@ 21.4 /** All versions of this function that have been generated to code */ 21.5 protected final CompiledFunctions code; 21.6 21.7 + /** Function flags */ 21.8 + protected int flags; 21.9 + 21.10 private int arity; 21.11 21.12 - private final boolean isStrict; 21.13 - 21.14 - private final boolean isBuiltin; 21.15 - 21.16 - private final boolean isConstructor; 21.17 - 21.18 private static final MethodHandle NEWFILTER = findOwnMH("newFilter", Object.class, Object.class, Object.class); 21.19 private static final MethodHandle BIND_VAR_ARGS = findOwnMH("bindVarArgs", Object[].class, Object[].class, Object[].class); 21.20 21.21 + /** Is this a strict mode function? */ 21.22 + public static final int IS_STRICT = 1 << 0; 21.23 + /** Is this a built-in function? */ 21.24 + public static final int IS_BUILTIN = 1 << 1; 21.25 + /** Is this a constructor function? */ 21.26 + public static final int IS_CONSTRUCTOR = 1 << 2; 21.27 + /** Does this function expect a callee argument? */ 21.28 + public static final int NEEDS_CALLEE = 1 << 3; 21.29 + /** Does this function make use of the this-object argument? */ 21.30 + public static final int USES_THIS = 1 << 4; 21.31 + 21.32 + /** Flag for strict or built-in functions */ 21.33 + public static final int IS_STRICT_OR_BUILTIN = IS_STRICT | IS_BUILTIN; 21.34 + /** Flag for built-in constructors */ 21.35 + public static final int IS_BUILTIN_CONSTRUCTOR = IS_BUILTIN | IS_CONSTRUCTOR; 21.36 + /** Flag for strict constructors */ 21.37 + public static final int IS_STRICT_CONSTRUCTOR = IS_STRICT | IS_CONSTRUCTOR; 21.38 + 21.39 /** 21.40 * Constructor 21.41 * 21.42 * @param name script function name 21.43 * @param arity arity 21.44 - * @param isStrict is the function strict 21.45 - * @param isBuiltin is the function built in 21.46 - * @param isConstructor is the function a constructor 21.47 + * @param flags the function flags 21.48 */ 21.49 - ScriptFunctionData(final String name, final int arity, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) { 21.50 - this.name = name; 21.51 - this.arity = arity; 21.52 - this.code = new CompiledFunctions(); 21.53 - this.isStrict = isStrict; 21.54 - this.isBuiltin = isBuiltin; 21.55 - this.isConstructor = isConstructor; 21.56 + ScriptFunctionData(final String name, final int arity, final int flags) { 21.57 + this.name = name; 21.58 + this.arity = arity; 21.59 + this.code = new CompiledFunctions(); 21.60 + this.flags = flags; 21.61 } 21.62 21.63 final int getArity() { 21.64 @@ -105,21 +116,21 @@ 21.65 * @return true if strict, false otherwise 21.66 */ 21.67 public boolean isStrict() { 21.68 - return isStrict; 21.69 + return (flags & IS_STRICT) != 0; 21.70 } 21.71 21.72 boolean isBuiltin() { 21.73 - return isBuiltin; 21.74 + return (flags & IS_BUILTIN) != 0; 21.75 } 21.76 21.77 boolean isConstructor() { 21.78 - return isConstructor; 21.79 + return (flags & IS_CONSTRUCTOR) != 0; 21.80 } 21.81 21.82 boolean needsCallee() { 21.83 - // we don't know if we need a callee or not unless we are generated 21.84 - ensureCodeGenerated(); 21.85 - return code.needsCallee(); 21.86 + // we don't know if we need a callee or not unless code has been compiled 21.87 + ensureCompiled(); 21.88 + return (flags & NEEDS_CALLEE) != 0; 21.89 } 21.90 21.91 /** 21.92 @@ -128,7 +139,7 @@ 21.93 * @return true if this argument must be an object 21.94 */ 21.95 boolean needsWrappedThis() { 21.96 - return !isStrict && !isBuiltin; 21.97 + return (flags & USES_THIS) != 0 && (flags & IS_STRICT_OR_BUILTIN) == 0; 21.98 } 21.99 21.100 String toSource() { 21.101 @@ -202,6 +213,15 @@ 21.102 } 21.103 21.104 /** 21.105 + * If we can have lazy code generation, this is a hook to ensure that the code has been compiled. 21.106 + * This does not guarantee the code been installed in this {@code ScriptFunctionData} instance; 21.107 + * use {@link #ensureCodeGenerated()} to install the actual method handles. 21.108 + */ 21.109 + protected void ensureCompiled() { 21.110 + //empty 21.111 + } 21.112 + 21.113 + /** 21.114 * Return a generic Object/Object invoker for this method. It will ensure code 21.115 * is generated, get the most generic of all versions of this function and adapt it 21.116 * to Objects. 21.117 @@ -259,6 +279,8 @@ 21.118 21.119 final Object[] allArgs = args == null ? ScriptRuntime.EMPTY_ARRAY : args; 21.120 final int length = args == null ? 0 : args.length; 21.121 + // Clear the callee and this flags 21.122 + final int boundFlags = flags & ~NEEDS_CALLEE & ~USES_THIS; 21.123 21.124 CompiledFunctions boundList = new CompiledFunctions(); 21.125 if (code.size() == 1) { 21.126 @@ -273,8 +295,7 @@ 21.127 boundList.add(bind(inv, fn, self, allArgs)); 21.128 } 21.129 21.130 - ScriptFunctionData boundData = new FinalScriptFunctionData(name, arity == -1 ? -1 : Math.max(0, arity - length), boundList, isStrict(), isBuiltin(), isConstructor()); 21.131 - return boundData; 21.132 + return new FinalScriptFunctionData(name, arity == -1 ? -1 : Math.max(0, arity - length), boundList, boundFlags); 21.133 } 21.134 21.135 /**
22.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Mar 12 16:33:28 2014 +0100 22.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Mar 12 11:26:00 2014 +0100 22.3 @@ -66,6 +66,7 @@ 22.4 import jdk.nashorn.internal.lookup.MethodHandleFactory; 22.5 import jdk.nashorn.internal.objects.AccessorPropertyDescriptor; 22.6 import jdk.nashorn.internal.objects.DataPropertyDescriptor; 22.7 +import jdk.nashorn.internal.objects.Global; 22.8 import jdk.nashorn.internal.runtime.arrays.ArrayData; 22.9 import jdk.nashorn.internal.runtime.arrays.ArrayIndex; 22.10 import jdk.nashorn.internal.runtime.linker.Bootstrap; 22.11 @@ -131,7 +132,8 @@ 22.12 22.13 static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class); 22.14 static final MethodHandle SETPROTOCHECK = findOwnMH("setProtoCheck", void.class, Object.class); 22.15 - static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class); 22.16 + static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class, boolean.class); 22.17 + static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class); 22.18 22.19 static final MethodHandle SETFIELD = findOwnMH("setField", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class); 22.20 static final MethodHandle SETSPILL = findOwnMH("setSpill", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class); 22.21 @@ -225,6 +227,7 @@ 22.22 final Property oldProp = newMap.findProperty(key); 22.23 if (oldProp == null) { 22.24 if (property instanceof UserAccessorProperty) { 22.25 + // Note: we copy accessor functions to this object which is semantically different from binding. 22.26 final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source)); 22.27 newMap = newMap.addPropertyNoHistory(prop); 22.28 } else { 22.29 @@ -975,17 +978,6 @@ 22.30 } 22.31 22.32 /** 22.33 - * Get the object value of a property 22.34 - * 22.35 - * @param find {@link FindProperty} lookup result 22.36 - * 22.37 - * @return the value of the property 22.38 - */ 22.39 - protected static Object getObjectValue(final FindProperty find) { 22.40 - return find.getObjectValue(); 22.41 - } 22.42 - 22.43 - /** 22.44 * Return methodHandle of value function for call. 22.45 * 22.46 * @param find data from find property. 22.47 @@ -995,7 +987,7 @@ 22.48 * @return value of property as a MethodHandle or null. 22.49 */ 22.50 protected MethodHandle getCallMethodHandle(final FindProperty find, final MethodType type, final String bindName) { 22.51 - return getCallMethodHandle(getObjectValue(find), type, bindName); 22.52 + return getCallMethodHandle(find.getObjectValue(), type, bindName); 22.53 } 22.54 22.55 /** 22.56 @@ -1019,7 +1011,7 @@ 22.57 * @return Value of property. 22.58 */ 22.59 public final Object getWithProperty(final Property property) { 22.60 - return getObjectValue(new FindProperty(this, this, property)); 22.61 + return new FindProperty(this, this, property).getObjectValue(); 22.62 } 22.63 22.64 /** 22.65 @@ -1740,7 +1732,7 @@ 22.66 protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) { 22.67 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 22.68 if (request.isCallSiteUnstable() || hasWithScope()) { 22.69 - return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator)); 22.70 + return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator), isScope() && NashornCallSiteDescriptor.isScope(desc)); 22.71 } 22.72 22.73 final FindProperty find = findProperty(name, true); 22.74 @@ -1765,9 +1757,8 @@ 22.75 final Property property = find.getProperty(); 22.76 methodHandle = find.getGetter(returnType); 22.77 22.78 - final boolean noGuard = ObjectClassGenerator.OBJECT_FIELDS_ONLY && NashornCallSiteDescriptor.isFastScope(desc) && !property.canChangeType(); 22.79 - // getMap() is fine as we have the prototype switchpoint depending on where the property was found 22.80 - final MethodHandle guard = noGuard ? null : NashornGuards.getMapGuard(getMap()); 22.81 + // Get the appropriate guard for this callsite and property. 22.82 + final MethodHandle guard = NashornGuards.getGuard(this, property, desc); 22.83 final ScriptObject owner = find.getOwner(); 22.84 22.85 if (methodHandle != null) { 22.86 @@ -1777,31 +1768,32 @@ 22.87 } 22.88 22.89 if (!property.hasGetterFunction(owner)) { 22.90 - // If not a scope bind to actual prototype as changing prototype will change the property map. 22.91 - // For scopes we install a filter that replaces the self object with the prototype owning the property. 22.92 - methodHandle = isScope() ? 22.93 - addProtoFilter(methodHandle, find.getProtoChainLength()) : 22.94 - bindTo(methodHandle, owner); 22.95 + // Add a filter that replaces the self object with the prototype owning the property. 22.96 + methodHandle = addProtoFilter(methodHandle, find.getProtoChainLength()); 22.97 } 22.98 - return new GuardedInvocation(methodHandle, noGuard ? null : getProtoSwitchPoint(name, owner), guard); 22.99 + return new GuardedInvocation(methodHandle, guard == null ? null : getProtoSwitchPoint(name, owner), guard); 22.100 } 22.101 22.102 assert !NashornCallSiteDescriptor.isFastScope(desc); 22.103 return new GuardedInvocation(Lookup.emptyGetter(returnType), getProtoSwitchPoint(name, owner), guard); 22.104 } 22.105 22.106 - private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) { 22.107 - final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod); 22.108 + private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, 22.109 + final boolean isMethod, final boolean isScope) { 22.110 + final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod, isScope); 22.111 final MethodHandle guard = getScriptObjectGuard(desc.getMethodType()); 22.112 return new GuardedInvocation(invoker, guard); 22.113 } 22.114 22.115 @SuppressWarnings("unused") 22.116 - private Object megamorphicGet(final String key, final boolean isMethod) { 22.117 + private Object megamorphicGet(final String key, final boolean isMethod, final boolean isScope) { 22.118 final FindProperty find = findProperty(key, true); 22.119 22.120 if (find != null) { 22.121 - return getObjectValue(find); 22.122 + return find.getObjectValue(); 22.123 + } 22.124 + if (isScope) { 22.125 + throw referenceError("not.defined", key); 22.126 } 22.127 22.128 return isMethod ? getNoSuchMethod(key) : invokeNoSuchProperty(key); 22.129 @@ -1996,6 +1988,15 @@ 22.130 } 22.131 } 22.132 22.133 + @SuppressWarnings("unused") 22.134 + private static Object globalFilter(final Object object) { 22.135 + ScriptObject sobj = (ScriptObject) object; 22.136 + while (sobj != null && !(sobj instanceof Global)) { 22.137 + sobj = sobj.getProto(); 22.138 + } 22.139 + return sobj; 22.140 + } 22.141 + 22.142 private static GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) { 22.143 final MethodType type = desc.getMethodType().insertParameterTypes(1, Object.class); 22.144 final GuardedInvocation inv = findSetIndexMethod(type, NashornCallSiteDescriptor.isStrict(desc)); 22.145 @@ -2041,7 +2042,7 @@ 22.146 return noSuchProperty(desc, request); 22.147 } 22.148 22.149 - final Object value = getObjectValue(find); 22.150 + final Object value = find.getObjectValue(); 22.151 if (! (value instanceof ScriptFunction)) { 22.152 return createEmptyGetter(desc, name); 22.153 } 22.154 @@ -2067,7 +2068,7 @@ 22.155 final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc); 22.156 22.157 if (find != null) { 22.158 - final Object value = getObjectValue(find); 22.159 + final Object value = find.getObjectValue(); 22.160 ScriptFunction func = null; 22.161 MethodHandle methodHandle = null; 22.162 22.163 @@ -2102,7 +2103,7 @@ 22.164 final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true); 22.165 22.166 if (find != null) { 22.167 - final Object func = getObjectValue(find); 22.168 + final Object func = find.getObjectValue(); 22.169 22.170 if (func instanceof ScriptFunction) { 22.171 return ScriptRuntime.apply((ScriptFunction)func, this, name); 22.172 @@ -2124,7 +2125,7 @@ 22.173 return invokeNoSuchProperty(name); 22.174 } 22.175 22.176 - final Object value = getObjectValue(find); 22.177 + final Object value = find.getObjectValue(); 22.178 if (! (value instanceof ScriptFunction)) { 22.179 return UNDEFINED; 22.180 } 22.181 @@ -2664,7 +2665,7 @@ 22.182 final FindProperty find = object.findProperty(key, false, false, this); 22.183 22.184 if (find != null) { 22.185 - return getObjectValue(find); 22.186 + return find.getObjectValue(); 22.187 } 22.188 } 22.189 22.190 @@ -2682,7 +2683,7 @@ 22.191 final FindProperty find = findProperty(key, true); 22.192 22.193 if (find != null) { 22.194 - return getObjectValue(find); 22.195 + return find.getObjectValue(); 22.196 } 22.197 } 22.198 22.199 @@ -2823,7 +2824,15 @@ 22.200 throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this)); 22.201 } 22.202 } else { 22.203 - spill(key, value); 22.204 + ScriptObject sobj = this; 22.205 + // undefined scope properties are set in the global object. 22.206 + if (isScope()) { 22.207 + while (sobj != null && !(sobj instanceof Global)) { 22.208 + sobj = sobj.getProto(); 22.209 + } 22.210 + assert sobj != null : "no parent global object in scope"; 22.211 + } 22.212 + sobj.spill(key, value); 22.213 } 22.214 } 22.215
23.1 --- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Wed Mar 12 16:33:28 2014 +0100 23.2 +++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Wed Mar 12 11:26:00 2014 +0100 23.3 @@ -31,7 +31,6 @@ 23.4 import java.lang.invoke.MethodHandle; 23.5 import jdk.internal.dynalink.CallSiteDescriptor; 23.6 import jdk.internal.dynalink.linker.GuardedInvocation; 23.7 -import jdk.nashorn.internal.codegen.ObjectClassGenerator; 23.8 import jdk.nashorn.internal.lookup.Lookup; 23.9 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; 23.10 import jdk.nashorn.internal.runtime.linker.NashornGuards; 23.11 @@ -104,21 +103,9 @@ 23.12 * @return the composed guarded invocation that represents the dynamic setter method for the property. 23.13 */ 23.14 GuardedInvocation createGuardedInvocation() { 23.15 - return new GuardedInvocation(methodHandle, getGuard()); 23.16 + return new GuardedInvocation(methodHandle, NashornGuards.getGuard(sobj, property, desc)); 23.17 } 23.18 23.19 - private MethodHandle getGuard() { 23.20 - return needsNoGuard() ? null : NashornGuards.getMapGuard(getMap()); 23.21 - } 23.22 - 23.23 - private boolean needsNoGuard() { 23.24 - return NashornCallSiteDescriptor.isFastScope(desc) && 23.25 - (ObjectClassGenerator.OBJECT_FIELDS_ONLY || isPropertyTypeStable()); 23.26 - } 23.27 - 23.28 - private boolean isPropertyTypeStable() { 23.29 - return property == null || !property.canChangeType(); 23.30 - } 23.31 } 23.32 23.33 private SetMethod createSetMethod() { 23.34 @@ -153,10 +140,7 @@ 23.35 23.36 final MethodHandle boundHandle; 23.37 if (!property.hasSetterFunction(find.getOwner()) && find.isInherited()) { 23.38 - // Bind or add prototype filter depending on whether this is a scope object. 23.39 - boundHandle = sobj.isScope() ? 23.40 - ScriptObject.addProtoFilter(methodHandle, find.getProtoChainLength()): 23.41 - ScriptObject.bindTo(methodHandle, find.getOwner()); 23.42 + boundHandle = ScriptObject.addProtoFilter(methodHandle, find.getProtoChainLength()); 23.43 } else { 23.44 boundHandle = methodHandle; 23.45 } 23.46 @@ -165,7 +149,7 @@ 23.47 23.48 private SetMethod createGlobalPropertySetter() { 23.49 final ScriptObject global = Context.getGlobalTrusted(); 23.50 - return new SetMethod(ScriptObject.bindTo(global.addSpill(getName()), global), null); 23.51 + return new SetMethod(MH.filterArguments(global.addSpill(getName()), 0, ScriptObject.GLOBALFILTER), null); 23.52 } 23.53 23.54 private SetMethod createNewPropertySetter() {
24.1 --- a/src/jdk/nashorn/internal/runtime/WithObject.java Wed Mar 12 16:33:28 2014 +0100 24.2 +++ b/src/jdk/nashorn/internal/runtime/WithObject.java Wed Mar 12 11:26:00 2014 +0100 24.3 @@ -88,6 +88,11 @@ 24.4 24.5 @Override 24.6 public GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request) { 24.7 + if (request.isCallSiteUnstable()) { 24.8 + // Fall back to megamorphic invocation which performs a complete lookup each time without further relinking. 24.9 + return super.lookup(desc, request); 24.10 + } 24.11 + 24.12 // With scopes can never be observed outside of Nashorn code, so all call sites that can address it will of 24.13 // necessity have a Nashorn descriptor - it is safe to cast. 24.14 final NashornCallSiteDescriptor ndesc = (NashornCallSiteDescriptor)desc; 24.15 @@ -265,7 +270,7 @@ 24.16 } 24.17 24.18 private static MethodHandle filter(final MethodHandle mh, final MethodHandle filter) { 24.19 - return MH.filterArguments(mh, 0, filter); 24.20 + return MH.filterArguments(mh, 0, filter.asType(filter.type().changeReturnType(mh.type().parameterType(0)))); 24.21 } 24.22 24.23 /**
25.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java Wed Mar 12 16:33:28 2014 +0100 25.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java Wed Mar 12 11:26:00 2014 +0100 25.3 @@ -29,6 +29,11 @@ 25.4 25.5 import java.lang.invoke.MethodHandle; 25.6 import java.lang.invoke.MethodHandles; 25.7 +import java.lang.ref.WeakReference; 25.8 +import jdk.internal.dynalink.CallSiteDescriptor; 25.9 +import jdk.nashorn.internal.codegen.ObjectClassGenerator; 25.10 +import jdk.nashorn.internal.objects.Global; 25.11 +import jdk.nashorn.internal.runtime.Property; 25.12 import jdk.nashorn.internal.runtime.PropertyMap; 25.13 import jdk.nashorn.internal.runtime.ScriptFunction; 25.14 import jdk.nashorn.internal.runtime.ScriptObject; 25.15 @@ -40,6 +45,7 @@ 25.16 private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class); 25.17 private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class); 25.18 private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class); 25.19 + private static final MethodHandle SAME_OBJECT = findOwnMH("sameObject", boolean.class, Object.class, WeakReference.class); 25.20 private static final MethodHandle IS_INSTANCEOF_2 = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class); 25.21 25.22 // don't create me! 25.23 @@ -75,6 +81,55 @@ 25.24 } 25.25 25.26 /** 25.27 + * Determine whether the given callsite needs a guard. 25.28 + * @param property the property, or null 25.29 + * @param desc the callsite descriptor 25.30 + * @return true if a guard should be used for this callsite 25.31 + */ 25.32 + static boolean needsGuard(final Property property, final CallSiteDescriptor desc) { 25.33 + return property == null || property.isConfigurable() 25.34 + || property.isBound() || !ObjectClassGenerator.OBJECT_FIELDS_ONLY 25.35 + || !NashornCallSiteDescriptor.isFastScope(desc) || property.canChangeType(); 25.36 + } 25.37 + 25.38 + /** 25.39 + * Get the guard for a property access. This returns an identity guard for non-configurable global properties 25.40 + * and a map guard for everything else. 25.41 + * 25.42 + * @param sobj the first object in the prototype chain 25.43 + * @param property the property 25.44 + * @param desc the callsite descriptor 25.45 + * @return method handle for guard 25.46 + */ 25.47 + public static MethodHandle getGuard(final ScriptObject sobj, final Property property, final CallSiteDescriptor desc) { 25.48 + if (!needsGuard(property, desc)) { 25.49 + return null; 25.50 + } 25.51 + if (NashornCallSiteDescriptor.isScope(desc)) { 25.52 + if (property != null && property.isBound()) { 25.53 + // This is a declared top level variables in main script or eval, use identity guard. 25.54 + return getIdentityGuard(sobj); 25.55 + } 25.56 + if (!(sobj instanceof Global) && (property == null || property.isConfigurable())) { 25.57 + // Undeclared variables in nested evals need stronger guards 25.58 + return combineGuards(getIdentityGuard(sobj), getMapGuard(sobj.getMap())); 25.59 + } 25.60 + } 25.61 + return getMapGuard(sobj.getMap()); 25.62 + } 25.63 + 25.64 + 25.65 + /** 25.66 + * Get a guard that checks referential identity of the current object. 25.67 + * 25.68 + * @param sobj the self object 25.69 + * @return true if same self object instance 25.70 + */ 25.71 + public static MethodHandle getIdentityGuard(final ScriptObject sobj) { 25.72 + return MH.insertArguments(SAME_OBJECT, 1, new WeakReference<>(sobj)); 25.73 + } 25.74 + 25.75 + /** 25.76 * Get a guard that checks if in item is an instance of either of two classes. 25.77 * 25.78 * @param class1 the first class 25.79 @@ -112,6 +167,11 @@ 25.80 } 25.81 25.82 @SuppressWarnings("unused") 25.83 + private static boolean sameObject(final Object self, final WeakReference<ScriptObject> ref) { 25.84 + return self == ref.get(); 25.85 + } 25.86 + 25.87 + @SuppressWarnings("unused") 25.88 private static boolean isInstanceOf2(final Object self, final Class<?> class1, final Class<?> class2) { 25.89 return class1.isInstance(self) || class2.isInstance(self); 25.90 }
26.1 --- a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Wed Mar 12 16:33:28 2014 +0100 26.2 +++ b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Wed Mar 12 11:26:00 2014 +0100 26.3 @@ -35,6 +35,7 @@ 26.4 import jdk.internal.dynalink.support.CallSiteDescriptorFactory; 26.5 import jdk.internal.dynalink.support.Guards; 26.6 import jdk.nashorn.internal.lookup.Lookup; 26.7 +import jdk.nashorn.internal.runtime.FindProperty; 26.8 import jdk.nashorn.internal.runtime.ScriptObject; 26.9 26.10 /** 26.11 @@ -61,8 +62,9 @@ 26.12 * type {@code receiverClass}. 26.13 */ 26.14 public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Class<?> receiverClass, 26.15 - final ScriptObject wrappedReceiver, final MethodHandle wrapFilter) { 26.16 - return lookupPrimitive(request, Guards.getInstanceOfGuard(receiverClass), wrappedReceiver, wrapFilter); 26.17 + final ScriptObject wrappedReceiver, final MethodHandle wrapFilter, 26.18 + final MethodHandle protoFilter) { 26.19 + return lookupPrimitive(request, Guards.getInstanceOfGuard(receiverClass), wrappedReceiver, wrapFilter, protoFilter); 26.20 } 26.21 26.22 /** 26.23 @@ -79,7 +81,8 @@ 26.24 * type (that is implied by both {@code guard} and {@code wrappedReceiver}). 26.25 */ 26.26 public static GuardedInvocation lookupPrimitive(final LinkRequest request, final MethodHandle guard, 26.27 - final ScriptObject wrappedReceiver, final MethodHandle wrapFilter) { 26.28 + final ScriptObject wrappedReceiver, final MethodHandle wrapFilter, 26.29 + final MethodHandle protoFilter) { 26.30 final CallSiteDescriptor desc = request.getCallSiteDescriptor(); 26.31 final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); 26.32 if ("setProp".equals(operator) || "setElem".equals(operator)) { 26.33 @@ -93,9 +96,23 @@ 26.34 26.35 if(desc.getNameTokenCount() > 2) { 26.36 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 26.37 - if(wrappedReceiver.findProperty(name, true) == null) { 26.38 + final FindProperty find = wrappedReceiver.findProperty(name, true); 26.39 + if(find == null) { 26.40 // Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it. 26.41 return null; 26.42 + } else if (find.isInherited() && !find.getProperty().hasGetterFunction(find.getOwner())) { 26.43 + // If property is found in the prototype object bind the method handle directly to 26.44 + // the proto filter instead of going through wrapper instantiation below. 26.45 + final ScriptObject proto = wrappedReceiver.getProto(); 26.46 + final GuardedInvocation link = proto.lookup(desc, request); 26.47 + 26.48 + if (link != null) { 26.49 + final MethodHandle invocation = link.getInvocation(); 26.50 + final MethodHandle adaptedInvocation = MH.asType(invocation, invocation.type().changeParameterType(0, Object.class)); 26.51 + final MethodHandle method = MH.filterArguments(adaptedInvocation, 0, protoFilter); 26.52 + final MethodHandle protoGuard = MH.filterArguments(link.getGuard(), 0, protoFilter); 26.53 + return new GuardedInvocation(method, NashornGuards.combineGuards(guard, protoGuard)); 26.54 + } 26.55 } 26.56 } 26.57 final GuardedInvocation link = wrappedReceiver.lookup(desc, request);
27.1 --- a/test/src/jdk/nashorn/api/scripting/ScopeTest.java Wed Mar 12 16:33:28 2014 +0100 27.2 +++ b/test/src/jdk/nashorn/api/scripting/ScopeTest.java Wed Mar 12 11:26:00 2014 +0100 27.3 @@ -245,4 +245,320 @@ 27.4 sb.put("x", "newX"); 27.5 assertTrue(e.eval("x", ctx).equals("newX")); 27.6 } 27.7 + 27.8 + /** 27.9 + * Test multi-threaded access to defined global variables for shared script classes with multiple globals. 27.10 + */ 27.11 + @Test 27.12 + public static void multiThreadedVarTest() throws ScriptException, InterruptedException { 27.13 + final ScriptEngineManager m = new ScriptEngineManager(); 27.14 + final ScriptEngine e = m.getEngineByName("nashorn"); 27.15 + final Bindings b = e.createBindings(); 27.16 + final ScriptContext origContext = e.getContext(); 27.17 + final ScriptContext newCtxt = new SimpleScriptContext(); 27.18 + newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE); 27.19 + final String sharedScript = "foo"; 27.20 + 27.21 + assertEquals(e.eval("var foo = 'original context';", origContext), null); 27.22 + assertEquals(e.eval("var foo = 'new context';", newCtxt), null); 27.23 + 27.24 + final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000)); 27.25 + final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000)); 27.26 + t1.start(); 27.27 + t2.start(); 27.28 + t1.join(); 27.29 + t2.join(); 27.30 + 27.31 + assertEquals(e.eval("var foo = 'newer context';", newCtxt), null); 27.32 + final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000)); 27.33 + final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000)); 27.34 + 27.35 + t3.start(); 27.36 + t4.start(); 27.37 + t3.join(); 27.38 + t4.join(); 27.39 + 27.40 + assertEquals(e.eval(sharedScript), "original context"); 27.41 + assertEquals(e.eval(sharedScript, newCtxt), "newer context"); 27.42 + } 27.43 + 27.44 + /** 27.45 + * Test multi-threaded access to undefined global variables for shared script classes with multiple globals. 27.46 + */ 27.47 + @Test 27.48 + public static void multiThreadedGlobalTest() throws ScriptException, InterruptedException { 27.49 + final ScriptEngineManager m = new ScriptEngineManager(); 27.50 + final ScriptEngine e = m.getEngineByName("nashorn"); 27.51 + final Bindings b = e.createBindings(); 27.52 + final ScriptContext origContext = e.getContext(); 27.53 + final ScriptContext newCtxt = new SimpleScriptContext(); 27.54 + newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE); 27.55 + 27.56 + assertEquals(e.eval("foo = 'original context';", origContext), "original context"); 27.57 + assertEquals(e.eval("foo = 'new context';", newCtxt), "new context"); 27.58 + final String sharedScript = "foo"; 27.59 + 27.60 + final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000)); 27.61 + final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000)); 27.62 + t1.start(); 27.63 + t2.start(); 27.64 + t1.join(); 27.65 + t2.join(); 27.66 + 27.67 + Object obj3 = e.eval("delete foo; foo = 'newer context';", newCtxt); 27.68 + assertEquals(obj3, "newer context"); 27.69 + final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000)); 27.70 + final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000)); 27.71 + 27.72 + t3.start(); 27.73 + t4.start(); 27.74 + t3.join(); 27.75 + t4.join(); 27.76 + 27.77 + Assert.assertEquals(e.eval(sharedScript), "original context"); 27.78 + Assert.assertEquals(e.eval(sharedScript, newCtxt), "newer context"); 27.79 + } 27.80 + 27.81 + /** 27.82 + * Test multi-threaded access using the postfix ++ operator for shared script classes with multiple globals. 27.83 + */ 27.84 + @Test 27.85 + public static void multiThreadedIncTest() throws ScriptException, InterruptedException { 27.86 + final ScriptEngineManager m = new ScriptEngineManager(); 27.87 + final ScriptEngine e = m.getEngineByName("nashorn"); 27.88 + final Bindings b = e.createBindings(); 27.89 + final ScriptContext origContext = e.getContext(); 27.90 + final ScriptContext newCtxt = new SimpleScriptContext(); 27.91 + newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE); 27.92 + 27.93 + assertEquals(e.eval("var x = 0;", origContext), null); 27.94 + assertEquals(e.eval("var x = 2;", newCtxt), null); 27.95 + final String sharedScript = "x++;"; 27.96 + 27.97 + final Thread t1 = new Thread(new Runnable() { 27.98 + @Override 27.99 + public void run() { 27.100 + try { 27.101 + for (int i = 0; i < 1000; i++) { 27.102 + assertEquals(e.eval(sharedScript, origContext), (double)i); 27.103 + } 27.104 + } catch (ScriptException se) { 27.105 + fail(se.toString()); 27.106 + } 27.107 + } 27.108 + }); 27.109 + final Thread t2 = new Thread(new Runnable() { 27.110 + @Override 27.111 + public void run() { 27.112 + try { 27.113 + for (int i = 2; i < 1000; i++) { 27.114 + assertEquals(e.eval(sharedScript, newCtxt), (double)i); 27.115 + } 27.116 + } catch (ScriptException se) { 27.117 + fail(se.toString()); 27.118 + } 27.119 + } 27.120 + }); 27.121 + t1.start(); 27.122 + t2.start(); 27.123 + t1.join(); 27.124 + t2.join(); 27.125 + } 27.126 + 27.127 + /** 27.128 + * Test multi-threaded access to primitive prototype properties for shared script classes with multiple globals. 27.129 + */ 27.130 + @Test 27.131 + public static void multiThreadedPrimitiveTest() throws ScriptException, InterruptedException { 27.132 + final ScriptEngineManager m = new ScriptEngineManager(); 27.133 + final ScriptEngine e = m.getEngineByName("nashorn"); 27.134 + final Bindings b = e.createBindings(); 27.135 + final ScriptContext origContext = e.getContext(); 27.136 + final ScriptContext newCtxt = new SimpleScriptContext(); 27.137 + newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE); 27.138 + 27.139 + Object obj1 = e.eval("String.prototype.foo = 'original context';", origContext); 27.140 + Object obj2 = e.eval("String.prototype.foo = 'new context';", newCtxt); 27.141 + assertEquals(obj1, "original context"); 27.142 + assertEquals(obj2, "new context"); 27.143 + final String sharedScript = "''.foo"; 27.144 + 27.145 + final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000)); 27.146 + final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000)); 27.147 + t1.start(); 27.148 + t2.start(); 27.149 + t1.join(); 27.150 + t2.join(); 27.151 + 27.152 + Object obj3 = e.eval("delete String.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt); 27.153 + assertEquals(obj3, "newer context"); 27.154 + final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000)); 27.155 + final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000)); 27.156 + 27.157 + t3.start(); 27.158 + t4.start(); 27.159 + t3.join(); 27.160 + t4.join(); 27.161 + 27.162 + Assert.assertEquals(e.eval(sharedScript), "original context"); 27.163 + Assert.assertEquals(e.eval(sharedScript, newCtxt), "newer context"); 27.164 + } 27.165 + 27.166 + /** 27.167 + * Test multi-threaded scope function invocation for shared script classes with multiple globals. 27.168 + */ 27.169 + @Test 27.170 + public static void multiThreadedFunctionTest() throws ScriptException, InterruptedException { 27.171 + final ScriptEngineManager m = new ScriptEngineManager(); 27.172 + final ScriptEngine e = m.getEngineByName("nashorn"); 27.173 + final Bindings b = e.createBindings(); 27.174 + final ScriptContext origContext = e.getContext(); 27.175 + final ScriptContext newCtxt = new SimpleScriptContext(); 27.176 + newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE); 27.177 + 27.178 + e.eval(new URLReader(ScopeTest.class.getResource("resources/func.js")), origContext); 27.179 + assertEquals(origContext.getAttribute("scopeVar"), 1); 27.180 + assertEquals(e.eval("scopeTest()"), 1); 27.181 + 27.182 + e.eval(new URLReader(ScopeTest.class.getResource("resources/func.js")), newCtxt); 27.183 + assertEquals(newCtxt.getAttribute("scopeVar"), 1); 27.184 + assertEquals(e.eval("scopeTest();", newCtxt), 1); 27.185 + 27.186 + assertEquals(e.eval("scopeVar = 3;", newCtxt), 3); 27.187 + assertEquals(newCtxt.getAttribute("scopeVar"), 3); 27.188 + 27.189 + 27.190 + final Thread t1 = new Thread(new ScriptRunner(e, origContext, "scopeTest()", 1, 1000)); 27.191 + final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, "scopeTest()", 3, 1000)); 27.192 + 27.193 + t1.start(); 27.194 + t2.start(); 27.195 + t1.join(); 27.196 + t2.join(); 27.197 + 27.198 + } 27.199 + 27.200 + /** 27.201 + * Test multi-threaded access to global getters and setters for shared script classes with multiple globals. 27.202 + */ 27.203 + @Test 27.204 + public static void getterSetterTest() throws ScriptException, InterruptedException { 27.205 + final ScriptEngineManager m = new ScriptEngineManager(); 27.206 + final ScriptEngine e = m.getEngineByName("nashorn"); 27.207 + final Bindings b = e.createBindings(); 27.208 + final ScriptContext origContext = e.getContext(); 27.209 + final ScriptContext newCtxt = new SimpleScriptContext(); 27.210 + newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE); 27.211 + final String sharedScript = "accessor1"; 27.212 + 27.213 + e.eval(new URLReader(ScopeTest.class.getResource("resources/gettersetter.js")), origContext); 27.214 + assertEquals(e.eval("accessor1 = 1;"), 1); 27.215 + assertEquals(e.eval(sharedScript), 1); 27.216 + 27.217 + e.eval(new URLReader(ScopeTest.class.getResource("resources/gettersetter.js")), newCtxt); 27.218 + assertEquals(e.eval("accessor1 = 2;", newCtxt), 2); 27.219 + assertEquals(e.eval(sharedScript, newCtxt), 2); 27.220 + 27.221 + 27.222 + final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, 1, 1000)); 27.223 + final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, 2, 1000)); 27.224 + 27.225 + t1.start(); 27.226 + t2.start(); 27.227 + t1.join(); 27.228 + t2.join(); 27.229 + 27.230 + assertEquals(e.eval(sharedScript), 1); 27.231 + assertEquals(e.eval(sharedScript, newCtxt), 2); 27.232 + assertEquals(e.eval("v"), 1); 27.233 + assertEquals(e.eval("v", newCtxt), 2); 27.234 + } 27.235 + 27.236 + /** 27.237 + * Test multi-threaded access to global getters and setters for shared script classes with multiple globals. 27.238 + */ 27.239 + @Test 27.240 + public static void getterSetter2Test() throws ScriptException, InterruptedException { 27.241 + final ScriptEngineManager m = new ScriptEngineManager(); 27.242 + final ScriptEngine e = m.getEngineByName("nashorn"); 27.243 + final Bindings b = e.createBindings(); 27.244 + final ScriptContext origContext = e.getContext(); 27.245 + final ScriptContext newCtxt = new SimpleScriptContext(); 27.246 + newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE); 27.247 + final String sharedScript = "accessor2"; 27.248 + 27.249 + e.eval(new URLReader(ScopeTest.class.getResource("resources/gettersetter.js")), origContext); 27.250 + assertEquals(e.eval("accessor2 = 1;"), 1); 27.251 + assertEquals(e.eval(sharedScript), 1); 27.252 + 27.253 + e.eval(new URLReader(ScopeTest.class.getResource("resources/gettersetter.js")), newCtxt); 27.254 + assertEquals(e.eval("accessor2 = 2;", newCtxt), 2); 27.255 + assertEquals(e.eval(sharedScript, newCtxt), 2); 27.256 + 27.257 + 27.258 + final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, 1, 1000)); 27.259 + final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, 2, 1000)); 27.260 + 27.261 + t1.start(); 27.262 + t2.start(); 27.263 + t1.join(); 27.264 + t2.join(); 27.265 + 27.266 + assertEquals(e.eval(sharedScript), 1); 27.267 + assertEquals(e.eval(sharedScript, newCtxt), 2); 27.268 + assertEquals(e.eval("x"), 1); 27.269 + assertEquals(e.eval("x", newCtxt), 2); 27.270 + } 27.271 + 27.272 + /** 27.273 + * Test "slow" scopes involving {@code with} and {@code eval} statements for shared script classes with multiple globals. 27.274 + */ 27.275 + @Test 27.276 + public static void testSlowScope() throws ScriptException, InterruptedException { 27.277 + final ScriptEngineManager m = new ScriptEngineManager(); 27.278 + final ScriptEngine e = m.getEngineByName("nashorn"); 27.279 + 27.280 + for (int i = 0; i < 100; i++) { 27.281 + final Bindings b = e.createBindings(); 27.282 + final ScriptContext ctxt = new SimpleScriptContext(); 27.283 + ctxt.setBindings(b, ScriptContext.ENGINE_SCOPE); 27.284 + 27.285 + e.eval(new URLReader(ScopeTest.class.getResource("resources/witheval.js")), ctxt); 27.286 + assertEquals(e.eval("a", ctxt), 1); 27.287 + assertEquals(b.get("a"), 1); 27.288 + assertEquals(e.eval("b", ctxt), 3); 27.289 + assertEquals(b.get("b"), 3); 27.290 + assertEquals(e.eval("c", ctxt), 10); 27.291 + assertEquals(b.get("c"), 10); 27.292 + } 27.293 + } 27.294 + 27.295 + private static class ScriptRunner implements Runnable { 27.296 + 27.297 + final ScriptEngine engine; 27.298 + final ScriptContext context; 27.299 + final String source; 27.300 + final Object expected; 27.301 + final int iterations; 27.302 + 27.303 + ScriptRunner(final ScriptEngine engine, final ScriptContext context, final String source, final Object expected, final int iterations) { 27.304 + this.engine = engine; 27.305 + this.context = context; 27.306 + this.source = source; 27.307 + this.expected = expected; 27.308 + this.iterations = iterations; 27.309 + } 27.310 + 27.311 + @Override 27.312 + public void run() { 27.313 + try { 27.314 + for (int i = 0; i < iterations; i++) { 27.315 + assertEquals(engine.eval(source, context), expected); 27.316 + } 27.317 + } catch (ScriptException se) { 27.318 + throw new RuntimeException(se); 27.319 + } 27.320 + } 27.321 + } 27.322 + 27.323 }
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/test/src/jdk/nashorn/api/scripting/resources/func.js Wed Mar 12 11:26:00 2014 +0100 28.3 @@ -0,0 +1,42 @@ 28.4 +/* 28.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 28.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 28.7 + * 28.8 + * This code is free software; you can redistribute it and/or modify it 28.9 + * under the terms of the GNU General Public License version 2 only, as 28.10 + * published by the Free Software Foundation. Oracle designates this 28.11 + * particular file as subject to the "Classpath" exception as provided 28.12 + * by Oracle in the LICENSE file that accompanied this code. 28.13 + * 28.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 28.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 28.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 28.17 + * version 2 for more details (a copy is included in the LICENSE file that 28.18 + * accompanied this code). 28.19 + * 28.20 + * You should have received a copy of the GNU General Public License version 28.21 + * 2 along with this work; if not, write to the Free Software Foundation, 28.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 28.23 + * 28.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 28.25 + * or visit www.oracle.com if you need additional information or have any 28.26 + * questions. 28.27 + */ 28.28 + 28.29 +// This script is loaded from jdk.nashorn.api.scripting.ScopeTest to test script class sharing and reuse. 28.30 + 28.31 +var scopeVar = 1; 28.32 +var global = this; 28.33 +undefGlobal = this; 28.34 + 28.35 +function scopeTest() { 28.36 + if (this !== global) { 28.37 + throw new Error("this !== global"); 28.38 + } 28.39 + if (this !== undefGlobal) { 28.40 + throw new Error("this !== undefinedGlobal") 28.41 + } 28.42 + return scopeVar; 28.43 +} 28.44 + 28.45 +scopeTest();
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/test/src/jdk/nashorn/api/scripting/resources/gettersetter.js Wed Mar 12 11:26:00 2014 +0100 29.3 @@ -0,0 +1,38 @@ 29.4 +/* 29.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 29.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 29.7 + * 29.8 + * This code is free software; you can redistribute it and/or modify it 29.9 + * under the terms of the GNU General Public License version 2 only, as 29.10 + * published by the Free Software Foundation. Oracle designates this 29.11 + * particular file as subject to the "Classpath" exception as provided 29.12 + * by Oracle in the LICENSE file that accompanied this code. 29.13 + * 29.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 29.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 29.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 29.17 + * version 2 for more details (a copy is included in the LICENSE file that 29.18 + * accompanied this code). 29.19 + * 29.20 + * You should have received a copy of the GNU General Public License version 29.21 + * 2 along with this work; if not, write to the Free Software Foundation, 29.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 29.23 + * 29.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 29.25 + * or visit www.oracle.com if you need additional information or have any 29.26 + * questions. 29.27 + */ 29.28 + 29.29 +// This script is loaded from jdk.nashorn.api.scripting.ScopeTest to test script class sharing and reuse. 29.30 + 29.31 +var v; 29.32 + 29.33 +Object.defineProperty(this, "accessor1", { 29.34 + get: function() { return v; }, 29.35 + set: function(n) { v = n; } 29.36 +}); 29.37 + 29.38 +Object.defineProperty(this, "accessor2", { 29.39 + get: function() { return x; }, 29.40 + set: function(n) { x = n; } 29.41 +});
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/test/src/jdk/nashorn/api/scripting/resources/witheval.js Wed Mar 12 11:26:00 2014 +0100 30.3 @@ -0,0 +1,60 @@ 30.4 +/* 30.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 30.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 30.7 + * 30.8 + * This code is free software; you can redistribute it and/or modify it 30.9 + * under the terms of the GNU General Public License version 2 only, as 30.10 + * published by the Free Software Foundation. Oracle designates this 30.11 + * particular file as subject to the "Classpath" exception as provided 30.12 + * by Oracle in the LICENSE file that accompanied this code. 30.13 + * 30.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 30.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 30.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 30.17 + * version 2 for more details (a copy is included in the LICENSE file that 30.18 + * accompanied this code). 30.19 + * 30.20 + * You should have received a copy of the GNU General Public License version 30.21 + * 2 along with this work; if not, write to the Free Software Foundation, 30.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 30.23 + * 30.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 30.25 + * or visit www.oracle.com if you need additional information or have any 30.26 + * questions. 30.27 + */ 30.28 + 30.29 +// This script is loaded from jdk.nashorn.api.scripting.ScopeTest to test script class sharing and reuse. 30.30 + 30.31 +var a; 30.32 + 30.33 +function outer(p, e) { 30.34 + eval(e); 30.35 + with(p) { 30.36 + function inner() { 30.37 + a = 1; 30.38 + c = 10; 30.39 + if (a !== 1) { 30.40 + throw new Error("a !== 1"); 30.41 + } 30.42 + if (b !== 3) { 30.43 + throw new Error("b !== 3"); 30.44 + } 30.45 + if (c !== 10) { 30.46 + throw new Error("c !== 10"); 30.47 + } 30.48 + } 30.49 + inner(); 30.50 + } 30.51 +} 30.52 + 30.53 +outer({}, "b = 3;"); 30.54 + 30.55 +if (a !== 1) { 30.56 + throw new Error("a !== 1"); 30.57 +} 30.58 +if (b !== 3) { 30.59 + throw new Error("b !== 3"); 30.60 +} 30.61 +if (c !== 10) { 30.62 + throw new Error("c !== 10"); 30.63 +}