Tue, 15 Oct 2013 22:13:56 +0530
Merge
1.1 --- a/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java Fri Oct 11 23:31:18 2013 -0700 1.2 +++ b/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java Tue Oct 15 22:13:56 2013 +0530 1.3 @@ -91,6 +91,7 @@ 1.4 import jdk.internal.dynalink.CallSiteDescriptor; 1.5 import jdk.internal.dynalink.linker.LinkerServices; 1.6 import jdk.internal.dynalink.support.Guards; 1.7 +import jdk.internal.dynalink.support.Lookup; 1.8 1.9 /** 1.10 * Base class for dynamic methods that dispatch to a single target Java method or constructor. Handles adaptation of the 1.11 @@ -100,6 +101,9 @@ 1.12 * @version $Id: $ 1.13 */ 1.14 abstract class SingleDynamicMethod extends DynamicMethod { 1.15 + 1.16 + private static final MethodHandle CAN_CONVERT_TO = Lookup.findOwnStatic(MethodHandles.lookup(), "canConvertTo", boolean.class, LinkerServices.class, Class.class, Object.class); 1.17 + 1.18 SingleDynamicMethod(String name) { 1.19 super(name); 1.20 } 1.21 @@ -201,23 +205,69 @@ 1.22 return createConvertingInvocation(target, linkerServices, callSiteType).asVarargsCollector( 1.23 callSiteLastArgType); 1.24 } 1.25 - if(!linkerServices.canConvert(callSiteLastArgType, varArgType)) { 1.26 - // Call site signature guarantees the argument can definitely not be an array (i.e. it is primitive); 1.27 - // link immediately to a vararg-packing method handle. 1.28 - return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType); 1.29 + 1.30 + // This method handle takes the single argument and packs it into a newly allocated single-element array. It 1.31 + // will be used when the incoming argument can't be converted to the vararg array type (the "vararg packer" 1.32 + // method). 1.33 + final MethodHandle varArgCollectingInvocation = createConvertingInvocation(collectArguments(fixTarget, 1.34 + argsLen), linkerServices, callSiteType); 1.35 + 1.36 + // Is call site type assignable from an array type (e.g. Object:int[], or Object[]:String[]) 1.37 + final boolean isAssignableFromArray = callSiteLastArgType.isAssignableFrom(varArgType); 1.38 + // Do we have a custom conversion that can potentially convert the call site type to an array? 1.39 + final boolean isCustomConvertible = linkerServices.canConvert(callSiteLastArgType, varArgType); 1.40 + if(!isAssignableFromArray && !isCustomConvertible) { 1.41 + // Call site signature guarantees the argument can definitely not be converted to an array (i.e. it is 1.42 + // primitive), and no conversion can help with it either. Link immediately to a vararg-packing method 1.43 + // handle. 1.44 + return varArgCollectingInvocation; 1.45 } 1.46 - // Call site signature makes no guarantees that the single argument in the vararg position will be 1.47 - // compatible across all invocations. Need to insert an appropriate guard and fall back to generic vararg 1.48 - // method when it is not. 1.49 - return MethodHandles.guardWithTest(Guards.isInstance(varArgType, fixParamsLen, callSiteType), 1.50 - createConvertingInvocation(fixTarget, linkerServices, callSiteType), 1.51 - createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType)); 1.52 + 1.53 + // This method handle employs language-specific conversions to convert the last argument into an array of 1.54 + // vararg type. 1.55 + final MethodHandle arrayConvertingInvocation = createConvertingInvocation(MethodHandles.filterArguments( 1.56 + fixTarget, fixParamsLen, linkerServices.getTypeConverter(callSiteLastArgType, varArgType)), 1.57 + linkerServices, callSiteType); 1.58 + 1.59 + // This method handle determines whether the value can be converted to the array of vararg type using a 1.60 + // language-specific conversion. 1.61 + final MethodHandle canConvertArgToArray = MethodHandles.insertArguments(CAN_CONVERT_TO, 0, linkerServices, 1.62 + varArgType); 1.63 + 1.64 + // This one adjusts the previous one for the location of the argument and the call site type. 1.65 + final MethodHandle canConvertLastArgToArray = MethodHandles.dropArguments(canConvertArgToArray, 0, 1.66 + MethodType.genericMethodType(fixParamsLen).parameterList()).asType(callSiteType.changeReturnType(boolean.class)); 1.67 + 1.68 + // This one takes the previous ones and combines them into a method handle that converts the argument into 1.69 + // a vararg array when it can, otherwise falls back to the vararg packer. 1.70 + final MethodHandle convertToArrayWhenPossible = MethodHandles.guardWithTest(canConvertLastArgToArray, 1.71 + arrayConvertingInvocation, varArgCollectingInvocation); 1.72 + 1.73 + if(isAssignableFromArray) { 1.74 + return MethodHandles.guardWithTest( 1.75 + // Is incoming parameter already a compatible array? 1.76 + Guards.isInstance(varArgType, fixParamsLen, callSiteType), 1.77 + // Yes: just pass it to the method 1.78 + createConvertingInvocation(fixTarget, linkerServices, callSiteType), 1.79 + // No: either go through a custom conversion, or if it is not possible, go directly to the 1.80 + // vararg packer. 1.81 + isCustomConvertible ? convertToArrayWhenPossible : varArgCollectingInvocation); 1.82 + } 1.83 + 1.84 + // Just do the custom conversion with fallback to the vararg packer logic. 1.85 + assert isCustomConvertible; 1.86 + return convertToArrayWhenPossible; 1.87 } 1.88 1.89 // Remaining case: more than one vararg. 1.90 return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType); 1.91 } 1.92 1.93 + @SuppressWarnings("unused") 1.94 + private static boolean canConvertTo(final LinkerServices linkerServices, Class<?> to, Object obj) { 1.95 + return obj == null ? false : linkerServices.canConvert(obj.getClass(), to); 1.96 + } 1.97 + 1.98 /** 1.99 * Creates a method handle out of the original target that will collect the varargs for the exact component type of 1.100 * the varArg array. Note that this will nicely trigger language-specific type converters for exactly those varargs
2.1 --- a/src/jdk/internal/dynalink/support/Guards.java Fri Oct 11 23:31:18 2013 -0700 2.2 +++ b/src/jdk/internal/dynalink/support/Guards.java Tue Oct 15 22:13:56 2013 +0530 2.3 @@ -88,6 +88,7 @@ 2.4 import java.lang.invoke.MethodType; 2.5 import java.util.logging.Level; 2.6 import java.util.logging.Logger; 2.7 +import jdk.internal.dynalink.DynamicLinker; 2.8 import jdk.internal.dynalink.linker.LinkerServices; 2.9 2.10 /** 2.11 @@ -115,11 +116,11 @@ 2.12 public static MethodHandle isOfClass(Class<?> clazz, MethodType type) { 2.13 final Class<?> declaredType = type.parameterType(0); 2.14 if(clazz == declaredType) { 2.15 - LOG.log(Level.WARNING, "isOfClassGuardAlwaysTrue", new Object[] { clazz.getName(), 0, type }); 2.16 + LOG.log(Level.WARNING, "isOfClassGuardAlwaysTrue", new Object[] { clazz.getName(), 0, type, DynamicLinker.getLinkedCallSiteLocation() }); 2.17 return constantTrue(type); 2.18 } 2.19 if(!declaredType.isAssignableFrom(clazz)) { 2.20 - LOG.log(Level.WARNING, "isOfClassGuardAlwaysFalse", new Object[] { clazz.getName(), 0, type }); 2.21 + LOG.log(Level.WARNING, "isOfClassGuardAlwaysFalse", new Object[] { clazz.getName(), 0, type, DynamicLinker.getLinkedCallSiteLocation() }); 2.22 return constantFalse(type); 2.23 } 2.24 return getClassBoundArgumentTest(IS_OF_CLASS, clazz, 0, type); 2.25 @@ -152,11 +153,11 @@ 2.26 public static MethodHandle isInstance(Class<?> clazz, int pos, MethodType type) { 2.27 final Class<?> declaredType = type.parameterType(pos); 2.28 if(clazz.isAssignableFrom(declaredType)) { 2.29 - LOG.log(Level.WARNING, "isInstanceGuardAlwaysTrue", new Object[] { clazz.getName(), pos, type }); 2.30 + LOG.log(Level.WARNING, "isInstanceGuardAlwaysTrue", new Object[] { clazz.getName(), pos, type, DynamicLinker.getLinkedCallSiteLocation() }); 2.31 return constantTrue(type); 2.32 } 2.33 if(!declaredType.isAssignableFrom(clazz)) { 2.34 - LOG.log(Level.WARNING, "isInstanceGuardAlwaysFalse", new Object[] { clazz.getName(), pos, type }); 2.35 + LOG.log(Level.WARNING, "isInstanceGuardAlwaysFalse", new Object[] { clazz.getName(), pos, type, DynamicLinker.getLinkedCallSiteLocation() }); 2.36 return constantFalse(type); 2.37 } 2.38 return getClassBoundArgumentTest(IS_INSTANCE, clazz, pos, type); 2.39 @@ -174,11 +175,11 @@ 2.40 public static MethodHandle isArray(int pos, MethodType type) { 2.41 final Class<?> declaredType = type.parameterType(pos); 2.42 if(declaredType.isArray()) { 2.43 - LOG.log(Level.WARNING, "isArrayGuardAlwaysTrue", new Object[] { pos, type }); 2.44 + LOG.log(Level.WARNING, "isArrayGuardAlwaysTrue", new Object[] { pos, type, DynamicLinker.getLinkedCallSiteLocation() }); 2.45 return constantTrue(type); 2.46 } 2.47 if(!declaredType.isAssignableFrom(Object[].class)) { 2.48 - LOG.log(Level.WARNING, "isArrayGuardAlwaysFalse", new Object[] { pos, type }); 2.49 + LOG.log(Level.WARNING, "isArrayGuardAlwaysFalse", new Object[] { pos, type, DynamicLinker.getLinkedCallSiteLocation() }); 2.50 return constantFalse(type); 2.51 } 2.52 return asType(IS_ARRAY, pos, type);
3.1 --- a/src/jdk/internal/dynalink/support/messages.properties Fri Oct 11 23:31:18 2013 -0700 3.2 +++ b/src/jdk/internal/dynalink/support/messages.properties Tue Oct 15 22:13:56 2013 +0530 3.3 @@ -76,11 +76,11 @@ 3.4 # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 3.5 # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3.6 3.7 -isInstanceGuardAlwaysTrue=isInstance guard for {0} in position {1} in method type {2} will always return true 3.8 -isInstanceGuardAlwaysFalse=isInstance guard for {0} in position {1} in method type {2} will always return false 3.9 +isInstanceGuardAlwaysTrue=isInstance guard for {0} in position {1} in method type {2} at {3} will always return true 3.10 +isInstanceGuardAlwaysFalse=isInstance guard for {0} in position {1} in method type {2} at {3} will always return false 3.11 3.12 -isOfClassGuardAlwaysTrue=isOfClass guard for {0} in position {1} in method type {2} will always return true 3.13 -isOfClassGuardAlwaysFalse=isOfClass guard for {0} in position {1} in method type {2} will always return false 3.14 +isOfClassGuardAlwaysTrue=isOfClass guard for {0} in position {1} in method type {2} at {3} will always return true 3.15 +isOfClassGuardAlwaysFalse=isOfClass guard for {0} in position {1} in method type {2} at {3} will always return false 3.16 3.17 -isArrayGuardAlwaysTrue=isArray guard in position {0} in method type {1} will always return true 3.18 -isArrayGuardAlwaysFalse=isArray guard in position {0} in method type {1} will always return false 3.19 \ No newline at end of file 3.20 +isArrayGuardAlwaysTrue=isArray guard in position {0} in method type {1} at {2} will always return true 3.21 +isArrayGuardAlwaysFalse=isArray guard in position {0} in method type {1} at {2} will always return false 3.22 \ No newline at end of file
4.1 --- a/src/jdk/nashorn/api/scripting/ScriptUtils.java Fri Oct 11 23:31:18 2013 -0700 4.2 +++ b/src/jdk/nashorn/api/scripting/ScriptUtils.java Tue Oct 15 22:13:56 2013 +0530 4.3 @@ -25,6 +25,7 @@ 4.4 4.5 package jdk.nashorn.api.scripting; 4.6 4.7 +import jdk.nashorn.internal.runtime.ScriptFunction; 4.8 import jdk.nashorn.internal.runtime.ScriptRuntime; 4.9 4.10 /** 4.11 @@ -57,4 +58,17 @@ 4.12 public static String format(final String format, final Object[] args) { 4.13 return Formatter.format(format, args); 4.14 } 4.15 + 4.16 + /** 4.17 + * Create a wrapper function that calls {@code func} synchronized on {@code sync} or, if that is undefined, 4.18 + * {@code self}. Used to implement "sync" function in resources/mozilla_compat.js. 4.19 + * 4.20 + * @param func the function to invoke 4.21 + * @param sync the object to synchronize on 4.22 + * @return a synchronizing wrapper function 4.23 + */ 4.24 + public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) { 4.25 + return func.makeSynchronizedFunction(sync); 4.26 + } 4.27 + 4.28 }
5.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Oct 11 23:31:18 2013 -0700 5.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Tue Oct 15 22:13:56 2013 +0530 5.3 @@ -453,7 +453,13 @@ 5.4 public boolean enterFunctionNode(FunctionNode functionNode) { 5.5 // function nodes will always leave a constructed function object on stack, no need to load the symbol 5.6 // separately as in enterDefault() 5.7 + lc.pop(functionNode); 5.8 functionNode.accept(codegen); 5.9 + // NOTE: functionNode.accept() will produce a different FunctionNode that we discard. This incidentally 5.10 + // doesn't cause problems as we're never touching FunctionNode again after it's visited here - codegen 5.11 + // is the last element in the compilation pipeline, the AST it produces is not used externally. So, we 5.12 + // re-push the original functionNode. 5.13 + lc.push(functionNode); 5.14 method.convert(type); 5.15 return false; 5.16 }
6.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Fri Oct 11 23:31:18 2013 -0700 6.2 +++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Tue Oct 15 22:13:56 2013 +0530 6.3 @@ -25,6 +25,7 @@ 6.4 6.5 package jdk.nashorn.internal.objects; 6.6 6.7 +import static jdk.nashorn.internal.lookup.Lookup.MH; 6.8 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 6.9 6.10 import java.lang.invoke.MethodHandle; 6.11 @@ -255,6 +256,12 @@ 6.12 return makeFunction(name, methodHandle, null); 6.13 } 6.14 6.15 + @Override 6.16 + public ScriptFunction makeSynchronizedFunction(final Object sync) { 6.17 + final MethodHandle mh = MH.insertArguments(ScriptFunction.INVOKE_SYNC, 0, this, sync); 6.18 + return makeFunction(getName(), mh); 6.19 + } 6.20 + 6.21 /** 6.22 * Same as {@link ScriptFunction#makeBoundFunction(Object, Object[])}. The only reason we override it is so that we 6.23 * can expose it to methods in this package.
7.1 --- a/src/jdk/nashorn/internal/runtime/JSType.java Fri Oct 11 23:31:18 2013 -0700 7.2 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Tue Oct 15 22:13:56 2013 +0530 7.3 @@ -31,6 +31,8 @@ 7.4 import java.lang.invoke.MethodHandle; 7.5 import java.lang.invoke.MethodHandles; 7.6 import java.lang.reflect.Array; 7.7 +import java.util.Deque; 7.8 +import java.util.List; 7.9 import jdk.internal.dynalink.beans.StaticClass; 7.10 import jdk.nashorn.api.scripting.JSObject; 7.11 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 7.12 @@ -110,6 +112,15 @@ 7.13 /** Combined call to toPrimitive followed by toString. */ 7.14 public static final Call TO_PRIMITIVE_TO_STRING = staticCall(myLookup, JSType.class, "toPrimitiveToString", String.class, Object.class); 7.15 7.16 + /** Method handle to convert a JS Object to a Java array. */ 7.17 + public static final Call TO_JAVA_ARRAY = staticCall(myLookup, JSType.class, "toJavaArray", Object.class, Object.class, Class.class); 7.18 + 7.19 + /** Method handle to convert a JS Object to a Java List. */ 7.20 + public static final Call TO_JAVA_LIST = staticCall(myLookup, JSType.class, "toJavaList", List.class, Object.class); 7.21 + 7.22 + /** Method handle to convert a JS Object to a Java deque. */ 7.23 + public static final Call TO_JAVA_DEQUE = staticCall(myLookup, JSType.class, "toJavaDeque", Deque.class, Object.class); 7.24 + 7.25 private static final double INT32_LIMIT = 4294967296.0; 7.26 7.27 /** 7.28 @@ -890,6 +901,8 @@ 7.29 res[idx++] = itr.next(); 7.30 } 7.31 return convertArray(res, componentType); 7.32 + } else if(obj == null) { 7.33 + return null; 7.34 } else { 7.35 throw new IllegalArgumentException("not a script object"); 7.36 } 7.37 @@ -919,6 +932,24 @@ 7.38 } 7.39 7.40 /** 7.41 + * Converts a JavaScript object to a Java List. See {@link ListAdapter} for details. 7.42 + * @param obj the object to convert. Can be any array-like object. 7.43 + * @return a List that is live-backed by the JavaScript object. 7.44 + */ 7.45 + public static List<?> toJavaList(final Object obj) { 7.46 + return ListAdapter.create(obj); 7.47 + } 7.48 + 7.49 + /** 7.50 + * Converts a JavaScript object to a Java Deque. See {@link ListAdapter} for details. 7.51 + * @param obj the object to convert. Can be any array-like object. 7.52 + * @return a Deque that is live-backed by the JavaScript object. 7.53 + */ 7.54 + public static Deque<?> toJavaDeque(final Object obj) { 7.55 + return ListAdapter.create(obj); 7.56 + } 7.57 + 7.58 + /** 7.59 * Check if an object is null or undefined 7.60 * 7.61 * @param obj object to check
8.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Fri Oct 11 23:31:18 2013 -0700 8.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Tue Oct 15 22:13:56 2013 +0530 8.3 @@ -53,7 +53,7 @@ 8.4 public final class RecompilableScriptFunctionData extends ScriptFunctionData { 8.5 8.6 /** FunctionNode with the code for this ScriptFunction */ 8.7 - private volatile FunctionNode functionNode; 8.8 + private FunctionNode functionNode; 8.9 8.10 /** Source from which FunctionNode was parsed. */ 8.11 private final Source source; 8.12 @@ -65,7 +65,7 @@ 8.13 private final PropertyMap allocatorMap; 8.14 8.15 /** Code installer used for all further recompilation/specialization of this ScriptFunction */ 8.16 - private volatile CodeInstaller<ScriptEnvironment> installer; 8.17 + private CodeInstaller<ScriptEnvironment> installer; 8.18 8.19 /** Name of class where allocator function resides */ 8.20 private final String allocatorClassName; 8.21 @@ -178,7 +178,7 @@ 8.22 } 8.23 8.24 @Override 8.25 - protected void ensureCodeGenerated() { 8.26 + protected synchronized void ensureCodeGenerated() { 8.27 if (!code.isEmpty()) { 8.28 return; // nothing to do, we have code, at least some. 8.29 } 8.30 @@ -336,7 +336,7 @@ 8.31 } 8.32 8.33 @Override 8.34 - MethodHandle getBestInvoker(final MethodType callSiteType, final Object[] args) { 8.35 + synchronized MethodHandle getBestInvoker(final MethodType callSiteType, final Object[] args) { 8.36 final MethodType runtimeType = runtimeType(callSiteType, args); 8.37 assert runtimeType.parameterCount() == callSiteType.parameterCount(); 8.38
9.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java Fri Oct 11 23:31:18 2013 -0700 9.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java Tue Oct 15 22:13:56 2013 +0530 9.3 @@ -59,6 +59,9 @@ 9.4 /** Method handle for name getter for this ScriptFunction */ 9.5 public static final MethodHandle G$NAME = findOwnMH("G$name", Object.class, Object.class); 9.6 9.7 + /** Method handle used for implementing sync() in mozilla_compat */ 9.8 + public static final MethodHandle INVOKE_SYNC = findOwnMH("invokeSync", Object.class, ScriptFunction.class, Object.class, Object.class, Object[].class); 9.9 + 9.10 /** Method handle for allocate function for this ScriptFunction */ 9.11 static final MethodHandle ALLOCATE = findOwnMH("allocate", Object.class); 9.12 9.13 @@ -301,6 +304,14 @@ 9.14 public abstract void setPrototype(Object prototype); 9.15 9.16 /** 9.17 + * Create a function that invokes this function synchronized on {@code sync} or the self object 9.18 + * of the invocation. 9.19 + * @param sync the Object to synchronize on, or undefined 9.20 + * @return synchronized function 9.21 + */ 9.22 + public abstract ScriptFunction makeSynchronizedFunction(Object sync); 9.23 + 9.24 + /** 9.25 * Return the most appropriate invoke handle if there are specializations 9.26 * @param type most specific method type to look for invocation with 9.27 * @param args args for trampoline invocation 9.28 @@ -614,6 +625,15 @@ 9.29 return result; 9.30 } 9.31 9.32 + @SuppressWarnings("unused") 9.33 + private static Object invokeSync(final ScriptFunction func, final Object sync, final Object self, final Object... args) 9.34 + throws Throwable { 9.35 + final Object syncObj = sync == UNDEFINED ? self : sync; 9.36 + synchronized (syncObj) { 9.37 + return func.invoke(self, args); 9.38 + } 9.39 + } 9.40 + 9.41 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { 9.42 final Class<?> own = ScriptFunction.class; 9.43 final MethodType mt = MH.type(rtype, types);
10.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Fri Oct 11 23:31:18 2013 -0700 10.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Tue Oct 15 22:13:56 2013 +0530 10.3 @@ -675,7 +675,7 @@ 10.4 10.5 /** 10.6 * Heuristic to figure out if the method handle has a callee argument. If it's type is either 10.7 - * {@code (boolean, Object, ScriptFunction, ...)} or {@code (Object, ScriptFunction, ...)}, then we'll assume it has 10.8 + * {@code (boolean, ScriptFunction, ...)} or {@code (ScriptFunction, ...)}, then we'll assume it has 10.9 * a callee argument. We need this as the constructor above is not passed this information, and can't just blindly 10.10 * assume it's false (notably, it's being invoked for creation of new scripts, and scripts have scopes, therefore 10.11 * they also always receive a callee). 10.12 @@ -692,11 +692,11 @@ 10.13 return false; 10.14 } 10.15 10.16 - if (type.parameterType(0) == boolean.class) { 10.17 - return length > 1 && type.parameterType(1) == ScriptFunction.class; 10.18 + if (type.parameterType(0) == ScriptFunction.class) { 10.19 + return true; 10.20 } 10.21 10.22 - return type.parameterType(0) == ScriptFunction.class; 10.23 + return length > 1 && type.parameterType(0) == boolean.class && type.parameterType(1) == ScriptFunction.class; 10.24 } 10.25 10.26 /**
11.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Fri Oct 11 23:31:18 2013 -0700 11.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Tue Oct 15 22:13:56 2013 +0530 11.3 @@ -37,6 +37,8 @@ 11.4 import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE; 11.5 import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE; 11.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 11.7 +import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex; 11.8 +import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; 11.9 11.10 import java.lang.invoke.MethodHandle; 11.11 import java.lang.invoke.MethodHandles; 11.12 @@ -131,6 +133,7 @@ 11.13 11.14 static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class); 11.15 static final MethodHandle SETPROTOCHECK = findOwnMH("setProtoCheck", void.class, Object.class); 11.16 + static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class); 11.17 11.18 static final MethodHandle SETFIELD = findOwnMH("setField", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class); 11.19 static final MethodHandle SETSPILL = findOwnMH("setSpill", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class); 11.20 @@ -388,7 +391,7 @@ 11.21 return global.newDataDescriptor(getWithProperty(property), configurable, enumerable, writable); 11.22 } 11.23 11.24 - final int index = ArrayIndex.getArrayIndex(key); 11.25 + final int index = getArrayIndex(key); 11.26 final ArrayData array = getArray(); 11.27 11.28 if (array.has(index)) { 11.29 @@ -592,7 +595,7 @@ 11.30 * @param value value to define 11.31 */ 11.32 protected final void defineOwnProperty(final int index, final Object value) { 11.33 - assert ArrayIndex.isValidArrayIndex(index) : "invalid array index"; 11.34 + assert isValidArrayIndex(index) : "invalid array index"; 11.35 final long longIndex = ArrayIndex.toLongIndex(index); 11.36 if (longIndex >= getArray().length()) { 11.37 // make array big enough to hold.. 11.38 @@ -602,9 +605,9 @@ 11.39 } 11.40 11.41 private void checkIntegerKey(final String key) { 11.42 - final int index = ArrayIndex.getArrayIndex(key); 11.43 - 11.44 - if (ArrayIndex.isValidArrayIndex(index)) { 11.45 + final int index = getArrayIndex(key); 11.46 + 11.47 + if (isValidArrayIndex(index)) { 11.48 final ArrayData data = getArray(); 11.49 11.50 if (data.has(index)) { 11.51 @@ -614,7 +617,7 @@ 11.52 } 11.53 11.54 private void removeArraySlot(final String key) { 11.55 - final int index = ArrayIndex.getArrayIndex(key); 11.56 + final int index = getArrayIndex(key); 11.57 final ArrayData array = getArray(); 11.58 11.59 if (array.has(index)) { 11.60 @@ -717,6 +720,28 @@ 11.61 } 11.62 11.63 /** 11.64 + * Low level property API. This is similar to {@link #findProperty(String, boolean)} but returns a 11.65 + * {@code boolean} value instead of a {@link FindProperty} object. 11.66 + * @param key Property key. 11.67 + * @param deep Whether the search should look up proto chain. 11.68 + * @return true if the property was found. 11.69 + */ 11.70 + boolean hasProperty(final String key, final boolean deep) { 11.71 + if (getMap().findProperty(key) != null) { 11.72 + return true; 11.73 + } 11.74 + 11.75 + if (deep) { 11.76 + final ScriptObject myProto = getProto(); 11.77 + if (myProto != null) { 11.78 + return myProto.hasProperty(key, deep); 11.79 + } 11.80 + } 11.81 + 11.82 + return false; 11.83 + } 11.84 + 11.85 + /** 11.86 * Add a new property to the object. 11.87 * <p> 11.88 * This a more "low level" way that doesn't involve {@link PropertyDescriptor}s 11.89 @@ -1708,8 +1733,11 @@ 11.90 */ 11.91 protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) { 11.92 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 11.93 + if (request.isCallSiteUnstable()) { 11.94 + return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator)); 11.95 + } 11.96 + 11.97 final FindProperty find = findProperty(name, true); 11.98 - 11.99 MethodHandle methodHandle; 11.100 11.101 if (find == null) { 11.102 @@ -1727,10 +1755,6 @@ 11.103 throw new AssertionError(); // never invoked with any other operation 11.104 } 11.105 11.106 - if (request.isCallSiteUnstable()) { 11.107 - return findMegaMorphicGetMethod(desc, name); 11.108 - } 11.109 - 11.110 final Class<?> returnType = desc.getMethodType().returnType(); 11.111 final Property property = find.getProperty(); 11.112 methodHandle = find.getGetter(returnType); 11.113 @@ -1757,11 +1781,21 @@ 11.114 return new GuardedInvocation(Lookup.emptyGetter(returnType), getMap().getProtoGetSwitchPoint(proto, name), guard); 11.115 } 11.116 11.117 - private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name) { 11.118 - final MethodType mhType = desc.getMethodType().insertParameterTypes(1, Object.class); 11.119 - final GuardedInvocation inv = findGetIndexMethod(mhType); 11.120 - 11.121 - return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard()); 11.122 + private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) { 11.123 + final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod); 11.124 + final MethodHandle guard = getScriptObjectGuard(desc.getMethodType()); 11.125 + return new GuardedInvocation(invoker, guard); 11.126 + } 11.127 + 11.128 + @SuppressWarnings("unused") 11.129 + private Object megamorphicGet(final String key, final boolean isMethod) { 11.130 + final FindProperty find = findProperty(key, true); 11.131 + 11.132 + if (find != null) { 11.133 + return getObjectValue(find); 11.134 + } 11.135 + 11.136 + return isMethod ? getNoSuchMethod(key) : invokeNoSuchProperty(key); 11.137 } 11.138 11.139 /** 11.140 @@ -1810,7 +1844,7 @@ 11.141 */ 11.142 protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) { 11.143 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 11.144 - if(request.isCallSiteUnstable()) { 11.145 + if (request.isCallSiteUnstable()) { 11.146 return findMegaMorphicSetMethod(desc, name); 11.147 } 11.148 11.149 @@ -2045,6 +2079,26 @@ 11.150 return UNDEFINED; 11.151 } 11.152 11.153 + /** 11.154 + * Get __noSuchMethod__ as a function bound to this object and {@code name} if it is defined. 11.155 + * @param name the method name 11.156 + * @return the bound function, or undefined 11.157 + */ 11.158 + private Object getNoSuchMethod(final String name) { 11.159 + final FindProperty find = findProperty(NO_SUCH_METHOD_NAME, true); 11.160 + 11.161 + if (find == null) { 11.162 + return invokeNoSuchProperty(name); 11.163 + } 11.164 + 11.165 + final Object value = getObjectValue(find); 11.166 + if (! (value instanceof ScriptFunction)) { 11.167 + return UNDEFINED; 11.168 + } 11.169 + 11.170 + return ((ScriptFunction)value).makeBoundFunction(this, new Object[] {name}); 11.171 + } 11.172 + 11.173 private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final String name) { 11.174 return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()), getMap().getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(getMap())); 11.175 } 11.176 @@ -2308,7 +2362,7 @@ 11.177 } 11.178 11.179 private int getInt(final int index, final String key) { 11.180 - if (ArrayIndex.isValidArrayIndex(index)) { 11.181 + if (isValidArrayIndex(index)) { 11.182 for (ScriptObject object = this; ; ) { 11.183 final FindProperty find = object.findProperty(key, false, false, this); 11.184 11.185 @@ -2339,7 +2393,7 @@ 11.186 11.187 @Override 11.188 public int getInt(final Object key) { 11.189 - final int index = ArrayIndex.getArrayIndex(key); 11.190 + final int index = getArrayIndex(key); 11.191 final ArrayData array = getArray(); 11.192 11.193 if (array.has(index)) { 11.194 @@ -2351,7 +2405,7 @@ 11.195 11.196 @Override 11.197 public int getInt(final double key) { 11.198 - final int index = ArrayIndex.getArrayIndex(key); 11.199 + final int index = getArrayIndex(key); 11.200 final ArrayData array = getArray(); 11.201 11.202 if (array.has(index)) { 11.203 @@ -2363,7 +2417,7 @@ 11.204 11.205 @Override 11.206 public int getInt(final long key) { 11.207 - final int index = ArrayIndex.getArrayIndex(key); 11.208 + final int index = getArrayIndex(key); 11.209 final ArrayData array = getArray(); 11.210 11.211 if (array.has(index)) { 11.212 @@ -2385,7 +2439,7 @@ 11.213 } 11.214 11.215 private long getLong(final int index, final String key) { 11.216 - if (ArrayIndex.isValidArrayIndex(index)) { 11.217 + if (isValidArrayIndex(index)) { 11.218 for (ScriptObject object = this; ; ) { 11.219 final FindProperty find = object.findProperty(key, false, false, this); 11.220 11.221 @@ -2416,7 +2470,7 @@ 11.222 11.223 @Override 11.224 public long getLong(final Object key) { 11.225 - final int index = ArrayIndex.getArrayIndex(key); 11.226 + final int index = getArrayIndex(key); 11.227 final ArrayData array = getArray(); 11.228 11.229 if (array.has(index)) { 11.230 @@ -2428,7 +2482,7 @@ 11.231 11.232 @Override 11.233 public long getLong(final double key) { 11.234 - final int index = ArrayIndex.getArrayIndex(key); 11.235 + final int index = getArrayIndex(key); 11.236 final ArrayData array = getArray(); 11.237 11.238 if (array.has(index)) { 11.239 @@ -2440,7 +2494,7 @@ 11.240 11.241 @Override 11.242 public long getLong(final long key) { 11.243 - final int index = ArrayIndex.getArrayIndex(key); 11.244 + final int index = getArrayIndex(key); 11.245 final ArrayData array = getArray(); 11.246 11.247 if (array.has(index)) { 11.248 @@ -2462,7 +2516,7 @@ 11.249 } 11.250 11.251 private double getDouble(final int index, final String key) { 11.252 - if (ArrayIndex.isValidArrayIndex(index)) { 11.253 + if (isValidArrayIndex(index)) { 11.254 for (ScriptObject object = this; ; ) { 11.255 final FindProperty find = object.findProperty(key, false, false, this); 11.256 11.257 @@ -2493,7 +2547,7 @@ 11.258 11.259 @Override 11.260 public double getDouble(final Object key) { 11.261 - final int index = ArrayIndex.getArrayIndex(key); 11.262 + final int index = getArrayIndex(key); 11.263 final ArrayData array = getArray(); 11.264 11.265 if (array.has(index)) { 11.266 @@ -2505,7 +2559,7 @@ 11.267 11.268 @Override 11.269 public double getDouble(final double key) { 11.270 - final int index = ArrayIndex.getArrayIndex(key); 11.271 + final int index = getArrayIndex(key); 11.272 final ArrayData array = getArray(); 11.273 11.274 if (array.has(index)) { 11.275 @@ -2517,7 +2571,7 @@ 11.276 11.277 @Override 11.278 public double getDouble(final long key) { 11.279 - final int index = ArrayIndex.getArrayIndex(key); 11.280 + final int index = getArrayIndex(key); 11.281 final ArrayData array = getArray(); 11.282 11.283 if (array.has(index)) { 11.284 @@ -2539,7 +2593,7 @@ 11.285 } 11.286 11.287 private Object get(final int index, final String key) { 11.288 - if (ArrayIndex.isValidArrayIndex(index)) { 11.289 + if (isValidArrayIndex(index)) { 11.290 for (ScriptObject object = this; ; ) { 11.291 final FindProperty find = object.findProperty(key, false, false, this); 11.292 11.293 @@ -2570,7 +2624,7 @@ 11.294 11.295 @Override 11.296 public Object get(final Object key) { 11.297 - final int index = ArrayIndex.getArrayIndex(key); 11.298 + final int index = getArrayIndex(key); 11.299 final ArrayData array = getArray(); 11.300 11.301 if (array.has(index)) { 11.302 @@ -2582,7 +2636,7 @@ 11.303 11.304 @Override 11.305 public Object get(final double key) { 11.306 - final int index = ArrayIndex.getArrayIndex(key); 11.307 + final int index = getArrayIndex(key); 11.308 final ArrayData array = getArray(); 11.309 11.310 if (array.has(index)) { 11.311 @@ -2594,7 +2648,7 @@ 11.312 11.313 @Override 11.314 public Object get(final long key) { 11.315 - final int index = ArrayIndex.getArrayIndex(key); 11.316 + final int index = getArrayIndex(key); 11.317 final ArrayData array = getArray(); 11.318 11.319 if (array.has(index)) { 11.320 @@ -2710,9 +2764,9 @@ 11.321 11.322 @Override 11.323 public void set(final Object key, final int value, final boolean strict) { 11.324 - final int index = ArrayIndex.getArrayIndex(key); 11.325 - 11.326 - if (ArrayIndex.isValidArrayIndex(index)) { 11.327 + final int index = getArrayIndex(key); 11.328 + 11.329 + if (isValidArrayIndex(index)) { 11.330 if (getArray().has(index)) { 11.331 setArray(getArray().set(index, value, strict)); 11.332 } else { 11.333 @@ -2722,14 +2776,15 @@ 11.334 return; 11.335 } 11.336 11.337 - set(key, JSType.toObject(value), strict); 11.338 + final String propName = JSType.toString(key); 11.339 + setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 11.340 } 11.341 11.342 @Override 11.343 public void set(final Object key, final long value, final boolean strict) { 11.344 - final int index = ArrayIndex.getArrayIndex(key); 11.345 - 11.346 - if (ArrayIndex.isValidArrayIndex(index)) { 11.347 + final int index = getArrayIndex(key); 11.348 + 11.349 + if (isValidArrayIndex(index)) { 11.350 if (getArray().has(index)) { 11.351 setArray(getArray().set(index, value, strict)); 11.352 } else { 11.353 @@ -2739,14 +2794,15 @@ 11.354 return; 11.355 } 11.356 11.357 - set(key, JSType.toObject(value), strict); 11.358 + final String propName = JSType.toString(key); 11.359 + setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 11.360 } 11.361 11.362 @Override 11.363 public void set(final Object key, final double value, final boolean strict) { 11.364 - final int index = ArrayIndex.getArrayIndex(key); 11.365 - 11.366 - if (ArrayIndex.isValidArrayIndex(index)) { 11.367 + final int index = getArrayIndex(key); 11.368 + 11.369 + if (isValidArrayIndex(index)) { 11.370 if (getArray().has(index)) { 11.371 setArray(getArray().set(index, value, strict)); 11.372 } else { 11.373 @@ -2756,14 +2812,15 @@ 11.374 return; 11.375 } 11.376 11.377 - set(key, JSType.toObject(value), strict); 11.378 + final String propName = JSType.toString(key); 11.379 + setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 11.380 } 11.381 11.382 @Override 11.383 public void set(final Object key, final Object value, final boolean strict) { 11.384 - final int index = ArrayIndex.getArrayIndex(key); 11.385 - 11.386 - if (ArrayIndex.isValidArrayIndex(index)) { 11.387 + final int index = getArrayIndex(key); 11.388 + 11.389 + if (isValidArrayIndex(index)) { 11.390 if (getArray().has(index)) { 11.391 setArray(getArray().set(index, value, strict)); 11.392 } else { 11.393 @@ -2773,17 +2830,15 @@ 11.394 return; 11.395 } 11.396 11.397 - final String propName = JSType.toString(key); 11.398 - final FindProperty find = findProperty(propName, true); 11.399 - 11.400 - setObject(find, strict, propName, value); 11.401 + final String propName = JSType.toString(key); 11.402 + setObject(findProperty(propName, true), strict, propName, value); 11.403 } 11.404 11.405 @Override 11.406 public void set(final double key, final int value, final boolean strict) { 11.407 - final int index = ArrayIndex.getArrayIndex(key); 11.408 - 11.409 - if (ArrayIndex.isValidArrayIndex(index)) { 11.410 + final int index = getArrayIndex(key); 11.411 + 11.412 + if (isValidArrayIndex(index)) { 11.413 if (getArray().has(index)) { 11.414 setArray(getArray().set(index, value, strict)); 11.415 } else { 11.416 @@ -2793,14 +2848,15 @@ 11.417 return; 11.418 } 11.419 11.420 - set(JSType.toObject(key), JSType.toObject(value), strict); 11.421 + final String propName = JSType.toString(key); 11.422 + setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 11.423 } 11.424 11.425 @Override 11.426 public void set(final double key, final long value, final boolean strict) { 11.427 - final int index = ArrayIndex.getArrayIndex(key); 11.428 - 11.429 - if (ArrayIndex.isValidArrayIndex(index)) { 11.430 + final int index = getArrayIndex(key); 11.431 + 11.432 + if (isValidArrayIndex(index)) { 11.433 if (getArray().has(index)) { 11.434 setArray(getArray().set(index, value, strict)); 11.435 } else { 11.436 @@ -2810,14 +2866,15 @@ 11.437 return; 11.438 } 11.439 11.440 - set(JSType.toObject(key), JSType.toObject(value), strict); 11.441 + final String propName = JSType.toString(key); 11.442 + setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 11.443 } 11.444 11.445 @Override 11.446 public void set(final double key, final double value, final boolean strict) { 11.447 - final int index = ArrayIndex.getArrayIndex(key); 11.448 - 11.449 - if (ArrayIndex.isValidArrayIndex(index)) { 11.450 + final int index = getArrayIndex(key); 11.451 + 11.452 + if (isValidArrayIndex(index)) { 11.453 if (getArray().has(index)) { 11.454 setArray(getArray().set(index, value, strict)); 11.455 } else { 11.456 @@ -2827,14 +2884,15 @@ 11.457 return; 11.458 } 11.459 11.460 - set(JSType.toObject(key), JSType.toObject(value), strict); 11.461 + final String propName = JSType.toString(key); 11.462 + setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 11.463 } 11.464 11.465 @Override 11.466 public void set(final double key, final Object value, final boolean strict) { 11.467 - final int index = ArrayIndex.getArrayIndex(key); 11.468 - 11.469 - if (ArrayIndex.isValidArrayIndex(index)) { 11.470 + final int index = getArrayIndex(key); 11.471 + 11.472 + if (isValidArrayIndex(index)) { 11.473 if (getArray().has(index)) { 11.474 setArray(getArray().set(index, value, strict)); 11.475 } else { 11.476 @@ -2844,14 +2902,15 @@ 11.477 return; 11.478 } 11.479 11.480 - set(JSType.toObject(key), value, strict); 11.481 + final String propName = JSType.toString(key); 11.482 + setObject(findProperty(propName, true), strict, propName, value); 11.483 } 11.484 11.485 @Override 11.486 public void set(final long key, final int value, final boolean strict) { 11.487 - final int index = ArrayIndex.getArrayIndex(key); 11.488 - 11.489 - if (ArrayIndex.isValidArrayIndex(index)) { 11.490 + final int index = getArrayIndex(key); 11.491 + 11.492 + if (isValidArrayIndex(index)) { 11.493 if (getArray().has(index)) { 11.494 setArray(getArray().set(index, value, strict)); 11.495 } else { 11.496 @@ -2861,14 +2920,15 @@ 11.497 return; 11.498 } 11.499 11.500 - set(JSType.toObject(key), JSType.toObject(value), strict); 11.501 + final String propName = JSType.toString(key); 11.502 + setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 11.503 } 11.504 11.505 @Override 11.506 public void set(final long key, final long value, final boolean strict) { 11.507 - final int index = ArrayIndex.getArrayIndex(key); 11.508 - 11.509 - if (ArrayIndex.isValidArrayIndex(index)) { 11.510 + final int index = getArrayIndex(key); 11.511 + 11.512 + if (isValidArrayIndex(index)) { 11.513 if (getArray().has(index)) { 11.514 setArray(getArray().set(index, value, strict)); 11.515 } else { 11.516 @@ -2878,14 +2938,15 @@ 11.517 return; 11.518 } 11.519 11.520 - set(JSType.toObject(key), JSType.toObject(value), strict); 11.521 + final String propName = JSType.toString(key); 11.522 + setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 11.523 } 11.524 11.525 @Override 11.526 public void set(final long key, final double value, final boolean strict) { 11.527 - final int index = ArrayIndex.getArrayIndex(key); 11.528 - 11.529 - if (ArrayIndex.isValidArrayIndex(index)) { 11.530 + final int index = getArrayIndex(key); 11.531 + 11.532 + if (isValidArrayIndex(index)) { 11.533 if (getArray().has(index)) { 11.534 setArray(getArray().set(index, value, strict)); 11.535 } else { 11.536 @@ -2895,14 +2956,15 @@ 11.537 return; 11.538 } 11.539 11.540 - set(JSType.toObject(key), JSType.toObject(value), strict); 11.541 + final String propName = JSType.toString(key); 11.542 + setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 11.543 } 11.544 11.545 @Override 11.546 public void set(final long key, final Object value, final boolean strict) { 11.547 - final int index = ArrayIndex.getArrayIndex(key); 11.548 - 11.549 - if (ArrayIndex.isValidArrayIndex(index)) { 11.550 + final int index = getArrayIndex(key); 11.551 + 11.552 + if (isValidArrayIndex(index)) { 11.553 if (getArray().has(index)) { 11.554 setArray(getArray().set(index, value, strict)); 11.555 } else { 11.556 @@ -2912,14 +2974,15 @@ 11.557 return; 11.558 } 11.559 11.560 - set(JSType.toObject(key), value, strict); 11.561 + final String propName = JSType.toString(key); 11.562 + setObject(findProperty(propName, true), strict, propName, value); 11.563 } 11.564 11.565 @Override 11.566 public void set(final int key, final int value, final boolean strict) { 11.567 - final int index = ArrayIndex.getArrayIndex(key); 11.568 - 11.569 - if (ArrayIndex.isValidArrayIndex(index)) { 11.570 + final int index = getArrayIndex(key); 11.571 + 11.572 + if (isValidArrayIndex(index)) { 11.573 if (getArray().has(index)) { 11.574 setArray(getArray().set(index, value, strict)); 11.575 } else { 11.576 @@ -2929,14 +2992,15 @@ 11.577 return; 11.578 } 11.579 11.580 - set(JSType.toObject(key), JSType.toObject(value), strict); 11.581 + final String propName = JSType.toString(key); 11.582 + setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 11.583 } 11.584 11.585 @Override 11.586 public void set(final int key, final long value, final boolean strict) { 11.587 - final int index = ArrayIndex.getArrayIndex(key); 11.588 - 11.589 - if (ArrayIndex.isValidArrayIndex(index)) { 11.590 + final int index = getArrayIndex(key); 11.591 + 11.592 + if (isValidArrayIndex(index)) { 11.593 if (getArray().has(index)) { 11.594 setArray(getArray().set(index, value, strict)); 11.595 } else { 11.596 @@ -2946,14 +3010,15 @@ 11.597 return; 11.598 } 11.599 11.600 - set(JSType.toObject(key), JSType.toObject(value), strict); 11.601 + final String propName = JSType.toString(key); 11.602 + setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 11.603 } 11.604 11.605 @Override 11.606 public void set(final int key, final double value, final boolean strict) { 11.607 - final int index = ArrayIndex.getArrayIndex(key); 11.608 - 11.609 - if (ArrayIndex.isValidArrayIndex(index)) { 11.610 + final int index = getArrayIndex(key); 11.611 + 11.612 + if (isValidArrayIndex(index)) { 11.613 if (getArray().has(index)) { 11.614 setArray(getArray().set(index, value, strict)); 11.615 } else { 11.616 @@ -2963,14 +3028,15 @@ 11.617 return; 11.618 } 11.619 11.620 - set(JSType.toObject(key), JSType.toObject(value), strict); 11.621 + final String propName = JSType.toString(key); 11.622 + setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 11.623 } 11.624 11.625 @Override 11.626 public void set(final int key, final Object value, final boolean strict) { 11.627 - final int index = ArrayIndex.getArrayIndex(key); 11.628 - 11.629 - if (ArrayIndex.isValidArrayIndex(index)) { 11.630 + final int index = getArrayIndex(key); 11.631 + 11.632 + if (isValidArrayIndex(index)) { 11.633 if (getArray().has(index)) { 11.634 setArray(getArray().set(index, value, strict)); 11.635 } else { 11.636 @@ -2980,14 +3046,15 @@ 11.637 return; 11.638 } 11.639 11.640 - set(JSType.toObject(key), value, strict); 11.641 + final String propName = JSType.toString(key); 11.642 + setObject(findProperty(propName, true), strict, propName, value); 11.643 } 11.644 11.645 @Override 11.646 public boolean has(final Object key) { 11.647 - final int index = ArrayIndex.getArrayIndex(key); 11.648 - 11.649 - if (ArrayIndex.isValidArrayIndex(index)) { 11.650 + final int index = getArrayIndex(key); 11.651 + 11.652 + if (isValidArrayIndex(index)) { 11.653 for (ScriptObject self = this; self != null; self = self.getProto()) { 11.654 if (self.getArray().has(index)) { 11.655 return true; 11.656 @@ -2995,16 +3062,14 @@ 11.657 } 11.658 } 11.659 11.660 - final FindProperty find = findProperty(JSType.toString(key), true); 11.661 - 11.662 - return find != null; 11.663 + return hasProperty(JSType.toString(key), true); 11.664 } 11.665 11.666 @Override 11.667 public boolean has(final double key) { 11.668 - final int index = ArrayIndex.getArrayIndex(key); 11.669 - 11.670 - if (ArrayIndex.isValidArrayIndex(index)) { 11.671 + final int index = getArrayIndex(key); 11.672 + 11.673 + if (isValidArrayIndex(index)) { 11.674 for (ScriptObject self = this; self != null; self = self.getProto()) { 11.675 if (self.getArray().has(index)) { 11.676 return true; 11.677 @@ -3012,16 +3077,14 @@ 11.678 } 11.679 } 11.680 11.681 - final FindProperty find = findProperty(JSType.toString(key), true); 11.682 - 11.683 - return find != null; 11.684 + return hasProperty(JSType.toString(key), true); 11.685 } 11.686 11.687 @Override 11.688 public boolean has(final long key) { 11.689 - final int index = ArrayIndex.getArrayIndex(key); 11.690 - 11.691 - if (ArrayIndex.isValidArrayIndex(index)) { 11.692 + final int index = getArrayIndex(key); 11.693 + 11.694 + if (isValidArrayIndex(index)) { 11.695 for (ScriptObject self = this; self != null; self = self.getProto()) { 11.696 if (self.getArray().has(index)) { 11.697 return true; 11.698 @@ -3029,16 +3092,14 @@ 11.699 } 11.700 } 11.701 11.702 - final FindProperty find = findProperty(JSType.toString(key), true); 11.703 - 11.704 - return find != null; 11.705 + return hasProperty(JSType.toString(key), true); 11.706 } 11.707 11.708 @Override 11.709 public boolean has(final int key) { 11.710 - final int index = ArrayIndex.getArrayIndex(key); 11.711 - 11.712 - if (ArrayIndex.isValidArrayIndex(index)) { 11.713 + final int index = getArrayIndex(key); 11.714 + 11.715 + if (isValidArrayIndex(index)) { 11.716 for (ScriptObject self = this; self != null; self = self.getProto()) { 11.717 if (self.getArray().has(index)) { 11.718 return true; 11.719 @@ -3046,66 +3107,32 @@ 11.720 } 11.721 } 11.722 11.723 - final FindProperty find = findProperty(JSType.toString(key), true); 11.724 - 11.725 - return find != null; 11.726 + return hasProperty(JSType.toString(key), true); 11.727 } 11.728 11.729 @Override 11.730 public boolean hasOwnProperty(final Object key) { 11.731 - final int index = ArrayIndex.getArrayIndex(key); 11.732 - 11.733 - if (getArray().has(index)) { 11.734 - return true; 11.735 - } 11.736 - 11.737 - final FindProperty find = findProperty(JSType.toString(key), false); 11.738 - 11.739 - return find != null; 11.740 + return getArray().has(getArrayIndex(key)) || hasProperty(JSType.toString(key), false); 11.741 } 11.742 11.743 @Override 11.744 public boolean hasOwnProperty(final int key) { 11.745 - final int index = ArrayIndex.getArrayIndex(key); 11.746 - 11.747 - if (getArray().has(index)) { 11.748 - return true; 11.749 - } 11.750 - 11.751 - final FindProperty find = findProperty(JSType.toString(key), false); 11.752 - 11.753 - return find != null; 11.754 + return getArray().has(getArrayIndex(key)) || hasProperty(JSType.toString(key), false); 11.755 } 11.756 11.757 @Override 11.758 public boolean hasOwnProperty(final long key) { 11.759 - final int index = ArrayIndex.getArrayIndex(key); 11.760 - 11.761 - if (getArray().has(index)) { 11.762 - return true; 11.763 - } 11.764 - 11.765 - final FindProperty find = findProperty(JSType.toString(key), false); 11.766 - 11.767 - return find != null; 11.768 + return getArray().has(getArrayIndex(key)) || hasProperty(JSType.toString(key), false); 11.769 } 11.770 11.771 @Override 11.772 public boolean hasOwnProperty(final double key) { 11.773 - final int index = ArrayIndex.getArrayIndex(key); 11.774 - 11.775 - if (getArray().has(index)) { 11.776 - return true; 11.777 - } 11.778 - 11.779 - final FindProperty find = findProperty(JSType.toString(key), false); 11.780 - 11.781 - return find != null; 11.782 + return getArray().has(getArrayIndex(key)) || hasProperty(JSType.toString(key), false); 11.783 } 11.784 11.785 @Override 11.786 public boolean delete(final int key, final boolean strict) { 11.787 - final int index = ArrayIndex.getArrayIndex(key); 11.788 + final int index = getArrayIndex(key); 11.789 final ArrayData array = getArray(); 11.790 11.791 if (array.has(index)) { 11.792 @@ -3121,7 +3148,7 @@ 11.793 11.794 @Override 11.795 public boolean delete(final long key, final boolean strict) { 11.796 - final int index = ArrayIndex.getArrayIndex(key); 11.797 + final int index = getArrayIndex(key); 11.798 final ArrayData array = getArray(); 11.799 11.800 if (array.has(index)) { 11.801 @@ -3137,7 +3164,7 @@ 11.802 11.803 @Override 11.804 public boolean delete(final double key, final boolean strict) { 11.805 - final int index = ArrayIndex.getArrayIndex(key); 11.806 + final int index = getArrayIndex(key); 11.807 final ArrayData array = getArray(); 11.808 11.809 if (array.has(index)) { 11.810 @@ -3153,7 +3180,7 @@ 11.811 11.812 @Override 11.813 public boolean delete(final Object key, final boolean strict) { 11.814 - final int index = ArrayIndex.getArrayIndex(key); 11.815 + final int index = getArrayIndex(key); 11.816 final ArrayData array = getArray(); 11.817 11.818 if (array.has(index)) {
12.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Fri Oct 11 23:31:18 2013 -0700 12.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Tue Oct 15 22:13:56 2013 +0530 12.3 @@ -25,9 +25,9 @@ 12.4 12.5 package jdk.nashorn.internal.runtime.linker; 12.6 12.7 +import static jdk.nashorn.internal.lookup.Lookup.MH; 12.8 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 12.9 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 12.10 -import static jdk.nashorn.internal.lookup.Lookup.MH; 12.11 12.12 import java.lang.invoke.MethodHandle; 12.13 import java.lang.invoke.MethodHandles; 12.14 @@ -211,6 +211,20 @@ 12.15 return null; 12.16 } else if (obj instanceof Long) { 12.17 return (Long) obj; 12.18 + } else if (obj instanceof Integer) { 12.19 + return ((Integer)obj).longValue(); 12.20 + } else if (obj instanceof Double) { 12.21 + final Double d = (Double)obj; 12.22 + if(Double.isInfinite(d.doubleValue())) { 12.23 + return 0L; 12.24 + } 12.25 + return d.longValue(); 12.26 + } else if (obj instanceof Float) { 12.27 + final Float f = (Float)obj; 12.28 + if(Float.isInfinite(f.floatValue())) { 12.29 + return 0L; 12.30 + } 12.31 + return f.longValue(); 12.32 } else if (obj instanceof Number) { 12.33 return ((Number)obj).longValue(); 12.34 } else if (obj instanceof String || obj instanceof ConsString) {
13.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java Fri Oct 11 23:31:18 2013 -0700 13.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java Tue Oct 15 22:13:56 2013 +0530 13.3 @@ -30,6 +30,8 @@ 13.4 import java.lang.invoke.MethodHandle; 13.5 import java.lang.invoke.MethodHandles; 13.6 import java.lang.reflect.Modifier; 13.7 +import java.util.Deque; 13.8 +import java.util.List; 13.9 import jdk.internal.dynalink.CallSiteDescriptor; 13.10 import jdk.internal.dynalink.linker.ConversionComparator; 13.11 import jdk.internal.dynalink.linker.GuardedInvocation; 13.12 @@ -38,6 +40,8 @@ 13.13 import jdk.internal.dynalink.linker.LinkerServices; 13.14 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; 13.15 import jdk.internal.dynalink.support.Guards; 13.16 +import jdk.nashorn.internal.objects.NativeArray; 13.17 +import jdk.nashorn.internal.runtime.JSType; 13.18 import jdk.nashorn.internal.runtime.ScriptFunction; 13.19 import jdk.nashorn.internal.runtime.ScriptObject; 13.20 import jdk.nashorn.internal.runtime.Undefined; 13.21 @@ -47,6 +51,13 @@ 13.22 * includes {@link ScriptFunction} and its subclasses) as well as {@link Undefined}. 13.23 */ 13.24 final class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory, ConversionComparator { 13.25 + private static final ClassValue<MethodHandle> ARRAY_CONVERTERS = new ClassValue<MethodHandle>() { 13.26 + @Override 13.27 + protected MethodHandle computeValue(Class<?> type) { 13.28 + return createArrayConverter(type); 13.29 + } 13.30 + }; 13.31 + 13.32 /** 13.33 * Returns true if {@code ScriptObject} is assignable from {@code type}, or it is {@code Undefined}. 13.34 */ 13.35 @@ -103,6 +114,12 @@ 13.36 if (mh != null) { 13.37 return new GuardedInvocation(mh, canLinkTypeStatic(sourceType) ? null : IS_NASHORN_OR_UNDEFINED_TYPE); 13.38 } 13.39 + 13.40 + GuardedInvocation inv = getArrayConverter(sourceType, targetType); 13.41 + if(inv != null) { 13.42 + return inv; 13.43 + } 13.44 + 13.45 return getSamTypeConverter(sourceType, targetType); 13.46 } 13.47 13.48 @@ -129,6 +146,41 @@ 13.49 return null; 13.50 } 13.51 13.52 + /** 13.53 + * Returns a guarded invocation that converts from a source type that is NativeArray to a Java array or List or 13.54 + * Deque type. 13.55 + * @param sourceType the source type (presumably NativeArray a superclass of it) 13.56 + * @param targetType the target type (presumably an array type, or List or Deque) 13.57 + * @return a guarded invocation that converts from the source type to the target type. null is returned if 13.58 + * either the source type is neither NativeArray, nor a superclass of it, or if the target type is not an array 13.59 + * type, List, or Deque. 13.60 + */ 13.61 + private static GuardedInvocation getArrayConverter(final Class<?> sourceType, final Class<?> targetType) { 13.62 + final boolean isSourceTypeNativeArray = sourceType == NativeArray.class; 13.63 + // If source type is more generic than ScriptFunction class, we'll need to use a guard 13.64 + final boolean isSourceTypeGeneric = !isSourceTypeNativeArray && sourceType.isAssignableFrom(NativeArray.class); 13.65 + 13.66 + if (isSourceTypeNativeArray || isSourceTypeGeneric) { 13.67 + final MethodHandle guard = isSourceTypeGeneric ? IS_NATIVE_ARRAY : null; 13.68 + if(targetType.isArray()) { 13.69 + return new GuardedInvocation(ARRAY_CONVERTERS.get(targetType), guard); 13.70 + } 13.71 + if(targetType == List.class) { 13.72 + return new GuardedInvocation(JSType.TO_JAVA_LIST.methodHandle(), guard); 13.73 + } 13.74 + if(targetType == Deque.class) { 13.75 + return new GuardedInvocation(JSType.TO_JAVA_DEQUE.methodHandle(), guard); 13.76 + } 13.77 + } 13.78 + return null; 13.79 + } 13.80 + 13.81 + private static MethodHandle createArrayConverter(final Class<?> type) { 13.82 + assert type.isArray(); 13.83 + final MethodHandle converter = MH.insertArguments(JSType.TO_JAVA_ARRAY.methodHandle(), 1, type.getComponentType()); 13.84 + return MH.asType(converter, converter.type().changeReturnType(type)); 13.85 + } 13.86 + 13.87 private static boolean isAutoConvertibleFromFunction(final Class<?> clazz) { 13.88 return isAbstractClass(clazz) && !ScriptObject.class.isAssignableFrom(clazz) && 13.89 JavaAdapterFactory.isAutoConvertibleFromFunction(clazz); 13.90 @@ -148,7 +200,26 @@ 13.91 13.92 @Override 13.93 public Comparison compareConversion(final Class<?> sourceType, final Class<?> targetType1, final Class<?> targetType2) { 13.94 + if(sourceType == NativeArray.class) { 13.95 + // Prefer lists, as they're less costly to create than arrays. 13.96 + if(isList(targetType1)) { 13.97 + if(!isList(targetType2)) { 13.98 + return Comparison.TYPE_1_BETTER; 13.99 + } 13.100 + } else if(isList(targetType2)) { 13.101 + return Comparison.TYPE_2_BETTER; 13.102 + } 13.103 + // Then prefer arrays 13.104 + if(targetType1.isArray()) { 13.105 + if(!targetType2.isArray()) { 13.106 + return Comparison.TYPE_1_BETTER; 13.107 + } 13.108 + } else if(targetType2.isArray()) { 13.109 + return Comparison.TYPE_2_BETTER; 13.110 + } 13.111 + } 13.112 if(ScriptObject.class.isAssignableFrom(sourceType)) { 13.113 + // Prefer interfaces 13.114 if(targetType1.isInterface()) { 13.115 if(!targetType2.isInterface()) { 13.116 return Comparison.TYPE_1_BETTER; 13.117 @@ -160,7 +231,12 @@ 13.118 return Comparison.INDETERMINATE; 13.119 } 13.120 13.121 + private static boolean isList(Class<?> clazz) { 13.122 + return clazz == List.class || clazz == Deque.class; 13.123 + } 13.124 + 13.125 private static final MethodHandle IS_SCRIPT_FUNCTION = Guards.isInstance(ScriptFunction.class, MH.type(Boolean.TYPE, Object.class)); 13.126 + private static final MethodHandle IS_NATIVE_ARRAY = Guards.isOfClass(NativeArray.class, MH.type(Boolean.TYPE, Object.class)); 13.127 13.128 private static final MethodHandle IS_NASHORN_OR_UNDEFINED_TYPE = findOwnMH("isNashornTypeOrUndefined", 13.129 Boolean.TYPE, Object.class);
14.1 --- a/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js Fri Oct 11 23:31:18 2013 -0700 14.2 +++ b/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js Tue Oct 15 22:13:56 2013 +0530 14.3 @@ -98,6 +98,17 @@ 14.4 14.5 } 14.6 14.7 +// sync 14.8 +Object.defineProperty(this, "sync", { 14.9 + configurable: true, enumerable: false, writable: true, 14.10 + value: function(func, syncobj) { 14.11 + if (arguments.length < 1 || arguments.length > 2 ) { 14.12 + throw "sync(function [,object]) parameter count mismatch"; 14.13 + } 14.14 + return Packages.jdk.nashorn.api.scripting.ScriptUtils.makeSynchronizedFunction(func, syncobj); 14.15 + } 14.16 +}); 14.17 + 14.18 // Object.prototype.__defineGetter__ 14.19 Object.defineProperty(Object.prototype, "__defineGetter__", { 14.20 configurable: true, enumerable: false, writable: true,
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/test/script/basic/JDK-8026016.js Tue Oct 15 22:13:56 2013 +0530 15.3 @@ -0,0 +1,68 @@ 15.4 +/* 15.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 15.7 + * 15.8 + * This code is free software; you can redistribute it and/or modify it 15.9 + * under the terms of the GNU General Public License version 2 only, as 15.10 + * published by the Free Software Foundation. 15.11 + * 15.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 15.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15.15 + * version 2 for more details (a copy is included in the LICENSE file that 15.16 + * accompanied this code). 15.17 + * 15.18 + * You should have received a copy of the GNU General Public License version 15.19 + * 2 along with this work; if not, write to the Free Software Foundation, 15.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 15.21 + * 15.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 15.23 + * or visit www.oracle.com if you need additional information or have any 15.24 + * questions. 15.25 + */ 15.26 + 15.27 +/** 15.28 + * JDK-8026016: too many relinks dominate avatar.js http benchmark 15.29 + * 15.30 + * @test 15.31 + * @run 15.32 + */ 15.33 + 15.34 +function accessMegamorphic() { 15.35 + for (var i = 0; i < 26; i++) { 15.36 + var o = {}; 15.37 + o[String.fromCharCode(i + 97)] = 1; 15.38 + o._; 15.39 + } 15.40 +} 15.41 + 15.42 +function invokeMegamorphic() { 15.43 + for (var i = 0; i < 26; i++) { 15.44 + var o = {}; 15.45 + o[String.fromCharCode(i + 97)] = 1; 15.46 + try { 15.47 + o._(i); 15.48 + } catch (e) { 15.49 + print(e); 15.50 + } 15.51 + } 15.52 +} 15.53 + 15.54 +Object.prototype.__noSuchProperty__ = function() { 15.55 + print("no such property", Array.prototype.slice.call(arguments)); 15.56 +}; 15.57 + 15.58 +invokeMegamorphic(); 15.59 +accessMegamorphic(); 15.60 + 15.61 +Object.prototype.__noSuchMethod__ = function() { 15.62 + print("no such method", Array.prototype.slice.call(arguments)); 15.63 +}; 15.64 + 15.65 +invokeMegamorphic(); 15.66 +accessMegamorphic(); 15.67 + 15.68 +Object.prototype.__noSuchMethod__ = "nofunction"; 15.69 + 15.70 +invokeMegamorphic(); 15.71 +accessMegamorphic();
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/test/script/basic/JDK-8026016.js.EXPECTED Tue Oct 15 22:13:56 2013 +0530 16.3 @@ -0,0 +1,182 @@ 16.4 +no such property _ 16.5 +TypeError: Cannot call undefined 16.6 +no such property _ 16.7 +TypeError: Cannot call undefined 16.8 +no such property _ 16.9 +TypeError: Cannot call undefined 16.10 +no such property _ 16.11 +TypeError: Cannot call undefined 16.12 +no such property _ 16.13 +TypeError: Cannot call undefined 16.14 +no such property _ 16.15 +TypeError: Cannot call undefined 16.16 +no such property _ 16.17 +TypeError: Cannot call undefined 16.18 +no such property _ 16.19 +TypeError: Cannot call undefined 16.20 +no such property _ 16.21 +TypeError: Cannot call undefined 16.22 +no such property _ 16.23 +TypeError: Cannot call undefined 16.24 +no such property _ 16.25 +TypeError: Cannot call undefined 16.26 +no such property _ 16.27 +TypeError: Cannot call undefined 16.28 +no such property _ 16.29 +TypeError: Cannot call undefined 16.30 +no such property _ 16.31 +TypeError: Cannot call undefined 16.32 +no such property _ 16.33 +TypeError: Cannot call undefined 16.34 +no such property _ 16.35 +TypeError: Cannot call undefined 16.36 +no such property _ 16.37 +TypeError: Cannot call undefined 16.38 +no such property _ 16.39 +TypeError: Cannot call undefined 16.40 +no such property _ 16.41 +TypeError: Cannot call undefined 16.42 +no such property _ 16.43 +TypeError: Cannot call undefined 16.44 +no such property _ 16.45 +TypeError: Cannot call undefined 16.46 +no such property _ 16.47 +TypeError: Cannot call undefined 16.48 +no such property _ 16.49 +TypeError: Cannot call undefined 16.50 +no such property _ 16.51 +TypeError: Cannot call undefined 16.52 +no such property _ 16.53 +TypeError: Cannot call undefined 16.54 +no such property _ 16.55 +TypeError: Cannot call undefined 16.56 +no such property _ 16.57 +no such property _ 16.58 +no such property _ 16.59 +no such property _ 16.60 +no such property _ 16.61 +no such property _ 16.62 +no such property _ 16.63 +no such property _ 16.64 +no such property _ 16.65 +no such property _ 16.66 +no such property _ 16.67 +no such property _ 16.68 +no such property _ 16.69 +no such property _ 16.70 +no such property _ 16.71 +no such property _ 16.72 +no such property _ 16.73 +no such property _ 16.74 +no such property _ 16.75 +no such property _ 16.76 +no such property _ 16.77 +no such property _ 16.78 +no such property _ 16.79 +no such property _ 16.80 +no such property _ 16.81 +no such property _ 16.82 +no such method _,0 16.83 +no such method _,1 16.84 +no such method _,2 16.85 +no such method _,3 16.86 +no such method _,4 16.87 +no such method _,5 16.88 +no such method _,6 16.89 +no such method _,7 16.90 +no such method _,8 16.91 +no such method _,9 16.92 +no such method _,10 16.93 +no such method _,11 16.94 +no such method _,12 16.95 +no such method _,13 16.96 +no such method _,14 16.97 +no such method _,15 16.98 +no such method _,16 16.99 +no such method _,17 16.100 +no such method _,18 16.101 +no such method _,19 16.102 +no such method _,20 16.103 +no such method _,21 16.104 +no such method _,22 16.105 +no such method _,23 16.106 +no such method _,24 16.107 +no such method _,25 16.108 +no such property _ 16.109 +no such property _ 16.110 +no such property _ 16.111 +no such property _ 16.112 +no such property _ 16.113 +no such property _ 16.114 +no such property _ 16.115 +no such property _ 16.116 +no such property _ 16.117 +no such property _ 16.118 +no such property _ 16.119 +no such property _ 16.120 +no such property _ 16.121 +no such property _ 16.122 +no such property _ 16.123 +no such property _ 16.124 +no such property _ 16.125 +no such property _ 16.126 +no such property _ 16.127 +no such property _ 16.128 +no such property _ 16.129 +no such property _ 16.130 +no such property _ 16.131 +no such property _ 16.132 +no such property _ 16.133 +no such property _ 16.134 +TypeError: Cannot call undefined 16.135 +TypeError: Cannot call undefined 16.136 +TypeError: Cannot call undefined 16.137 +TypeError: Cannot call undefined 16.138 +TypeError: Cannot call undefined 16.139 +TypeError: Cannot call undefined 16.140 +TypeError: Cannot call undefined 16.141 +TypeError: Cannot call undefined 16.142 +TypeError: Cannot call undefined 16.143 +TypeError: Cannot call undefined 16.144 +TypeError: Cannot call undefined 16.145 +TypeError: Cannot call undefined 16.146 +TypeError: Cannot call undefined 16.147 +TypeError: Cannot call undefined 16.148 +TypeError: Cannot call undefined 16.149 +TypeError: Cannot call undefined 16.150 +TypeError: Cannot call undefined 16.151 +TypeError: Cannot call undefined 16.152 +TypeError: Cannot call undefined 16.153 +TypeError: Cannot call undefined 16.154 +TypeError: Cannot call undefined 16.155 +TypeError: Cannot call undefined 16.156 +TypeError: Cannot call undefined 16.157 +TypeError: Cannot call undefined 16.158 +TypeError: Cannot call undefined 16.159 +TypeError: Cannot call undefined 16.160 +no such property _ 16.161 +no such property _ 16.162 +no such property _ 16.163 +no such property _ 16.164 +no such property _ 16.165 +no such property _ 16.166 +no such property _ 16.167 +no such property _ 16.168 +no such property _ 16.169 +no such property _ 16.170 +no such property _ 16.171 +no such property _ 16.172 +no such property _ 16.173 +no such property _ 16.174 +no such property _ 16.175 +no such property _ 16.176 +no such property _ 16.177 +no such property _ 16.178 +no such property _ 16.179 +no such property _ 16.180 +no such property _ 16.181 +no such property _ 16.182 +no such property _ 16.183 +no such property _ 16.184 +no such property _ 16.185 +no such property _
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/test/script/basic/JDK-8026367.js Tue Oct 15 22:13:56 2013 +0530 17.3 @@ -0,0 +1,61 @@ 17.4 +/* 17.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 17.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 17.7 + * 17.8 + * This code is free software; you can redistribute it and/or modify it 17.9 + * under the terms of the GNU General Public License version 2 only, as 17.10 + * published by the Free Software Foundation. 17.11 + * 17.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 17.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17.15 + * version 2 for more details (a copy is included in the LICENSE file that 17.16 + * accompanied this code). 17.17 + * 17.18 + * You should have received a copy of the GNU General Public License version 17.19 + * 2 along with this work; if not, write to the Free Software Foundation, 17.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17.21 + * 17.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 17.23 + * or visit www.oracle.com if you need additional information or have any 17.24 + * questions. 17.25 + */ 17.26 + 17.27 +/** 17.28 + * JDK-8026367: Add a sync keyword to mozilla_compat 17.29 + * 17.30 + * @test 17.31 + * @run 17.32 + */ 17.33 + 17.34 +if (typeof sync === "undefined") { 17.35 + load("nashorn:mozilla_compat.js"); 17.36 +} 17.37 + 17.38 +var obj = { 17.39 + count: 0, 17.40 + // Sync called with one argument will synchronize on this-object of invocation 17.41 + inc: sync(function(d) { 17.42 + this.count += d; 17.43 + }), 17.44 + // Pass explicit object to synchronize on as second argument 17.45 + dec: sync(function(d) { 17.46 + this.count -= d; 17.47 + }, obj) 17.48 +}; 17.49 + 17.50 +var t1 = new java.lang.Thread(function() { 17.51 + for (var i = 0; i < 100000; i++) obj.inc(1); 17.52 +}); 17.53 +var t2 = new java.lang.Thread(function() { 17.54 + for (var i = 0; i < 100000; i++) obj.dec(1); 17.55 +}); 17.56 + 17.57 +t1.start(); 17.58 +t2.start(); 17.59 +t1.join(); 17.60 +t2.join(); 17.61 + 17.62 +if (obj.count !== 0) { 17.63 + throw new Error("Expected count == 0, got " + obj.count); 17.64 +}
18.1 --- a/test/script/sandbox/loadcompat.js Fri Oct 11 23:31:18 2013 -0700 18.2 +++ b/test/script/sandbox/loadcompat.js Tue Oct 15 22:13:56 2013 +0530 18.3 @@ -48,3 +48,7 @@ 18.4 if (typeof importPackage != 'function') { 18.5 fail("importPackage function is missing in compatibility script"); 18.6 } 18.7 + 18.8 +if (typeof sync != 'function') { 18.9 + fail("sync function is missing in compatibility script"); 18.10 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java Tue Oct 15 22:13:56 2013 +0530 19.3 @@ -0,0 +1,235 @@ 19.4 +/* 19.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 19.7 + * 19.8 + * This code is free software; you can redistribute it and/or modify it 19.9 + * under the terms of the GNU General Public License version 2 only, as 19.10 + * published by the Free Software Foundation. Oracle designates this 19.11 + * particular file as subject to the "Classpath" exception as provided 19.12 + * by Oracle in the LICENSE file that accompanied this code. 19.13 + * 19.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 19.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 19.17 + * version 2 for more details (a copy is included in the LICENSE file that 19.18 + * accompanied this code). 19.19 + * 19.20 + * You should have received a copy of the GNU General Public License version 19.21 + * 2 along with this work; if not, write to the Free Software Foundation, 19.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19.23 + * 19.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19.25 + * or visit www.oracle.com if you need additional information or have any 19.26 + * questions. 19.27 + */ 19.28 + 19.29 +package jdk.nashorn.api.javaaccess; 19.30 + 19.31 +import static org.testng.AssertJUnit.assertEquals; 19.32 +import static org.testng.AssertJUnit.assertFalse; 19.33 +import static org.testng.AssertJUnit.assertNull; 19.34 +import static org.testng.AssertJUnit.assertTrue; 19.35 + 19.36 +import java.util.Arrays; 19.37 +import java.util.List; 19.38 +import javax.script.ScriptContext; 19.39 +import javax.script.ScriptEngine; 19.40 +import javax.script.ScriptEngineManager; 19.41 +import javax.script.ScriptException; 19.42 +import org.testng.TestNG; 19.43 +import org.testng.annotations.AfterClass; 19.44 +import org.testng.annotations.BeforeClass; 19.45 +import org.testng.annotations.Test; 19.46 + 19.47 +public class ArrayConversionTest { 19.48 + private static ScriptEngine e = null; 19.49 + 19.50 + public static void main(final String[] args) { 19.51 + TestNG.main(args); 19.52 + } 19.53 + 19.54 + @BeforeClass 19.55 + public static void setUpClass() throws ScriptException { 19.56 + e = new ScriptEngineManager().getEngineByName("nashorn"); 19.57 + } 19.58 + 19.59 + @AfterClass 19.60 + public static void tearDownClass() { 19.61 + e = null; 19.62 + } 19.63 + 19.64 + @Test 19.65 + public void testIntArrays() throws ScriptException { 19.66 + runTest("assertNullIntArray", "null"); 19.67 + runTest("assertEmptyIntArray", "[]"); 19.68 + runTest("assertSingle42IntArray", "[42]"); 19.69 + runTest("assertSingle42IntArray", "['42']"); 19.70 + runTest("assertIntArrayConversions", "[false, true, NaN, Infinity, -Infinity, 0.4, 0.6, null, undefined, [], {}, [1], [1, 2]]"); 19.71 + } 19.72 + 19.73 + @Test 19.74 + public void testIntIntArrays() throws ScriptException { 19.75 + runTest("assertNullIntIntArray", "null"); 19.76 + runTest("assertEmptyIntIntArray", "[]"); 19.77 + runTest("assertSingleEmptyIntIntArray", "[[]]"); 19.78 + runTest("assertSingleNullIntIntArray", "[null]"); 19.79 + runTest("assertLargeIntIntArray", "[[false], [1], [2, 3], [4, 5, 6], ['7', {valueOf: function() { return 8 }}]]"); 19.80 + } 19.81 + 19.82 + @Test 19.83 + public void testObjectObjectArrays() throws ScriptException { 19.84 + runTest("assertLargeObjectObjectArray", "[[false], [1], ['foo', 42.3], [{x: 17}]]"); 19.85 + } 19.86 + 19.87 + @Test 19.88 + public void testBooleanArrays() throws ScriptException { 19.89 + runTest("assertBooleanArrayConversions", "[false, true, '', 'false', 0, 1, 0.4, 0.6, {}, [], [false], [true], NaN, Infinity, null, undefined]"); 19.90 + } 19.91 + 19.92 + @Test 19.93 + public void testArrayAmbiguity() throws ScriptException { 19.94 + runTest("x", "'abc'"); 19.95 + runTest("x", "['foo', 'bar']"); 19.96 + } 19.97 + 19.98 + @Test 19.99 + public void testListArrays() throws ScriptException { 19.100 + runTest("assertListArray", "[['foo', 'bar'], ['apple', 'orange']]"); 19.101 + } 19.102 + 19.103 + @Test 19.104 + public void testVarArgs() throws ScriptException { 19.105 + // Sole NativeArray in vararg position becomes vararg array itself 19.106 + runTest("assertVarArg_42_17", "[42, 17]"); 19.107 + // NativeArray in vararg position becomes an argument if there are more arguments 19.108 + runTest("assertVarArg_array_17", "[42], 18"); 19.109 + // Only NativeArray is converted to vararg array, other objects (e.g. a function) aren't 19.110 + runTest("assertVarArg_function", "function() { return 'Hello' }"); 19.111 + } 19.112 + 19.113 + private static void runTest(final String testMethodName, final String argument) throws ScriptException { 19.114 + e.eval("Java.type('" + ArrayConversionTest.class.getName() + "')." + testMethodName + "(" + argument + ")"); 19.115 + } 19.116 + 19.117 + public static void assertNullIntArray(int[] array) { 19.118 + assertNull(array); 19.119 + } 19.120 + 19.121 + public static void assertNullIntIntArray(int[][] array) { 19.122 + assertNull(array); 19.123 + } 19.124 + 19.125 + public static void assertEmptyIntArray(int[] array) { 19.126 + assertEquals(0, array.length); 19.127 + } 19.128 + 19.129 + public static void assertSingle42IntArray(int[] array) { 19.130 + assertEquals(1, array.length); 19.131 + assertEquals(42, array[0]); 19.132 + } 19.133 + 19.134 + 19.135 + public static void assertIntArrayConversions(int[] array) { 19.136 + assertEquals(13, array.length); 19.137 + assertEquals(0, array[0]); // false 19.138 + assertEquals(1, array[1]); // true 19.139 + assertEquals(0, array[2]); // NaN 19.140 + assertEquals(0, array[3]); // Infinity 19.141 + assertEquals(0, array[4]); // -Infinity 19.142 + assertEquals(0, array[5]); // 0.4 19.143 + assertEquals(0, array[6]); // 0.6 - floor, not round 19.144 + assertEquals(0, array[7]); // null 19.145 + assertEquals(0, array[8]); // undefined 19.146 + assertEquals(0, array[9]); // [] 19.147 + assertEquals(0, array[10]); // {} 19.148 + assertEquals(1, array[11]); // [1] 19.149 + assertEquals(0, array[12]); // [1, 2] 19.150 + } 19.151 + 19.152 + public static void assertEmptyIntIntArray(int[][] array) { 19.153 + assertEquals(0, array.length); 19.154 + } 19.155 + 19.156 + public static void assertSingleEmptyIntIntArray(int[][] array) { 19.157 + assertEquals(1, array.length); 19.158 + assertTrue(Arrays.equals(new int[0], array[0])); 19.159 + } 19.160 + 19.161 + public static void assertSingleNullIntIntArray(int[][] array) { 19.162 + assertEquals(1, array.length); 19.163 + assertNull(null, array[0]); 19.164 + } 19.165 + 19.166 + public static void assertLargeIntIntArray(int[][] array) { 19.167 + assertEquals(5, array.length); 19.168 + assertTrue(Arrays.equals(new int[] { 0 }, array[0])); 19.169 + assertTrue(Arrays.equals(new int[] { 1 }, array[1])); 19.170 + assertTrue(Arrays.equals(new int[] { 2, 3 }, array[2])); 19.171 + assertTrue(Arrays.equals(new int[] { 4, 5, 6 }, array[3])); 19.172 + assertTrue(Arrays.equals(new int[] { 7, 8 }, array[4])); 19.173 + } 19.174 + 19.175 + public static void assertLargeObjectObjectArray(Object[][] array) throws ScriptException { 19.176 + assertEquals(4, array.length); 19.177 + assertTrue(Arrays.equals(new Object[] { Boolean.FALSE }, array[0])); 19.178 + assertTrue(Arrays.equals(new Object[] { 1 }, array[1])); 19.179 + assertTrue(Arrays.equals(new Object[] { "foo", 42.3d }, array[2])); 19.180 + assertEquals(1, array[3].length); 19.181 + e.getBindings(ScriptContext.ENGINE_SCOPE).put("obj", array[3][0]); 19.182 + assertEquals(17, e.eval("obj.x")); 19.183 + } 19.184 + 19.185 + public static void assertBooleanArrayConversions(boolean[] array) { 19.186 + assertEquals(16, array.length); 19.187 + assertFalse(array[0]); // false 19.188 + assertTrue(array[1]); // true 19.189 + assertFalse(array[2]); // '' 19.190 + assertTrue(array[3]); // 'false' (yep, every non-empty string converts to true) 19.191 + assertFalse(array[4]); // 0 19.192 + assertTrue(array[5]); // 1 19.193 + assertTrue(array[6]); // 0.4 19.194 + assertTrue(array[7]); // 0.6 19.195 + assertTrue(array[8]); // {} 19.196 + assertTrue(array[9]); // [] 19.197 + assertTrue(array[10]); // [false] 19.198 + assertTrue(array[11]); // [true] 19.199 + assertFalse(array[12]); // NaN 19.200 + assertTrue(array[13]); // Infinity 19.201 + assertFalse(array[14]); // null 19.202 + assertFalse(array[15]); // undefined 19.203 + } 19.204 + 19.205 + public static void assertListArray(List<?>[] array) { 19.206 + assertEquals(2, array.length); 19.207 + assertEquals(Arrays.asList("foo", "bar"), array[0]); 19.208 + assertEquals(Arrays.asList("apple", "orange"), array[1]); 19.209 + } 19.210 + 19.211 + public static void assertVarArg_42_17(Object... args) throws ScriptException { 19.212 + assertEquals(2, args.length); 19.213 + assertEquals(42, ((Number)args[0]).intValue()); 19.214 + assertEquals(17, ((Number)args[1]).intValue()); 19.215 + } 19.216 + 19.217 + public static void assertVarArg_array_17(Object... args) throws ScriptException { 19.218 + assertEquals(2, args.length); 19.219 + e.getBindings(ScriptContext.ENGINE_SCOPE).put("arr", args[0]); 19.220 + assertTrue((Boolean)e.eval("arr instanceof Array && arr.length == 1 && arr[0] == 42")); 19.221 + assertEquals(18, ((Number)args[1]).intValue()); 19.222 + } 19.223 + 19.224 + public static void assertVarArg_function(Object... args) throws ScriptException { 19.225 + assertEquals(1, args.length); 19.226 + e.getBindings(ScriptContext.ENGINE_SCOPE).put("fn", args[0]); 19.227 + assertEquals("Hello", e.eval("fn()")); 19.228 + } 19.229 + 19.230 + 19.231 + 19.232 + public static void x(String y) { 19.233 + assertEquals("abc", y); 19.234 + } 19.235 + public static void x(String[] y) { 19.236 + assertTrue(Arrays.equals(new String[] { "foo", "bar"}, y)); 19.237 + } 19.238 +}