Wed, 18 Mar 2015 18:21:55 -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 18 13:57:04 2015 -0700 1.2 +++ b/src/jdk/nashorn/api/scripting/AbstractJSObject.java Wed Mar 18 18:21:55 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 Wed Mar 18 18:21:55 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 18 13:57:04 2015 -0700 3.2 +++ b/src/jdk/nashorn/api/scripting/JSObject.java Wed Mar 18 18:21:55 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 18 13:57:04 2015 -0700 4.2 +++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Wed Mar 18 18:21:55 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 18 13:57:04 2015 -0700 5.2 +++ b/src/jdk/nashorn/internal/codegen/BranchOptimizer.java Wed Mar 18 18:21:55 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 18 13:57:04 2015 -0700 6.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Mar 18 18:21:55 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 18 13:57:04 2015 -0700 7.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java Wed Mar 18 18:21:55 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 18 13:57:04 2015 -0700 8.2 +++ b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java Wed Mar 18 18:21:55 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 18 13:57:04 2015 -0700 9.2 +++ b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Wed Mar 18 18:21:55 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 18 13:57:04 2015 -0700 10.2 +++ b/src/jdk/nashorn/internal/codegen/MapCreator.java Wed Mar 18 18:21:55 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 18 13:57:04 2015 -0700 11.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Mar 18 18:21:55 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 18 13:57:04 2015 -0700 12.2 +++ b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Wed Mar 18 18:21:55 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 18 13:57:04 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 18 13:57:04 2015 -0700 14.2 +++ b/src/jdk/nashorn/internal/ir/BinaryNode.java Wed Mar 18 18:21:55 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 18 13:57:04 2015 -0700 15.2 +++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java Wed Mar 18 18:21:55 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 18 13:57:04 2015 -0700 16.2 +++ b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java Wed Mar 18 18:21:55 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 18 13:57:04 2015 -0700 17.2 +++ b/src/jdk/nashorn/internal/objects/Global.java Wed Mar 18 18:21:55 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/NativeArrayBuffer.java Wed Mar 18 13:57:04 2015 -0700 18.2 +++ b/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java Wed Mar 18 18:21:55 2015 -0700 18.3 @@ -101,7 +101,7 @@ 18.4 } 18.5 18.6 if (args.length == 0) { 18.7 - throw new RuntimeException("missing length argument"); 18.8 + return new NativeArrayBuffer(0); 18.9 } 18.10 18.11 return new NativeArrayBuffer(JSType.toInt32(args[0]));
19.1 --- a/src/jdk/nashorn/internal/objects/NativeDate.java Wed Mar 18 13:57:04 2015 -0700 19.2 +++ b/src/jdk/nashorn/internal/objects/NativeDate.java Wed Mar 18 18:21:55 2015 -0700 19.3 @@ -30,6 +30,7 @@ 19.4 import static java.lang.Double.isNaN; 19.5 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError; 19.6 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 19.7 + 19.8 import java.util.Locale; 19.9 import java.util.TimeZone; 19.10 import java.util.concurrent.Callable; 19.11 @@ -40,7 +41,6 @@ 19.12 import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 19.13 import jdk.nashorn.internal.objects.annotations.Where; 19.14 import jdk.nashorn.internal.parser.DateParser; 19.15 -import jdk.nashorn.internal.runtime.ConsString; 19.16 import jdk.nashorn.internal.runtime.JSType; 19.17 import jdk.nashorn.internal.runtime.PropertyMap; 19.18 import jdk.nashorn.internal.runtime.ScriptEnvironment; 19.19 @@ -183,7 +183,7 @@ 19.20 case 1: 19.21 double num; 19.22 final Object arg = JSType.toPrimitive(args[0]); 19.23 - if (arg instanceof String || arg instanceof ConsString) { 19.24 + if (JSType.isString(arg)) { 19.25 num = parseDateString(arg.toString()); 19.26 } else { 19.27 num = timeClip(JSType.toNumber(args[0]));
20.1 --- a/src/jdk/nashorn/internal/objects/NativeJSON.java Wed Mar 18 13:57:04 2015 -0700 20.2 +++ b/src/jdk/nashorn/internal/objects/NativeJSON.java Wed Mar 18 18:21:55 2015 -0700 20.3 @@ -181,7 +181,7 @@ 20.4 } 20.5 gap = sb.toString(); 20.6 } 20.7 - } else if (modSpace instanceof String || modSpace instanceof ConsString) { 20.8 + } else if (JSType.isString(modSpace)) { 20.9 final String str = modSpace.toString(); 20.10 gap = str.substring(0, Math.min(10, str.length())); 20.11 } else {
21.1 --- a/src/jdk/nashorn/internal/objects/NativeString.java Wed Mar 18 13:57:04 2015 -0700 21.2 +++ b/src/jdk/nashorn/internal/objects/NativeString.java Wed Mar 18 18:21:55 2015 -0700 21.3 @@ -90,7 +90,7 @@ 21.4 21.5 private NativeString(final CharSequence value, final ScriptObject proto, final PropertyMap map) { 21.6 super(proto, map); 21.7 - assert value instanceof String || value instanceof ConsString; 21.8 + assert JSType.isString(value); 21.9 this.value = value; 21.10 } 21.11 21.12 @@ -155,7 +155,7 @@ 21.13 final Object self = request.getReceiver(); 21.14 final Class<?> returnType = desc.getMethodType().returnType(); 21.15 21.16 - if (returnType == Object.class && (self instanceof String || self instanceof ConsString)) { 21.17 + if (returnType == Object.class && JSType.isString(self)) { 21.18 try { 21.19 return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getInstanceOf2Guard(String.class, ConsString.class)); 21.20 } catch (final LookupException e) { 21.21 @@ -1312,7 +1312,7 @@ 21.22 } 21.23 21.24 private static CharSequence getCharSequence(final Object self) { 21.25 - if (self instanceof String || self instanceof ConsString) { 21.26 + if (JSType.isString(self)) { 21.27 return (CharSequence)self; 21.28 } else if (self instanceof NativeString) { 21.29 return ((NativeString)self).getValue();
22.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Wed Mar 18 13:57:04 2015 -0700 22.2 +++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Wed Mar 18 18:21:55 2015 -0700 22.3 @@ -305,7 +305,7 @@ 22.4 final ScriptFunction typeErrorThrower = global.getTypeErrorThrower(); 22.5 if (findProperty("arguments", true) != null) { 22.6 initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower); 22.7 - } 22.8 + } 22.9 if (findProperty("caller", true) != null) { 22.10 initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower); 22.11 }
23.1 --- a/src/jdk/nashorn/internal/parser/JSONParser.java Wed Mar 18 13:57:04 2015 -0700 23.2 +++ b/src/jdk/nashorn/internal/parser/JSONParser.java Wed Mar 18 18:21:55 2015 -0700 23.3 @@ -244,20 +244,15 @@ 23.4 private static PropertyMap addObjectProperty(final PropertyMap propertyMap, final List<Object> values, 23.5 final String id, final Object value) { 23.6 final Property oldProperty = propertyMap.findProperty(id); 23.7 - final Property newProperty; 23.8 final PropertyMap newMap; 23.9 final Class<?> type = ObjectClassGenerator.OBJECT_FIELDS_ONLY ? Object.class : getType(value); 23.10 23.11 if (oldProperty != null) { 23.12 values.set(oldProperty.getSlot(), value); 23.13 - newProperty = new SpillProperty(id, 0, oldProperty.getSlot()); 23.14 - newProperty.setType(type); 23.15 - newMap = propertyMap.replaceProperty(oldProperty, newProperty);; 23.16 + newMap = propertyMap.replaceProperty(oldProperty, new SpillProperty(id, 0, oldProperty.getSlot(), type));; 23.17 } else { 23.18 values.add(value); 23.19 - newProperty = new SpillProperty(id, 0, propertyMap.size()); 23.20 - newProperty.setType(type); 23.21 - newMap = propertyMap.addProperty(newProperty); 23.22 + newMap = propertyMap.addProperty(new SpillProperty(id, 0, propertyMap.size(), type)); 23.23 } 23.24 23.25 return newMap;
24.1 --- a/src/jdk/nashorn/internal/runtime/AllocationStrategy.java Wed Mar 18 13:57:04 2015 -0700 24.2 +++ b/src/jdk/nashorn/internal/runtime/AllocationStrategy.java Wed Mar 18 18:21:55 2015 -0700 24.3 @@ -29,55 +29,52 @@ 24.4 import java.io.Serializable; 24.5 import java.lang.invoke.MethodHandle; 24.6 import java.lang.invoke.MethodHandles; 24.7 +import jdk.nashorn.internal.codegen.Compiler; 24.8 import jdk.nashorn.internal.codegen.CompilerConstants; 24.9 -import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor; 24.10 +import jdk.nashorn.internal.codegen.ObjectClassGenerator; 24.11 24.12 /** 24.13 - * Encapsulates the allocation strategy for a function when used as a constructor. Basically the same as 24.14 - * {@link AllocatorDescriptor}, but with an additionally cached resolved method handle. There is also a 24.15 - * canonical default allocation strategy for functions that don't assign any "this" properties (vast majority 24.16 - * of all functions), therefore saving some storage space in {@link RecompilableScriptFunctionData} that would 24.17 - * otherwise be lost to identical tuples of (map, className, handle) fields. 24.18 + * Encapsulates the allocation strategy for a function when used as a constructor. 24.19 */ 24.20 -final class AllocationStrategy implements Serializable { 24.21 +final public class AllocationStrategy implements Serializable { 24.22 private static final long serialVersionUID = 1L; 24.23 24.24 private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); 24.25 24.26 - private static final AllocationStrategy DEFAULT_STRATEGY = new AllocationStrategy(new AllocatorDescriptor(0)); 24.27 - 24.28 - /** Allocator map from allocator descriptor */ 24.29 - private final PropertyMap allocatorMap; 24.30 + /** Number of fields in the allocated object */ 24.31 + private final int fieldCount; 24.32 24.33 /** Name of class where allocator function resides */ 24.34 - private final String allocatorClassName; 24.35 + private transient String allocatorClassName; 24.36 24.37 /** lazily generated allocator */ 24.38 private transient MethodHandle allocator; 24.39 24.40 - private AllocationStrategy(final AllocatorDescriptor desc) { 24.41 - this.allocatorMap = desc.getAllocatorMap(); 24.42 - // These classes get loaded, so an interned variant of their name is most likely around anyway. 24.43 - this.allocatorClassName = desc.getAllocatorClassName().intern(); 24.44 + /** 24.45 + * Construct an allocation strategy with the given map and class name. 24.46 + * @param fieldCount number of fields in the allocated object 24.47 + */ 24.48 + public AllocationStrategy(final int fieldCount) { 24.49 + this.fieldCount = fieldCount; 24.50 } 24.51 24.52 - private boolean matches(final AllocatorDescriptor desc) { 24.53 - return desc.getAllocatorMap().size() == allocatorMap.size() && 24.54 - desc.getAllocatorClassName().equals(allocatorClassName); 24.55 - } 24.56 - 24.57 - static AllocationStrategy get(final AllocatorDescriptor desc) { 24.58 - return DEFAULT_STRATEGY.matches(desc) ? DEFAULT_STRATEGY : new AllocationStrategy(desc); 24.59 + private String getAllocatorClassName() { 24.60 + if (allocatorClassName == null) { 24.61 + // These classes get loaded, so an interned variant of their name is most likely around anyway. 24.62 + allocatorClassName = Compiler.binaryName(ObjectClassGenerator.getClassName(fieldCount)).intern(); 24.63 + } 24.64 + return allocatorClassName; 24.65 } 24.66 24.67 PropertyMap getAllocatorMap() { 24.68 - return allocatorMap; 24.69 + // Create a new map for each function instance 24.70 + return PropertyMap.newMap(null, getAllocatorClassName(), 0, fieldCount, 0); 24.71 } 24.72 24.73 ScriptObject allocate(final PropertyMap map) { 24.74 try { 24.75 if (allocator == null) { 24.76 - allocator = MH.findStatic(LOOKUP, Context.forStructureClass(allocatorClassName), 24.77 + allocator = MH.findStatic(LOOKUP, Context.forStructureClass(getAllocatorClassName()), 24.78 CompilerConstants.ALLOCATE.symbolName(), MH.type(ScriptObject.class, PropertyMap.class)); 24.79 } 24.80 return (ScriptObject)allocator.invokeExact(map); 24.81 @@ -88,17 +85,8 @@ 24.82 } 24.83 } 24.84 24.85 - private Object readResolve() { 24.86 - if(allocatorMap.size() == DEFAULT_STRATEGY.allocatorMap.size() && 24.87 - allocatorClassName.equals(DEFAULT_STRATEGY.allocatorClassName)) { 24.88 - return DEFAULT_STRATEGY; 24.89 - } 24.90 - return this; 24.91 - } 24.92 - 24.93 @Override 24.94 public String toString() { 24.95 - return "AllocationStrategy[allocatorClassName=" + allocatorClassName + ", allocatorMap.size=" + 24.96 - allocatorMap.size() + "]"; 24.97 + return "AllocationStrategy[fieldCount=" + fieldCount + "]"; 24.98 } 24.99 }
25.1 --- a/src/jdk/nashorn/internal/runtime/ConsString.java Wed Mar 18 13:57:04 2015 -0700 25.2 +++ b/src/jdk/nashorn/internal/runtime/ConsString.java Wed Mar 18 18:21:55 2015 -0700 25.3 @@ -25,6 +25,8 @@ 25.4 25.5 package jdk.nashorn.internal.runtime; 25.6 25.7 +import static jdk.nashorn.internal.runtime.JSType.isString; 25.8 + 25.9 import java.util.ArrayDeque; 25.10 import java.util.Deque; 25.11 25.12 @@ -52,8 +54,8 @@ 25.13 * @param right right char sequence 25.14 */ 25.15 public ConsString(final CharSequence left, final CharSequence right) { 25.16 - assert left instanceof String || left instanceof ConsString; 25.17 - assert right instanceof String || right instanceof ConsString; 25.18 + assert isString(left); 25.19 + assert isString(right); 25.20 this.left = left; 25.21 this.right = right; 25.22 length = left.length() + right.length();
26.1 --- a/src/jdk/nashorn/internal/runtime/JSType.java Wed Mar 18 13:57:04 2015 -0700 26.2 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Wed Mar 18 18:21:55 2015 -0700 26.3 @@ -29,6 +29,7 @@ 26.4 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY; 26.5 import static jdk.nashorn.internal.lookup.Lookup.MH; 26.6 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 26.7 + 26.8 import java.lang.invoke.MethodHandle; 26.9 import java.lang.invoke.MethodHandles; 26.10 import java.lang.reflect.Array; 26.11 @@ -37,6 +38,7 @@ 26.12 import java.util.Deque; 26.13 import java.util.List; 26.14 import jdk.internal.dynalink.beans.StaticClass; 26.15 +import jdk.nashorn.api.scripting.AbstractJSObject; 26.16 import jdk.nashorn.api.scripting.JSObject; 26.17 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 26.18 import jdk.nashorn.internal.codegen.types.Type; 26.19 @@ -210,7 +212,6 @@ 26.20 /** Method handle for void returns. */ 26.21 public static final Call VOID_RETURN = staticCall(JSTYPE_LOOKUP, JSType.class, "voidReturn", void.class); 26.22 26.23 - 26.24 /** 26.25 * The list of available accessor types in width order. This order is used for type guesses narrow{@literal ->} wide 26.26 * in the dual--fields world 26.27 @@ -311,7 +312,7 @@ 26.28 return JSType.BOOLEAN; 26.29 } 26.30 26.31 - if (obj instanceof String || obj instanceof ConsString) { 26.32 + if (isString(obj)) { 26.33 return JSType.STRING; 26.34 } 26.35 26.36 @@ -349,7 +350,7 @@ 26.37 return JSType.BOOLEAN; 26.38 } 26.39 26.40 - if (obj instanceof String || obj instanceof ConsString) { 26.41 + if (isString(obj)) { 26.42 return JSType.STRING; 26.43 } 26.44 26.45 @@ -455,8 +456,7 @@ 26.46 obj == ScriptRuntime.UNDEFINED || 26.47 obj instanceof Boolean || 26.48 obj instanceof Number || 26.49 - obj instanceof String || 26.50 - obj instanceof ConsString; 26.51 + isString(obj); 26.52 } 26.53 26.54 /** 26.55 @@ -480,17 +480,47 @@ 26.56 * @return the primitive form of the object 26.57 */ 26.58 public static Object toPrimitive(final Object obj, final Class<?> hint) { 26.59 - return obj instanceof ScriptObject ? toPrimitive((ScriptObject)obj, hint) : obj; 26.60 + if (obj instanceof ScriptObject) { 26.61 + return toPrimitive((ScriptObject)obj, hint); 26.62 + } else if (isPrimitive(obj)) { 26.63 + return obj; 26.64 + } else if (obj instanceof JSObject) { 26.65 + return toPrimitive((JSObject)obj, hint); 26.66 + } else if (obj instanceof StaticClass) { 26.67 + final String name = ((StaticClass)obj).getRepresentedClass().getName(); 26.68 + return new StringBuilder(12 + name.length()).append("[JavaClass ").append(name).append(']').toString(); 26.69 + } 26.70 + return obj.toString(); 26.71 } 26.72 26.73 private static Object toPrimitive(final ScriptObject sobj, final Class<?> hint) { 26.74 - final Object result = sobj.getDefaultValue(hint); 26.75 + return requirePrimitive(sobj.getDefaultValue(hint)); 26.76 + } 26.77 26.78 + private static Object requirePrimitive(final Object result) { 26.79 if (!isPrimitive(result)) { 26.80 throw typeError("bad.default.value", result.toString()); 26.81 } 26.82 + return result; 26.83 + } 26.84 26.85 - return result; 26.86 + /** 26.87 + * Primitive converter for a {@link JSObject} including type hint. Invokes 26.88 + * {@link AbstractJSObject#getDefaultValue(JSObject, Class)} and translates any thrown 26.89 + * {@link UnsupportedOperationException} to an ECMAScript {@code TypeError}. 26.90 + * See ECMA 9.1 ToPrimitive 26.91 + * 26.92 + * @param jsobj a JSObject 26.93 + * @param hint a type hint 26.94 + * 26.95 + * @return the primitive form of the JSObject 26.96 + */ 26.97 + public static Object toPrimitive(final JSObject jsobj, final Class<?> hint) { 26.98 + try { 26.99 + return requirePrimitive(AbstractJSObject.getDefaultValue(jsobj, hint)); 26.100 + } catch (final UnsupportedOperationException e) { 26.101 + throw new ECMAException(Context.getGlobal().newTypeError(e.getMessage()), e); 26.102 + } 26.103 } 26.104 26.105 /** 26.106 @@ -547,7 +577,7 @@ 26.107 return num != 0 && !Double.isNaN(num); 26.108 } 26.109 26.110 - if (obj instanceof String || obj instanceof ConsString) { 26.111 + if (isString(obj)) { 26.112 return ((CharSequence)obj).length() > 0; 26.113 } 26.114 26.115 @@ -598,6 +628,15 @@ 26.116 } 26.117 26.118 /** 26.119 + * Returns true if object represents a primitive JavaScript string value. 26.120 + * @param obj the object 26.121 + * @return true if the object represents a primitive JavaScript string value. 26.122 + */ 26.123 + public static boolean isString(final Object obj) { 26.124 + return obj instanceof String || obj instanceof ConsString; 26.125 + } 26.126 + 26.127 + /** 26.128 * JavaScript compliant conversion of integer to String 26.129 * 26.130 * @param num an integer 26.131 @@ -723,6 +762,48 @@ 26.132 return toNumberGeneric(obj); 26.133 } 26.134 26.135 + /** 26.136 + * Converts an object for a comparison with a number. Almost identical to {@link #toNumber(Object)} but 26.137 + * converts {@code null} to {@code NaN} instead of zero, so it won't compare equal to zero. 26.138 + * 26.139 + * @param obj an object 26.140 + * 26.141 + * @return a number 26.142 + */ 26.143 + public static double toNumberForEq(final Object obj) { 26.144 + return obj == null ? Double.NaN : toNumber(obj); 26.145 + } 26.146 + 26.147 + /** 26.148 + * Converts an object for strict comparison with a number. Returns {@code NaN} for any object that is not 26.149 + * a {@link Number}, so only boxed numerics can compare strictly equal to numbers. 26.150 + * 26.151 + * @param obj an object 26.152 + * 26.153 + * @return a number 26.154 + */ 26.155 + public static double toNumberForStrictEq(final Object obj) { 26.156 + if (obj instanceof Double) { 26.157 + return (Double)obj; 26.158 + } 26.159 + if (obj instanceof Number) { 26.160 + return ((Number)obj).doubleValue(); 26.161 + } 26.162 + return Double.NaN; 26.163 + } 26.164 + 26.165 + 26.166 + /** 26.167 + * JavaScript compliant conversion of Boolean to number 26.168 + * See ECMA 9.3 ToNumber 26.169 + * 26.170 + * @param b a boolean 26.171 + * 26.172 + * @return JS numeric value of the boolean: 1.0 or 0.0 26.173 + */ 26.174 + public static double toNumber(final Boolean b) { 26.175 + return b ? 1d : +0d; 26.176 + } 26.177 26.178 /** 26.179 * JavaScript compliant conversion of Object to number 26.180 @@ -1301,6 +1382,10 @@ 26.181 return (String)obj; 26.182 } 26.183 26.184 + if (obj instanceof ConsString) { 26.185 + return obj.toString(); 26.186 + } 26.187 + 26.188 if (obj instanceof Number) { 26.189 return toString(((Number)obj).doubleValue()); 26.190 } 26.191 @@ -1313,23 +1398,19 @@ 26.192 return "null"; 26.193 } 26.194 26.195 - if (obj instanceof ScriptObject) { 26.196 - if (safe) { 26.197 - final ScriptObject sobj = (ScriptObject)obj; 26.198 - final Global gobj = Context.getGlobal(); 26.199 - return gobj.isError(sobj) ? 26.200 - ECMAException.safeToString(sobj) : 26.201 - sobj.safeToString(); 26.202 - } 26.203 - 26.204 - return toString(toPrimitive(obj, String.class)); 26.205 + if (obj instanceof Boolean) { 26.206 + return obj.toString(); 26.207 } 26.208 26.209 - if (obj instanceof StaticClass) { 26.210 - return "[JavaClass " + ((StaticClass)obj).getRepresentedClass().getName() + "]"; 26.211 + if (safe && obj instanceof ScriptObject) { 26.212 + final ScriptObject sobj = (ScriptObject)obj; 26.213 + final Global gobj = Context.getGlobal(); 26.214 + return gobj.isError(sobj) ? 26.215 + ECMAException.safeToString(sobj) : 26.216 + sobj.safeToString(); 26.217 } 26.218 26.219 - return obj.toString(); 26.220 + return toString(toPrimitive(obj, String.class)); 26.221 } 26.222 26.223 // trim from left for JS whitespaces. 26.224 @@ -1822,18 +1903,18 @@ 26.225 } 26.226 26.227 if (obj instanceof Boolean) { 26.228 - return (Boolean)obj ? 1 : +0.0; 26.229 + return toNumber((Boolean)obj); 26.230 } 26.231 26.232 if (obj instanceof ScriptObject) { 26.233 return toNumber((ScriptObject)obj); 26.234 } 26.235 26.236 - if (obj instanceof JSObject) { 26.237 - return ((JSObject)obj).toNumber(); 26.238 + if (obj instanceof Undefined) { 26.239 + return Double.NaN; 26.240 } 26.241 26.242 - return Double.NaN; 26.243 + return toNumber(toPrimitive(obj, Number.class)); 26.244 } 26.245 26.246 private static Object invoke(final MethodHandle mh, final Object arg) {
27.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Mar 18 13:57:04 2015 -0700 27.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Mar 18 18:21:55 2015 -0700 27.3 @@ -43,7 +43,6 @@ 27.4 import jdk.nashorn.internal.codegen.CompilerConstants; 27.5 import jdk.nashorn.internal.codegen.FunctionSignature; 27.6 import jdk.nashorn.internal.codegen.Namespace; 27.7 -import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor; 27.8 import jdk.nashorn.internal.codegen.OptimisticTypesPersistence; 27.9 import jdk.nashorn.internal.codegen.TypeMap; 27.10 import jdk.nashorn.internal.codegen.types.Type; 27.11 @@ -126,7 +125,7 @@ 27.12 * 27.13 * @param functionNode functionNode that represents this function code 27.14 * @param installer installer for code regeneration versions of this function 27.15 - * @param allocationDescriptor descriptor for the allocation behavior when this function is used as a constructor 27.16 + * @param allocationStrategy strategy for the allocation behavior when this function is used as a constructor 27.17 * @param nestedFunctions nested function map 27.18 * @param externalScopeDepths external scope depths 27.19 * @param internalSymbols internal symbols to method, defined in its scope 27.20 @@ -135,7 +134,7 @@ 27.21 public RecompilableScriptFunctionData( 27.22 final FunctionNode functionNode, 27.23 final CodeInstaller<ScriptEnvironment> installer, 27.24 - final AllocatorDescriptor allocationDescriptor, 27.25 + final AllocationStrategy allocationStrategy, 27.26 final Map<Integer, RecompilableScriptFunctionData> nestedFunctions, 27.27 final Map<String, Integer> externalScopeDepths, 27.28 final Set<String> internalSymbols, 27.29 @@ -153,7 +152,7 @@ 27.30 this.endParserState = functionNode.getEndParserState(); 27.31 this.token = tokenFor(functionNode); 27.32 this.installer = installer; 27.33 - this.allocationStrategy = AllocationStrategy.get(allocationDescriptor); 27.34 + this.allocationStrategy = allocationStrategy; 27.35 this.nestedFunctions = smallMap(nestedFunctions); 27.36 this.externalScopeDepths = smallMap(externalScopeDepths); 27.37 this.internalSymbols = smallSet(new HashSet<>(internalSymbols));
28.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Mar 18 13:57:04 2015 -0700 28.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Mar 18 18:21:55 2015 -0700 28.3 @@ -143,7 +143,6 @@ 28.4 28.5 this.data = data; 28.6 this.scope = scope; 28.7 - this.allocatorMap = data.getAllocatorMap(); 28.8 } 28.9 28.10 @Override 28.11 @@ -253,7 +252,7 @@ 28.12 28.13 assert !isBoundFunction(); // allocate never invoked on bound functions 28.14 28.15 - final ScriptObject object = data.allocate(allocatorMap); 28.16 + final ScriptObject object = data.allocate(getAllocatorMap()); 28.17 28.18 if (object != null) { 28.19 final Object prototype = getPrototype(); 28.20 @@ -269,6 +268,13 @@ 28.21 return object; 28.22 } 28.23 28.24 + private PropertyMap getAllocatorMap() { 28.25 + if (allocatorMap == null) { 28.26 + allocatorMap = data.getAllocatorMap(); 28.27 + } 28.28 + return allocatorMap; 28.29 + } 28.30 + 28.31 /** 28.32 * Return Object.prototype - used by "allocate" 28.33 * @return Object.prototype
29.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Mar 18 13:57:04 2015 -0700 29.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Mar 18 18:21:55 2015 -0700 29.3 @@ -28,6 +28,7 @@ 29.4 import static jdk.nashorn.internal.lookup.Lookup.MH; 29.5 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 29.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 29.7 + 29.8 import java.io.IOException; 29.9 import java.io.ObjectInputStream; 29.10 import java.io.Serializable; 29.11 @@ -456,8 +457,7 @@ 29.12 } 29.13 29.14 static boolean isPrimitiveThis(final Object obj) { 29.15 - return obj instanceof String || obj instanceof ConsString || 29.16 - obj instanceof Number || obj instanceof Boolean; 29.17 + return JSType.isString(obj) || obj instanceof Number || obj instanceof Boolean; 29.18 } 29.19 29.20 /**
30.1 --- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Mar 18 13:57:04 2015 -0700 30.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Mar 18 18:21:55 2015 -0700 30.3 @@ -32,6 +32,8 @@ 30.4 import static jdk.nashorn.internal.runtime.ECMAErrors.syntaxError; 30.5 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 30.6 import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt; 30.7 +import static jdk.nashorn.internal.runtime.JSType.isString; 30.8 + 30.9 import java.lang.invoke.MethodHandle; 30.10 import java.lang.invoke.MethodHandles; 30.11 import java.lang.invoke.SwitchPoint; 30.12 @@ -55,7 +57,6 @@ 30.13 import jdk.nashorn.internal.parser.Lexer; 30.14 import jdk.nashorn.internal.runtime.linker.Bootstrap; 30.15 30.16 - 30.17 /** 30.18 * Utilities to be called by JavaScript runtime API and generated classes. 30.19 */ 30.20 @@ -535,8 +536,6 @@ 30.21 30.22 /** 30.23 * ECMA 11.6.1 - The addition operator (+) - generic implementation 30.24 - * Compiler specializes using {@link jdk.nashorn.internal.codegen.RuntimeCallSite} 30.25 - * if any type information is available for any of the operands 30.26 * 30.27 * @param x first term 30.28 * @param y second term 30.29 @@ -563,8 +562,7 @@ 30.30 final Object xPrim = JSType.toPrimitive(x); 30.31 final Object yPrim = JSType.toPrimitive(y); 30.32 30.33 - if (xPrim instanceof String || yPrim instanceof String 30.34 - || xPrim instanceof ConsString || yPrim instanceof ConsString) { 30.35 + if (isString(xPrim) || isString(yPrim)) { 30.36 try { 30.37 return new ConsString(JSType.toCharSequence(xPrim), JSType.toCharSequence(yPrim)); 30.38 } catch (final IllegalArgumentException iae) { 30.39 @@ -734,7 +732,7 @@ 30.40 return true; 30.41 } 30.42 if (x instanceof ScriptObject && y instanceof ScriptObject) { 30.43 - return x == y; 30.44 + return false; // x != y 30.45 } 30.46 if (x instanceof ScriptObjectMirror || y instanceof ScriptObjectMirror) { 30.47 return ScriptObjectMirror.identical(x, y); 30.48 @@ -798,37 +796,55 @@ 30.49 * @return true if they're equal 30.50 */ 30.51 private static boolean equalDifferentTypeValues(final Object x, final Object y, final JSType xType, final JSType yType) { 30.52 - if (xType == JSType.UNDEFINED && yType == JSType.NULL || xType == JSType.NULL && yType == JSType.UNDEFINED) { 30.53 + if (isUndefinedAndNull(xType, yType) || isUndefinedAndNull(yType, xType)) { 30.54 return true; 30.55 - } 30.56 - 30.57 - if (xType == JSType.NUMBER && yType == JSType.STRING) { 30.58 - return equals(x, JSType.toNumber(y)); 30.59 - } 30.60 - 30.61 - if (xType == JSType.STRING && yType == JSType.NUMBER) { 30.62 - return equals(JSType.toNumber(x), y); 30.63 - } 30.64 - 30.65 - if (xType == JSType.BOOLEAN) { 30.66 - return equals(JSType.toNumber(x), y); 30.67 - } 30.68 - 30.69 - if (yType == JSType.BOOLEAN) { 30.70 - return equals(x, JSType.toNumber(y)); 30.71 - } 30.72 - 30.73 - if ((xType == JSType.STRING || xType == JSType.NUMBER) && y instanceof ScriptObject) { 30.74 - return equals(x, JSType.toPrimitive(y)); 30.75 - } 30.76 - 30.77 - if (x instanceof ScriptObject && (yType == JSType.STRING || yType == JSType.NUMBER)) { 30.78 - return equals(JSType.toPrimitive(x), y); 30.79 + } else if (isNumberAndString(xType, yType)) { 30.80 + return equalNumberToString(x, y); 30.81 + } else if (isNumberAndString(yType, xType)) { 30.82 + // Can reverse order as both are primitives 30.83 + return equalNumberToString(y, x); 30.84 + } else if (xType == JSType.BOOLEAN) { 30.85 + return equalBooleanToAny(x, y); 30.86 + } else if (yType == JSType.BOOLEAN) { 30.87 + // Can reverse order as y is primitive 30.88 + return equalBooleanToAny(y, x); 30.89 + } else if (isNumberOrStringAndObject(xType, yType)) { 30.90 + return equalNumberOrStringToObject(x, y); 30.91 + } else if (isNumberOrStringAndObject(yType, xType)) { 30.92 + // Can reverse order as y is primitive 30.93 + return equalNumberOrStringToObject(y, x); 30.94 } 30.95 30.96 return false; 30.97 } 30.98 30.99 + private static boolean isUndefinedAndNull(final JSType xType, final JSType yType) { 30.100 + return xType == JSType.UNDEFINED && yType == JSType.NULL; 30.101 + } 30.102 + 30.103 + private static boolean isNumberAndString(final JSType xType, final JSType yType) { 30.104 + return xType == JSType.NUMBER && yType == JSType.STRING; 30.105 + } 30.106 + 30.107 + private static boolean isNumberOrStringAndObject(final JSType xType, final JSType yType) { 30.108 + return (xType == JSType.NUMBER || xType == JSType.STRING) && yType == JSType.OBJECT; 30.109 + } 30.110 + 30.111 + private static boolean equalNumberToString(final Object num, final Object str) { 30.112 + // Specification says comparing a number to string should be done as "equals(num, JSType.toNumber(str))". We 30.113 + // can short circuit it to this as we know that "num" is a number, so it'll end up being a number-number 30.114 + // comparison. 30.115 + return ((Number)num).doubleValue() == JSType.toNumber(str.toString()); 30.116 + } 30.117 + 30.118 + private static boolean equalBooleanToAny(final Object bool, final Object any) { 30.119 + return equals(JSType.toNumber((Boolean)bool), any); 30.120 + } 30.121 + 30.122 + private static boolean equalNumberOrStringToObject(final Object numOrStr, final Object any) { 30.123 + return equals(numOrStr, JSType.toPrimitive(any)); 30.124 + } 30.125 + 30.126 /** 30.127 * ECMA 11.9.4 - The strict equal operator (===) - generic implementation 30.128 * 30.129 @@ -935,8 +951,15 @@ 30.130 * @return true if x is less than y 30.131 */ 30.132 public static boolean LT(final Object x, final Object y) { 30.133 - final Object value = lessThan(x, y, true); 30.134 - return value == UNDEFINED ? false : (Boolean)value; 30.135 + final Object px = JSType.toPrimitive(x, Number.class); 30.136 + final Object py = JSType.toPrimitive(y, Number.class); 30.137 + 30.138 + return areBothString(px, py) ? px.toString().compareTo(py.toString()) < 0 : 30.139 + JSType.toNumber(px) < JSType.toNumber(py); 30.140 + } 30.141 + 30.142 + private static boolean areBothString(final Object x, final Object y) { 30.143 + return isString(x) && isString(y); 30.144 } 30.145 30.146 /** 30.147 @@ -948,8 +971,11 @@ 30.148 * @return true if x is greater than y 30.149 */ 30.150 public static boolean GT(final Object x, final Object y) { 30.151 - final Object value = lessThan(y, x, false); 30.152 - return value == UNDEFINED ? false : (Boolean)value; 30.153 + final Object px = JSType.toPrimitive(x, Number.class); 30.154 + final Object py = JSType.toPrimitive(y, Number.class); 30.155 + 30.156 + return areBothString(px, py) ? px.toString().compareTo(py.toString()) > 0 : 30.157 + JSType.toNumber(px) > JSType.toNumber(py); 30.158 } 30.159 30.160 /** 30.161 @@ -961,8 +987,11 @@ 30.162 * @return true if x is less than or equal to y 30.163 */ 30.164 public static boolean LE(final Object x, final Object y) { 30.165 - final Object value = lessThan(y, x, false); 30.166 - return !(Boolean.TRUE.equals(value) || value == UNDEFINED); 30.167 + final Object px = JSType.toPrimitive(x, Number.class); 30.168 + final Object py = JSType.toPrimitive(y, Number.class); 30.169 + 30.170 + return areBothString(px, py) ? px.toString().compareTo(py.toString()) <= 0 : 30.171 + JSType.toNumber(px) <= JSType.toNumber(py); 30.172 } 30.173 30.174 /** 30.175 @@ -974,48 +1003,11 @@ 30.176 * @return true if x is greater than or equal to y 30.177 */ 30.178 public static boolean GE(final Object x, final Object y) { 30.179 - final Object value = lessThan(x, y, true); 30.180 - return !(Boolean.TRUE.equals(value) || value == UNDEFINED); 30.181 - } 30.182 + final Object px = JSType.toPrimitive(x, Number.class); 30.183 + final Object py = JSType.toPrimitive(y, Number.class); 30.184 30.185 - /** ECMA 11.8.5 The Abstract Relational Comparison Algorithm */ 30.186 - private static Object lessThan(final Object x, final Object y, final boolean leftFirst) { 30.187 - Object px, py; 30.188 - 30.189 - //support e.g. x < y should throw exception correctly if x or y are not numeric 30.190 - if (leftFirst) { 30.191 - px = JSType.toPrimitive(x, Number.class); 30.192 - py = JSType.toPrimitive(y, Number.class); 30.193 - } else { 30.194 - py = JSType.toPrimitive(y, Number.class); 30.195 - px = JSType.toPrimitive(x, Number.class); 30.196 - } 30.197 - 30.198 - if (JSType.ofNoFunction(px) == JSType.STRING && JSType.ofNoFunction(py) == JSType.STRING) { 30.199 - // May be String or ConsString 30.200 - return px.toString().compareTo(py.toString()) < 0; 30.201 - } 30.202 - 30.203 - final double nx = JSType.toNumber(px); 30.204 - final double ny = JSType.toNumber(py); 30.205 - 30.206 - if (Double.isNaN(nx) || Double.isNaN(ny)) { 30.207 - return UNDEFINED; 30.208 - } 30.209 - 30.210 - if (nx == ny) { 30.211 - return false; 30.212 - } 30.213 - 30.214 - if (nx > 0 && ny > 0 && Double.isInfinite(nx) && Double.isInfinite(ny)) { 30.215 - return false; 30.216 - } 30.217 - 30.218 - if (nx < 0 && ny < 0 && Double.isInfinite(nx) && Double.isInfinite(ny)) { 30.219 - return false; 30.220 - } 30.221 - 30.222 - return nx < ny; 30.223 + return areBothString(px, py) ? px.toString().compareTo(py.toString()) >= 0 : 30.224 + JSType.toNumber(px) >= JSType.toNumber(py); 30.225 } 30.226 30.227 /** 30.228 @@ -1028,9 +1020,7 @@ 30.229 final Context context = Context.getContextTrusted(); 30.230 final SwitchPoint sp = context.getBuiltinSwitchPoint(name); 30.231 assert sp != null; 30.232 - if (sp != null) { 30.233 - context.getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint"); 30.234 - SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 30.235 - } 30.236 + context.getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint"); 30.237 + SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 30.238 } 30.239 }
31.1 --- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Wed Mar 18 13:57:04 2015 -0700 31.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Wed Mar 18 18:21:55 2015 -0700 31.3 @@ -107,7 +107,7 @@ 31.4 31.5 if (file instanceof File) { 31.6 f = (File)file; 31.7 - } else if (file instanceof String || file instanceof ConsString) { 31.8 + } else if (JSType.isString(file)) { 31.9 f = new java.io.File(((CharSequence)file).toString()); 31.10 } 31.11
32.1 --- a/src/jdk/nashorn/internal/runtime/SpillProperty.java Wed Mar 18 13:57:04 2015 -0700 32.2 +++ b/src/jdk/nashorn/internal/runtime/SpillProperty.java Wed Mar 18 18:21:55 2015 -0700 32.3 @@ -164,7 +164,14 @@ 32.4 assert !OBJECT_FIELDS_ONLY || getLocalType() == Object.class; 32.5 } 32.6 32.7 - SpillProperty(final String key, final int flags, final int slot, final Class<?> initialType) { 32.8 + /** 32.9 + * Constructor for spill properties with an initial type. 32.10 + * @param key the property key 32.11 + * @param flags the property flags 32.12 + * @param slot spill slot 32.13 + * @param initialType initial type 32.14 + */ 32.15 + public SpillProperty(final String key, final int flags, final int slot, final Class<?> initialType) { 32.16 this(key, flags, slot); 32.17 setType(OBJECT_FIELDS_ONLY ? Object.class : initialType); 32.18 }
33.1 --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Mar 18 13:57:04 2015 -0700 33.2 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Mar 18 18:21:55 2015 -0700 33.3 @@ -48,7 +48,6 @@ 33.4 import jdk.nashorn.api.scripting.JSObject; 33.5 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 33.6 import jdk.nashorn.internal.codegen.ObjectClassGenerator; 33.7 -import jdk.nashorn.internal.codegen.RuntimeCallSite; 33.8 import jdk.nashorn.internal.lookup.MethodHandleFactory; 33.9 import jdk.nashorn.internal.lookup.MethodHandleFunctionality; 33.10 import jdk.nashorn.internal.objects.ScriptFunctionImpl; 33.11 @@ -210,19 +209,6 @@ 33.12 } 33.13 33.14 /** 33.15 - * Bootstrapper for a specialized Runtime call 33.16 - * 33.17 - * @param lookup lookup 33.18 - * @param initialName initial name for callsite 33.19 - * @param type method type for call site 33.20 - * 33.21 - * @return callsite for a runtime node 33.22 - */ 33.23 - public static CallSite runtimeBootstrap(final MethodHandles.Lookup lookup, final String initialName, final MethodType type) { 33.24 - return new RuntimeCallSite(type, initialName); 33.25 - } 33.26 - 33.27 - /** 33.28 * Boostrapper for math calls that may overflow 33.29 * @param lookup lookup 33.30 * @param name name of operation
34.1 --- a/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Wed Mar 18 13:57:04 2015 -0700 34.2 +++ b/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Wed Mar 18 18:21:55 2015 -0700 34.3 @@ -25,11 +25,13 @@ 34.4 34.5 package jdk.nashorn.internal.runtime.linker; 34.6 34.7 +import static jdk.nashorn.internal.runtime.JSType.isString; 34.8 +import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_CALL; 34.9 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETMEMBER; 34.10 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETSLOT; 34.11 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETMEMBER; 34.12 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETSLOT; 34.13 -import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_CALL; 34.14 + 34.15 import java.lang.invoke.MethodHandle; 34.16 import java.lang.invoke.MethodHandles; 34.17 import jdk.internal.dynalink.CallSiteDescriptor; 34.18 @@ -170,12 +172,12 @@ 34.19 if (index > -1) { 34.20 return JSOBJECT_GETSLOT.invokeExact(jsobj, index); 34.21 } 34.22 - } else if (key instanceof String) { 34.23 - final String name = (String)key; 34.24 + } else if (isString(key)) { 34.25 + final String name = key.toString(); 34.26 if (name.indexOf('(') != -1) { 34.27 - return fallback.invokeExact(jsobj, key); 34.28 + return fallback.invokeExact(jsobj, (Object) name); 34.29 } 34.30 - return JSOBJECT_GETMEMBER.invokeExact(jsobj, (String)key); 34.31 + return JSOBJECT_GETMEMBER.invokeExact(jsobj, name); 34.32 } 34.33 return null; 34.34 } 34.35 @@ -186,8 +188,8 @@ 34.36 JSOBJECT_SETSLOT.invokeExact(jsobj, (int)key, value); 34.37 } else if (key instanceof Number) { 34.38 JSOBJECT_SETSLOT.invokeExact(jsobj, getIndex((Number)key), value); 34.39 - } else if (key instanceof String) { 34.40 - JSOBJECT_SETMEMBER.invokeExact(jsobj, (String)key, value); 34.41 + } else if (isString(key)) { 34.42 + JSOBJECT_SETMEMBER.invokeExact(jsobj, key.toString(), value); 34.43 } 34.44 } 34.45
35.1 --- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Wed Mar 18 13:57:04 2015 -0700 35.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Wed Mar 18 18:21:55 2015 -0700 35.3 @@ -25,16 +25,14 @@ 35.4 35.5 package jdk.nashorn.internal.runtime.linker; 35.6 35.7 +import static jdk.nashorn.internal.runtime.JSType.isString; 35.8 + 35.9 import java.lang.invoke.MethodHandle; 35.10 import java.lang.invoke.MethodHandles; 35.11 -import java.lang.invoke.MethodType; 35.12 -import java.util.HashMap; 35.13 import java.util.Map; 35.14 import javax.script.Bindings; 35.15 import jdk.internal.dynalink.CallSiteDescriptor; 35.16 import jdk.internal.dynalink.linker.GuardedInvocation; 35.17 -import jdk.internal.dynalink.linker.GuardedTypeConversion; 35.18 -import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; 35.19 import jdk.internal.dynalink.linker.LinkRequest; 35.20 import jdk.internal.dynalink.linker.LinkerServices; 35.21 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; 35.22 @@ -48,7 +46,7 @@ 35.23 * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well 35.24 * as ScriptObjects from other Nashorn contexts. 35.25 */ 35.26 -final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory { 35.27 +final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { 35.28 private final NashornBeansLinker nashornBeansLinker; 35.29 35.30 JSObjectLinker(final NashornBeansLinker nashornBeansLinker) { 35.31 @@ -94,22 +92,6 @@ 35.32 return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc); 35.33 } 35.34 35.35 - @Override 35.36 - public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception { 35.37 - final boolean sourceIsAlwaysJSObject = JSObject.class.isAssignableFrom(sourceType); 35.38 - if(!sourceIsAlwaysJSObject && !sourceType.isAssignableFrom(JSObject.class)) { 35.39 - return null; 35.40 - } 35.41 - 35.42 - final MethodHandle converter = CONVERTERS.get(targetType); 35.43 - if(converter == null) { 35.44 - return null; 35.45 - } 35.46 - 35.47 - return new GuardedTypeConversion(new GuardedInvocation(converter, sourceIsAlwaysJSObject ? null : IS_JSOBJECT_GUARD).asType(MethodType.methodType(targetType, sourceType)), true); 35.48 - } 35.49 - 35.50 - 35.51 private GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request, final LinkerServices linkerServices) throws Exception { 35.52 final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); 35.53 final int c = desc.getNameTokenCount(); 35.54 @@ -185,11 +167,11 @@ 35.55 if (index > -1) { 35.56 return ((JSObject)jsobj).getSlot(index); 35.57 } 35.58 - } else if (key instanceof String) { 35.59 - final String name = (String)key; 35.60 + } else if (isString(key)) { 35.61 + final String name = key.toString(); 35.62 // get with method name and signature. delegate it to beans linker! 35.63 if (name.indexOf('(') != -1) { 35.64 - return fallback.invokeExact(jsobj, key); 35.65 + return fallback.invokeExact(jsobj, (Object) name); 35.66 } 35.67 return ((JSObject)jsobj).getMember(name); 35.68 } 35.69 @@ -202,30 +184,11 @@ 35.70 ((JSObject)jsobj).setSlot((Integer)key, value); 35.71 } else if (key instanceof Number) { 35.72 ((JSObject)jsobj).setSlot(getIndex((Number)key), value); 35.73 - } else if (key instanceof String) { 35.74 - ((JSObject)jsobj).setMember((String)key, value); 35.75 + } else if (isString(key)) { 35.76 + ((JSObject)jsobj).setMember(key.toString(), value); 35.77 } 35.78 } 35.79 35.80 - @SuppressWarnings("unused") 35.81 - private static int toInt32(final JSObject obj) { 35.82 - return JSType.toInt32(toNumber(obj)); 35.83 - } 35.84 - 35.85 - @SuppressWarnings("unused") 35.86 - private static long toLong(final JSObject obj) { 35.87 - return JSType.toLong(toNumber(obj)); 35.88 - } 35.89 - 35.90 - private static double toNumber(final JSObject obj) { 35.91 - return obj == null ? 0 : obj.toNumber(); 35.92 - } 35.93 - 35.94 - @SuppressWarnings("unused") 35.95 - private static boolean toBoolean(final JSObject obj) { 35.96 - return obj != null; 35.97 - } 35.98 - 35.99 private static int getIndex(final Number n) { 35.100 final double value = n.doubleValue(); 35.101 return JSType.isRepresentableAsInt(value) ? (int)value : -1; 35.102 @@ -260,14 +223,6 @@ 35.103 private static final MethodHandle JSOBJECT_CALL_TO_APPLY = findOwnMH_S("callToApply", Object.class, MethodHandle.class, JSObject.class, Object.class, Object[].class); 35.104 private static final MethodHandle JSOBJECT_NEW = findJSObjectMH_V("newObject", Object.class, Object[].class); 35.105 35.106 - private static final Map<Class<?>, MethodHandle> CONVERTERS = new HashMap<>(); 35.107 - static { 35.108 - CONVERTERS.put(boolean.class, findOwnMH_S("toBoolean", boolean.class, JSObject.class)); 35.109 - CONVERTERS.put(int.class, findOwnMH_S("toInt32", int.class, JSObject.class)); 35.110 - CONVERTERS.put(long.class, findOwnMH_S("toLong", long.class, JSObject.class)); 35.111 - CONVERTERS.put(double.class, findOwnMH_S("toNumber", double.class, JSObject.class)); 35.112 - } 35.113 - 35.114 private static MethodHandle findJSObjectMH_V(final String name, final Class<?> rtype, final Class<?>... types) { 35.115 return MH.findVirtual(MethodHandles.lookup(), JSObject.class, name, MH.type(rtype, types)); 35.116 }
36.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Wed Mar 18 13:57:04 2015 -0700 36.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Wed Mar 18 18:21:55 2015 -0700 36.3 @@ -27,6 +27,7 @@ 36.4 36.5 import static jdk.nashorn.internal.lookup.Lookup.MH; 36.6 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 36.7 +import static jdk.nashorn.internal.runtime.JSType.isString; 36.8 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 36.9 36.10 import java.lang.invoke.MethodHandle; 36.11 @@ -78,7 +79,7 @@ 36.12 } 36.13 36.14 if (obj == UNDEFINED) { 36.15 - // NOTE: same reasoning for FindBugs NP_BOOLEAN_RETURN_NUL warning as in the preceding comment. 36.16 + // NOTE: same reasoning for FindBugs NP_BOOLEAN_RETURN_NULL warning as in the preceding comment. 36.17 return null; 36.18 } 36.19 36.20 @@ -87,7 +88,7 @@ 36.21 return num != 0 && !Double.isNaN(num); 36.22 } 36.23 36.24 - if (obj instanceof String || obj instanceof ConsString) { 36.25 + if (isString(obj)) { 36.26 return ((CharSequence) obj).length() > 0; 36.27 } 36.28 36.29 @@ -207,7 +208,7 @@ 36.30 return f.longValue(); 36.31 } else if (obj instanceof Number) { 36.32 return ((Number)obj).longValue(); 36.33 - } else if (obj instanceof String || obj instanceof ConsString) { 36.34 + } else if (isString(obj)) { 36.35 return JSType.toLong(obj); 36.36 } else if (obj instanceof Boolean) { 36.37 return (Boolean)obj ? 1L : 0L;
37.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Wed Mar 18 13:57:04 2015 -0700 37.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Wed Mar 18 18:21:55 2015 -0700 37.3 @@ -39,6 +39,7 @@ 37.4 import jdk.internal.dynalink.support.TypeUtilities; 37.5 import jdk.nashorn.internal.objects.Global; 37.6 import jdk.nashorn.internal.runtime.ConsString; 37.7 +import jdk.nashorn.internal.runtime.JSType; 37.8 import jdk.nashorn.internal.runtime.ScriptRuntime; 37.9 37.10 /** 37.11 @@ -170,7 +171,7 @@ 37.12 37.13 @SuppressWarnings("unused") 37.14 private static boolean isJavaScriptPrimitive(final Object o) { 37.15 - return o instanceof String || o instanceof Boolean || o instanceof Number || o instanceof ConsString || o == null; 37.16 + return JSType.isString(o) || o instanceof Boolean || o instanceof Number || o == null; 37.17 } 37.18 37.19 private static final MethodHandle GUARD_PRIMITIVE = findOwnMH("isJavaScriptPrimitive", boolean.class, Object.class);
38.1 --- a/test/script/basic/JDK-8023026.js.EXPECTED Wed Mar 18 13:57:04 2015 -0700 38.2 +++ b/test/script/basic/JDK-8023026.js.EXPECTED Wed Mar 18 18:21:55 2015 -0700 38.3 @@ -26,7 +26,7 @@ 38.4 reduceRight 15 1 38.5 right sum 16 38.6 squared 1,9,25,49 38.7 -iterating on [object Array] 38.8 +iterating on 2,4,6,8 38.9 forEach 2 38.10 forEach 4 38.11 forEach 6
39.1 --- a/test/script/basic/JDK-8024847.js Wed Mar 18 13:57:04 2015 -0700 39.2 +++ b/test/script/basic/JDK-8024847.js Wed Mar 18 18:21:55 2015 -0700 39.3 @@ -102,7 +102,18 @@ 39.4 print(jlist); 39.5 39.6 var obj = new JSObject() { 39.7 - toNumber: function() { return 42; } 39.8 + getMember: function(name) { 39.9 + if (name == "valueOf") { 39.10 + return new JSObject() { 39.11 + isFunction: function() { 39.12 + return true; 39.13 + }, 39.14 + call: function(thiz) { 39.15 + return 42; 39.16 + } 39.17 + }; 39.18 + } 39.19 + } 39.20 }; 39.21 39.22 print(32 + obj);
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/test/script/basic/JDK-8035712.js Wed Mar 18 18:21:55 2015 -0700 40.3 @@ -0,0 +1,282 @@ 40.4 +/* 40.5 + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. 40.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 40.7 + * 40.8 + * This code is free software; you can redistribute it and/or modify it 40.9 + * under the terms of the GNU General Public License version 2 only, as 40.10 + * published by the Free Software Foundation. 40.11 + * 40.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 40.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 40.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 40.15 + * version 2 for more details (a copy is included in the LICENSE file that 40.16 + * accompanied this code). 40.17 + * 40.18 + * You should have received a copy of the GNU General Public License version 40.19 + * 2 along with this work; if not, write to the Free Software Foundation, 40.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 40.21 + * 40.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 40.23 + * or visit www.oracle.com if you need additional information or have any 40.24 + * questions. 40.25 + */ 40.26 + 40.27 +/** 40.28 + * JDK-8035712: Restore some of the RuntimeCallSite specializations 40.29 + * 40.30 + * @test 40.31 + * @run 40.32 + */ 40.33 + 40.34 +if ((typeof Assert) == "undefined") { 40.35 + Assert = { 40.36 + assertTrue: function(x) { if(!x) { throw "expected true" } }, 40.37 + assertFalse: function(x) { if(x) { throw "expected false" } }, 40.38 + }; 40.39 +} 40.40 + 40.41 +function nop() {} 40.42 + 40.43 +function EQ(x, y) { 40.44 + // Exercise normal evaluation 40.45 + Assert.assertTrue (x == y); 40.46 + Assert.assertTrue (y == x); 40.47 + Assert.assertFalse(x != y); 40.48 + Assert.assertFalse(y != x); 40.49 + // Exercise the branch optimizer 40.50 + if (x == y) { nop(); } else { Assert.fail(); } 40.51 + if (y == x) { nop(); } else { Assert.fail(); } 40.52 + if (x != y) { Assert.fail(); } else { nop(); } 40.53 + if (y != x) { Assert.fail(); } else { nop(); } 40.54 +} 40.55 + 40.56 +function NE(x, y) { 40.57 + // Exercise normal evaluation 40.58 + Assert.assertTrue (x != y); 40.59 + Assert.assertTrue (y != x); 40.60 + Assert.assertFalse(x == y); 40.61 + Assert.assertFalse(y == x); 40.62 + // Exercise the branch optimizer 40.63 + if (x != y) { nop(); } else { Assert.fail(); } 40.64 + if (y != x) { nop(); } else { Assert.fail(); } 40.65 + if (x == y) { Assert.fail(); } else { nop(); } 40.66 + if (y == x) { Assert.fail(); } else { nop(); } 40.67 +} 40.68 + 40.69 +function STRICT_EQ(x, y) { 40.70 + // Exercise normal evaluation 40.71 + Assert.assertTrue (x === y); 40.72 + Assert.assertTrue (y === x); 40.73 + Assert.assertFalse(x !== y); 40.74 + Assert.assertFalse(y !== x); 40.75 + // Exercise the branch optimizer 40.76 + if (x === y) { nop(); } else { Assert.fail(); } 40.77 + if (y === x) { nop(); } else { Assert.fail(); } 40.78 + if (x !== y) { Assert.fail(); } else { nop(); } 40.79 + if (y !== x) { Assert.fail(); } else { nop(); } 40.80 +} 40.81 + 40.82 +function STRICT_NE(x, y) { 40.83 + // Exercise normal evaluation 40.84 + Assert.assertTrue (x !== y); 40.85 + Assert.assertTrue (y !== x); 40.86 + Assert.assertFalse(x === y); 40.87 + Assert.assertFalse(y === x); 40.88 + // Exercise the branch optimizer 40.89 + if (x !== y) { nop(); } else { Assert.fail(); } 40.90 + if (y !== x) { nop(); } else { Assert.fail(); } 40.91 + if (x === y) { Assert.fail(); } else { nop(); } 40.92 + if (y === x) { Assert.fail(); } else { nop(); } 40.93 +} 40.94 + 40.95 +function cmpToAnyNumber(cmp, value) { 40.96 + cmp(1, value); 40.97 + cmp(4294967296, value); 40.98 + cmp(1.2, value); 40.99 + cmp(Infinity, value); 40.100 + cmp(-Infinity, value); 40.101 + cmp(1/Infinity, value); 40.102 + cmp(0, value); 40.103 + cmp(-0, value); 40.104 + cmp(true, value); 40.105 + cmp(false, value); 40.106 +} 40.107 + 40.108 +function notEqualToAnyNumber(value) { 40.109 + cmpToAnyNumber(NE, value); 40.110 + cmpToAnyNumber(STRICT_NE, value); 40.111 +} 40.112 + 40.113 +notEqualToAnyNumber(null); 40.114 +notEqualToAnyNumber(void 0); 40.115 +notEqualToAnyNumber("abc"); 40.116 +notEqualToAnyNumber({}); 40.117 +notEqualToAnyNumber(["xyz"]); 40.118 + 40.119 +function objectWithPrimitiveFunctionNotEqualToAnyNumber(fnName) { 40.120 + var obj = { 40.121 + count: 0 40.122 + }; 40.123 + obj[fnName] = function() { this.count++; return "foo"; }; 40.124 + notEqualToAnyNumber(obj); 40.125 + // Every NE will invoke it 8 times; cmpToAnyNumber has 10 comparisons 40.126 + // STRICT_NE doesn't invoke toString. 40.127 + Assert.assertTrue(80 === obj.count); 40.128 +} 40.129 +objectWithPrimitiveFunctionNotEqualToAnyNumber("valueOf"); 40.130 +objectWithPrimitiveFunctionNotEqualToAnyNumber("toString"); 40.131 + 40.132 +function objectEqualButNotStrictlyEqual(val, obj) { 40.133 + EQ(val, obj); 40.134 + STRICT_NE(val, obj); 40.135 +} 40.136 + 40.137 +function numberEqualButNotStrictlyEqualToObject(num, obj) { 40.138 + objectEqualButNotStrictlyEqual(num, obj); 40.139 + objectEqualButNotStrictlyEqual(num, [obj]); 40.140 + objectEqualButNotStrictlyEqual(num, [[obj]]); 40.141 +} 40.142 + 40.143 +function numberEqualButNotStrictlyEqualToZeroObjects(num) { 40.144 + numberEqualButNotStrictlyEqualToObject(num, [0]); 40.145 + numberEqualButNotStrictlyEqualToObject(num, ""); 40.146 + numberEqualButNotStrictlyEqualToObject(num, []); 40.147 + numberEqualButNotStrictlyEqualToObject(num, "0"); 40.148 +} 40.149 + 40.150 +numberEqualButNotStrictlyEqualToZeroObjects(0); 40.151 +numberEqualButNotStrictlyEqualToZeroObjects(1/Infinity); 40.152 +numberEqualButNotStrictlyEqualToZeroObjects(false); 40.153 + 40.154 +function numberEqualButNotStrictlyEqualToObjectEquivalent(num) { 40.155 + var str = String(num); 40.156 + objectEqualButNotStrictlyEqual(num, str); 40.157 + objectEqualButNotStrictlyEqual(num, { valueOf: function() { return str }}); 40.158 + objectEqualButNotStrictlyEqual(num, { toString: function() { return str }}); 40.159 + objectEqualButNotStrictlyEqual(num, { valueOf: function() { return num }}); 40.160 + objectEqualButNotStrictlyEqual(num, { toString: function() { return num }}); 40.161 +} 40.162 + 40.163 +numberEqualButNotStrictlyEqualToObjectEquivalent(1); 40.164 +numberEqualButNotStrictlyEqualToObjectEquivalent(4294967296); 40.165 +numberEqualButNotStrictlyEqualToObjectEquivalent(1.2); 40.166 +numberEqualButNotStrictlyEqualToObjectEquivalent(Infinity); 40.167 +numberEqualButNotStrictlyEqualToObjectEquivalent(-Infinity); 40.168 +numberEqualButNotStrictlyEqualToObjectEquivalent(1/Infinity); 40.169 +numberEqualButNotStrictlyEqualToObjectEquivalent(0); 40.170 +numberEqualButNotStrictlyEqualToObjectEquivalent(-0); 40.171 + 40.172 +STRICT_EQ(1, new java.lang.Integer(1)); 40.173 +STRICT_EQ(1, new java.lang.Double(1)); 40.174 +STRICT_EQ(1.2, new java.lang.Double(1.2)); 40.175 + 40.176 +function LE(x, y) { 40.177 + // Exercise normal evaluation 40.178 + Assert.assertTrue(x <= y); 40.179 + Assert.assertTrue(y >= x); 40.180 + Assert.assertFalse(x > y); 40.181 + Assert.assertFalse(x < y); 40.182 + // Exercise the branch optimizer 40.183 + if (x <= y) { nop(); } else { Assert.fail(); } 40.184 + if (y >= x) { nop(); } else { Assert.fail(); } 40.185 + if (x > y) { Assert.fail(); } else { nop(); } 40.186 + if (y < x) { Assert.fail(); } else { nop(); } 40.187 +} 40.188 + 40.189 +function mutuallyLessThanOrEqual(x, y) { 40.190 + LE(x, y); 40.191 + LE(y, x); 40.192 +} 40.193 + 40.194 +mutuallyLessThanOrEqual(0, null); 40.195 +mutuallyLessThanOrEqual(false, null); 40.196 +mutuallyLessThanOrEqual(1/Infinity, null); 40.197 + 40.198 +function mutuallyLessThanEqualToObjectWithValue(num, val) { 40.199 + mutuallyLessThanOrEqual(num, { valueOf: function() { return val } }); 40.200 + mutuallyLessThanOrEqual(num, { toString: function() { return val } }); 40.201 +} 40.202 + 40.203 +mutuallyLessThanEqualToObjectWithValue(false, 0); 40.204 +mutuallyLessThanEqualToObjectWithValue(false, ""); 40.205 + 40.206 +mutuallyLessThanEqualToObjectWithValue(true, 1); 40.207 +mutuallyLessThanEqualToObjectWithValue(true, "1"); 40.208 + 40.209 +function lessThanEqualToObjectEquivalent(num) { 40.210 + var str = String(num); 40.211 + mutuallyLessThanOrEqual(num, str); 40.212 + mutuallyLessThanEqualToObjectWithValue(num, num); 40.213 + mutuallyLessThanEqualToObjectWithValue(num, str); 40.214 +} 40.215 + 40.216 +lessThanEqualToObjectEquivalent(1); 40.217 +lessThanEqualToObjectEquivalent(4294967296); 40.218 +lessThanEqualToObjectEquivalent(1.2); 40.219 +lessThanEqualToObjectEquivalent(Infinity); 40.220 +lessThanEqualToObjectEquivalent(-Infinity); 40.221 +lessThanEqualToObjectEquivalent(1/Infinity); 40.222 +lessThanEqualToObjectEquivalent(0); 40.223 +lessThanEqualToObjectEquivalent(-0); 40.224 + 40.225 +function INCOMPARABLE(x, y) { 40.226 + // Exercise normal evaluation 40.227 + Assert.assertFalse(x < y); 40.228 + Assert.assertFalse(x > y); 40.229 + Assert.assertFalse(x <= y); 40.230 + Assert.assertFalse(x >= y); 40.231 + Assert.assertFalse(y < x); 40.232 + Assert.assertFalse(y > x); 40.233 + Assert.assertFalse(y <= x); 40.234 + Assert.assertFalse(y >= x); 40.235 + // Exercise the branch optimizer 40.236 + if (x < y) { Assert.fail(); } else { nop(); } 40.237 + if (x > y) { Assert.fail(); } else { nop(); } 40.238 + if (x <= y) { Assert.fail(); } else { nop(); } 40.239 + if (x >= y) { Assert.fail(); } else { nop(); } 40.240 + if (y < x) { Assert.fail(); } else { nop(); } 40.241 + if (y > x) { Assert.fail(); } else { nop(); } 40.242 + if (y <= x) { Assert.fail(); } else { nop(); } 40.243 + if (y >= x) { Assert.fail(); } else { nop(); } 40.244 +} 40.245 + 40.246 +function isIncomparable(value) { 40.247 + cmpToAnyNumber(INCOMPARABLE, value); 40.248 +} 40.249 + 40.250 +isIncomparable(void 0); 40.251 +isIncomparable({ valueOf: function() { return NaN }}); 40.252 +isIncomparable({ toString: function() { return NaN }}); 40.253 + 40.254 +// Force ScriptRuntime.LT(Object, Object) etc. comparisons 40.255 +function cmpObj(fn, x, y) { 40.256 + fn({valueOf: function() { return x }}, {valueOf: function() { return y }}); 40.257 +} 40.258 + 40.259 +function LT(x, y) { 40.260 + Assert.assertTrue(x < y); 40.261 + Assert.assertTrue(y > x); 40.262 + Assert.assertFalse(x >= y); 40.263 + Assert.assertFalse(y <= x); 40.264 +} 40.265 + 40.266 +cmpObj(LT, 1, 2); 40.267 +cmpObj(LT, 1, "2"); 40.268 +cmpObj(LT, "1", 2); 40.269 +cmpObj(LT, "a", "b"); 40.270 +cmpObj(LT, -Infinity, 0); 40.271 +cmpObj(LT, 0, Infinity); 40.272 +cmpObj(LT, -Infinity, Infinity); 40.273 +cmpObj(INCOMPARABLE, 1, NaN); 40.274 +cmpObj(INCOMPARABLE, NaN, NaN); 40.275 +cmpObj(INCOMPARABLE, "boo", NaN); 40.276 +cmpObj(INCOMPARABLE, 1, "boo"); // boo number value will be NaN 40.277 + 40.278 +// Test that a comparison call site can deoptimize from (int, int) to (object, object) 40.279 +(function(){ 40.280 + var x = [1, 2, "a"]; 40.281 + var y = [2, "3", "b"]; 40.282 + for(var i = 0; i < 3; ++i) { 40.283 + Assert.assertTrue(x[i] < y[i]); 40.284 + } 40.285 +})();
41.1 --- a/test/script/basic/JDK-8055762.js Wed Mar 18 13:57:04 2015 -0700 41.2 +++ b/test/script/basic/JDK-8055762.js Wed Mar 18 18:21:55 2015 -0700 41.3 @@ -74,9 +74,12 @@ 41.4 } 41.5 }; 41.6 41.7 + var a = "a"; 41.8 print(obj["foo"]); 41.9 + print(obj[a + "bc"]); 41.10 print(obj[2]); 41.11 obj.bar = 23; 41.12 + obj[a + "bc"] = 23; 41.13 obj[3] = 23; 41.14 obj.func("hello"); 41.15 }
42.1 --- a/test/script/basic/JDK-8055762.js.EXPECTED Wed Mar 18 13:57:04 2015 -0700 42.2 +++ b/test/script/basic/JDK-8055762.js.EXPECTED Wed Mar 18 18:21:55 2015 -0700 42.3 @@ -1,5 +1,7 @@ 42.4 FOO 42.5 +ABC 42.6 0 42.7 bar set to 23 42.8 +abc set to 23 42.9 [3] set to 23 42.10 func called with hello
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 43.2 +++ b/test/script/basic/JDK-8072426.js Wed Mar 18 18:21:55 2015 -0700 43.3 @@ -0,0 +1,164 @@ 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-8072426: Can't compare Java objects to strings or numbers 43.29 + * 43.30 + * @test 43.31 + * @run 43.32 + */ 43.33 + 43.34 +Assert.assertTrue(java.math.RoundingMode.UP == "UP"); 43.35 + 43.36 +var JSObject = Java.type("jdk.nashorn.api.scripting.JSObject"); 43.37 + 43.38 +// Adds an "isFunction" member to the JSObject that returns the specified value 43.39 +function addIsFunction(isFunction, obj) { 43.40 + obj.isFunction = function() { 43.41 + return isFunction; 43.42 + }; 43.43 + return obj; 43.44 +} 43.45 + 43.46 +function makeJSObjectConstantFunction(value) { 43.47 + return new JSObject(addIsFunction(true, { 43.48 + call: function() { 43.49 + return value; 43.50 + } 43.51 + })); 43.52 +} 43.53 + 43.54 +function makeJSObjectWithMembers(mapping) { 43.55 + return new JSObject({ 43.56 + getMember: function(name) { 43.57 + Assert.assertTrue(mapping.hasOwnProperty(name)); 43.58 + return mapping[name]; 43.59 + }, 43.60 + toNumber: function() { 43.61 + // toNumber no longer invoked 43.62 + Assert.fail(); 43.63 + } 43.64 + }); 43.65 +} 43.66 + 43.67 +// Test JSObjectLinker toInt32/toLong/toNumber 43.68 +function testNumericJSObject(kind, value) { 43.69 + var obj = makeJSObjectWithMembers({ 43.70 + valueOf: makeJSObjectConstantFunction(value) 43.71 + }); 43.72 + 43.73 + if (kind === "double") { 43.74 + // There's no assertEquals(double actual, double expected). There's only 43.75 + // assertEquals(double actual, double expected, double delta). 43.76 + Assert["assertEquals(double,double,double)"](value, obj, 0); 43.77 + } else { 43.78 + Assert["assertEquals(" + kind + ", " + kind + ")"](value, obj); 43.79 + } 43.80 + Assert.assertTrue(value == Number(obj)); 43.81 +} 43.82 +testNumericJSObject("int", 42); 43.83 +testNumericJSObject("long", 4294967296); 43.84 +testNumericJSObject("double", 1.2); 43.85 + 43.86 +// Test fallback from toNumber to toString for numeric conversion when toNumber doesn't exist 43.87 +(function() { 43.88 + var obj = makeJSObjectWithMembers({ 43.89 + valueOf: null, // Explicitly no valueOf 43.90 + toString: makeJSObjectConstantFunction("123") 43.91 + }); 43.92 + Assert["assertEquals(int,int)"](123, obj); 43.93 +})(); 43.94 + 43.95 +// Test fallback from toNumber to toString for numeric conversion when toNumber isn't a callable 43.96 +(function() { 43.97 + var obj = makeJSObjectWithMembers({ 43.98 + valueOf: new JSObject(addIsFunction(false, {})), 43.99 + toString: makeJSObjectConstantFunction("124") 43.100 + }); 43.101 + Assert["assertEquals(int,int)"](124, obj); 43.102 +})(); 43.103 + 43.104 +// Test fallback from toNumber to toString for numeric conversion when toNumber returns a non-primitive 43.105 +(function() { 43.106 + var obj = makeJSObjectWithMembers({ 43.107 + valueOf: makeJSObjectConstantFunction({}), 43.108 + toString: makeJSObjectConstantFunction("125") 43.109 + }); 43.110 + Assert["assertEquals(int,int)"](125, obj); 43.111 +})(); 43.112 + 43.113 +// Test TypeError from toNumber to toString when both return a non-primitive 43.114 +(function() { 43.115 + var obj = makeJSObjectWithMembers({ 43.116 + valueOf: makeJSObjectConstantFunction({}), 43.117 + toString: makeJSObjectConstantFunction({}) 43.118 + }); 43.119 + try { 43.120 + Number(obj); 43.121 + Assert.fail(); // must throw 43.122 + } catch(e) { 43.123 + Assert.assertTrue(e instanceof TypeError); 43.124 + } 43.125 +})(); 43.126 + 43.127 +// Test toString for string conversion 43.128 +(function() { 43.129 + var obj = makeJSObjectWithMembers({ 43.130 + toString: makeJSObjectConstantFunction("Hello") 43.131 + }); 43.132 + Assert.assertTrue("Hello" === String(obj)); 43.133 + Assert["assertEquals(String,String)"]("Hello", obj); 43.134 +})(); 43.135 + 43.136 +// Test fallback from toString to valueOf for string conversion when toString doesn't exist 43.137 +(function() { 43.138 + var obj = makeJSObjectWithMembers({ 43.139 + toString: null, 43.140 + valueOf: makeJSObjectConstantFunction("Hello1") 43.141 + }); 43.142 + Assert.assertTrue("Hello1" === String(obj)); 43.143 + Assert["assertEquals(String,String)"]("Hello1", obj); 43.144 +})(); 43.145 + 43.146 +// Test fallback from toString to valueOf for string conversion when toString is not callable 43.147 +(function() { 43.148 + var obj = makeJSObjectWithMembers({ 43.149 + toString: new JSObject(addIsFunction(false, {})), 43.150 + valueOf: makeJSObjectConstantFunction("Hello2") 43.151 + }); 43.152 + Assert["assertEquals(String,String)"]("Hello2", obj); 43.153 +})(); 43.154 + 43.155 +// Test fallback from toString to valueOf for string conversion when toString returns non-primitive 43.156 +(function() { 43.157 + var obj = makeJSObjectWithMembers({ 43.158 + toString: makeJSObjectConstantFunction({}), 43.159 + valueOf: makeJSObjectConstantFunction("Hello3") 43.160 + }); 43.161 + Assert["assertEquals(String,String)"]("Hello3", obj); 43.162 +})(); 43.163 + 43.164 +// Test toBoolean for JSObject 43.165 +(function() { 43.166 + Assert["assertEquals(boolean,boolean)"](true, new JSObject({})); 43.167 +})();
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 44.2 +++ b/test/script/basic/JDK-8074545.js Wed Mar 18 18:21:55 2015 -0700 44.3 @@ -0,0 +1,1038 @@ 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-8074545: Undefined object values in object literals with spill properties 44.29 + * 44.30 + * @test 44.31 + * @run 44.32 + */ 44.33 + 44.34 +var obj = { 44.35 + "p0": { "x" : 0 }, 44.36 + "p1": { "x" : 1 }, 44.37 + "p2": { "x" : 2 }, 44.38 + "p3": { "x" : 3 }, 44.39 + "p4": { "x" : 4 }, 44.40 + "p5": { "x" : 5 }, 44.41 + "p6": { "x" : 6 }, 44.42 + "p7": { "x" : 7 }, 44.43 + "p8": { "x" : 8 }, 44.44 + "p9": { "x" : 9 }, 44.45 + "p10": { "x" : 10 }, 44.46 + "p11": { "x" : 11 }, 44.47 + "p12": { "x" : 12 }, 44.48 + "p13": { "x" : 13 }, 44.49 + "p14": { "x" : 14 }, 44.50 + "p15": { "x" : 15 }, 44.51 + "p16": { "x" : 16 }, 44.52 + "p17": { "x" : 17 }, 44.53 + "p18": { "x" : 18 }, 44.54 + "p19": { "x" : 19 }, 44.55 + "p20": { "x" : 20 }, 44.56 + "p21": { "x" : 21 }, 44.57 + "p22": { "x" : 22 }, 44.58 + "p23": { "x" : 23 }, 44.59 + "p24": { "x" : 24 }, 44.60 + "p25": { "x" : 25 }, 44.61 + "p26": { "x" : 26 }, 44.62 + "p27": { "x" : 27 }, 44.63 + "p28": { "x" : 28 }, 44.64 + "p29": { "x" : 29 }, 44.65 + "p30": { "x" : 30 }, 44.66 + "p31": { "x" : 31 }, 44.67 + "p32": { "x" : 32 }, 44.68 + "p33": { "x" : 33 }, 44.69 + "p34": { "x" : 34 }, 44.70 + "p35": { "x" : 35 }, 44.71 + "p36": { "x" : 36 }, 44.72 + "p37": { "x" : 37 }, 44.73 + "p38": { "x" : 38 }, 44.74 + "p39": { "x" : 39 }, 44.75 + "p40": { "x" : 40 }, 44.76 + "p41": { "x" : 41 }, 44.77 + "p42": { "x" : 42 }, 44.78 + "p43": { "x" : 43 }, 44.79 + "p44": { "x" : 44 }, 44.80 + "p45": { "x" : 45 }, 44.81 + "p46": { "x" : 46 }, 44.82 + "p47": { "x" : 47 }, 44.83 + "p48": { "x" : 48 }, 44.84 + "p49": { "x" : 49 }, 44.85 + "p50": { "x" : 50 }, 44.86 + "p51": { "x" : 51 }, 44.87 + "p52": { "x" : 52 }, 44.88 + "p53": { "x" : 53 }, 44.89 + "p54": { "x" : 54 }, 44.90 + "p55": { "x" : 55 }, 44.91 + "p56": { "x" : 56 }, 44.92 + "p57": { "x" : 57 }, 44.93 + "p58": { "x" : 58 }, 44.94 + "p59": { "x" : 59 }, 44.95 + "p60": { "x" : 60 }, 44.96 + "p61": { "x" : 61 }, 44.97 + "p62": { "x" : 62 }, 44.98 + "p63": { "x" : 63 }, 44.99 + "p64": { "x" : 64 }, 44.100 + "p65": { "x" : 65 }, 44.101 + "p66": { "x" : 66 }, 44.102 + "p67": { "x" : 67 }, 44.103 + "p68": { "x" : 68 }, 44.104 + "p69": { "x" : 69 }, 44.105 + "p70": { "x" : 70 }, 44.106 + "p71": { "x" : 71 }, 44.107 + "p72": { "x" : 72 }, 44.108 + "p73": { "x" : 73 }, 44.109 + "p74": { "x" : 74 }, 44.110 + "p75": { "x" : 75 }, 44.111 + "p76": { "x" : 76 }, 44.112 + "p77": { "x" : 77 }, 44.113 + "p78": { "x" : 78 }, 44.114 + "p79": { "x" : 79 }, 44.115 + "p80": { "x" : 80 }, 44.116 + "p81": { "x" : 81 }, 44.117 + "p82": { "x" : 82 }, 44.118 + "p83": { "x" : 83 }, 44.119 + "p84": { "x" : 84 }, 44.120 + "p85": { "x" : 85 }, 44.121 + "p86": { "x" : 86 }, 44.122 + "p87": { "x" : 87 }, 44.123 + "p88": { "x" : 88 }, 44.124 + "p89": { "x" : 89 }, 44.125 + "p90": { "x" : 90 }, 44.126 + "p91": { "x" : 91 }, 44.127 + "p92": { "x" : 92 }, 44.128 + "p93": { "x" : 93 }, 44.129 + "p94": { "x" : 94 }, 44.130 + "p95": { "x" : 95 }, 44.131 + "p96": { "x" : 96 }, 44.132 + "p97": { "x" : 97 }, 44.133 + "p98": { "x" : 98 }, 44.134 + "p99": { "x" : 99 }, 44.135 + "p100": { "x" : 100 }, 44.136 + "p101": { "x" : 101 }, 44.137 + "p102": { "x" : 102 }, 44.138 + "p103": { "x" : 103 }, 44.139 + "p104": { "x" : 104 }, 44.140 + "p105": { "x" : 105 }, 44.141 + "p106": { "x" : 106 }, 44.142 + "p107": { "x" : 107 }, 44.143 + "p108": { "x" : 108 }, 44.144 + "p109": { "x" : 109 }, 44.145 + "p110": { "x" : 110 }, 44.146 + "p111": { "x" : 111 }, 44.147 + "p112": { "x" : 112 }, 44.148 + "p113": { "x" : 113 }, 44.149 + "p114": { "x" : 114 }, 44.150 + "p115": { "x" : 115 }, 44.151 + "p116": { "x" : 116 }, 44.152 + "p117": { "x" : 117 }, 44.153 + "p118": { "x" : 118 }, 44.154 + "p119": { "x" : 119 }, 44.155 + "p120": { "x" : 120 }, 44.156 + "p121": { "x" : 121 }, 44.157 + "p122": { "x" : 122 }, 44.158 + "p123": { "x" : 123 }, 44.159 + "p124": { "x" : 124 }, 44.160 + "p125": { "x" : 125 }, 44.161 + "p126": { "x" : 126 }, 44.162 + "p127": { "x" : 127 }, 44.163 + "p128": { "x" : 128 }, 44.164 + "p129": { "x" : 129 }, 44.165 + "p130": { "x" : 130 }, 44.166 + "p131": { "x" : 131 }, 44.167 + "p132": { "x" : 132 }, 44.168 + "p133": { "x" : 133 }, 44.169 + "p134": { "x" : 134 }, 44.170 + "p135": { "x" : 135 }, 44.171 + "p136": { "x" : 136 }, 44.172 + "p137": { "x" : 137 }, 44.173 + "p138": { "x" : 138 }, 44.174 + "p139": { "x" : 139 }, 44.175 + "p140": { "x" : 140 }, 44.176 + "p141": { "x" : 141 }, 44.177 + "p142": { "x" : 142 }, 44.178 + "p143": { "x" : 143 }, 44.179 + "p144": { "x" : 144 }, 44.180 + "p145": { "x" : 145 }, 44.181 + "p146": { "x" : 146 }, 44.182 + "p147": { "x" : 147 }, 44.183 + "p148": { "x" : 148 }, 44.184 + "p149": { "x" : 149 }, 44.185 + "p150": { "x" : 150 }, 44.186 + "p151": { "x" : 151 }, 44.187 + "p152": { "x" : 152 }, 44.188 + "p153": { "x" : 153 }, 44.189 + "p154": { "x" : 154 }, 44.190 + "p155": { "x" : 155 }, 44.191 + "p156": { "x" : 156 }, 44.192 + "p157": { "x" : 157 }, 44.193 + "p158": { "x" : 158 }, 44.194 + "p159": { "x" : 159 }, 44.195 + "p160": { "x" : 160 }, 44.196 + "p161": { "x" : 161 }, 44.197 + "p162": { "x" : 162 }, 44.198 + "p163": { "x" : 163 }, 44.199 + "p164": { "x" : 164 }, 44.200 + "p165": { "x" : 165 }, 44.201 + "p166": { "x" : 166 }, 44.202 + "p167": { "x" : 167 }, 44.203 + "p168": { "x" : 168 }, 44.204 + "p169": { "x" : 169 }, 44.205 + "p170": { "x" : 170 }, 44.206 + "p171": { "x" : 171 }, 44.207 + "p172": { "x" : 172 }, 44.208 + "p173": { "x" : 173 }, 44.209 + "p174": { "x" : 174 }, 44.210 + "p175": { "x" : 175 }, 44.211 + "p176": { "x" : 176 }, 44.212 + "p177": { "x" : 177 }, 44.213 + "p178": { "x" : 178 }, 44.214 + "p179": { "x" : 179 }, 44.215 + "p180": { "x" : 180 }, 44.216 + "p181": { "x" : 181 }, 44.217 + "p182": { "x" : 182 }, 44.218 + "p183": { "x" : 183 }, 44.219 + "p184": { "x" : 184 }, 44.220 + "p185": { "x" : 185 }, 44.221 + "p186": { "x" : 186 }, 44.222 + "p187": { "x" : 187 }, 44.223 + "p188": { "x" : 188 }, 44.224 + "p189": { "x" : 189 }, 44.225 + "p190": { "x" : 190 }, 44.226 + "p191": { "x" : 191 }, 44.227 + "p192": { "x" : 192 }, 44.228 + "p193": { "x" : 193 }, 44.229 + "p194": { "x" : 194 }, 44.230 + "p195": { "x" : 195 }, 44.231 + "p196": { "x" : 196 }, 44.232 + "p197": { "x" : 197 }, 44.233 + "p198": { "x" : 198 }, 44.234 + "p199": { "x" : 199 }, 44.235 + "p200": { "x" : 200 }, 44.236 + "p201": { "x" : 201 }, 44.237 + "p202": { "x" : 202 }, 44.238 + "p203": { "x" : 203 }, 44.239 + "p204": { "x" : 204 }, 44.240 + "p205": { "x" : 205 }, 44.241 + "p206": { "x" : 206 }, 44.242 + "p207": { "x" : 207 }, 44.243 + "p208": { "x" : 208 }, 44.244 + "p209": { "x" : 209 }, 44.245 + "p210": { "x" : 210 }, 44.246 + "p211": { "x" : 211 }, 44.247 + "p212": { "x" : 212 }, 44.248 + "p213": { "x" : 213 }, 44.249 + "p214": { "x" : 214 }, 44.250 + "p215": { "x" : 215 }, 44.251 + "p216": { "x" : 216 }, 44.252 + "p217": { "x" : 217 }, 44.253 + "p218": { "x" : 218 }, 44.254 + "p219": { "x" : 219 }, 44.255 + "p220": { "x" : 220 }, 44.256 + "p221": { "x" : 221 }, 44.257 + "p222": { "x" : 222 }, 44.258 + "p223": { "x" : 223 }, 44.259 + "p224": { "x" : 224 }, 44.260 + "p225": { "x" : 225 }, 44.261 + "p226": { "x" : 226 }, 44.262 + "p227": { "x" : 227 }, 44.263 + "p228": { "x" : 228 }, 44.264 + "p229": { "x" : 229 }, 44.265 + "p230": { "x" : 230 }, 44.266 + "p231": { "x" : 231 }, 44.267 + "p232": { "x" : 232 }, 44.268 + "p233": { "x" : 233 }, 44.269 + "p234": { "x" : 234 }, 44.270 + "p235": { "x" : 235 }, 44.271 + "p236": { "x" : 236 }, 44.272 + "p237": { "x" : 237 }, 44.273 + "p238": { "x" : 238 }, 44.274 + "p239": { "x" : 239 }, 44.275 + "p240": { "x" : 240 }, 44.276 + "p241": { "x" : 241 }, 44.277 + "p242": { "x" : 242 }, 44.278 + "p243": { "x" : 243 }, 44.279 + "p244": { "x" : 244 }, 44.280 + "p245": { "x" : 245 }, 44.281 + "p246": { "x" : 246 }, 44.282 + "p247": { "x" : 247 }, 44.283 + "p248": { "x" : 248 }, 44.284 + "p249": { "x" : 249 }, 44.285 + "p250": { "x" : 250 }, 44.286 + "p251": { "x" : 251 }, 44.287 + "p252": { "x" : 252 }, 44.288 + "p253": { "x" : 253 }, 44.289 + "p254": { "x" : 254 }, 44.290 + "p255": { "x" : 255 }, 44.291 + "p256": { "x" : 256 }, 44.292 + "p257": { "x" : 257 }, 44.293 + "p258": { "x" : 258 }, 44.294 + "p259": { "x" : 259 }, 44.295 + "p260": { "x" : 260 }, 44.296 + "p261": { "x" : 261 }, 44.297 + "p262": { "x" : 262 }, 44.298 + "p263": { "x" : 263 }, 44.299 + "p264": { "x" : 264 }, 44.300 + "p265": { "x" : 265 }, 44.301 + "p266": { "x" : 266 }, 44.302 + "p267": { "x" : 267 }, 44.303 + "p268": { "x" : 268 }, 44.304 + "p269": { "x" : 269 }, 44.305 + "p270": { "x" : 270 }, 44.306 + "p271": { "x" : 271 }, 44.307 + "p272": { "x" : 272 }, 44.308 + "p273": { "x" : 273 }, 44.309 + "p274": { "x" : 274 }, 44.310 + "p275": { "x" : 275 }, 44.311 + "p276": { "x" : 276 }, 44.312 + "p277": { "x" : 277 }, 44.313 + "p278": { "x" : 278 }, 44.314 + "p279": { "x" : 279 }, 44.315 + "p280": { "x" : 280 }, 44.316 + "p281": { "x" : 281 }, 44.317 + "p282": { "x" : 282 }, 44.318 + "p283": { "x" : 283 }, 44.319 + "p284": { "x" : 284 }, 44.320 + "p285": { "x" : 285 }, 44.321 + "p286": { "x" : 286 }, 44.322 + "p287": { "x" : 287 }, 44.323 + "p288": { "x" : 288 }, 44.324 + "p289": { "x" : 289 }, 44.325 + "p290": { "x" : 290 }, 44.326 + "p291": { "x" : 291 }, 44.327 + "p292": { "x" : 292 }, 44.328 + "p293": { "x" : 293 }, 44.329 + "p294": { "x" : 294 }, 44.330 + "p295": { "x" : 295 }, 44.331 + "p296": { "x" : 296 }, 44.332 + "p297": { "x" : 297 }, 44.333 + "p298": { "x" : 298 }, 44.334 + "p299": { "x" : 299 }, 44.335 + "p300": { "x" : 300 }, 44.336 + "p301": { "x" : 301 }, 44.337 + "p302": { "x" : 302 }, 44.338 + "p303": { "x" : 303 }, 44.339 + "p304": { "x" : 304 }, 44.340 + "p305": { "x" : 305 }, 44.341 + "p306": { "x" : 306 }, 44.342 + "p307": { "x" : 307 }, 44.343 + "p308": { "x" : 308 }, 44.344 + "p309": { "x" : 309 }, 44.345 + "p310": { "x" : 310 }, 44.346 + "p311": { "x" : 311 }, 44.347 + "p312": { "x" : 312 }, 44.348 + "p313": { "x" : 313 }, 44.349 + "p314": { "x" : 314 }, 44.350 + "p315": { "x" : 315 }, 44.351 + "p316": { "x" : 316 }, 44.352 + "p317": { "x" : 317 }, 44.353 + "p318": { "x" : 318 }, 44.354 + "p319": { "x" : 319 }, 44.355 + "p320": { "x" : 320 }, 44.356 + "p321": { "x" : 321 }, 44.357 + "p322": { "x" : 322 }, 44.358 + "p323": { "x" : 323 }, 44.359 + "p324": { "x" : 324 }, 44.360 + "p325": { "x" : 325 }, 44.361 + "p326": { "x" : 326 }, 44.362 + "p327": { "x" : 327 }, 44.363 + "p328": { "x" : 328 }, 44.364 + "p329": { "x" : 329 }, 44.365 + "p330": { "x" : 330 }, 44.366 + "p331": { "x" : 331 }, 44.367 + "p332": { "x" : 332 }, 44.368 + "p333": { "x" : 333 }, 44.369 + "p334": { "x" : 334 }, 44.370 + "p335": { "x" : 335 }, 44.371 + "p336": { "x" : 336 }, 44.372 + "p337": { "x" : 337 }, 44.373 + "p338": { "x" : 338 }, 44.374 + "p339": { "x" : 339 }, 44.375 + "p340": { "x" : 340 }, 44.376 + "p341": { "x" : 341 }, 44.377 + "p342": { "x" : 342 }, 44.378 + "p343": { "x" : 343 }, 44.379 + "p344": { "x" : 344 }, 44.380 + "p345": { "x" : 345 }, 44.381 + "p346": { "x" : 346 }, 44.382 + "p347": { "x" : 347 }, 44.383 + "p348": { "x" : 348 }, 44.384 + "p349": { "x" : 349 }, 44.385 + "p350": { "x" : 350 }, 44.386 + "p351": { "x" : 351 }, 44.387 + "p352": { "x" : 352 }, 44.388 + "p353": { "x" : 353 }, 44.389 + "p354": { "x" : 354 }, 44.390 + "p355": { "x" : 355 }, 44.391 + "p356": { "x" : 356 }, 44.392 + "p357": { "x" : 357 }, 44.393 + "p358": { "x" : 358 }, 44.394 + "p359": { "x" : 359 }, 44.395 + "p360": { "x" : 360 }, 44.396 + "p361": { "x" : 361 }, 44.397 + "p362": { "x" : 362 }, 44.398 + "p363": { "x" : 363 }, 44.399 + "p364": { "x" : 364 }, 44.400 + "p365": { "x" : 365 }, 44.401 + "p366": { "x" : 366 }, 44.402 + "p367": { "x" : 367 }, 44.403 + "p368": { "x" : 368 }, 44.404 + "p369": { "x" : 369 }, 44.405 + "p370": { "x" : 370 }, 44.406 + "p371": { "x" : 371 }, 44.407 + "p372": { "x" : 372 }, 44.408 + "p373": { "x" : 373 }, 44.409 + "p374": { "x" : 374 }, 44.410 + "p375": { "x" : 375 }, 44.411 + "p376": { "x" : 376 }, 44.412 + "p377": { "x" : 377 }, 44.413 + "p378": { "x" : 378 }, 44.414 + "p379": { "x" : 379 }, 44.415 + "p380": { "x" : 380 }, 44.416 + "p381": { "x" : 381 }, 44.417 + "p382": { "x" : 382 }, 44.418 + "p383": { "x" : 383 }, 44.419 + "p384": { "x" : 384 }, 44.420 + "p385": { "x" : 385 }, 44.421 + "p386": { "x" : 386 }, 44.422 + "p387": { "x" : 387 }, 44.423 + "p388": { "x" : 388 }, 44.424 + "p389": { "x" : 389 }, 44.425 + "p390": { "x" : 390 }, 44.426 + "p391": { "x" : 391 }, 44.427 + "p392": { "x" : 392 }, 44.428 + "p393": { "x" : 393 }, 44.429 + "p394": { "x" : 394 }, 44.430 + "p395": { "x" : 395 }, 44.431 + "p396": { "x" : 396 }, 44.432 + "p397": { "x" : 397 }, 44.433 + "p398": { "x" : 398 }, 44.434 + "p399": { "x" : 399 }, 44.435 + "p400": { "x" : 400 }, 44.436 + "p401": { "x" : 401 }, 44.437 + "p402": { "x" : 402 }, 44.438 + "p403": { "x" : 403 }, 44.439 + "p404": { "x" : 404 }, 44.440 + "p405": { "x" : 405 }, 44.441 + "p406": { "x" : 406 }, 44.442 + "p407": { "x" : 407 }, 44.443 + "p408": { "x" : 408 }, 44.444 + "p409": { "x" : 409 }, 44.445 + "p410": { "x" : 410 }, 44.446 + "p411": { "x" : 411 }, 44.447 + "p412": { "x" : 412 }, 44.448 + "p413": { "x" : 413 }, 44.449 + "p414": { "x" : 414 }, 44.450 + "p415": { "x" : 415 }, 44.451 + "p416": { "x" : 416 }, 44.452 + "p417": { "x" : 417 }, 44.453 + "p418": { "x" : 418 }, 44.454 + "p419": { "x" : 419 }, 44.455 + "p420": { "x" : 420 }, 44.456 + "p421": { "x" : 421 }, 44.457 + "p422": { "x" : 422 }, 44.458 + "p423": { "x" : 423 }, 44.459 + "p424": { "x" : 424 }, 44.460 + "p425": { "x" : 425 }, 44.461 + "p426": { "x" : 426 }, 44.462 + "p427": { "x" : 427 }, 44.463 + "p428": { "x" : 428 }, 44.464 + "p429": { "x" : 429 }, 44.465 + "p430": { "x" : 430 }, 44.466 + "p431": { "x" : 431 }, 44.467 + "p432": { "x" : 432 }, 44.468 + "p433": { "x" : 433 }, 44.469 + "p434": { "x" : 434 }, 44.470 + "p435": { "x" : 435 }, 44.471 + "p436": { "x" : 436 }, 44.472 + "p437": { "x" : 437 }, 44.473 + "p438": { "x" : 438 }, 44.474 + "p439": { "x" : 439 }, 44.475 + "p440": { "x" : 440 }, 44.476 + "p441": { "x" : 441 }, 44.477 + "p442": { "x" : 442 }, 44.478 + "p443": { "x" : 443 }, 44.479 + "p444": { "x" : 444 }, 44.480 + "p445": { "x" : 445 }, 44.481 + "p446": { "x" : 446 }, 44.482 + "p447": { "x" : 447 }, 44.483 + "p448": { "x" : 448 }, 44.484 + "p449": { "x" : 449 }, 44.485 + "p450": { "x" : 450 }, 44.486 + "p451": { "x" : 451 }, 44.487 + "p452": { "x" : 452 }, 44.488 + "p453": { "x" : 453 }, 44.489 + "p454": { "x" : 454 }, 44.490 + "p455": { "x" : 455 }, 44.491 + "p456": { "x" : 456 }, 44.492 + "p457": { "x" : 457 }, 44.493 + "p458": { "x" : 458 }, 44.494 + "p459": { "x" : 459 }, 44.495 + "p460": { "x" : 460 }, 44.496 + "p461": { "x" : 461 }, 44.497 + "p462": { "x" : 462 }, 44.498 + "p463": { "x" : 463 }, 44.499 + "p464": { "x" : 464 }, 44.500 + "p465": { "x" : 465 }, 44.501 + "p466": { "x" : 466 }, 44.502 + "p467": { "x" : 467 }, 44.503 + "p468": { "x" : 468 }, 44.504 + "p469": { "x" : 469 }, 44.505 + "p470": { "x" : 470 }, 44.506 + "p471": { "x" : 471 }, 44.507 + "p472": { "x" : 472 }, 44.508 + "p473": { "x" : 473 }, 44.509 + "p474": { "x" : 474 }, 44.510 + "p475": { "x" : 475 }, 44.511 + "p476": { "x" : 476 }, 44.512 + "p477": { "x" : 477 }, 44.513 + "p478": { "x" : 478 }, 44.514 + "p479": { "x" : 479 }, 44.515 + "p480": { "x" : 480 }, 44.516 + "p481": { "x" : 481 }, 44.517 + "p482": { "x" : 482 }, 44.518 + "p483": { "x" : 483 }, 44.519 + "p484": { "x" : 484 }, 44.520 + "p485": { "x" : 485 }, 44.521 + "p486": { "x" : 486 }, 44.522 + "p487": { "x" : 487 }, 44.523 + "p488": { "x" : 488 }, 44.524 + "p489": { "x" : 489 }, 44.525 + "p490": { "x" : 490 }, 44.526 + "p491": { "x" : 491 }, 44.527 + "p492": { "x" : 492 }, 44.528 + "p493": { "x" : 493 }, 44.529 + "p494": { "x" : 494 }, 44.530 + "p495": { "x" : 495 }, 44.531 + "p496": { "x" : 496 }, 44.532 + "p497": { "x" : 497 }, 44.533 + "p498": { "x" : 498 }, 44.534 + "p499": { "x" : 499 }, 44.535 + "p500": { "x" : 500 }, 44.536 + "p501": { "x" : 501 }, 44.537 + "p502": { "x" : 502 }, 44.538 + "p503": { "x" : 503 }, 44.539 + "p504": { "x" : 504 }, 44.540 + "p505": { "x" : 505 }, 44.541 + "p506": { "x" : 506 }, 44.542 + "p507": { "x" : 507 }, 44.543 + "p508": { "x" : 508 }, 44.544 + "p509": { "x" : 509 }, 44.545 + "p510": { "x" : 510 }, 44.546 + "p511": { "x" : 511 }, 44.547 + "p512": { "x" : 512 }, 44.548 + "p513": { "x" : 513 }, 44.549 + "p514": { "x" : 514 }, 44.550 + "p515": { "x" : 515 }, 44.551 + "p516": { "x" : 516 }, 44.552 + "p517": { "x" : 517 }, 44.553 + "p518": { "x" : 518 }, 44.554 + "p519": { "x" : 519 }, 44.555 + "p520": { "x" : 520 }, 44.556 + "p521": { "x" : 521 }, 44.557 + "p522": { "x" : 522 }, 44.558 + "p523": { "x" : 523 }, 44.559 + "p524": { "x" : 524 }, 44.560 + "p525": { "x" : 525 }, 44.561 + "p526": { "x" : 526 }, 44.562 + "p527": { "x" : 527 }, 44.563 + "p528": { "x" : 528 }, 44.564 + "p529": { "x" : 529 }, 44.565 + "p530": { "x" : 530 }, 44.566 + "p531": { "x" : 531 }, 44.567 + "p532": { "x" : 532 }, 44.568 + "p533": { "x" : 533 }, 44.569 + "p534": { "x" : 534 }, 44.570 + "p535": { "x" : 535 }, 44.571 + "p536": { "x" : 536 }, 44.572 + "p537": { "x" : 537 }, 44.573 + "p538": { "x" : 538 }, 44.574 + "p539": { "x" : 539 }, 44.575 + "p540": { "x" : 540 }, 44.576 + "p541": { "x" : 541 }, 44.577 + "p542": { "x" : 542 }, 44.578 + "p543": { "x" : 543 }, 44.579 + "p544": { "x" : 544 }, 44.580 + "p545": { "x" : 545 }, 44.581 + "p546": { "x" : 546 }, 44.582 + "p547": { "x" : 547 }, 44.583 + "p548": { "x" : 548 }, 44.584 + "p549": { "x" : 549 }, 44.585 + "p550": { "x" : 550 }, 44.586 + "p551": { "x" : 551 }, 44.587 + "p552": { "x" : 552 }, 44.588 + "p553": { "x" : 553 }, 44.589 + "p554": { "x" : 554 }, 44.590 + "p555": { "x" : 555 }, 44.591 + "p556": { "x" : 556 }, 44.592 + "p557": { "x" : 557 }, 44.593 + "p558": { "x" : 558 }, 44.594 + "p559": { "x" : 559 }, 44.595 + "p560": { "x" : 560 }, 44.596 + "p561": { "x" : 561 }, 44.597 + "p562": { "x" : 562 }, 44.598 + "p563": { "x" : 563 }, 44.599 + "p564": { "x" : 564 }, 44.600 + "p565": { "x" : 565 }, 44.601 + "p566": { "x" : 566 }, 44.602 + "p567": { "x" : 567 }, 44.603 + "p568": { "x" : 568 }, 44.604 + "p569": { "x" : 569 }, 44.605 + "p570": { "x" : 570 }, 44.606 + "p571": { "x" : 571 }, 44.607 + "p572": { "x" : 572 }, 44.608 + "p573": { "x" : 573 }, 44.609 + "p574": { "x" : 574 }, 44.610 + "p575": { "x" : 575 }, 44.611 + "p576": { "x" : 576 }, 44.612 + "p577": { "x" : 577 }, 44.613 + "p578": { "x" : 578 }, 44.614 + "p579": { "x" : 579 }, 44.615 + "p580": { "x" : 580 }, 44.616 + "p581": { "x" : 581 }, 44.617 + "p582": { "x" : 582 }, 44.618 + "p583": { "x" : 583 }, 44.619 + "p584": { "x" : 584 }, 44.620 + "p585": { "x" : 585 }, 44.621 + "p586": { "x" : 586 }, 44.622 + "p587": { "x" : 587 }, 44.623 + "p588": { "x" : 588 }, 44.624 + "p589": { "x" : 589 }, 44.625 + "p590": { "x" : 590 }, 44.626 + "p591": { "x" : 591 }, 44.627 + "p592": { "x" : 592 }, 44.628 + "p593": { "x" : 593 }, 44.629 + "p594": { "x" : 594 }, 44.630 + "p595": { "x" : 595 }, 44.631 + "p596": { "x" : 596 }, 44.632 + "p597": { "x" : 597 }, 44.633 + "p598": { "x" : 598 }, 44.634 + "p599": { "x" : 599 }, 44.635 + "p600": { "x" : 600 }, 44.636 + "p601": { "x" : 601 }, 44.637 + "p602": { "x" : 602 }, 44.638 + "p603": { "x" : 603 }, 44.639 + "p604": { "x" : 604 }, 44.640 + "p605": { "x" : 605 }, 44.641 + "p606": { "x" : 606 }, 44.642 + "p607": { "x" : 607 }, 44.643 + "p608": { "x" : 608 }, 44.644 + "p609": { "x" : 609 }, 44.645 + "p610": { "x" : 610 }, 44.646 + "p611": { "x" : 611 }, 44.647 + "p612": { "x" : 612 }, 44.648 + "p613": { "x" : 613 }, 44.649 + "p614": { "x" : 614 }, 44.650 + "p615": { "x" : 615 }, 44.651 + "p616": { "x" : 616 }, 44.652 + "p617": { "x" : 617 }, 44.653 + "p618": { "x" : 618 }, 44.654 + "p619": { "x" : 619 }, 44.655 + "p620": { "x" : 620 }, 44.656 + "p621": { "x" : 621 }, 44.657 + "p622": { "x" : 622 }, 44.658 + "p623": { "x" : 623 }, 44.659 + "p624": { "x" : 624 }, 44.660 + "p625": { "x" : 625 }, 44.661 + "p626": { "x" : 626 }, 44.662 + "p627": { "x" : 627 }, 44.663 + "p628": { "x" : 628 }, 44.664 + "p629": { "x" : 629 }, 44.665 + "p630": { "x" : 630 }, 44.666 + "p631": { "x" : 631 }, 44.667 + "p632": { "x" : 632 }, 44.668 + "p633": { "x" : 633 }, 44.669 + "p634": { "x" : 634 }, 44.670 + "p635": { "x" : 635 }, 44.671 + "p636": { "x" : 636 }, 44.672 + "p637": { "x" : 637 }, 44.673 + "p638": { "x" : 638 }, 44.674 + "p639": { "x" : 639 }, 44.675 + "p640": { "x" : 640 }, 44.676 + "p641": { "x" : 641 }, 44.677 + "p642": { "x" : 642 }, 44.678 + "p643": { "x" : 643 }, 44.679 + "p644": { "x" : 644 }, 44.680 + "p645": { "x" : 645 }, 44.681 + "p646": { "x" : 646 }, 44.682 + "p647": { "x" : 647 }, 44.683 + "p648": { "x" : 648 }, 44.684 + "p649": { "x" : 649 }, 44.685 + "p650": { "x" : 650 }, 44.686 + "p651": { "x" : 651 }, 44.687 + "p652": { "x" : 652 }, 44.688 + "p653": { "x" : 653 }, 44.689 + "p654": { "x" : 654 }, 44.690 + "p655": { "x" : 655 }, 44.691 + "p656": { "x" : 656 }, 44.692 + "p657": { "x" : 657 }, 44.693 + "p658": { "x" : 658 }, 44.694 + "p659": { "x" : 659 }, 44.695 + "p660": { "x" : 660 }, 44.696 + "p661": { "x" : 661 }, 44.697 + "p662": { "x" : 662 }, 44.698 + "p663": { "x" : 663 }, 44.699 + "p664": { "x" : 664 }, 44.700 + "p665": { "x" : 665 }, 44.701 + "p666": { "x" : 666 }, 44.702 + "p667": { "x" : 667 }, 44.703 + "p668": { "x" : 668 }, 44.704 + "p669": { "x" : 669 }, 44.705 + "p670": { "x" : 670 }, 44.706 + "p671": { "x" : 671 }, 44.707 + "p672": { "x" : 672 }, 44.708 + "p673": { "x" : 673 }, 44.709 + "p674": { "x" : 674 }, 44.710 + "p675": { "x" : 675 }, 44.711 + "p676": { "x" : 676 }, 44.712 + "p677": { "x" : 677 }, 44.713 + "p678": { "x" : 678 }, 44.714 + "p679": { "x" : 679 }, 44.715 + "p680": { "x" : 680 }, 44.716 + "p681": { "x" : 681 }, 44.717 + "p682": { "x" : 682 }, 44.718 + "p683": { "x" : 683 }, 44.719 + "p684": { "x" : 684 }, 44.720 + "p685": { "x" : 685 }, 44.721 + "p686": { "x" : 686 }, 44.722 + "p687": { "x" : 687 }, 44.723 + "p688": { "x" : 688 }, 44.724 + "p689": { "x" : 689 }, 44.725 + "p690": { "x" : 690 }, 44.726 + "p691": { "x" : 691 }, 44.727 + "p692": { "x" : 692 }, 44.728 + "p693": { "x" : 693 }, 44.729 + "p694": { "x" : 694 }, 44.730 + "p695": { "x" : 695 }, 44.731 + "p696": { "x" : 696 }, 44.732 + "p697": { "x" : 697 }, 44.733 + "p698": { "x" : 698 }, 44.734 + "p699": { "x" : 699 }, 44.735 + "p700": { "x" : 700 }, 44.736 + "p701": { "x" : 701 }, 44.737 + "p702": { "x" : 702 }, 44.738 + "p703": { "x" : 703 }, 44.739 + "p704": { "x" : 704 }, 44.740 + "p705": { "x" : 705 }, 44.741 + "p706": { "x" : 706 }, 44.742 + "p707": { "x" : 707 }, 44.743 + "p708": { "x" : 708 }, 44.744 + "p709": { "x" : 709 }, 44.745 + "p710": { "x" : 710 }, 44.746 + "p711": { "x" : 711 }, 44.747 + "p712": { "x" : 712 }, 44.748 + "p713": { "x" : 713 }, 44.749 + "p714": { "x" : 714 }, 44.750 + "p715": { "x" : 715 }, 44.751 + "p716": { "x" : 716 }, 44.752 + "p717": { "x" : 717 }, 44.753 + "p718": { "x" : 718 }, 44.754 + "p719": { "x" : 719 }, 44.755 + "p720": { "x" : 720 }, 44.756 + "p721": { "x" : 721 }, 44.757 + "p722": { "x" : 722 }, 44.758 + "p723": { "x" : 723 }, 44.759 + "p724": { "x" : 724 }, 44.760 + "p725": { "x" : 725 }, 44.761 + "p726": { "x" : 726 }, 44.762 + "p727": { "x" : 727 }, 44.763 + "p728": { "x" : 728 }, 44.764 + "p729": { "x" : 729 }, 44.765 + "p730": { "x" : 730 }, 44.766 + "p731": { "x" : 731 }, 44.767 + "p732": { "x" : 732 }, 44.768 + "p733": { "x" : 733 }, 44.769 + "p734": { "x" : 734 }, 44.770 + "p735": { "x" : 735 }, 44.771 + "p736": { "x" : 736 }, 44.772 + "p737": { "x" : 737 }, 44.773 + "p738": { "x" : 738 }, 44.774 + "p739": { "x" : 739 }, 44.775 + "p740": { "x" : 740 }, 44.776 + "p741": { "x" : 741 }, 44.777 + "p742": { "x" : 742 }, 44.778 + "p743": { "x" : 743 }, 44.779 + "p744": { "x" : 744 }, 44.780 + "p745": { "x" : 745 }, 44.781 + "p746": { "x" : 746 }, 44.782 + "p747": { "x" : 747 }, 44.783 + "p748": { "x" : 748 }, 44.784 + "p749": { "x" : 749 }, 44.785 + "p750": { "x" : 750 }, 44.786 + "p751": { "x" : 751 }, 44.787 + "p752": { "x" : 752 }, 44.788 + "p753": { "x" : 753 }, 44.789 + "p754": { "x" : 754 }, 44.790 + "p755": { "x" : 755 }, 44.791 + "p756": { "x" : 756 }, 44.792 + "p757": { "x" : 757 }, 44.793 + "p758": { "x" : 758 }, 44.794 + "p759": { "x" : 759 }, 44.795 + "p760": { "x" : 760 }, 44.796 + "p761": { "x" : 761 }, 44.797 + "p762": { "x" : 762 }, 44.798 + "p763": { "x" : 763 }, 44.799 + "p764": { "x" : 764 }, 44.800 + "p765": { "x" : 765 }, 44.801 + "p766": { "x" : 766 }, 44.802 + "p767": { "x" : 767 }, 44.803 + "p768": { "x" : 768 }, 44.804 + "p769": { "x" : 769 }, 44.805 + "p770": { "x" : 770 }, 44.806 + "p771": { "x" : 771 }, 44.807 + "p772": { "x" : 772 }, 44.808 + "p773": { "x" : 773 }, 44.809 + "p774": { "x" : 774 }, 44.810 + "p775": { "x" : 775 }, 44.811 + "p776": { "x" : 776 }, 44.812 + "p777": { "x" : 777 }, 44.813 + "p778": { "x" : 778 }, 44.814 + "p779": { "x" : 779 }, 44.815 + "p780": { "x" : 780 }, 44.816 + "p781": { "x" : 781 }, 44.817 + "p782": { "x" : 782 }, 44.818 + "p783": { "x" : 783 }, 44.819 + "p784": { "x" : 784 }, 44.820 + "p785": { "x" : 785 }, 44.821 + "p786": { "x" : 786 }, 44.822 + "p787": { "x" : 787 }, 44.823 + "p788": { "x" : 788 }, 44.824 + "p789": { "x" : 789 }, 44.825 + "p790": { "x" : 790 }, 44.826 + "p791": { "x" : 791 }, 44.827 + "p792": { "x" : 792 }, 44.828 + "p793": { "x" : 793 }, 44.829 + "p794": { "x" : 794 }, 44.830 + "p795": { "x" : 795 }, 44.831 + "p796": { "x" : 796 }, 44.832 + "p797": { "x" : 797 }, 44.833 + "p798": { "x" : 798 }, 44.834 + "p799": { "x" : 799 }, 44.835 + "p800": { "x" : 800 }, 44.836 + "p801": { "x" : 801 }, 44.837 + "p802": { "x" : 802 }, 44.838 + "p803": { "x" : 803 }, 44.839 + "p804": { "x" : 804 }, 44.840 + "p805": { "x" : 805 }, 44.841 + "p806": { "x" : 806 }, 44.842 + "p807": { "x" : 807 }, 44.843 + "p808": { "x" : 808 }, 44.844 + "p809": { "x" : 809 }, 44.845 + "p810": { "x" : 810 }, 44.846 + "p811": { "x" : 811 }, 44.847 + "p812": { "x" : 812 }, 44.848 + "p813": { "x" : 813 }, 44.849 + "p814": { "x" : 814 }, 44.850 + "p815": { "x" : 815 }, 44.851 + "p816": { "x" : 816 }, 44.852 + "p817": { "x" : 817 }, 44.853 + "p818": { "x" : 818 }, 44.854 + "p819": { "x" : 819 }, 44.855 + "p820": { "x" : 820 }, 44.856 + "p821": { "x" : 821 }, 44.857 + "p822": { "x" : 822 }, 44.858 + "p823": { "x" : 823 }, 44.859 + "p824": { "x" : 824 }, 44.860 + "p825": { "x" : 825 }, 44.861 + "p826": { "x" : 826 }, 44.862 + "p827": { "x" : 827 }, 44.863 + "p828": { "x" : 828 }, 44.864 + "p829": { "x" : 829 }, 44.865 + "p830": { "x" : 830 }, 44.866 + "p831": { "x" : 831 }, 44.867 + "p832": { "x" : 832 }, 44.868 + "p833": { "x" : 833 }, 44.869 + "p834": { "x" : 834 }, 44.870 + "p835": { "x" : 835 }, 44.871 + "p836": { "x" : 836 }, 44.872 + "p837": { "x" : 837 }, 44.873 + "p838": { "x" : 838 }, 44.874 + "p839": { "x" : 839 }, 44.875 + "p840": { "x" : 840 }, 44.876 + "p841": { "x" : 841 }, 44.877 + "p842": { "x" : 842 }, 44.878 + "p843": { "x" : 843 }, 44.879 + "p844": { "x" : 844 }, 44.880 + "p845": { "x" : 845 }, 44.881 + "p846": { "x" : 846 }, 44.882 + "p847": { "x" : 847 }, 44.883 + "p848": { "x" : 848 }, 44.884 + "p849": { "x" : 849 }, 44.885 + "p850": { "x" : 850 }, 44.886 + "p851": { "x" : 851 }, 44.887 + "p852": { "x" : 852 }, 44.888 + "p853": { "x" : 853 }, 44.889 + "p854": { "x" : 854 }, 44.890 + "p855": { "x" : 855 }, 44.891 + "p856": { "x" : 856 }, 44.892 + "p857": { "x" : 857 }, 44.893 + "p858": { "x" : 858 }, 44.894 + "p859": { "x" : 859 }, 44.895 + "p860": { "x" : 860 }, 44.896 + "p861": { "x" : 861 }, 44.897 + "p862": { "x" : 862 }, 44.898 + "p863": { "x" : 863 }, 44.899 + "p864": { "x" : 864 }, 44.900 + "p865": { "x" : 865 }, 44.901 + "p866": { "x" : 866 }, 44.902 + "p867": { "x" : 867 }, 44.903 + "p868": { "x" : 868 }, 44.904 + "p869": { "x" : 869 }, 44.905 + "p870": { "x" : 870 }, 44.906 + "p871": { "x" : 871 }, 44.907 + "p872": { "x" : 872 }, 44.908 + "p873": { "x" : 873 }, 44.909 + "p874": { "x" : 874 }, 44.910 + "p875": { "x" : 875 }, 44.911 + "p876": { "x" : 876 }, 44.912 + "p877": { "x" : 877 }, 44.913 + "p878": { "x" : 878 }, 44.914 + "p879": { "x" : 879 }, 44.915 + "p880": { "x" : 880 }, 44.916 + "p881": { "x" : 881 }, 44.917 + "p882": { "x" : 882 }, 44.918 + "p883": { "x" : 883 }, 44.919 + "p884": { "x" : 884 }, 44.920 + "p885": { "x" : 885 }, 44.921 + "p886": { "x" : 886 }, 44.922 + "p887": { "x" : 887 }, 44.923 + "p888": { "x" : 888 }, 44.924 + "p889": { "x" : 889 }, 44.925 + "p890": { "x" : 890 }, 44.926 + "p891": { "x" : 891 }, 44.927 + "p892": { "x" : 892 }, 44.928 + "p893": { "x" : 893 }, 44.929 + "p894": { "x" : 894 }, 44.930 + "p895": { "x" : 895 }, 44.931 + "p896": { "x" : 896 }, 44.932 + "p897": { "x" : 897 }, 44.933 + "p898": { "x" : 898 }, 44.934 + "p899": { "x" : 899 }, 44.935 + "p900": { "x" : 900 }, 44.936 + "p901": { "x" : 901 }, 44.937 + "p902": { "x" : 902 }, 44.938 + "p903": { "x" : 903 }, 44.939 + "p904": { "x" : 904 }, 44.940 + "p905": { "x" : 905 }, 44.941 + "p906": { "x" : 906 }, 44.942 + "p907": { "x" : 907 }, 44.943 + "p908": { "x" : 908 }, 44.944 + "p909": { "x" : 909 }, 44.945 + "p910": { "x" : 910 }, 44.946 + "p911": { "x" : 911 }, 44.947 + "p912": { "x" : 912 }, 44.948 + "p913": { "x" : 913 }, 44.949 + "p914": { "x" : 914 }, 44.950 + "p915": { "x" : 915 }, 44.951 + "p916": { "x" : 916 }, 44.952 + "p917": { "x" : 917 }, 44.953 + "p918": { "x" : 918 }, 44.954 + "p919": { "x" : 919 }, 44.955 + "p920": { "x" : 920 }, 44.956 + "p921": { "x" : 921 }, 44.957 + "p922": { "x" : 922 }, 44.958 + "p923": { "x" : 923 }, 44.959 + "p924": { "x" : 924 }, 44.960 + "p925": { "x" : 925 }, 44.961 + "p926": { "x" : 926 }, 44.962 + "p927": { "x" : 927 }, 44.963 + "p928": { "x" : 928 }, 44.964 + "p929": { "x" : 929 }, 44.965 + "p930": { "x" : 930 }, 44.966 + "p931": { "x" : 931 }, 44.967 + "p932": { "x" : 932 }, 44.968 + "p933": { "x" : 933 }, 44.969 + "p934": { "x" : 934 }, 44.970 + "p935": { "x" : 935 }, 44.971 + "p936": { "x" : 936 }, 44.972 + "p937": { "x" : 937 }, 44.973 + "p938": { "x" : 938 }, 44.974 + "p939": { "x" : 939 }, 44.975 + "p940": { "x" : 940 }, 44.976 + "p941": { "x" : 941 }, 44.977 + "p942": { "x" : 942 }, 44.978 + "p943": { "x" : 943 }, 44.979 + "p944": { "x" : 944 }, 44.980 + "p945": { "x" : 945 }, 44.981 + "p946": { "x" : 946 }, 44.982 + "p947": { "x" : 947 }, 44.983 + "p948": { "x" : 948 }, 44.984 + "p949": { "x" : 949 }, 44.985 + "p950": { "x" : 950 }, 44.986 + "p951": { "x" : 951 }, 44.987 + "p952": { "x" : 952 }, 44.988 + "p953": { "x" : 953 }, 44.989 + "p954": { "x" : 954 }, 44.990 + "p955": { "x" : 955 }, 44.991 + "p956": { "x" : 956 }, 44.992 + "p957": { "x" : 957 }, 44.993 + "p958": { "x" : 958 }, 44.994 + "p959": { "x" : 959 }, 44.995 + "p960": { "x" : 960 }, 44.996 + "p961": { "x" : 961 }, 44.997 + "p962": { "x" : 962 }, 44.998 + "p963": { "x" : 963 }, 44.999 + "p964": { "x" : 964 }, 44.1000 + "p965": { "x" : 965 }, 44.1001 + "p966": { "x" : 966 }, 44.1002 + "p967": { "x" : 967 }, 44.1003 + "p968": { "x" : 968 }, 44.1004 + "p969": { "x" : 969 }, 44.1005 + "p970": { "x" : 970 }, 44.1006 + "p971": { "x" : 971 }, 44.1007 + "p972": { "x" : 972 }, 44.1008 + "p973": { "x" : 973 }, 44.1009 + "p974": { "x" : 974 }, 44.1010 + "p975": { "x" : 975 }, 44.1011 + "p976": { "x" : 976 }, 44.1012 + "p977": { "x" : 977 }, 44.1013 + "p978": { "x" : 978 }, 44.1014 + "p979": { "x" : 979 }, 44.1015 + "p980": { "x" : 980 }, 44.1016 + "p981": { "x" : 981 }, 44.1017 + "p982": { "x" : 982 }, 44.1018 + "p983": { "x" : 983 }, 44.1019 + "p984": { "x" : 984 }, 44.1020 + "p985": { "x" : 985 }, 44.1021 + "p986": { "x" : 986 }, 44.1022 + "p987": { "x" : 987 }, 44.1023 + "p988": { "x" : 988 }, 44.1024 + "p989": { "x" : 989 }, 44.1025 + "p990": { "x" : 990 }, 44.1026 + "p991": { "x" : 991 }, 44.1027 + "p992": { "x" : 992 }, 44.1028 + "p993": { "x" : 993 }, 44.1029 + "p994": { "x" : 994 }, 44.1030 + "p995": { "x" : 995 }, 44.1031 + "p996": { "x" : 996 }, 44.1032 + "p997": { "x" : 997 }, 44.1033 + "p998": { "x" : 998 }, 44.1034 + "p999": { "x" : 999 } 44.1035 +}; 44.1036 + 44.1037 +for (var i = 0; i < 1000; i++) { 44.1038 + var value = obj["p" + i]; 44.1039 + Assert.assertTrue(typeof value === "object"); 44.1040 + Assert.assertTrue(value.x === i); 44.1041 +}
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 45.2 +++ b/test/script/basic/JDK-8074556.js Wed Mar 18 18:21:55 2015 -0700 45.3 @@ -0,0 +1,52 @@ 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-8074556: Functions should not share allocator maps 45.29 + * 45.30 + * @test 45.31 + * @run 45.32 + */ 45.33 + 45.34 +function A () { 45.35 + return this; 45.36 +} 45.37 + 45.38 +function B() { 45.39 + return this; 45.40 +} 45.41 + 45.42 +A.prototype.x = "x"; 45.43 +A.prototype.y = "y"; 45.44 +B.prototype.y = "y"; // same properties but different order 45.45 +B.prototype.x = "x"; 45.46 + 45.47 +function test(o) { 45.48 + Assert.assertEquals(o.x, "x"); 45.49 + Assert.assertEquals(o.y, "y"); 45.50 +} 45.51 + 45.52 +test(new A()); 45.53 +test(new B()); 45.54 +test(new A()); 45.55 +test(new B());
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 46.2 +++ b/test/script/basic/JDK-8074687.js Wed Mar 18 18:21:55 2015 -0700 46.3 @@ -0,0 +1,60 @@ 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-8074687: Add tests for JSON parsing of numeric keys 46.29 + * 46.30 + * @test 46.31 + * @run 46.32 + */ 46.33 + 46.34 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {} }')), '{"0":{}}'); 46.35 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1 }')), '{"0":1}'); 46.36 + 46.37 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "65503": {} }')), '{"65503":{}}'); 46.38 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "65503": 1 }')), '{"65503":1}'); 46.39 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {}, "65503": {} }')), '{"0":{},"65503":{}}'); 46.40 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1, "65503": 1 }')), '{"0":1,"65503":1}'); 46.41 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "65503": {}, "0": {} }')), '{"0":{},"65503":{}}'); 46.42 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "65503": 1, "0": 1 }')), '{"0":1,"65503":1}'); 46.43 + 46.44 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "4294967295": {} }')), '{"4294967295":{}}'); 46.45 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "4294967295": 1 }')), '{"4294967295":1}'); 46.46 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {}, "4294967295": {} }')), '{"0":{},"4294967295":{}}'); 46.47 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1, "4294967295": 1 }')), '{"0":1,"4294967295":1}'); 46.48 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "4294967295": {}, "0": {} }')), '{"0":{},"4294967295":{}}'); 46.49 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "4294967295": 1, "0": 1 }')), '{"0":1,"4294967295":1}'); 46.50 + 46.51 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "100": {} }')), '{"100":{}}'); 46.52 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "100": 1 }')), '{"100":1}'); 46.53 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {}, "100": {} }')), '{"0":{},"100":{}}'); 46.54 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1, "100": 1 }')), '{"0":1,"100":1}'); 46.55 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "100": {}, "0": {} }')), '{"0":{},"100":{}}'); 46.56 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "100": 1, "0": 1 }')), '{"0":1,"100":1}'); 46.57 + 46.58 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "-100": {} }')), '{"-100":{}}'); 46.59 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "-100": 1 }')), '{"-100":1}'); 46.60 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {}, "-100": {} }')), '{"0":{},"-100":{}}'); 46.61 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1, "-100": 1 }')), '{"0":1,"-100":1}'); 46.62 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "-100": {}, "0": {} }')), '{"0":{},"-100":{}}'); 46.63 +Assert.assertEquals(JSON.stringify(JSON.parse('{ "-100": 1, "0": 1 }')), '{"0":1,"-100":1}');
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 47.2 +++ b/test/script/basic/JDK-8074693.js Wed Mar 18 18:21:55 2015 -0700 47.3 @@ -0,0 +1,74 @@ 47.4 +/* 47.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 47.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 47.7 + * 47.8 + * This code is free software; you can redistribute it and/or modify it 47.9 + * under the terms of the GNU General Public License version 2 only, as 47.10 + * published by the Free Software Foundation. 47.11 + * 47.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 47.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 47.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 47.15 + * version 2 for more details (a copy is included in the LICENSE file that 47.16 + * accompanied this code). 47.17 + * 47.18 + * You should have received a copy of the GNU General Public License version 47.19 + * 2 along with this work; if not, write to the Free Software Foundation, 47.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 47.21 + * 47.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 47.23 + * or visit www.oracle.com if you need additional information or have any 47.24 + * questions. 47.25 + */ 47.26 + 47.27 +/** 47.28 + * JDK-8074693: Different instances of same function use same allocator map 47.29 + * 47.30 + * @test 47.31 + * @run 47.32 + */ 47.33 + 47.34 +var lib = {}; 47.35 + 47.36 +lib.mixin = function(target, source) { 47.37 + for (var p in source) { 47.38 + if (source.hasOwnProperty(p) && !target.hasOwnProperty(p)) { 47.39 + target.prototype[p] = source[p]; 47.40 + } 47.41 + } 47.42 +}; 47.43 + 47.44 +lib.declare = function(def) { 47.45 + var className = def.name; 47.46 + 47.47 + lib[className] = function() { 47.48 + this.init.apply(this, arguments); 47.49 + }; 47.50 + 47.51 + lib.mixin(lib[className], def.members); 47.52 +}; 47.53 + 47.54 + 47.55 +lib.declare({ 47.56 + name: "ClassA", 47.57 + members: { 47.58 + init : function () { 47.59 + print("init A called"); 47.60 + } 47.61 + } 47.62 +}); 47.63 + 47.64 +lib.declare({ 47.65 + name: "ClassB", 47.66 + members: { 47.67 + util : function () { 47.68 + print("util called") 47.69 + }, 47.70 + init : function() { 47.71 + print("init B called"); 47.72 + } 47.73 + } 47.74 +}); 47.75 + 47.76 +var objA = new lib.ClassA(); 47.77 +var objB = new lib.ClassB();
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 48.2 +++ b/test/script/basic/JDK-8074693.js.EXPECTED Wed Mar 18 18:21:55 2015 -0700 48.3 @@ -0,0 +1,2 @@ 48.4 +init A called 48.5 +init B called
49.1 --- a/test/script/basic/typedarrays.js Wed Mar 18 13:57:04 2015 -0700 49.2 +++ b/test/script/basic/typedarrays.js Wed Mar 18 18:21:55 2015 -0700 49.3 @@ -28,6 +28,17 @@ 49.4 * @run 49.5 */ 49.6 49.7 +//JDK-8066217, constructor for arraybuffer not behaving as per spec 49.8 +function checkLength(ab, l) { 49.9 + if (ab.byteLength != l) { 49.10 + throw "length error: " + ab.byteLength + " != " + l; 49.11 + } 49.12 +} 49.13 +checkLength(new ArrayBuffer(), 0); 49.14 +checkLength(new ArrayBuffer(0), 0); 49.15 +checkLength(new ArrayBuffer(1024), 1024); 49.16 +checkLength(new ArrayBuffer(1,2,3), 1); 49.17 +checkLength(new ArrayBuffer([17]), 17); 49.18 49.19 var typeDefinitions = [ 49.20 Int8Array,
50.1 --- a/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java Wed Mar 18 13:57:04 2015 -0700 50.2 +++ b/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java Wed Mar 18 18:21:55 2015 -0700 50.3 @@ -109,6 +109,35 @@ 50.4 } 50.5 } 50.6 50.7 + // @bug 8062030: Nashorn bug retrieving array property after key string concatenation 50.8 + @Test 50.9 + // ConsString attribute access on a JSObject 50.10 + public void consStringTest() { 50.11 + final ScriptEngineManager m = new ScriptEngineManager(); 50.12 + final ScriptEngine e = m.getEngineByName("nashorn"); 50.13 + try { 50.14 + final MapWrapperObject obj = new MapWrapperObject(); 50.15 + e.put("obj", obj); 50.16 + e.put("f", "f"); 50.17 + e.eval("obj[f + 'oo'] = 'bar';"); 50.18 + 50.19 + assertEquals(obj.getMap().get("foo"), "bar"); 50.20 + assertEquals(e.eval("obj[f + 'oo']"), "bar"); 50.21 + assertEquals(e.eval("obj['foo']"), "bar"); 50.22 + assertEquals(e.eval("f + 'oo' in obj"), Boolean.TRUE); 50.23 + assertEquals(e.eval("'foo' in obj"), Boolean.TRUE); 50.24 + e.eval("delete obj[f + 'oo']"); 50.25 + assertFalse(obj.getMap().containsKey("foo")); 50.26 + assertEquals(e.eval("obj[f + 'oo']"), null); 50.27 + assertEquals(e.eval("obj['foo']"), null); 50.28 + assertEquals(e.eval("f + 'oo' in obj"), Boolean.FALSE); 50.29 + assertEquals(e.eval("'foo' in obj"), Boolean.FALSE); 50.30 + } catch (final Exception exp) { 50.31 + exp.printStackTrace(); 50.32 + fail(exp.getMessage()); 50.33 + } 50.34 + } 50.35 + 50.36 public static class BufferObject extends AbstractJSObject { 50.37 private final IntBuffer buf; 50.38