Thu, 12 Mar 2015 13:45:00 -0700
Merge
src/jdk/nashorn/internal/codegen/RuntimeCallSite.java | file | annotate | diff | comparison | revisions |
1.1 --- a/src/jdk/nashorn/api/scripting/AbstractJSObject.java Wed Mar 11 14:11:06 2015 -0700 1.2 +++ b/src/jdk/nashorn/api/scripting/AbstractJSObject.java Thu Mar 12 13:45:00 2015 -0700 1.3 @@ -28,6 +28,7 @@ 1.4 import java.util.Collection; 1.5 import java.util.Collections; 1.6 import java.util.Set; 1.7 +import jdk.nashorn.internal.runtime.JSType; 1.8 1.9 /** 1.10 * This is the base class for nashorn ScriptObjectMirror class. 1.11 @@ -161,9 +162,8 @@ 1.12 * @return set of property names 1.13 */ 1.14 @Override 1.15 - @SuppressWarnings("unchecked") 1.16 public Set<String> keySet() { 1.17 - return Collections.EMPTY_SET; 1.18 + return Collections.emptySet(); 1.19 } 1.20 1.21 /** 1.22 @@ -172,9 +172,8 @@ 1.23 * @return set of property values. 1.24 */ 1.25 @Override 1.26 - @SuppressWarnings("unchecked") 1.27 public Collection<Object> values() { 1.28 - return Collections.EMPTY_SET; 1.29 + return Collections.emptySet(); 1.30 } 1.31 1.32 // JavaScript instanceof check 1.33 @@ -249,9 +248,41 @@ 1.34 * Returns this object's numeric value. 1.35 * 1.36 * @return this object's numeric value. 1.37 + * @deprecated use {@link #getDefaultValue(Class)} with {@link Number} hint instead. 1.38 */ 1.39 - @Override 1.40 + @Override @Deprecated 1.41 public double toNumber() { 1.42 - return Double.NaN; 1.43 + return JSType.toNumber(JSType.toPrimitive(this, Number.class)); 1.44 + } 1.45 + 1.46 + /** 1.47 + * Implements this object's {@code [[DefaultValue]]} method. The default implementation follows ECMAScript 5.1 1.48 + * section 8.6.2 but subclasses are free to provide their own implementations. 1.49 + * 1.50 + * @param hint the type hint. Should be either {@code null}, {@code Number.class} or {@code String.class}. 1.51 + * @return this object's default value. 1.52 + * @throws UnsupportedOperationException if the conversion can't be performed. The engine will convert this 1.53 + * exception into a JavaScript {@code TypeError}. 1.54 + */ 1.55 + public Object getDefaultValue(final Class<?> hint) { 1.56 + return DefaultValueImpl.getDefaultValue(this, hint); 1.57 + } 1.58 + 1.59 + /** 1.60 + * When passed an {@link AbstractJSObject}, invokes its {@link #getDefaultValue(Class)} method. When passed any 1.61 + * other {@link JSObject}, it will obtain its {@code [[DefaultValue]]} method as per ECMAScript 5.1 section 1.62 + * 8.6.2. 1.63 + * 1.64 + * @param jsobj the {@link JSObject} whose {@code [[DefaultValue]]} is obtained. 1.65 + * @param hint the type hint. Should be either {@code null}, {@code Number.class} or {@code String.class}. 1.66 + * @return this object's default value. 1.67 + * @throws UnsupportedOperationException if the conversion can't be performed. The engine will convert this 1.68 + * exception into a JavaScript {@code TypeError}. 1.69 + */ 1.70 + public static Object getDefaultValue(final JSObject jsobj, final Class<?> hint) { 1.71 + if (jsobj instanceof AbstractJSObject) { 1.72 + return ((AbstractJSObject)jsobj).getDefaultValue(hint); 1.73 + } 1.74 + return DefaultValueImpl.getDefaultValue(jsobj, hint); 1.75 } 1.76 }
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/jdk/nashorn/api/scripting/DefaultValueImpl.java Thu Mar 12 13:45:00 2015 -0700 2.3 @@ -0,0 +1,55 @@ 2.4 +/* 2.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. Oracle designates this 2.11 + * particular file as subject to the "Classpath" exception as provided 2.12 + * by Oracle in the LICENSE file that accompanied this code. 2.13 + * 2.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.17 + * version 2 for more details (a copy is included in the LICENSE file that 2.18 + * accompanied this code). 2.19 + * 2.20 + * You should have received a copy of the GNU General Public License version 2.21 + * 2 along with this work; if not, write to the Free Software Foundation, 2.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.23 + * 2.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.25 + * or visit www.oracle.com if you need additional information or have any 2.26 + * questions. 2.27 + */ 2.28 + 2.29 +package jdk.nashorn.api.scripting; 2.30 + 2.31 +import jdk.nashorn.internal.runtime.JSType; 2.32 + 2.33 +/** 2.34 + * Default implementation of {@link JSObject#getDefaultValue(Class)}. Isolated into a separate class mostly so 2.35 + * that we can have private static instances of function name arrays, something we couldn't declare without it 2.36 + * being visible in {@link JSObject} interface. 2.37 + */ 2.38 +class DefaultValueImpl { 2.39 + private static final String[] DEFAULT_VALUE_FNS_NUMBER = new String[] { "valueOf", "toString" }; 2.40 + private static final String[] DEFAULT_VALUE_FNS_STRING = new String[] { "toString", "valueOf" }; 2.41 + 2.42 + static Object getDefaultValue(final JSObject jsobj, final Class<?> hint) throws UnsupportedOperationException { 2.43 + final boolean isNumber = hint == null || hint == Number.class; 2.44 + for(final String methodName: isNumber ? DEFAULT_VALUE_FNS_NUMBER : DEFAULT_VALUE_FNS_STRING) { 2.45 + final Object objMember = jsobj.getMember(methodName); 2.46 + if (objMember instanceof JSObject) { 2.47 + final JSObject member = (JSObject)objMember; 2.48 + if (member.isFunction()) { 2.49 + final Object value = member.call(jsobj); 2.50 + if (JSType.isPrimitive(value)) { 2.51 + return value; 2.52 + } 2.53 + } 2.54 + } 2.55 + } 2.56 + throw new UnsupportedOperationException(isNumber ? "cannot.get.default.number" : "cannot.get.default.string"); 2.57 + } 2.58 +}
3.1 --- a/src/jdk/nashorn/api/scripting/JSObject.java Wed Mar 11 14:11:06 2015 -0700 3.2 +++ b/src/jdk/nashorn/api/scripting/JSObject.java Thu Mar 12 13:45:00 2015 -0700 3.3 @@ -186,6 +186,8 @@ 3.4 * Returns this object's numeric value. 3.5 * 3.6 * @return this object's numeric value. 3.7 + * @deprecated use {@link AbstractJSObject#getDefaultValue(JSObject, Class)} with {@link Number} hint instead. 3.8 */ 3.9 + @Deprecated 3.10 public double toNumber(); 3.11 }
4.1 --- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Wed Mar 11 14:11:06 2015 -0700 4.2 +++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Thu Mar 12 13:45:00 2015 -0700 4.3 @@ -46,6 +46,7 @@ 4.4 import jdk.nashorn.internal.objects.Global; 4.5 import jdk.nashorn.internal.runtime.ConsString; 4.6 import jdk.nashorn.internal.runtime.Context; 4.7 +import jdk.nashorn.internal.runtime.ECMAException; 4.8 import jdk.nashorn.internal.runtime.JSType; 4.9 import jdk.nashorn.internal.runtime.ScriptFunction; 4.10 import jdk.nashorn.internal.runtime.ScriptObject; 4.11 @@ -812,7 +813,7 @@ 4.12 } 4.13 } 4.14 4.15 - @Override 4.16 + @Override @Deprecated 4.17 public double toNumber() { 4.18 return inGlobal(new Callable<Double>() { 4.19 @Override public Double call() { 4.20 @@ -820,4 +821,21 @@ 4.21 } 4.22 }); 4.23 } 4.24 + 4.25 + @Override 4.26 + public Object getDefaultValue(final Class<?> hint) { 4.27 + return inGlobal(new Callable<Object>() { 4.28 + @Override public Object call() { 4.29 + try { 4.30 + return sobj.getDefaultValue(hint); 4.31 + } catch (final ECMAException e) { 4.32 + // We're catching ECMAException (likely TypeError), and translating it to 4.33 + // UnsupportedOperationException. This in turn will be translated into TypeError of the 4.34 + // caller's Global by JSType#toPrimitive(JSObject,Class) therefore ensuring that it's 4.35 + // recognized as "instanceof TypeError" in the caller. 4.36 + throw new UnsupportedOperationException(e.getMessage(), e); 4.37 + } 4.38 + } 4.39 + }); 4.40 + } 4.41 }
5.1 --- a/src/jdk/nashorn/internal/codegen/BranchOptimizer.java Wed Mar 11 14:11:06 2015 -0700 5.2 +++ b/src/jdk/nashorn/internal/codegen/BranchOptimizer.java Thu Mar 12 13:45:00 2015 -0700 5.3 @@ -105,33 +105,33 @@ 5.4 5.5 case EQ: 5.6 case EQ_STRICT: 5.7 - codegen.loadBinaryOperands(binaryNode); 5.8 + codegen.loadComparisonOperands(binaryNode); 5.9 method.conditionalJump(state ? EQ : NE, true, label); 5.10 return; 5.11 5.12 case NE: 5.13 case NE_STRICT: 5.14 - codegen.loadBinaryOperands(binaryNode); 5.15 + codegen.loadComparisonOperands(binaryNode); 5.16 method.conditionalJump(state ? NE : EQ, true, label); 5.17 return; 5.18 5.19 case GE: 5.20 - codegen.loadBinaryOperands(binaryNode); 5.21 + codegen.loadComparisonOperands(binaryNode); 5.22 method.conditionalJump(state ? GE : LT, false, label); 5.23 return; 5.24 5.25 case GT: 5.26 - codegen.loadBinaryOperands(binaryNode); 5.27 + codegen.loadComparisonOperands(binaryNode); 5.28 method.conditionalJump(state ? GT : LE, false, label); 5.29 return; 5.30 5.31 case LE: 5.32 - codegen.loadBinaryOperands(binaryNode); 5.33 + codegen.loadComparisonOperands(binaryNode); 5.34 method.conditionalJump(state ? LE : GT, true, label); 5.35 return; 5.36 5.37 case LT: 5.38 - codegen.loadBinaryOperands(binaryNode); 5.39 + codegen.loadComparisonOperands(binaryNode); 5.40 method.conditionalJump(state ? LT : GE, true, label); 5.41 return; 5.42
6.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Mar 11 14:11:06 2015 -0700 6.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Mar 12 13:45:00 2015 -0700 6.3 @@ -202,6 +202,12 @@ 6.4 private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class, 6.5 "create", ScriptFunction.class, Object[].class, int.class); 6.6 6.7 + private static final Call TO_NUMBER_FOR_EQ = CompilerConstants.staticCallNoLookup(JSType.class, 6.8 + "toNumberForEq", double.class, Object.class); 6.9 + private static final Call TO_NUMBER_FOR_STRICT_EQ = CompilerConstants.staticCallNoLookup(JSType.class, 6.10 + "toNumberForStrictEq", double.class, Object.class); 6.11 + 6.12 + 6.13 private static final Class<?> ITERATOR_CLASS = Iterator.class; 6.14 static { 6.15 assert ITERATOR_CLASS == CompilerConstants.ITERATOR_PREFIX.type(); 6.16 @@ -618,6 +624,104 @@ 6.17 return method; 6.18 } 6.19 6.20 + /** 6.21 + * Similar to {@link #loadBinaryOperands(BinaryNode)} but used specifically for loading operands of 6.22 + * relational and equality comparison operators where at least one argument is non-object. (When both 6.23 + * arguments are objects, we use {@link ScriptRuntime#EQ(Object, Object)}, {@link ScriptRuntime#LT(Object, Object)} 6.24 + * etc. methods instead. Additionally, {@code ScriptRuntime} methods are used for strict (in)equality comparison 6.25 + * of a boolean to anything that isn't a boolean.) This method handles the special case where one argument 6.26 + * is an object and another is a primitive. Naively, these could also be delegated to {@code ScriptRuntime} methods 6.27 + * by boxing the primitive. However, in all such cases the comparison is performed on numeric values, so it is 6.28 + * possible to strength-reduce the operation by taking the number value of the object argument instead and 6.29 + * comparing that to the primitive value ("primitive" will always be int, long, double, or boolean, and booleans 6.30 + * compare as ints in these cases, so they're essentially numbers too). This method will emit code for loading 6.31 + * arguments for such strength-reduced comparison. When both arguments are primitives, it just delegates to 6.32 + * {@link #loadBinaryOperands(BinaryNode)}. 6.33 + * 6.34 + * @param cmp the comparison operation for which the operands need to be loaded on stack. 6.35 + * @return the current method emitter. 6.36 + */ 6.37 + MethodEmitter loadComparisonOperands(final BinaryNode cmp) { 6.38 + final Expression lhs = cmp.lhs(); 6.39 + final Expression rhs = cmp.rhs(); 6.40 + final Type lhsType = lhs.getType(); 6.41 + final Type rhsType = rhs.getType(); 6.42 + 6.43 + // Only used when not both are object, for that we have ScriptRuntime.LT etc. 6.44 + assert !(lhsType.isObject() && rhsType.isObject()); 6.45 + 6.46 + if (lhsType.isObject() || rhsType.isObject()) { 6.47 + // We can reorder CONVERT LEFT and LOAD RIGHT only if either the left is a primitive, or the right 6.48 + // is a local. This is more strict than loadBinaryNode reorder criteria, as it can allow JS primitive 6.49 + // types too (notably: String is a JS primitive, but not a JVM primitive). We disallow String otherwise 6.50 + // we would prematurely convert it to number when comparing to an optimistic expression, e.g. in 6.51 + // "Hello" === String("Hello") the RHS starts out as an optimistic-int function call. If we allowed 6.52 + // reordering, we'd end up with ToNumber("Hello") === {I%}String("Hello") that is obviously incorrect. 6.53 + final boolean canReorder = lhsType.isPrimitive() || rhs.isLocal(); 6.54 + // If reordering is allowed, and we're using a relational operator (that is, <, <=, >, >=) and not an 6.55 + // (in)equality operator, then we encourage combining of LOAD and CONVERT into a single operation. 6.56 + // This is because relational operators' semantics prescribes vanilla ToNumber() conversion, while 6.57 + // (in)equality operators need the specialized JSType.toNumberFor[Strict]Equals. E.g. in the code snippet 6.58 + // "i < obj.size" (where i is primitive and obj.size is statically an object), ".size" will thus be allowed 6.59 + // to compile as: 6.60 + // invokedynamic dyn:getProp|getElem|getMethod:size(Object;)D 6.61 + // instead of the more costly: 6.62 + // invokedynamic dyn:getProp|getElem|getMethod:size(Object;)Object 6.63 + // invokestatic JSType.toNumber(Object)D 6.64 + // Note also that even if this is allowed, we're only using it on operands that are non-optimistic, as 6.65 + // otherwise the logic for determining effective optimistic-ness would turn an optimistic double return 6.66 + // into a freely coercible one, which would be wrong. 6.67 + final boolean canCombineLoadAndConvert = canReorder && cmp.isRelational(); 6.68 + 6.69 + // LOAD LEFT 6.70 + loadExpression(lhs, canCombineLoadAndConvert && !lhs.isOptimistic() ? TypeBounds.NUMBER : TypeBounds.UNBOUNDED); 6.71 + 6.72 + final Type lhsLoadedType = method.peekType(); 6.73 + final TokenType tt = cmp.tokenType(); 6.74 + if (canReorder) { 6.75 + // Can reorder CONVERT LEFT and LOAD RIGHT 6.76 + emitObjectToNumberComparisonConversion(method, tt); 6.77 + loadExpression(rhs, canCombineLoadAndConvert && !rhs.isOptimistic() ? TypeBounds.NUMBER : TypeBounds.UNBOUNDED); 6.78 + } else { 6.79 + // Can't reorder CONVERT LEFT and LOAD RIGHT 6.80 + loadExpression(rhs, TypeBounds.UNBOUNDED); 6.81 + if (lhsLoadedType != Type.NUMBER) { 6.82 + method.swap(); 6.83 + emitObjectToNumberComparisonConversion(method, tt); 6.84 + method.swap(); 6.85 + } 6.86 + } 6.87 + 6.88 + // CONVERT RIGHT 6.89 + emitObjectToNumberComparisonConversion(method, tt); 6.90 + return method; 6.91 + } 6.92 + // For primitive operands, just don't do anything special. 6.93 + return loadBinaryOperands(cmp); 6.94 + } 6.95 + 6.96 + private static void emitObjectToNumberComparisonConversion(final MethodEmitter method, final TokenType tt) { 6.97 + switch(tt) { 6.98 + case EQ: 6.99 + case NE: 6.100 + if (method.peekType().isObject()) { 6.101 + TO_NUMBER_FOR_EQ.invoke(method); 6.102 + return; 6.103 + } 6.104 + break; 6.105 + case EQ_STRICT: 6.106 + case NE_STRICT: 6.107 + if (method.peekType().isObject()) { 6.108 + TO_NUMBER_FOR_STRICT_EQ.invoke(method); 6.109 + return; 6.110 + } 6.111 + break; 6.112 + default: 6.113 + break; 6.114 + } 6.115 + method.convert(Type.NUMBER); 6.116 + } 6.117 + 6.118 private static final Type undefinedToNumber(final Type type) { 6.119 return type == Type.UNDEFINED ? Type.NUMBER : type; 6.120 } 6.121 @@ -628,6 +732,7 @@ 6.122 6.123 static final TypeBounds UNBOUNDED = new TypeBounds(Type.UNKNOWN, Type.OBJECT); 6.124 static final TypeBounds INT = exact(Type.INT); 6.125 + static final TypeBounds NUMBER = exact(Type.NUMBER); 6.126 static final TypeBounds OBJECT = exact(Type.OBJECT); 6.127 static final TypeBounds BOOLEAN = exact(Type.BOOLEAN); 6.128 6.129 @@ -731,7 +836,7 @@ 6.130 */ 6.131 final CodeGenerator codegen = this; 6.132 6.133 - final Node currentDiscard = codegen.lc.getCurrentDiscard(); 6.134 + final boolean isCurrentDiscard = codegen.lc.isCurrentDiscard(expr); 6.135 expr.accept(new NodeOperatorVisitor<LexicalContext>(new LexicalContext()) { 6.136 @Override 6.137 public boolean enterIdentNode(final IdentNode identNode) { 6.138 @@ -1087,7 +1192,7 @@ 6.139 6.140 @Override 6.141 public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinExpr) { 6.142 - loadExpression(joinExpr.getExpression(), resultBounds); 6.143 + loadMaybeDiscard(joinExpr, joinExpr.getExpression(), resultBounds); 6.144 return false; 6.145 } 6.146 6.147 @@ -1104,7 +1209,7 @@ 6.148 throw new AssertionError(otherNode.getClass().getName()); 6.149 } 6.150 }); 6.151 - if(currentDiscard != expr) { 6.152 + if(!isCurrentDiscard) { 6.153 coerceStackTop(resultBounds); 6.154 } 6.155 return method; 6.156 @@ -2756,25 +2861,18 @@ 6.157 newRuntimeNode = runtimeNode; 6.158 } 6.159 6.160 - new OptimisticOperation(newRuntimeNode, TypeBounds.UNBOUNDED) { 6.161 - @Override 6.162 - void loadStack() { 6.163 - for (final Expression arg : args) { 6.164 - loadExpression(arg, TypeBounds.OBJECT); 6.165 - } 6.166 - } 6.167 - @Override 6.168 - void consumeStack() { 6.169 - method.invokestatic( 6.170 - CompilerConstants.className(ScriptRuntime.class), 6.171 - newRuntimeNode.getRequest().toString(), 6.172 - new FunctionSignature( 6.173 - false, 6.174 - false, 6.175 - newRuntimeNode.getType(), 6.176 - args.size()).toString()); 6.177 - } 6.178 - }.emit(); 6.179 + for (final Expression arg : args) { 6.180 + loadExpression(arg, TypeBounds.OBJECT); 6.181 + } 6.182 + 6.183 + method.invokestatic( 6.184 + CompilerConstants.className(ScriptRuntime.class), 6.185 + newRuntimeNode.getRequest().toString(), 6.186 + new FunctionSignature( 6.187 + false, 6.188 + false, 6.189 + newRuntimeNode.getType(), 6.190 + args.size()).toString()); 6.191 6.192 method.convert(newRuntimeNode.getType()); 6.193 } 6.194 @@ -3550,7 +3648,7 @@ 6.195 // TODO: move checks for discarding to actual expression load code (e.g. as we do with void). That way we might 6.196 // be able to eliminate even more checks. 6.197 if(expr instanceof PrimitiveLiteralNode | isLocalVariable(expr)) { 6.198 - assert lc.getCurrentDiscard() != expr; 6.199 + assert !lc.isCurrentDiscard(expr); 6.200 // Don't bother evaluating expressions without side effects. Typical usage is "void 0" for reliably generating 6.201 // undefined. 6.202 return; 6.203 @@ -3558,11 +3656,37 @@ 6.204 6.205 lc.pushDiscard(expr); 6.206 loadExpression(expr, TypeBounds.UNBOUNDED); 6.207 - if (lc.getCurrentDiscard() == expr) { 6.208 + if (lc.popDiscardIfCurrent(expr)) { 6.209 assert !expr.isAssignment(); 6.210 // NOTE: if we had a way to load with type void, we could avoid popping 6.211 method.pop(); 6.212 - lc.popDiscard(); 6.213 + } 6.214 + } 6.215 + 6.216 + /** 6.217 + * Loads the expression with the specified type bounds, but if the parent expression is the current discard, 6.218 + * then instead loads and discards the expression. 6.219 + * @param parent the parent expression that's tested for being the current discard 6.220 + * @param expr the expression that's either normally loaded or discard-loaded 6.221 + * @param resultBounds result bounds for when loading the expression normally 6.222 + */ 6.223 + private void loadMaybeDiscard(final Expression parent, final Expression expr, final TypeBounds resultBounds) { 6.224 + loadMaybeDiscard(lc.popDiscardIfCurrent(parent), expr, resultBounds); 6.225 + } 6.226 + 6.227 + /** 6.228 + * Loads the expression with the specified type bounds, or loads and discards the expression, depending on the 6.229 + * value of the discard flag. Useful as a helper for expressions with control flow where you often can't combine 6.230 + * testing for being the current discard and loading the subexpressions. 6.231 + * @param discard if true, the expression is loaded and discarded 6.232 + * @param expr the expression that's either normally loaded or discard-loaded 6.233 + * @param resultBounds result bounds for when loading the expression normally 6.234 + */ 6.235 + private void loadMaybeDiscard(final boolean discard, final Expression expr, final TypeBounds resultBounds) { 6.236 + if (discard) { 6.237 + loadAndDiscard(expr); 6.238 + } else { 6.239 + loadExpression(expr, resultBounds); 6.240 } 6.241 } 6.242 6.243 @@ -3619,9 +3743,7 @@ 6.244 6.245 public void loadVOID(final UnaryNode unaryNode, final TypeBounds resultBounds) { 6.246 loadAndDiscard(unaryNode.getExpression()); 6.247 - if(lc.getCurrentDiscard() == unaryNode) { 6.248 - lc.popDiscard(); 6.249 - } else { 6.250 + if (!lc.popDiscardIfCurrent(unaryNode)) { 6.251 method.loadUndefined(resultBounds.widest); 6.252 } 6.253 } 6.254 @@ -3654,16 +3776,23 @@ 6.255 private void loadAND_OR(final BinaryNode binaryNode, final TypeBounds resultBounds, final boolean isAnd) { 6.256 final Type narrowestOperandType = Type.widestReturnType(binaryNode.lhs().getType(), binaryNode.rhs().getType()); 6.257 6.258 + final boolean isCurrentDiscard = lc.popDiscardIfCurrent(binaryNode); 6.259 + 6.260 final Label skip = new Label("skip"); 6.261 if(narrowestOperandType == Type.BOOLEAN) { 6.262 // optimize all-boolean logical expressions 6.263 final Label onTrue = new Label("andor_true"); 6.264 emitBranch(binaryNode, onTrue, true); 6.265 - method.load(false); 6.266 - method._goto(skip); 6.267 - method.label(onTrue); 6.268 - method.load(true); 6.269 - method.label(skip); 6.270 + if (isCurrentDiscard) { 6.271 + method.label(onTrue); 6.272 + method.pop(); 6.273 + } else { 6.274 + method.load(false); 6.275 + method._goto(skip); 6.276 + method.label(onTrue); 6.277 + method.load(true); 6.278 + method.label(skip); 6.279 + } 6.280 return; 6.281 } 6.282 6.283 @@ -3672,7 +3801,11 @@ 6.284 final boolean lhsConvert = LocalVariableConversion.hasLiveConversion(lhs); 6.285 final Label evalRhs = lhsConvert ? new Label("eval_rhs") : null; 6.286 6.287 - loadExpression(lhs, outBounds).dup().convert(Type.BOOLEAN); 6.288 + loadExpression(lhs, outBounds); 6.289 + if (!isCurrentDiscard) { 6.290 + method.dup(); 6.291 + } 6.292 + method.convert(Type.BOOLEAN); 6.293 if (isAnd) { 6.294 if(lhsConvert) { 6.295 method.ifne(evalRhs); 6.296 @@ -3691,9 +3824,11 @@ 6.297 method.label(evalRhs); 6.298 } 6.299 6.300 - method.pop(); 6.301 + if (!isCurrentDiscard) { 6.302 + method.pop(); 6.303 + } 6.304 final JoinPredecessorExpression rhs = (JoinPredecessorExpression)binaryNode.rhs(); 6.305 - loadExpression(rhs, outBounds); 6.306 + loadMaybeDiscard(isCurrentDiscard, rhs, outBounds); 6.307 method.beforeJoinPoint(rhs); 6.308 method.label(skip); 6.309 } 6.310 @@ -3715,9 +3850,8 @@ 6.311 // Detect dead assignments 6.312 if(lhs instanceof IdentNode) { 6.313 final Symbol symbol = ((IdentNode)lhs).getSymbol(); 6.314 - if(!symbol.isScope() && !symbol.hasSlotFor(rhsType) && lc.getCurrentDiscard() == binaryNode) { 6.315 + if(!symbol.isScope() && !symbol.hasSlotFor(rhsType) && lc.popDiscardIfCurrent(binaryNode)) { 6.316 loadAndDiscard(rhs); 6.317 - lc.popDiscard(); 6.318 method.markDeadLocalVariable(symbol); 6.319 return; 6.320 } 6.321 @@ -3971,11 +4105,11 @@ 6.322 6.323 private void loadCOMMARIGHT(final BinaryNode binaryNode, final TypeBounds resultBounds) { 6.324 loadAndDiscard(binaryNode.lhs()); 6.325 - loadExpression(binaryNode.rhs(), resultBounds); 6.326 + loadMaybeDiscard(binaryNode, binaryNode.rhs(), resultBounds); 6.327 } 6.328 6.329 private void loadCOMMALEFT(final BinaryNode binaryNode, final TypeBounds resultBounds) { 6.330 - loadExpression(binaryNode.lhs(), resultBounds); 6.331 + loadMaybeDiscard(binaryNode, binaryNode.lhs(), resultBounds); 6.332 loadAndDiscard(binaryNode.rhs()); 6.333 } 6.334 6.335 @@ -3989,8 +4123,7 @@ 6.336 } 6.337 6.338 private void loadCmp(final BinaryNode binaryNode, final Condition cond) { 6.339 - assert comparisonOperandsArePrimitive(binaryNode) : binaryNode; 6.340 - loadBinaryOperands(binaryNode); 6.341 + loadComparisonOperands(binaryNode); 6.342 6.343 final Label trueLabel = new Label("trueLabel"); 6.344 final Label afterLabel = new Label("skip"); 6.345 @@ -4004,11 +4137,6 @@ 6.346 method.label(afterLabel); 6.347 } 6.348 6.349 - private static boolean comparisonOperandsArePrimitive(final BinaryNode binaryNode) { 6.350 - final Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType()); 6.351 - return widest.isNumeric() || widest.isBoolean(); 6.352 - } 6.353 - 6.354 private void loadMOD(final BinaryNode binaryNode, final TypeBounds resultBounds) { 6.355 new BinaryArith() { 6.356 @Override 6.357 @@ -4081,13 +4209,14 @@ 6.358 6.359 emitBranch(test, falseLabel, false); 6.360 6.361 - loadExpression(trueExpr.getExpression(), outBounds); 6.362 - assert Type.generic(method.peekType()) == outBounds.narrowest; 6.363 + final boolean isCurrentDiscard = lc.popDiscardIfCurrent(ternaryNode); 6.364 + loadMaybeDiscard(isCurrentDiscard, trueExpr.getExpression(), outBounds); 6.365 + assert isCurrentDiscard || Type.generic(method.peekType()) == outBounds.narrowest; 6.366 method.beforeJoinPoint(trueExpr); 6.367 method._goto(exitLabel); 6.368 method.label(falseLabel); 6.369 - loadExpression(falseExpr.getExpression(), outBounds); 6.370 - assert Type.generic(method.peekType()) == outBounds.narrowest; 6.371 + loadMaybeDiscard(isCurrentDiscard, falseExpr.getExpression(), outBounds); 6.372 + assert isCurrentDiscard || Type.generic(method.peekType()) == outBounds.narrowest; 6.373 method.beforeJoinPoint(falseExpr); 6.374 method.label(exitLabel); 6.375 } 6.376 @@ -4273,9 +4402,8 @@ 6.377 6.378 // store the result that "lives on" after the op, e.g. "i" in i++ postfix. 6.379 protected void storeNonDiscard() { 6.380 - if (lc.getCurrentDiscard() == assignNode) { 6.381 + if (lc.popDiscardIfCurrent(assignNode)) { 6.382 assert assignNode.isAssignment(); 6.383 - lc.popDiscard(); 6.384 return; 6.385 } 6.386
7.1 --- a/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java Wed Mar 11 14:11:06 2015 -0700 7.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java Thu Mar 12 13:45:00 2015 -0700 7.3 @@ -34,6 +34,7 @@ 7.4 import jdk.nashorn.internal.IntDeque; 7.5 import jdk.nashorn.internal.codegen.types.Type; 7.6 import jdk.nashorn.internal.ir.Block; 7.7 +import jdk.nashorn.internal.ir.Expression; 7.8 import jdk.nashorn.internal.ir.FunctionNode; 7.9 import jdk.nashorn.internal.ir.LexicalContext; 7.10 import jdk.nashorn.internal.ir.LexicalContextNode; 7.11 @@ -59,9 +60,11 @@ 7.12 /** Method emitter stack - every time we start a sub method (e.g. a split) we push one */ 7.13 private final Deque<MethodEmitter> methodEmitters = new ArrayDeque<>(); 7.14 7.15 - /** The discard stack - whenever we enter a discard node we keep track of its return value status - 7.16 - * i.e. should we keep it or throw it away */ 7.17 - private final Deque<Node> discard = new ArrayDeque<>(); 7.18 + /** The discard stack - whenever we evaluate an expression that will be discarded, we push it on this stack. Various 7.19 + * implementations of expression code emitter can choose to emit code that'll discard the expression themselves, or 7.20 + * ignore it in which case CodeGenerator.loadAndDiscard() will explicitly emit a pop instruction. */ 7.21 + private final Deque<Expression> discard = new ArrayDeque<>(); 7.22 + 7.23 7.24 private final Deque<Map<String, Collection<Label>>> unwarrantedOptimismHandlers = new ArrayDeque<>(); 7.25 private final Deque<StringBuilder> slotTypesDescriptors = new ArrayDeque<>(); 7.26 @@ -270,16 +273,20 @@ 7.27 } 7.28 } 7.29 7.30 - void pushDiscard(final Node node) { 7.31 - discard.push(node); 7.32 + void pushDiscard(final Expression expr) { 7.33 + discard.push(expr); 7.34 } 7.35 7.36 - Node popDiscard() { 7.37 - return discard.pop(); 7.38 + boolean popDiscardIfCurrent(final Expression expr) { 7.39 + if (isCurrentDiscard(expr)) { 7.40 + discard.pop(); 7.41 + return true; 7.42 + } 7.43 + return false; 7.44 } 7.45 7.46 - Node getCurrentDiscard() { 7.47 - return discard.peek(); 7.48 + boolean isCurrentDiscard(final Expression expr) { 7.49 + return discard.peek() == expr; 7.50 } 7.51 7.52 int quickSlot(final Type type) {
8.1 --- a/src/jdk/nashorn/internal/codegen/FindScopeDepths.java Wed Mar 11 14:11:06 2015 -0700 8.2 +++ b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java Thu Mar 12 13:45:00 2015 -0700 8.3 @@ -32,7 +32,6 @@ 8.4 import java.util.Iterator; 8.5 import java.util.Map; 8.6 import java.util.Set; 8.7 -import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor; 8.8 import jdk.nashorn.internal.ir.Block; 8.9 import jdk.nashorn.internal.ir.FunctionNode; 8.10 import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 8.11 @@ -208,7 +207,7 @@ 8.12 final RecompilableScriptFunctionData data = new RecompilableScriptFunctionData( 8.13 newFunctionNode, 8.14 compiler.getCodeInstaller(), 8.15 - new AllocatorDescriptor(newFunctionNode.getThisProperties()), 8.16 + ObjectClassGenerator.createAllocationStrategy(newFunctionNode.getThisProperties()), 8.17 nestedFunctions, 8.18 externalSymbolDepths.get(fnId), 8.19 internalSymbols.get(fnId),
9.1 --- a/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Wed Mar 11 14:11:06 2015 -0700 9.2 +++ b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Thu Mar 12 13:45:00 2015 -0700 9.3 @@ -206,7 +206,6 @@ 9.4 // continuations (since RewriteException's byteCodeSlots carries an array and not a name-value map). 9.5 9.6 symbolIsConverted(symbol, branchLvarType, targetType); 9.7 - //symbolIsUsed(symbol, branchLvarType); 9.8 return new LocalVariableConversion(symbol, branchLvarType.type, targetType.type, next); 9.9 } 9.10 9.11 @@ -229,7 +228,7 @@ 9.12 for(final Symbol symbol: commonSymbols) { 9.13 final LvarType type1 = types1.get(symbol); 9.14 final LvarType type2 = types2.get(symbol); 9.15 - final LvarType widest = widestLvarType(type1, type2); 9.16 + final LvarType widest = widestLvarType(type1, type2); 9.17 if(widest != type1 && matches1) { 9.18 matches1 = false; 9.19 if(!matches2) { 9.20 @@ -242,7 +241,7 @@ 9.21 union = cloneMap(types2); 9.22 } 9.23 } 9.24 - if(!(matches1 || matches2) && union != null) { //remove overly enthusiastic "union can be null" warning 9.25 + if(!(matches1 || matches2)) { 9.26 assert union != null; 9.27 union.put(symbol, widest); 9.28 } 9.29 @@ -711,8 +710,13 @@ 9.30 9.31 @Override 9.32 public boolean enterIfNode(final IfNode ifNode) { 9.33 + processIfNode(ifNode); 9.34 + return false; 9.35 + } 9.36 + 9.37 + private void processIfNode(final IfNode ifNode) { 9.38 if(!reachable) { 9.39 - return false; 9.40 + return; 9.41 } 9.42 9.43 final Expression test = ifNode.getTest(); 9.44 @@ -721,48 +725,48 @@ 9.45 9.46 visitExpressionOnEmptyStack(test); 9.47 9.48 - final Map<Symbol, LvarType> afterTestLvarTypes = localVariableTypes; 9.49 - if(!isAlwaysFalse(test)) { 9.50 + final Map<Symbol, LvarType> passLvarTypes; 9.51 + final boolean reachableFromPass; 9.52 + final boolean isTestAlwaysTrue = isAlwaysTrue(test); 9.53 + if(isAlwaysFalse(test)) { 9.54 + passLvarTypes = null; 9.55 + reachableFromPass = false; 9.56 + } else { 9.57 + final Map<Symbol, LvarType> afterTestLvarTypes = localVariableTypes; 9.58 pass.accept(this); 9.59 assertTypeStackIsEmpty(); 9.60 + if (isTestAlwaysTrue) { 9.61 + return; 9.62 + } 9.63 + passLvarTypes = localVariableTypes; 9.64 + reachableFromPass = reachable; 9.65 + localVariableTypes = afterTestLvarTypes; 9.66 + reachable = true; 9.67 } 9.68 - final Map<Symbol, LvarType> passLvarTypes = localVariableTypes; 9.69 - final boolean reachableFromPass = reachable; 9.70 9.71 - reachable = true; 9.72 - localVariableTypes = afterTestLvarTypes; 9.73 - if(!isAlwaysTrue(test) && fail != null) { 9.74 + // If we get here, then we need to consider the case where pass block is not executed 9.75 + assert !isTestAlwaysTrue; 9.76 + 9.77 + if (fail != null) { 9.78 fail.accept(this); 9.79 assertTypeStackIsEmpty(); 9.80 - final boolean reachableFromFail = reachable; 9.81 - reachable |= reachableFromPass; 9.82 - if(!reachable) { 9.83 - return false; 9.84 - } 9.85 - 9.86 - if(reachableFromFail) { 9.87 - if(reachableFromPass) { 9.88 - final Map<Symbol, LvarType> failLvarTypes = localVariableTypes; 9.89 - localVariableTypes = getUnionTypes(passLvarTypes, failLvarTypes); 9.90 - setConversion(pass, passLvarTypes, localVariableTypes); 9.91 - setConversion(fail, failLvarTypes, localVariableTypes); 9.92 - } 9.93 - return false; 9.94 - } 9.95 } 9.96 9.97 - if(reachableFromPass) { 9.98 - localVariableTypes = getUnionTypes(afterTestLvarTypes, passLvarTypes); 9.99 - // IfNode itself is associated with conversions that might need to be performed after the test if there's no 9.100 - // else branch. E.g. 9.101 - // if(x = 1, cond) { x = 1.0 } must widen "x = 1" to a double. 9.102 - setConversion(pass, passLvarTypes, localVariableTypes); 9.103 - setConversion(ifNode, afterTestLvarTypes, localVariableTypes); 9.104 - } else { 9.105 - localVariableTypes = afterTestLvarTypes; 9.106 + if(reachable) { 9.107 + if(reachableFromPass) { 9.108 + final Map<Symbol, LvarType> failLvarTypes = localVariableTypes; 9.109 + localVariableTypes = getUnionTypes(passLvarTypes, failLvarTypes); 9.110 + setConversion(pass, passLvarTypes, localVariableTypes); 9.111 + // IfNode itself is associated with conversions that might need to be performed after the test if 9.112 + // there's no else branch. E.g. 9.113 + // if(x = 1, cond) { x = 1.0 } must widen "x = 1" to a double. 9.114 + setConversion(fail != null ? fail : ifNode, failLvarTypes, localVariableTypes); 9.115 + } 9.116 + } else if (reachableFromPass) { 9.117 + assert passLvarTypes != null; 9.118 + localVariableTypes = passLvarTypes; 9.119 + reachable = true; 9.120 } 9.121 - 9.122 - return false; 9.123 } 9.124 9.125 @Override 9.126 @@ -1359,8 +1363,6 @@ 9.127 final Expression lhs = binaryNode.lhs(); 9.128 final Expression rhs = binaryNode.rhs(); 9.129 9.130 - Type cmpWidest = Type.widest(lhs.getType(), rhs.getType()); 9.131 - boolean newRuntimeNode = false, finalized = false; 9.132 final TokenType tt = binaryNode.tokenType(); 9.133 switch (tt) { 9.134 case EQ_STRICT: 9.135 @@ -1373,14 +1375,12 @@ 9.136 } 9.137 // Specialize comparison of boolean with non-boolean 9.138 if (lhs.getType().isBoolean() != rhs.getType().isBoolean()) { 9.139 - newRuntimeNode = true; 9.140 - cmpWidest = Type.OBJECT; 9.141 - finalized = true; 9.142 + return new RuntimeNode(binaryNode); 9.143 } 9.144 // fallthrough 9.145 default: 9.146 - if (newRuntimeNode || cmpWidest.isObject()) { 9.147 - return new RuntimeNode(binaryNode).setIsFinal(finalized); 9.148 + if (lhs.getType().isObject() && rhs.getType().isObject()) { 9.149 + return new RuntimeNode(binaryNode); 9.150 } 9.151 } 9.152 } else if(binaryNode.isOptimisticUndecidedType()) {
10.1 --- a/src/jdk/nashorn/internal/codegen/MapCreator.java Wed Mar 11 14:11:06 2015 -0700 10.2 +++ b/src/jdk/nashorn/internal/codegen/MapCreator.java Thu Mar 12 13:45:00 2015 -0700 10.3 @@ -100,15 +100,16 @@ 10.4 for (final MapTuple<T> tuple : tuples) { 10.5 final String key = tuple.key; 10.6 final Symbol symbol = tuple.symbol; 10.7 + final Class<?> initialType = tuple.getValueType(); 10.8 10.9 - //TODO initial type is object here no matter what. Is that right? 10.10 if (symbol != null && !isValidArrayIndex(getArrayIndex(key))) { 10.11 final int flags = getPropertyFlags(symbol, hasArguments, false); 10.12 properties.add( 10.13 new SpillProperty( 10.14 key, 10.15 flags, 10.16 - spillIndex++)); 10.17 + spillIndex++, 10.18 + initialType)); 10.19 } 10.20 } 10.21
11.1 --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Mar 11 14:11:06 2015 -0700 11.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java Thu Mar 12 13:45:00 2015 -0700 11.3 @@ -94,7 +94,6 @@ 11.4 import jdk.nashorn.internal.ir.JoinPredecessor; 11.5 import jdk.nashorn.internal.ir.LiteralNode; 11.6 import jdk.nashorn.internal.ir.LocalVariableConversion; 11.7 -import jdk.nashorn.internal.ir.RuntimeNode; 11.8 import jdk.nashorn.internal.ir.Symbol; 11.9 import jdk.nashorn.internal.ir.TryNode; 11.10 import jdk.nashorn.internal.objects.Global; 11.11 @@ -175,9 +174,6 @@ 11.12 /** Bootstrap for normal indy:s */ 11.13 private static final Handle LINKERBOOTSTRAP = new Handle(H_INVOKESTATIC, Bootstrap.BOOTSTRAP.className(), Bootstrap.BOOTSTRAP.name(), Bootstrap.BOOTSTRAP.descriptor()); 11.14 11.15 - /** Bootstrap for runtime node indy:s */ 11.16 - private static final Handle RUNTIMEBOOTSTRAP = new Handle(H_INVOKESTATIC, RuntimeCallSite.BOOTSTRAP.className(), RuntimeCallSite.BOOTSTRAP.name(), RuntimeCallSite.BOOTSTRAP.descriptor()); 11.17 - 11.18 /** Bootstrap for array populators */ 11.19 private static final Handle POPULATE_ARRAY_BOOTSTRAP = new Handle(H_INVOKESTATIC, RewriteException.BOOTSTRAP.className(), RewriteException.BOOTSTRAP.name(), RewriteException.BOOTSTRAP.descriptor()); 11.20 11.21 @@ -2189,25 +2185,6 @@ 11.22 } 11.23 11.24 /** 11.25 - * Generate a dynamic call for a runtime node 11.26 - * 11.27 - * @param name tag for the invoke dynamic for this runtime node 11.28 - * @param returnType return type 11.29 - * @param request RuntimeNode request 11.30 - * 11.31 - * @return the method emitter 11.32 - */ 11.33 - MethodEmitter dynamicRuntimeCall(final String name, final Type returnType, final RuntimeNode.Request request) { 11.34 - debug("dynamic_runtime_call", name, "args=", request.getArity(), "returnType=", returnType); 11.35 - final String signature = getDynamicSignature(returnType, request.getArity()); 11.36 - debug(" signature", signature); 11.37 - method.visitInvokeDynamicInsn(name, signature, RUNTIMEBOOTSTRAP); 11.38 - pushType(returnType); 11.39 - 11.40 - return this; 11.41 - } 11.42 - 11.43 - /** 11.44 * Generate dynamic getter. Pop scope from stack. Push result 11.45 * 11.46 * @param valueType type of the value to set
12.1 --- a/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Wed Mar 11 14:11:06 2015 -0700 12.2 +++ b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Thu Mar 12 13:45:00 2015 -0700 12.3 @@ -56,6 +56,7 @@ 12.4 import jdk.nashorn.internal.codegen.ClassEmitter.Flag; 12.5 import jdk.nashorn.internal.codegen.types.Type; 12.6 import jdk.nashorn.internal.runtime.AccessorProperty; 12.7 +import jdk.nashorn.internal.runtime.AllocationStrategy; 12.8 import jdk.nashorn.internal.runtime.Context; 12.9 import jdk.nashorn.internal.runtime.FunctionScope; 12.10 import jdk.nashorn.internal.runtime.JSType; 12.11 @@ -826,44 +827,13 @@ 12.12 } 12.13 12.14 /** 12.15 - * Describes the allocator class name and property map for a constructor function with the specified 12.16 + * Creates the allocator class name and property map for a constructor function with the specified 12.17 * number of "this" properties that it initializes. 12.18 - * 12.19 + * @param thisProperties number of properties assigned to "this" 12.20 + * @return the allocation strategy 12.21 */ 12.22 - public static class AllocatorDescriptor { 12.23 - private final String allocatorClassName; 12.24 - private final PropertyMap allocatorMap; 12.25 - 12.26 - /** 12.27 - * Creates a new allocator descriptor 12.28 - * @param thisProperties the number of "this" properties that the function initializes 12.29 - */ 12.30 - public AllocatorDescriptor(final int thisProperties) { 12.31 - final int paddedFieldCount = getPaddedFieldCount(thisProperties); 12.32 - this.allocatorClassName = Compiler.binaryName(getClassName(paddedFieldCount)); 12.33 - this.allocatorMap = PropertyMap.newMap(null, allocatorClassName, 0, paddedFieldCount, 0); 12.34 - } 12.35 - 12.36 - /** 12.37 - * Returns the name of the class that the function allocates 12.38 - * @return the name of the class that the function allocates 12.39 - */ 12.40 - public String getAllocatorClassName() { 12.41 - return allocatorClassName; 12.42 - } 12.43 - 12.44 - /** 12.45 - * Returns the allocator map for the function. 12.46 - * @return the allocator map for the function. 12.47 - */ 12.48 - public PropertyMap getAllocatorMap() { 12.49 - return allocatorMap; 12.50 - } 12.51 - 12.52 - @Override 12.53 - public String toString() { 12.54 - return "AllocatorDescriptor[allocatorClassName=" + allocatorClassName + ", allocatorMap.size=" + 12.55 - allocatorMap.size() + "]"; 12.56 - } 12.57 + static AllocationStrategy createAllocationStrategy(final int thisProperties) { 12.58 + final int paddedFieldCount = getPaddedFieldCount(thisProperties); 12.59 + return new AllocationStrategy(paddedFieldCount); 12.60 } 12.61 }
13.1 --- a/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java Wed Mar 11 14:11:06 2015 -0700 13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 13.3 @@ -1,683 +0,0 @@ 13.4 -/* 13.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 13.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 13.7 - * 13.8 - * This code is free software; you can redistribute it and/or modify it 13.9 - * under the terms of the GNU General Public License version 2 only, as 13.10 - * published by the Free Software Foundation. Oracle designates this 13.11 - * particular file as subject to the "Classpath" exception as provided 13.12 - * by Oracle in the LICENSE file that accompanied this code. 13.13 - * 13.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 13.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13.17 - * version 2 for more details (a copy is included in the LICENSE file that 13.18 - * accompanied this code). 13.19 - * 13.20 - * You should have received a copy of the GNU General Public License version 13.21 - * 2 along with this work; if not, write to the Free Software Foundation, 13.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 13.23 - * 13.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 13.25 - * or visit www.oracle.com if you need additional information or have any 13.26 - * questions. 13.27 - */ 13.28 - 13.29 -package jdk.nashorn.internal.codegen; 13.30 - 13.31 -import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; 13.32 -import static jdk.nashorn.internal.codegen.types.Type.BOOLEAN; 13.33 -import static jdk.nashorn.internal.codegen.types.Type.INT; 13.34 -import static jdk.nashorn.internal.lookup.Lookup.MH; 13.35 - 13.36 -import java.lang.invoke.CallSite; 13.37 -import java.lang.invoke.MethodHandle; 13.38 -import java.lang.invoke.MethodHandles; 13.39 -import java.lang.invoke.MethodType; 13.40 -import java.lang.invoke.MutableCallSite; 13.41 -import java.util.HashMap; 13.42 -import java.util.Map; 13.43 -import jdk.nashorn.internal.codegen.CompilerConstants.Call; 13.44 -import jdk.nashorn.internal.codegen.types.Type; 13.45 -import jdk.nashorn.internal.ir.RuntimeNode; 13.46 -import jdk.nashorn.internal.ir.RuntimeNode.Request; 13.47 -import jdk.nashorn.internal.lookup.Lookup; 13.48 -import jdk.nashorn.internal.runtime.ScriptRuntime; 13.49 -import jdk.nashorn.internal.runtime.linker.Bootstrap; 13.50 - 13.51 -/** 13.52 - * Optimistic call site that assumes its Object arguments to be of a boxed type. 13.53 - * Gradually reverts to wider boxed types if the assumption for the RuntimeNode 13.54 - * is proven wrong. Finally reverts to the generic ScriptRuntime method. 13.55 - * 13.56 - * This is used from the CodeGenerator when we have a runtime node, but 1 or more 13.57 - * primitive arguments. This class generated appropriate specializations, for example 13.58 - * {@code Object a === int b} is a good idea to specialize to {@code ((Integer)a).intValue() == b} 13.59 - * surrounded by catch blocks that will try less narrow specializations 13.60 - */ 13.61 -public final class RuntimeCallSite extends MutableCallSite { 13.62 - static final Call BOOTSTRAP = staticCallNoLookup(Bootstrap.class, "runtimeBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class); 13.63 - 13.64 - private static final MethodHandle NEXT = findOwnMH_V("next", MethodHandle.class, String.class); 13.65 - 13.66 - private final RuntimeNode.Request request; 13.67 - 13.68 - /** 13.69 - * A specialized runtime node, i.e. on where we know at least one more specific type than object 13.70 - */ 13.71 - static final class SpecializedRuntimeNode { 13.72 - private static final char REQUEST_SEPARATOR = ':'; 13.73 - 13.74 - private final RuntimeNode.Request request; 13.75 - 13.76 - private final Type[] parameterTypes; 13.77 - 13.78 - private final Type returnType; 13.79 - 13.80 - /** 13.81 - * Constructor. 13.82 - * 13.83 - * @param request runtime node request to specialize 13.84 - * @param parameterTypes parameter types of the call site 13.85 - * @param returnType return type of the call site 13.86 - */ 13.87 - SpecializedRuntimeNode(final RuntimeNode.Request request, final Type[] parameterTypes, final Type returnType) { 13.88 - this.request = request; 13.89 - this.parameterTypes = parameterTypes; 13.90 - this.returnType = returnType; 13.91 - } 13.92 - 13.93 - /** 13.94 - * The first type to try to use for this generated runtime node 13.95 - * 13.96 - * @return a type 13.97 - */ 13.98 - public Type firstTypeGuess() { 13.99 - Type widest = Type.UNKNOWN; 13.100 - for (final Type type : parameterTypes) { 13.101 - if (type.isObject()) { 13.102 - continue; 13.103 - } 13.104 - widest = Type.widest(type, widest); 13.105 - } 13.106 - widest = Type.widest(widest, firstTypeGuessForObject(request)); 13.107 - 13.108 - return widest; 13.109 - } 13.110 - 13.111 - private static Type firstTypeGuessForObject(final Request request) { 13.112 - switch (request) { 13.113 - case ADD: 13.114 - return INT; 13.115 - default: 13.116 - return BOOLEAN; 13.117 - } 13.118 - } 13.119 - 13.120 - Request getRequest() { 13.121 - return request; 13.122 - } 13.123 - 13.124 - Type[] getParameterTypes() { 13.125 - return parameterTypes; 13.126 - } 13.127 - 13.128 - Type getReturnType() { 13.129 - return returnType; 13.130 - } 13.131 - 13.132 - private static char descFor(final Type type) { 13.133 - if (type.isObject()) { 13.134 - return 'O'; 13.135 - } 13.136 - return type.getDescriptor().charAt(0); 13.137 - } 13.138 - 13.139 - @Override 13.140 - public boolean equals(final Object other) { 13.141 - if (other instanceof SpecializedRuntimeNode) { 13.142 - final SpecializedRuntimeNode otherNode = (SpecializedRuntimeNode)other; 13.143 - 13.144 - if (!otherNode.getReturnType().equals(getReturnType())) { 13.145 - return false; 13.146 - } 13.147 - 13.148 - if (getParameterTypes().length != otherNode.getParameterTypes().length) { 13.149 - return false; 13.150 - } 13.151 - 13.152 - for (int i = 0; i < getParameterTypes().length; i++) { 13.153 - if (!Type.areEquivalent(getParameterTypes()[i], otherNode.getParameterTypes()[i])) { 13.154 - return false; 13.155 - } 13.156 - } 13.157 - 13.158 - return otherNode.getRequest().equals(getRequest()); 13.159 - } 13.160 - 13.161 - return false; 13.162 - } 13.163 - 13.164 - @Override 13.165 - public int hashCode() { 13.166 - int hashCode = getRequest().toString().hashCode(); 13.167 - hashCode ^= getReturnType().hashCode(); 13.168 - for (final Type type : getParameterTypes()) { 13.169 - hashCode ^= type.hashCode(); 13.170 - } 13.171 - return hashCode; 13.172 - } 13.173 - 13.174 - @Override 13.175 - public String toString() { 13.176 - final StringBuilder sb = new StringBuilder(); 13.177 - sb.append(getRequest().toString()); 13.178 - sb.append(REQUEST_SEPARATOR); 13.179 - sb.append(descFor(getReturnType())); 13.180 - 13.181 - for (final Type type : getParameterTypes()) { 13.182 - sb.append(descFor(type)); 13.183 - } 13.184 - 13.185 - return sb.toString(); 13.186 - } 13.187 - 13.188 - String getName(final Type extraType) { 13.189 - return toString() + "_" + descFor(extraType); 13.190 - } 13.191 - 13.192 - String getInitialName() { 13.193 - return getName(firstTypeGuess()); 13.194 - } 13.195 - } 13.196 - 13.197 - 13.198 - /** 13.199 - * Constructor 13.200 - * 13.201 - * @param type method type for call site 13.202 - * @param name name of runtime call 13.203 - */ 13.204 - public RuntimeCallSite(final MethodType type, final String name) { 13.205 - super(type); 13.206 - this.request = Request.valueOf(name.substring(0, name.indexOf(SpecializedRuntimeNode.REQUEST_SEPARATOR))); 13.207 - setTarget(makeMethod(name)); 13.208 - } 13.209 - 13.210 - private String nextName(final String requestName) { 13.211 - if (requestName.equals(request.toString())) { 13.212 - return null; 13.213 - } 13.214 - 13.215 - final char[] c = requestName.toCharArray(); 13.216 - final int last = c.length - 1; 13.217 - 13.218 - if (c[last - 1] != '_') { 13.219 - return null; 13.220 - } 13.221 - 13.222 - switch (c[last]) { 13.223 - case 'Z': 13.224 - c[last] = 'I'; 13.225 - break; 13.226 - case 'I': 13.227 - c[last] = 'J'; 13.228 - break; 13.229 - case 'J': 13.230 - c[last] = 'D'; 13.231 - break; 13.232 - case 'D': 13.233 - default: 13.234 - return request.toString(); 13.235 - } 13.236 - 13.237 - return new String(c); 13.238 - } 13.239 - 13.240 - private boolean isSpecialized(final String requestName) { 13.241 - return nextName(requestName) != null; 13.242 - } 13.243 - 13.244 - private MethodHandle makeMethod(final String requestName) { 13.245 - MethodHandle mh; 13.246 - 13.247 - if (isSpecialized(requestName)) { 13.248 - final Class<?> boxedType; 13.249 - final Class<?> primitiveType; 13.250 - 13.251 - switch (requestName.charAt(requestName.length() - 1)) { 13.252 - case 'Z': 13.253 - boxedType = Boolean.class; 13.254 - primitiveType = int.class; 13.255 - break; 13.256 - case 'I': 13.257 - boxedType = Integer.class; 13.258 - primitiveType = int.class; 13.259 - break; 13.260 - case 'J': 13.261 - boxedType = Long.class; 13.262 - primitiveType = long.class; 13.263 - break; 13.264 - case 'D': 13.265 - boxedType = Number.class; 13.266 - primitiveType = double.class; 13.267 - break; 13.268 - default: 13.269 - throw new RuntimeException("should not reach here"); 13.270 - } 13.271 - 13.272 - final boolean isStrictCmp = (request == Request.EQ_STRICT || request == Request.NE_STRICT); 13.273 - 13.274 - if (isStrictCmp && 13.275 - (boxedType != Boolean.class && 13.276 - (type().parameterType(0) == boolean.class || 13.277 - type().parameterType(1) == boolean.class))) { 13.278 - // number and boolean are never strictly equal, e.g. 0 !== false 13.279 - mh = MH.dropArguments(MH.constant(boolean.class, request == Request.NE_STRICT), 0, type().parameterArray()); 13.280 - } else { 13.281 - mh = METHODS.get(request.nonStrictName() + primitiveType.getSimpleName()); 13.282 - // unbox objects 13.283 - 13.284 - for (int i = 0; i < type().parameterCount(); i++) { 13.285 - if (!type().parameterType(i).isPrimitive()) { 13.286 - mh = MH.filterArguments(mh, i, UNBOX.get(boxedType)); 13.287 - } 13.288 - } 13.289 - 13.290 - mh = Lookup.filterReturnType(mh, type().returnType()); 13.291 - mh = MH.explicitCastArguments(mh, type()); 13.292 - } 13.293 - 13.294 - final MethodHandle fallback = MH.foldArguments(MethodHandles.exactInvoker(type()), MH.insertArguments(NEXT, 0, this, requestName)); 13.295 - 13.296 - MethodHandle guard; 13.297 - if (type().parameterType(0).isPrimitive()) { 13.298 - guard = MH.insertArguments( 13.299 - MH.dropArguments(CHECKCAST, 1, type().parameterType(0)), 0, boxedType); 13.300 - } else if (type().parameterType(1).isPrimitive()) { 13.301 - guard = MH.insertArguments( 13.302 - MH.dropArguments(CHECKCAST, 2, type().parameterType(1)), 0, boxedType); 13.303 - } else { 13.304 - assert !type().parameterType(0).isPrimitive() && !type().parameterType(1).isPrimitive(); 13.305 - guard = MH.insertArguments(CHECKCAST2, 0, boxedType); 13.306 - } 13.307 - 13.308 - if (request == Request.ADD && boxedType == Integer.class) { 13.309 - // int add needs additional overflow check 13.310 - MethodHandle addcheck = ADDCHECK; 13.311 - for (int i = 0; i < type().parameterCount(); i++) { 13.312 - if (!type().parameterType(i).isPrimitive()) { 13.313 - addcheck = MH.filterArguments(addcheck, i, UNBOX.get(boxedType)); 13.314 - } 13.315 - } 13.316 - addcheck = MH.explicitCastArguments(addcheck, type().changeReturnType(boolean.class)); 13.317 - guard = MH.guardWithTest(upcastGuard(guard), addcheck, 13.318 - MH.dropArguments(MH.constant(boolean.class, false), 0, type().parameterArray())); 13.319 - } 13.320 - 13.321 - return MH.guardWithTest(upcastGuard(guard), mh, fallback); 13.322 - } 13.323 - 13.324 - // generic fallback 13.325 - return MH.explicitCastArguments(Lookup.filterReturnType(GENERIC_METHODS.get(request.name()), type().returnType()), type()); 13.326 - } 13.327 - 13.328 - private MethodHandle upcastGuard(final MethodHandle guard) { 13.329 - return MH.asType(guard, type().changeReturnType(boolean.class)); 13.330 - } 13.331 - 13.332 - /** 13.333 - * This is public just so that the generated specialization code can 13.334 - * use it to get the next wider typed method 13.335 - * 13.336 - * Do not call directly 13.337 - * 13.338 - * @param name current name (with type) of runtime call at the call site 13.339 - * @return next wider specialization method for this RuntimeCallSite 13.340 - */ 13.341 - public MethodHandle next(final String name) { 13.342 - final MethodHandle next = makeMethod(nextName(name)); 13.343 - setTarget(next); 13.344 - return next; 13.345 - } 13.346 - 13.347 - /** Method cache */ 13.348 - private static final Map<String, MethodHandle> METHODS; 13.349 - 13.350 - /** Generic method cache */ 13.351 - private static final Map<String, MethodHandle> GENERIC_METHODS; 13.352 - 13.353 - /** Unbox cache */ 13.354 - private static final Map<Class<?>, MethodHandle> UNBOX; 13.355 - 13.356 - private static final MethodHandle CHECKCAST = findOwnMH_S("checkcast", boolean.class, Class.class, Object.class); 13.357 - private static final MethodHandle CHECKCAST2 = findOwnMH_S("checkcast", boolean.class, Class.class, Object.class, Object.class); 13.358 - private static final MethodHandle ADDCHECK = findOwnMH_S("ADDcheck", boolean.class, int.class, int.class); 13.359 - 13.360 - /** 13.361 - * Build maps of correct boxing operations 13.362 - */ 13.363 - static { 13.364 - UNBOX = new HashMap<>(); 13.365 - UNBOX.put(Boolean.class, findOwnMH_S("unboxZ", int.class, Object.class)); 13.366 - UNBOX.put(Integer.class, findOwnMH_S("unboxI", int.class, Object.class)); 13.367 - UNBOX.put(Long.class, findOwnMH_S("unboxJ", long.class, Object.class)); 13.368 - UNBOX.put(Number.class, findOwnMH_S("unboxD", double.class, Object.class)); 13.369 - 13.370 - METHODS = new HashMap<>(); 13.371 - 13.372 - for (final Request req : Request.values()) { 13.373 - if (req.canSpecialize()) { 13.374 - if (req.name().endsWith("_STRICT")) { 13.375 - continue; 13.376 - } 13.377 - 13.378 - final boolean isCmp = Request.isComparison(req); 13.379 - 13.380 - METHODS.put(req.name() + "int", findOwnMH_S(req.name(), (isCmp ? boolean.class : int.class), int.class, int.class)); 13.381 - METHODS.put(req.name() + "long", findOwnMH_S(req.name(), (isCmp ? boolean.class : long.class), long.class, long.class)); 13.382 - METHODS.put(req.name() + "double", findOwnMH_S(req.name(), (isCmp ? boolean.class : double.class), double.class, double.class)); 13.383 - } 13.384 - } 13.385 - 13.386 - GENERIC_METHODS = new HashMap<>(); 13.387 - for (final Request req : Request.values()) { 13.388 - if (req.canSpecialize()) { 13.389 - GENERIC_METHODS.put(req.name(), MH.findStatic(MethodHandles.lookup(), ScriptRuntime.class, req.name(), 13.390 - MH.type(req.getReturnType().getTypeClass(), Object.class, Object.class))); 13.391 - } 13.392 - } 13.393 - } 13.394 - 13.395 - /** 13.396 - * Specialized version of != operator for two int arguments. Do not call directly. 13.397 - * @param a int 13.398 - * @param b int 13.399 - * @return a != b 13.400 - */ 13.401 - public static boolean NE(final int a, final int b) { 13.402 - return a != b; 13.403 - } 13.404 - 13.405 - /** 13.406 - * Specialized version of != operator for two double arguments. Do not call directly. 13.407 - * @param a double 13.408 - * @param b double 13.409 - * @return a != b 13.410 - */ 13.411 - public static boolean NE(final double a, final double b) { 13.412 - return a != b; 13.413 - } 13.414 - 13.415 - /** 13.416 - * Specialized version of != operator for two long arguments. Do not call directly. 13.417 - * @param a long 13.418 - * @param b long 13.419 - * @return a != b 13.420 - */ 13.421 - public static boolean NE(final long a, final long b) { 13.422 - return a != b; 13.423 - } 13.424 - 13.425 - /** 13.426 - * Specialized version of == operator for two int arguments. Do not call directly. 13.427 - * @param a int 13.428 - * @param b int 13.429 - * @return a == b 13.430 - */ 13.431 - public static boolean EQ(final int a, final int b) { 13.432 - return a == b; 13.433 - } 13.434 - 13.435 - /** 13.436 - * Specialized version of == operator for two double arguments. Do not call directly. 13.437 - * @param a double 13.438 - * @param b double 13.439 - * @return a == b 13.440 - */ 13.441 - public static boolean EQ(final double a, final double b) { 13.442 - return a == b; 13.443 - } 13.444 - 13.445 - /** 13.446 - * Specialized version of == operator for two long arguments. Do not call directly. 13.447 - * @param a long 13.448 - * @param b long 13.449 - * @return a == b 13.450 - */ 13.451 - public static boolean EQ(final long a, final long b) { 13.452 - return a == b; 13.453 - } 13.454 - 13.455 - /** 13.456 - * Specialized version of {@literal <} operator for two int arguments. Do not call directly. 13.457 - * @param a int 13.458 - * @param b int 13.459 - * @return a {@code <} b 13.460 - */ 13.461 - public static boolean LT(final int a, final int b) { 13.462 - return a < b; 13.463 - } 13.464 - 13.465 - /** 13.466 - * Specialized version of {@literal <} operator for two double arguments. Do not call directly. 13.467 - * @param a double 13.468 - * @param b double 13.469 - * @return a {@literal <} b 13.470 - */ 13.471 - public static boolean LT(final double a, final double b) { 13.472 - return a < b; 13.473 - } 13.474 - 13.475 - /** 13.476 - * Specialized version of {@literal <} operator for two long arguments. Do not call directly. 13.477 - * @param a long 13.478 - * @param b long 13.479 - * @return a {@literal <} b 13.480 - */ 13.481 - public static boolean LT(final long a, final long b) { 13.482 - return a < b; 13.483 - } 13.484 - 13.485 - /** 13.486 - * Specialized version of {@literal <=} operator for two int arguments. Do not call directly. 13.487 - * @param a int 13.488 - * @param b int 13.489 - * @return a {@literal <=} b 13.490 - */ 13.491 - public static boolean LE(final int a, final int b) { 13.492 - return a <= b; 13.493 - } 13.494 - 13.495 - /** 13.496 - * Specialized version of {@literal <=} operator for two double arguments. Do not call directly. 13.497 - * @param a double 13.498 - * @param b double 13.499 - * @return a {@literal <=} b 13.500 - */ 13.501 - public static boolean LE(final double a, final double b) { 13.502 - return a <= b; 13.503 - } 13.504 - 13.505 - /** 13.506 - * Specialized version of {@literal <=} operator for two long arguments. Do not call directly. 13.507 - * @param a long 13.508 - * @param b long 13.509 - * @return a {@literal <=} b 13.510 - */ 13.511 - public static boolean LE(final long a, final long b) { 13.512 - return a <= b; 13.513 - } 13.514 - 13.515 - /** 13.516 - * Specialized version of {@literal >} operator for two int arguments. Do not call directly. 13.517 - * @param a int 13.518 - * @param b int 13.519 - * @return a {@literal >} b 13.520 - */ 13.521 - public static boolean GT(final int a, final int b) { 13.522 - return a > b; 13.523 - } 13.524 - 13.525 - /** 13.526 - * Specialized version of {@literal >} operator for two double arguments. Do not call directly. 13.527 - * @param a double 13.528 - * @param b double 13.529 - * @return a {@literal >} b 13.530 - */ 13.531 - public static boolean GT(final double a, final double b) { 13.532 - return a > b; 13.533 - } 13.534 - 13.535 - /** 13.536 - * Specialized version of {@literal >} operator for two long arguments. Do not call directly. 13.537 - * @param a long 13.538 - * @param b long 13.539 - * @return a {@literal >} b 13.540 - */ 13.541 - public static boolean GT(final long a, final long b) { 13.542 - return a > b; 13.543 - } 13.544 - 13.545 - /** 13.546 - * Specialized version of {@literal >=} operator for two int arguments. Do not call directly. 13.547 - * @param a int 13.548 - * @param b int 13.549 - * @return a {@literal >=} b 13.550 - */ 13.551 - public static boolean GE(final int a, final int b) { 13.552 - return a >= b; 13.553 - } 13.554 - 13.555 - /** 13.556 - * Specialized version of {@literal >=} operator for two double arguments. Do not call directly. 13.557 - * @param a double 13.558 - * @param b double 13.559 - * @return a {@literal >=} b 13.560 - */ 13.561 - public static boolean GE(final double a, final double b) { 13.562 - return a >= b; 13.563 - } 13.564 - 13.565 - /** 13.566 - * Specialized version of {@literal >=} operator for two long arguments. Do not call directly. 13.567 - * @param a long 13.568 - * @param b long 13.569 - * @return a {@code >=} b 13.570 - */ 13.571 - public static boolean GE(final long a, final long b) { 13.572 - return a >= b; 13.573 - } 13.574 - 13.575 - /** 13.576 - * Specialized version of + operator for two int arguments. Do not call directly. 13.577 - * @param a int 13.578 - * @param b int 13.579 - * @return a + b 13.580 - */ 13.581 - public static int ADD(final int a, final int b) { 13.582 - return a + b; 13.583 - } 13.584 - 13.585 - /** 13.586 - * Specialized version of + operator for two long arguments. Do not call directly. 13.587 - * @param a long 13.588 - * @param b long 13.589 - * @return a + b 13.590 - */ 13.591 - public static long ADD(final long a, final long b) { 13.592 - return a + b; 13.593 - } 13.594 - 13.595 - /** 13.596 - * Specialized version of + operator for two double arguments. Do not call directly. 13.597 - * @param a double 13.598 - * @param b double 13.599 - * @return a + b 13.600 - */ 13.601 - public static double ADD(final double a, final double b) { 13.602 - return a + b; 13.603 - } 13.604 - 13.605 - /** 13.606 - * Check that ints are addition compatible, i.e. their sum is equal to the sum 13.607 - * of them cast to long. Otherwise the addition will overflow. Do not call directly. 13.608 - * 13.609 - * @param a int 13.610 - * @param b int 13.611 - * 13.612 - * @return true if addition does not overflow 13.613 - */ 13.614 - public static boolean ADDcheck(final int a, final int b) { 13.615 - return (a + b == (long)a + (long)b); 13.616 - } 13.617 - 13.618 - /** 13.619 - * Checkcast used for specialized ops. Do not call directly 13.620 - * 13.621 - * @param type to to check against 13.622 - * @param obj object to check for type 13.623 - * 13.624 - * @return true if type check holds 13.625 - */ 13.626 - public static boolean checkcast(final Class<?> type, final Object obj) { 13.627 - return type.isInstance(obj); 13.628 - } 13.629 - 13.630 - /** 13.631 - * Checkcast used for specialized ops. Do not call directly 13.632 - * 13.633 - * @param type type to check against 13.634 - * @param objA first object to check against type 13.635 - * @param objB second object to check against type 13.636 - * 13.637 - * @return true if type check holds for both objects 13.638 - */ 13.639 - public static boolean checkcast(final Class<?> type, final Object objA, final Object objB) { 13.640 - return type.isInstance(objA) && type.isInstance(objB); 13.641 - } 13.642 - 13.643 - /** 13.644 - * Unbox a java.lang.Boolean. Do not call directly 13.645 - * @param obj object to cast to int and unbox 13.646 - * @return an int value for the boolean, 1 is true, 0 is false 13.647 - */ 13.648 - public static int unboxZ(final Object obj) { 13.649 - return (boolean)obj ? 1 : 0; 13.650 - } 13.651 - 13.652 - /** 13.653 - * Unbox a java.lang.Integer. Do not call directly 13.654 - * @param obj object to cast to int and unbox 13.655 - * @return an int 13.656 - */ 13.657 - public static int unboxI(final Object obj) { 13.658 - return (int)obj; 13.659 - } 13.660 - 13.661 - /** 13.662 - * Unbox a java.lang.Long. Do not call directly 13.663 - * @param obj object to cast to long and unbox 13.664 - * @return a long 13.665 - */ 13.666 - public static long unboxJ(final Object obj) { 13.667 - return (long)obj; 13.668 - } 13.669 - 13.670 - /** 13.671 - * Unbox a java.lang.Number. Do not call directly 13.672 - * @param obj object to cast to Number and unbox 13.673 - * @return a double 13.674 - */ 13.675 - public static double unboxD(final Object obj) { 13.676 - return ((Number)obj).doubleValue(); 13.677 - } 13.678 - 13.679 - private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) { 13.680 - return MH.findStatic(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types)); 13.681 - } 13.682 - 13.683 - private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) { 13.684 - return MH.findVirtual(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types)); 13.685 - } 13.686 -}
14.1 --- a/src/jdk/nashorn/internal/ir/BinaryNode.java Wed Mar 11 14:11:06 2015 -0700 14.2 +++ b/src/jdk/nashorn/internal/ir/BinaryNode.java Thu Mar 12 13:45:00 2015 -0700 14.3 @@ -98,7 +98,7 @@ 14.4 } 14.5 14.6 /** 14.7 - * Returns true if the node is a comparison operation. 14.8 + * Returns true if the node is a comparison operation (either equality, inequality, or relational). 14.9 * @return true if the node is a comparison operation. 14.10 */ 14.11 public boolean isComparison() { 14.12 @@ -118,6 +118,22 @@ 14.13 } 14.14 14.15 /** 14.16 + * Returns true if the node is a relational operation (less than (or equals), greater than (or equals)). 14.17 + * @return true if the node is a relational operation. 14.18 + */ 14.19 + public boolean isRelational() { 14.20 + switch (tokenType()) { 14.21 + case LT: 14.22 + case GT: 14.23 + case LE: 14.24 + case GE: 14.25 + return true; 14.26 + default: 14.27 + return false; 14.28 + } 14.29 + } 14.30 + 14.31 + /** 14.32 * Returns true if the node is a logical operation. 14.33 * @return true if the node is a logical operation. 14.34 */
15.1 --- a/src/jdk/nashorn/internal/ir/RuntimeNode.java Wed Mar 11 14:11:06 2015 -0700 15.2 +++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java Thu Mar 12 13:45:00 2015 -0700 15.3 @@ -25,8 +25,6 @@ 15.4 15.5 package jdk.nashorn.internal.ir; 15.6 15.7 -import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 15.8 - 15.9 import java.util.Arrays; 15.10 import java.util.Collections; 15.11 import java.util.List; 15.12 @@ -39,7 +37,7 @@ 15.13 * IR representation for a runtime call. 15.14 */ 15.15 @Immutable 15.16 -public class RuntimeNode extends Expression implements Optimistic { 15.17 +public class RuntimeNode extends Expression { 15.18 private static final long serialVersionUID = 1L; 15.19 15.20 /** 15.21 @@ -333,11 +331,6 @@ 15.22 /** Call arguments. */ 15.23 private final List<Expression> args; 15.24 15.25 - /** is final - i.e. may not be removed again, lower in the code pipeline */ 15.26 - private final boolean isFinal; 15.27 - 15.28 - private final int programPoint; 15.29 - 15.30 /** 15.31 * Constructor 15.32 * 15.33 @@ -351,17 +344,13 @@ 15.34 15.35 this.request = request; 15.36 this.args = args; 15.37 - this.isFinal = false; 15.38 - this.programPoint = INVALID_PROGRAM_POINT; 15.39 } 15.40 15.41 - private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final boolean isFinal, final List<Expression> args, final int programPoint) { 15.42 + private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final List<Expression> args) { 15.43 super(runtimeNode); 15.44 15.45 this.request = request; 15.46 this.args = args; 15.47 - this.isFinal = isFinal; 15.48 - this.programPoint = programPoint; 15.49 } 15.50 15.51 /** 15.52 @@ -399,8 +388,6 @@ 15.53 15.54 this.request = request; 15.55 this.args = args; 15.56 - this.isFinal = false; 15.57 - this.programPoint = parent instanceof Optimistic ? ((Optimistic)parent).getProgramPoint() : INVALID_PROGRAM_POINT; 15.58 } 15.59 15.60 /** 15.61 @@ -428,32 +415,11 @@ 15.62 * @return new runtime node or same if same request 15.63 */ 15.64 public RuntimeNode setRequest(final Request request) { 15.65 - if (this.request == request) { 15.66 - return this; 15.67 - } 15.68 - return new RuntimeNode(this, request, isFinal, args, programPoint); 15.69 - } 15.70 - 15.71 - 15.72 - /** 15.73 - * Is this node final - i.e. it can never be replaced with other nodes again 15.74 - * @return true if final 15.75 - */ 15.76 - public boolean isFinal() { 15.77 - return isFinal; 15.78 - } 15.79 - 15.80 - /** 15.81 - * Flag this node as final - i.e it may never be replaced with other nodes again 15.82 - * @param isFinal is the node final, i.e. can not be removed and replaced by a less generic one later in codegen 15.83 - * @return same runtime node if already final, otherwise a new one 15.84 - */ 15.85 - public RuntimeNode setIsFinal(final boolean isFinal) { 15.86 - if (this.isFinal == isFinal) { 15.87 + if (this.request == request) { 15.88 return this; 15.89 } 15.90 - return new RuntimeNode(this, request, isFinal, args, programPoint); 15.91 - } 15.92 + return new RuntimeNode(this, request, args); 15.93 + } 15.94 15.95 /** 15.96 * Return type for the ReferenceNode 15.97 @@ -510,7 +476,7 @@ 15.98 if (this.args == args) { 15.99 return this; 15.100 } 15.101 - return new RuntimeNode(this, request, isFinal, args, programPoint); 15.102 + return new RuntimeNode(this, request, args); 15.103 } 15.104 15.105 /** 15.106 @@ -536,39 +502,4 @@ 15.107 } 15.108 return true; 15.109 } 15.110 - 15.111 -//TODO these are blank for now: 15.112 - 15.113 - @Override 15.114 - public int getProgramPoint() { 15.115 - return programPoint; 15.116 - } 15.117 - 15.118 - @Override 15.119 - public RuntimeNode setProgramPoint(final int programPoint) { 15.120 - if(this.programPoint == programPoint) { 15.121 - return this; 15.122 - } 15.123 - return new RuntimeNode(this, request, isFinal, args, programPoint); 15.124 - } 15.125 - 15.126 - @Override 15.127 - public boolean canBeOptimistic() { 15.128 - return false; 15.129 - } 15.130 - 15.131 - @Override 15.132 - public Type getMostOptimisticType() { 15.133 - return getType(); 15.134 - } 15.135 - 15.136 - @Override 15.137 - public Type getMostPessimisticType() { 15.138 - return getType(); 15.139 - } 15.140 - 15.141 - @Override 15.142 - public RuntimeNode setType(final Type type) { 15.143 - return this; 15.144 - } 15.145 }
16.1 --- a/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java Wed Mar 11 14:11:06 2015 -0700 16.2 +++ b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java Thu Mar 12 13:45:00 2015 -0700 16.3 @@ -25,6 +25,8 @@ 16.4 16.5 package jdk.nashorn.internal.lookup; 16.6 16.7 +import static jdk.nashorn.internal.runtime.JSType.isString; 16.8 + 16.9 import java.io.ByteArrayOutputStream; 16.10 import java.io.PrintStream; 16.11 import java.lang.invoke.MethodHandle; 16.12 @@ -36,7 +38,6 @@ 16.13 import java.util.Arrays; 16.14 import java.util.List; 16.15 import java.util.logging.Level; 16.16 -import jdk.nashorn.internal.runtime.ConsString; 16.17 import jdk.nashorn.internal.runtime.Context; 16.18 import jdk.nashorn.internal.runtime.Debug; 16.19 import jdk.nashorn.internal.runtime.ScriptObject; 16.20 @@ -343,7 +344,7 @@ 16.21 final Object d = data[i]; 16.22 if (d == null) { 16.23 sb.append("<null> "); 16.24 - } else if (d instanceof String || d instanceof ConsString) { 16.25 + } else if (isString(d)) { 16.26 sb.append(d.toString()); 16.27 sb.append(' '); 16.28 } else if (d.getClass().isArray()) {
17.1 --- a/src/jdk/nashorn/internal/objects/Global.java Wed Mar 11 14:11:06 2015 -0700 17.2 +++ b/src/jdk/nashorn/internal/objects/Global.java Thu Mar 12 13:45:00 2015 -0700 17.3 @@ -28,6 +28,7 @@ 17.4 import static jdk.nashorn.internal.lookup.Lookup.MH; 17.5 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; 17.6 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 17.7 +import static jdk.nashorn.internal.runtime.JSType.isString; 17.8 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 17.9 17.10 import java.io.IOException; 17.11 @@ -55,7 +56,6 @@ 17.12 import jdk.nashorn.internal.objects.annotations.Attribute; 17.13 import jdk.nashorn.internal.objects.annotations.Property; 17.14 import jdk.nashorn.internal.objects.annotations.ScriptClass; 17.15 -import jdk.nashorn.internal.runtime.ConsString; 17.16 import jdk.nashorn.internal.runtime.Context; 17.17 import jdk.nashorn.internal.runtime.ECMAErrors; 17.18 import jdk.nashorn.internal.runtime.GlobalConstants; 17.19 @@ -578,7 +578,7 @@ 17.20 return new NativeBoolean((Boolean)obj, this); 17.21 } else if (obj instanceof Number) { 17.22 return new NativeNumber(((Number)obj).doubleValue(), this); 17.23 - } else if (obj instanceof String || obj instanceof ConsString) { 17.24 + } else if (isString(obj)) { 17.25 return new NativeString((CharSequence)obj, this); 17.26 } else if (obj instanceof Object[]) { // extension 17.27 return new NativeArray(ArrayData.allocate((Object[])obj), this); 17.28 @@ -605,7 +605,7 @@ 17.29 * @return guarded invocation 17.30 */ 17.31 public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) { 17.32 - if (self instanceof String || self instanceof ConsString) { 17.33 + if (isString(self)) { 17.34 return NativeString.lookupPrimitive(request, self); 17.35 } else if (self instanceof Number) { 17.36 return NativeNumber.lookupPrimitive(request, self); 17.37 @@ -622,7 +622,7 @@ 17.38 * @return method handle to create wrapper objects for primitive receiver 17.39 */ 17.40 public static MethodHandle getPrimitiveWrapFilter(final Object self) { 17.41 - if (self instanceof String || self instanceof ConsString) { 17.42 + if (isString(self)) { 17.43 return NativeString.WRAPFILTER; 17.44 } else if (self instanceof Number) { 17.45 return NativeNumber.WRAPFILTER; 17.46 @@ -948,7 +948,7 @@ 17.47 * This is directly invoked from generated when eval(code) is called in user code 17.48 */ 17.49 public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) { 17.50 - if (!(str instanceof String || str instanceof ConsString)) { 17.51 + if (!isString(str)) { 17.52 return str; 17.53 } 17.54 final Global global = Global.instanceFrom(self);
18.1 --- a/src/jdk/nashorn/internal/objects/NativeDate.java Wed Mar 11 14:11:06 2015 -0700 18.2 +++ b/src/jdk/nashorn/internal/objects/NativeDate.java Thu Mar 12 13:45:00 2015 -0700 18.3 @@ -30,6 +30,7 @@ 18.4 import static java.lang.Double.isNaN; 18.5 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError; 18.6 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 18.7 + 18.8 import java.util.Locale; 18.9 import java.util.TimeZone; 18.10 import java.util.concurrent.Callable; 18.11 @@ -40,7 +41,6 @@ 18.12 import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 18.13 import jdk.nashorn.internal.objects.annotations.Where; 18.14 import jdk.nashorn.internal.parser.DateParser; 18.15 -import jdk.nashorn.internal.runtime.ConsString; 18.16 import jdk.nashorn.internal.runtime.JSType; 18.17 import jdk.nashorn.internal.runtime.PropertyMap; 18.18 import jdk.nashorn.internal.runtime.ScriptEnvironment; 18.19 @@ -183,7 +183,7 @@ 18.20 case 1: 18.21 double num; 18.22 final Object arg = JSType.toPrimitive(args[0]); 18.23 - if (arg instanceof String || arg instanceof ConsString) { 18.24 + if (JSType.isString(arg)) { 18.25 num = parseDateString(arg.toString()); 18.26 } else { 18.27 num = timeClip(JSType.toNumber(args[0]));
19.1 --- a/src/jdk/nashorn/internal/objects/NativeJSON.java Wed Mar 11 14:11:06 2015 -0700 19.2 +++ b/src/jdk/nashorn/internal/objects/NativeJSON.java Thu Mar 12 13:45:00 2015 -0700 19.3 @@ -181,7 +181,7 @@ 19.4 } 19.5 gap = sb.toString(); 19.6 } 19.7 - } else if (modSpace instanceof String || modSpace instanceof ConsString) { 19.8 + } else if (JSType.isString(modSpace)) { 19.9 final String str = modSpace.toString(); 19.10 gap = str.substring(0, Math.min(10, str.length())); 19.11 } else {
20.1 --- a/src/jdk/nashorn/internal/objects/NativeString.java Wed Mar 11 14:11:06 2015 -0700 20.2 +++ b/src/jdk/nashorn/internal/objects/NativeString.java Thu Mar 12 13:45:00 2015 -0700 20.3 @@ -90,7 +90,7 @@ 20.4 20.5 private NativeString(final CharSequence value, final ScriptObject proto, final PropertyMap map) { 20.6 super(proto, map); 20.7 - assert value instanceof String || value instanceof ConsString; 20.8 + assert JSType.isString(value); 20.9 this.value = value; 20.10 } 20.11 20.12 @@ -155,7 +155,7 @@ 20.13 final Object self = request.getReceiver(); 20.14 final Class<?> returnType = desc.getMethodType().returnType(); 20.15 20.16 - if (returnType == Object.class && (self instanceof String || self instanceof ConsString)) { 20.17 + if (returnType == Object.class && JSType.isString(self)) { 20.18 try { 20.19 return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getInstanceOf2Guard(String.class, ConsString.class)); 20.20 } catch (final LookupException e) { 20.21 @@ -1312,7 +1312,7 @@ 20.22 } 20.23 20.24 private static CharSequence getCharSequence(final Object self) { 20.25 - if (self instanceof String || self instanceof ConsString) { 20.26 + if (JSType.isString(self)) { 20.27 return (CharSequence)self; 20.28 } else if (self instanceof NativeString) { 20.29 return ((NativeString)self).getValue();
21.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Wed Mar 11 14:11:06 2015 -0700 21.2 +++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Thu Mar 12 13:45:00 2015 -0700 21.3 @@ -305,7 +305,7 @@ 21.4 final ScriptFunction typeErrorThrower = global.getTypeErrorThrower(); 21.5 if (findProperty("arguments", true) != null) { 21.6 initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower); 21.7 - } 21.8 + } 21.9 if (findProperty("caller", true) != null) { 21.10 initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower); 21.11 }
22.1 --- a/src/jdk/nashorn/internal/parser/JSONParser.java Wed Mar 11 14:11:06 2015 -0700 22.2 +++ b/src/jdk/nashorn/internal/parser/JSONParser.java Thu Mar 12 13:45:00 2015 -0700 22.3 @@ -244,20 +244,15 @@ 22.4 private static PropertyMap addObjectProperty(final PropertyMap propertyMap, final List<Object> values, 22.5 final String id, final Object value) { 22.6 final Property oldProperty = propertyMap.findProperty(id); 22.7 - final Property newProperty; 22.8 final PropertyMap newMap; 22.9 final Class<?> type = ObjectClassGenerator.OBJECT_FIELDS_ONLY ? Object.class : getType(value); 22.10 22.11 if (oldProperty != null) { 22.12 values.set(oldProperty.getSlot(), value); 22.13 - newProperty = new SpillProperty(id, 0, oldProperty.getSlot()); 22.14 - newProperty.setType(type); 22.15 - newMap = propertyMap.replaceProperty(oldProperty, newProperty);; 22.16 + newMap = propertyMap.replaceProperty(oldProperty, new SpillProperty(id, 0, oldProperty.getSlot(), type));; 22.17 } else { 22.18 values.add(value); 22.19 - newProperty = new SpillProperty(id, 0, propertyMap.size()); 22.20 - newProperty.setType(type); 22.21 - newMap = propertyMap.addProperty(newProperty); 22.22 + newMap = propertyMap.addProperty(new SpillProperty(id, 0, propertyMap.size(), type)); 22.23 } 22.24 22.25 return newMap;
23.1 --- a/src/jdk/nashorn/internal/runtime/AllocationStrategy.java Wed Mar 11 14:11:06 2015 -0700 23.2 +++ b/src/jdk/nashorn/internal/runtime/AllocationStrategy.java Thu Mar 12 13:45:00 2015 -0700 23.3 @@ -29,55 +29,52 @@ 23.4 import java.io.Serializable; 23.5 import java.lang.invoke.MethodHandle; 23.6 import java.lang.invoke.MethodHandles; 23.7 +import jdk.nashorn.internal.codegen.Compiler; 23.8 import jdk.nashorn.internal.codegen.CompilerConstants; 23.9 -import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor; 23.10 +import jdk.nashorn.internal.codegen.ObjectClassGenerator; 23.11 23.12 /** 23.13 - * Encapsulates the allocation strategy for a function when used as a constructor. Basically the same as 23.14 - * {@link AllocatorDescriptor}, but with an additionally cached resolved method handle. There is also a 23.15 - * canonical default allocation strategy for functions that don't assign any "this" properties (vast majority 23.16 - * of all functions), therefore saving some storage space in {@link RecompilableScriptFunctionData} that would 23.17 - * otherwise be lost to identical tuples of (map, className, handle) fields. 23.18 + * Encapsulates the allocation strategy for a function when used as a constructor. 23.19 */ 23.20 -final class AllocationStrategy implements Serializable { 23.21 +final public class AllocationStrategy implements Serializable { 23.22 private static final long serialVersionUID = 1L; 23.23 23.24 private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); 23.25 23.26 - private static final AllocationStrategy DEFAULT_STRATEGY = new AllocationStrategy(new AllocatorDescriptor(0)); 23.27 - 23.28 - /** Allocator map from allocator descriptor */ 23.29 - private final PropertyMap allocatorMap; 23.30 + /** Number of fields in the allocated object */ 23.31 + private final int fieldCount; 23.32 23.33 /** Name of class where allocator function resides */ 23.34 - private final String allocatorClassName; 23.35 + private transient String allocatorClassName; 23.36 23.37 /** lazily generated allocator */ 23.38 private transient MethodHandle allocator; 23.39 23.40 - private AllocationStrategy(final AllocatorDescriptor desc) { 23.41 - this.allocatorMap = desc.getAllocatorMap(); 23.42 - // These classes get loaded, so an interned variant of their name is most likely around anyway. 23.43 - this.allocatorClassName = desc.getAllocatorClassName().intern(); 23.44 + /** 23.45 + * Construct an allocation strategy with the given map and class name. 23.46 + * @param fieldCount number of fields in the allocated object 23.47 + */ 23.48 + public AllocationStrategy(final int fieldCount) { 23.49 + this.fieldCount = fieldCount; 23.50 } 23.51 23.52 - private boolean matches(final AllocatorDescriptor desc) { 23.53 - return desc.getAllocatorMap().size() == allocatorMap.size() && 23.54 - desc.getAllocatorClassName().equals(allocatorClassName); 23.55 - } 23.56 - 23.57 - static AllocationStrategy get(final AllocatorDescriptor desc) { 23.58 - return DEFAULT_STRATEGY.matches(desc) ? DEFAULT_STRATEGY : new AllocationStrategy(desc); 23.59 + private String getAllocatorClassName() { 23.60 + if (allocatorClassName == null) { 23.61 + // These classes get loaded, so an interned variant of their name is most likely around anyway. 23.62 + allocatorClassName = Compiler.binaryName(ObjectClassGenerator.getClassName(fieldCount)).intern(); 23.63 + } 23.64 + return allocatorClassName; 23.65 } 23.66 23.67 PropertyMap getAllocatorMap() { 23.68 - return allocatorMap; 23.69 + // Create a new map for each function instance 23.70 + return PropertyMap.newMap(null, getAllocatorClassName(), 0, fieldCount, 0); 23.71 } 23.72 23.73 ScriptObject allocate(final PropertyMap map) { 23.74 try { 23.75 if (allocator == null) { 23.76 - allocator = MH.findStatic(LOOKUP, Context.forStructureClass(allocatorClassName), 23.77 + allocator = MH.findStatic(LOOKUP, Context.forStructureClass(getAllocatorClassName()), 23.78 CompilerConstants.ALLOCATE.symbolName(), MH.type(ScriptObject.class, PropertyMap.class)); 23.79 } 23.80 return (ScriptObject)allocator.invokeExact(map); 23.81 @@ -88,17 +85,8 @@ 23.82 } 23.83 } 23.84 23.85 - private Object readResolve() { 23.86 - if(allocatorMap.size() == DEFAULT_STRATEGY.allocatorMap.size() && 23.87 - allocatorClassName.equals(DEFAULT_STRATEGY.allocatorClassName)) { 23.88 - return DEFAULT_STRATEGY; 23.89 - } 23.90 - return this; 23.91 - } 23.92 - 23.93 @Override 23.94 public String toString() { 23.95 - return "AllocationStrategy[allocatorClassName=" + allocatorClassName + ", allocatorMap.size=" + 23.96 - allocatorMap.size() + "]"; 23.97 + return "AllocationStrategy[fieldCount=" + fieldCount + "]"; 23.98 } 23.99 }
24.1 --- a/src/jdk/nashorn/internal/runtime/ConsString.java Wed Mar 11 14:11:06 2015 -0700 24.2 +++ b/src/jdk/nashorn/internal/runtime/ConsString.java Thu Mar 12 13:45:00 2015 -0700 24.3 @@ -25,6 +25,8 @@ 24.4 24.5 package jdk.nashorn.internal.runtime; 24.6 24.7 +import static jdk.nashorn.internal.runtime.JSType.isString; 24.8 + 24.9 import java.util.ArrayDeque; 24.10 import java.util.Deque; 24.11 24.12 @@ -52,8 +54,8 @@ 24.13 * @param right right char sequence 24.14 */ 24.15 public ConsString(final CharSequence left, final CharSequence right) { 24.16 - assert left instanceof String || left instanceof ConsString; 24.17 - assert right instanceof String || right instanceof ConsString; 24.18 + assert isString(left); 24.19 + assert isString(right); 24.20 this.left = left; 24.21 this.right = right; 24.22 length = left.length() + right.length();
25.1 --- a/src/jdk/nashorn/internal/runtime/JSType.java Wed Mar 11 14:11:06 2015 -0700 25.2 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Thu Mar 12 13:45:00 2015 -0700 25.3 @@ -29,6 +29,7 @@ 25.4 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY; 25.5 import static jdk.nashorn.internal.lookup.Lookup.MH; 25.6 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 25.7 + 25.8 import java.lang.invoke.MethodHandle; 25.9 import java.lang.invoke.MethodHandles; 25.10 import java.lang.reflect.Array; 25.11 @@ -37,6 +38,7 @@ 25.12 import java.util.Deque; 25.13 import java.util.List; 25.14 import jdk.internal.dynalink.beans.StaticClass; 25.15 +import jdk.nashorn.api.scripting.AbstractJSObject; 25.16 import jdk.nashorn.api.scripting.JSObject; 25.17 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 25.18 import jdk.nashorn.internal.codegen.types.Type; 25.19 @@ -210,7 +212,6 @@ 25.20 /** Method handle for void returns. */ 25.21 public static final Call VOID_RETURN = staticCall(JSTYPE_LOOKUP, JSType.class, "voidReturn", void.class); 25.22 25.23 - 25.24 /** 25.25 * The list of available accessor types in width order. This order is used for type guesses narrow{@literal ->} wide 25.26 * in the dual--fields world 25.27 @@ -311,7 +312,7 @@ 25.28 return JSType.BOOLEAN; 25.29 } 25.30 25.31 - if (obj instanceof String || obj instanceof ConsString) { 25.32 + if (isString(obj)) { 25.33 return JSType.STRING; 25.34 } 25.35 25.36 @@ -349,7 +350,7 @@ 25.37 return JSType.BOOLEAN; 25.38 } 25.39 25.40 - if (obj instanceof String || obj instanceof ConsString) { 25.41 + if (isString(obj)) { 25.42 return JSType.STRING; 25.43 } 25.44 25.45 @@ -455,8 +456,7 @@ 25.46 obj == ScriptRuntime.UNDEFINED || 25.47 obj instanceof Boolean || 25.48 obj instanceof Number || 25.49 - obj instanceof String || 25.50 - obj instanceof ConsString; 25.51 + isString(obj); 25.52 } 25.53 25.54 /** 25.55 @@ -480,17 +480,47 @@ 25.56 * @return the primitive form of the object 25.57 */ 25.58 public static Object toPrimitive(final Object obj, final Class<?> hint) { 25.59 - return obj instanceof ScriptObject ? toPrimitive((ScriptObject)obj, hint) : obj; 25.60 + if (obj instanceof ScriptObject) { 25.61 + return toPrimitive((ScriptObject)obj, hint); 25.62 + } else if (isPrimitive(obj)) { 25.63 + return obj; 25.64 + } else if (obj instanceof JSObject) { 25.65 + return toPrimitive((JSObject)obj, hint); 25.66 + } else if (obj instanceof StaticClass) { 25.67 + final String name = ((StaticClass)obj).getRepresentedClass().getName(); 25.68 + return new StringBuilder(12 + name.length()).append("[JavaClass ").append(name).append(']').toString(); 25.69 + } 25.70 + return obj.toString(); 25.71 } 25.72 25.73 private static Object toPrimitive(final ScriptObject sobj, final Class<?> hint) { 25.74 - final Object result = sobj.getDefaultValue(hint); 25.75 + return requirePrimitive(sobj.getDefaultValue(hint)); 25.76 + } 25.77 25.78 + private static Object requirePrimitive(final Object result) { 25.79 if (!isPrimitive(result)) { 25.80 throw typeError("bad.default.value", result.toString()); 25.81 } 25.82 + return result; 25.83 + } 25.84 25.85 - return result; 25.86 + /** 25.87 + * Primitive converter for a {@link JSObject} including type hint. Invokes 25.88 + * {@link AbstractJSObject#getDefaultValue(JSObject, Class)} and translates any thrown 25.89 + * {@link UnsupportedOperationException} to an ECMAScript {@code TypeError}. 25.90 + * See ECMA 9.1 ToPrimitive 25.91 + * 25.92 + * @param jsobj a JSObject 25.93 + * @param hint a type hint 25.94 + * 25.95 + * @return the primitive form of the JSObject 25.96 + */ 25.97 + public static Object toPrimitive(final JSObject jsobj, final Class<?> hint) { 25.98 + try { 25.99 + return requirePrimitive(AbstractJSObject.getDefaultValue(jsobj, hint)); 25.100 + } catch (final UnsupportedOperationException e) { 25.101 + throw new ECMAException(Context.getGlobal().newTypeError(e.getMessage()), e); 25.102 + } 25.103 } 25.104 25.105 /** 25.106 @@ -547,7 +577,7 @@ 25.107 return num != 0 && !Double.isNaN(num); 25.108 } 25.109 25.110 - if (obj instanceof String || obj instanceof ConsString) { 25.111 + if (isString(obj)) { 25.112 return ((CharSequence)obj).length() > 0; 25.113 } 25.114 25.115 @@ -598,6 +628,15 @@ 25.116 } 25.117 25.118 /** 25.119 + * Returns true if object represents a primitive JavaScript string value. 25.120 + * @param obj the object 25.121 + * @return true if the object represents a primitive JavaScript string value. 25.122 + */ 25.123 + public static boolean isString(final Object obj) { 25.124 + return obj instanceof String || obj instanceof ConsString; 25.125 + } 25.126 + 25.127 + /** 25.128 * JavaScript compliant conversion of integer to String 25.129 * 25.130 * @param num an integer 25.131 @@ -723,6 +762,48 @@ 25.132 return toNumberGeneric(obj); 25.133 } 25.134 25.135 + /** 25.136 + * Converts an object for a comparison with a number. Almost identical to {@link #toNumber(Object)} but 25.137 + * converts {@code null} to {@code NaN} instead of zero, so it won't compare equal to zero. 25.138 + * 25.139 + * @param obj an object 25.140 + * 25.141 + * @return a number 25.142 + */ 25.143 + public static double toNumberForEq(final Object obj) { 25.144 + return obj == null ? Double.NaN : toNumber(obj); 25.145 + } 25.146 + 25.147 + /** 25.148 + * Converts an object for strict comparison with a number. Returns {@code NaN} for any object that is not 25.149 + * a {@link Number}, so only boxed numerics can compare strictly equal to numbers. 25.150 + * 25.151 + * @param obj an object 25.152 + * 25.153 + * @return a number 25.154 + */ 25.155 + public static double toNumberForStrictEq(final Object obj) { 25.156 + if (obj instanceof Double) { 25.157 + return (Double)obj; 25.158 + } 25.159 + if (obj instanceof Number) { 25.160 + return ((Number)obj).doubleValue(); 25.161 + } 25.162 + return Double.NaN; 25.163 + } 25.164 + 25.165 + 25.166 + /** 25.167 + * JavaScript compliant conversion of Boolean to number 25.168 + * See ECMA 9.3 ToNumber 25.169 + * 25.170 + * @param b a boolean 25.171 + * 25.172 + * @return JS numeric value of the boolean: 1.0 or 0.0 25.173 + */ 25.174 + public static double toNumber(final Boolean b) { 25.175 + return b ? 1d : +0d; 25.176 + } 25.177 25.178 /** 25.179 * JavaScript compliant conversion of Object to number 25.180 @@ -1301,6 +1382,10 @@ 25.181 return (String)obj; 25.182 } 25.183 25.184 + if (obj instanceof ConsString) { 25.185 + return obj.toString(); 25.186 + } 25.187 + 25.188 if (obj instanceof Number) { 25.189 return toString(((Number)obj).doubleValue()); 25.190 } 25.191 @@ -1313,23 +1398,19 @@ 25.192 return "null"; 25.193 } 25.194 25.195 - if (obj instanceof ScriptObject) { 25.196 - if (safe) { 25.197 - final ScriptObject sobj = (ScriptObject)obj; 25.198 - final Global gobj = Context.getGlobal(); 25.199 - return gobj.isError(sobj) ? 25.200 - ECMAException.safeToString(sobj) : 25.201 - sobj.safeToString(); 25.202 - } 25.203 - 25.204 - return toString(toPrimitive(obj, String.class)); 25.205 + if (obj instanceof Boolean) { 25.206 + return obj.toString(); 25.207 } 25.208 25.209 - if (obj instanceof StaticClass) { 25.210 - return "[JavaClass " + ((StaticClass)obj).getRepresentedClass().getName() + "]"; 25.211 + if (safe && obj instanceof ScriptObject) { 25.212 + final ScriptObject sobj = (ScriptObject)obj; 25.213 + final Global gobj = Context.getGlobal(); 25.214 + return gobj.isError(sobj) ? 25.215 + ECMAException.safeToString(sobj) : 25.216 + sobj.safeToString(); 25.217 } 25.218 25.219 - return obj.toString(); 25.220 + return toString(toPrimitive(obj, String.class)); 25.221 } 25.222 25.223 // trim from left for JS whitespaces. 25.224 @@ -1822,18 +1903,18 @@ 25.225 } 25.226 25.227 if (obj instanceof Boolean) { 25.228 - return (Boolean)obj ? 1 : +0.0; 25.229 + return toNumber((Boolean)obj); 25.230 } 25.231 25.232 if (obj instanceof ScriptObject) { 25.233 return toNumber((ScriptObject)obj); 25.234 } 25.235 25.236 - if (obj instanceof JSObject) { 25.237 - return ((JSObject)obj).toNumber(); 25.238 + if (obj instanceof Undefined) { 25.239 + return Double.NaN; 25.240 } 25.241 25.242 - return Double.NaN; 25.243 + return toNumber(toPrimitive(obj, Number.class)); 25.244 } 25.245 25.246 private static Object invoke(final MethodHandle mh, final Object arg) {
26.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Mar 11 14:11:06 2015 -0700 26.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Thu Mar 12 13:45:00 2015 -0700 26.3 @@ -43,7 +43,6 @@ 26.4 import jdk.nashorn.internal.codegen.CompilerConstants; 26.5 import jdk.nashorn.internal.codegen.FunctionSignature; 26.6 import jdk.nashorn.internal.codegen.Namespace; 26.7 -import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor; 26.8 import jdk.nashorn.internal.codegen.OptimisticTypesPersistence; 26.9 import jdk.nashorn.internal.codegen.TypeMap; 26.10 import jdk.nashorn.internal.codegen.types.Type; 26.11 @@ -126,7 +125,7 @@ 26.12 * 26.13 * @param functionNode functionNode that represents this function code 26.14 * @param installer installer for code regeneration versions of this function 26.15 - * @param allocationDescriptor descriptor for the allocation behavior when this function is used as a constructor 26.16 + * @param allocationStrategy strategy for the allocation behavior when this function is used as a constructor 26.17 * @param nestedFunctions nested function map 26.18 * @param externalScopeDepths external scope depths 26.19 * @param internalSymbols internal symbols to method, defined in its scope 26.20 @@ -135,7 +134,7 @@ 26.21 public RecompilableScriptFunctionData( 26.22 final FunctionNode functionNode, 26.23 final CodeInstaller<ScriptEnvironment> installer, 26.24 - final AllocatorDescriptor allocationDescriptor, 26.25 + final AllocationStrategy allocationStrategy, 26.26 final Map<Integer, RecompilableScriptFunctionData> nestedFunctions, 26.27 final Map<String, Integer> externalScopeDepths, 26.28 final Set<String> internalSymbols, 26.29 @@ -153,7 +152,7 @@ 26.30 this.endParserState = functionNode.getEndParserState(); 26.31 this.token = tokenFor(functionNode); 26.32 this.installer = installer; 26.33 - this.allocationStrategy = AllocationStrategy.get(allocationDescriptor); 26.34 + this.allocationStrategy = allocationStrategy; 26.35 this.nestedFunctions = smallMap(nestedFunctions); 26.36 this.externalScopeDepths = smallMap(externalScopeDepths); 26.37 this.internalSymbols = smallSet(new HashSet<>(internalSymbols));
27.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Mar 11 14:11:06 2015 -0700 27.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Mar 12 13:45:00 2015 -0700 27.3 @@ -143,7 +143,6 @@ 27.4 27.5 this.data = data; 27.6 this.scope = scope; 27.7 - this.allocatorMap = data.getAllocatorMap(); 27.8 } 27.9 27.10 @Override 27.11 @@ -253,7 +252,7 @@ 27.12 27.13 assert !isBoundFunction(); // allocate never invoked on bound functions 27.14 27.15 - final ScriptObject object = data.allocate(allocatorMap); 27.16 + final ScriptObject object = data.allocate(getAllocatorMap()); 27.17 27.18 if (object != null) { 27.19 final Object prototype = getPrototype(); 27.20 @@ -269,6 +268,13 @@ 27.21 return object; 27.22 } 27.23 27.24 + private PropertyMap getAllocatorMap() { 27.25 + if (allocatorMap == null) { 27.26 + allocatorMap = data.getAllocatorMap(); 27.27 + } 27.28 + return allocatorMap; 27.29 + } 27.30 + 27.31 /** 27.32 * Return Object.prototype - used by "allocate" 27.33 * @return Object.prototype
28.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Mar 11 14:11:06 2015 -0700 28.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Thu Mar 12 13:45:00 2015 -0700 28.3 @@ -28,6 +28,7 @@ 28.4 import static jdk.nashorn.internal.lookup.Lookup.MH; 28.5 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 28.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 28.7 + 28.8 import java.io.IOException; 28.9 import java.io.ObjectInputStream; 28.10 import java.io.Serializable; 28.11 @@ -456,8 +457,7 @@ 28.12 } 28.13 28.14 static boolean isPrimitiveThis(final Object obj) { 28.15 - return obj instanceof String || obj instanceof ConsString || 28.16 - obj instanceof Number || obj instanceof Boolean; 28.17 + return JSType.isString(obj) || obj instanceof Number || obj instanceof Boolean; 28.18 } 28.19 28.20 /**
29.1 --- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Mar 11 14:11:06 2015 -0700 29.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Thu Mar 12 13:45:00 2015 -0700 29.3 @@ -32,6 +32,8 @@ 29.4 import static jdk.nashorn.internal.runtime.ECMAErrors.syntaxError; 29.5 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 29.6 import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt; 29.7 +import static jdk.nashorn.internal.runtime.JSType.isString; 29.8 + 29.9 import java.lang.invoke.MethodHandle; 29.10 import java.lang.invoke.MethodHandles; 29.11 import java.lang.invoke.SwitchPoint; 29.12 @@ -55,7 +57,6 @@ 29.13 import jdk.nashorn.internal.parser.Lexer; 29.14 import jdk.nashorn.internal.runtime.linker.Bootstrap; 29.15 29.16 - 29.17 /** 29.18 * Utilities to be called by JavaScript runtime API and generated classes. 29.19 */ 29.20 @@ -535,8 +536,6 @@ 29.21 29.22 /** 29.23 * ECMA 11.6.1 - The addition operator (+) - generic implementation 29.24 - * Compiler specializes using {@link jdk.nashorn.internal.codegen.RuntimeCallSite} 29.25 - * if any type information is available for any of the operands 29.26 * 29.27 * @param x first term 29.28 * @param y second term 29.29 @@ -563,8 +562,7 @@ 29.30 final Object xPrim = JSType.toPrimitive(x); 29.31 final Object yPrim = JSType.toPrimitive(y); 29.32 29.33 - if (xPrim instanceof String || yPrim instanceof String 29.34 - || xPrim instanceof ConsString || yPrim instanceof ConsString) { 29.35 + if (isString(xPrim) || isString(yPrim)) { 29.36 try { 29.37 return new ConsString(JSType.toCharSequence(xPrim), JSType.toCharSequence(yPrim)); 29.38 } catch (final IllegalArgumentException iae) { 29.39 @@ -734,7 +732,7 @@ 29.40 return true; 29.41 } 29.42 if (x instanceof ScriptObject && y instanceof ScriptObject) { 29.43 - return x == y; 29.44 + return false; // x != y 29.45 } 29.46 if (x instanceof ScriptObjectMirror || y instanceof ScriptObjectMirror) { 29.47 return ScriptObjectMirror.identical(x, y); 29.48 @@ -798,37 +796,55 @@ 29.49 * @return true if they're equal 29.50 */ 29.51 private static boolean equalDifferentTypeValues(final Object x, final Object y, final JSType xType, final JSType yType) { 29.52 - if (xType == JSType.UNDEFINED && yType == JSType.NULL || xType == JSType.NULL && yType == JSType.UNDEFINED) { 29.53 + if (isUndefinedAndNull(xType, yType) || isUndefinedAndNull(yType, xType)) { 29.54 return true; 29.55 - } 29.56 - 29.57 - if (xType == JSType.NUMBER && yType == JSType.STRING) { 29.58 - return equals(x, JSType.toNumber(y)); 29.59 - } 29.60 - 29.61 - if (xType == JSType.STRING && yType == JSType.NUMBER) { 29.62 - return equals(JSType.toNumber(x), y); 29.63 - } 29.64 - 29.65 - if (xType == JSType.BOOLEAN) { 29.66 - return equals(JSType.toNumber(x), y); 29.67 - } 29.68 - 29.69 - if (yType == JSType.BOOLEAN) { 29.70 - return equals(x, JSType.toNumber(y)); 29.71 - } 29.72 - 29.73 - if ((xType == JSType.STRING || xType == JSType.NUMBER) && y instanceof ScriptObject) { 29.74 - return equals(x, JSType.toPrimitive(y)); 29.75 - } 29.76 - 29.77 - if (x instanceof ScriptObject && (yType == JSType.STRING || yType == JSType.NUMBER)) { 29.78 - return equals(JSType.toPrimitive(x), y); 29.79 + } else if (isNumberAndString(xType, yType)) { 29.80 + return equalNumberToString(x, y); 29.81 + } else if (isNumberAndString(yType, xType)) { 29.82 + // Can reverse order as both are primitives 29.83 + return equalNumberToString(y, x); 29.84 + } else if (xType == JSType.BOOLEAN) { 29.85 + return equalBooleanToAny(x, y); 29.86 + } else if (yType == JSType.BOOLEAN) { 29.87 + // Can reverse order as y is primitive 29.88 + return equalBooleanToAny(y, x); 29.89 + } else if (isNumberOrStringAndObject(xType, yType)) { 29.90 + return equalNumberOrStringToObject(x, y); 29.91 + } else if (isNumberOrStringAndObject(yType, xType)) { 29.92 + // Can reverse order as y is primitive 29.93 + return equalNumberOrStringToObject(y, x); 29.94 } 29.95 29.96 return false; 29.97 } 29.98 29.99 + private static boolean isUndefinedAndNull(final JSType xType, final JSType yType) { 29.100 + return xType == JSType.UNDEFINED && yType == JSType.NULL; 29.101 + } 29.102 + 29.103 + private static boolean isNumberAndString(final JSType xType, final JSType yType) { 29.104 + return xType == JSType.NUMBER && yType == JSType.STRING; 29.105 + } 29.106 + 29.107 + private static boolean isNumberOrStringAndObject(final JSType xType, final JSType yType) { 29.108 + return (xType == JSType.NUMBER || xType == JSType.STRING) && yType == JSType.OBJECT; 29.109 + } 29.110 + 29.111 + private static boolean equalNumberToString(final Object num, final Object str) { 29.112 + // Specification says comparing a number to string should be done as "equals(num, JSType.toNumber(str))". We 29.113 + // can short circuit it to this as we know that "num" is a number, so it'll end up being a number-number 29.114 + // comparison. 29.115 + return ((Number)num).doubleValue() == JSType.toNumber(str.toString()); 29.116 + } 29.117 + 29.118 + private static boolean equalBooleanToAny(final Object bool, final Object any) { 29.119 + return equals(JSType.toNumber((Boolean)bool), any); 29.120 + } 29.121 + 29.122 + private static boolean equalNumberOrStringToObject(final Object numOrStr, final Object any) { 29.123 + return equals(numOrStr, JSType.toPrimitive(any)); 29.124 + } 29.125 + 29.126 /** 29.127 * ECMA 11.9.4 - The strict equal operator (===) - generic implementation 29.128 * 29.129 @@ -935,8 +951,15 @@ 29.130 * @return true if x is less than y 29.131 */ 29.132 public static boolean LT(final Object x, final Object y) { 29.133 - final Object value = lessThan(x, y, true); 29.134 - return value == UNDEFINED ? false : (Boolean)value; 29.135 + final Object px = JSType.toPrimitive(x, Number.class); 29.136 + final Object py = JSType.toPrimitive(y, Number.class); 29.137 + 29.138 + return areBothString(px, py) ? px.toString().compareTo(py.toString()) < 0 : 29.139 + JSType.toNumber(px) < JSType.toNumber(py); 29.140 + } 29.141 + 29.142 + private static boolean areBothString(final Object x, final Object y) { 29.143 + return isString(x) && isString(y); 29.144 } 29.145 29.146 /** 29.147 @@ -948,8 +971,11 @@ 29.148 * @return true if x is greater than y 29.149 */ 29.150 public static boolean GT(final Object x, final Object y) { 29.151 - final Object value = lessThan(y, x, false); 29.152 - return value == UNDEFINED ? false : (Boolean)value; 29.153 + final Object px = JSType.toPrimitive(x, Number.class); 29.154 + final Object py = JSType.toPrimitive(y, Number.class); 29.155 + 29.156 + return areBothString(px, py) ? px.toString().compareTo(py.toString()) > 0 : 29.157 + JSType.toNumber(px) > JSType.toNumber(py); 29.158 } 29.159 29.160 /** 29.161 @@ -961,8 +987,11 @@ 29.162 * @return true if x is less than or equal to y 29.163 */ 29.164 public static boolean LE(final Object x, final Object y) { 29.165 - final Object value = lessThan(y, x, false); 29.166 - return !(Boolean.TRUE.equals(value) || value == UNDEFINED); 29.167 + final Object px = JSType.toPrimitive(x, Number.class); 29.168 + final Object py = JSType.toPrimitive(y, Number.class); 29.169 + 29.170 + return areBothString(px, py) ? px.toString().compareTo(py.toString()) <= 0 : 29.171 + JSType.toNumber(px) <= JSType.toNumber(py); 29.172 } 29.173 29.174 /** 29.175 @@ -974,48 +1003,11 @@ 29.176 * @return true if x is greater than or equal to y 29.177 */ 29.178 public static boolean GE(final Object x, final Object y) { 29.179 - final Object value = lessThan(x, y, true); 29.180 - return !(Boolean.TRUE.equals(value) || value == UNDEFINED); 29.181 - } 29.182 + final Object px = JSType.toPrimitive(x, Number.class); 29.183 + final Object py = JSType.toPrimitive(y, Number.class); 29.184 29.185 - /** ECMA 11.8.5 The Abstract Relational Comparison Algorithm */ 29.186 - private static Object lessThan(final Object x, final Object y, final boolean leftFirst) { 29.187 - Object px, py; 29.188 - 29.189 - //support e.g. x < y should throw exception correctly if x or y are not numeric 29.190 - if (leftFirst) { 29.191 - px = JSType.toPrimitive(x, Number.class); 29.192 - py = JSType.toPrimitive(y, Number.class); 29.193 - } else { 29.194 - py = JSType.toPrimitive(y, Number.class); 29.195 - px = JSType.toPrimitive(x, Number.class); 29.196 - } 29.197 - 29.198 - if (JSType.ofNoFunction(px) == JSType.STRING && JSType.ofNoFunction(py) == JSType.STRING) { 29.199 - // May be String or ConsString 29.200 - return px.toString().compareTo(py.toString()) < 0; 29.201 - } 29.202 - 29.203 - final double nx = JSType.toNumber(px); 29.204 - final double ny = JSType.toNumber(py); 29.205 - 29.206 - if (Double.isNaN(nx) || Double.isNaN(ny)) { 29.207 - return UNDEFINED; 29.208 - } 29.209 - 29.210 - if (nx == ny) { 29.211 - return false; 29.212 - } 29.213 - 29.214 - if (nx > 0 && ny > 0 && Double.isInfinite(nx) && Double.isInfinite(ny)) { 29.215 - return false; 29.216 - } 29.217 - 29.218 - if (nx < 0 && ny < 0 && Double.isInfinite(nx) && Double.isInfinite(ny)) { 29.219 - return false; 29.220 - } 29.221 - 29.222 - return nx < ny; 29.223 + return areBothString(px, py) ? px.toString().compareTo(py.toString()) >= 0 : 29.224 + JSType.toNumber(px) >= JSType.toNumber(py); 29.225 } 29.226 29.227 /** 29.228 @@ -1028,9 +1020,7 @@ 29.229 final Context context = Context.getContextTrusted(); 29.230 final SwitchPoint sp = context.getBuiltinSwitchPoint(name); 29.231 assert sp != null; 29.232 - if (sp != null) { 29.233 - context.getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint"); 29.234 - SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 29.235 - } 29.236 + context.getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint"); 29.237 + SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 29.238 } 29.239 }
30.1 --- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Wed Mar 11 14:11:06 2015 -0700 30.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Thu Mar 12 13:45:00 2015 -0700 30.3 @@ -107,7 +107,7 @@ 30.4 30.5 if (file instanceof File) { 30.6 f = (File)file; 30.7 - } else if (file instanceof String || file instanceof ConsString) { 30.8 + } else if (JSType.isString(file)) { 30.9 f = new java.io.File(((CharSequence)file).toString()); 30.10 } 30.11
31.1 --- a/src/jdk/nashorn/internal/runtime/SpillProperty.java Wed Mar 11 14:11:06 2015 -0700 31.2 +++ b/src/jdk/nashorn/internal/runtime/SpillProperty.java Thu Mar 12 13:45:00 2015 -0700 31.3 @@ -164,7 +164,14 @@ 31.4 assert !OBJECT_FIELDS_ONLY || getLocalType() == Object.class; 31.5 } 31.6 31.7 - SpillProperty(final String key, final int flags, final int slot, final Class<?> initialType) { 31.8 + /** 31.9 + * Constructor for spill properties with an initial type. 31.10 + * @param key the property key 31.11 + * @param flags the property flags 31.12 + * @param slot spill slot 31.13 + * @param initialType initial type 31.14 + */ 31.15 + public SpillProperty(final String key, final int flags, final int slot, final Class<?> initialType) { 31.16 this(key, flags, slot); 31.17 setType(OBJECT_FIELDS_ONLY ? Object.class : initialType); 31.18 }
32.1 --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Mar 11 14:11:06 2015 -0700 32.2 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Thu Mar 12 13:45:00 2015 -0700 32.3 @@ -48,7 +48,6 @@ 32.4 import jdk.nashorn.api.scripting.JSObject; 32.5 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 32.6 import jdk.nashorn.internal.codegen.ObjectClassGenerator; 32.7 -import jdk.nashorn.internal.codegen.RuntimeCallSite; 32.8 import jdk.nashorn.internal.lookup.MethodHandleFactory; 32.9 import jdk.nashorn.internal.lookup.MethodHandleFunctionality; 32.10 import jdk.nashorn.internal.objects.ScriptFunctionImpl; 32.11 @@ -210,19 +209,6 @@ 32.12 } 32.13 32.14 /** 32.15 - * Bootstrapper for a specialized Runtime call 32.16 - * 32.17 - * @param lookup lookup 32.18 - * @param initialName initial name for callsite 32.19 - * @param type method type for call site 32.20 - * 32.21 - * @return callsite for a runtime node 32.22 - */ 32.23 - public static CallSite runtimeBootstrap(final MethodHandles.Lookup lookup, final String initialName, final MethodType type) { 32.24 - return new RuntimeCallSite(type, initialName); 32.25 - } 32.26 - 32.27 - /** 32.28 * Boostrapper for math calls that may overflow 32.29 * @param lookup lookup 32.30 * @param name name of operation
33.1 --- a/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Wed Mar 11 14:11:06 2015 -0700 33.2 +++ b/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Thu Mar 12 13:45:00 2015 -0700 33.3 @@ -25,11 +25,13 @@ 33.4 33.5 package jdk.nashorn.internal.runtime.linker; 33.6 33.7 +import static jdk.nashorn.internal.runtime.JSType.isString; 33.8 +import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_CALL; 33.9 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETMEMBER; 33.10 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETSLOT; 33.11 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETMEMBER; 33.12 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETSLOT; 33.13 -import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_CALL; 33.14 + 33.15 import java.lang.invoke.MethodHandle; 33.16 import java.lang.invoke.MethodHandles; 33.17 import jdk.internal.dynalink.CallSiteDescriptor; 33.18 @@ -170,12 +172,12 @@ 33.19 if (index > -1) { 33.20 return JSOBJECT_GETSLOT.invokeExact(jsobj, index); 33.21 } 33.22 - } else if (key instanceof String) { 33.23 - final String name = (String)key; 33.24 + } else if (isString(key)) { 33.25 + final String name = key.toString(); 33.26 if (name.indexOf('(') != -1) { 33.27 - return fallback.invokeExact(jsobj, key); 33.28 + return fallback.invokeExact(jsobj, (Object) name); 33.29 } 33.30 - return JSOBJECT_GETMEMBER.invokeExact(jsobj, (String)key); 33.31 + return JSOBJECT_GETMEMBER.invokeExact(jsobj, name); 33.32 } 33.33 return null; 33.34 } 33.35 @@ -186,8 +188,8 @@ 33.36 JSOBJECT_SETSLOT.invokeExact(jsobj, (int)key, value); 33.37 } else if (key instanceof Number) { 33.38 JSOBJECT_SETSLOT.invokeExact(jsobj, getIndex((Number)key), value); 33.39 - } else if (key instanceof String) { 33.40 - JSOBJECT_SETMEMBER.invokeExact(jsobj, (String)key, value); 33.41 + } else if (isString(key)) { 33.42 + JSOBJECT_SETMEMBER.invokeExact(jsobj, key.toString(), value); 33.43 } 33.44 } 33.45
34.1 --- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Wed Mar 11 14:11:06 2015 -0700 34.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Thu Mar 12 13:45:00 2015 -0700 34.3 @@ -25,16 +25,14 @@ 34.4 34.5 package jdk.nashorn.internal.runtime.linker; 34.6 34.7 +import static jdk.nashorn.internal.runtime.JSType.isString; 34.8 + 34.9 import java.lang.invoke.MethodHandle; 34.10 import java.lang.invoke.MethodHandles; 34.11 -import java.lang.invoke.MethodType; 34.12 -import java.util.HashMap; 34.13 import java.util.Map; 34.14 import javax.script.Bindings; 34.15 import jdk.internal.dynalink.CallSiteDescriptor; 34.16 import jdk.internal.dynalink.linker.GuardedInvocation; 34.17 -import jdk.internal.dynalink.linker.GuardedTypeConversion; 34.18 -import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; 34.19 import jdk.internal.dynalink.linker.LinkRequest; 34.20 import jdk.internal.dynalink.linker.LinkerServices; 34.21 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; 34.22 @@ -48,7 +46,7 @@ 34.23 * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well 34.24 * as ScriptObjects from other Nashorn contexts. 34.25 */ 34.26 -final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory { 34.27 +final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { 34.28 private final NashornBeansLinker nashornBeansLinker; 34.29 34.30 JSObjectLinker(final NashornBeansLinker nashornBeansLinker) { 34.31 @@ -94,22 +92,6 @@ 34.32 return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc); 34.33 } 34.34 34.35 - @Override 34.36 - public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception { 34.37 - final boolean sourceIsAlwaysJSObject = JSObject.class.isAssignableFrom(sourceType); 34.38 - if(!sourceIsAlwaysJSObject && !sourceType.isAssignableFrom(JSObject.class)) { 34.39 - return null; 34.40 - } 34.41 - 34.42 - final MethodHandle converter = CONVERTERS.get(targetType); 34.43 - if(converter == null) { 34.44 - return null; 34.45 - } 34.46 - 34.47 - return new GuardedTypeConversion(new GuardedInvocation(converter, sourceIsAlwaysJSObject ? null : IS_JSOBJECT_GUARD).asType(MethodType.methodType(targetType, sourceType)), true); 34.48 - } 34.49 - 34.50 - 34.51 private GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request, final LinkerServices linkerServices) throws Exception { 34.52 final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); 34.53 final int c = desc.getNameTokenCount(); 34.54 @@ -185,11 +167,11 @@ 34.55 if (index > -1) { 34.56 return ((JSObject)jsobj).getSlot(index); 34.57 } 34.58 - } else if (key instanceof String) { 34.59 - final String name = (String)key; 34.60 + } else if (isString(key)) { 34.61 + final String name = key.toString(); 34.62 // get with method name and signature. delegate it to beans linker! 34.63 if (name.indexOf('(') != -1) { 34.64 - return fallback.invokeExact(jsobj, key); 34.65 + return fallback.invokeExact(jsobj, (Object) name); 34.66 } 34.67 return ((JSObject)jsobj).getMember(name); 34.68 } 34.69 @@ -202,30 +184,11 @@ 34.70 ((JSObject)jsobj).setSlot((Integer)key, value); 34.71 } else if (key instanceof Number) { 34.72 ((JSObject)jsobj).setSlot(getIndex((Number)key), value); 34.73 - } else if (key instanceof String) { 34.74 - ((JSObject)jsobj).setMember((String)key, value); 34.75 + } else if (isString(key)) { 34.76 + ((JSObject)jsobj).setMember(key.toString(), value); 34.77 } 34.78 } 34.79 34.80 - @SuppressWarnings("unused") 34.81 - private static int toInt32(final JSObject obj) { 34.82 - return JSType.toInt32(toNumber(obj)); 34.83 - } 34.84 - 34.85 - @SuppressWarnings("unused") 34.86 - private static long toLong(final JSObject obj) { 34.87 - return JSType.toLong(toNumber(obj)); 34.88 - } 34.89 - 34.90 - private static double toNumber(final JSObject obj) { 34.91 - return obj == null ? 0 : obj.toNumber(); 34.92 - } 34.93 - 34.94 - @SuppressWarnings("unused") 34.95 - private static boolean toBoolean(final JSObject obj) { 34.96 - return obj != null; 34.97 - } 34.98 - 34.99 private static int getIndex(final Number n) { 34.100 final double value = n.doubleValue(); 34.101 return JSType.isRepresentableAsInt(value) ? (int)value : -1; 34.102 @@ -260,14 +223,6 @@ 34.103 private static final MethodHandle JSOBJECT_CALL_TO_APPLY = findOwnMH_S("callToApply", Object.class, MethodHandle.class, JSObject.class, Object.class, Object[].class); 34.104 private static final MethodHandle JSOBJECT_NEW = findJSObjectMH_V("newObject", Object.class, Object[].class); 34.105 34.106 - private static final Map<Class<?>, MethodHandle> CONVERTERS = new HashMap<>(); 34.107 - static { 34.108 - CONVERTERS.put(boolean.class, findOwnMH_S("toBoolean", boolean.class, JSObject.class)); 34.109 - CONVERTERS.put(int.class, findOwnMH_S("toInt32", int.class, JSObject.class)); 34.110 - CONVERTERS.put(long.class, findOwnMH_S("toLong", long.class, JSObject.class)); 34.111 - CONVERTERS.put(double.class, findOwnMH_S("toNumber", double.class, JSObject.class)); 34.112 - } 34.113 - 34.114 private static MethodHandle findJSObjectMH_V(final String name, final Class<?> rtype, final Class<?>... types) { 34.115 return MH.findVirtual(MethodHandles.lookup(), JSObject.class, name, MH.type(rtype, types)); 34.116 }
35.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Wed Mar 11 14:11:06 2015 -0700 35.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Thu Mar 12 13:45:00 2015 -0700 35.3 @@ -27,6 +27,7 @@ 35.4 35.5 import static jdk.nashorn.internal.lookup.Lookup.MH; 35.6 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 35.7 +import static jdk.nashorn.internal.runtime.JSType.isString; 35.8 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 35.9 35.10 import java.lang.invoke.MethodHandle; 35.11 @@ -78,7 +79,7 @@ 35.12 } 35.13 35.14 if (obj == UNDEFINED) { 35.15 - // NOTE: same reasoning for FindBugs NP_BOOLEAN_RETURN_NUL warning as in the preceding comment. 35.16 + // NOTE: same reasoning for FindBugs NP_BOOLEAN_RETURN_NULL warning as in the preceding comment. 35.17 return null; 35.18 } 35.19 35.20 @@ -87,7 +88,7 @@ 35.21 return num != 0 && !Double.isNaN(num); 35.22 } 35.23 35.24 - if (obj instanceof String || obj instanceof ConsString) { 35.25 + if (isString(obj)) { 35.26 return ((CharSequence) obj).length() > 0; 35.27 } 35.28 35.29 @@ -207,7 +208,7 @@ 35.30 return f.longValue(); 35.31 } else if (obj instanceof Number) { 35.32 return ((Number)obj).longValue(); 35.33 - } else if (obj instanceof String || obj instanceof ConsString) { 35.34 + } else if (isString(obj)) { 35.35 return JSType.toLong(obj); 35.36 } else if (obj instanceof Boolean) { 35.37 return (Boolean)obj ? 1L : 0L;
36.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Wed Mar 11 14:11:06 2015 -0700 36.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Thu Mar 12 13:45:00 2015 -0700 36.3 @@ -39,6 +39,7 @@ 36.4 import jdk.internal.dynalink.support.TypeUtilities; 36.5 import jdk.nashorn.internal.objects.Global; 36.6 import jdk.nashorn.internal.runtime.ConsString; 36.7 +import jdk.nashorn.internal.runtime.JSType; 36.8 import jdk.nashorn.internal.runtime.ScriptRuntime; 36.9 36.10 /** 36.11 @@ -170,7 +171,7 @@ 36.12 36.13 @SuppressWarnings("unused") 36.14 private static boolean isJavaScriptPrimitive(final Object o) { 36.15 - return o instanceof String || o instanceof Boolean || o instanceof Number || o instanceof ConsString || o == null; 36.16 + return JSType.isString(o) || o instanceof Boolean || o instanceof Number || o == null; 36.17 } 36.18 36.19 private static final MethodHandle GUARD_PRIMITIVE = findOwnMH("isJavaScriptPrimitive", boolean.class, Object.class);
37.1 --- a/test/script/basic/JDK-8023026.js.EXPECTED Wed Mar 11 14:11:06 2015 -0700 37.2 +++ b/test/script/basic/JDK-8023026.js.EXPECTED Thu Mar 12 13:45:00 2015 -0700 37.3 @@ -26,7 +26,7 @@ 37.4 reduceRight 15 1 37.5 right sum 16 37.6 squared 1,9,25,49 37.7 -iterating on [object Array] 37.8 +iterating on 2,4,6,8 37.9 forEach 2 37.10 forEach 4 37.11 forEach 6
38.1 --- a/test/script/basic/JDK-8024847.js Wed Mar 11 14:11:06 2015 -0700 38.2 +++ b/test/script/basic/JDK-8024847.js Thu Mar 12 13:45:00 2015 -0700 38.3 @@ -102,7 +102,18 @@ 38.4 print(jlist); 38.5 38.6 var obj = new JSObject() { 38.7 - toNumber: function() { return 42; } 38.8 + getMember: function(name) { 38.9 + if (name == "valueOf") { 38.10 + return new JSObject() { 38.11 + isFunction: function() { 38.12 + return true; 38.13 + }, 38.14 + call: function(thiz) { 38.15 + return 42; 38.16 + } 38.17 + }; 38.18 + } 38.19 + } 38.20 }; 38.21 38.22 print(32 + obj);
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/test/script/basic/JDK-8035712.js Thu Mar 12 13:45:00 2015 -0700 39.3 @@ -0,0 +1,282 @@ 39.4 +/* 39.5 + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. 39.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 39.7 + * 39.8 + * This code is free software; you can redistribute it and/or modify it 39.9 + * under the terms of the GNU General Public License version 2 only, as 39.10 + * published by the Free Software Foundation. 39.11 + * 39.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 39.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 39.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 39.15 + * version 2 for more details (a copy is included in the LICENSE file that 39.16 + * accompanied this code). 39.17 + * 39.18 + * You should have received a copy of the GNU General Public License version 39.19 + * 2 along with this work; if not, write to the Free Software Foundation, 39.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 39.21 + * 39.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 39.23 + * or visit www.oracle.com if you need additional information or have any 39.24 + * questions. 39.25 + */ 39.26 + 39.27 +/** 39.28 + * JDK-8035712: Restore some of the RuntimeCallSite specializations 39.29 + * 39.30 + * @test 39.31 + * @run 39.32 + */ 39.33 + 39.34 +if ((typeof Assert) == "undefined") { 39.35 + Assert = { 39.36 + assertTrue: function(x) { if(!x) { throw "expected true" } }, 39.37 + assertFalse: function(x) { if(x) { throw "expected false" } }, 39.38 + }; 39.39 +} 39.40 + 39.41 +function nop() {} 39.42 + 39.43 +function EQ(x, y) { 39.44 + // Exercise normal evaluation 39.45 + Assert.assertTrue (x == y); 39.46 + Assert.assertTrue (y == x); 39.47 + Assert.assertFalse(x != y); 39.48 + Assert.assertFalse(y != x); 39.49 + // Exercise the branch optimizer 39.50 + if (x == y) { nop(); } else { Assert.fail(); } 39.51 + if (y == x) { nop(); } else { Assert.fail(); } 39.52 + if (x != y) { Assert.fail(); } else { nop(); } 39.53 + if (y != x) { Assert.fail(); } else { nop(); } 39.54 +} 39.55 + 39.56 +function NE(x, y) { 39.57 + // Exercise normal evaluation 39.58 + Assert.assertTrue (x != y); 39.59 + Assert.assertTrue (y != x); 39.60 + Assert.assertFalse(x == y); 39.61 + Assert.assertFalse(y == x); 39.62 + // Exercise the branch optimizer 39.63 + if (x != y) { nop(); } else { Assert.fail(); } 39.64 + if (y != x) { nop(); } else { Assert.fail(); } 39.65 + if (x == y) { Assert.fail(); } else { nop(); } 39.66 + if (y == x) { Assert.fail(); } else { nop(); } 39.67 +} 39.68 + 39.69 +function STRICT_EQ(x, y) { 39.70 + // Exercise normal evaluation 39.71 + Assert.assertTrue (x === y); 39.72 + Assert.assertTrue (y === x); 39.73 + Assert.assertFalse(x !== y); 39.74 + Assert.assertFalse(y !== x); 39.75 + // Exercise the branch optimizer 39.76 + if (x === y) { nop(); } else { Assert.fail(); } 39.77 + if (y === x) { nop(); } else { Assert.fail(); } 39.78 + if (x !== y) { Assert.fail(); } else { nop(); } 39.79 + if (y !== x) { Assert.fail(); } else { nop(); } 39.80 +} 39.81 + 39.82 +function STRICT_NE(x, y) { 39.83 + // Exercise normal evaluation 39.84 + Assert.assertTrue (x !== y); 39.85 + Assert.assertTrue (y !== x); 39.86 + Assert.assertFalse(x === y); 39.87 + Assert.assertFalse(y === x); 39.88 + // Exercise the branch optimizer 39.89 + if (x !== y) { nop(); } else { Assert.fail(); } 39.90 + if (y !== x) { nop(); } else { Assert.fail(); } 39.91 + if (x === y) { Assert.fail(); } else { nop(); } 39.92 + if (y === x) { Assert.fail(); } else { nop(); } 39.93 +} 39.94 + 39.95 +function cmpToAnyNumber(cmp, value) { 39.96 + cmp(1, value); 39.97 + cmp(4294967296, value); 39.98 + cmp(1.2, value); 39.99 + cmp(Infinity, value); 39.100 + cmp(-Infinity, value); 39.101 + cmp(1/Infinity, value); 39.102 + cmp(0, value); 39.103 + cmp(-0, value); 39.104 + cmp(true, value); 39.105 + cmp(false, value); 39.106 +} 39.107 + 39.108 +function notEqualToAnyNumber(value) { 39.109 + cmpToAnyNumber(NE, value); 39.110 + cmpToAnyNumber(STRICT_NE, value); 39.111 +} 39.112 + 39.113 +notEqualToAnyNumber(null); 39.114 +notEqualToAnyNumber(void 0); 39.115 +notEqualToAnyNumber("abc"); 39.116 +notEqualToAnyNumber({}); 39.117 +notEqualToAnyNumber(["xyz"]); 39.118 + 39.119 +function objectWithPrimitiveFunctionNotEqualToAnyNumber(fnName) { 39.120 + var obj = { 39.121 + count: 0 39.122 + }; 39.123 + obj[fnName] = function() { this.count++; return "foo"; }; 39.124 + notEqualToAnyNumber(obj); 39.125 + // Every NE will invoke it 8 times; cmpToAnyNumber has 10 comparisons 39.126 + // STRICT_NE doesn't invoke toString. 39.127 + Assert.assertTrue(80 === obj.count); 39.128 +} 39.129 +objectWithPrimitiveFunctionNotEqualToAnyNumber("valueOf"); 39.130 +objectWithPrimitiveFunctionNotEqualToAnyNumber("toString"); 39.131 + 39.132 +function objectEqualButNotStrictlyEqual(val, obj) { 39.133 + EQ(val, obj); 39.134 + STRICT_NE(val, obj); 39.135 +} 39.136 + 39.137 +function numberEqualButNotStrictlyEqualToObject(num, obj) { 39.138 + objectEqualButNotStrictlyEqual(num, obj); 39.139 + objectEqualButNotStrictlyEqual(num, [obj]); 39.140 + objectEqualButNotStrictlyEqual(num, [[obj]]); 39.141 +} 39.142 + 39.143 +function numberEqualButNotStrictlyEqualToZeroObjects(num) { 39.144 + numberEqualButNotStrictlyEqualToObject(num, [0]); 39.145 + numberEqualButNotStrictlyEqualToObject(num, ""); 39.146 + numberEqualButNotStrictlyEqualToObject(num, []); 39.147 + numberEqualButNotStrictlyEqualToObject(num, "0"); 39.148 +} 39.149 + 39.150 +numberEqualButNotStrictlyEqualToZeroObjects(0); 39.151 +numberEqualButNotStrictlyEqualToZeroObjects(1/Infinity); 39.152 +numberEqualButNotStrictlyEqualToZeroObjects(false); 39.153 + 39.154 +function numberEqualButNotStrictlyEqualToObjectEquivalent(num) { 39.155 + var str = String(num); 39.156 + objectEqualButNotStrictlyEqual(num, str); 39.157 + objectEqualButNotStrictlyEqual(num, { valueOf: function() { return str }}); 39.158 + objectEqualButNotStrictlyEqual(num, { toString: function() { return str }}); 39.159 + objectEqualButNotStrictlyEqual(num, { valueOf: function() { return num }}); 39.160 + objectEqualButNotStrictlyEqual(num, { toString: function() { return num }}); 39.161 +} 39.162 + 39.163 +numberEqualButNotStrictlyEqualToObjectEquivalent(1); 39.164 +numberEqualButNotStrictlyEqualToObjectEquivalent(4294967296); 39.165 +numberEqualButNotStrictlyEqualToObjectEquivalent(1.2); 39.166 +numberEqualButNotStrictlyEqualToObjectEquivalent(Infinity); 39.167 +numberEqualButNotStrictlyEqualToObjectEquivalent(-Infinity); 39.168 +numberEqualButNotStrictlyEqualToObjectEquivalent(1/Infinity); 39.169 +numberEqualButNotStrictlyEqualToObjectEquivalent(0); 39.170 +numberEqualButNotStrictlyEqualToObjectEquivalent(-0); 39.171 + 39.172 +STRICT_EQ(1, new java.lang.Integer(1)); 39.173 +STRICT_EQ(1, new java.lang.Double(1)); 39.174 +STRICT_EQ(1.2, new java.lang.Double(1.2)); 39.175 + 39.176 +function LE(x, y) { 39.177 + // Exercise normal evaluation 39.178 + Assert.assertTrue(x <= y); 39.179 + Assert.assertTrue(y >= x); 39.180 + Assert.assertFalse(x > y); 39.181 + Assert.assertFalse(x < y); 39.182 + // Exercise the branch optimizer 39.183 + if (x <= y) { nop(); } else { Assert.fail(); } 39.184 + if (y >= x) { nop(); } else { Assert.fail(); } 39.185 + if (x > y) { Assert.fail(); } else { nop(); } 39.186 + if (y < x) { Assert.fail(); } else { nop(); } 39.187 +} 39.188 + 39.189 +function mutuallyLessThanOrEqual(x, y) { 39.190 + LE(x, y); 39.191 + LE(y, x); 39.192 +} 39.193 + 39.194 +mutuallyLessThanOrEqual(0, null); 39.195 +mutuallyLessThanOrEqual(false, null); 39.196 +mutuallyLessThanOrEqual(1/Infinity, null); 39.197 + 39.198 +function mutuallyLessThanEqualToObjectWithValue(num, val) { 39.199 + mutuallyLessThanOrEqual(num, { valueOf: function() { return val } }); 39.200 + mutuallyLessThanOrEqual(num, { toString: function() { return val } }); 39.201 +} 39.202 + 39.203 +mutuallyLessThanEqualToObjectWithValue(false, 0); 39.204 +mutuallyLessThanEqualToObjectWithValue(false, ""); 39.205 + 39.206 +mutuallyLessThanEqualToObjectWithValue(true, 1); 39.207 +mutuallyLessThanEqualToObjectWithValue(true, "1"); 39.208 + 39.209 +function lessThanEqualToObjectEquivalent(num) { 39.210 + var str = String(num); 39.211 + mutuallyLessThanOrEqual(num, str); 39.212 + mutuallyLessThanEqualToObjectWithValue(num, num); 39.213 + mutuallyLessThanEqualToObjectWithValue(num, str); 39.214 +} 39.215 + 39.216 +lessThanEqualToObjectEquivalent(1); 39.217 +lessThanEqualToObjectEquivalent(4294967296); 39.218 +lessThanEqualToObjectEquivalent(1.2); 39.219 +lessThanEqualToObjectEquivalent(Infinity); 39.220 +lessThanEqualToObjectEquivalent(-Infinity); 39.221 +lessThanEqualToObjectEquivalent(1/Infinity); 39.222 +lessThanEqualToObjectEquivalent(0); 39.223 +lessThanEqualToObjectEquivalent(-0); 39.224 + 39.225 +function INCOMPARABLE(x, y) { 39.226 + // Exercise normal evaluation 39.227 + Assert.assertFalse(x < y); 39.228 + Assert.assertFalse(x > y); 39.229 + Assert.assertFalse(x <= y); 39.230 + Assert.assertFalse(x >= y); 39.231 + Assert.assertFalse(y < x); 39.232 + Assert.assertFalse(y > x); 39.233 + Assert.assertFalse(y <= x); 39.234 + Assert.assertFalse(y >= x); 39.235 + // Exercise the branch optimizer 39.236 + if (x < y) { Assert.fail(); } else { nop(); } 39.237 + if (x > y) { Assert.fail(); } else { nop(); } 39.238 + if (x <= y) { Assert.fail(); } else { nop(); } 39.239 + if (x >= y) { Assert.fail(); } else { nop(); } 39.240 + if (y < x) { Assert.fail(); } else { nop(); } 39.241 + if (y > x) { Assert.fail(); } else { nop(); } 39.242 + if (y <= x) { Assert.fail(); } else { nop(); } 39.243 + if (y >= x) { Assert.fail(); } else { nop(); } 39.244 +} 39.245 + 39.246 +function isIncomparable(value) { 39.247 + cmpToAnyNumber(INCOMPARABLE, value); 39.248 +} 39.249 + 39.250 +isIncomparable(void 0); 39.251 +isIncomparable({ valueOf: function() { return NaN }}); 39.252 +isIncomparable({ toString: function() { return NaN }}); 39.253 + 39.254 +// Force ScriptRuntime.LT(Object, Object) etc. comparisons 39.255 +function cmpObj(fn, x, y) { 39.256 + fn({valueOf: function() { return x }}, {valueOf: function() { return y }}); 39.257 +} 39.258 + 39.259 +function LT(x, y) { 39.260 + Assert.assertTrue(x < y); 39.261 + Assert.assertTrue(y > x); 39.262 + Assert.assertFalse(x >= y); 39.263 + Assert.assertFalse(y <= x); 39.264 +} 39.265 + 39.266 +cmpObj(LT, 1, 2); 39.267 +cmpObj(LT, 1, "2"); 39.268 +cmpObj(LT, "1", 2); 39.269 +cmpObj(LT, "a", "b"); 39.270 +cmpObj(LT, -Infinity, 0); 39.271 +cmpObj(LT, 0, Infinity); 39.272 +cmpObj(LT, -Infinity, Infinity); 39.273 +cmpObj(INCOMPARABLE, 1, NaN); 39.274 +cmpObj(INCOMPARABLE, NaN, NaN); 39.275 +cmpObj(INCOMPARABLE, "boo", NaN); 39.276 +cmpObj(INCOMPARABLE, 1, "boo"); // boo number value will be NaN 39.277 + 39.278 +// Test that a comparison call site can deoptimize from (int, int) to (object, object) 39.279 +(function(){ 39.280 + var x = [1, 2, "a"]; 39.281 + var y = [2, "3", "b"]; 39.282 + for(var i = 0; i < 3; ++i) { 39.283 + Assert.assertTrue(x[i] < y[i]); 39.284 + } 39.285 +})();
40.1 --- a/test/script/basic/JDK-8055762.js Wed Mar 11 14:11:06 2015 -0700 40.2 +++ b/test/script/basic/JDK-8055762.js Thu Mar 12 13:45:00 2015 -0700 40.3 @@ -74,9 +74,12 @@ 40.4 } 40.5 }; 40.6 40.7 + var a = "a"; 40.8 print(obj["foo"]); 40.9 + print(obj[a + "bc"]); 40.10 print(obj[2]); 40.11 obj.bar = 23; 40.12 + obj[a + "bc"] = 23; 40.13 obj[3] = 23; 40.14 obj.func("hello"); 40.15 }
41.1 --- a/test/script/basic/JDK-8055762.js.EXPECTED Wed Mar 11 14:11:06 2015 -0700 41.2 +++ b/test/script/basic/JDK-8055762.js.EXPECTED Thu Mar 12 13:45:00 2015 -0700 41.3 @@ -1,5 +1,7 @@ 41.4 FOO 41.5 +ABC 41.6 0 41.7 bar set to 23 41.8 +abc set to 23 41.9 [3] set to 23 41.10 func called with hello
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 42.2 +++ b/test/script/basic/JDK-8072426.js Thu Mar 12 13:45:00 2015 -0700 42.3 @@ -0,0 +1,164 @@ 42.4 +/* 42.5 + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. 42.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 42.7 + * 42.8 + * This code is free software; you can redistribute it and/or modify it 42.9 + * under the terms of the GNU General Public License version 2 only, as 42.10 + * published by the Free Software Foundation. 42.11 + * 42.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 42.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 42.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 42.15 + * version 2 for more details (a copy is included in the LICENSE file that 42.16 + * accompanied this code). 42.17 + * 42.18 + * You should have received a copy of the GNU General Public License version 42.19 + * 2 along with this work; if not, write to the Free Software Foundation, 42.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 42.21 + * 42.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 42.23 + * or visit www.oracle.com if you need additional information or have any 42.24 + * questions. 42.25 + */ 42.26 + 42.27 +/** 42.28 + * JDK-8072426: Can't compare Java objects to strings or numbers 42.29 + * 42.30 + * @test 42.31 + * @run 42.32 + */ 42.33 + 42.34 +Assert.assertTrue(java.math.RoundingMode.UP == "UP"); 42.35 + 42.36 +var JSObject = Java.type("jdk.nashorn.api.scripting.JSObject"); 42.37 + 42.38 +// Adds an "isFunction" member to the JSObject that returns the specified value 42.39 +function addIsFunction(isFunction, obj) { 42.40 + obj.isFunction = function() { 42.41 + return isFunction; 42.42 + }; 42.43 + return obj; 42.44 +} 42.45 + 42.46 +function makeJSObjectConstantFunction(value) { 42.47 + return new JSObject(addIsFunction(true, { 42.48 + call: function() { 42.49 + return value; 42.50 + } 42.51 + })); 42.52 +} 42.53 + 42.54 +function makeJSObjectWithMembers(mapping) { 42.55 + return new JSObject({ 42.56 + getMember: function(name) { 42.57 + Assert.assertTrue(mapping.hasOwnProperty(name)); 42.58 + return mapping[name]; 42.59 + }, 42.60 + toNumber: function() { 42.61 + // toNumber no longer invoked 42.62 + Assert.fail(); 42.63 + } 42.64 + }); 42.65 +} 42.66 + 42.67 +// Test JSObjectLinker toInt32/toLong/toNumber 42.68 +function testNumericJSObject(kind, value) { 42.69 + var obj = makeJSObjectWithMembers({ 42.70 + valueOf: makeJSObjectConstantFunction(value) 42.71 + }); 42.72 + 42.73 + if (kind === "double") { 42.74 + // There's no assertEquals(double actual, double expected). There's only 42.75 + // assertEquals(double actual, double expected, double delta). 42.76 + Assert["assertEquals(double,double,double)"](value, obj, 0); 42.77 + } else { 42.78 + Assert["assertEquals(" + kind + ", " + kind + ")"](value, obj); 42.79 + } 42.80 + Assert.assertTrue(value == Number(obj)); 42.81 +} 42.82 +testNumericJSObject("int", 42); 42.83 +testNumericJSObject("long", 4294967296); 42.84 +testNumericJSObject("double", 1.2); 42.85 + 42.86 +// Test fallback from toNumber to toString for numeric conversion when toNumber doesn't exist 42.87 +(function() { 42.88 + var obj = makeJSObjectWithMembers({ 42.89 + valueOf: null, // Explicitly no valueOf 42.90 + toString: makeJSObjectConstantFunction("123") 42.91 + }); 42.92 + Assert["assertEquals(int,int)"](123, obj); 42.93 +})(); 42.94 + 42.95 +// Test fallback from toNumber to toString for numeric conversion when toNumber isn't a callable 42.96 +(function() { 42.97 + var obj = makeJSObjectWithMembers({ 42.98 + valueOf: new JSObject(addIsFunction(false, {})), 42.99 + toString: makeJSObjectConstantFunction("124") 42.100 + }); 42.101 + Assert["assertEquals(int,int)"](124, obj); 42.102 +})(); 42.103 + 42.104 +// Test fallback from toNumber to toString for numeric conversion when toNumber returns a non-primitive 42.105 +(function() { 42.106 + var obj = makeJSObjectWithMembers({ 42.107 + valueOf: makeJSObjectConstantFunction({}), 42.108 + toString: makeJSObjectConstantFunction("125") 42.109 + }); 42.110 + Assert["assertEquals(int,int)"](125, obj); 42.111 +})(); 42.112 + 42.113 +// Test TypeError from toNumber to toString when both return a non-primitive 42.114 +(function() { 42.115 + var obj = makeJSObjectWithMembers({ 42.116 + valueOf: makeJSObjectConstantFunction({}), 42.117 + toString: makeJSObjectConstantFunction({}) 42.118 + }); 42.119 + try { 42.120 + Number(obj); 42.121 + Assert.fail(); // must throw 42.122 + } catch(e) { 42.123 + Assert.assertTrue(e instanceof TypeError); 42.124 + } 42.125 +})(); 42.126 + 42.127 +// Test toString for string conversion 42.128 +(function() { 42.129 + var obj = makeJSObjectWithMembers({ 42.130 + toString: makeJSObjectConstantFunction("Hello") 42.131 + }); 42.132 + Assert.assertTrue("Hello" === String(obj)); 42.133 + Assert["assertEquals(String,String)"]("Hello", obj); 42.134 +})(); 42.135 + 42.136 +// Test fallback from toString to valueOf for string conversion when toString doesn't exist 42.137 +(function() { 42.138 + var obj = makeJSObjectWithMembers({ 42.139 + toString: null, 42.140 + valueOf: makeJSObjectConstantFunction("Hello1") 42.141 + }); 42.142 + Assert.assertTrue("Hello1" === String(obj)); 42.143 + Assert["assertEquals(String,String)"]("Hello1", obj); 42.144 +})(); 42.145 + 42.146 +// Test fallback from toString to valueOf for string conversion when toString is not callable 42.147 +(function() { 42.148 + var obj = makeJSObjectWithMembers({ 42.149 + toString: new JSObject(addIsFunction(false, {})), 42.150 + valueOf: makeJSObjectConstantFunction("Hello2") 42.151 + }); 42.152 + Assert["assertEquals(String,String)"]("Hello2", obj); 42.153 +})(); 42.154 + 42.155 +// Test fallback from toString to valueOf for string conversion when toString returns non-primitive 42.156 +(function() { 42.157 + var obj = makeJSObjectWithMembers({ 42.158 + toString: makeJSObjectConstantFunction({}), 42.159 + valueOf: makeJSObjectConstantFunction("Hello3") 42.160 + }); 42.161 + Assert["assertEquals(String,String)"]("Hello3", obj); 42.162 +})(); 42.163 + 42.164 +// Test toBoolean for JSObject 42.165 +(function() { 42.166 + Assert["assertEquals(boolean,boolean)"](true, new JSObject({})); 42.167 +})();
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 43.2 +++ b/test/script/basic/JDK-8074545.js Thu Mar 12 13:45:00 2015 -0700 43.3 @@ -0,0 +1,1038 @@ 43.4 +/* 43.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 43.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 43.7 + * 43.8 + * This code is free software; you can redistribute it and/or modify it 43.9 + * under the terms of the GNU General Public License version 2 only, as 43.10 + * published by the Free Software Foundation. 43.11 + * 43.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 43.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 43.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 43.15 + * version 2 for more details (a copy is included in the LICENSE file that 43.16 + * accompanied this code). 43.17 + * 43.18 + * You should have received a copy of the GNU General Public License version 43.19 + * 2 along with this work; if not, write to the Free Software Foundation, 43.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 43.21 + * 43.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 43.23 + * or visit www.oracle.com if you need additional information or have any 43.24 + * questions. 43.25 + */ 43.26 + 43.27 +/** 43.28 + * JDK-8074545: Undefined object values in object literals with spill properties 43.29 + * 43.30 + * @test 43.31 + * @run 43.32 + */ 43.33 + 43.34 +var obj = { 43.35 + "p0": { "x" : 0 }, 43.36 + "p1": { "x" : 1 }, 43.37 + "p2": { "x" : 2 }, 43.38 + "p3": { "x" : 3 }, 43.39 + "p4": { "x" : 4 }, 43.40 + "p5": { "x" : 5 }, 43.41 + "p6": { "x" : 6 }, 43.42 + "p7": { "x" : 7 }, 43.43 + "p8": { "x" : 8 }, 43.44 + "p9": { "x" : 9 }, 43.45 + "p10": { "x" : 10 }, 43.46 + "p11": { "x" : 11 }, 43.47 + "p12": { "x" : 12 }, 43.48 + "p13": { "x" : 13 }, 43.49 + "p14": { "x" : 14 }, 43.50 + "p15": { "x" : 15 }, 43.51 + "p16": { "x" : 16 }, 43.52 + "p17": { "x" : 17 }, 43.53 + "p18": { "x" : 18 }, 43.54 + "p19": { "x" : 19 }, 43.55 + "p20": { "x" : 20 }, 43.56 + "p21": { "x" : 21 }, 43.57 + "p22": { "x" : 22 }, 43.58 + "p23": { "x" : 23 }, 43.59 + "p24": { "x" : 24 }, 43.60 + "p25": { "x" : 25 }, 43.61 + "p26": { "x" : 26 }, 43.62 + "p27": { "x" : 27 }, 43.63 + "p28": { "x" : 28 }, 43.64 + "p29": { "x" : 29 }, 43.65 + "p30": { "x" : 30 }, 43.66 + "p31": { "x" : 31 }, 43.67 + "p32": { "x" : 32 }, 43.68 + "p33": { "x" : 33 }, 43.69 + "p34": { "x" : 34 }, 43.70 + "p35": { "x" : 35 }, 43.71 + "p36": { "x" : 36 }, 43.72 + "p37": { "x" : 37 }, 43.73 + "p38": { "x" : 38 }, 43.74 + "p39": { "x" : 39 }, 43.75 + "p40": { "x" : 40 }, 43.76 + "p41": { "x" : 41 }, 43.77 + "p42": { "x" : 42 }, 43.78 + "p43": { "x" : 43 }, 43.79 + "p44": { "x" : 44 }, 43.80 + "p45": { "x" : 45 }, 43.81 + "p46": { "x" : 46 }, 43.82 + "p47": { "x" : 47 }, 43.83 + "p48": { "x" : 48 }, 43.84 + "p49": { "x" : 49 }, 43.85 + "p50": { "x" : 50 }, 43.86 + "p51": { "x" : 51 }, 43.87 + "p52": { "x" : 52 }, 43.88 + "p53": { "x" : 53 }, 43.89 + "p54": { "x" : 54 }, 43.90 + "p55": { "x" : 55 }, 43.91 + "p56": { "x" : 56 }, 43.92 + "p57": { "x" : 57 }, 43.93 + "p58": { "x" : 58 }, 43.94 + "p59": { "x" : 59 }, 43.95 + "p60": { "x" : 60 }, 43.96 + "p61": { "x" : 61 }, 43.97 + "p62": { "x" : 62 }, 43.98 + "p63": { "x" : 63 }, 43.99 + "p64": { "x" : 64 }, 43.100 + "p65": { "x" : 65 }, 43.101 + "p66": { "x" : 66 }, 43.102 + "p67": { "x" : 67 }, 43.103 + "p68": { "x" : 68 }, 43.104 + "p69": { "x" : 69 }, 43.105 + "p70": { "x" : 70 }, 43.106 + "p71": { "x" : 71 }, 43.107 + "p72": { "x" : 72 }, 43.108 + "p73": { "x" : 73 }, 43.109 + "p74": { "x" : 74 }, 43.110 + "p75": { "x" : 75 }, 43.111 + "p76": { "x" : 76 }, 43.112 + "p77": { "x" : 77 }, 43.113 + "p78": { "x" : 78 }, 43.114 + "p79": { "x" : 79 }, 43.115 + "p80": { "x" : 80 }, 43.116 + "p81": { "x" : 81 }, 43.117 + "p82": { "x" : 82 }, 43.118 + "p83": { "x" : 83 }, 43.119 + "p84": { "x" : 84 }, 43.120 + "p85": { "x" : 85 }, 43.121 + "p86": { "x" : 86 }, 43.122 + "p87": { "x" : 87 }, 43.123 + "p88": { "x" : 88 }, 43.124 + "p89": { "x" : 89 }, 43.125 + "p90": { "x" : 90 }, 43.126 + "p91": { "x" : 91 }, 43.127 + "p92": { "x" : 92 }, 43.128 + "p93": { "x" : 93 }, 43.129 + "p94": { "x" : 94 }, 43.130 + "p95": { "x" : 95 }, 43.131 + "p96": { "x" : 96 }, 43.132 + "p97": { "x" : 97 }, 43.133 + "p98": { "x" : 98 }, 43.134 + "p99": { "x" : 99 }, 43.135 + "p100": { "x" : 100 }, 43.136 + "p101": { "x" : 101 }, 43.137 + "p102": { "x" : 102 }, 43.138 + "p103": { "x" : 103 }, 43.139 + "p104": { "x" : 104 }, 43.140 + "p105": { "x" : 105 }, 43.141 + "p106": { "x" : 106 }, 43.142 + "p107": { "x" : 107 }, 43.143 + "p108": { "x" : 108 }, 43.144 + "p109": { "x" : 109 }, 43.145 + "p110": { "x" : 110 }, 43.146 + "p111": { "x" : 111 }, 43.147 + "p112": { "x" : 112 }, 43.148 + "p113": { "x" : 113 }, 43.149 + "p114": { "x" : 114 }, 43.150 + "p115": { "x" : 115 }, 43.151 + "p116": { "x" : 116 }, 43.152 + "p117": { "x" : 117 }, 43.153 + "p118": { "x" : 118 }, 43.154 + "p119": { "x" : 119 }, 43.155 + "p120": { "x" : 120 }, 43.156 + "p121": { "x" : 121 }, 43.157 + "p122": { "x" : 122 }, 43.158 + "p123": { "x" : 123 }, 43.159 + "p124": { "x" : 124 }, 43.160 + "p125": { "x" : 125 }, 43.161 + "p126": { "x" : 126 }, 43.162 + "p127": { "x" : 127 }, 43.163 + "p128": { "x" : 128 }, 43.164 + "p129": { "x" : 129 }, 43.165 + "p130": { "x" : 130 }, 43.166 + "p131": { "x" : 131 }, 43.167 + "p132": { "x" : 132 }, 43.168 + "p133": { "x" : 133 }, 43.169 + "p134": { "x" : 134 }, 43.170 + "p135": { "x" : 135 }, 43.171 + "p136": { "x" : 136 }, 43.172 + "p137": { "x" : 137 }, 43.173 + "p138": { "x" : 138 }, 43.174 + "p139": { "x" : 139 }, 43.175 + "p140": { "x" : 140 }, 43.176 + "p141": { "x" : 141 }, 43.177 + "p142": { "x" : 142 }, 43.178 + "p143": { "x" : 143 }, 43.179 + "p144": { "x" : 144 }, 43.180 + "p145": { "x" : 145 }, 43.181 + "p146": { "x" : 146 }, 43.182 + "p147": { "x" : 147 }, 43.183 + "p148": { "x" : 148 }, 43.184 + "p149": { "x" : 149 }, 43.185 + "p150": { "x" : 150 }, 43.186 + "p151": { "x" : 151 }, 43.187 + "p152": { "x" : 152 }, 43.188 + "p153": { "x" : 153 }, 43.189 + "p154": { "x" : 154 }, 43.190 + "p155": { "x" : 155 }, 43.191 + "p156": { "x" : 156 }, 43.192 + "p157": { "x" : 157 }, 43.193 + "p158": { "x" : 158 }, 43.194 + "p159": { "x" : 159 }, 43.195 + "p160": { "x" : 160 }, 43.196 + "p161": { "x" : 161 }, 43.197 + "p162": { "x" : 162 }, 43.198 + "p163": { "x" : 163 }, 43.199 + "p164": { "x" : 164 }, 43.200 + "p165": { "x" : 165 }, 43.201 + "p166": { "x" : 166 }, 43.202 + "p167": { "x" : 167 }, 43.203 + "p168": { "x" : 168 }, 43.204 + "p169": { "x" : 169 }, 43.205 + "p170": { "x" : 170 }, 43.206 + "p171": { "x" : 171 }, 43.207 + "p172": { "x" : 172 }, 43.208 + "p173": { "x" : 173 }, 43.209 + "p174": { "x" : 174 }, 43.210 + "p175": { "x" : 175 }, 43.211 + "p176": { "x" : 176 }, 43.212 + "p177": { "x" : 177 }, 43.213 + "p178": { "x" : 178 }, 43.214 + "p179": { "x" : 179 }, 43.215 + "p180": { "x" : 180 }, 43.216 + "p181": { "x" : 181 }, 43.217 + "p182": { "x" : 182 }, 43.218 + "p183": { "x" : 183 }, 43.219 + "p184": { "x" : 184 }, 43.220 + "p185": { "x" : 185 }, 43.221 + "p186": { "x" : 186 }, 43.222 + "p187": { "x" : 187 }, 43.223 + "p188": { "x" : 188 }, 43.224 + "p189": { "x" : 189 }, 43.225 + "p190": { "x" : 190 }, 43.226 + "p191": { "x" : 191 }, 43.227 + "p192": { "x" : 192 }, 43.228 + "p193": { "x" : 193 }, 43.229 + "p194": { "x" : 194 }, 43.230 + "p195": { "x" : 195 }, 43.231 + "p196": { "x" : 196 }, 43.232 + "p197": { "x" : 197 }, 43.233 + "p198": { "x" : 198 }, 43.234 + "p199": { "x" : 199 }, 43.235 + "p200": { "x" : 200 }, 43.236 + "p201": { "x" : 201 }, 43.237 + "p202": { "x" : 202 }, 43.238 + "p203": { "x" : 203 }, 43.239 + "p204": { "x" : 204 }, 43.240 + "p205": { "x" : 205 }, 43.241 + "p206": { "x" : 206 }, 43.242 + "p207": { "x" : 207 }, 43.243 + "p208": { "x" : 208 }, 43.244 + "p209": { "x" : 209 }, 43.245 + "p210": { "x" : 210 }, 43.246 + "p211": { "x" : 211 }, 43.247 + "p212": { "x" : 212 }, 43.248 + "p213": { "x" : 213 }, 43.249 + "p214": { "x" : 214 }, 43.250 + "p215": { "x" : 215 }, 43.251 + "p216": { "x" : 216 }, 43.252 + "p217": { "x" : 217 }, 43.253 + "p218": { "x" : 218 }, 43.254 + "p219": { "x" : 219 }, 43.255 + "p220": { "x" : 220 }, 43.256 + "p221": { "x" : 221 }, 43.257 + "p222": { "x" : 222 }, 43.258 + "p223": { "x" : 223 }, 43.259 + "p224": { "x" : 224 }, 43.260 + "p225": { "x" : 225 }, 43.261 + "p226": { "x" : 226 }, 43.262 + "p227": { "x" : 227 }, 43.263 + "p228": { "x" : 228 }, 43.264 + "p229": { "x" : 229 }, 43.265 + "p230": { "x" : 230 }, 43.266 + "p231": { "x" : 231 }, 43.267 + "p232": { "x" : 232 }, 43.268 + "p233": { "x" : 233 }, 43.269 + "p234": { "x" : 234 }, 43.270 + "p235": { "x" : 235 }, 43.271 + "p236": { "x" : 236 }, 43.272 + "p237": { "x" : 237 }, 43.273 + "p238": { "x" : 238 }, 43.274 + "p239": { "x" : 239 }, 43.275 + "p240": { "x" : 240 }, 43.276 + "p241": { "x" : 241 }, 43.277 + "p242": { "x" : 242 }, 43.278 + "p243": { "x" : 243 }, 43.279 + "p244": { "x" : 244 }, 43.280 + "p245": { "x" : 245 }, 43.281 + "p246": { "x" : 246 }, 43.282 + "p247": { "x" : 247 }, 43.283 + "p248": { "x" : 248 }, 43.284 + "p249": { "x" : 249 }, 43.285 + "p250": { "x" : 250 }, 43.286 + "p251": { "x" : 251 }, 43.287 + "p252": { "x" : 252 }, 43.288 + "p253": { "x" : 253 }, 43.289 + "p254": { "x" : 254 }, 43.290 + "p255": { "x" : 255 }, 43.291 + "p256": { "x" : 256 }, 43.292 + "p257": { "x" : 257 }, 43.293 + "p258": { "x" : 258 }, 43.294 + "p259": { "x" : 259 }, 43.295 + "p260": { "x" : 260 }, 43.296 + "p261": { "x" : 261 }, 43.297 + "p262": { "x" : 262 }, 43.298 + "p263": { "x" : 263 }, 43.299 + "p264": { "x" : 264 }, 43.300 + "p265": { "x" : 265 }, 43.301 + "p266": { "x" : 266 }, 43.302 + "p267": { "x" : 267 }, 43.303 + "p268": { "x" : 268 }, 43.304 + "p269": { "x" : 269 }, 43.305 + "p270": { "x" : 270 }, 43.306 + "p271": { "x" : 271 }, 43.307 + "p272": { "x" : 272 }, 43.308 + "p273": { "x" : 273 }, 43.309 + "p274": { "x" : 274 }, 43.310 + "p275": { "x" : 275 }, 43.311 + "p276": { "x" : 276 }, 43.312 + "p277": { "x" : 277 }, 43.313 + "p278": { "x" : 278 }, 43.314 + "p279": { "x" : 279 }, 43.315 + "p280": { "x" : 280 }, 43.316 + "p281": { "x" : 281 }, 43.317 + "p282": { "x" : 282 }, 43.318 + "p283": { "x" : 283 }, 43.319 + "p284": { "x" : 284 }, 43.320 + "p285": { "x" : 285 }, 43.321 + "p286": { "x" : 286 }, 43.322 + "p287": { "x" : 287 }, 43.323 + "p288": { "x" : 288 }, 43.324 + "p289": { "x" : 289 }, 43.325 + "p290": { "x" : 290 }, 43.326 + "p291": { "x" : 291 }, 43.327 + "p292": { "x" : 292 }, 43.328 + "p293": { "x" : 293 }, 43.329 + "p294": { "x" : 294 }, 43.330 + "p295": { "x" : 295 }, 43.331 + "p296": { "x" : 296 }, 43.332 + "p297": { "x" : 297 }, 43.333 + "p298": { "x" : 298 }, 43.334 + "p299": { "x" : 299 }, 43.335 + "p300": { "x" : 300 }, 43.336 + "p301": { "x" : 301 }, 43.337 + "p302": { "x" : 302 }, 43.338 + "p303": { "x" : 303 }, 43.339 + "p304": { "x" : 304 }, 43.340 + "p305": { "x" : 305 }, 43.341 + "p306": { "x" : 306 }, 43.342 + "p307": { "x" : 307 }, 43.343 + "p308": { "x" : 308 }, 43.344 + "p309": { "x" : 309 }, 43.345 + "p310": { "x" : 310 }, 43.346 + "p311": { "x" : 311 }, 43.347 + "p312": { "x" : 312 }, 43.348 + "p313": { "x" : 313 }, 43.349 + "p314": { "x" : 314 }, 43.350 + "p315": { "x" : 315 }, 43.351 + "p316": { "x" : 316 }, 43.352 + "p317": { "x" : 317 }, 43.353 + "p318": { "x" : 318 }, 43.354 + "p319": { "x" : 319 }, 43.355 + "p320": { "x" : 320 }, 43.356 + "p321": { "x" : 321 }, 43.357 + "p322": { "x" : 322 }, 43.358 + "p323": { "x" : 323 }, 43.359 + "p324": { "x" : 324 }, 43.360 + "p325": { "x" : 325 }, 43.361 + "p326": { "x" : 326 }, 43.362 + "p327": { "x" : 327 }, 43.363 + "p328": { "x" : 328 }, 43.364 + "p329": { "x" : 329 }, 43.365 + "p330": { "x" : 330 }, 43.366 + "p331": { "x" : 331 }, 43.367 + "p332": { "x" : 332 }, 43.368 + "p333": { "x" : 333 }, 43.369 + "p334": { "x" : 334 }, 43.370 + "p335": { "x" : 335 }, 43.371 + "p336": { "x" : 336 }, 43.372 + "p337": { "x" : 337 }, 43.373 + "p338": { "x" : 338 }, 43.374 + "p339": { "x" : 339 }, 43.375 + "p340": { "x" : 340 }, 43.376 + "p341": { "x" : 341 }, 43.377 + "p342": { "x" : 342 }, 43.378 + "p343": { "x" : 343 }, 43.379 + "p344": { "x" : 344 }, 43.380 + "p345": { "x" : 345 }, 43.381 + "p346": { "x" : 346 }, 43.382 + "p347": { "x" : 347 }, 43.383 + "p348": { "x" : 348 }, 43.384 + "p349": { "x" : 349 }, 43.385 + "p350": { "x" : 350 }, 43.386 + "p351": { "x" : 351 }, 43.387 + "p352": { "x" : 352 }, 43.388 + "p353": { "x" : 353 }, 43.389 + "p354": { "x" : 354 }, 43.390 + "p355": { "x" : 355 }, 43.391 + "p356": { "x" : 356 }, 43.392 + "p357": { "x" : 357 }, 43.393 + "p358": { "x" : 358 }, 43.394 + "p359": { "x" : 359 }, 43.395 + "p360": { "x" : 360 }, 43.396 + "p361": { "x" : 361 }, 43.397 + "p362": { "x" : 362 }, 43.398 + "p363": { "x" : 363 }, 43.399 + "p364": { "x" : 364 }, 43.400 + "p365": { "x" : 365 }, 43.401 + "p366": { "x" : 366 }, 43.402 + "p367": { "x" : 367 }, 43.403 + "p368": { "x" : 368 }, 43.404 + "p369": { "x" : 369 }, 43.405 + "p370": { "x" : 370 }, 43.406 + "p371": { "x" : 371 }, 43.407 + "p372": { "x" : 372 }, 43.408 + "p373": { "x" : 373 }, 43.409 + "p374": { "x" : 374 }, 43.410 + "p375": { "x" : 375 }, 43.411 + "p376": { "x" : 376 }, 43.412 + "p377": { "x" : 377 }, 43.413 + "p378": { "x" : 378 }, 43.414 + "p379": { "x" : 379 }, 43.415 + "p380": { "x" : 380 }, 43.416 + "p381": { "x" : 381 }, 43.417 + "p382": { "x" : 382 }, 43.418 + "p383": { "x" : 383 }, 43.419 + "p384": { "x" : 384 }, 43.420 + "p385": { "x" : 385 }, 43.421 + "p386": { "x" : 386 }, 43.422 + "p387": { "x" : 387 }, 43.423 + "p388": { "x" : 388 }, 43.424 + "p389": { "x" : 389 }, 43.425 + "p390": { "x" : 390 }, 43.426 + "p391": { "x" : 391 }, 43.427 + "p392": { "x" : 392 }, 43.428 + "p393": { "x" : 393 }, 43.429 + "p394": { "x" : 394 }, 43.430 + "p395": { "x" : 395 }, 43.431 + "p396": { "x" : 396 }, 43.432 + "p397": { "x" : 397 }, 43.433 + "p398": { "x" : 398 }, 43.434 + "p399": { "x" : 399 }, 43.435 + "p400": { "x" : 400 }, 43.436 + "p401": { "x" : 401 }, 43.437 + "p402": { "x" : 402 }, 43.438 + "p403": { "x" : 403 }, 43.439 + "p404": { "x" : 404 }, 43.440 + "p405": { "x" : 405 }, 43.441 + "p406": { "x" : 406 }, 43.442 + "p407": { "x" : 407 }, 43.443 + "p408": { "x" : 408 }, 43.444 + "p409": { "x" : 409 }, 43.445 + "p410": { "x" : 410 }, 43.446 + "p411": { "x" : 411 }, 43.447 + "p412": { "x" : 412 }, 43.448 + "p413": { "x" : 413 }, 43.449 + "p414": { "x" : 414 }, 43.450 + "p415": { "x" : 415 }, 43.451 + "p416": { "x" : 416 }, 43.452 + "p417": { "x" : 417 }, 43.453 + "p418": { "x" : 418 }, 43.454 + "p419": { "x" : 419 }, 43.455 + "p420": { "x" : 420 }, 43.456 + "p421": { "x" : 421 }, 43.457 + "p422": { "x" : 422 }, 43.458 + "p423": { "x" : 423 }, 43.459 + "p424": { "x" : 424 }, 43.460 + "p425": { "x" : 425 }, 43.461 + "p426": { "x" : 426 }, 43.462 + "p427": { "x" : 427 }, 43.463 + "p428": { "x" : 428 }, 43.464 + "p429": { "x" : 429 }, 43.465 + "p430": { "x" : 430 }, 43.466 + "p431": { "x" : 431 }, 43.467 + "p432": { "x" : 432 }, 43.468 + "p433": { "x" : 433 }, 43.469 + "p434": { "x" : 434 }, 43.470 + "p435": { "x" : 435 }, 43.471 + "p436": { "x" : 436 }, 43.472 + "p437": { "x" : 437 }, 43.473 + "p438": { "x" : 438 }, 43.474 + "p439": { "x" : 439 }, 43.475 + "p440": { "x" : 440 }, 43.476 + "p441": { "x" : 441 }, 43.477 + "p442": { "x" : 442 }, 43.478 + "p443": { "x" : 443 }, 43.479 + "p444": { "x" : 444 }, 43.480 + "p445": { "x" : 445 }, 43.481 + "p446": { "x" : 446 }, 43.482 + "p447": { "x" : 447 }, 43.483 + "p448": { "x" : 448 }, 43.484 + "p449": { "x" : 449 }, 43.485 + "p450": { "x" : 450 }, 43.486 + "p451": { "x" : 451 }, 43.487 + "p452": { "x" : 452 }, 43.488 + "p453": { "x" : 453 }, 43.489 + "p454": { "x" : 454 }, 43.490 + "p455": { "x" : 455 }, 43.491 + "p456": { "x" : 456 }, 43.492 + "p457": { "x" : 457 }, 43.493 + "p458": { "x" : 458 }, 43.494 + "p459": { "x" : 459 }, 43.495 + "p460": { "x" : 460 }, 43.496 + "p461": { "x" : 461 }, 43.497 + "p462": { "x" : 462 }, 43.498 + "p463": { "x" : 463 }, 43.499 + "p464": { "x" : 464 }, 43.500 + "p465": { "x" : 465 }, 43.501 + "p466": { "x" : 466 }, 43.502 + "p467": { "x" : 467 }, 43.503 + "p468": { "x" : 468 }, 43.504 + "p469": { "x" : 469 }, 43.505 + "p470": { "x" : 470 }, 43.506 + "p471": { "x" : 471 }, 43.507 + "p472": { "x" : 472 }, 43.508 + "p473": { "x" : 473 }, 43.509 + "p474": { "x" : 474 }, 43.510 + "p475": { "x" : 475 }, 43.511 + "p476": { "x" : 476 }, 43.512 + "p477": { "x" : 477 }, 43.513 + "p478": { "x" : 478 }, 43.514 + "p479": { "x" : 479 }, 43.515 + "p480": { "x" : 480 }, 43.516 + "p481": { "x" : 481 }, 43.517 + "p482": { "x" : 482 }, 43.518 + "p483": { "x" : 483 }, 43.519 + "p484": { "x" : 484 }, 43.520 + "p485": { "x" : 485 }, 43.521 + "p486": { "x" : 486 }, 43.522 + "p487": { "x" : 487 }, 43.523 + "p488": { "x" : 488 }, 43.524 + "p489": { "x" : 489 }, 43.525 + "p490": { "x" : 490 }, 43.526 + "p491": { "x" : 491 }, 43.527 + "p492": { "x" : 492 }, 43.528 + "p493": { "x" : 493 }, 43.529 + "p494": { "x" : 494 }, 43.530 + "p495": { "x" : 495 }, 43.531 + "p496": { "x" : 496 }, 43.532 + "p497": { "x" : 497 }, 43.533 + "p498": { "x" : 498 }, 43.534 + "p499": { "x" : 499 }, 43.535 + "p500": { "x" : 500 }, 43.536 + "p501": { "x" : 501 }, 43.537 + "p502": { "x" : 502 }, 43.538 + "p503": { "x" : 503 }, 43.539 + "p504": { "x" : 504 }, 43.540 + "p505": { "x" : 505 }, 43.541 + "p506": { "x" : 506 }, 43.542 + "p507": { "x" : 507 }, 43.543 + "p508": { "x" : 508 }, 43.544 + "p509": { "x" : 509 }, 43.545 + "p510": { "x" : 510 }, 43.546 + "p511": { "x" : 511 }, 43.547 + "p512": { "x" : 512 }, 43.548 + "p513": { "x" : 513 }, 43.549 + "p514": { "x" : 514 }, 43.550 + "p515": { "x" : 515 }, 43.551 + "p516": { "x" : 516 }, 43.552 + "p517": { "x" : 517 }, 43.553 + "p518": { "x" : 518 }, 43.554 + "p519": { "x" : 519 }, 43.555 + "p520": { "x" : 520 }, 43.556 + "p521": { "x" : 521 }, 43.557 + "p522": { "x" : 522 }, 43.558 + "p523": { "x" : 523 }, 43.559 + "p524": { "x" : 524 }, 43.560 + "p525": { "x" : 525 }, 43.561 + "p526": { "x" : 526 }, 43.562 + "p527": { "x" : 527 }, 43.563 + "p528": { "x" : 528 }, 43.564 + "p529": { "x" : 529 }, 43.565 + "p530": { "x" : 530 }, 43.566 + "p531": { "x" : 531 }, 43.567 + "p532": { "x" : 532 }, 43.568 + "p533": { "x" : 533 }, 43.569 + "p534": { "x" : 534 }, 43.570 + "p535": { "x" : 535 }, 43.571 + "p536": { "x" : 536 }, 43.572 + "p537": { "x" : 537 }, 43.573 + "p538": { "x" : 538 }, 43.574 + "p539": { "x" : 539 }, 43.575 + "p540": { "x" : 540 }, 43.576 + "p541": { "x" : 541 }, 43.577 + "p542": { "x" : 542 }, 43.578 + "p543": { "x" : 543 }, 43.579 + "p544": { "x" : 544 }, 43.580 + "p545": { "x" : 545 }, 43.581 + "p546": { "x" : 546 }, 43.582 + "p547": { "x" : 547 }, 43.583 + "p548": { "x" : 548 }, 43.584 + "p549": { "x" : 549 }, 43.585 + "p550": { "x" : 550 }, 43.586 + "p551": { "x" : 551 }, 43.587 + "p552": { "x" : 552 }, 43.588 + "p553": { "x" : 553 }, 43.589 + "p554": { "x" : 554 }, 43.590 + "p555": { "x" : 555 }, 43.591 + "p556": { "x" : 556 }, 43.592 + "p557": { "x" : 557 }, 43.593 + "p558": { "x" : 558 }, 43.594 + "p559": { "x" : 559 }, 43.595 + "p560": { "x" : 560 }, 43.596 + "p561": { "x" : 561 }, 43.597 + "p562": { "x" : 562 }, 43.598 + "p563": { "x" : 563 }, 43.599 + "p564": { "x" : 564 }, 43.600 + "p565": { "x" : 565 }, 43.601 + "p566": { "x" : 566 }, 43.602 + "p567": { "x" : 567 }, 43.603 + "p568": { "x" : 568 }, 43.604 + "p569": { "x" : 569 }, 43.605 + "p570": { "x" : 570 }, 43.606 + "p571": { "x" : 571 }, 43.607 + "p572": { "x" : 572 }, 43.608 + "p573": { "x" : 573 }, 43.609 + "p574": { "x" : 574 }, 43.610 + "p575": { "x" : 575 }, 43.611 + "p576": { "x" : 576 }, 43.612 + "p577": { "x" : 577 }, 43.613 + "p578": { "x" : 578 }, 43.614 + "p579": { "x" : 579 }, 43.615 + "p580": { "x" : 580 }, 43.616 + "p581": { "x" : 581 }, 43.617 + "p582": { "x" : 582 }, 43.618 + "p583": { "x" : 583 }, 43.619 + "p584": { "x" : 584 }, 43.620 + "p585": { "x" : 585 }, 43.621 + "p586": { "x" : 586 }, 43.622 + "p587": { "x" : 587 }, 43.623 + "p588": { "x" : 588 }, 43.624 + "p589": { "x" : 589 }, 43.625 + "p590": { "x" : 590 }, 43.626 + "p591": { "x" : 591 }, 43.627 + "p592": { "x" : 592 }, 43.628 + "p593": { "x" : 593 }, 43.629 + "p594": { "x" : 594 }, 43.630 + "p595": { "x" : 595 }, 43.631 + "p596": { "x" : 596 }, 43.632 + "p597": { "x" : 597 }, 43.633 + "p598": { "x" : 598 }, 43.634 + "p599": { "x" : 599 }, 43.635 + "p600": { "x" : 600 }, 43.636 + "p601": { "x" : 601 }, 43.637 + "p602": { "x" : 602 }, 43.638 + "p603": { "x" : 603 }, 43.639 + "p604": { "x" : 604 }, 43.640 + "p605": { "x" : 605 }, 43.641 + "p606": { "x" : 606 }, 43.642 + "p607": { "x" : 607 }, 43.643 + "p608": { "x" : 608 }, 43.644 + "p609": { "x" : 609 }, 43.645 + "p610": { "x" : 610 }, 43.646 + "p611": { "x" : 611 }, 43.647 + "p612": { "x" : 612 }, 43.648 + "p613": { "x" : 613 }, 43.649 + "p614": { "x" : 614 }, 43.650 + "p615": { "x" : 615 }, 43.651 + "p616": { "x" : 616 }, 43.652 + "p617": { "x" : 617 }, 43.653 + "p618": { "x" : 618 }, 43.654 + "p619": { "x" : 619 }, 43.655 + "p620": { "x" : 620 }, 43.656 + "p621": { "x" : 621 }, 43.657 + "p622": { "x" : 622 }, 43.658 + "p623": { "x" : 623 }, 43.659 + "p624": { "x" : 624 }, 43.660 + "p625": { "x" : 625 }, 43.661 + "p626": { "x" : 626 }, 43.662 + "p627": { "x" : 627 }, 43.663 + "p628": { "x" : 628 }, 43.664 + "p629": { "x" : 629 }, 43.665 + "p630": { "x" : 630 }, 43.666 + "p631": { "x" : 631 }, 43.667 + "p632": { "x" : 632 }, 43.668 + "p633": { "x" : 633 }, 43.669 + "p634": { "x" : 634 }, 43.670 + "p635": { "x" : 635 }, 43.671 + "p636": { "x" : 636 }, 43.672 + "p637": { "x" : 637 }, 43.673 + "p638": { "x" : 638 }, 43.674 + "p639": { "x" : 639 }, 43.675 + "p640": { "x" : 640 }, 43.676 + "p641": { "x" : 641 }, 43.677 + "p642": { "x" : 642 }, 43.678 + "p643": { "x" : 643 }, 43.679 + "p644": { "x" : 644 }, 43.680 + "p645": { "x" : 645 }, 43.681 + "p646": { "x" : 646 }, 43.682 + "p647": { "x" : 647 }, 43.683 + "p648": { "x" : 648 }, 43.684 + "p649": { "x" : 649 }, 43.685 + "p650": { "x" : 650 }, 43.686 + "p651": { "x" : 651 }, 43.687 + "p652": { "x" : 652 }, 43.688 + "p653": { "x" : 653 }, 43.689 + "p654": { "x" : 654 }, 43.690 + "p655": { "x" : 655 }, 43.691 + "p656": { "x" : 656 }, 43.692 + "p657": { "x" : 657 }, 43.693 + "p658": { "x" : 658 }, 43.694 + "p659": { "x" : 659 }, 43.695 + "p660": { "x" : 660 }, 43.696 + "p661": { "x" : 661 }, 43.697 + "p662": { "x" : 662 }, 43.698 + "p663": { "x" : 663 }, 43.699 + "p664": { "x" : 664 }, 43.700 + "p665": { "x" : 665 }, 43.701 + "p666": { "x" : 666 }, 43.702 + "p667": { "x" : 667 }, 43.703 + "p668": { "x" : 668 }, 43.704 + "p669": { "x" : 669 }, 43.705 + "p670": { "x" : 670 }, 43.706 + "p671": { "x" : 671 }, 43.707 + "p672": { "x" : 672 }, 43.708 + "p673": { "x" : 673 }, 43.709 + "p674": { "x" : 674 }, 43.710 + "p675": { "x" : 675 }, 43.711 + "p676": { "x" : 676 }, 43.712 + "p677": { "x" : 677 }, 43.713 + "p678": { "x" : 678 }, 43.714 + "p679": { "x" : 679 }, 43.715 + "p680": { "x" : 680 }, 43.716 + "p681": { "x" : 681 }, 43.717 + "p682": { "x" : 682 }, 43.718 + "p683": { "x" : 683 }, 43.719 + "p684": { "x" : 684 }, 43.720 + "p685": { "x" : 685 }, 43.721 + "p686": { "x" : 686 }, 43.722 + "p687": { "x" : 687 }, 43.723 + "p688": { "x" : 688 }, 43.724 + "p689": { "x" : 689 }, 43.725 + "p690": { "x" : 690 }, 43.726 + "p691": { "x" : 691 }, 43.727 + "p692": { "x" : 692 }, 43.728 + "p693": { "x" : 693 }, 43.729 + "p694": { "x" : 694 }, 43.730 + "p695": { "x" : 695 }, 43.731 + "p696": { "x" : 696 }, 43.732 + "p697": { "x" : 697 }, 43.733 + "p698": { "x" : 698 }, 43.734 + "p699": { "x" : 699 }, 43.735 + "p700": { "x" : 700 }, 43.736 + "p701": { "x" : 701 }, 43.737 + "p702": { "x" : 702 }, 43.738 + "p703": { "x" : 703 }, 43.739 + "p704": { "x" : 704 }, 43.740 + "p705": { "x" : 705 }, 43.741 + "p706": { "x" : 706 }, 43.742 + "p707": { "x" : 707 }, 43.743 + "p708": { "x" : 708 }, 43.744 + "p709": { "x" : 709 }, 43.745 + "p710": { "x" : 710 }, 43.746 + "p711": { "x" : 711 }, 43.747 + "p712": { "x" : 712 }, 43.748 + "p713": { "x" : 713 }, 43.749 + "p714": { "x" : 714 }, 43.750 + "p715": { "x" : 715 }, 43.751 + "p716": { "x" : 716 }, 43.752 + "p717": { "x" : 717 }, 43.753 + "p718": { "x" : 718 }, 43.754 + "p719": { "x" : 719 }, 43.755 + "p720": { "x" : 720 }, 43.756 + "p721": { "x" : 721 }, 43.757 + "p722": { "x" : 722 }, 43.758 + "p723": { "x" : 723 }, 43.759 + "p724": { "x" : 724 }, 43.760 + "p725": { "x" : 725 }, 43.761 + "p726": { "x" : 726 }, 43.762 + "p727": { "x" : 727 }, 43.763 + "p728": { "x" : 728 }, 43.764 + "p729": { "x" : 729 }, 43.765 + "p730": { "x" : 730 }, 43.766 + "p731": { "x" : 731 }, 43.767 + "p732": { "x" : 732 }, 43.768 + "p733": { "x" : 733 }, 43.769 + "p734": { "x" : 734 }, 43.770 + "p735": { "x" : 735 }, 43.771 + "p736": { "x" : 736 }, 43.772 + "p737": { "x" : 737 }, 43.773 + "p738": { "x" : 738 }, 43.774 + "p739": { "x" : 739 }, 43.775 + "p740": { "x" : 740 }, 43.776 + "p741": { "x" : 741 }, 43.777 + "p742": { "x" : 742 }, 43.778 + "p743": { "x" : 743 }, 43.779 + "p744": { "x" : 744 }, 43.780 + "p745": { "x" : 745 }, 43.781 + "p746": { "x" : 746 }, 43.782 + "p747": { "x" : 747 }, 43.783 + "p748": { "x" : 748 }, 43.784 + "p749": { "x" : 749 }, 43.785 + "p750": { "x" : 750 }, 43.786 + "p751": { "x" : 751 }, 43.787 + "p752": { "x" : 752 }, 43.788 + "p753": { "x" : 753 }, 43.789 + "p754": { "x" : 754 }, 43.790 + "p755": { "x" : 755 }, 43.791 + "p756": { "x" : 756 }, 43.792 + "p757": { "x" : 757 }, 43.793 + "p758": { "x" : 758 }, 43.794 + "p759": { "x" : 759 }, 43.795 + "p760": { "x" : 760 }, 43.796 + "p761": { "x" : 761 }, 43.797 + "p762": { "x" : 762 }, 43.798 + "p763": { "x" : 763 }, 43.799 + "p764": { "x" : 764 }, 43.800 + "p765": { "x" : 765 }, 43.801 + "p766": { "x" : 766 }, 43.802 + "p767": { "x" : 767 }, 43.803 + "p768": { "x" : 768 }, 43.804 + "p769": { "x" : 769 }, 43.805 + "p770": { "x" : 770 }, 43.806 + "p771": { "x" : 771 }, 43.807 + "p772": { "x" : 772 }, 43.808 + "p773": { "x" : 773 }, 43.809 + "p774": { "x" : 774 }, 43.810 + "p775": { "x" : 775 }, 43.811 + "p776": { "x" : 776 }, 43.812 + "p777": { "x" : 777 }, 43.813 + "p778": { "x" : 778 }, 43.814 + "p779": { "x" : 779 }, 43.815 + "p780": { "x" : 780 }, 43.816 + "p781": { "x" : 781 }, 43.817 + "p782": { "x" : 782 }, 43.818 + "p783": { "x" : 783 }, 43.819 + "p784": { "x" : 784 }, 43.820 + "p785": { "x" : 785 }, 43.821 + "p786": { "x" : 786 }, 43.822 + "p787": { "x" : 787 }, 43.823 + "p788": { "x" : 788 }, 43.824 + "p789": { "x" : 789 }, 43.825 + "p790": { "x" : 790 }, 43.826 + "p791": { "x" : 791 }, 43.827 + "p792": { "x" : 792 }, 43.828 + "p793": { "x" : 793 }, 43.829 + "p794": { "x" : 794 }, 43.830 + "p795": { "x" : 795 }, 43.831 + "p796": { "x" : 796 }, 43.832 + "p797": { "x" : 797 }, 43.833 + "p798": { "x" : 798 }, 43.834 + "p799": { "x" : 799 }, 43.835 + "p800": { "x" : 800 }, 43.836 + "p801": { "x" : 801 }, 43.837 + "p802": { "x" : 802 }, 43.838 + "p803": { "x" : 803 }, 43.839 + "p804": { "x" : 804 }, 43.840 + "p805": { "x" : 805 }, 43.841 + "p806": { "x" : 806 }, 43.842 + "p807": { "x" : 807 }, 43.843 + "p808": { "x" : 808 }, 43.844 + "p809": { "x" : 809 }, 43.845 + "p810": { "x" : 810 }, 43.846 + "p811": { "x" : 811 }, 43.847 + "p812": { "x" : 812 }, 43.848 + "p813": { "x" : 813 }, 43.849 + "p814": { "x" : 814 }, 43.850 + "p815": { "x" : 815 }, 43.851 + "p816": { "x" : 816 }, 43.852 + "p817": { "x" : 817 }, 43.853 + "p818": { "x" : 818 }, 43.854 + "p819": { "x" : 819 }, 43.855 + "p820": { "x" : 820 }, 43.856 + "p821": { "x" : 821 }, 43.857 + "p822": { "x" : 822 }, 43.858 + "p823": { "x" : 823 }, 43.859 + "p824": { "x" : 824 }, 43.860 + "p825": { "x" : 825 }, 43.861 + "p826": { "x" : 826 }, 43.862 + "p827": { "x" : 827 }, 43.863 + "p828": { "x" : 828 }, 43.864 + "p829": { "x" : 829 }, 43.865 + "p830": { "x" : 830 }, 43.866 + "p831": { "x" : 831 }, 43.867 + "p832": { "x" : 832 }, 43.868 + "p833": { "x" : 833 }, 43.869 + "p834": { "x" : 834 }, 43.870 + "p835": { "x" : 835 }, 43.871 + "p836": { "x" : 836 }, 43.872 + "p837": { "x" : 837 }, 43.873 + "p838": { "x" : 838 }, 43.874 + "p839": { "x" : 839 }, 43.875 + "p840": { "x" : 840 }, 43.876 + "p841": { "x" : 841 }, 43.877 + "p842": { "x" : 842 }, 43.878 + "p843": { "x" : 843 }, 43.879 + "p844": { "x" : 844 }, 43.880 + "p845": { "x" : 845 }, 43.881 + "p846": { "x" : 846 }, 43.882 + "p847": { "x" : 847 }, 43.883 + "p848": { "x" : 848 }, 43.884 + "p849": { "x" : 849 }, 43.885 + "p850": { "x" : 850 }, 43.886 + "p851": { "x" : 851 }, 43.887 + "p852": { "x" : 852 }, 43.888 + "p853": { "x" : 853 }, 43.889 + "p854": { "x" : 854 }, 43.890 + "p855": { "x" : 855 }, 43.891 + "p856": { "x" : 856 }, 43.892 + "p857": { "x" : 857 }, 43.893 + "p858": { "x" : 858 }, 43.894 + "p859": { "x" : 859 }, 43.895 + "p860": { "x" : 860 }, 43.896 + "p861": { "x" : 861 }, 43.897 + "p862": { "x" : 862 }, 43.898 + "p863": { "x" : 863 }, 43.899 + "p864": { "x" : 864 }, 43.900 + "p865": { "x" : 865 }, 43.901 + "p866": { "x" : 866 }, 43.902 + "p867": { "x" : 867 }, 43.903 + "p868": { "x" : 868 }, 43.904 + "p869": { "x" : 869 }, 43.905 + "p870": { "x" : 870 }, 43.906 + "p871": { "x" : 871 }, 43.907 + "p872": { "x" : 872 }, 43.908 + "p873": { "x" : 873 }, 43.909 + "p874": { "x" : 874 }, 43.910 + "p875": { "x" : 875 }, 43.911 + "p876": { "x" : 876 }, 43.912 + "p877": { "x" : 877 }, 43.913 + "p878": { "x" : 878 }, 43.914 + "p879": { "x" : 879 }, 43.915 + "p880": { "x" : 880 }, 43.916 + "p881": { "x" : 881 }, 43.917 + "p882": { "x" : 882 }, 43.918 + "p883": { "x" : 883 }, 43.919 + "p884": { "x" : 884 }, 43.920 + "p885": { "x" : 885 }, 43.921 + "p886": { "x" : 886 }, 43.922 + "p887": { "x" : 887 }, 43.923 + "p888": { "x" : 888 }, 43.924 + "p889": { "x" : 889 }, 43.925 + "p890": { "x" : 890 }, 43.926 + "p891": { "x" : 891 }, 43.927 + "p892": { "x" : 892 }, 43.928 + "p893": { "x" : 893 }, 43.929 + "p894": { "x" : 894 }, 43.930 + "p895": { "x" : 895 }, 43.931 + "p896": { "x" : 896 }, 43.932 + "p897": { "x" : 897 }, 43.933 + "p898": { "x" : 898 }, 43.934 + "p899": { "x" : 899 }, 43.935 + "p900": { "x" : 900 }, 43.936 + "p901": { "x" : 901 }, 43.937 + "p902": { "x" : 902 }, 43.938 + "p903": { "x" : 903 }, 43.939 + "p904": { "x" : 904 }, 43.940 + "p905": { "x" : 905 }, 43.941 + "p906": { "x" : 906 }, 43.942 + "p907": { "x" : 907 }, 43.943 + "p908": { "x" : 908 }, 43.944 + "p909": { "x" : 909 }, 43.945 + "p910": { "x" : 910 }, 43.946 + "p911": { "x" : 911 }, 43.947 + "p912": { "x" : 912 }, 43.948 + "p913": { "x" : 913 }, 43.949 + "p914": { "x" : 914 }, 43.950 + "p915": { "x" : 915 }, 43.951 + "p916": { "x" : 916 }, 43.952 + "p917": { "x" : 917 }, 43.953 + "p918": { "x" : 918 }, 43.954 + "p919": { "x" : 919 }, 43.955 + "p920": { "x" : 920 }, 43.956 + "p921": { "x" : 921 }, 43.957 + "p922": { "x" : 922 }, 43.958 + "p923": { "x" : 923 }, 43.959 + "p924": { "x" : 924 }, 43.960 + "p925": { "x" : 925 }, 43.961 + "p926": { "x" : 926 }, 43.962 + "p927": { "x" : 927 }, 43.963 + "p928": { "x" : 928 }, 43.964 + "p929": { "x" : 929 }, 43.965 + "p930": { "x" : 930 }, 43.966 + "p931": { "x" : 931 }, 43.967 + "p932": { "x" : 932 }, 43.968 + "p933": { "x" : 933 }, 43.969 + "p934": { "x" : 934 }, 43.970 + "p935": { "x" : 935 }, 43.971 + "p936": { "x" : 936 }, 43.972 + "p937": { "x" : 937 }, 43.973 + "p938": { "x" : 938 }, 43.974 + "p939": { "x" : 939 }, 43.975 + "p940": { "x" : 940 }, 43.976 + "p941": { "x" : 941 }, 43.977 + "p942": { "x" : 942 }, 43.978 + "p943": { "x" : 943 }, 43.979 + "p944": { "x" : 944 }, 43.980 + "p945": { "x" : 945 }, 43.981 + "p946": { "x" : 946 }, 43.982 + "p947": { "x" : 947 }, 43.983 + "p948": { "x" : 948 }, 43.984 + "p949": { "x" : 949 }, 43.985 + "p950": { "x" : 950 }, 43.986 + "p951": { "x" : 951 }, 43.987 + "p952": { "x" : 952 }, 43.988 + "p953": { "x" : 953 }, 43.989 + "p954": { "x" : 954 }, 43.990 + "p955": { "x" : 955 }, 43.991 + "p956": { "x" : 956 }, 43.992 + "p957": { "x" : 957 }, 43.993 + "p958": { "x" : 958 }, 43.994 + "p959": { "x" : 959 }, 43.995 + "p960": { "x" : 960 }, 43.996 + "p961": { "x" : 961 }, 43.997 + "p962": { "x" : 962 }, 43.998 + "p963": { "x" : 963 }, 43.999 + "p964": { "x" : 964 }, 43.1000 + "p965": { "x" : 965 }, 43.1001 + "p966": { "x" : 966 }, 43.1002 + "p967": { "x" : 967 }, 43.1003 + "p968": { "x" : 968 }, 43.1004 + "p969": { "x" : 969 }, 43.1005 + "p970": { "x" : 970 }, 43.1006 + "p971": { "x" : 971 }, 43.1007 + "p972": { "x" : 972 }, 43.1008 + "p973": { "x" : 973 }, 43.1009 + "p974": { "x" : 974 }, 43.1010 + "p975": { "x" : 975 }, 43.1011 + "p976": { "x" : 976 }, 43.1012 + "p977": { "x" : 977 }, 43.1013 + "p978": { "x" : 978 }, 43.1014 + "p979": { "x" : 979 }, 43.1015 + "p980": { "x" : 980 }, 43.1016 + "p981": { "x" : 981 }, 43.1017 + "p982": { "x" : 982 }, 43.1018 + "p983": { "x" : 983 }, 43.1019 + "p984": { "x" : 984 }, 43.1020 + "p985": { "x" : 985 }, 43.1021 + "p986": { "x" : 986 }, 43.1022 + "p987": { "x" : 987 }, 43.1023 + "p988": { "x" : 988 }, 43.1024 + "p989": { "x" : 989 }, 43.1025 + "p990": { "x" : 990 }, 43.1026 + "p991": { "x" : 991 }, 43.1027 + "p992": { "x" : 992 }, 43.1028 + "p993": { "x" : 993 }, 43.1029 + "p994": { "x" : 994 }, 43.1030 + "p995": { "x" : 995 }, 43.1031 + "p996": { "x" : 996 }, 43.1032 + "p997": { "x" : 997 }, 43.1033 + "p998": { "x" : 998 }, 43.1034 + "p999": { "x" : 999 } 43.1035 +}; 43.1036 + 43.1037 +for (var i = 0; i < 1000; i++) { 43.1038 + var value = obj["p" + i]; 43.1039 + Assert.assertTrue(typeof value === "object"); 43.1040 + Assert.assertTrue(value.x === i); 43.1041 +}
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 44.2 +++ b/test/script/basic/JDK-8074556.js Thu Mar 12 13:45:00 2015 -0700 44.3 @@ -0,0 +1,52 @@ 44.4 +/* 44.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 44.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 44.7 + * 44.8 + * This code is free software; you can redistribute it and/or modify it 44.9 + * under the terms of the GNU General Public License version 2 only, as 44.10 + * published by the Free Software Foundation. 44.11 + * 44.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 44.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 44.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 44.15 + * version 2 for more details (a copy is included in the LICENSE file that 44.16 + * accompanied this code). 44.17 + * 44.18 + * You should have received a copy of the GNU General Public License version 44.19 + * 2 along with this work; if not, write to the Free Software Foundation, 44.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 44.21 + * 44.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 44.23 + * or visit www.oracle.com if you need additional information or have any 44.24 + * questions. 44.25 + */ 44.26 + 44.27 +/** 44.28 + * JDK-8074556: Functions should not share allocator maps 44.29 + * 44.30 + * @test 44.31 + * @run 44.32 + */ 44.33 + 44.34 +function A () { 44.35 + return this; 44.36 +} 44.37 + 44.38 +function B() { 44.39 + return this; 44.40 +} 44.41 + 44.42 +A.prototype.x = "x"; 44.43 +A.prototype.y = "y"; 44.44 +B.prototype.y = "y"; // same properties but different order 44.45 +B.prototype.x = "x"; 44.46 + 44.47 +function test(o) { 44.48 + Assert.assertEquals(o.x, "x"); 44.49 + Assert.assertEquals(o.y, "y"); 44.50 +} 44.51 + 44.52 +test(new A()); 44.53 +test(new B()); 44.54 +test(new A()); 44.55 +test(new B());
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 45.2 +++ b/test/script/basic/JDK-8074687.js Thu Mar 12 13:45:00 2015 -0700 45.3 @@ -0,0 +1,60 @@ 45.4 +/* 45.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 45.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 45.7 + * 45.8 + * This code is free software; you can redistribute it and/or modify it 45.9 + * under the terms of the GNU General Public License version 2 only, as 45.10 + * published by the Free Software Foundation. 45.11 + * 45.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 45.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 45.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 45.15 + * version 2 for more details (a copy is included in the LICENSE file that 45.16 + * accompanied this code). 45.17 + * 45.18 + * You should have received a copy of the GNU General Public License version 45.19 + * 2 along with this work; if not, write to the Free Software Foundation, 45.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 45.21 + * 45.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 45.23 + * or visit www.oracle.com if you need additional information or have any 45.24 + * questions. 45.25 + */ 45.26 + 45.27 +/** 45.28 + * JDK-8074687: Add tests for JSON parsing of numeric keys 45.29 + * 45.30 + * @test 45.31 + * @run 45.32 + */ 45.33 + 45.34 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {} }')), '{"0":{}}'); 45.35 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1 }')), '{"0":1}'); 45.36 + 45.37 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "65503": {} }')), '{"65503":{}}'); 45.38 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "65503": 1 }')), '{"65503":1}'); 45.39 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {}, "65503": {} }')), '{"0":{},"65503":{}}'); 45.40 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1, "65503": 1 }')), '{"0":1,"65503":1}'); 45.41 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "65503": {}, "0": {} }')), '{"0":{},"65503":{}}'); 45.42 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "65503": 1, "0": 1 }')), '{"0":1,"65503":1}'); 45.43 + 45.44 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "4294967295": {} }')), '{"4294967295":{}}'); 45.45 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "4294967295": 1 }')), '{"4294967295":1}'); 45.46 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {}, "4294967295": {} }')), '{"0":{},"4294967295":{}}'); 45.47 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1, "4294967295": 1 }')), '{"0":1,"4294967295":1}'); 45.48 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "4294967295": {}, "0": {} }')), '{"0":{},"4294967295":{}}'); 45.49 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "4294967295": 1, "0": 1 }')), '{"0":1,"4294967295":1}'); 45.50 + 45.51 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "100": {} }')), '{"100":{}}'); 45.52 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "100": 1 }')), '{"100":1}'); 45.53 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {}, "100": {} }')), '{"0":{},"100":{}}'); 45.54 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1, "100": 1 }')), '{"0":1,"100":1}'); 45.55 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "100": {}, "0": {} }')), '{"0":{},"100":{}}'); 45.56 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "100": 1, "0": 1 }')), '{"0":1,"100":1}'); 45.57 + 45.58 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "-100": {} }')), '{"-100":{}}'); 45.59 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "-100": 1 }')), '{"-100":1}'); 45.60 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {}, "-100": {} }')), '{"0":{},"-100":{}}'); 45.61 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1, "-100": 1 }')), '{"0":1,"-100":1}'); 45.62 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "-100": {}, "0": {} }')), '{"0":{},"-100":{}}'); 45.63 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "-100": 1, "0": 1 }')), '{"0":1,"-100":1}');
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 46.2 +++ b/test/script/basic/JDK-8074693.js Thu Mar 12 13:45:00 2015 -0700 46.3 @@ -0,0 +1,74 @@ 46.4 +/* 46.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 46.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 46.7 + * 46.8 + * This code is free software; you can redistribute it and/or modify it 46.9 + * under the terms of the GNU General Public License version 2 only, as 46.10 + * published by the Free Software Foundation. 46.11 + * 46.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 46.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 46.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 46.15 + * version 2 for more details (a copy is included in the LICENSE file that 46.16 + * accompanied this code). 46.17 + * 46.18 + * You should have received a copy of the GNU General Public License version 46.19 + * 2 along with this work; if not, write to the Free Software Foundation, 46.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 46.21 + * 46.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 46.23 + * or visit www.oracle.com if you need additional information or have any 46.24 + * questions. 46.25 + */ 46.26 + 46.27 +/** 46.28 + * JDK-8074693: Different instances of same function use same allocator map 46.29 + * 46.30 + * @test 46.31 + * @run 46.32 + */ 46.33 + 46.34 +var lib = {}; 46.35 + 46.36 +lib.mixin = function(target, source) { 46.37 + for (var p in source) { 46.38 + if (source.hasOwnProperty(p) && !target.hasOwnProperty(p)) { 46.39 + target.prototype[p] = source[p]; 46.40 + } 46.41 + } 46.42 +}; 46.43 + 46.44 +lib.declare = function(def) { 46.45 + var className = def.name; 46.46 + 46.47 + lib[className] = function() { 46.48 + this.init.apply(this, arguments); 46.49 + }; 46.50 + 46.51 + lib.mixin(lib[className], def.members); 46.52 +}; 46.53 + 46.54 + 46.55 +lib.declare({ 46.56 + name: "ClassA", 46.57 + members: { 46.58 + init : function () { 46.59 + print("init A called"); 46.60 + } 46.61 + } 46.62 +}); 46.63 + 46.64 +lib.declare({ 46.65 + name: "ClassB", 46.66 + members: { 46.67 + util : function () { 46.68 + print("util called") 46.69 + }, 46.70 + init : function() { 46.71 + print("init B called"); 46.72 + } 46.73 + } 46.74 +}); 46.75 + 46.76 +var objA = new lib.ClassA(); 46.77 +var objB = new lib.ClassB();
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 47.2 +++ b/test/script/basic/JDK-8074693.js.EXPECTED Thu Mar 12 13:45:00 2015 -0700 47.3 @@ -0,0 +1,2 @@ 47.4 +init A called 47.5 +init B called
48.1 --- a/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java Wed Mar 11 14:11:06 2015 -0700 48.2 +++ b/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java Thu Mar 12 13:45:00 2015 -0700 48.3 @@ -109,6 +109,35 @@ 48.4 } 48.5 } 48.6 48.7 + // @bug 8062030: Nashorn bug retrieving array property after key string concatenation 48.8 + @Test 48.9 + // ConsString attribute access on a JSObject 48.10 + public void consStringTest() { 48.11 + final ScriptEngineManager m = new ScriptEngineManager(); 48.12 + final ScriptEngine e = m.getEngineByName("nashorn"); 48.13 + try { 48.14 + final MapWrapperObject obj = new MapWrapperObject(); 48.15 + e.put("obj", obj); 48.16 + e.put("f", "f"); 48.17 + e.eval("obj[f + 'oo'] = 'bar';"); 48.18 + 48.19 + assertEquals(obj.getMap().get("foo"), "bar"); 48.20 + assertEquals(e.eval("obj[f + 'oo']"), "bar"); 48.21 + assertEquals(e.eval("obj['foo']"), "bar"); 48.22 + assertEquals(e.eval("f + 'oo' in obj"), Boolean.TRUE); 48.23 + assertEquals(e.eval("'foo' in obj"), Boolean.TRUE); 48.24 + e.eval("delete obj[f + 'oo']"); 48.25 + assertFalse(obj.getMap().containsKey("foo")); 48.26 + assertEquals(e.eval("obj[f + 'oo']"), null); 48.27 + assertEquals(e.eval("obj['foo']"), null); 48.28 + assertEquals(e.eval("f + 'oo' in obj"), Boolean.FALSE); 48.29 + assertEquals(e.eval("'foo' in obj"), Boolean.FALSE); 48.30 + } catch (final Exception exp) { 48.31 + exp.printStackTrace(); 48.32 + fail(exp.getMessage()); 48.33 + } 48.34 + } 48.35 + 48.36 public static class BufferObject extends AbstractJSObject { 48.37 private final IntBuffer buf; 48.38