Tue, 14 Oct 2014 10:20:24 -0700
Merge
src/jdk/nashorn/internal/objects/annotations/SpecializedConstructor.java | file | annotate | diff | comparison | revisions |
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/bin/fixwhitespace.sh Tue Oct 14 10:20:24 2014 -0700 1.3 @@ -0,0 +1,37 @@ 1.4 +#!/bin/bash 1.5 +# 1.6 +# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 1.7 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 +# 1.9 +# This code is free software; you can redistribute it and/or modify it 1.10 +# under the terms of the GNU General Public License version 2 only, as 1.11 +# published by the Free Software Foundation. 1.12 +# 1.13 +# This code is distributed in the hope that it will be useful, but WITHOUT 1.14 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.15 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.16 +# version 2 for more details (a copy is included in the LICENSE file that 1.17 +# accompanied this code). 1.18 +# 1.19 +# You should have received a copy of the GNU General Public License version 1.20 +# 2 along with this work; if not, write to the Free Software Foundation, 1.21 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.22 +# 1.23 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.24 +# or visit www.oracle.com if you need additional information or have any 1.25 +# questions. 1.26 +# 1.27 + 1.28 +fix() { 1.29 + #convert tabs to spaces 1.30 + find . -name $1 -exec sed -i "" 's/ / /g' {} \; 1.31 + #remove trailing whitespace 1.32 + find . -name $1 -exec sed -i "" 's/[ ]*$//' \{} \; 1.33 +} 1.34 + 1.35 +if [ ! -z $1 ]; then 1.36 + fix $1; 1.37 +else 1.38 + fix "*.java" 1.39 + fix "*.js" 1.40 +fi
2.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Wed Oct 08 14:16:54 2014 -0700 2.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Tue Oct 14 10:20:24 2014 -0700 2.3 @@ -292,7 +292,6 @@ 2.4 mi.push(memInfo.getArity()); 2.5 mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETARITY, SCRIPTFUNCTION_SETARITY_DESC); 2.6 } 2.7 - 2.8 } 2.9 2.10 static void linkerAddGetterSetter(final MethodGenerator mi, final String className, final MemberInfo memInfo) {
3.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Wed Oct 08 14:16:54 2014 -0700 3.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Tue Oct 14 10:20:24 2014 -0700 3.3 @@ -28,7 +28,6 @@ 3.4 import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; 3.5 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_DESC; 3.6 import static jdk.nashorn.internal.tools.nasgen.StringConstants.STRING_DESC; 3.7 - 3.8 import jdk.internal.org.objectweb.asm.Opcodes; 3.9 import jdk.internal.org.objectweb.asm.Type; 3.10 import jdk.nashorn.internal.objects.annotations.Where; 3.11 @@ -75,10 +74,6 @@ 3.12 * This is a specialized version of a function 3.13 */ 3.14 SPECIALIZED_FUNCTION, 3.15 - /** 3.16 - * This is a specialized version of a constructor 3.17 - */ 3.18 - SPECIALIZED_CONSTRUCTOR 3.19 } 3.20 3.21 // keep in sync with jdk.nashorn.internal.objects.annotations.Attribute 3.22 @@ -107,6 +102,12 @@ 3.23 3.24 private Where where; 3.25 3.26 + private Type linkLogicClass; 3.27 + 3.28 + private boolean isSpecializedConstructor; 3.29 + 3.30 + private boolean isOptimistic; 3.31 + 3.32 /** 3.33 * @return the kind 3.34 */ 3.35 @@ -136,6 +137,57 @@ 3.36 } 3.37 3.38 /** 3.39 + * Tag something as specialized constructor or not 3.40 + * @param isSpecializedConstructor boolean, true if specialized constructor 3.41 + */ 3.42 + public void setIsSpecializedConstructor(final boolean isSpecializedConstructor) { 3.43 + this.isSpecializedConstructor = isSpecializedConstructor; 3.44 + } 3.45 + 3.46 + /** 3.47 + * Check if something is a specialized constructor 3.48 + * @return true if specialized constructor 3.49 + */ 3.50 + public boolean isSpecializedConstructor() { 3.51 + return isSpecializedConstructor; 3.52 + } 3.53 + 3.54 + /** 3.55 + * Check if this is an optimistic builtin function 3.56 + * @return true if optimistic builtin 3.57 + */ 3.58 + public boolean isOptimistic() { 3.59 + return isOptimistic; 3.60 + } 3.61 + 3.62 + /** 3.63 + * Tag something as optimitic builtin or not 3.64 + * @param isOptimistic boolean, true if builtin constructor 3.65 + */ 3.66 + public void setIsOptimistic(final boolean isOptimistic) { 3.67 + this.isOptimistic = isOptimistic; 3.68 + } 3.69 + 3.70 + /** 3.71 + * Get the SpecializedFunction guard for specializations, i.e. optimistic 3.72 + * builtins 3.73 + * @return specialization, null if none 3.74 + */ 3.75 + public Type getLinkLogicClass() { 3.76 + return linkLogicClass; 3.77 + } 3.78 + 3.79 + /** 3.80 + * Set thre SpecializedFunction link logic class for specializations, i.e. optimistic 3.81 + * builtins 3.82 + * @param linkLogicClass link logic class 3.83 + */ 3.84 + 3.85 + public void setLinkLogicClass(final Type linkLogicClass) { 3.86 + this.linkLogicClass = linkLogicClass; 3.87 + } 3.88 + 3.89 + /** 3.90 * @return the attributes 3.91 */ 3.92 public int getAttributes() { 3.93 @@ -304,19 +356,6 @@ 3.94 } 3.95 } 3.96 break; 3.97 - case SPECIALIZED_CONSTRUCTOR: { 3.98 - final Type returnType = Type.getReturnType(javaDesc); 3.99 - if (!isJSObjectType(returnType)) { 3.100 - error("return value of a @SpecializedConstructor method should be a valid JS type, found " + returnType); 3.101 - } 3.102 - final Type[] argTypes = Type.getArgumentTypes(javaDesc); 3.103 - for (int i = 0; i < argTypes.length; i++) { 3.104 - if (!isValidJSType(argTypes[i])) { 3.105 - error(i + "'th argument of a @SpecializedConstructor method is not valid JS type, found " + argTypes[i]); 3.106 - } 3.107 - } 3.108 - } 3.109 - break; 3.110 case FUNCTION: { 3.111 final Type returnType = Type.getReturnType(javaDesc); 3.112 if (!(isValidJSType(returnType) || Type.VOID_TYPE == returnType)) { 3.113 @@ -351,7 +390,7 @@ 3.114 break; 3.115 case SPECIALIZED_FUNCTION: { 3.116 final Type returnType = Type.getReturnType(javaDesc); 3.117 - if (!(isValidJSType(returnType) || Type.VOID_TYPE == returnType)) { 3.118 + if (!(isValidJSType(returnType) || (isSpecializedConstructor() && Type.VOID_TYPE == returnType))) { 3.119 error("return value of a @SpecializedFunction method should be a valid JS type, found " + returnType); 3.120 } 3.121 final Type[] argTypes = Type.getArgumentTypes(javaDesc);
4.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java Wed Oct 08 14:16:54 2014 -0700 4.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java Tue Oct 14 10:20:24 2014 -0700 4.3 @@ -56,6 +56,7 @@ 4.4 import static jdk.internal.org.objectweb.asm.Opcodes.IALOAD; 4.5 import static jdk.internal.org.objectweb.asm.Opcodes.IASTORE; 4.6 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_0; 4.7 +import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_1; 4.8 import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD; 4.9 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEINTERFACE; 4.10 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL; 4.11 @@ -76,13 +77,16 @@ 4.12 import static jdk.internal.org.objectweb.asm.Opcodes.SASTORE; 4.13 import static jdk.internal.org.objectweb.asm.Opcodes.SIPUSH; 4.14 import static jdk.internal.org.objectweb.asm.Opcodes.SWAP; 4.15 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.METHODHANDLE_TYPE; 4.16 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_METHODHANDLE; 4.17 - 4.18 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; 4.19 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SPECIALIZATION_INIT2; 4.20 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SPECIALIZATION_INIT3; 4.21 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SPECIALIZATION_TYPE; 4.22 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_SPECIALIZATION; 4.23 import java.util.List; 4.24 import jdk.internal.org.objectweb.asm.Handle; 4.25 import jdk.internal.org.objectweb.asm.MethodVisitor; 4.26 import jdk.internal.org.objectweb.asm.Type; 4.27 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 4.28 4.29 /** 4.30 * Base class for all method generating classes. 4.31 @@ -95,6 +99,8 @@ 4.32 private final Type returnType; 4.33 private final Type[] argumentTypes; 4.34 4.35 + static final Type EMPTY_LINK_LOGIC_TYPE = Type.getType(LinkLogic.getEmptyLinkLogicClass()); 4.36 + 4.37 MethodGenerator(final MethodVisitor mv, final int access, final String name, final String descriptor) { 4.38 super(ASM4, mv); 4.39 this.access = access; 4.40 @@ -380,6 +386,11 @@ 4.41 super.visitFieldInsn(GETFIELD, owner, field, desc); 4.42 } 4.43 4.44 + private static boolean linkLogicIsEmpty(final Type type) { 4.45 + assert EMPTY_LINK_LOGIC_TYPE != null; //type is ok for null if we are a @SpecializedFunction without any attribs 4.46 + return EMPTY_LINK_LOGIC_TYPE.equals(type); 4.47 + } 4.48 + 4.49 void memberInfoArray(final String className, final List<MemberInfo> mis) { 4.50 if (mis.isEmpty()) { 4.51 pushNull(); 4.52 @@ -388,12 +399,22 @@ 4.53 4.54 int pos = 0; 4.55 push(mis.size()); 4.56 - newObjectArray(METHODHANDLE_TYPE); 4.57 + newObjectArray(SPECIALIZATION_TYPE); 4.58 for (final MemberInfo mi : mis) { 4.59 dup(); 4.60 push(pos++); 4.61 + visitTypeInsn(NEW, SPECIALIZATION_TYPE); 4.62 + dup(); 4.63 visitLdcInsn(new Handle(H_INVOKESTATIC, className, mi.getJavaName(), mi.getJavaDesc())); 4.64 - arrayStore(TYPE_METHODHANDLE); 4.65 + final Type linkLogicClass = mi.getLinkLogicClass(); 4.66 + final boolean linkLogic = !linkLogicIsEmpty(linkLogicClass); 4.67 + final String ctor = linkLogic ? SPECIALIZATION_INIT3 : SPECIALIZATION_INIT2; 4.68 + if (linkLogic) { 4.69 + visitLdcInsn(linkLogicClass); 4.70 + } 4.71 + visitInsn(mi.isOptimistic() ? ICONST_1 : ICONST_0); 4.72 + visitMethodInsn(INVOKESPECIAL, SPECIALIZATION_TYPE, INIT, ctor, false); 4.73 + arrayStore(TYPE_SPECIALIZATION); 4.74 } 4.75 } 4.76
5.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java Wed Oct 08 14:16:54 2014 -0700 5.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java Tue Oct 14 10:20:24 2014 -0700 5.3 @@ -37,8 +37,8 @@ 5.4 import jdk.nashorn.internal.objects.annotations.Property; 5.5 import jdk.nashorn.internal.objects.annotations.ScriptClass; 5.6 import jdk.nashorn.internal.objects.annotations.Setter; 5.7 -import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; 5.8 import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 5.9 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 5.10 import jdk.nashorn.internal.objects.annotations.Where; 5.11 import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind; 5.12 5.13 @@ -56,8 +56,8 @@ 5.14 static final String SETTER_ANNO_DESC = Type.getDescriptor(Setter.class); 5.15 static final String PROPERTY_ANNO_DESC = Type.getDescriptor(Property.class); 5.16 static final String WHERE_ENUM_DESC = Type.getDescriptor(Where.class); 5.17 + static final String LINK_LOGIC_DESC = Type.getDescriptor(LinkLogic.class); 5.18 static final String SPECIALIZED_FUNCTION = Type.getDescriptor(SpecializedFunction.class); 5.19 - static final String SPECIALIZED_CONSTRUCTOR = Type.getDescriptor(SpecializedConstructor.class); 5.20 5.21 static final Map<String, Kind> annotations = new HashMap<>(); 5.22 5.23 @@ -69,7 +69,6 @@ 5.24 annotations.put(SETTER_ANNO_DESC, Kind.SETTER); 5.25 annotations.put(PROPERTY_ANNO_DESC, Kind.PROPERTY); 5.26 annotations.put(SPECIALIZED_FUNCTION, Kind.SPECIALIZED_FUNCTION); 5.27 - annotations.put(SPECIALIZED_CONSTRUCTOR, Kind.SPECIALIZED_CONSTRUCTOR); 5.28 } 5.29 5.30 // name of the script class 5.31 @@ -119,11 +118,12 @@ 5.32 List<MemberInfo> getSpecializedConstructors() { 5.33 final List<MemberInfo> res = new LinkedList<>(); 5.34 for (final MemberInfo memInfo : members) { 5.35 - if (memInfo.getKind() == Kind.SPECIALIZED_CONSTRUCTOR) { 5.36 + if (memInfo.isSpecializedConstructor()) { 5.37 + assert memInfo.getKind() == Kind.SPECIALIZED_FUNCTION; 5.38 res.add(memInfo); 5.39 } 5.40 } 5.41 - return res; 5.42 + return Collections.unmodifiableList(res); 5.43 } 5.44 5.45 int getPrototypeMemberCount() { 5.46 @@ -175,7 +175,7 @@ 5.47 res.add(memInfo); 5.48 } 5.49 } 5.50 - return res; 5.51 + return Collections.unmodifiableList(res); 5.52 } 5.53 5.54 MemberInfo findSetter(final MemberInfo getter) {
6.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Wed Oct 08 14:16:54 2014 -0700 6.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Tue Oct 14 10:20:24 2014 -0700 6.3 @@ -27,7 +27,6 @@ 6.4 6.5 import static jdk.nashorn.internal.tools.nasgen.ScriptClassInfo.SCRIPT_CLASS_ANNO_DESC; 6.6 import static jdk.nashorn.internal.tools.nasgen.ScriptClassInfo.WHERE_ENUM_DESC; 6.7 - 6.8 import java.io.BufferedInputStream; 6.9 import java.io.FileInputStream; 6.10 import java.io.IOException; 6.11 @@ -41,6 +40,7 @@ 6.12 import jdk.internal.org.objectweb.asm.FieldVisitor; 6.13 import jdk.internal.org.objectweb.asm.MethodVisitor; 6.14 import jdk.internal.org.objectweb.asm.Opcodes; 6.15 +import jdk.internal.org.objectweb.asm.Type; 6.16 import jdk.nashorn.internal.objects.annotations.Where; 6.17 import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind; 6.18 6.19 @@ -194,6 +194,7 @@ 6.20 6.21 final MemberInfo memInfo = new MemberInfo(); 6.22 6.23 + //annokind == e.g. GETTER or SPECIALIZED_FUNCTION 6.24 memInfo.setKind(annoKind); 6.25 memInfo.setJavaName(methodName); 6.26 memInfo.setJavaDesc(methodDesc); 6.27 @@ -208,12 +209,18 @@ 6.28 private Integer attributes; 6.29 private Integer arity; 6.30 private Where where; 6.31 + private boolean isSpecializedConstructor; 6.32 + private boolean isOptimistic; 6.33 + private Type linkLogicClass = MethodGenerator.EMPTY_LINK_LOGIC_TYPE; 6.34 6.35 @Override 6.36 public void visit(final String annotationName, final Object annotationValue) { 6.37 switch (annotationName) { 6.38 case "name": 6.39 this.name = (String)annotationValue; 6.40 + if (name.isEmpty()) { 6.41 + name = null; 6.42 + } 6.43 break; 6.44 case "attributes": 6.45 this.attributes = (Integer)annotationValue; 6.46 @@ -221,6 +228,17 @@ 6.47 case "arity": 6.48 this.arity = (Integer)annotationValue; 6.49 break; 6.50 + case "isConstructor": 6.51 + assert annoKind == Kind.SPECIALIZED_FUNCTION; 6.52 + this.isSpecializedConstructor = (Boolean)annotationValue; 6.53 + break; 6.54 + case "isOptimistic": 6.55 + assert annoKind == Kind.SPECIALIZED_FUNCTION; 6.56 + this.isOptimistic = (Boolean)annotationValue; 6.57 + break; 6.58 + case "linkLogic": 6.59 + this.linkLogicClass = (Type)annotationValue; 6.60 + break; 6.61 default: 6.62 break; 6.63 } 6.64 @@ -230,12 +248,19 @@ 6.65 6.66 @Override 6.67 public void visitEnum(final String enumName, final String desc, final String enumValue) { 6.68 - if ("where".equals(enumName) && WHERE_ENUM_DESC.equals(desc)) { 6.69 - this.where = Where.valueOf(enumValue); 6.70 + switch (enumName) { 6.71 + case "where": 6.72 + if (WHERE_ENUM_DESC.equals(desc)) { 6.73 + this.where = Where.valueOf(enumValue); 6.74 + } 6.75 + break; 6.76 + default: 6.77 + break; 6.78 } 6.79 super.visitEnum(enumName, desc, enumValue); 6.80 } 6.81 6.82 + @SuppressWarnings("fallthrough") 6.83 @Override 6.84 public void visitEnd() { 6.85 super.visitEnd(); 6.86 @@ -256,7 +281,6 @@ 6.87 case SETTER: 6.88 where = Where.INSTANCE; 6.89 break; 6.90 - case SPECIALIZED_CONSTRUCTOR: 6.91 case CONSTRUCTOR: 6.92 where = Where.CONSTRUCTOR; 6.93 break; 6.94 @@ -264,12 +288,18 @@ 6.95 where = Where.PROTOTYPE; 6.96 break; 6.97 case SPECIALIZED_FUNCTION: 6.98 - //TODO is this correct 6.99 + if (isSpecializedConstructor) { 6.100 + where = Where.CONSTRUCTOR; 6.101 + } 6.102 + //fallthru 6.103 default: 6.104 break; 6.105 } 6.106 } 6.107 memInfo.setWhere(where); 6.108 + memInfo.setLinkLogicClass(linkLogicClass); 6.109 + memInfo.setIsSpecializedConstructor(isSpecializedConstructor); 6.110 + memInfo.setIsOptimistic(isOptimistic); 6.111 } 6.112 }; 6.113 }
7.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java Wed Oct 08 14:16:54 2014 -0700 7.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java Tue Oct 14 10:20:24 2014 -0700 7.3 @@ -38,7 +38,6 @@ 7.4 import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; 7.5 import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; 7.6 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_TYPE; 7.7 - 7.8 import java.io.BufferedInputStream; 7.9 import java.io.FileInputStream; 7.10 import java.io.FileOutputStream;
8.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Wed Oct 08 14:16:54 2014 -0700 8.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Tue Oct 14 10:20:24 2014 -0700 8.3 @@ -37,6 +37,7 @@ 8.4 import jdk.nashorn.internal.runtime.PropertyMap; 8.5 import jdk.nashorn.internal.runtime.ScriptFunction; 8.6 import jdk.nashorn.internal.runtime.ScriptObject; 8.7 +import jdk.nashorn.internal.runtime.Specialization; 8.8 8.9 /** 8.10 * String constants used for code generation/instrumentation. 8.11 @@ -44,20 +45,26 @@ 8.12 @SuppressWarnings("javadoc") 8.13 public interface StringConstants { 8.14 // standard jdk types, methods 8.15 - static final Type TYPE_METHODHANDLE = Type.getType(MethodHandle.class); 8.16 - static final Type TYPE_METHODHANDLE_ARRAY = Type.getType(MethodHandle[].class); 8.17 - static final Type TYPE_OBJECT = Type.getType(Object.class); 8.18 - static final Type TYPE_STRING = Type.getType(String.class); 8.19 - static final Type TYPE_COLLECTION = Type.getType(Collection.class); 8.20 - static final Type TYPE_COLLECTIONS = Type.getType(Collections.class); 8.21 - static final Type TYPE_ARRAYLIST = Type.getType(ArrayList.class); 8.22 - static final Type TYPE_LIST = Type.getType(List.class); 8.23 + static final Type TYPE_METHODHANDLE = Type.getType(MethodHandle.class); 8.24 + static final Type TYPE_METHODHANDLE_ARRAY = Type.getType(MethodHandle[].class); 8.25 + static final Type TYPE_SPECIALIZATION = Type.getType(Specialization.class); 8.26 + static final Type TYPE_SPECIALIZATION_ARRAY = Type.getType(Specialization[].class); 8.27 + static final Type TYPE_OBJECT = Type.getType(Object.class); 8.28 + static final Type TYPE_STRING = Type.getType(String.class); 8.29 + static final Type TYPE_CLASS = Type.getType(Class.class); 8.30 + static final Type TYPE_COLLECTION = Type.getType(Collection.class); 8.31 + static final Type TYPE_COLLECTIONS = Type.getType(Collections.class); 8.32 + static final Type TYPE_ARRAYLIST = Type.getType(ArrayList.class); 8.33 + static final Type TYPE_LIST = Type.getType(List.class); 8.34 8.35 static final String CLINIT = "<clinit>"; 8.36 static final String INIT = "<init>"; 8.37 static final String DEFAULT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE); 8.38 8.39 static final String METHODHANDLE_TYPE = TYPE_METHODHANDLE.getInternalName(); 8.40 + static final String SPECIALIZATION_TYPE = TYPE_SPECIALIZATION.getInternalName(); 8.41 + static final String SPECIALIZATION_INIT2 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, Type.getType(boolean.class)); 8.42 + static final String SPECIALIZATION_INIT3 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, TYPE_CLASS, Type.getType(boolean.class)); 8.43 static final String OBJECT_TYPE = TYPE_OBJECT.getInternalName(); 8.44 static final String OBJECT_DESC = TYPE_OBJECT.getDescriptor(); 8.45 static final String STRING_TYPE = TYPE_STRING.getInternalName(); 8.46 @@ -122,11 +129,11 @@ 8.47 static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC = 8.48 Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE); 8.49 static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC = 8.50 - Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE, TYPE_METHODHANDLE_ARRAY); 8.51 + Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY); 8.52 static final String SCRIPTFUNCTIONIMPL_INIT_DESC3 = 8.53 - Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_METHODHANDLE_ARRAY); 8.54 + Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY); 8.55 static final String SCRIPTFUNCTIONIMPL_INIT_DESC4 = 8.56 - Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_PROPERTYMAP, TYPE_METHODHANDLE_ARRAY); 8.57 + Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_PROPERTYMAP, TYPE_SPECIALIZATION_ARRAY); 8.58 8.59 // ScriptObject 8.60 static final String SCRIPTOBJECT_TYPE = TYPE_SCRIPTOBJECT.getInternalName();
9.1 --- a/make/BuildNashorn.gmk Wed Oct 08 14:16:54 2014 -0700 9.2 +++ b/make/BuildNashorn.gmk Tue Oct 14 10:20:24 2014 -0700 9.3 @@ -65,7 +65,7 @@ 9.4 SETUP := GENERATE_NEWBYTECODE_DEBUG, \ 9.5 SRC := $(NASGEN_SRC) $(ASM_SRC), \ 9.6 BIN := $(NASHORN_OUTPUTDIR)/nasgen_classes, \ 9.7 - ADD_JAVAC_FLAGS := -cp $(NASHORN_OUTPUTDIR)/nashorn_classes)) 9.8 + ADD_JAVAC_FLAGS := -bootclasspath "$(BOOT_RTJAR)$(PATH_SEP)$(NASHORN_OUTPUTDIR)/nashorn_classes")) 9.9 9.10 # Nasgen needs nashorn classes 9.11 $(BUILD_NASGEN): $(BUILD_NASHORN)
10.1 --- a/make/build.xml Wed Oct 08 14:16:54 2014 -0700 10.2 +++ b/make/build.xml Tue Oct 14 10:20:24 2014 -0700 10.3 @@ -78,7 +78,7 @@ 10.4 <istrue value="${jfr}"/> 10.5 </condition> 10.6 </target> 10.7 - 10.8 + 10.9 <target name="init" depends="init-conditions, init-cc"> 10.10 <!-- extends jvm args --> 10.11 <property name="run.test.jvmargs" value="${run.test.jvmargs.main} ${run.test.cc.jvmargs} ${jfr.options}"/> 10.12 @@ -419,6 +419,7 @@ 10.13 <propertyref prefix="test-sys-prop-no-security."/> 10.14 <mapper from="test-sys-prop-no-security.*" to="*" type="glob"/> 10.15 </propertyset> 10.16 + <sysproperty key="optimistic.override" value="${optimistic}"/> 10.17 <classpath> 10.18 <pathelement path="${run.test.classpath}"/> 10.19 </classpath> 10.20 @@ -430,7 +431,7 @@ 10.21 <delete dir="${build.dir}/nashorn_code_cache"/> 10.22 <property name="debug.test.jvmargs" value=""/> 10.23 <testng outputdir="${build.test.results.dir}" classfilesetref="test.classes" 10.24 - verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}"> 10.25 + verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}"> 10.26 <jvmarg line="${ext.class.path}"/> 10.27 <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/> 10.28 <jvmarg line="${debug.test.jvmargs}"/> 10.29 @@ -441,6 +442,7 @@ 10.30 <propertyref prefix="test-sys-prop."/> 10.31 <mapper from="test-sys-prop.*" to="*" type="glob"/> 10.32 </propertyset> 10.33 + <sysproperty key="optimistic.override" value="${optimistic}"/> 10.34 <sysproperty key="test.js.excludes.file" value="${exclude.list}"/> 10.35 <classpath> 10.36 <pathelement path="${run.test.classpath}"/> 10.37 @@ -448,7 +450,27 @@ 10.38 </testng> 10.39 </target> 10.40 10.41 - <target name="test" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file, -test-security, -test-nosecurity" if="testng.available"/> 10.42 + <target name="test" depends="test-pessimistic, test-optimistic"/> 10.43 + 10.44 + <target name="test-optimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available"> 10.45 + <echo message="Running test suite in OPTIMISTIC mode..."/> 10.46 + <antcall target="-test-nosecurity" inheritRefs="true"> 10.47 + <param name="optimistic" value="true"/> 10.48 + </antcall> 10.49 + <antcall target="-test-security" inheritRefs="true"> 10.50 + <param name="optimistic" value="true"/> 10.51 + </antcall> 10.52 + </target> 10.53 + 10.54 + <target name="test-pessimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available"> 10.55 + <echo message="Running test suite in PESSIMISTIC mode..."/> 10.56 + <antcall target="-test-nosecurity" inheritRefs="true"> 10.57 + <param name="optimistic" value="false"/> 10.58 + </antcall> 10.59 + <antcall target="-test-security" inheritRefs="true"> 10.60 + <param name="optimistic" value="false"/> 10.61 + </antcall> 10.62 + </target> 10.63 10.64 <target name="check-jemmy.jfx.testng" unless="jemmy.jfx.testng.available"> 10.65 <echo message="WARNING: Jemmy or JavaFX or TestNG not available, will not run tests. Please copy testng.jar, JemmyCore.jar, JemmyFX.jar, JemmyAWTInput.jar under test${file.separator}lib directory. And make sure you have jfxrt.jar in ${java.home}${file.separator}lib${file.separator}ext dir."/>
11.1 --- a/make/project.properties Wed Oct 08 14:16:54 2014 -0700 11.2 +++ b/make/project.properties Tue Oct 14 10:20:24 2014 -0700 11.3 @@ -286,7 +286,8 @@ 11.4 # turn on assertions for tests 11.5 run.test.jvmargs.main=${run.test.jvmargs.common} -ea 11.6 11.7 -# extra jvmargs that might be useful for debugging 11.8 +# Extra jvmargs that might be useful for debugging 11.9 +# and performance improvements/monitoring 11.10 # 11.11 # -XX:+UnlockDiagnosticVMOptions 11.12 # 11.13 @@ -304,9 +305,25 @@ 11.14 # 11.15 # print all compiled nmethods with oopmaps and lots of other info 11.16 # -XX:+PrintNMethods 11.17 +# 11.18 +# activate the generic "UseNewCode" flag to test whatever functionality 11.19 +# lies behind it. This is the preferred way to test a, yet flagless, 11.20 +# feature in HotSpot - for example, the uncommon trap placement fix 11.21 +# was hidden behind this flag before it became the default 11.22 +# 11.23 +# -XX:+UnlockDiagnosticVMOptions -XX:+UseNewCode 11.24 +# 11.25 +# Crank up the type profile level to 222, which has some warmup 11.26 +# penalties, but produces much better code for JavaScript, where better 11.27 +# and more intrusive type profiling is required to get rid of 11.28 +# a large amount of unnecessary guard code, that could not otherwise 11.29 +# be eliminated 11.30 +# 11.31 +# -XX:TypeProfileLevel=222 11.32 +# 11.33 11.34 # Use best known performance options for octane 11.35 -run.test.jvmargs.octane.main=${run.test.jvmargs.common} -XX:+UnlockDiagnosticVMOptions -XX:+UseNewCode -XX:TypeProfileLevel=222 11.36 +run.test.jvmargs.octane.main=${run.test.jvmargs.common} -XX:TypeProfileLevel=222 11.37 11.38 # Security manager args - make sure that we run with the nashorn.policy that the build creates 11.39 run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${build.dir}/nashorn.policy
12.1 --- a/samples/BufferArray.java Wed Oct 08 14:16:54 2014 -0700 12.2 +++ b/samples/BufferArray.java Tue Oct 14 10:20:24 2014 -0700 12.3 @@ -29,8 +29,8 @@ 12.4 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12.5 */ 12.6 12.7 +import java.nio.DoubleBuffer; 12.8 import jdk.nashorn.api.scripting.AbstractJSObject; 12.9 -import java.nio.DoubleBuffer; 12.10 12.11 /** 12.12 * Simple class demonstrating pluggable script object 12.13 @@ -52,41 +52,49 @@ 12.14 // underlying nio buffer 12.15 private final DoubleBuffer buf; 12.16 12.17 - public BufferArray(int size) { 12.18 + /** 12.19 + * Constructor 12.20 + * @param size initial size 12.21 + */ 12.22 + public BufferArray(final int size) { 12.23 buf = DoubleBuffer.allocate(size); 12.24 } 12.25 12.26 - public BufferArray(DoubleBuffer buf) { 12.27 + /** 12.28 + * Constructur 12.29 + * @param buf {@link DoubleBuffer} to link to 12.30 + */ 12.31 + public BufferArray(final DoubleBuffer buf) { 12.32 this.buf = buf; 12.33 } 12.34 12.35 // called to check if indexed property exists 12.36 @Override 12.37 - public boolean hasSlot(int index) { 12.38 + public boolean hasSlot(final int index) { 12.39 return index > 0 && index < buf.capacity(); 12.40 } 12.41 12.42 // get the value from that index 12.43 @Override 12.44 - public Object getSlot(int index) { 12.45 + public Object getSlot(final int index) { 12.46 return buf.get(index); 12.47 } 12.48 12.49 // set the value at that index 12.50 @Override 12.51 - public void setSlot(int index, Object value) { 12.52 + public void setSlot(final int index, final Object value) { 12.53 buf.put(index, ((Number)value).doubleValue()); 12.54 } 12.55 12.56 // do you have a property of that given name? 12.57 @Override 12.58 - public boolean hasMember(String name) { 12.59 + public boolean hasMember(final String name) { 12.60 return "length".equals(name) || "buf".equals(name); 12.61 } 12.62 12.63 // get the value of that named property 12.64 @Override 12.65 - public Object getMember(String name) { 12.66 + public Object getMember(final String name) { 12.67 switch (name) { 12.68 case "length": 12.69 return buf.capacity(); 12.70 @@ -94,7 +102,7 @@ 12.71 // return a 'function' value for this property 12.72 return new AbstractJSObject() { 12.73 @Override 12.74 - public Object call(Object thiz, Object... args) { 12.75 + public Object call(final Object thiz, final Object... args) { 12.76 return BufferArray.this.buf; 12.77 } 12.78 12.79 @@ -104,6 +112,8 @@ 12.80 return true; 12.81 } 12.82 }; 12.83 + default: 12.84 + break; 12.85 } 12.86 return null; 12.87 }
13.1 --- a/src/jdk/nashorn/internal/codegen/ApplySpecialization.java Wed Oct 08 14:16:54 2014 -0700 13.2 +++ b/src/jdk/nashorn/internal/codegen/ApplySpecialization.java Tue Oct 14 10:20:24 2014 -0700 13.3 @@ -27,7 +27,6 @@ 13.4 13.5 import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR; 13.6 import static jdk.nashorn.internal.codegen.CompilerConstants.EXPLODED_ARGUMENT_PREFIX; 13.7 - 13.8 import java.lang.invoke.MethodType; 13.9 import java.util.ArrayDeque; 13.10 import java.util.ArrayList; 13.11 @@ -35,7 +34,6 @@ 13.12 import java.util.HashSet; 13.13 import java.util.List; 13.14 import java.util.Set; 13.15 - 13.16 import jdk.nashorn.internal.ir.AccessNode; 13.17 import jdk.nashorn.internal.ir.CallNode; 13.18 import jdk.nashorn.internal.ir.Expression; 13.19 @@ -131,11 +129,12 @@ 13.20 @SuppressWarnings("serial") 13.21 final UnsupportedOperationException uoe = new UnsupportedOperationException() { 13.22 @Override 13.23 - public Throwable fillInStackTrace() { 13.24 + public synchronized Throwable fillInStackTrace() { 13.25 return null; 13.26 } 13.27 }; 13.28 13.29 + final Set<Expression> argumentsFound = new HashSet<>(); 13.30 final Deque<Set<Expression>> stack = new ArrayDeque<>(); 13.31 //ensure that arguments is only passed as arg to apply 13.32 try { 13.33 @@ -145,7 +144,11 @@ 13.34 } 13.35 13.36 private boolean isArguments(final Expression expr) { 13.37 - return expr instanceof IdentNode && ARGUMENTS.equals(((IdentNode)expr).getName()); 13.38 + if (expr instanceof IdentNode && ARGUMENTS.equals(((IdentNode)expr).getName())) { 13.39 + argumentsFound.add(expr); 13.40 + return true; 13.41 + } 13.42 + return false; 13.43 } 13.44 13.45 private boolean isParam(final String name) { 13.46 @@ -159,7 +162,7 @@ 13.47 13.48 @Override 13.49 public Node leaveIdentNode(final IdentNode identNode) { 13.50 - if (isParam(identNode.getName()) || ARGUMENTS.equals(identNode.getName()) && !isCurrentArg(identNode)) { 13.51 + if (isParam(identNode.getName()) || isArguments(identNode) && !isCurrentArg(identNode)) { 13.52 throw uoe; //avoid filling in stack trace 13.53 } 13.54 return identNode; 13.55 @@ -186,7 +189,9 @@ 13.56 } 13.57 }); 13.58 } catch (final UnsupportedOperationException e) { 13.59 - log.fine("'arguments' escapes, is not used in standard call dispatch, or is reassigned in '" + functionNode.getName() + "'. Aborting"); 13.60 + if (!argumentsFound.isEmpty()) { 13.61 + log.fine("'arguments' is used but escapes, or is reassigned in '" + functionNode.getName() + "'. Aborting"); 13.62 + } 13.63 return true; //bad 13.64 } 13.65 13.66 @@ -267,9 +272,9 @@ 13.67 return false; 13.68 } 13.69 13.70 - if (!Global.instance().isSpecialNameValid("apply")) { 13.71 + if (!Global.isBuiltinFunctionPrototypeApply()) { 13.72 log.fine("Apply transform disabled: apply/call overridden"); 13.73 - assert !Global.instance().isSpecialNameValid("call") : "call and apply should have the same SwitchPoint"; 13.74 + assert !Global.isBuiltinFunctionPrototypeCall() : "call and apply should have the same SwitchPoint"; 13.75 return false; 13.76 } 13.77
14.1 --- a/src/jdk/nashorn/internal/codegen/ClassEmitter.java Wed Oct 08 14:16:54 2014 -0700 14.2 +++ b/src/jdk/nashorn/internal/codegen/ClassEmitter.java Tue Oct 14 10:20:24 2014 -0700 14.3 @@ -51,15 +51,14 @@ 14.4 import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor; 14.5 import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor; 14.6 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup; 14.7 - 14.8 import java.io.ByteArrayOutputStream; 14.9 import java.io.PrintWriter; 14.10 import java.security.AccessController; 14.11 import java.security.PrivilegedAction; 14.12 +import java.util.Collections; 14.13 import java.util.EnumSet; 14.14 import java.util.HashSet; 14.15 import java.util.Set; 14.16 - 14.17 import jdk.internal.org.objectweb.asm.ClassWriter; 14.18 import jdk.internal.org.objectweb.asm.MethodVisitor; 14.19 import jdk.internal.org.objectweb.asm.util.TraceClassVisitor; 14.20 @@ -160,8 +159,12 @@ 14.21 this.methodNames = new HashSet<>(); 14.22 } 14.23 14.24 + /** 14.25 + * Return the method names encountered 14.26 + * @return method names 14.27 + */ 14.28 public Set<String> getMethodNames() { 14.29 - return methodNames; 14.30 + return Collections.unmodifiableSet(methodNames); 14.31 } 14.32 14.33 /**
15.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Oct 08 14:16:54 2014 -0700 15.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Tue Oct 14 10:20:24 2014 -0700 15.3 @@ -104,6 +104,7 @@ 15.4 import jdk.nashorn.internal.ir.IndexNode; 15.5 import jdk.nashorn.internal.ir.JoinPredecessor; 15.6 import jdk.nashorn.internal.ir.JoinPredecessorExpression; 15.7 +import jdk.nashorn.internal.ir.JumpStatement; 15.8 import jdk.nashorn.internal.ir.LabelNode; 15.9 import jdk.nashorn.internal.ir.LexicalContext; 15.10 import jdk.nashorn.internal.ir.LexicalContextNode; 15.11 @@ -1204,17 +1205,21 @@ 15.12 15.13 @Override 15.14 public boolean enterBreakNode(final BreakNode breakNode) { 15.15 + return enterJumpStatement(breakNode); 15.16 + } 15.17 + 15.18 + private boolean enterJumpStatement(final JumpStatement jump) { 15.19 if(!method.isReachable()) { 15.20 return false; 15.21 } 15.22 - enterStatement(breakNode); 15.23 - 15.24 - method.beforeJoinPoint(breakNode); 15.25 - final BreakableNode breakFrom = lc.getBreakable(breakNode.getLabelName()); 15.26 - popScopesUntil(breakFrom); 15.27 - final Label breakLabel = breakFrom.getBreakLabel(); 15.28 - breakLabel.markAsBreakTarget(); 15.29 - method.splitAwareGoto(lc, breakLabel, breakFrom); 15.30 + enterStatement(jump); 15.31 + 15.32 + method.beforeJoinPoint(jump); 15.33 + final BreakableNode target = jump.getTarget(lc); 15.34 + popScopesUntil(target); 15.35 + final Label targetLabel = jump.getTargetLabel(target); 15.36 + targetLabel.markAsBreakTarget(); 15.37 + method.splitAwareGoto(lc, targetLabel, target); 15.38 15.39 return false; 15.40 } 15.41 @@ -1517,19 +1522,7 @@ 15.42 15.43 @Override 15.44 public boolean enterContinueNode(final ContinueNode continueNode) { 15.45 - if(!method.isReachable()) { 15.46 - return false; 15.47 - } 15.48 - enterStatement(continueNode); 15.49 - method.beforeJoinPoint(continueNode); 15.50 - 15.51 - final LoopNode continueTo = lc.getContinueTo(continueNode.getLabelName()); 15.52 - popScopesUntil(continueTo); 15.53 - final Label continueLabel = continueTo.getContinueLabel(); 15.54 - continueLabel.markAsBreakTarget(); 15.55 - method.splitAwareGoto(lc, continueLabel, continueTo); 15.56 - 15.57 - return false; 15.58 + return enterJumpStatement(continueNode); 15.59 } 15.60 15.61 @Override 15.62 @@ -2807,6 +2800,7 @@ 15.63 final boolean hasReturn = method.hasReturn(); 15.64 final SplitMethodEmitter splitMethod = ((SplitMethodEmitter)method); 15.65 final List<Label> targets = splitMethod.getExternalTargets(); 15.66 + final boolean hasControlFlow = hasReturn || !targets.isEmpty(); 15.67 final List<BreakableNode> targetNodes = splitMethod.getExternalTargetNodes(); 15.68 final Type returnType = lc.getCurrentFunction().getReturnType(); 15.69 15.70 @@ -2814,6 +2808,9 @@ 15.71 // Wrap up this method. 15.72 15.73 if(method.isReachable()) { 15.74 + if (hasControlFlow) { 15.75 + method.setSplitState(-1); 15.76 + } 15.77 method.loadCompilerConstant(RETURN, returnType); 15.78 method._return(returnType); 15.79 } 15.80 @@ -2831,17 +2828,16 @@ 15.81 throw e; 15.82 } 15.83 15.84 + //no external jump targets or return in switch node 15.85 + if (!hasControlFlow) { 15.86 + return splitNode; 15.87 + } 15.88 + 15.89 // Handle return from split method if there was one. 15.90 final MethodEmitter caller = method; 15.91 final int targetCount = targets.size(); 15.92 15.93 - //no external jump targets or return in switch node 15.94 - if (!hasReturn && targets.isEmpty()) { 15.95 - return splitNode; 15.96 - } 15.97 - 15.98 - caller.loadCompilerConstant(SCOPE); 15.99 - caller.checkcast(Scope.class); 15.100 + caller.loadScope(); 15.101 caller.invoke(Scope.GET_SPLIT_STATE); 15.102 15.103 final Label breakLabel = new Label("no_split_state"); 15.104 @@ -2873,19 +2869,16 @@ 15.105 caller.loadCompilerConstant(RETURN, returnType); 15.106 caller._return(returnType); 15.107 } else { 15.108 - // Clear split state. 15.109 - caller.loadCompilerConstant(SCOPE); 15.110 - caller.checkcast(Scope.class); 15.111 - caller.load(-1); 15.112 - caller.invoke(Scope.SET_SPLIT_STATE); 15.113 final BreakableNode targetNode = targetNodes.get(i - 1); 15.114 final Label label = targets.get(i - 1); 15.115 - final JoinPredecessor jumpOrigin = splitNode.getJumpOrigin(label); 15.116 - if(jumpOrigin != null) { 15.117 - method.beforeJoinPoint(jumpOrigin); 15.118 + if (!lc.isExternalTarget(splitNode, targetNode)) { 15.119 + final JoinPredecessor jumpOrigin = splitNode.getJumpOrigin(label); 15.120 + if(jumpOrigin != null) { 15.121 + method.beforeJoinPoint(jumpOrigin); 15.122 + } 15.123 + popScopesUntil(targetNode); 15.124 } 15.125 - popScopesUntil(targetNode); 15.126 - caller.splitAwareGoto(lc, targets.get(i - 1), targetNode); 15.127 + caller.splitAwareGoto(lc, label, targetNode); 15.128 } 15.129 } 15.130 caller.label(breakLabel);
16.1 --- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java Wed Oct 08 14:16:54 2014 -0700 16.2 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java Tue Oct 14 10:20:24 2014 -0700 16.3 @@ -38,7 +38,6 @@ 16.4 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SPLIT; 16.5 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SYMBOLS_ASSIGNED; 16.6 import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote; 16.7 - 16.8 import java.io.PrintWriter; 16.9 import java.util.ArrayList; 16.10 import java.util.EnumSet; 16.11 @@ -48,7 +47,6 @@ 16.12 import java.util.Map; 16.13 import java.util.Map.Entry; 16.14 import java.util.Set; 16.15 - 16.16 import jdk.nashorn.internal.AssertsEnabled; 16.17 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; 16.18 import jdk.nashorn.internal.ir.FunctionNode; 16.19 @@ -627,7 +625,7 @@ 16.20 16.21 /** 16.22 * Start a compilation phase 16.23 - * @param compiler 16.24 + * @param compiler the compiler to use 16.25 * @param functionNode function to compile 16.26 * @return function node 16.27 */
17.1 --- a/src/jdk/nashorn/internal/codegen/CompileUnit.java Wed Oct 08 14:16:54 2014 -0700 17.2 +++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java Tue Oct 14 10:20:24 2014 -0700 17.3 @@ -60,6 +60,10 @@ 17.4 emittedUnitCount++; 17.5 } 17.6 17.7 + /** 17.8 + * Get the amount of emitted compile units so far in the system 17.9 + * @return emitted compile unit count 17.10 + */ 17.11 public static int getEmittedUnitCount() { 17.12 return emittedUnitCount; 17.13 } 17.14 @@ -72,6 +76,10 @@ 17.15 return isUsed; 17.16 } 17.17 17.18 + /** 17.19 + * Check if a compile unit has code, not counting inits and clinits 17.20 + * @return true of if there is "real code" in the compile unit 17.21 + */ 17.22 public boolean hasCode() { 17.23 return (classEmitter.getMethodCount() - classEmitter.getInitCount() - classEmitter.getClinitCount()) > 0; 17.24 }
18.1 --- a/src/jdk/nashorn/internal/codegen/Compiler.java Wed Oct 08 14:16:54 2014 -0700 18.2 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java Tue Oct 14 10:20:24 2014 -0700 18.3 @@ -32,7 +32,6 @@ 18.4 import static jdk.nashorn.internal.codegen.CompilerConstants.THIS; 18.5 import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS; 18.6 import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote; 18.7 - 18.8 import java.io.File; 18.9 import java.lang.invoke.MethodType; 18.10 import java.util.Arrays; 18.11 @@ -154,6 +153,13 @@ 18.12 private RecompilableScriptFunctionData compiledFunction; 18.13 18.14 /** 18.15 + * Most compile unit names are longer than the default StringBuilder buffer, 18.16 + * worth startup performance when massive class generation is going on to increase 18.17 + * this 18.18 + */ 18.19 + private static final int COMPILE_UNIT_NAME_BUFFER_SIZE = 32; 18.20 + 18.21 + /** 18.22 * Compilation phases that a compilation goes through 18.23 */ 18.24 public static class CompilationPhases implements Iterable<CompilationPhase> { 18.25 @@ -452,12 +458,16 @@ 18.26 18.27 @Override 18.28 public DebugLogger initLogger(final Context ctxt) { 18.29 + final boolean optimisticTypes = env._optimistic_types; 18.30 + final boolean lazyCompilation = env._lazy_compilation; 18.31 + 18.32 return ctxt.getLogger(this.getClass(), new Consumer<DebugLogger>() { 18.33 @Override 18.34 public void accept(final DebugLogger newLogger) { 18.35 - if (!Compiler.this.getScriptEnvironment()._lazy_compilation) { 18.36 + if (!lazyCompilation) { 18.37 newLogger.warning("WARNING: Running with lazy compilation switched off. This is not a default setting."); 18.38 } 18.39 + newLogger.warning("Optimistic types are ", optimisticTypes ? "ENABLED." : "DISABLED."); 18.40 } 18.41 }); 18.42 } 18.43 @@ -535,9 +545,10 @@ 18.44 * @throws CompilationException if error occurs during compilation 18.45 */ 18.46 public FunctionNode compile(final FunctionNode functionNode, final CompilationPhases phases) throws CompilationException { 18.47 - 18.48 - log.finest("Starting compile job for ", DebugLogger.quote(functionNode.getName()), " phases=", quote(phases.getDesc())); 18.49 - log.indent(); 18.50 + if (log.isEnabled()) { 18.51 + log.info(">> Starting compile job for ", DebugLogger.quote(functionNode.getName()), " phases=", quote(phases.getDesc())); 18.52 + log.indent(); 18.53 + } 18.54 18.55 final String name = DebugLogger.quote(functionNode.getName()); 18.56 18.57 @@ -554,7 +565,7 @@ 18.58 long time = 0L; 18.59 18.60 for (final CompilationPhase phase : phases) { 18.61 - log.fine(phase, " starting for ", quote(name)); 18.62 + log.fine(phase, " starting for ", name); 18.63 18.64 try { 18.65 newFunctionNode = phase.apply(this, phases, newFunctionNode); 18.66 @@ -582,8 +593,11 @@ 18.67 log.unindent(); 18.68 18.69 if (info) { 18.70 - final StringBuilder sb = new StringBuilder(); 18.71 - sb.append("Compile job for ").append(newFunctionNode.getSource()).append(':').append(quote(newFunctionNode.getName())).append(" finished"); 18.72 + final StringBuilder sb = new StringBuilder("<< Finished compile job for "); 18.73 + sb.append(newFunctionNode.getSource()). 18.74 + append(':'). 18.75 + append(quote(newFunctionNode.getName())); 18.76 + 18.77 if (time > 0L && timeLogger != null) { 18.78 assert env.isTimingEnabled(); 18.79 sb.append(" in ").append(time).append(" ms"); 18.80 @@ -631,7 +645,8 @@ 18.81 } 18.82 18.83 String nextCompileUnitName() { 18.84 - final StringBuilder sb = new StringBuilder(firstCompileUnitName); 18.85 + final StringBuilder sb = new StringBuilder(COMPILE_UNIT_NAME_BUFFER_SIZE); 18.86 + sb.append(firstCompileUnitName); 18.87 final int cuid = nextCompileUnitId.getAndIncrement(); 18.88 if (cuid > 0) { 18.89 sb.append("$cu").append(cuid);
19.1 --- a/src/jdk/nashorn/internal/codegen/Label.java Wed Oct 08 14:16:54 2014 -0700 19.2 +++ b/src/jdk/nashorn/internal/codegen/Label.java Tue Oct 14 10:20:24 2014 -0700 19.3 @@ -590,8 +590,13 @@ 19.4 return label.getOffset() > other.label.getOffset(); 19.5 } 19.6 19.7 + private String str; 19.8 + 19.9 @Override 19.10 public String toString() { 19.11 - return name + '_' + id; 19.12 + if (str == null) { 19.13 + str = name + '_' + id; 19.14 + } 19.15 + return str; 19.16 } 19.17 }
20.1 --- a/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Wed Oct 08 14:16:54 2014 -0700 20.2 +++ b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Tue Oct 14 10:20:24 2014 -0700 20.3 @@ -464,21 +464,20 @@ 20.4 20.5 @Override 20.6 public boolean enterBreakNode(final BreakNode breakNode) { 20.7 - if(!reachable) { 20.8 - return false; 20.9 - } 20.10 - 20.11 - final BreakableNode target = lc.getBreakable(breakNode.getLabelName()); 20.12 - return splitAwareJumpToLabel(breakNode, target, target.getBreakLabel()); 20.13 + return enterJumpStatement(breakNode); 20.14 } 20.15 20.16 @Override 20.17 public boolean enterContinueNode(final ContinueNode continueNode) { 20.18 + return enterJumpStatement(continueNode); 20.19 + } 20.20 + 20.21 + private boolean enterJumpStatement(final JumpStatement jump) { 20.22 if(!reachable) { 20.23 return false; 20.24 } 20.25 - final LoopNode target = lc.getContinueTo(continueNode.getLabelName()); 20.26 - return splitAwareJumpToLabel(continueNode, target, target.getContinueLabel()); 20.27 + final BreakableNode target = jump.getTarget(lc); 20.28 + return splitAwareJumpToLabel(jump, target, jump.getTargetLabel(target)); 20.29 } 20.30 20.31 private boolean splitAwareJumpToLabel(final JumpStatement jumpStatement, final BreakableNode target, final Label targetLabel) {
21.1 --- a/src/jdk/nashorn/internal/codegen/Lower.java Wed Oct 08 14:16:54 2014 -0700 21.2 +++ b/src/jdk/nashorn/internal/codegen/Lower.java Tue Oct 14 10:20:24 2014 -0700 21.3 @@ -52,6 +52,7 @@ 21.4 import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 21.5 import jdk.nashorn.internal.ir.IdentNode; 21.6 import jdk.nashorn.internal.ir.IfNode; 21.7 +import jdk.nashorn.internal.ir.JumpStatement; 21.8 import jdk.nashorn.internal.ir.LabelNode; 21.9 import jdk.nashorn.internal.ir.LexicalContext; 21.10 import jdk.nashorn.internal.ir.LiteralNode; 21.11 @@ -382,12 +383,16 @@ 21.12 21.13 @Override 21.14 public Node leaveBreakNode(final BreakNode breakNode) { 21.15 - return copy(breakNode, (Node)Lower.this.lc.getBreakable(breakNode.getLabelName())); 21.16 + return leaveJumpStatement(breakNode); 21.17 } 21.18 21.19 @Override 21.20 public Node leaveContinueNode(final ContinueNode continueNode) { 21.21 - return copy(continueNode, Lower.this.lc.getContinueTo(continueNode.getLabelName())); 21.22 + return leaveJumpStatement(continueNode); 21.23 + } 21.24 + 21.25 + private Node leaveJumpStatement(final JumpStatement jump) { 21.26 + return copy(jump, (Node)jump.getTarget(Lower.this.lc)); 21.27 } 21.28 21.29 @Override 21.30 @@ -627,7 +632,7 @@ 21.31 @Override 21.32 public Node leaveContinueNode(final ContinueNode node) { 21.33 // all inner loops have been popped. 21.34 - if (lex.contains(lex.getContinueTo(node.getLabelName()))) { 21.35 + if (lex.contains(node.getTarget(lex))) { 21.36 escapes.add(node); 21.37 } 21.38 return node;
22.1 --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Oct 08 14:16:54 2014 -0700 22.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java Tue Oct 14 10:20:24 2014 -0700 22.3 @@ -71,7 +71,6 @@ 22.4 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE; 22.5 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC; 22.6 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT; 22.7 - 22.8 import java.io.PrintStream; 22.9 import java.lang.reflect.Array; 22.10 import java.util.Collection; 22.11 @@ -105,7 +104,9 @@ 22.12 import jdk.nashorn.internal.runtime.Debug; 22.13 import jdk.nashorn.internal.runtime.JSType; 22.14 import jdk.nashorn.internal.runtime.RewriteException; 22.15 +import jdk.nashorn.internal.runtime.Scope; 22.16 import jdk.nashorn.internal.runtime.ScriptObject; 22.17 +import jdk.nashorn.internal.runtime.ScriptRuntime; 22.18 import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; 22.19 import jdk.nashorn.internal.runtime.linker.Bootstrap; 22.20 import jdk.nashorn.internal.runtime.logging.DebugLogger; 22.21 @@ -180,9 +181,6 @@ 22.22 /** Bootstrap for array populators */ 22.23 private static final Handle POPULATE_ARRAY_BOOTSTRAP = new Handle(H_INVOKESTATIC, RewriteException.BOOTSTRAP.className(), RewriteException.BOOTSTRAP.name(), RewriteException.BOOTSTRAP.descriptor()); 22.24 22.25 - /** Bootstrap for global name invalidation */ 22.26 - private static final Handle INVALIDATE_NAME_BOOTSTRAP = new Handle(H_INVOKESTATIC, Global.BOOTSTRAP.className(), Global.BOOTSTRAP.name(), Global.BOOTSTRAP.descriptor()); 22.27 - 22.28 /** 22.29 * Constructor - internal use from ClassEmitter only 22.30 * @see ClassEmitter#method 22.31 @@ -1050,6 +1048,14 @@ 22.32 return load(getCompilerConstantSymbol(cc), type != null ? type : getCompilerConstantType(cc)); 22.33 } 22.34 22.35 + MethodEmitter loadScope() { 22.36 + return loadCompilerConstant(SCOPE).checkcast(Scope.class); 22.37 + } 22.38 + 22.39 + MethodEmitter setSplitState(final int state) { 22.40 + return loadScope().load(state).invoke(Scope.SET_SPLIT_STATE); 22.41 + } 22.42 + 22.43 void storeCompilerConstant(final CompilerConstants cc) { 22.44 storeCompilerConstant(cc, null); 22.45 } 22.46 @@ -2131,10 +2137,15 @@ 22.47 } 22.48 22.49 MethodEmitter invalidateSpecialName(final String name) { 22.50 - //this is a nop if the global hasn't registered this as a special name - we can just ignore it 22.51 - if (Global.instance().isSpecialName(name)) { 22.52 - debug("dynamic_invalidate_name", "name=", name); 22.53 - method.visitInvokeDynamicInsn(name, "()V", INVALIDATE_NAME_BOOTSTRAP); 22.54 + switch (name) { 22.55 + case "apply": 22.56 + case "call": 22.57 + debug("invalidate_name", "name=", name); 22.58 + load("Function"); 22.59 + invoke(ScriptRuntime.INVALIDATE_RESERVED_BUILTIN_NAME); 22.60 + break; 22.61 + default: 22.62 + break; 22.63 } 22.64 return this; 22.65 } 22.66 @@ -2575,12 +2586,55 @@ 22.67 * 22.68 * @param args debug information to print 22.69 */ 22.70 + @SuppressWarnings("unused") 22.71 private void debug(final Object... args) { 22.72 if (debug) { 22.73 debug(30, args); 22.74 } 22.75 } 22.76 22.77 + private void debug(final String arg) { 22.78 + if (debug) { 22.79 + debug(30, arg); 22.80 + } 22.81 + } 22.82 + 22.83 + private void debug(final Object arg0, final Object arg1) { 22.84 + if (debug) { 22.85 + debug(30, new Object[] { arg0, arg1 }); 22.86 + } 22.87 + } 22.88 + 22.89 + private void debug(final Object arg0, final Object arg1, final Object arg2) { 22.90 + if (debug) { 22.91 + debug(30, new Object[] { arg0, arg1, arg2 }); 22.92 + } 22.93 + } 22.94 + 22.95 + private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3) { 22.96 + if (debug) { 22.97 + debug(30, new Object[] { arg0, arg1, arg2, arg3 }); 22.98 + } 22.99 + } 22.100 + 22.101 + private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4) { 22.102 + if (debug) { 22.103 + debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4 }); 22.104 + } 22.105 + } 22.106 + 22.107 + private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5) { 22.108 + if (debug) { 22.109 + debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5 }); 22.110 + } 22.111 + } 22.112 + 22.113 + private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5, final Object arg6) { 22.114 + if (debug) { 22.115 + debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6 }); 22.116 + } 22.117 + } 22.118 + 22.119 /** 22.120 * Debug function that outputs generated bytecode and stack contents 22.121 * for a label - indentation is currently the only thing that differs
23.1 --- a/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java Wed Oct 08 14:16:54 2014 -0700 23.2 +++ b/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java Tue Oct 14 10:20:24 2014 -0700 23.3 @@ -429,7 +429,6 @@ 23.4 } 23.5 23.6 private static void doCleanup() throws IOException { 23.7 - final long start = System.nanoTime(); 23.8 final Path[] files = getAllRegularFilesInLastModifiedOrder(); 23.9 final int nFiles = files.length; 23.10 final int filesToDelete = Math.max(0, nFiles - MAX_FILES); 23.11 @@ -444,8 +443,7 @@ 23.12 // does not increase filesDeleted 23.13 } 23.14 files[i] = null; // gc eligible 23.15 - }; 23.16 - final long duration = System.nanoTime() - start; 23.17 + } 23.18 } 23.19 23.20 private static Path[] getAllRegularFilesInLastModifiedOrder() throws IOException { 23.21 @@ -456,7 +454,7 @@ 23.22 @Override 23.23 public boolean test(final Path path) { 23.24 return !Files.isDirectory(path); 23.25 - }; 23.26 + } 23.27 }) 23.28 .map(new Function<Path, PathAndTime>() { 23.29 @Override 23.30 @@ -497,7 +495,7 @@ 23.31 private static long getTime(final Path path) { 23.32 try { 23.33 return Files.getLastModifiedTime(path).toMillis(); 23.34 - } catch (IOException e) { 23.35 + } catch (final IOException e) { 23.36 // All files for which we can't retrieve the last modified date will be considered oldest. 23.37 return -1L; 23.38 }
24.1 --- a/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java Wed Oct 08 14:16:54 2014 -0700 24.2 +++ b/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java Tue Oct 14 10:20:24 2014 -0700 24.3 @@ -25,8 +25,6 @@ 24.4 24.5 package jdk.nashorn.internal.codegen; 24.6 24.7 -import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE; 24.8 - 24.9 import java.util.ArrayList; 24.10 import java.util.List; 24.11 import jdk.internal.org.objectweb.asm.MethodVisitor; 24.12 @@ -34,7 +32,6 @@ 24.13 import jdk.nashorn.internal.ir.BreakableNode; 24.14 import jdk.nashorn.internal.ir.LexicalContext; 24.15 import jdk.nashorn.internal.ir.SplitNode; 24.16 -import jdk.nashorn.internal.runtime.Scope; 24.17 24.18 /** 24.19 * Emitter used for splitting methods. Needs to keep track of if there are jump targets 24.20 @@ -65,15 +62,13 @@ 24.21 assert splitNode != null; 24.22 final int index = findExternalTarget(lc, label, targetNode); 24.23 if (index >= 0) { 24.24 - loadCompilerConstant(SCOPE); 24.25 - checkcast(Scope.class); 24.26 - load(index + 1); 24.27 - invoke(Scope.SET_SPLIT_STATE); 24.28 - loadUndefined(Type.OBJECT); 24.29 - _return(functionNode.getReturnType()); 24.30 - return; 24.31 + setSplitState(index + 1); // 0 is ordinary return 24.32 + final Type retType = functionNode.getReturnType(); 24.33 + loadUndefined(retType); 24.34 + _return(retType); 24.35 + } else { 24.36 + super.splitAwareGoto(lc, label, targetNode); 24.37 } 24.38 - super.splitAwareGoto(lc, label, targetNode); 24.39 } 24.40 24.41 private int findExternalTarget(final LexicalContext lc, final Label label, final BreakableNode targetNode) { 24.42 @@ -94,11 +89,7 @@ 24.43 @Override 24.44 MethodEmitter registerReturn() { 24.45 setHasReturn(); 24.46 - loadCompilerConstant(SCOPE); 24.47 - checkcast(Scope.class); 24.48 - load(0); 24.49 - invoke(Scope.SET_SPLIT_STATE); 24.50 - return this; 24.51 + return setSplitState(0); 24.52 } 24.53 24.54 final List<Label> getExternalTargets() {
25.1 --- a/src/jdk/nashorn/internal/codegen/types/Type.java Wed Oct 08 14:16:54 2014 -0700 25.2 +++ b/src/jdk/nashorn/internal/codegen/types/Type.java Tue Oct 14 10:20:24 2014 -0700 25.3 @@ -47,7 +47,6 @@ 25.4 import static jdk.internal.org.objectweb.asm.Opcodes.T_INT; 25.5 import static jdk.internal.org.objectweb.asm.Opcodes.T_LONG; 25.6 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; 25.7 - 25.8 import java.io.DataInput; 25.9 import java.io.DataOutput; 25.10 import java.io.IOException; 25.11 @@ -55,8 +54,10 @@ 25.12 import java.lang.invoke.MethodHandle; 25.13 import java.lang.invoke.MethodHandles; 25.14 import java.lang.invoke.MethodType; 25.15 +import java.util.Collections; 25.16 import java.util.Map; 25.17 import java.util.TreeMap; 25.18 +import java.util.WeakHashMap; 25.19 import java.util.concurrent.ConcurrentHashMap; 25.20 import java.util.concurrent.ConcurrentMap; 25.21 import jdk.internal.org.objectweb.asm.Handle; 25.22 @@ -104,6 +105,16 @@ 25.23 /** The class for this type */ 25.24 private final Class<?> clazz; 25.25 25.26 + /** 25.27 + * Cache for internal types - this is a query that requires complex stringbuilding inside 25.28 + * ASM and it saves startup time to cache the type mappings 25.29 + */ 25.30 + private static final Map<Class<?>, jdk.internal.org.objectweb.asm.Type> INTERNAL_TYPE_CACHE = 25.31 + Collections.synchronizedMap(new WeakHashMap<Class<?>, jdk.internal.org.objectweb.asm.Type>()); 25.32 + 25.33 + /** Internal ASM type for this Type - computed once at construction */ 25.34 + private final jdk.internal.org.objectweb.asm.Type internalType; 25.35 + 25.36 /** Weights are used to decide which types are "wider" than other types */ 25.37 protected static final int MIN_WEIGHT = -1; 25.38 25.39 @@ -122,12 +133,13 @@ 25.40 * @param slots how many bytecode slots the type takes up 25.41 */ 25.42 Type(final String name, final Class<?> clazz, final int weight, final int slots) { 25.43 - this.name = name; 25.44 - this.clazz = clazz; 25.45 - this.descriptor = jdk.internal.org.objectweb.asm.Type.getDescriptor(clazz); 25.46 - this.weight = weight; 25.47 + this.name = name; 25.48 + this.clazz = clazz; 25.49 + this.descriptor = jdk.internal.org.objectweb.asm.Type.getDescriptor(clazz); 25.50 + this.weight = weight; 25.51 assert weight >= MIN_WEIGHT && weight <= MAX_WEIGHT : "illegal type weight: " + weight; 25.52 - this.slots = slots; 25.53 + this.slots = slots; 25.54 + this.internalType = getInternalType(clazz); 25.55 } 25.56 25.57 /** 25.58 @@ -299,7 +311,7 @@ 25.59 * 25.60 * @param typeMap the type map 25.61 * @param output data output 25.62 - * @throws IOException 25.63 + * @throws IOException if write cannot be completed 25.64 */ 25.65 public static void writeTypeMap(final Map<Integer, Type> typeMap, final DataOutput output) throws IOException { 25.66 if (typeMap == null) { 25.67 @@ -329,7 +341,7 @@ 25.68 * 25.69 * @param input data input 25.70 * @return type map 25.71 - * @throws IOException 25.72 + * @throws IOException if read cannot be completed 25.73 */ 25.74 public static Map<Integer, Type> readTypeMap(final DataInput input) throws IOException { 25.75 final int size = input.readInt(); 25.76 @@ -357,11 +369,22 @@ 25.77 } 25.78 25.79 private jdk.internal.org.objectweb.asm.Type getInternalType() { 25.80 - return jdk.internal.org.objectweb.asm.Type.getType(getTypeClass()); 25.81 + return internalType; 25.82 + } 25.83 + 25.84 + private static jdk.internal.org.objectweb.asm.Type lookupInternalType(final Class<?> type) { 25.85 + final Map<Class<?>, jdk.internal.org.objectweb.asm.Type> cache = INTERNAL_TYPE_CACHE; 25.86 + jdk.internal.org.objectweb.asm.Type itype = cache.get(type); 25.87 + if (itype != null) { 25.88 + return itype; 25.89 + } 25.90 + itype = jdk.internal.org.objectweb.asm.Type.getType(type); 25.91 + cache.put(type, itype); 25.92 + return itype; 25.93 } 25.94 25.95 private static jdk.internal.org.objectweb.asm.Type getInternalType(final Class<?> type) { 25.96 - return jdk.internal.org.objectweb.asm.Type.getType(type); 25.97 + return lookupInternalType(type); 25.98 } 25.99 25.100 static void invokestatic(final MethodVisitor method, final Call call) {
26.1 --- a/src/jdk/nashorn/internal/ir/BreakNode.java Wed Oct 08 14:16:54 2014 -0700 26.2 +++ b/src/jdk/nashorn/internal/ir/BreakNode.java Tue Oct 14 10:20:24 2014 -0700 26.3 @@ -25,6 +25,7 @@ 26.4 26.5 package jdk.nashorn.internal.ir; 26.6 26.7 +import jdk.nashorn.internal.codegen.Label; 26.8 import jdk.nashorn.internal.ir.annotations.Immutable; 26.9 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 26.10 26.11 @@ -68,4 +69,14 @@ 26.12 String getStatementName() { 26.13 return "break"; 26.14 } 26.15 + 26.16 + @Override 26.17 + public BreakableNode getTarget(final LexicalContext lc) { 26.18 + return lc.getBreakable(getLabelName()); 26.19 + } 26.20 + 26.21 + @Override 26.22 + public Label getTargetLabel(final BreakableNode target) { 26.23 + return target.getBreakLabel(); 26.24 + } 26.25 }
27.1 --- a/src/jdk/nashorn/internal/ir/ContinueNode.java Wed Oct 08 14:16:54 2014 -0700 27.2 +++ b/src/jdk/nashorn/internal/ir/ContinueNode.java Tue Oct 14 10:20:24 2014 -0700 27.3 @@ -25,6 +25,7 @@ 27.4 27.5 package jdk.nashorn.internal.ir; 27.6 27.7 +import jdk.nashorn.internal.codegen.Label; 27.8 import jdk.nashorn.internal.ir.annotations.Immutable; 27.9 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 27.10 27.11 @@ -67,5 +68,16 @@ 27.12 String getStatementName() { 27.13 return "continue"; 27.14 } 27.15 + 27.16 + 27.17 + @Override 27.18 + public BreakableNode getTarget(final LexicalContext lc) { 27.19 + return lc.getContinueTo(getLabelName()); 27.20 + } 27.21 + 27.22 + @Override 27.23 + public Label getTargetLabel(final BreakableNode target) { 27.24 + return ((LoopNode)target).getContinueLabel(); 27.25 + } 27.26 } 27.27
28.1 --- a/src/jdk/nashorn/internal/ir/FunctionNode.java Wed Oct 08 14:16:54 2014 -0700 28.2 +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java Tue Oct 14 10:20:24 2014 -0700 28.3 @@ -238,17 +238,21 @@ 28.4 * Note that even IS_STRICT is one such flag but that requires special handling. 28.5 */ 28.6 28.7 - // parser, lower debugging this function 28.8 + /** parser, print parse tree */ 28.9 public static final int IS_PRINT_PARSE = 1 << 18; 28.10 + /** parser, print lower parse tree */ 28.11 public static final int IS_PRINT_LOWER_PARSE = 1 << 19; 28.12 + /** parser, print AST */ 28.13 public static final int IS_PRINT_AST = 1 << 20; 28.14 + /** parser, print lower AST */ 28.15 public static final int IS_PRINT_LOWER_AST = 1 << 21; 28.16 + /** parser, print symbols */ 28.17 public static final int IS_PRINT_SYMBOLS = 1 << 22; 28.18 28.19 + // callsite tracing, profiling within this function 28.20 /** profile callsites in this function? */ 28.21 public static final int IS_PROFILE = 1 << 23; 28.22 28.23 - // callsite tracing, profiling within this function 28.24 /** trace callsite enterexit in this function? */ 28.25 public static final int IS_TRACE_ENTEREXIT = 1 << 24; 28.26 28.27 @@ -337,7 +341,7 @@ 28.28 private FunctionNode( 28.29 final FunctionNode functionNode, 28.30 final long lastToken, 28.31 - Object endParserState, 28.32 + final Object endParserState, 28.33 final int flags, 28.34 final String name, 28.35 final Type returnType,
29.1 --- a/src/jdk/nashorn/internal/ir/JumpStatement.java Wed Oct 08 14:16:54 2014 -0700 29.2 +++ b/src/jdk/nashorn/internal/ir/JumpStatement.java Tue Oct 14 10:20:24 2014 -0700 29.3 @@ -25,6 +25,8 @@ 29.4 29.5 package jdk.nashorn.internal.ir; 29.6 29.7 +import jdk.nashorn.internal.codegen.Label; 29.8 + 29.9 /** 29.10 * Common base class for jump statements (e.g. {@code break} and {@code continue}). 29.11 */ 29.12 @@ -82,6 +84,24 @@ 29.13 29.14 abstract String getStatementName(); 29.15 29.16 + /** 29.17 + * Finds the target for this jump statement in a lexical context. 29.18 + * @param lc the lexical context 29.19 + * @return the target, or null if not found 29.20 + */ 29.21 + public abstract BreakableNode getTarget(final LexicalContext lc); 29.22 + 29.23 + /** 29.24 + * Returns the label corresponding to this kind of jump statement (either a break or continue label) in the target. 29.25 + * @param target the target. Note that it need not be the target of this jump statement, as the method can retrieve 29.26 + * a label on any passed target as long as the target has a label of the requisite kind. Of course, it is advisable 29.27 + * to invoke the method on a jump statement that targets the breakable. 29.28 + * @return the label of the target corresponding to the kind of jump statement. 29.29 + * @throws ClassCastException if invoked on the kind of breakable node that this jump statement is not prepared to 29.30 + * handle. 29.31 + */ 29.32 + public abstract Label getTargetLabel(final BreakableNode target); 29.33 + 29.34 @Override 29.35 public JumpStatement setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) { 29.36 if(this.conversion == conversion) {
30.1 --- a/src/jdk/nashorn/internal/ir/LiteralNode.java Wed Oct 08 14:16:54 2014 -0700 30.2 +++ b/src/jdk/nashorn/internal/ir/LiteralNode.java Tue Oct 14 10:20:24 2014 -0700 30.3 @@ -237,6 +237,10 @@ 30.4 return value; 30.5 } 30.6 30.7 + private static Expression[] valueToArray(final List<Expression> value) { 30.8 + return value.toArray(new Expression[value.size()]); 30.9 + } 30.10 + 30.11 /** 30.12 * Create a new null literal 30.13 * 30.14 @@ -981,10 +985,9 @@ 30.15 * @return the new literal node 30.16 */ 30.17 public static LiteralNode<Expression[]> newInstance(final long token, final int finish, final List<Expression> value) { 30.18 - return new ArrayLiteralNode(token, finish, value.toArray(new Expression[value.size()])); 30.19 + return new ArrayLiteralNode(token, finish, valueToArray(value)); 30.20 } 30.21 30.22 - 30.23 /** 30.24 * Create a new array literal based on a parent node (source, token, finish) 30.25 * 30.26 @@ -994,7 +997,7 @@ 30.27 * @return the new literal node 30.28 */ 30.29 public static LiteralNode<?> newInstance(final Node parent, final List<Expression> value) { 30.30 - return new ArrayLiteralNode(parent.getToken(), parent.getFinish(), value.toArray(new Expression[value.size()])); 30.31 + return new ArrayLiteralNode(parent.getToken(), parent.getFinish(), valueToArray(value)); 30.32 } 30.33 30.34 /**
31.1 --- a/src/jdk/nashorn/internal/ir/Symbol.java Wed Oct 08 14:16:54 2014 -0700 31.2 +++ b/src/jdk/nashorn/internal/ir/Symbol.java Tue Oct 14 10:20:24 2014 -0700 31.3 @@ -448,14 +448,25 @@ 31.4 return (flags & IS_FUNCTION_SELF) != 0; 31.5 } 31.6 31.7 + /** 31.8 + * Is this a block scoped symbol 31.9 + * @return true if block scoped 31.10 + */ 31.11 public boolean isBlockScoped() { 31.12 return isLet() || isConst(); 31.13 } 31.14 31.15 + /** 31.16 + * Has this symbol been declared 31.17 + * @return true if declared 31.18 + */ 31.19 public boolean hasBeenDeclared() { 31.20 return (flags & HAS_BEEN_DECLARED) != 0; 31.21 } 31.22 31.23 + /** 31.24 + * Mark this symbol as declared 31.25 + */ 31.26 public void setHasBeenDeclared() { 31.27 if (!hasBeenDeclared()) { 31.28 flags |= HAS_BEEN_DECLARED;
32.1 --- a/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java Wed Oct 08 14:16:54 2014 -0700 32.2 +++ b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java Tue Oct 14 10:20:24 2014 -0700 32.3 @@ -116,6 +116,10 @@ 32.4 32.5 private static final String VOID_TAG = "[VOID]"; 32.6 32.7 + private static void err(final String str) { 32.8 + Context.getContext().getErr().println(str); 32.9 + } 32.10 + 32.11 /** 32.12 * Tracer that is applied before a value is returned from the traced function. It will output the return 32.13 * value and its class 32.14 @@ -124,13 +128,16 @@ 32.15 * @return return value unmodified 32.16 */ 32.17 static Object traceReturn(final DebugLogger logger, final Object value) { 32.18 - if (logger.isEnabled()) { 32.19 - final String str = " return" + 32.20 - (VOID_TAG.equals(value) ? 32.21 - ";" : 32.22 - " " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']')); 32.23 + final String str = " return" + 32.24 + (VOID_TAG.equals(value) ? 32.25 + ";" : 32.26 + " " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']')); 32.27 + if (logger == null) { 32.28 + err(str); 32.29 + } else if (logger.isEnabled()) { 32.30 logger.log(TRACE_LEVEL, str); 32.31 } 32.32 + 32.33 return value; 32.34 } 32.35 32.36 @@ -169,8 +176,11 @@ 32.37 } 32.38 } 32.39 32.40 - assert logger != null; 32.41 - logger.log(TRACE_LEVEL, sb); 32.42 + if (logger == null) { 32.43 + err(sb.toString()); 32.44 + } else { 32.45 + logger.log(TRACE_LEVEL, sb); 32.46 + } 32.47 stacktrace(logger); 32.48 } 32.49 32.50 @@ -181,7 +191,12 @@ 32.51 final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 32.52 final PrintStream ps = new PrintStream(baos); 32.53 new Throwable().printStackTrace(ps); 32.54 - logger.log(TRACE_LEVEL, baos.toString()); 32.55 + final String st = baos.toString(); 32.56 + if (logger == null) { 32.57 + err(st); 32.58 + } else { 32.59 + logger.log(TRACE_LEVEL, st); 32.60 + } 32.61 } 32.62 32.63 private static String argString(final Object arg) { 32.64 @@ -201,7 +216,7 @@ 32.65 if (arg instanceof ScriptObject) { 32.66 return arg.toString() + 32.67 " (map=" + Debug.id(((ScriptObject)arg).getMap()) + 32.68 - ")"; 32.69 + ')'; 32.70 } 32.71 32.72 return arg.toString(); 32.73 @@ -209,6 +224,18 @@ 32.74 32.75 /** 32.76 * Add a debug printout to a method handle, tracing parameters and return values 32.77 + * Output will be unconditional to stderr 32.78 + * 32.79 + * @param mh method handle to trace 32.80 + * @param tag start of trace message 32.81 + * @return traced method handle 32.82 + */ 32.83 + public static MethodHandle addDebugPrintout(final MethodHandle mh, final Object tag) { 32.84 + return addDebugPrintout(null, Level.OFF, mh, 0, true, tag); 32.85 + } 32.86 + 32.87 + /** 32.88 + * Add a debug printout to a method handle, tracing parameters and return values 32.89 * 32.90 * @param logger a specific logger to which to write the output 32.91 * @param level level over which to print 32.92 @@ -222,6 +249,20 @@ 32.93 32.94 /** 32.95 * Add a debug printout to a method handle, tracing parameters and return values 32.96 + * Output will be unconditional to stderr 32.97 + * 32.98 + * @param mh method handle to trace 32.99 + * @param paramStart first param to print/trace 32.100 + * @param printReturnValue should we print/trace return value if available? 32.101 + * @param tag start of trace message 32.102 + * @return traced method handle 32.103 + */ 32.104 + public static MethodHandle addDebugPrintout(final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Object tag) { 32.105 + return addDebugPrintout(null, Level.OFF, mh, paramStart, printReturnValue, tag); 32.106 + } 32.107 + 32.108 + /** 32.109 + * Add a debug printout to a method handle, tracing parameters and return values 32.110 * 32.111 * @param logger a specific logger to which to write the output 32.112 * @param level level over which to print 32.113 @@ -240,7 +281,6 @@ 32.114 return mh; 32.115 } 32.116 32.117 - assert logger != null; 32.118 assert TRACE != null; 32.119 32.120 MethodHandle trace = MethodHandles.insertArguments(TRACE, 0, logger, tag, paramStart); 32.121 @@ -428,6 +468,12 @@ 32.122 } 32.123 32.124 @Override 32.125 + public MethodHandle identity(final Class<?> type) { 32.126 + final MethodHandle mh = MethodHandles.identity(type); 32.127 + return debug(mh, "identity", type); 32.128 + } 32.129 + 32.130 + @Override 32.131 public MethodHandle asCollector(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) { 32.132 final MethodHandle mh = handle.asCollector(arrayType, arrayLength); 32.133 return debug(mh, "asCollector", handle, arrayType, arrayLength);
33.1 --- a/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java Wed Oct 08 14:16:54 2014 -0700 33.2 +++ b/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java Tue Oct 14 10:20:24 2014 -0700 33.3 @@ -173,6 +173,15 @@ 33.4 public MethodHandle constant(Class<?> type, Object value); 33.5 33.6 /** 33.7 + * Wrapper for {@link java.lang.invoke.MethodHandles#identity(Class)} 33.8 + * 33.9 + * @param type type of value 33.10 + * 33.11 + * @return method handle that returns identity argument 33.12 + */ 33.13 + public MethodHandle identity(Class<?> type); 33.14 + 33.15 + /** 33.16 * Wrapper for {@link java.lang.invoke.MethodHandle#asType(MethodType)} 33.17 * 33.18 * @param handle method handle for type conversion
34.1 --- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java Wed Oct 08 14:16:54 2014 -0700 34.2 +++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java Tue Oct 14 10:20:24 2014 -0700 34.3 @@ -31,6 +31,7 @@ 34.4 34.5 import java.nio.ByteBuffer; 34.6 import java.nio.ByteOrder; 34.7 + 34.8 import jdk.internal.dynalink.CallSiteDescriptor; 34.9 import jdk.internal.dynalink.linker.GuardedInvocation; 34.10 import jdk.internal.dynalink.linker.LinkRequest;
35.1 --- a/src/jdk/nashorn/internal/objects/Global.java Wed Oct 08 14:16:54 2014 -0700 35.2 +++ b/src/jdk/nashorn/internal/objects/Global.java Tue Oct 14 10:20:24 2014 -0700 35.3 @@ -25,23 +25,19 @@ 35.4 35.5 package jdk.nashorn.internal.objects; 35.6 35.7 -import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; 35.8 import static jdk.nashorn.internal.lookup.Lookup.MH; 35.9 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; 35.10 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 35.11 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 35.12 - 35.13 import java.io.IOException; 35.14 import java.io.PrintWriter; 35.15 -import java.lang.invoke.CallSite; 35.16 -import java.lang.invoke.ConstantCallSite; 35.17 import java.lang.invoke.MethodHandle; 35.18 import java.lang.invoke.MethodHandles; 35.19 -import java.lang.invoke.MethodType; 35.20 import java.lang.invoke.SwitchPoint; 35.21 import java.lang.reflect.Field; 35.22 +import java.util.ArrayList; 35.23 import java.util.Arrays; 35.24 -import java.util.HashMap; 35.25 +import java.util.List; 35.26 import java.util.Map; 35.27 import java.util.concurrent.Callable; 35.28 import java.util.concurrent.ConcurrentHashMap; 35.29 @@ -52,8 +48,6 @@ 35.30 import jdk.internal.dynalink.linker.LinkRequest; 35.31 import jdk.nashorn.api.scripting.ClassFilter; 35.32 import jdk.nashorn.api.scripting.ScriptObjectMirror; 35.33 -import jdk.nashorn.internal.codegen.ApplySpecialization; 35.34 -import jdk.nashorn.internal.codegen.CompilerConstants.Call; 35.35 import jdk.nashorn.internal.lookup.Lookup; 35.36 import jdk.nashorn.internal.objects.annotations.Attribute; 35.37 import jdk.nashorn.internal.objects.annotations.Property; 35.38 @@ -72,6 +66,7 @@ 35.39 import jdk.nashorn.internal.runtime.ScriptObject; 35.40 import jdk.nashorn.internal.runtime.ScriptRuntime; 35.41 import jdk.nashorn.internal.runtime.ScriptingFunctions; 35.42 +import jdk.nashorn.internal.runtime.Specialization; 35.43 import jdk.nashorn.internal.runtime.arrays.ArrayData; 35.44 import jdk.nashorn.internal.runtime.linker.Bootstrap; 35.45 import jdk.nashorn.internal.runtime.linker.InvokeByName; 35.46 @@ -107,10 +102,6 @@ 35.47 * it's when you start adding property checks for said builtins you have 35.48 * problems with guard speed. 35.49 */ 35.50 - public final Map<String, SwitchPoint> optimisticFunctionMap; 35.51 - 35.52 - /** Name invalidator for things like call/apply */ 35.53 - public static final Call BOOTSTRAP = staticCall(MethodHandles.lookup(), Global.class, "invalidateNameBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class); 35.54 35.55 /** Nashorn extension: arguments array */ 35.56 @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE) 35.57 @@ -428,9 +419,6 @@ 35.58 private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class); 35.59 private static final MethodHandle EXIT = findOwnMH_S("exit", Object.class, Object.class, Object.class); 35.60 35.61 - /** Invalidate a reserved name, such as "apply" or "call" if assigned */ 35.62 - public MethodHandle INVALIDATE_RESERVED_NAME = MH.bindTo(findOwnMH_V("invalidateReservedName", void.class, String.class), this); 35.63 - 35.64 // initialized by nasgen 35.65 private static PropertyMap $nasgenmap$; 35.66 35.67 @@ -482,7 +470,6 @@ 35.68 super(checkAndGetMap(context)); 35.69 this.context = context; 35.70 this.setIsScope(); 35.71 - this.optimisticFunctionMap = new HashMap<>(); 35.72 //we can only share one instance of Global constants between globals, or we consume way too much 35.73 //memory - this is good enough for most programs 35.74 while (gcsInstance.get() == null) { 35.75 @@ -574,6 +561,7 @@ 35.76 * 35.77 * @param engine ScriptEngine to initialize 35.78 */ 35.79 + @SuppressWarnings("hiding") 35.80 public void initBuiltinObjects(final ScriptEngine engine) { 35.81 if (this.builtinObject != null) { 35.82 // already initialized, just return 35.83 @@ -918,10 +906,12 @@ 35.84 } 35.85 35.86 switch (nameStr) { 35.87 - case "context": 35.88 - return sctxt; 35.89 - case "engine": 35.90 - return global.engine; 35.91 + case "context": 35.92 + return sctxt; 35.93 + case "engine": 35.94 + return global.engine; 35.95 + default: 35.96 + break; 35.97 } 35.98 35.99 if (self == UNDEFINED) { 35.100 @@ -1244,6 +1234,40 @@ 35.101 return instance.function == instance.getBuiltinFunction(); 35.102 } 35.103 35.104 + /** 35.105 + * Get the switchpoint used to check property changes for Function.prototype.apply 35.106 + * @return the switchpoint guarding apply (same as guarding call, and everything else in function) 35.107 + */ 35.108 + public static SwitchPoint getBuiltinFunctionApplySwitchPoint() { 35.109 + return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint(); 35.110 + } 35.111 + 35.112 + private static boolean isBuiltinFunctionProperty(final String name) { 35.113 + final Global instance = Global.instance(); 35.114 + final ScriptFunction builtinFunction = instance.getBuiltinFunction(); 35.115 + if (builtinFunction == null) { 35.116 + return false; //conservative for compile-only mode 35.117 + } 35.118 + final boolean isBuiltinFunction = instance.function == builtinFunction; 35.119 + return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin(); 35.120 + } 35.121 + 35.122 + /** 35.123 + * Check if the Function.prototype.apply has not been replaced 35.124 + * @return true if Function.prototype.apply has been replaced 35.125 + */ 35.126 + public static boolean isBuiltinFunctionPrototypeApply() { 35.127 + return isBuiltinFunctionProperty("apply"); 35.128 + } 35.129 + 35.130 + /** 35.131 + * Check if the Function.prototype.apply has not been replaced 35.132 + * @return true if Function.prototype.call has been replaced 35.133 + */ 35.134 + public static boolean isBuiltinFunctionPrototypeCall() { 35.135 + return isBuiltinFunctionProperty("call"); 35.136 + } 35.137 + 35.138 private ScriptFunction getBuiltinJSAdapter() { 35.139 return builtinJSAdapter; 35.140 } 35.141 @@ -1688,6 +1712,13 @@ 35.142 splitState = state; 35.143 } 35.144 35.145 + private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) { 35.146 + final T func = initConstructor(name, clazz); 35.147 + tagBuiltinProperties(name, func); 35.148 + return func; 35.149 + } 35.150 + 35.151 + @SuppressWarnings("hiding") 35.152 private void init(final ScriptEngine engine) { 35.153 assert Context.getGlobal() == this : "this global is not set as current"; 35.154 35.155 @@ -1702,8 +1733,19 @@ 35.156 // initialize global function properties 35.157 this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL); 35.158 35.159 - this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT, 35.160 - new MethodHandle[] { GlobalFunctions.PARSEINT_OI, GlobalFunctions.PARSEINT_O }); 35.161 + this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT, 35.162 + new Specialization[] { 35.163 + new Specialization(GlobalFunctions.PARSEINT_Z), 35.164 + new Specialization(GlobalFunctions.PARSEINT_I), 35.165 + new Specialization(GlobalFunctions.PARSEINT_J), 35.166 + new Specialization(GlobalFunctions.PARSEINT_OI), 35.167 + new Specialization(GlobalFunctions.PARSEINT_O) }); 35.168 + this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT); 35.169 + this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN, 35.170 + new Specialization[] { 35.171 + new Specialization(GlobalFunctions.IS_NAN_I), 35.172 + new Specialization(GlobalFunctions.IS_NAN_J), 35.173 + new Specialization(GlobalFunctions.IS_NAN_D) }); 35.174 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT); 35.175 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN); 35.176 this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE); 35.177 @@ -1720,15 +1762,15 @@ 35.178 this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT); 35.179 35.180 // built-in constructors 35.181 - this.builtinArray = initConstructor("Array", ScriptFunction.class); 35.182 - this.builtinBoolean = initConstructor("Boolean", ScriptFunction.class); 35.183 - this.builtinDate = initConstructor("Date", ScriptFunction.class); 35.184 - this.builtinJSON = initConstructor("JSON", ScriptObject.class); 35.185 - this.builtinJSAdapter = initConstructor("JSAdapter", ScriptFunction.class); 35.186 - this.builtinMath = initConstructor("Math", ScriptObject.class); 35.187 - this.builtinNumber = initConstructor("Number", ScriptFunction.class); 35.188 - this.builtinRegExp = initConstructor("RegExp", ScriptFunction.class); 35.189 - this.builtinString = initConstructor("String", ScriptFunction.class); 35.190 + this.builtinArray = initConstructorAndSwitchPoint("Array", ScriptFunction.class); 35.191 + this.builtinBoolean = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class); 35.192 + this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class); 35.193 + this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class); 35.194 + this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class); 35.195 + this.builtinMath = initConstructorAndSwitchPoint("Math", ScriptObject.class); 35.196 + this.builtinNumber = initConstructorAndSwitchPoint("Number", ScriptFunction.class); 35.197 + this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class); 35.198 + this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class); 35.199 35.200 // initialize String.prototype.length to 0 35.201 // add String.prototype.length 35.202 @@ -1830,6 +1872,8 @@ 35.203 // Error.prototype.message = ""; 35.204 errorProto.set(NativeError.MESSAGE, "", 0); 35.205 35.206 + tagBuiltinProperties("Error", builtinError); 35.207 + 35.208 this.builtinEvalError = initErrorSubtype("EvalError", errorProto); 35.209 this.builtinRangeError = initErrorSubtype("RangeError", errorProto); 35.210 this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto); 35.211 @@ -1844,6 +1888,7 @@ 35.212 prototype.set(NativeError.NAME, name, 0); 35.213 prototype.set(NativeError.MESSAGE, "", 0); 35.214 prototype.setInitialProto(errorProto); 35.215 + tagBuiltinProperties(name, cons); 35.216 return cons; 35.217 } 35.218 35.219 @@ -1910,17 +1955,18 @@ 35.220 } 35.221 35.222 private void initTypedArray() { 35.223 - this.builtinArrayBuffer = initConstructor("ArrayBuffer", ScriptFunction.class); 35.224 - this.builtinDataView = initConstructor("DataView", ScriptFunction.class); 35.225 - this.builtinInt8Array = initConstructor("Int8Array", ScriptFunction.class); 35.226 - this.builtinUint8Array = initConstructor("Uint8Array", ScriptFunction.class); 35.227 - this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray", ScriptFunction.class); 35.228 - this.builtinInt16Array = initConstructor("Int16Array", ScriptFunction.class); 35.229 - this.builtinUint16Array = initConstructor("Uint16Array", ScriptFunction.class); 35.230 - this.builtinInt32Array = initConstructor("Int32Array", ScriptFunction.class); 35.231 - this.builtinUint32Array = initConstructor("Uint32Array", ScriptFunction.class); 35.232 - this.builtinFloat32Array = initConstructor("Float32Array", ScriptFunction.class); 35.233 - this.builtinFloat64Array = initConstructor("Float64Array", ScriptFunction.class); 35.234 + this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class); 35.235 + this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class); 35.236 + this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class); 35.237 + this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class); 35.238 + this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class); 35.239 + this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class); 35.240 + this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class); 35.241 + this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class); 35.242 + this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class); 35.243 + this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class); 35.244 + this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class); 35.245 + 35.246 } 35.247 35.248 private void copyBuiltins() { 35.249 @@ -1993,10 +2039,6 @@ 35.250 return UNDEFINED; 35.251 } 35.252 35.253 - /** 35.254 - * These classes are generated by nasgen tool and so we have to use 35.255 - * reflection to load and create new instance of these classes. 35.256 - */ 35.257 private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) { 35.258 try { 35.259 // Assuming class name pattern for built-in JS constructors. 35.260 @@ -2021,12 +2063,52 @@ 35.261 } 35.262 35.263 res.setIsBuiltin(); 35.264 + 35.265 return res; 35.266 } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) { 35.267 throw new RuntimeException(e); 35.268 } 35.269 } 35.270 35.271 + private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) { 35.272 + final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>(); 35.273 + 35.274 + list.addAll(Arrays.asList(func.getMap().getProperties())); 35.275 + 35.276 + if (func instanceof ScriptFunction) { 35.277 + final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func); 35.278 + if (proto != null) { 35.279 + list.addAll(Arrays.asList(proto.getMap().getProperties())); 35.280 + } 35.281 + } 35.282 + 35.283 + final jdk.nashorn.internal.runtime.Property prop = getProperty(name); 35.284 + if (prop != null) { 35.285 + list.add(prop); 35.286 + } 35.287 + 35.288 + return list; 35.289 + } 35.290 + 35.291 + /** 35.292 + * Given a builtin object, traverse its properties recursively and associate them with a name that 35.293 + * will be a key to their invalidation switchpoint. 35.294 + * @param name name for key 35.295 + * @param func builtin script object 35.296 + */ 35.297 + private void tagBuiltinProperties(final String name, final ScriptObject func) { 35.298 + SwitchPoint sp = context.getBuiltinSwitchPoint(name); 35.299 + if (sp == null) { 35.300 + sp = context.newBuiltinSwitchPoint(name); 35.301 + } 35.302 + 35.303 + //get all builtin properties in this builtin object and register switchpoints keyed on the propery name, 35.304 + //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc 35.305 + for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) { 35.306 + prop.setBuiltinSwitchPoint(sp); 35.307 + } 35.308 + } 35.309 + 35.310 // Function and Object constructors are inter-dependent. Also, 35.311 // Function.prototype 35.312 // functions are not properly initialized. We fix the references here. 35.313 @@ -2035,7 +2117,8 @@ 35.314 // to play with object references carefully!! 35.315 private void initFunctionAndObject() { 35.316 // First-n-foremost is Function 35.317 - this.builtinFunction = initConstructor("Function", ScriptFunction.class); 35.318 + 35.319 + this.builtinFunction = initConstructor("Function", ScriptFunction.class); 35.320 35.321 // create global anonymous function 35.322 final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(); 35.323 @@ -2101,13 +2184,6 @@ 35.324 } 35.325 } 35.326 35.327 - //make sure apply and call have the same invalidation switchpoint 35.328 - final SwitchPoint sp = new SwitchPoint(); 35.329 - optimisticFunctionMap.put("apply", sp); 35.330 - optimisticFunctionMap.put("call", sp); 35.331 - getFunctionPrototype().getProperty("apply").setChangeCallback(sp); 35.332 - getFunctionPrototype().getProperty("call").setChangeCallback(sp); 35.333 - 35.334 properties = getObjectPrototype().getMap().getProperties(); 35.335 35.336 for (final jdk.nashorn.internal.runtime.Property property : properties) { 35.337 @@ -2125,10 +2201,10 @@ 35.338 } 35.339 } 35.340 } 35.341 - } 35.342 35.343 - private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) { 35.344 - return MH.findVirtual(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types)); 35.345 + tagBuiltinProperties("Object", builtinObject); 35.346 + tagBuiltinProperties("Function", builtinFunction); 35.347 + tagBuiltinProperties("Function", anon); 35.348 } 35.349 35.350 private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) { 35.351 @@ -2147,62 +2223,4 @@ 35.352 protected boolean isGlobal() { 35.353 return true; 35.354 } 35.355 - 35.356 - /** 35.357 - * Check if there is a switchpoint for a reserved name. If there 35.358 - * is, it must be invalidated upon properties with this name 35.359 - * @param name property name 35.360 - * @return switchpoint for invalidating this property, or null if not registered 35.361 - */ 35.362 - public SwitchPoint getChangeCallback(final String name) { 35.363 - return optimisticFunctionMap.get(name); 35.364 - } 35.365 - 35.366 - /** 35.367 - * Is this a special name, that might be subject to invalidation 35.368 - * on write, such as "apply" or "call" 35.369 - * @param name name to check 35.370 - * @return true if special name 35.371 - */ 35.372 - public boolean isSpecialName(final String name) { 35.373 - return getChangeCallback(name) != null; 35.374 - } 35.375 - 35.376 - /** 35.377 - * Check if a reserved property name is invalidated 35.378 - * @param name property name 35.379 - * @return true if someone has written to it since Global was instantiated 35.380 - */ 35.381 - public boolean isSpecialNameValid(final String name) { 35.382 - final SwitchPoint sp = getChangeCallback(name); 35.383 - return sp != null && !sp.hasBeenInvalidated(); 35.384 - } 35.385 - 35.386 - /** 35.387 - * Tag a reserved name as invalidated - used when someone writes 35.388 - * to a property with this name - overly conservative, but link time 35.389 - * is too late to apply e.g. apply->call specialization 35.390 - * @param name property name 35.391 - */ 35.392 - public void invalidateReservedName(final String name) { 35.393 - final SwitchPoint sp = getChangeCallback(name); 35.394 - if (sp != null) { 35.395 - getContext().getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint"); 35.396 - SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 35.397 - } 35.398 - } 35.399 - 35.400 - /** 35.401 - * Bootstrapper for invalidating a builtin name 35.402 - * @param lookup lookup 35.403 - * @param name name to invalidate 35.404 - * @param type methodhandle type 35.405 - * @return callsite for invalidator 35.406 - */ 35.407 - public static CallSite invalidateNameBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type) { 35.408 - final MethodHandle target = MH.insertArguments(Global.instance().INVALIDATE_RESERVED_NAME, 0, name); 35.409 - return new ConstantCallSite(target); 35.410 - } 35.411 - 35.412 - 35.413 }
36.1 --- a/src/jdk/nashorn/internal/objects/NativeArray.java Wed Oct 08 14:16:54 2014 -0700 36.2 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java Tue Oct 14 10:20:24 2014 -0700 36.3 @@ -1,5 +1,5 @@ 36.4 /* 36.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 36.6 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 36.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 36.8 * 36.9 * This code is free software; you can redistribute it and/or modify it 36.10 @@ -33,8 +33,8 @@ 36.11 import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator; 36.12 import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator; 36.13 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT; 36.14 - 36.15 import java.lang.invoke.MethodHandle; 36.16 +import java.lang.invoke.SwitchPoint; 36.17 import java.util.ArrayList; 36.18 import java.util.Arrays; 36.19 import java.util.Collections; 36.20 @@ -52,12 +52,13 @@ 36.21 import jdk.nashorn.internal.objects.annotations.Getter; 36.22 import jdk.nashorn.internal.objects.annotations.ScriptClass; 36.23 import jdk.nashorn.internal.objects.annotations.Setter; 36.24 -import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; 36.25 import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 36.26 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 36.27 import jdk.nashorn.internal.objects.annotations.Where; 36.28 import jdk.nashorn.internal.runtime.Context; 36.29 import jdk.nashorn.internal.runtime.Debug; 36.30 import jdk.nashorn.internal.runtime.JSType; 36.31 +import jdk.nashorn.internal.runtime.OptimisticBuiltins; 36.32 import jdk.nashorn.internal.runtime.PropertyDescriptor; 36.33 import jdk.nashorn.internal.runtime.PropertyMap; 36.34 import jdk.nashorn.internal.runtime.ScriptFunction; 36.35 @@ -67,17 +68,20 @@ 36.36 import jdk.nashorn.internal.runtime.arrays.ArrayData; 36.37 import jdk.nashorn.internal.runtime.arrays.ArrayIndex; 36.38 import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator; 36.39 +import jdk.nashorn.internal.runtime.arrays.ContinuousArrayData; 36.40 +import jdk.nashorn.internal.runtime.arrays.IntElements; 36.41 +import jdk.nashorn.internal.runtime.arrays.IntOrLongElements; 36.42 import jdk.nashorn.internal.runtime.arrays.IteratorAction; 36.43 +import jdk.nashorn.internal.runtime.arrays.NumericElements; 36.44 import jdk.nashorn.internal.runtime.linker.Bootstrap; 36.45 import jdk.nashorn.internal.runtime.linker.InvokeByName; 36.46 -import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; 36.47 36.48 /** 36.49 * Runtime representation of a JavaScript array. NativeArray only holds numeric 36.50 * keyed values. All other values are stored in spill. 36.51 */ 36.52 @ScriptClass("Array") 36.53 -public final class NativeArray extends ScriptObject { 36.54 +public final class NativeArray extends ScriptObject implements OptimisticBuiltins { 36.55 private static final Object JOIN = new Object(); 36.56 private static final Object EVERY_CALLBACK_INVOKER = new Object(); 36.57 private static final Object SOME_CALLBACK_INVOKER = new Object(); 36.58 @@ -88,6 +92,16 @@ 36.59 private static final Object CALL_CMP = new Object(); 36.60 private static final Object TO_LOCALE_STRING = new Object(); 36.61 36.62 + private SwitchPoint lengthMadeNotWritableSwitchPoint; 36.63 + private PushLinkLogic pushLinkLogic; 36.64 + private PopLinkLogic popLinkLogic; 36.65 + 36.66 + /** 36.67 + * Index for the modification SwitchPoint that triggers when length 36.68 + * becomes not writable 36.69 + */ 36.70 + private static final int LENGTH_NOT_WRITABLE_SWITCHPOINT = 0; 36.71 + 36.72 /* 36.73 * Constructors. 36.74 */ 36.75 @@ -420,6 +434,28 @@ 36.76 return getArray().asObjectArray(); 36.77 } 36.78 36.79 + @Override 36.80 + public void setIsLengthNotWritable() { 36.81 + super.setIsLengthNotWritable(); 36.82 + /* 36.83 + * Switchpoints are created lazily. If we link any push or pop site, 36.84 + * we need to create the "length made not writable" switchpoint, if it 36.85 + * doesn't exist. 36.86 + * 36.87 + * If the switchpoint already exists, we will find it here, and invalidate 36.88 + * it, invalidating all previous callsites that use it. 36.89 + * 36.90 + * If the switchpoint doesn't exist, no push/pop has been linked so far, 36.91 + * because that would create it too. We invalidate it immediately and the 36.92 + * check link logic for all future callsites will fail immediately at link 36.93 + * time 36.94 + */ 36.95 + if (lengthMadeNotWritableSwitchPoint == null) { 36.96 + lengthMadeNotWritableSwitchPoint = new SwitchPoint(); 36.97 + } 36.98 + SwitchPoint.invalidateAll(new SwitchPoint[] { lengthMadeNotWritableSwitchPoint }); 36.99 + } 36.100 + 36.101 /** 36.102 * ECMA 15.4.3.2 Array.isArray ( arg ) 36.103 * 36.104 @@ -638,7 +674,7 @@ 36.105 * @param self self reference 36.106 * @return the new NativeArray 36.107 */ 36.108 - @SpecializedConstructor 36.109 + @SpecializedFunction(isConstructor=true) 36.110 public static NativeArray construct(final boolean newObj, final Object self) { 36.111 return new NativeArray(0); 36.112 } 36.113 @@ -653,7 +689,7 @@ 36.114 * @param element first element 36.115 * @return the new NativeArray 36.116 */ 36.117 - @SpecializedConstructor 36.118 + @SpecializedFunction(isConstructor=true) 36.119 public static Object construct(final boolean newObj, final Object self, final boolean element) { 36.120 return new NativeArray(new Object[] { element }); 36.121 } 36.122 @@ -668,7 +704,7 @@ 36.123 * @param length array length 36.124 * @return the new NativeArray 36.125 */ 36.126 - @SpecializedConstructor 36.127 + @SpecializedFunction(isConstructor=true) 36.128 public static NativeArray construct(final boolean newObj, final Object self, final int length) { 36.129 if (length >= 0) { 36.130 return new NativeArray(length); 36.131 @@ -687,7 +723,7 @@ 36.132 * @param length array length 36.133 * @return the new NativeArray 36.134 */ 36.135 - @SpecializedConstructor 36.136 + @SpecializedFunction(isConstructor=true) 36.137 public static NativeArray construct(final boolean newObj, final Object self, final long length) { 36.138 if (length >= 0L && length <= JSType.MAX_UINT) { 36.139 return new NativeArray(length); 36.140 @@ -706,7 +742,7 @@ 36.141 * @param length array length 36.142 * @return the new NativeArray 36.143 */ 36.144 - @SpecializedConstructor 36.145 + @SpecializedFunction(isConstructor=true) 36.146 public static NativeArray construct(final boolean newObj, final Object self, final double length) { 36.147 final long uint32length = JSType.toUint32(length); 36.148 36.149 @@ -721,7 +757,7 @@ 36.150 * ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] ) 36.151 * 36.152 * @param self self reference 36.153 - * @param args arguments to concat 36.154 + * @param args arguments 36.155 * @return resulting NativeArray 36.156 */ 36.157 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) 36.158 @@ -793,6 +829,68 @@ 36.159 } 36.160 36.161 /** 36.162 + * Specialization of pop for ContinuousArrayData 36.163 + * The link guard checks that the array is continuous AND not empty. 36.164 + * The runtime guard checks that the guard is continuous (CCE otherwise) 36.165 + * 36.166 + * Primitive specialization, {@link LinkLogic} 36.167 + * 36.168 + * @param self self reference 36.169 + * @return element popped 36.170 + * @throws ClassCastException if array is empty, facilitating Undefined return value 36.171 + */ 36.172 + @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class) 36.173 + public static int popInt(final Object self) { 36.174 + //must be non empty IntArrayData 36.175 + return getContinuousNonEmptyArrayDataCCE(self, IntElements.class).fastPopInt(); 36.176 + } 36.177 + 36.178 + /** 36.179 + * Specialization of pop for ContinuousArrayData 36.180 + * 36.181 + * Primitive specialization, {@link LinkLogic} 36.182 + * 36.183 + * @param self self reference 36.184 + * @return element popped 36.185 + * @throws ClassCastException if array is empty, facilitating Undefined return value 36.186 + */ 36.187 + @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class) 36.188 + public static long popLong(final Object self) { 36.189 + //must be non empty Int or LongArrayData 36.190 + return getContinuousNonEmptyArrayDataCCE(self, IntOrLongElements.class).fastPopLong(); 36.191 + } 36.192 + 36.193 + /** 36.194 + * Specialization of pop for ContinuousArrayData 36.195 + * 36.196 + * Primitive specialization, {@link LinkLogic} 36.197 + * 36.198 + * @param self self reference 36.199 + * @return element popped 36.200 + * @throws ClassCastException if array is empty, facilitating Undefined return value 36.201 + */ 36.202 + @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class) 36.203 + public static double popDouble(final Object self) { 36.204 + //must be non empty int long or double array data 36.205 + return getContinuousNonEmptyArrayDataCCE(self, NumericElements.class).fastPopDouble(); 36.206 + } 36.207 + 36.208 + /** 36.209 + * Specialization of pop for ContinuousArrayData 36.210 + * 36.211 + * Primitive specialization, {@link LinkLogic} 36.212 + * 36.213 + * @param self self reference 36.214 + * @return element popped 36.215 + * @throws ClassCastException if array is empty, facilitating Undefined return value 36.216 + */ 36.217 + @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class) 36.218 + public static Object popObject(final Object self) { 36.219 + //can be any data, because the numeric ones will throw cce and force relink 36.220 + return getContinuousArrayDataCCE(self, null).fastPopObject(); 36.221 + } 36.222 + 36.223 + /** 36.224 * ECMA 15.4.4.6 Array.prototype.pop () 36.225 * 36.226 * @param self self reference 36.227 @@ -829,6 +927,62 @@ 36.228 /** 36.229 * ECMA 15.4.4.7 Array.prototype.push (args...) 36.230 * 36.231 + * Primitive specialization, {@link LinkLogic} 36.232 + * 36.233 + * @param self self reference 36.234 + * @param arg a primitive to push 36.235 + * @return array length after push 36.236 + */ 36.237 + @SpecializedFunction(linkLogic=PushLinkLogic.class) 36.238 + public static long push(final Object self, final int arg) { 36.239 + return getContinuousArrayDataCCE(self, Integer.class).fastPush(arg); 36.240 + } 36.241 + 36.242 + /** 36.243 + * ECMA 15.4.4.7 Array.prototype.push (args...) 36.244 + * 36.245 + * Primitive specialization, {@link LinkLogic} 36.246 + * 36.247 + * @param self self reference 36.248 + * @param arg a primitive to push 36.249 + * @return array length after push 36.250 + */ 36.251 + @SpecializedFunction(linkLogic=PushLinkLogic.class) 36.252 + public static long push(final Object self, final long arg) { 36.253 + return getContinuousArrayDataCCE(self, Long.class).fastPush(arg); 36.254 + } 36.255 + 36.256 + /** 36.257 + * ECMA 15.4.4.7 Array.prototype.push (args...) 36.258 + * 36.259 + * Primitive specialization, {@link LinkLogic} 36.260 + * 36.261 + * @param self self reference 36.262 + * @param arg a primitive to push 36.263 + * @return array length after push 36.264 + */ 36.265 + @SpecializedFunction(linkLogic=PushLinkLogic.class) 36.266 + public static long push(final Object self, final double arg) { 36.267 + return getContinuousArrayDataCCE(self, Double.class).fastPush(arg); 36.268 + } 36.269 + 36.270 + /** 36.271 + * ECMA 15.4.4.7 Array.prototype.push (args...) 36.272 + * 36.273 + * Primitive specialization, {@link LinkLogic} 36.274 + * 36.275 + * @param self self reference 36.276 + * @param arg a primitive to push 36.277 + * @return array length after push 36.278 + */ 36.279 + @SpecializedFunction(name="push", linkLogic=PushLinkLogic.class) 36.280 + public static long pushObject(final Object self, final Object arg) { 36.281 + return getContinuousArrayDataCCE(self, Object.class).fastPush(arg); 36.282 + } 36.283 + 36.284 + /** 36.285 + * ECMA 15.4.4.7 Array.prototype.push (args...) 36.286 + * 36.287 * @param self self reference 36.288 * @param args arguments to push 36.289 * @return array length after pushes 36.290 @@ -857,61 +1011,6 @@ 36.291 } 36.292 36.293 /** 36.294 - * ECMA 15.4.4.7 Array.prototype.push (args...) specialized for single int argument 36.295 - * 36.296 - * @param self self reference 36.297 - * @param arg argument to push 36.298 - * @return array after pushes 36.299 - */ 36.300 -/* @SpecializedFunction 36.301 - public static long push(final Object self, final int arg) { 36.302 - try { 36.303 - final ScriptObject sobj = (ScriptObject)self; 36.304 - final ArrayData arrayData = sobj.getArray(); 36.305 - final long length = arrayData.length(); 36.306 - 36.307 - if (bulkable(sobj) && length + 1 <= JSType.MAX_UINT) { 36.308 - sobj.setArray(arrayData.ensure(length).set(ArrayIndex.getArrayIndex(length), arg, true)); 36.309 - return length + 1; 36.310 - } 36.311 - 36.312 - long len = JSType.toUint32(sobj.getLength()); 36.313 - sobj.set(len++, arg, true); 36.314 - sobj.set("length", len, true); 36.315 - return len; 36.316 - } catch (final ClassCastException | NullPointerException e) { 36.317 - throw typeError("not.an.object", ScriptRuntime.safeToString(self)); 36.318 - } 36.319 - } 36.320 -*/ 36.321 - /** 36.322 - * ECMA 15.4.4.7 Array.prototype.push (args...) specialized for single number argument 36.323 - * 36.324 - * @param self self reference 36.325 - * @param arg argument to push 36.326 - * @return array after pushes 36.327 - */ 36.328 - /* @SpecializedFunction 36.329 - public static long push(final Object self, final double arg) { 36.330 - try { 36.331 - final ScriptObject sobj = (ScriptObject)self; final ArrayData arrayData = sobj.getArray(); 36.332 - final long length = arrayData.length(); 36.333 - 36.334 - if (bulkable(sobj) && length + 1 <= JSType.MAX_UINT) { 36.335 - sobj.setArray(arrayData.ensure(length).set(ArrayIndex.getArrayIndex(length), arg, true)); 36.336 - return length + 1; 36.337 - } 36.338 - 36.339 - long len = JSType.toUint32(sobj.getLength()); 36.340 - sobj.set(len++, arg, true); 36.341 - sobj.set("length", len, true); 36.342 - return len; 36.343 - } catch (final ClassCastException | NullPointerException e) { 36.344 - throw typeError("not.an.object", ScriptRuntime.safeToString(self)); 36.345 - } 36.346 - } 36.347 -*/ 36.348 - /** 36.349 * ECMA 15.4.4.7 Array.prototype.push (args...) specialized for single object argument 36.350 * 36.351 * @param self self reference 36.352 @@ -925,7 +1024,7 @@ 36.353 final ArrayData arrayData = sobj.getArray(); 36.354 final long length = arrayData.length(); 36.355 if (bulkable(sobj) && length < JSType.MAX_UINT) { 36.356 - sobj.setArray(arrayData.push(true, arg)); //ensure(length).set(ArrayIndex.getArrayIndex(length), arg, true)); 36.357 + sobj.setArray(arrayData.push(true, arg)); 36.358 return length + 1; 36.359 } 36.360 36.361 @@ -1584,6 +1683,192 @@ 36.362 36.363 @Override 36.364 public String toString() { 36.365 - return "NativeArray@" + Debug.id(this) + '@' + getArray().getClass().getSimpleName(); 36.366 + return "NativeArray@" + Debug.id(this) + " [" + getArray().getClass().getSimpleName() + ']'; 36.367 + } 36.368 + 36.369 + @Override 36.370 + public SpecializedFunction.LinkLogic getLinkLogic(final Class<? extends LinkLogic> clazz) { 36.371 + if (clazz == PushLinkLogic.class) { 36.372 + return pushLinkLogic == null ? new PushLinkLogic(this) : pushLinkLogic; 36.373 + } else if (clazz == PopLinkLogic.class) { 36.374 + return popLinkLogic == null ? new PopLinkLogic(this) : pushLinkLogic; 36.375 + } 36.376 + return null; 36.377 + } 36.378 + 36.379 + @Override 36.380 + public boolean hasPerInstanceAssumptions() { 36.381 + return true; //length switchpoint 36.382 + } 36.383 + 36.384 + /** 36.385 + * This is an abstract super class that contains common functionality for all 36.386 + * specialized optimistic builtins in NativeArray. For example, it handles the 36.387 + * modification switchpoint which is touched when length is written. 36.388 + */ 36.389 + private static abstract class ArrayLinkLogic extends SpecializedFunction.LinkLogic { 36.390 + private final NativeArray array; 36.391 + 36.392 + protected ArrayLinkLogic(final NativeArray array) { 36.393 + this.array = array; 36.394 + } 36.395 + 36.396 + private SwitchPoint getSwitchPoint() { 36.397 + return array.lengthMadeNotWritableSwitchPoint; 36.398 + } 36.399 + 36.400 + private SwitchPoint newSwitchPoint() { 36.401 + assert array.lengthMadeNotWritableSwitchPoint == null; 36.402 + final SwitchPoint sp = new SwitchPoint(); 36.403 + array.lengthMadeNotWritableSwitchPoint = sp; 36.404 + return sp; 36.405 + } 36.406 + 36.407 + protected static ContinuousArrayData getContinuousArrayData(final Object self) { 36.408 + try { 36.409 + //cast to NativeArray, to avoid cases like x = {0:0, 1:1}, x.length = 2, where we can't use the array push/pop 36.410 + return (ContinuousArrayData)((NativeArray)self).getArray(); 36.411 + } catch (final Exception e) { 36.412 + return null; 36.413 + } 36.414 + } 36.415 + 36.416 + /** 36.417 + * Push and pop callsites can throw ClassCastException as a mechanism to have them 36.418 + * relinked - this enabled fast checks of the kind of ((IntArrayData)arrayData).push(x) 36.419 + * for an IntArrayData only push - if this fails, a CCE will be thrown and we will relink 36.420 + */ 36.421 + @Override 36.422 + public Class<? extends Throwable> getRelinkException() { 36.423 + return ClassCastException.class; 36.424 + } 36.425 + 36.426 + @Override 36.427 + public boolean hasModificationSwitchPoints() { 36.428 + return getSwitchPoint() != null; 36.429 + } 36.430 + 36.431 + @Override 36.432 + public boolean hasModificationSwitchPoint(final int index) { 36.433 + assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT; 36.434 + return hasModificationSwitchPoints(); 36.435 + } 36.436 + 36.437 + @Override 36.438 + public SwitchPoint getOrCreateModificationSwitchPoint(final int index) { 36.439 + assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT; 36.440 + SwitchPoint sp = getSwitchPoint(); 36.441 + if (sp == null) { 36.442 + sp = newSwitchPoint(); 36.443 + } 36.444 + return sp; 36.445 + } 36.446 + 36.447 + @Override 36.448 + public SwitchPoint[] getOrCreateModificationSwitchPoints() { 36.449 + return new SwitchPoint[] { getOrCreateModificationSwitchPoint(LENGTH_NOT_WRITABLE_SWITCHPOINT) }; 36.450 + } 36.451 + 36.452 + @Override 36.453 + public void invalidateModificationSwitchPoint(final int index) { 36.454 + assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT; 36.455 + invalidateModificationSwitchPoints(); 36.456 + } 36.457 + 36.458 + @Override 36.459 + public void invalidateModificationSwitchPoints() { 36.460 + final SwitchPoint sp = getSwitchPoint(); 36.461 + assert sp != null : "trying to invalidate non-existant modified SwitchPoint"; 36.462 + if (!sp.hasBeenInvalidated()) { 36.463 + SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 36.464 + } 36.465 + } 36.466 + 36.467 + @Override 36.468 + public boolean hasInvalidatedModificationSwitchPoint(final int index) { 36.469 + assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT; 36.470 + return hasInvalidatedModificationSwitchPoints(); 36.471 + } 36.472 + 36.473 + @Override 36.474 + public boolean hasInvalidatedModificationSwitchPoints() { 36.475 + final SwitchPoint sp = getSwitchPoint(); 36.476 + return sp != null && !sp.hasBeenInvalidated(); 36.477 + } 36.478 + } 36.479 + 36.480 + /** 36.481 + * This is linker logic for optimistic pushes 36.482 + */ 36.483 + private static final class PushLinkLogic extends ArrayLinkLogic { 36.484 + private PushLinkLogic(final NativeArray array) { 36.485 + super(array); 36.486 + } 36.487 + 36.488 + @Override 36.489 + public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { 36.490 + return getContinuousArrayData(self) != null; 36.491 + } 36.492 + } 36.493 + 36.494 + /** 36.495 + * This is linker logic for optimistic pops 36.496 + */ 36.497 + private static final class PopLinkLogic extends ArrayLinkLogic { 36.498 + private PopLinkLogic(final NativeArray array) { 36.499 + super(array); 36.500 + } 36.501 + 36.502 + /** 36.503 + * We need to check if we are dealing with a continuous non empty array data here, 36.504 + * as pop with a primitive return value returns undefined for arrays with length 0 36.505 + */ 36.506 + @Override 36.507 + public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { 36.508 + final ContinuousArrayData data = getContinuousNonEmptyArrayData(self); 36.509 + if (data != null) { 36.510 + final Class<?> elementType = data.getElementType(); 36.511 + final Class<?> returnType = desc.getMethodType().returnType(); 36.512 + final boolean typeFits = JSType.getAccessorTypeIndex(returnType) >= JSType.getAccessorTypeIndex(elementType); 36.513 + return typeFits; 36.514 + } 36.515 + return false; 36.516 + } 36.517 + 36.518 + private static ContinuousArrayData getContinuousNonEmptyArrayData(final Object self) { 36.519 + final ContinuousArrayData data = getContinuousArrayData(self); 36.520 + if (data != null) { 36.521 + return data.length() == 0 ? null : data; 36.522 + } 36.523 + return null; 36.524 + } 36.525 + } 36.526 + 36.527 + //runtime calls for push and pops. they could be used as guards, but they also perform the runtime logic, 36.528 + //so rather than synthesizing them into a guard method handle that would also perform the push on the 36.529 + //retrieved receiver, we use this as runtime logic 36.530 + 36.531 + //TODO - fold these into the Link logics, but I'll do that as a later step, as I want to do a checkin 36.532 + //where everything works first 36.533 + 36.534 + private static final <T> ContinuousArrayData getContinuousNonEmptyArrayDataCCE(final Object self, final Class<T> clazz) { 36.535 + try { 36.536 + @SuppressWarnings("unchecked") 36.537 + final ContinuousArrayData data = (ContinuousArrayData)(T)((NativeArray)self).getArray(); 36.538 + if (data.length() != 0L) { 36.539 + return data; //if length is 0 we cannot pop and have to relink, because then we'd have to return an undefined, which is a wider type than e.g. int 36.540 + } 36.541 + } catch (final NullPointerException e) { 36.542 + //fallthru 36.543 + } 36.544 + throw new ClassCastException(); 36.545 + } 36.546 + 36.547 + private static final ContinuousArrayData getContinuousArrayDataCCE(final Object self, final Class<?> elementType) { 36.548 + try { 36.549 + return (ContinuousArrayData)((NativeArray)self).getArray(elementType); //ensure element type can fit "elementType" 36.550 + } catch (final NullPointerException e) { 36.551 + throw new ClassCastException(); 36.552 + } 36.553 } 36.554 }
37.1 --- a/src/jdk/nashorn/internal/objects/NativeDataView.java Wed Oct 08 14:16:54 2014 -0700 37.2 +++ b/src/jdk/nashorn/internal/objects/NativeDataView.java Tue Oct 14 10:20:24 2014 -0700 37.3 @@ -27,7 +27,6 @@ 37.4 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError; 37.5 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 37.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 37.7 - 37.8 import java.nio.ByteBuffer; 37.9 import java.nio.ByteOrder; 37.10 import jdk.nashorn.internal.objects.annotations.Attribute; 37.11 @@ -35,7 +34,6 @@ 37.12 import jdk.nashorn.internal.objects.annotations.Function; 37.13 import jdk.nashorn.internal.objects.annotations.Property; 37.14 import jdk.nashorn.internal.objects.annotations.ScriptClass; 37.15 -import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; 37.16 import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 37.17 import jdk.nashorn.internal.runtime.JSType; 37.18 import jdk.nashorn.internal.runtime.PropertyMap; 37.19 @@ -156,7 +154,7 @@ 37.20 * @param offset offset in bytes from the start of the ArrayBuffer 37.21 * @return newly constructed DataView object 37.22 */ 37.23 - @SpecializedConstructor 37.24 + @SpecializedFunction(isConstructor=true) 37.25 public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset) { 37.26 if (!(arrBuf instanceof NativeArrayBuffer)) { 37.27 throw typeError("not.an.arraybuffer.in.dataview"); 37.28 @@ -174,7 +172,7 @@ 37.29 * @param length is the number of bytes from the offset that this DataView will reference 37.30 * @return newly constructed DataView object 37.31 */ 37.32 - @SpecializedConstructor 37.33 + @SpecializedFunction(isConstructor=true) 37.34 public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset, final int length) { 37.35 if (!(arrBuf instanceof NativeArrayBuffer)) { 37.36 throw typeError("not.an.arraybuffer.in.dataview");
38.1 --- a/src/jdk/nashorn/internal/objects/NativeDate.java Wed Oct 08 14:16:54 2014 -0700 38.2 +++ b/src/jdk/nashorn/internal/objects/NativeDate.java Tue Oct 14 10:20:24 2014 -0700 38.3 @@ -30,7 +30,6 @@ 38.4 import static java.lang.Double.isNaN; 38.5 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError; 38.6 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 38.7 - 38.8 import java.util.Locale; 38.9 import java.util.TimeZone; 38.10 import java.util.concurrent.Callable; 38.11 @@ -38,7 +37,7 @@ 38.12 import jdk.nashorn.internal.objects.annotations.Constructor; 38.13 import jdk.nashorn.internal.objects.annotations.Function; 38.14 import jdk.nashorn.internal.objects.annotations.ScriptClass; 38.15 -import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; 38.16 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 38.17 import jdk.nashorn.internal.objects.annotations.Where; 38.18 import jdk.nashorn.internal.parser.DateParser; 38.19 import jdk.nashorn.internal.runtime.ConsString; 38.20 @@ -155,7 +154,7 @@ 38.21 * @param self self references 38.22 * @return Date representing now 38.23 */ 38.24 - @SpecializedConstructor 38.25 + @SpecializedFunction(isConstructor=true) 38.26 public static Object construct(final boolean isNew, final Object self) { 38.27 final NativeDate result = new NativeDate(); 38.28 return isNew ? result : toStringImpl(result, FORMAT_DATE_TIME);
39.1 --- a/src/jdk/nashorn/internal/objects/NativeDebug.java Wed Oct 08 14:16:54 2014 -0700 39.2 +++ b/src/jdk/nashorn/internal/objects/NativeDebug.java Tue Oct 14 10:20:24 2014 -0700 39.3 @@ -26,7 +26,6 @@ 39.4 package jdk.nashorn.internal.objects; 39.5 39.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 39.7 - 39.8 import java.io.PrintWriter; 39.9 import java.util.LinkedList; 39.10 import java.util.Objects; 39.11 @@ -262,8 +261,8 @@ 39.12 39.13 /** 39.14 * Set the event queue capacity 39.15 - * @param self 39.16 - * @param newCapacity 39.17 + * @param self an event queue 39.18 + * @param newCapacity new capacity 39.19 */ 39.20 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 39.21 public static void setEventQueueCapacity(final Object self, final Object newCapacity) {
40.1 --- a/src/jdk/nashorn/internal/objects/NativeFloat32Array.java Wed Oct 08 14:16:54 2014 -0700 40.2 +++ b/src/jdk/nashorn/internal/objects/NativeFloat32Array.java Tue Oct 14 10:20:24 2014 -0700 40.3 @@ -26,7 +26,6 @@ 40.4 package jdk.nashorn.internal.objects; 40.5 40.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 40.7 - 40.8 import java.lang.invoke.MethodHandle; 40.9 import java.lang.invoke.MethodHandles; 40.10 import java.nio.ByteBuffer; 40.11 @@ -85,6 +84,11 @@ 40.12 } 40.13 40.14 @Override 40.15 + public Class<?> getElementType() { 40.16 + return double.class; 40.17 + } 40.18 + 40.19 + @Override 40.20 protected MethodHandle getGetElem() { 40.21 return GET_ELEM; 40.22 }
41.1 --- a/src/jdk/nashorn/internal/objects/NativeFloat64Array.java Wed Oct 08 14:16:54 2014 -0700 41.2 +++ b/src/jdk/nashorn/internal/objects/NativeFloat64Array.java Tue Oct 14 10:20:24 2014 -0700 41.3 @@ -26,7 +26,6 @@ 41.4 package jdk.nashorn.internal.objects; 41.5 41.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 41.7 - 41.8 import java.lang.invoke.MethodHandle; 41.9 import java.lang.invoke.MethodHandles; 41.10 import java.nio.ByteBuffer; 41.11 @@ -94,6 +93,11 @@ 41.12 return SET_ELEM; 41.13 } 41.14 41.15 + @Override 41.16 + public Class<?> getElementType() { 41.17 + return double.class; 41.18 + } 41.19 + 41.20 private double getElem(final int index) { 41.21 try { 41.22 return nb.get(index);
42.1 --- a/src/jdk/nashorn/internal/objects/NativeInt16Array.java Wed Oct 08 14:16:54 2014 -0700 42.2 +++ b/src/jdk/nashorn/internal/objects/NativeInt16Array.java Tue Oct 14 10:20:24 2014 -0700 42.3 @@ -26,7 +26,6 @@ 42.4 package jdk.nashorn.internal.objects; 42.5 42.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 42.7 - 42.8 import java.lang.invoke.MethodHandle; 42.9 import java.lang.invoke.MethodHandles; 42.10 import java.nio.ByteBuffer; 42.11 @@ -95,6 +94,11 @@ 42.12 return SET_ELEM; 42.13 } 42.14 42.15 + @Override 42.16 + public Class<?> getElementType() { 42.17 + return int.class; 42.18 + } 42.19 + 42.20 private int getElem(final int index) { 42.21 try { 42.22 return nb.get(index);
43.1 --- a/src/jdk/nashorn/internal/objects/NativeInt32Array.java Wed Oct 08 14:16:54 2014 -0700 43.2 +++ b/src/jdk/nashorn/internal/objects/NativeInt32Array.java Tue Oct 14 10:20:24 2014 -0700 43.3 @@ -26,7 +26,6 @@ 43.4 package jdk.nashorn.internal.objects; 43.5 43.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 43.7 - 43.8 import java.lang.invoke.MethodHandle; 43.9 import java.lang.invoke.MethodHandles; 43.10 import java.nio.ByteBuffer; 43.11 @@ -113,6 +112,11 @@ 43.12 } 43.13 43.14 @Override 43.15 + public Class<?> getElementType() { 43.16 + return int.class; 43.17 + } 43.18 + 43.19 + @Override 43.20 public int getInt(final int index) { 43.21 return getElem(index); 43.22 }
44.1 --- a/src/jdk/nashorn/internal/objects/NativeInt8Array.java Wed Oct 08 14:16:54 2014 -0700 44.2 +++ b/src/jdk/nashorn/internal/objects/NativeInt8Array.java Tue Oct 14 10:20:24 2014 -0700 44.3 @@ -26,7 +26,6 @@ 44.4 package jdk.nashorn.internal.objects; 44.5 44.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 44.7 - 44.8 import java.lang.invoke.MethodHandle; 44.9 import java.lang.invoke.MethodHandles; 44.10 import java.nio.ByteBuffer; 44.11 @@ -93,6 +92,11 @@ 44.12 return SET_ELEM; 44.13 } 44.14 44.15 + @Override 44.16 + public Class<?> getElementType() { 44.17 + return int.class; 44.18 + } 44.19 + 44.20 private int getElem(final int index) { 44.21 try { 44.22 return nb.get(index);
45.1 --- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Wed Oct 08 14:16:54 2014 -0700 45.2 +++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Tue Oct 14 10:20:24 2014 -0700 45.3 @@ -48,7 +48,6 @@ 45.4 import jdk.nashorn.internal.runtime.ScriptFunction; 45.5 import jdk.nashorn.internal.runtime.ScriptObject; 45.6 import jdk.nashorn.internal.runtime.ScriptRuntime; 45.7 -import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; 45.8 import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator; 45.9 import jdk.nashorn.internal.scripts.JO; 45.10
46.1 --- a/src/jdk/nashorn/internal/objects/NativeRegExp.java Wed Oct 08 14:16:54 2014 -0700 46.2 +++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java Tue Oct 14 10:20:24 2014 -0700 46.3 @@ -33,13 +33,14 @@ 46.4 import java.util.Arrays; 46.5 import java.util.List; 46.6 import java.util.concurrent.Callable; 46.7 + 46.8 import jdk.nashorn.internal.objects.annotations.Attribute; 46.9 import jdk.nashorn.internal.objects.annotations.Constructor; 46.10 import jdk.nashorn.internal.objects.annotations.Function; 46.11 import jdk.nashorn.internal.objects.annotations.Getter; 46.12 import jdk.nashorn.internal.objects.annotations.Property; 46.13 import jdk.nashorn.internal.objects.annotations.ScriptClass; 46.14 -import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; 46.15 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 46.16 import jdk.nashorn.internal.objects.annotations.Where; 46.17 import jdk.nashorn.internal.runtime.BitVector; 46.18 import jdk.nashorn.internal.runtime.JSType; 46.19 @@ -143,7 +144,7 @@ 46.20 * @param self self reference 46.21 * @return new NativeRegExp 46.22 */ 46.23 - @SpecializedConstructor 46.24 + @SpecializedFunction(isConstructor=true) 46.25 public static NativeRegExp constructor(final boolean isNew, final Object self) { 46.26 return new NativeRegExp("", ""); 46.27 } 46.28 @@ -158,7 +159,7 @@ 46.29 * @param pattern pattern 46.30 * @return new NativeRegExp 46.31 */ 46.32 - @SpecializedConstructor 46.33 + @SpecializedFunction(isConstructor=true) 46.34 public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern) { 46.35 return newRegExp(pattern, UNDEFINED); 46.36 } 46.37 @@ -174,7 +175,7 @@ 46.38 * @param flags flags 46.39 * @return new NativeRegExp 46.40 */ 46.41 - @SpecializedConstructor 46.42 + @SpecializedFunction(isConstructor=true) 46.43 public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern, final Object flags) { 46.44 return newRegExp(pattern, flags); 46.45 }
47.1 --- a/src/jdk/nashorn/internal/objects/NativeString.java Wed Oct 08 14:16:54 2014 -0700 47.2 +++ b/src/jdk/nashorn/internal/objects/NativeString.java Tue Oct 14 10:20:24 2014 -0700 47.3 @@ -29,7 +29,6 @@ 47.4 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 47.5 import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt; 47.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 47.7 - 47.8 import java.lang.invoke.MethodHandle; 47.9 import java.lang.invoke.MethodHandles; 47.10 import java.lang.invoke.MethodType; 47.11 @@ -49,11 +48,12 @@ 47.12 import jdk.nashorn.internal.objects.annotations.Function; 47.13 import jdk.nashorn.internal.objects.annotations.Getter; 47.14 import jdk.nashorn.internal.objects.annotations.ScriptClass; 47.15 -import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; 47.16 import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 47.17 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 47.18 import jdk.nashorn.internal.objects.annotations.Where; 47.19 import jdk.nashorn.internal.runtime.ConsString; 47.20 import jdk.nashorn.internal.runtime.JSType; 47.21 +import jdk.nashorn.internal.runtime.OptimisticBuiltins; 47.22 import jdk.nashorn.internal.runtime.PropertyMap; 47.23 import jdk.nashorn.internal.runtime.ScriptFunction; 47.24 import jdk.nashorn.internal.runtime.ScriptObject; 47.25 @@ -67,7 +67,7 @@ 47.26 * ECMA 15.5 String Objects. 47.27 */ 47.28 @ScriptClass("String") 47.29 -public final class NativeString extends ScriptObject { 47.30 +public final class NativeString extends ScriptObject implements OptimisticBuiltins { 47.31 47.32 private final CharSequence value; 47.33 47.34 @@ -568,6 +568,14 @@ 47.35 return pos < 0 || pos >= str.length() ? "" : String.valueOf(str.charAt(pos)); 47.36 } 47.37 47.38 + private static int getValidChar(final Object self, final int pos) { 47.39 + try { 47.40 + return ((CharSequence)self).charAt(pos); 47.41 + } catch (final IndexOutOfBoundsException e) { 47.42 + throw new ClassCastException(); 47.43 + } 47.44 + } 47.45 + 47.46 /** 47.47 * ECMA 15.5.4.5 String.prototype.charCodeAt (pos) 47.48 * @param self self reference 47.49 @@ -576,7 +584,9 @@ 47.50 */ 47.51 @Function(attributes = Attribute.NOT_ENUMERABLE) 47.52 public static double charCodeAt(final Object self, final Object pos) { 47.53 - return charCodeAtImpl(checkObjectToString(self), JSType.toInteger(pos)); 47.54 + final String str = checkObjectToString(self); 47.55 + final int idx = JSType.toInteger(pos); 47.56 + return idx < 0 || idx >= str.length() ? Double.NaN : str.charAt(idx); 47.57 } 47.58 47.59 /** 47.60 @@ -585,9 +595,20 @@ 47.61 * @param pos position in string 47.62 * @return number representing charcode at position 47.63 */ 47.64 - @SpecializedFunction 47.65 - public static double charCodeAt(final Object self, final double pos) { 47.66 - return charCodeAt(self, (int) pos); 47.67 + @SpecializedFunction(linkLogic=CharCodeAtLinkLogic.class) 47.68 + public static int charCodeAt(final Object self, final double pos) { 47.69 + return charCodeAt(self, (int)pos); //toInt pos is ok 47.70 + } 47.71 + 47.72 + /** 47.73 + * ECMA 15.5.4.5 String.prototype.charCodeAt (pos) - specialized version for long position 47.74 + * @param self self reference 47.75 + * @param pos position in string 47.76 + * @return number representing charcode at position 47.77 + */ 47.78 + @SpecializedFunction(linkLogic=CharCodeAtLinkLogic.class) 47.79 + public static int charCodeAt(final Object self, final long pos) { 47.80 + return charCodeAt(self, (int)pos); 47.81 } 47.82 47.83 /** 47.84 @@ -596,13 +617,10 @@ 47.85 * @param pos position in string 47.86 * @return number representing charcode at position 47.87 */ 47.88 - @SpecializedFunction 47.89 - public static double charCodeAt(final Object self, final int pos) { 47.90 - return charCodeAtImpl(checkObjectToString(self), pos); 47.91 - } 47.92 47.93 - private static double charCodeAtImpl(final String str, final int pos) { 47.94 - return pos < 0 || pos >= str.length() ? Double.NaN : str.charAt(pos); 47.95 + @SpecializedFunction(linkLogic=CharCodeAtLinkLogic.class) 47.96 + public static int charCodeAt(final Object self, final int pos) { 47.97 + return getValidChar(self, pos); 47.98 } 47.99 47.100 /** 47.101 @@ -1097,7 +1115,6 @@ 47.102 */ 47.103 @Function(attributes = Attribute.NOT_ENUMERABLE) 47.104 public static String trim(final Object self) { 47.105 - 47.106 final String str = checkObjectToString(self); 47.107 int start = 0; 47.108 int end = str.length() - 1; 47.109 @@ -1181,7 +1198,7 @@ 47.110 * 47.111 * @return new NativeString ("") 47.112 */ 47.113 - @SpecializedConstructor 47.114 + @SpecializedFunction(isConstructor=true) 47.115 public static Object constructor(final boolean newObj, final Object self) { 47.116 return newObj ? newObj("") : ""; 47.117 } 47.118 @@ -1197,7 +1214,7 @@ 47.119 * 47.120 * @return new NativeString (arg) 47.121 */ 47.122 - @SpecializedConstructor 47.123 + @SpecializedFunction(isConstructor=true) 47.124 public static Object constructor(final boolean newObj, final Object self, final Object arg) { 47.125 final CharSequence str = JSType.toCharSequence(arg); 47.126 return newObj ? newObj(str) : str.toString(); 47.127 @@ -1214,8 +1231,42 @@ 47.128 * 47.129 * @return new NativeString containing the string representation of the arg 47.130 */ 47.131 - @SpecializedConstructor 47.132 + @SpecializedFunction(isConstructor=true) 47.133 public static Object constructor(final boolean newObj, final Object self, final int arg) { 47.134 + final String str = Integer.toString(arg); 47.135 + return newObj ? newObj(str) : str; 47.136 + } 47.137 + 47.138 + /** 47.139 + * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code int} arg 47.140 + * 47.141 + * Constructor 47.142 + * 47.143 + * @param newObj is this constructor invoked with the new operator 47.144 + * @param self self reference 47.145 + * @param arg the arg 47.146 + * 47.147 + * @return new NativeString containing the string representation of the arg 47.148 + */ 47.149 + @SpecializedFunction(isConstructor=true) 47.150 + public static Object constructor(final boolean newObj, final Object self, final long arg) { 47.151 + final String str = Long.toString(arg); 47.152 + return newObj ? newObj(str) : str; 47.153 + } 47.154 + 47.155 + /** 47.156 + * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code int} arg 47.157 + * 47.158 + * Constructor 47.159 + * 47.160 + * @param newObj is this constructor invoked with the new operator 47.161 + * @param self self reference 47.162 + * @param arg the arg 47.163 + * 47.164 + * @return new NativeString containing the string representation of the arg 47.165 + */ 47.166 + @SpecializedFunction(isConstructor=true) 47.167 + public static Object constructor(final boolean newObj, final Object self, final double arg) { 47.168 final String str = JSType.toString(arg); 47.169 return newObj ? newObj(str) : str; 47.170 } 47.171 @@ -1231,9 +1282,9 @@ 47.172 * 47.173 * @return new NativeString containing the string representation of the arg 47.174 */ 47.175 - @SpecializedConstructor 47.176 + @SpecializedFunction(isConstructor=true) 47.177 public static Object constructor(final boolean newObj, final Object self, final boolean arg) { 47.178 - final String str = JSType.toString(arg); 47.179 + final String str = Boolean.toString(arg); 47.180 return newObj ? newObj(str) : str; 47.181 } 47.182 47.183 @@ -1281,7 +1332,7 @@ 47.184 } else if (self != null && self == Global.instance().getStringPrototype()) { 47.185 return ""; 47.186 } else { 47.187 - throw typeError( "not.a.string", ScriptRuntime.safeToString(self)); 47.188 + throw typeError("not.a.string", ScriptRuntime.safeToString(self)); 47.189 } 47.190 } 47.191 47.192 @@ -1310,4 +1361,50 @@ 47.193 return MH.findStatic(MethodHandles.lookup(), NativeString.class, name, type); 47.194 } 47.195 47.196 + @Override 47.197 + public LinkLogic getLinkLogic(final Class<? extends LinkLogic> clazz) { 47.198 + if (clazz == CharCodeAtLinkLogic.class) { 47.199 + return CharCodeAtLinkLogic.INSTANCE; 47.200 + } 47.201 + return null; 47.202 + } 47.203 + 47.204 + @Override 47.205 + public boolean hasPerInstanceAssumptions() { 47.206 + return false; 47.207 + } 47.208 + 47.209 + /** 47.210 + * This is linker logic charCodeAt - when we specialize further methods in NativeString 47.211 + * It may be expanded. It's link check makes sure that we are dealing with a char 47.212 + * sequence and that we are in range 47.213 + */ 47.214 + private static final class CharCodeAtLinkLogic extends SpecializedFunction.LinkLogic { 47.215 + 47.216 + private static final CharCodeAtLinkLogic INSTANCE = new CharCodeAtLinkLogic(); 47.217 + 47.218 + @Override 47.219 + public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { 47.220 + try { 47.221 + //check that it's a char sequence or throw cce 47.222 + final CharSequence cs = (CharSequence)self; 47.223 + //check that the index, representable as an int, is inside the array 47.224 + final int intIndex = JSType.toInteger(request.getArguments()[1]); 47.225 + return intIndex >= 0 && intIndex < cs.length(); //can link 47.226 + } catch (final ClassCastException | IndexOutOfBoundsException e) { 47.227 + //fallthru 47.228 + } 47.229 + return false; 47.230 + } 47.231 + 47.232 + /** 47.233 + * charCodeAt callsites can throw ClassCastException as a mechanism to have them 47.234 + * relinked - this enabled fast checks of the kind of ((IntArrayData)arrayData).push(x) 47.235 + * for an IntArrayData only push - if this fails, a CCE will be thrown and we will relink 47.236 + */ 47.237 + @Override 47.238 + public Class<? extends Throwable> getRelinkException() { 47.239 + return ClassCastException.class; 47.240 + } 47.241 + } 47.242 }
48.1 --- a/src/jdk/nashorn/internal/objects/NativeUint16Array.java Wed Oct 08 14:16:54 2014 -0700 48.2 +++ b/src/jdk/nashorn/internal/objects/NativeUint16Array.java Tue Oct 14 10:20:24 2014 -0700 48.3 @@ -26,7 +26,6 @@ 48.4 package jdk.nashorn.internal.objects; 48.5 48.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 48.7 - 48.8 import java.lang.invoke.MethodHandle; 48.9 import java.lang.invoke.MethodHandles; 48.10 import java.nio.ByteBuffer; 48.11 @@ -119,6 +118,11 @@ 48.12 } 48.13 48.14 @Override 48.15 + public Class<?> getElementType() { 48.16 + return int.class; 48.17 + } 48.18 + 48.19 + @Override 48.20 public int getInt(final int index) { 48.21 return getElem(index); 48.22 }
49.1 --- a/src/jdk/nashorn/internal/objects/NativeUint32Array.java Wed Oct 08 14:16:54 2014 -0700 49.2 +++ b/src/jdk/nashorn/internal/objects/NativeUint32Array.java Tue Oct 14 10:20:24 2014 -0700 49.3 @@ -26,7 +26,6 @@ 49.4 package jdk.nashorn.internal.objects; 49.5 49.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 49.7 - 49.8 import java.lang.invoke.MethodHandle; 49.9 import java.lang.invoke.MethodHandles; 49.10 import java.nio.ByteBuffer; 49.11 @@ -128,6 +127,11 @@ 49.12 } 49.13 49.14 @Override 49.15 + public Class<?> getElementType() { 49.16 + return int.class; 49.17 + } 49.18 + 49.19 + @Override 49.20 public int getInt(final int index) { 49.21 return (int)getLong(index); 49.22 }
50.1 --- a/src/jdk/nashorn/internal/objects/NativeUint8Array.java Wed Oct 08 14:16:54 2014 -0700 50.2 +++ b/src/jdk/nashorn/internal/objects/NativeUint8Array.java Tue Oct 14 10:20:24 2014 -0700 50.3 @@ -26,7 +26,6 @@ 50.4 package jdk.nashorn.internal.objects; 50.5 50.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 50.7 - 50.8 import java.lang.invoke.MethodHandle; 50.9 import java.lang.invoke.MethodHandles; 50.10 import java.nio.ByteBuffer; 50.11 @@ -119,6 +118,11 @@ 50.12 } 50.13 50.14 @Override 50.15 + public Class<?> getElementType() { 50.16 + return int.class; 50.17 + } 50.18 + 50.19 + @Override 50.20 public int getInt(final int index) { 50.21 return getElem(index); 50.22 }
51.1 --- a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Wed Oct 08 14:16:54 2014 -0700 51.2 +++ b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Tue Oct 14 10:20:24 2014 -0700 51.3 @@ -28,7 +28,6 @@ 51.4 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 51.5 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; 51.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 51.7 - 51.8 import java.lang.invoke.MethodHandle; 51.9 import java.lang.invoke.MethodHandles; 51.10 import java.nio.ByteBuffer; 51.11 @@ -98,6 +97,11 @@ 51.12 return SET_ELEM; 51.13 } 51.14 51.15 + @Override 51.16 + public Class<?> getElementType() { 51.17 + return int.class; 51.18 + } 51.19 + 51.20 private int getElem(final int index) { 51.21 try { 51.22 return nb.get(index) & 0xff;
52.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Wed Oct 08 14:16:54 2014 -0700 52.2 +++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Tue Oct 14 10:20:24 2014 -0700 52.3 @@ -30,6 +30,7 @@ 52.4 52.5 import java.lang.invoke.MethodHandle; 52.6 import java.util.ArrayList; 52.7 + 52.8 import jdk.nashorn.internal.runtime.AccessorProperty; 52.9 import jdk.nashorn.internal.runtime.GlobalFunctions; 52.10 import jdk.nashorn.internal.runtime.Property; 52.11 @@ -38,6 +39,7 @@ 52.12 import jdk.nashorn.internal.runtime.ScriptFunction; 52.13 import jdk.nashorn.internal.runtime.ScriptFunctionData; 52.14 import jdk.nashorn.internal.runtime.ScriptObject; 52.15 +import jdk.nashorn.internal.runtime.Specialization; 52.16 52.17 /** 52.18 * Concrete implementation of ScriptFunction. This sets correct map for the 52.19 @@ -58,7 +60,7 @@ 52.20 // Marker object for lazily initialized prototype object 52.21 private static final Object LAZY_PROTOTYPE = new Object(); 52.22 52.23 - private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs, final Global global) { 52.24 + private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs, final Global global) { 52.25 super(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); 52.26 init(global); 52.27 } 52.28 @@ -71,11 +73,11 @@ 52.29 * @param invokeHandle handle for invocation 52.30 * @param specs specialized versions of this method, if available, null otherwise 52.31 */ 52.32 - ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs) { 52.33 + ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs) { 52.34 this(name, invokeHandle, specs, Global.instance()); 52.35 } 52.36 52.37 - private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs, final Global global) { 52.38 + private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs, final Global global) { 52.39 super(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); 52.40 init(global); 52.41 } 52.42 @@ -89,11 +91,11 @@ 52.43 * @param map initial property map 52.44 * @param specs specialized versions of this method, if available, null otherwise 52.45 */ 52.46 - ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs) { 52.47 + ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs) { 52.48 this(name, invokeHandle, map, specs, Global.instance()); 52.49 } 52.50 52.51 - private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags, final Global global) { 52.52 + private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags, final Global global) { 52.53 super(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags); 52.54 init(global); 52.55 } 52.56 @@ -107,7 +109,7 @@ 52.57 * @param specs specialized versions of this method, if available, null otherwise 52.58 * @param flags {@link ScriptFunctionData} flags 52.59 */ 52.60 - ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags) { 52.61 + ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags) { 52.62 this(name, methodHandle, scope, specs, flags, Global.instance()); 52.63 } 52.64 52.65 @@ -184,7 +186,7 @@ 52.66 return new AnonymousFunction(); 52.67 } 52.68 52.69 - private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs, final int flags) { 52.70 + private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs, final int flags) { 52.71 final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, flags); 52.72 func.setPrototype(UNDEFINED); 52.73 // Non-constructor built-in functions do not have "prototype" property 52.74 @@ -201,7 +203,7 @@ 52.75 * @param specs specialized versions of function if available, null otherwise 52.76 * @return new ScriptFunction 52.77 */ 52.78 - static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) { 52.79 + static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs) { 52.80 return makeFunction(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN); 52.81 } 52.82
53.1 --- a/src/jdk/nashorn/internal/objects/annotations/SpecializedConstructor.java Wed Oct 08 14:16:54 2014 -0700 53.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 53.3 @@ -1,47 +0,0 @@ 53.4 -/* 53.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 53.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 53.7 - * 53.8 - * This code is free software; you can redistribute it and/or modify it 53.9 - * under the terms of the GNU General Public License version 2 only, as 53.10 - * published by the Free Software Foundation. Oracle designates this 53.11 - * particular file as subject to the "Classpath" exception as provided 53.12 - * by Oracle in the LICENSE file that accompanied this code. 53.13 - * 53.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 53.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 53.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 53.17 - * version 2 for more details (a copy is included in the LICENSE file that 53.18 - * accompanied this code). 53.19 - * 53.20 - * You should have received a copy of the GNU General Public License version 53.21 - * 2 along with this work; if not, write to the Free Software Foundation, 53.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 53.23 - * 53.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 53.25 - * or visit www.oracle.com if you need additional information or have any 53.26 - * questions. 53.27 - */ 53.28 - 53.29 -package jdk.nashorn.internal.objects.annotations; 53.30 - 53.31 -import java.lang.annotation.ElementType; 53.32 -import java.lang.annotation.Retention; 53.33 -import java.lang.annotation.RetentionPolicy; 53.34 -import java.lang.annotation.Target; 53.35 - 53.36 -/** 53.37 - * The SpecializedConstructor annotation is used to flag more type specific constructors than the standard one in 53.38 - * Native objects. For example {@link jdk.nashorn.internal.objects.NativeArray#construct} takes an arbitrary number of 53.39 - * Object elements as an array. Call this constructor, including the varargs collector that allocates the array 53.40 - * upon each invocation, is much more expensive than calling a specialized constructor that takes one arguments 53.41 - * of, e.g. int type from the call site, such as 53.42 - * {@link jdk.nashorn.internal.objects.NativeArray#construct(boolean, Object, int)}. 53.43 - * {@link jdk.nashorn.internal.runtime.ScriptFunction} will try to look up the most specific function when 53.44 - * linking the callsite. 53.45 - */ 53.46 -@Retention(RetentionPolicy.RUNTIME) 53.47 -@Target(ElementType.METHOD) 53.48 -public @interface SpecializedConstructor { 53.49 - //empty 53.50 -}
54.1 --- a/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Wed Oct 08 14:16:54 2014 -0700 54.2 +++ b/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Tue Oct 14 10:20:24 2014 -0700 54.3 @@ -1,5 +1,5 @@ 54.4 /* 54.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 54.6 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 54.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 54.8 * 54.9 * This code is free software; you can redistribute it and/or modify it 54.10 @@ -29,18 +29,315 @@ 54.11 import java.lang.annotation.Retention; 54.12 import java.lang.annotation.RetentionPolicy; 54.13 import java.lang.annotation.Target; 54.14 +import java.lang.invoke.MethodHandle; 54.15 +import java.lang.invoke.SwitchPoint; 54.16 +import jdk.internal.dynalink.CallSiteDescriptor; 54.17 +import jdk.internal.dynalink.linker.LinkRequest; 54.18 +import jdk.nashorn.internal.runtime.ScriptFunction; 54.19 54.20 /** 54.21 - * The SpecializedFunction annotation is used to flag more type specific functions than the standard one in 54.22 - * Native objects. For example {@link jdk.nashorn.internal.objects.NativeMath#max} takes an arbitrary number of 54.23 - * Object elements as an array. Call this function, including the varargs collector that allocates the array 54.24 - * upon each invocation, is much more expensive than calling a specialized function that takes two arguments 54.25 - * of, e.g. int type from the call site, such as {@link jdk.nashorn.internal.objects.NativeMath#max(Object, int, int)}. 54.26 - * {@link jdk.nashorn.internal.runtime.ScriptFunction} will try to look up the most specific function when 54.27 - * linking the callsite. 54.28 + * The SpecializedFunction annotation is used to flag more type specific 54.29 + * functions than the standard one in the native objects 54.30 */ 54.31 @Retention(RetentionPolicy.RUNTIME) 54.32 @Target(ElementType.METHOD) 54.33 public @interface SpecializedFunction { 54.34 - //empty 54.35 + 54.36 + /** 54.37 + * Functionality for testing if we are allowed to link a specialized 54.38 + * function the first time we encounter it. Then the guard will handle the 54.39 + * rest of the invocations 54.40 + * 54.41 + * This is the same for all callsites in Nashorn, the first time callsite is 54.42 + * linked, we have to manually check that the linkage is OK. Even if we add 54.43 + * a guard and it fails upon the first try, this is not good enough. 54.44 + * (Symmetrical to how it works everywhere else in the Nashorn runtime). 54.45 + * 54.46 + * Here we abstract out a few of the most common link guard checks. 54.47 + */ 54.48 + public static abstract class LinkLogic { 54.49 + /** 54.50 + * Empty link logic instance - this is the default 54.51 + * "no special linking or runtime guard behavior" 54.52 + */ 54.53 + public static final LinkLogic EMPTY_INSTANCE = new Empty(); 54.54 + 54.55 + private static final SwitchPoint[] INVALIDATED_SWITCHPOINTS = new SwitchPoint[0]; 54.56 + 54.57 + private SwitchPoint[] modificationSwitchPoints; //cache 54.58 + 54.59 + /** Empty link logic class - allow all linking, no guards */ 54.60 + private static final class Empty extends LinkLogic { 54.61 + @Override 54.62 + public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { 54.63 + return true; 54.64 + } 54.65 + 54.66 + @Override 54.67 + public boolean isEmpty() { 54.68 + return true; 54.69 + } 54.70 + } 54.71 + 54.72 + /** 54.73 + * Get the class representing the empty link logic 54.74 + * @return class representing empty link logic 54.75 + */ 54.76 + public static Class<? extends LinkLogic> getEmptyLinkLogicClass() { 54.77 + return Empty.class; 54.78 + } 54.79 + 54.80 + /** 54.81 + * Should this callsite relink when an exception is thrown 54.82 + * 54.83 + * @return the relink exception, or null if none 54.84 + */ 54.85 + public Class<? extends Throwable> getRelinkException() { 54.86 + return null; 54.87 + } 54.88 + 54.89 + /** 54.90 + * Is this link logic class empty - i.e. no special linking logic 54.91 + * supplied 54.92 + * 54.93 + * @param clazz class to check 54.94 + * 54.95 + * @return true if this link logic is empty 54.96 + */ 54.97 + public static boolean isEmpty(final Class<? extends LinkLogic> clazz) { 54.98 + return clazz == Empty.class; 54.99 + } 54.100 + 54.101 + /** 54.102 + * Is this link logic instance empty - i.e. no special linking logic 54.103 + * supplied 54.104 + * 54.105 + * @return true if this link logic instance is empty 54.106 + */ 54.107 + public boolean isEmpty() { 54.108 + return false; 54.109 + } 54.110 + 54.111 + /** 54.112 + * Given a callsite, can we link this method based on the receiver and 54.113 + * parameters? 54.114 + * 54.115 + * @param self receiver 54.116 + * @param desc callsite descriptor 54.117 + * @param request link request 54.118 + * 54.119 + * @return true if we can link this callsite at this time 54.120 + */ 54.121 + public abstract boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request); 54.122 + 54.123 + /** 54.124 + * Given a callsite, do we require an extra guard for specialization to 54.125 + * go through? 54.126 + * 54.127 + * @param self receiver 54.128 + * 54.129 + * @return true if a guard is to be woven into the callsite 54.130 + */ 54.131 + public boolean needsGuard(final Object self) { 54.132 + return true; 54.133 + } 54.134 + 54.135 + /** 54.136 + * Given a callsite, and optional arguments, do we need an extra guard 54.137 + * for specialization to go through - this guard can be a function of 54.138 + * the arguments too 54.139 + * 54.140 + * @param self receiver 54.141 + * @param args arguments 54.142 + * 54.143 + * @return true if a guard is to be woven into the callsite 54.144 + */ 54.145 + public boolean needsGuard(final Object self, final Object... args) { 54.146 + return true; 54.147 + } 54.148 + 54.149 + /** 54.150 + * Given a callsite, and optional arguments, return any extra guard we 54.151 + * might need for specialization as a method handle. 54.152 + * 54.153 + * @return methodhandle for guard, or null if no guard is needed 54.154 + */ 54.155 + public MethodHandle getGuard() { 54.156 + return null; 54.157 + } 54.158 + 54.159 + /** 54.160 + * Return the modification SwitchPoint of a particular index from this OptimisticBuiltins 54.161 + * If none exists, one is created and that one is return. 54.162 + * 54.163 + * The implementor must map indexes to specific SwitchPoints for specific events and keep 54.164 + * track of what they mean, for example NativeArray.LENGTH_NOT_WRITABLE_SWITCHPOINT 54.165 + * might be a useful index mapping 54.166 + * 54.167 + * @param index index for SwitchPoint to get or create 54.168 + * @return modification SwitchPoint of particular index for the receiver 54.169 + */ 54.170 + public SwitchPoint getOrCreateModificationSwitchPoint(final int index) { 54.171 + return null; 54.172 + } 54.173 + 54.174 + /** 54.175 + * Return the modification SwitchPoint from this OptimisticBuiltins. If none 54.176 + * exists, one is created and that one is return. 54.177 + * 54.178 + * @return modification SwitchPoint for the receiver 54.179 + */ 54.180 + public SwitchPoint[] getOrCreateModificationSwitchPoints() { 54.181 + return null; 54.182 + } 54.183 + 54.184 + /** 54.185 + * Hook to invalidate a modification SwitchPoint by index. 54.186 + * 54.187 + * @param index index for SwitchPoint to invalidate 54.188 + */ 54.189 + public void invalidateModificationSwitchPoint(final int index) { 54.190 + //empty 54.191 + } 54.192 + 54.193 + /** 54.194 + * Hook to invalidate all modification SwitchPoints for a receiver 54.195 + */ 54.196 + public void invalidateModificationSwitchPoints() { 54.197 + //empty 54.198 + } 54.199 + 54.200 + /** 54.201 + * Check whether the receiver has an invalidated modification SwitchPoint. 54.202 + * 54.203 + * @param index index for the modification SwitchPoint 54.204 + * @return true if the particular SwitchPoint at the index is invalidated 54.205 + */ 54.206 + public boolean hasInvalidatedModificationSwitchPoint(final int index) { 54.207 + return false; 54.208 + } 54.209 + 54.210 + /** 54.211 + * Check whether at least one of the modification SwitchPoints has been 54.212 + * invalidated 54.213 + * @return true if one of the SwitchPoints has been invalidated 54.214 + */ 54.215 + public boolean hasInvalidatedModificationSwitchPoints() { 54.216 + return false; 54.217 + } 54.218 + 54.219 + /** 54.220 + * Check whether this OptimisticBuiltins has a SwitchPoints of particular 54.221 + * index. 54.222 + * 54.223 + * As creation overhead for a SwitchPoint is non-zero, we have to create them lazily instead of, 54.224 + * e.g. in the constructor of every subclass. 54.225 + * 54.226 + * @param index index for the modification SwitchPoint 54.227 + * @return true if a modification SwitchPoint exists, no matter if it has been invalidated or not 54.228 + */ 54.229 + public boolean hasModificationSwitchPoint(final int index) { 54.230 + return false; 54.231 + } 54.232 + 54.233 + /** 54.234 + * Check whether this OptimisticBuiltins has SwitchPoints. 54.235 + * 54.236 + * As creation overhead for a SwitchPoint is non-zero, we have to create them lazily instead of, 54.237 + * e.g. in the constructor of every subclass. 54.238 + * 54.239 + * @return true if a modification SwitchPoint exists, no matter if it has been invalidated or not 54.240 + */ 54.241 + public boolean hasModificationSwitchPoints() { 54.242 + return false; 54.243 + } 54.244 + 54.245 + /** 54.246 + * Check, given a link request and a receiver, if this specialization 54.247 + * fits This is used by the linker in {@link ScriptFunction} to figure 54.248 + * out if an optimistic builtin can be linked when first discovered 54.249 + * 54.250 + * @param self receiver 54.251 + * @param desc callsite descriptor 54.252 + * @param request link request 54.253 + 54.254 + * @return true if we can link, false otherwise - that means we have to 54.255 + * pick a non specialized target 54.256 + */ 54.257 + public boolean checkLinkable(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { 54.258 + // no matter what the modification switchpoints are, if any of them are invalidated, 54.259 + // we can't link. Side effect is that if it's the first time we see this callsite, 54.260 + // we have to create the SwitchPoint(s) so future modification switchpoint invalidations 54.261 + // relink it 54.262 + final SwitchPoint[] sps = getOrCreateModificationSwitchPoints(self); 54.263 + if (sps == INVALIDATED_SWITCHPOINTS) { 54.264 + // nope, can't do the fast link as this assumption 54.265 + // has been invalidated already, e.g. length of an 54.266 + // array set to not writable 54.267 + return false; 54.268 + } 54.269 + modificationSwitchPoints = sps; //cache 54.270 + 54.271 + // check the link guard, if it says we can link, go ahead 54.272 + return canLink(self, desc, request); 54.273 + } 54.274 + 54.275 + private SwitchPoint[] getOrCreateModificationSwitchPoints(final Object self) { 54.276 + final SwitchPoint[] sps = getOrCreateModificationSwitchPoints(); //ask for all my switchpoints 54.277 + if (sps != null) { //switchpoint exists, but some may be invalidated 54.278 + for (final SwitchPoint sp : sps) { 54.279 + if (sp.hasBeenInvalidated()) { 54.280 + return INVALIDATED_SWITCHPOINTS; 54.281 + } 54.282 + } 54.283 + } 54.284 + return sps; 54.285 + } 54.286 + 54.287 + /** 54.288 + * Get the cached modification switchpoints. Only possible to do after a link 54.289 + * check call has been performed, one that has answered "true", or you will get the 54.290 + * wrong information. 54.291 + * 54.292 + * Should be used only from {@link ScriptFunction#findCallMethod} 54.293 + * 54.294 + * @return cached modification switchpoints for this callsite, null if none 54.295 + */ 54.296 + public SwitchPoint[] getModificationSwitchPoints() { 54.297 + return modificationSwitchPoints == null ? null : modificationSwitchPoints.clone(); 54.298 + } 54.299 + } 54.300 + 54.301 + /** 54.302 + * name override for return value polymorphism, for example we can't have 54.303 + * pop(V)I and pop(V)D in the same Java class, so they need to be named, 54.304 + * e.g. popInt(V)I and popDouble(V)D for disambiguation, however, their 54.305 + * names still need to resolve to "pop" to JavaScript so we can still 54.306 + * specialize on return values and so that the linker can find them 54.307 + * 54.308 + * @return name, "" means no override, use the Java function name, e.g. 54.309 + * "push" 54.310 + */ 54.311 + String name() default ""; 54.312 + 54.313 + /** 54.314 + * Return the guard for this specialized function. The default is no guard. 54.315 + * 54.316 + * @return guard 54.317 + */ 54.318 + Class<?> linkLogic() default LinkLogic.Empty.class; 54.319 + 54.320 + /** 54.321 + * Is this a specialized constructor? 54.322 + */ 54.323 + boolean isConstructor() default false; 54.324 + 54.325 + /** 54.326 + * Can this function throw UnwarrantedOptimismExceptions? This works just 54.327 + * like the normal functions, but we need the function to be 54.328 + * immutable/non-state modifying, as we can't generate continuations for 54.329 + * native code. Luckily a lot of the methods we want to specialize have this 54.330 + * property 54.331 + */ 54.332 + boolean isOptimistic() default false; 54.333 }
55.1 --- a/src/jdk/nashorn/internal/parser/AbstractParser.java Wed Oct 08 14:16:54 2014 -0700 55.2 +++ b/src/jdk/nashorn/internal/parser/AbstractParser.java Tue Oct 14 10:20:24 2014 -0700 55.3 @@ -30,7 +30,6 @@ 55.4 import static jdk.nashorn.internal.parser.TokenType.EOF; 55.5 import static jdk.nashorn.internal.parser.TokenType.EOL; 55.6 import static jdk.nashorn.internal.parser.TokenType.IDENT; 55.7 - 55.8 import java.util.HashMap; 55.9 import java.util.Map; 55.10 import jdk.nashorn.internal.ir.IdentNode;
56.1 --- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java Wed Oct 08 14:16:54 2014 -0700 56.2 +++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java Tue Oct 14 10:20:24 2014 -0700 56.3 @@ -36,7 +36,6 @@ 56.4 import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex; 56.5 import static jdk.nashorn.internal.runtime.JSType.getNumberOfAccessorTypes; 56.6 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 56.7 - 56.8 import java.io.IOException; 56.9 import java.io.ObjectInputStream; 56.10 import java.lang.invoke.MethodHandle; 56.11 @@ -57,9 +56,7 @@ 56.12 private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); 56.13 56.14 private static final MethodHandle REPLACE_MAP = findOwnMH_S("replaceMap", Object.class, Object.class, PropertyMap.class); 56.15 - private static final MethodHandle INVALIDATE_SP = findOwnMH_S("invalidateSwitchPoint", Object.class, Object.class, SwitchPoint.class); 56.16 - 56.17 - private static final SwitchPoint NO_CHANGE_CALLBACK = new SwitchPoint(); 56.18 + private static final MethodHandle INVALIDATE_SP = findOwnMH_S("invalidateSwitchPoint", Object.class, AccessorProperty.class, Object.class); 56.19 56.20 private static final int NOOF_TYPES = getNumberOfAccessorTypes(); 56.21 private static final long serialVersionUID = 3371720170182154920L; 56.22 @@ -221,7 +218,7 @@ 56.23 * @param setter the property setter or null if non writable, non configurable 56.24 */ 56.25 private AccessorProperty(final String key, final int flags, final int slot, final MethodHandle getter, final MethodHandle setter) { 56.26 - super(key, flags | (getter.type().returnType().isPrimitive() ? IS_NASGEN_PRIMITIVE : 0), slot); 56.27 + super(key, flags | IS_BUILTIN | (getter.type().returnType().isPrimitive() ? IS_NASGEN_PRIMITIVE : 0), slot); 56.28 assert !isSpill(); 56.29 56.30 // we don't need to prep the setters these will never be invalidated as this is a nasgen 56.31 @@ -602,7 +599,6 @@ 56.32 56.33 private Property getWiderProperty(final Class<?> type) { 56.34 return copy(type); //invalidate cache of new property 56.35 - 56.36 } 56.37 56.38 private PropertyMap getWiderMap(final PropertyMap oldMap, final Property newProperty) { 56.39 @@ -627,8 +623,10 @@ 56.40 } 56.41 56.42 @SuppressWarnings("unused") 56.43 - private static Object invalidateSwitchPoint(final Object obj, final SwitchPoint sp) { 56.44 - SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 56.45 + private static Object invalidateSwitchPoint(final AccessorProperty property, final Object obj) { 56.46 + if (!property.builtinSwitchPoint.hasBeenInvalidated()) { 56.47 + SwitchPoint.invalidateAll(new SwitchPoint[] { property.builtinSwitchPoint }); 56.48 + } 56.49 return obj; 56.50 } 56.51 56.52 @@ -668,12 +666,8 @@ 56.53 mh = generateSetter(!forType.isPrimitive() ? Object.class : forType, type); 56.54 } 56.55 56.56 - /** 56.57 - * Check if this is a special global name that requires switchpoint invalidation 56.58 - */ 56.59 - final SwitchPoint ccb = getChangeCallback(); 56.60 - if (ccb != null && ccb != NO_CHANGE_CALLBACK) { 56.61 - mh = MH.filterArguments(mh, 0, MH.insertArguments(debugInvalidate(getKey(), ccb), 1, changeCallback)); 56.62 + if (isBuiltin()) { 56.63 + mh = MH.filterArguments(mh, 0, debugInvalidate(MH.insertArguments(INVALIDATE_SP, 0, this), getKey())); 56.64 } 56.65 56.66 assert mh.type().returnType() == void.class : mh.type(); 56.67 @@ -681,25 +675,6 @@ 56.68 return mh; 56.69 } 56.70 56.71 - /** 56.72 - * Get the change callback for this property 56.73 - * @return switchpoint that is invalidated when property changes 56.74 - */ 56.75 - protected SwitchPoint getChangeCallback() { 56.76 - if (changeCallback == null) { 56.77 - try { 56.78 - changeCallback = Global.instance().getChangeCallback(getKey()); 56.79 - } catch (final NullPointerException e) { 56.80 - assert !"apply".equals(getKey()) && !"call".equals(getKey()); 56.81 - //empty 56.82 - } 56.83 - if (changeCallback == null) { 56.84 - changeCallback = NO_CHANGE_CALLBACK; 56.85 - } 56.86 - } 56.87 - return changeCallback; 56.88 - } 56.89 - 56.90 @Override 56.91 public final boolean canChangeType() { 56.92 if (OBJECT_FIELDS_ONLY) { 56.93 @@ -724,7 +699,6 @@ 56.94 return currentType; 56.95 } 56.96 56.97 - 56.98 private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) { 56.99 if (!Context.DEBUG || !Global.hasInstance()) { 56.100 return mh; 56.101 @@ -780,9 +754,9 @@ 56.102 return mh; 56.103 } 56.104 56.105 - private static MethodHandle debugInvalidate(final String key, final SwitchPoint sp) { 56.106 + private static MethodHandle debugInvalidate(final MethodHandle invalidator, final String key) { 56.107 if (!Context.DEBUG || !Global.hasInstance()) { 56.108 - return INVALIDATE_SP; 56.109 + return invalidator; 56.110 } 56.111 56.112 final Context context = Context.getContextTrusted(); 56.113 @@ -790,11 +764,11 @@ 56.114 56.115 return context.addLoggingToHandle( 56.116 ObjectClassGenerator.class, 56.117 - INVALIDATE_SP, 56.118 + invalidator, 56.119 new Supplier<String>() { 56.120 @Override 56.121 public String get() { 56.122 - return "Field change callback for " + key + " triggered: " + sp; 56.123 + return "Field change callback for " + key + " triggered "; 56.124 } 56.125 }); 56.126 }
57.1 --- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java Wed Oct 08 14:16:54 2014 -0700 57.2 +++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java Tue Oct 14 10:20:24 2014 -0700 57.3 @@ -81,13 +81,17 @@ 57.4 57.5 /** 57.6 * Store a compiled script for later reuse 57.7 + * 57.8 + * @param cacheKey key to use in cache 57.9 * @param source the script source 57.10 * @param mainClassName the main class name 57.11 * @param classBytes map of class names to class bytes 57.12 + * @param initializers compilation id -> FunctionInitializer map 57.13 * @param constants constants array 57.14 + * @param compilationId compilation id 57.15 */ 57.16 - public void storeScript(String cacheKey, Source source, String mainClassName, Map<String, byte[]> classBytes, 57.17 - Map<Integer, FunctionInitializer> initializers, Object[] constants, int compilationId); 57.18 + public void storeScript(final String cacheKey, final Source source, final String mainClassName, final Map<String, byte[]> classBytes, 57.19 + final Map<Integer, FunctionInitializer> initializers, final Object[] constants, final int compilationId); 57.20 57.21 /** 57.22 * Load a previously compiled script 57.23 @@ -96,4 +100,21 @@ 57.24 * @return compiled script data 57.25 */ 57.26 public StoredScript loadScript(Source source, String functionKey); 57.27 + 57.28 + /** 57.29 + * Returns a new code installer that shares most of the functionality of this code installer, but uses a 57.30 + * new, independent class loader. 57.31 + * @return a new code installer with a new independent class loader. 57.32 + */ 57.33 + public CodeInstaller<T> withNewLoader(); 57.34 + 57.35 + /** 57.36 + * Returns true if this code installer is compatible with the other code installer. Compatibility is expected to be 57.37 + * an equivalence relation, and installers are supposed to be compatible with those they create using 57.38 + * {@link #withNewLoader()}. 57.39 + * @param other the other code installer tested for compatibility with this code installer. 57.40 + * @return true if this code installer is compatible with the other code installer. 57.41 + */ 57.42 + public boolean isCompatibleWith(CodeInstaller<T> other); 57.43 + 57.44 }
58.1 --- a/src/jdk/nashorn/internal/runtime/CodeStore.java Wed Oct 08 14:16:54 2014 -0700 58.2 +++ b/src/jdk/nashorn/internal/runtime/CodeStore.java Tue Oct 14 10:20:24 2014 -0700 58.3 @@ -118,6 +118,8 @@ 58.4 * @param initializers the function initializers 58.5 * @param constants the constants array 58.6 * @param compilationId the compilation id 58.7 + * 58.8 + * @return stored script 58.9 */ 58.10 public StoredScript store(final String functionKey, 58.11 final Source source, 58.12 @@ -153,11 +155,13 @@ 58.13 /** 58.14 * Returns a new StoredScript instance. 58.15 * 58.16 + * @param source the source 58.17 * @param mainClassName the main class name 58.18 * @param classBytes a map of class bytes 58.19 * @param initializers function initializers 58.20 * @param constants the constants array 58.21 * @param compilationId the compilation id 58.22 + * 58.23 * @return The compiled script 58.24 */ 58.25 public StoredScript storedScriptFor(final Source source, final String mainClassName, 58.26 @@ -206,7 +210,7 @@ 58.27 /** 58.28 * Constructor 58.29 * 58.30 - * @throws IOException 58.31 + * @throws IOException if there are read/write problems with the cache and cache directory 58.32 */ 58.33 public DirectoryCodeStore() throws IOException { 58.34 this(Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache"), false, DEFAULT_MIN_SIZE); 58.35 @@ -216,8 +220,9 @@ 58.36 * Constructor 58.37 * 58.38 * @param path directory to store code in 58.39 + * @param readOnly is this a read only code store 58.40 * @param minSize minimum file size for caching scripts 58.41 - * @throws IOException 58.42 + * @throws IOException if there are read/write problems with the cache and cache directory 58.43 */ 58.44 public DirectoryCodeStore(final String path, final boolean readOnly, final int minSize) throws IOException { 58.45 this.dir = checkDirectory(path, readOnly);
59.1 --- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java Wed Oct 08 14:16:54 2014 -0700 59.2 +++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java Tue Oct 14 10:20:24 2014 -0700 59.3 @@ -33,12 +33,13 @@ 59.4 import java.lang.invoke.MethodType; 59.5 import java.lang.invoke.MutableCallSite; 59.6 import java.lang.invoke.SwitchPoint; 59.7 +import java.util.Collection; 59.8 +import java.util.Collections; 59.9 import java.util.Iterator; 59.10 import java.util.Map; 59.11 import java.util.TreeMap; 59.12 import java.util.function.Supplier; 59.13 import java.util.logging.Level; 59.14 - 59.15 import jdk.internal.dynalink.linker.GuardedInvocation; 59.16 import jdk.nashorn.internal.codegen.Compiler; 59.17 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; 59.18 @@ -46,6 +47,7 @@ 59.19 import jdk.nashorn.internal.codegen.types.ArrayType; 59.20 import jdk.nashorn.internal.codegen.types.Type; 59.21 import jdk.nashorn.internal.ir.FunctionNode; 59.22 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 59.23 import jdk.nashorn.internal.runtime.events.RecompilationEvent; 59.24 import jdk.nashorn.internal.runtime.linker.Bootstrap; 59.25 import jdk.nashorn.internal.runtime.logging.DebugLogger; 59.26 @@ -63,6 +65,8 @@ 59.27 59.28 private final DebugLogger log; 59.29 59.30 + static final Collection<CompiledFunction> NO_FUNCTIONS = Collections.emptySet(); 59.31 + 59.32 /** 59.33 * The method type may be more specific than the invoker, if. e.g. 59.34 * the invoker is guarded, and a guard with a generic object only 59.35 @@ -75,19 +79,38 @@ 59.36 private final int flags; // from FunctionNode 59.37 private final MethodType callSiteType; 59.38 59.39 + private final Specialization specialization; 59.40 + 59.41 CompiledFunction(final MethodHandle invoker) { 59.42 - this(invoker, null); 59.43 + this(invoker, null, null); 59.44 } 59.45 59.46 - static CompiledFunction createBuiltInConstructor(final MethodHandle invoker) { 59.47 - return new CompiledFunction(MH.insertArguments(invoker, 0, false), createConstructorFromInvoker(MH.insertArguments(invoker, 0, true))); 59.48 + static CompiledFunction createBuiltInConstructor(final MethodHandle invoker, final Specialization specialization) { 59.49 + return new CompiledFunction(MH.insertArguments(invoker, 0, false), createConstructorFromInvoker(MH.insertArguments(invoker, 0, true)), specialization); 59.50 } 59.51 59.52 - CompiledFunction(final MethodHandle invoker, final MethodHandle constructor) { 59.53 - this(invoker, constructor, 0, null, DebugLogger.DISABLED_LOGGER); 59.54 + CompiledFunction(final MethodHandle invoker, final MethodHandle constructor, final Specialization specialization) { 59.55 + this(invoker, constructor, 0, null, specialization, DebugLogger.DISABLED_LOGGER); 59.56 } 59.57 59.58 - CompiledFunction(final MethodHandle invoker, final MethodHandle constructor, final int flags, final MethodType callSiteType, final DebugLogger log) { 59.59 + CompiledFunction(final MethodHandle invoker, final MethodHandle constructor, final int flags, final MethodType callSiteType, final Specialization specialization, final DebugLogger log) { 59.60 + this.specialization = specialization; 59.61 + if (specialization != null && specialization.isOptimistic()) { 59.62 + /* 59.63 + * An optimistic builtin with isOptimistic=true works like any optimistic generated function, i.e. it 59.64 + * can throw unwarranted optimism exceptions. As native functions trivially can't have parts of them 59.65 + * regenerated as restof methods, this only works if the methods are atomic/functional in their behavior 59.66 + * and doesn't modify state before an UOE can be thrown. If they aren't, we can reexecute a wider version 59.67 + * of the same builtin in a recompilation handler for FinalScriptFunctionData. There are several 59.68 + * candidate methods in Native* that would benefit from this, but I haven't had time to implement any 59.69 + * of them currently. In order to fit in with the relinking framework, the current thinking is 59.70 + * that the methods still take a program point to fit in with other optimistic functions, but 59.71 + * it is set to "first", which is the beginning of the method. The relinker can tell the difference 59.72 + * between builtin and JavaScript functions. This might change. TODO 59.73 + */ 59.74 + this.invoker = MH.insertArguments(invoker, invoker.type().parameterCount() - 1, UnwarrantedOptimismException.FIRST_PROGRAM_POINT); 59.75 + throw new AssertionError("Optimistic (UnwarrantedOptimismException throwing) builtin functions are currently not in use"); 59.76 + } 59.77 this.invoker = invoker; 59.78 this.constructor = constructor; 59.79 this.flags = flags; 59.80 @@ -97,7 +120,7 @@ 59.81 59.82 CompiledFunction(final MethodHandle invoker, final RecompilableScriptFunctionData functionData, 59.83 final Map<Integer, Type> invalidatedProgramPoints, final MethodType callSiteType, final int flags) { 59.84 - this(invoker, null, flags, callSiteType, functionData.getLogger()); 59.85 + this(invoker, null, flags, callSiteType, null, functionData.getLogger()); 59.86 if ((flags & FunctionNode.IS_DEOPTIMIZABLE) != 0) { 59.87 optimismInfo = new OptimismInfo(functionData, invalidatedProgramPoints); 59.88 } else { 59.89 @@ -105,10 +128,45 @@ 59.90 } 59.91 } 59.92 59.93 + static CompiledFunction createBuiltInConstructor(final MethodHandle invoker) { 59.94 + return new CompiledFunction(MH.insertArguments(invoker, 0, false), createConstructorFromInvoker(MH.insertArguments(invoker, 0, true)), null); 59.95 + } 59.96 + 59.97 + boolean isSpecialization() { 59.98 + return specialization != null; 59.99 + } 59.100 + 59.101 + boolean hasLinkLogic() { 59.102 + return getLinkLogicClass() != null; 59.103 + } 59.104 + 59.105 + Class<? extends LinkLogic> getLinkLogicClass() { 59.106 + if (isSpecialization()) { 59.107 + final Class<? extends LinkLogic> linkLogicClass = specialization.getLinkLogicClass(); 59.108 + assert !LinkLogic.isEmpty(linkLogicClass) : "empty link logic classes should have been removed by nasgen"; 59.109 + return linkLogicClass; 59.110 + } 59.111 + return null; 59.112 + } 59.113 + 59.114 int getFlags() { 59.115 return flags; 59.116 } 59.117 59.118 + /** 59.119 + * An optimistic specialization is one that can throw UnwarrantedOptimismException. 59.120 + * This is allowed for native methods, as long as they are functional, i.e. don't change 59.121 + * any state between entering and throwing the UOE. Then we can re-execute a wider version 59.122 + * of the method in the continuation. Rest-of method generation for optimistic builtins is 59.123 + * of course not possible, but this approach works and fits into the same relinking 59.124 + * framework 59.125 + * 59.126 + * @return true if optimistic builtin 59.127 + */ 59.128 + boolean isOptimistic() { 59.129 + return isSpecialization() ? specialization.isOptimistic() : false; 59.130 + } 59.131 + 59.132 boolean isApplyToCall() { 59.133 return (flags & FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION) != 0; 59.134 } 59.135 @@ -119,7 +177,19 @@ 59.136 59.137 @Override 59.138 public String toString() { 59.139 - return "[invokerType=" + invoker.type() + " ctor=" + constructor + " weight=" + weight() + " isApplyToCall=" + isApplyToCall() + "]"; 59.140 + final StringBuilder sb = new StringBuilder(); 59.141 + final Class<? extends LinkLogic> linkLogicClass = getLinkLogicClass(); 59.142 + 59.143 + sb.append("[invokerType="). 59.144 + append(invoker.type()). 59.145 + append(" ctor="). 59.146 + append(constructor). 59.147 + append(" weight="). 59.148 + append(weight()). 59.149 + append(" linkLogic="). 59.150 + append(linkLogicClass != null ? linkLogicClass.getSimpleName() : "none"); 59.151 + 59.152 + return sb.toString(); 59.153 } 59.154 59.155 boolean needsCallee() { 59.156 @@ -281,10 +351,12 @@ 59.157 if (other == null) { 59.158 return true; 59.159 } 59.160 - return betterThanFinal(type(), other.type(), callSiteMethodType); 59.161 + return betterThanFinal(this, other, callSiteMethodType); 59.162 } 59.163 59.164 - static boolean betterThanFinal(final MethodType thisMethodType, final MethodType otherMethodType, final MethodType callSiteMethodType) { 59.165 + private static boolean betterThanFinal(final CompiledFunction cf, final CompiledFunction other, final MethodType callSiteMethodType) { 59.166 + final MethodType thisMethodType = cf.type(); 59.167 + final MethodType otherMethodType = other.type(); 59.168 final int thisParamCount = getParamCount(thisMethodType); 59.169 final int otherParamCount = getParamCount(otherMethodType); 59.170 final int callSiteRawParamCount = getParamCount(callSiteMethodType); 59.171 @@ -406,7 +478,17 @@ 59.172 return false; 59.173 } 59.174 59.175 - throw new AssertionError(thisMethodType + " identically applicable to " + otherMethodType + " for " + callSiteMethodType); // Signatures are identical 59.176 + //if they are equal, pick the specialized one first 59.177 + if (cf.isSpecialization() != other.isSpecialization()) { 59.178 + return cf.isSpecialization(); //always pick the specialized version if we can 59.179 + } 59.180 + 59.181 + if (cf.isSpecialization() && other.isSpecialization()) { 59.182 + return cf.getLinkLogicClass() != null; //pick link logic specialization above generic specializations 59.183 + } 59.184 + 59.185 + // Signatures are identical 59.186 + throw new AssertionError(thisMethodType + " identically applicable to " + otherMethodType + " for " + callSiteMethodType); 59.187 } 59.188 59.189 private static Type[] toTypeWithoutCallee(final MethodType type, final int thisIndex) { 59.190 @@ -427,8 +509,8 @@ 59.191 return ((ArrayType)paramTypes[paramTypes.length - 1]).getElementType(); 59.192 } 59.193 59.194 - boolean matchesCallSite(final MethodType callSiteType, final boolean pickVarArg) { 59.195 - if (callSiteType.equals(this.callSiteType)) { 59.196 + boolean matchesCallSite(final MethodType other, final boolean pickVarArg) { 59.197 + if (other.equals(this.callSiteType)) { 59.198 return true; 59.199 } 59.200 final MethodType type = type(); 59.201 @@ -438,7 +520,7 @@ 59.202 return pickVarArg; 59.203 } 59.204 59.205 - final int csParamCount = getParamCount(callSiteType); 59.206 + final int csParamCount = getParamCount(other); 59.207 final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE; 59.208 final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type 59.209 59.210 @@ -447,7 +529,7 @@ 59.211 // We must match all incoming parameters, except "this". Starting from 1 to skip "this". 59.212 for(int i = 1; i < minParams; ++i) { 59.213 final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex)); 59.214 - final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(callSiteType.parameterType(i + 1)); 59.215 + final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1)); 59.216 if(!fnType.isEquivalentTo(csType)) { 59.217 return false; 59.218 } 59.219 @@ -669,9 +751,9 @@ 59.220 return sb.toString(); 59.221 } 59.222 59.223 - private void logRecompile(final String reason, final FunctionNode fn, final MethodType callSiteType, final Map<Integer, Type> ipp) { 59.224 + private void logRecompile(final String reason, final FunctionNode fn, final MethodType type, final Map<Integer, Type> ipp) { 59.225 if (log.isEnabled()) { 59.226 - log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", callSiteType, " ", toStringInvalidations(ipp)); 59.227 + log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", type, " ", toStringInvalidations(ipp)); 59.228 } 59.229 } 59.230 59.231 @@ -732,8 +814,6 @@ 59.232 compiler.persistClassInfo(cacheKey, normalFn); 59.233 } 59.234 59.235 - FunctionNode fn2 = effectiveOptInfo.reparse(); 59.236 - fn2 = compiler.compile(fn2, CompilationPhases.COMPILE_UPTO_BYTECODE); 59.237 log.info("Done."); 59.238 59.239 final boolean canBeDeoptimized = normalFn.canBeDeoptimized();
60.1 --- a/src/jdk/nashorn/internal/runtime/Context.java Wed Oct 08 14:16:54 2014 -0700 60.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java Tue Oct 14 10:20:24 2014 -0700 60.3 @@ -33,13 +33,13 @@ 60.4 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 60.5 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 60.6 import static jdk.nashorn.internal.runtime.Source.sourceFor; 60.7 - 60.8 import java.io.File; 60.9 import java.io.IOException; 60.10 import java.io.PrintWriter; 60.11 import java.lang.invoke.MethodHandle; 60.12 import java.lang.invoke.MethodHandles; 60.13 import java.lang.invoke.MethodType; 60.14 +import java.lang.invoke.SwitchPoint; 60.15 import java.lang.ref.ReferenceQueue; 60.16 import java.lang.ref.SoftReference; 60.17 import java.lang.reflect.Field; 60.18 @@ -127,6 +127,16 @@ 60.19 private static MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); 60.20 private static MethodType CREATE_PROGRAM_FUNCTION_TYPE = MethodType.methodType(ScriptFunction.class, ScriptObject.class); 60.21 60.22 + /** 60.23 + * Keeps track of which builtin prototypes and properties have been relinked 60.24 + * Currently we are conservative and associate the name of a builtin class with all 60.25 + * its properties, so it's enough to invalidate a property to break all assumptions 60.26 + * about a prototype. This can be changed to a more fine grained approach, but no one 60.27 + * ever needs this, given the very rare occurance of swapping out only parts of 60.28 + * a builtin v.s. the entire builtin object 60.29 + */ 60.30 + private final Map<String, SwitchPoint> builtinSwitchPoints = new HashMap<>(); 60.31 + 60.32 /* Force DebuggerSupport to be loaded. */ 60.33 static { 60.34 DebuggerSupport.FORCELOAD = true; 60.35 @@ -148,7 +158,7 @@ 60.36 } 60.37 60.38 /** 60.39 - * Return the context for this installer 60.40 + * Return the script environment for this installer 60.41 * @return ScriptEnvironment 60.42 */ 60.43 @Override 60.44 @@ -212,6 +222,20 @@ 60.45 } 60.46 return null; 60.47 } 60.48 + 60.49 + @Override 60.50 + public CodeInstaller<ScriptEnvironment> withNewLoader() { 60.51 + return new ContextCodeInstaller(context, context.createNewLoader(), codeSource); 60.52 + } 60.53 + 60.54 + @Override 60.55 + public boolean isCompatibleWith(final CodeInstaller<ScriptEnvironment> other) { 60.56 + if (other instanceof ContextCodeInstaller) { 60.57 + final ContextCodeInstaller cci = (ContextCodeInstaller)other; 60.58 + return cci.context == context && cci.codeSource == codeSource; 60.59 + } 60.60 + return false; 60.61 + } 60.62 } 60.63 60.64 /** Is Context global debug mode enabled ? */ 60.65 @@ -1113,6 +1137,9 @@ 60.66 60.67 StoredScript storedScript = null; 60.68 FunctionNode functionNode = null; 60.69 + // We only use the code store here if optimistic types are disabled. With optimistic types, 60.70 + // code is stored per function in RecompilableScriptFunctionData. 60.71 + // TODO: This should really be triggered by lazy compilation, not optimistic types. 60.72 final boolean useCodeStore = env._persistent_cache && !env._parse_only && !env._optimistic_types; 60.73 final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0, null) : null; 60.74 60.75 @@ -1199,7 +1226,7 @@ 60.76 final String mainClassName = storedScript.getMainClassName(); 60.77 final byte[] mainClassBytes = classBytes.get(mainClassName); 60.78 final Class<?> mainClass = installer.install(mainClassName, mainClassBytes); 60.79 - final Map<Integer, FunctionInitializer> initialzers = storedScript.getInitializers(); 60.80 + final Map<Integer, FunctionInitializer> initializers = storedScript.getInitializers(); 60.81 60.82 installedClasses.put(mainClassName, mainClass); 60.83 60.84 @@ -1219,8 +1246,8 @@ 60.85 if (constant instanceof RecompilableScriptFunctionData) { 60.86 final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant; 60.87 data.initTransients(source, installer); 60.88 - if (initialzers != null) { 60.89 - final FunctionInitializer initializer = initialzers.get(data.getFunctionNodeId()); 60.90 + final FunctionInitializer initializer = initializers.get(data.getFunctionNodeId()); 60.91 + if (initializer != null) { 60.92 initializer.setCode(installedClasses.get(initializer.getClassName())); 60.93 data.initializeCode(initializer); 60.94 } 60.95 @@ -1371,4 +1398,34 @@ 60.96 return null; 60.97 } 60.98 60.99 + /** 60.100 + * This is a special kind of switchpoint used to guard builtin 60.101 + * properties and prototypes. In the future it might contain 60.102 + * logic to e.g. multiple switchpoint classes. 60.103 + */ 60.104 + public static final class BuiltinSwitchPoint extends SwitchPoint { 60.105 + //empty 60.106 + } 60.107 + 60.108 + /** 60.109 + * Create a new builtin switchpoint and return it 60.110 + * @param name key name 60.111 + * @return new builtin switchpoint 60.112 + */ 60.113 + public SwitchPoint newBuiltinSwitchPoint(final String name) { 60.114 + assert builtinSwitchPoints.get(name) == null; 60.115 + final SwitchPoint sp = new BuiltinSwitchPoint(); 60.116 + builtinSwitchPoints.put(name, sp); 60.117 + return sp; 60.118 + } 60.119 + 60.120 + /** 60.121 + * Return the builtin switchpoint for a particular key name 60.122 + * @param name key name 60.123 + * @return builtin switchpoint or null if none 60.124 + */ 60.125 + public SwitchPoint getBuiltinSwitchPoint(final String name) { 60.126 + return builtinSwitchPoints.get(name); 60.127 + } 60.128 + 60.129 }
61.1 --- a/src/jdk/nashorn/internal/runtime/Debug.java Wed Oct 08 14:16:54 2014 -0700 61.2 +++ b/src/jdk/nashorn/internal/runtime/Debug.java Tue Oct 14 10:20:24 2014 -0700 61.3 @@ -26,7 +26,6 @@ 61.4 package jdk.nashorn.internal.runtime; 61.5 61.6 import static jdk.nashorn.internal.parser.TokenType.EOF; 61.7 - 61.8 import jdk.nashorn.internal.parser.Lexer; 61.9 import jdk.nashorn.internal.parser.Token; 61.10 import jdk.nashorn.internal.parser.TokenStream; 61.11 @@ -42,12 +41,12 @@ 61.12 61.13 /** 61.14 * Return the topmost JavaScript frame in a stack trace 61.15 - * @param e 61.16 + * @param t throwable that contains the stack trace 61.17 * @return line describing the topmost JavaScript frame 61.18 */ 61.19 - public static String firstJSFrame(final Throwable e) { 61.20 - for (final StackTraceElement ste : e.getStackTrace()) { 61.21 - if(ECMAErrors.isScriptFrame(ste)) { 61.22 + public static String firstJSFrame(final Throwable t) { 61.23 + for (final StackTraceElement ste : t.getStackTrace()) { 61.24 + if (ECMAErrors.isScriptFrame(ste)) { 61.25 return ste.toString(); 61.26 } 61.27 }
62.1 --- a/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Wed Oct 08 14:16:54 2014 -0700 62.2 +++ b/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Tue Oct 14 10:20:24 2014 -0700 62.3 @@ -60,13 +60,13 @@ 62.4 * @param specs specializations 62.5 * @param flags {@link ScriptFunctionData} flags 62.6 */ 62.7 - FinalScriptFunctionData(final String name, final MethodHandle mh, final MethodHandle[] specs, final int flags) { 62.8 + FinalScriptFunctionData(final String name, final MethodHandle mh, final Specialization[] specs, final int flags) { 62.9 super(name, methodHandleArity(mh), flags); 62.10 62.11 addInvoker(mh); 62.12 if (specs != null) { 62.13 - for (final MethodHandle spec : specs) { 62.14 - addInvoker(spec); 62.15 + for (final Specialization spec : specs) { 62.16 + addInvoker(spec.getMethodHandle(), spec); 62.17 } 62.18 } 62.19 } 62.20 @@ -114,16 +114,25 @@ 62.21 return MethodType.genericMethodType(max + 1); 62.22 } 62.23 62.24 - private void addInvoker(final MethodHandle mh) { 62.25 + private CompiledFunction addInvoker(final MethodHandle mh, final Specialization specialization) { 62.26 assert !needsCallee(mh); 62.27 + 62.28 + final CompiledFunction invoker; 62.29 if (isConstructor(mh)) { 62.30 // only nasgen constructors: (boolean, self, args) are subject to binding a boolean newObj. isConstructor 62.31 // is too conservative a check. However, isConstructor(mh) always implies isConstructor param 62.32 assert isConstructor(); 62.33 - code.add(CompiledFunction.createBuiltInConstructor(mh)); 62.34 + invoker = CompiledFunction.createBuiltInConstructor(mh); 62.35 } else { 62.36 - code.add(new CompiledFunction(mh)); 62.37 + invoker = new CompiledFunction(mh, null, specialization); 62.38 } 62.39 + code.add(invoker); 62.40 + 62.41 + return invoker; 62.42 + } 62.43 + 62.44 + private CompiledFunction addInvoker(final MethodHandle mh) { 62.45 + return addInvoker(mh, null); 62.46 } 62.47 62.48 private static int methodHandleArity(final MethodHandle mh) {
63.1 --- a/src/jdk/nashorn/internal/runtime/FindProperty.java Wed Oct 08 14:16:54 2014 -0700 63.2 +++ b/src/jdk/nashorn/internal/runtime/FindProperty.java Tue Oct 14 10:20:24 2014 -0700 63.3 @@ -79,6 +79,8 @@ 63.4 * 63.5 * @param type type of getter, e.g. int.class if we want a function with {@code get()I} signature 63.6 * @param programPoint program point, or INVALID_PROGRAM_POINT if pessimistic 63.7 + * @param request link request 63.8 + * 63.9 * @return method handle for the getter 63.10 */ 63.11 public MethodHandle getGetter(final Class<?> type, final int programPoint, final LinkRequest request) { 63.12 @@ -102,6 +104,7 @@ 63.13 * 63.14 * @param type type of setter, e.g. int.class if we want a function with {@code set(I)V} signature 63.15 * @param strict are we in strict mode 63.16 + * @param request link request 63.17 * 63.18 * @return method handle for the getter 63.19 */
64.1 --- a/src/jdk/nashorn/internal/runtime/GlobalConstants.java Wed Oct 08 14:16:54 2014 -0700 64.2 +++ b/src/jdk/nashorn/internal/runtime/GlobalConstants.java Tue Oct 14 10:20:24 2014 -0700 64.3 @@ -358,8 +358,12 @@ 64.4 * @param c constant value 64.5 * @return method handle (with dummy receiver) that returns this constant 64.6 */ 64.7 + public static MethodHandle staticConstantGetter(final Object c) { 64.8 + return MH.dropArguments(JSType.unboxConstant(c), 0, Object.class); 64.9 + } 64.10 + 64.11 private MethodHandle constantGetter(final Object c) { 64.12 - final MethodHandle mh = MH.dropArguments(JSType.unboxConstant(c), 0, Object.class); 64.13 + final MethodHandle mh = staticConstantGetter(c); 64.14 if (log.isEnabled()) { 64.15 return MethodHandleFactory.addDebugPrintout(log, Level.FINEST, mh, "getting as constant"); 64.16 }
65.1 --- a/src/jdk/nashorn/internal/runtime/GlobalFunctions.java Wed Oct 08 14:16:54 2014 -0700 65.2 +++ b/src/jdk/nashorn/internal/runtime/GlobalFunctions.java Tue Oct 14 10:20:24 2014 -0700 65.3 @@ -42,12 +42,30 @@ 65.4 /** Methodhandle (specialized) to implementation of ECMA 15.1.2.2, parseInt */ 65.5 public static final MethodHandle PARSEINT_OI = findOwnMH("parseInt", double.class, Object.class, Object.class, int.class); 65.6 65.7 + /** ParseInt - NaN for booleans (thru string conversion to number conversion) */ 65.8 + public static final MethodHandle PARSEINT_Z = MH.dropArguments(MH.dropArguments(MH.constant(double.class, Double.NaN), 0, boolean.class), 0, Object.class); 65.9 + 65.10 + /** ParseInt - identity for ints */ 65.11 + public static final MethodHandle PARSEINT_I = MH.dropArguments(MH.identity(int.class), 0, Object.class); 65.12 + 65.13 + /** ParseInt - identity for longs */ 65.14 + public static final MethodHandle PARSEINT_J = MH.dropArguments(MH.identity(long.class), 0, Object.class); 65.15 + 65.16 /** Methodhandle (specialized) to implementation of ECMA 15.1.2.2, parseInt */ 65.17 public static final MethodHandle PARSEINT_O = findOwnMH("parseInt", double.class, Object.class, Object.class); 65.18 65.19 /** Methodhandle to implementation of ECMA 15.1.2.3, parseFloat */ 65.20 public static final MethodHandle PARSEFLOAT = findOwnMH("parseFloat", double.class, Object.class, Object.class); 65.21 65.22 + /** isNan for integers - always false */ 65.23 + public static final MethodHandle IS_NAN_I = MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class); 65.24 + 65.25 + /** isNan for longs - always false */ 65.26 + public static final MethodHandle IS_NAN_J = MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class); 65.27 + 65.28 + /** IsNan for doubles - use Double.isNaN */ 65.29 + public static final MethodHandle IS_NAN_D = MH.dropArguments(MH.findStatic(MethodHandles.lookup(), Double.class, "isNaN", MH.type(boolean.class, double.class)), 0, Object.class); 65.30 + 65.31 /** Methodhandle to implementation of ECMA 15.1.2.4, isNaN */ 65.32 public static final MethodHandle IS_NAN = findOwnMH("isNaN", boolean.class, Object.class, Object.class); 65.33
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 66.2 +++ b/src/jdk/nashorn/internal/runtime/OptimisticBuiltins.java Tue Oct 14 10:20:24 2014 -0700 66.3 @@ -0,0 +1,65 @@ 66.4 +/* 66.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 66.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 66.7 + * 66.8 + * This code is free software; you can redistribute it and/or modify it 66.9 + * under the terms of the GNU General Public License version 2 only, as 66.10 + * published by the Free Software Foundation. Oracle designates this 66.11 + * particular file as subject to the "Classpath" exception as provided 66.12 + * by Oracle in the LICENSE file that accompanied this code. 66.13 + * 66.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 66.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 66.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 66.17 + * version 2 for more details (a copy is included in the LICENSE file that 66.18 + * accompanied this code). 66.19 + * 66.20 + * You should have received a copy of the GNU General Public License version 66.21 + * 2 along with this work; if not, write to the Free Software Foundation, 66.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 66.23 + * 66.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 66.25 + * or visit www.oracle.com if you need additional information or have any 66.26 + * questions. 66.27 + */ 66.28 + 66.29 +package jdk.nashorn.internal.runtime; 66.30 + 66.31 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 66.32 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 66.33 + 66.34 +/** 66.35 + * This is an interface for classes that need custom linkage logic. This means Native objects 66.36 + * that contain optimistic native methods, that need special/extra rules for linking, guards and 66.37 + * SwitchPointing, known and internal to the Native object for its linkage 66.38 + */ 66.39 +public interface OptimisticBuiltins { 66.40 + 66.41 + /** 66.42 + * Return an instance of the linking logic we need for a particular LinkLogic 66.43 + * subclass, gotten from the compile time annotation of a specialized builtin method 66.44 + * No assumptions can be made about the lifetime of the instance. The receiver may 66.45 + * keep it as a perpetual final instance field or create new linking logic depending 66.46 + * on its current state for each call, depending on if the global state has changed 66.47 + * or other factors 66.48 + * 66.49 + * @param clazz linking logic class 66.50 + * @return linking logic instance for this class 66.51 + */ 66.52 + public SpecializedFunction.LinkLogic getLinkLogic(final Class<? extends LinkLogic> clazz); 66.53 + 66.54 + /** 66.55 + * Does this link logic vary depending on which instance we are working with. 66.56 + * Then we have to sort out certain primitives, as they are created as new 66.57 + * objects in the wrapFilter by JavaScript semantics. An example of instance only 66.58 + * assumptions are switchPoints per instance, as in NativeArray. NativeString is 66.59 + * fine, as it's only static. 66.60 + * 66.61 + * TODO: finer granularity on this, on the function level so certain functions 66.62 + * are forbidden only. Currently we don't have enough specialization to bump into this 66.63 + * 66.64 + * @return true if there are per instance assumptions for the optimism 66.65 + */ 66.66 + public boolean hasPerInstanceAssumptions(); 66.67 + 66.68 +}
67.1 --- a/src/jdk/nashorn/internal/runtime/Property.java Wed Oct 08 14:16:54 2014 -0700 67.2 +++ b/src/jdk/nashorn/internal/runtime/Property.java Tue Oct 14 10:20:24 2014 -0700 67.3 @@ -28,7 +28,6 @@ 67.4 import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE; 67.5 import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE; 67.6 import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE; 67.7 - 67.8 import java.io.Serializable; 67.9 import java.lang.invoke.MethodHandle; 67.10 import java.lang.invoke.SwitchPoint; 67.11 @@ -84,6 +83,9 @@ 67.12 */ 67.13 public static final int IS_NASGEN_PRIMITIVE = 1 << 6; 67.14 67.15 + /** Is this a builtin property, e.g. Function.prototype.apply */ 67.16 + public static final int IS_BUILTIN = 1 << 7; 67.17 + 67.18 /** Is this property bound to a receiver? This means get/set operations will be delegated to 67.19 * a statically defined object instead of the object passed as callsite parameter. */ 67.20 public static final int IS_BOUND = 1 << 7; 67.21 @@ -101,7 +103,7 @@ 67.22 private final int slot; 67.23 67.24 /** SwitchPoint that is invalidated when property is changed, optional */ 67.25 - protected transient SwitchPoint changeCallback; 67.26 + protected transient SwitchPoint builtinSwitchPoint; 67.27 67.28 private static final long serialVersionUID = 2099814273074501176L; 67.29 67.30 @@ -125,10 +127,10 @@ 67.31 * @param property source property 67.32 */ 67.33 Property(final Property property, final int flags) { 67.34 - this.key = property.key; 67.35 - this.slot = property.slot; 67.36 - this.changeCallback = property.changeCallback; 67.37 - this.flags = flags; 67.38 + this.key = property.key; 67.39 + this.slot = property.slot; 67.40 + this.builtinSwitchPoint = property.builtinSwitchPoint; 67.41 + this.flags = flags; 67.42 } 67.43 67.44 /** 67.45 @@ -182,8 +184,26 @@ 67.46 * changed 67.47 * @param sp SwitchPoint to use for change callback 67.48 */ 67.49 - public final void setChangeCallback(final SwitchPoint sp) { 67.50 - this.changeCallback = sp; 67.51 + public final void setBuiltinSwitchPoint(final SwitchPoint sp) { 67.52 + this.builtinSwitchPoint = sp; 67.53 + } 67.54 + 67.55 + /** 67.56 + * Builtin properties have an invalidation switchpoint that is 67.57 + * invalidated when they are set, this is a getter for it 67.58 + * @return builtin switchpoint, or null if none 67.59 + */ 67.60 + public final SwitchPoint getBuiltinSwitchPoint() { 67.61 + return builtinSwitchPoint; 67.62 + } 67.63 + 67.64 + /** 67.65 + * Checks if this is a builtin property, this means that it has 67.66 + * a builtin switchpoint that hasn't been invalidated by a setter 67.67 + * @return true if builtin, untouched (unset) property 67.68 + */ 67.69 + public boolean isBuiltin() { 67.70 + return builtinSwitchPoint != null && !builtinSwitchPoint.hasBeenInvalidated(); 67.71 } 67.72 67.73 /**
68.1 --- a/src/jdk/nashorn/internal/runtime/PropertyMap.java Wed Oct 08 14:16:54 2014 -0700 68.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java Tue Oct 14 10:20:24 2014 -0700 68.3 @@ -950,7 +950,7 @@ 68.4 68.5 @Override 68.6 public void remove() { 68.7 - throw new UnsupportedOperationException(); 68.8 + throw new UnsupportedOperationException("remove"); 68.9 } 68.10 } 68.11
69.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Oct 08 14:16:54 2014 -0700 69.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Tue Oct 14 10:20:24 2014 -0700 69.3 @@ -31,6 +31,7 @@ 69.4 import java.lang.invoke.MethodHandle; 69.5 import java.lang.invoke.MethodHandles; 69.6 import java.lang.invoke.MethodType; 69.7 +import java.util.Collection; 69.8 import java.util.Collections; 69.9 import java.util.HashMap; 69.10 import java.util.HashSet; 69.11 @@ -268,7 +269,7 @@ 69.12 if (this.source == null && this.installer == null) { 69.13 this.source = src; 69.14 this.installer = inst; 69.15 - } else if (this.source != src || this.installer != inst) { 69.16 + } else if (this.source != src || !this.installer.isCompatibleWith(inst)) { 69.17 // Existing values must be same as those passed as parameters 69.18 throw new IllegalArgumentException(); 69.19 } 69.20 @@ -407,6 +408,17 @@ 69.21 return getCompiler(fn, actualCallSiteType, newLocals(runtimeScope), null, null); 69.22 } 69.23 69.24 + /** 69.25 + * Returns a code installer for installing new code. If we're using either optimistic typing or loader-per-compile, 69.26 + * then asks for a code installer with a new class loader; otherwise just uses the current installer. We use 69.27 + * a new class loader with optimistic typing so that deoptimized code can get reclaimed by GC. 69.28 + * @return a code installer for installing new code. 69.29 + */ 69.30 + private CodeInstaller<ScriptEnvironment> getInstallerForNewCode() { 69.31 + final ScriptEnvironment env = installer.getOwner(); 69.32 + return env._optimistic_types || env._loader_per_compile ? installer.withNewLoader() : installer; 69.33 + } 69.34 + 69.35 Compiler getCompiler(final FunctionNode functionNode, final MethodType actualCallSiteType, 69.36 final ScriptObject runtimeScope, final Map<Integer, Type> invalidatedProgramPoints, 69.37 final int[] continuationEntryPoints) { 69.38 @@ -417,7 +429,7 @@ 69.39 return new Compiler( 69.40 context, 69.41 context.getEnv(), 69.42 - installer, 69.43 + getInstallerForNewCode(), 69.44 functionNode.getSource(), // source 69.45 context.getErrorManager(), 69.46 isStrict() | functionNode.isStrict(), // is strict 69.47 @@ -454,7 +466,7 @@ 69.48 // CompilationEnvironment#declareLocalSymbol()). 69.49 69.50 if (log.isEnabled()) { 69.51 - log.info("Type specialization of '", functionName, "' signature: ", actualCallSiteType); 69.52 + log.info("Parameter type specialization of '", functionName, "' signature: ", actualCallSiteType); 69.53 } 69.54 69.55 final boolean persistentCache = usePersistentCodeCache() && persist; 69.56 @@ -463,11 +475,12 @@ 69.57 final TypeMap typeMap = typeMap(actualCallSiteType); 69.58 final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId); 69.59 cacheKey = CodeStore.getCacheKey(functionNodeId, paramTypes); 69.60 - final StoredScript script = installer.loadScript(source, cacheKey); 69.61 + final CodeInstaller<ScriptEnvironment> newInstaller = getInstallerForNewCode(); 69.62 + final StoredScript script = newInstaller.loadScript(source, cacheKey); 69.63 69.64 if (script != null) { 69.65 Compiler.updateCompilationId(script.getCompilationId()); 69.66 - return install(script); 69.67 + return installStoredScript(script, newInstaller); 69.68 } 69.69 } 69.70 69.71 @@ -481,15 +494,7 @@ 69.72 return new FunctionInitializer(compiledFn, compiler.getInvalidatedProgramPoints()); 69.73 } 69.74 69.75 - 69.76 - /** 69.77 - * Install this script using the given {@code installer}. 69.78 - * 69.79 - * @param script the compiled script 69.80 - * @return the function initializer 69.81 - */ 69.82 - private FunctionInitializer install(final StoredScript script) { 69.83 - 69.84 + private static Map<String, Class<?>> installStoredScriptClasses(final StoredScript script, final CodeInstaller<ScriptEnvironment> installer) { 69.85 final Map<String, Class<?>> installedClasses = new HashMap<>(); 69.86 final Map<String, byte[]> classBytes = script.getClassBytes(); 69.87 final String mainClassName = script.getMainClassName(); 69.88 @@ -501,14 +506,25 @@ 69.89 69.90 for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) { 69.91 final String className = entry.getKey(); 69.92 - final byte[] code = entry.getValue(); 69.93 + final byte[] bytecode = entry.getValue(); 69.94 69.95 if (className.equals(mainClassName)) { 69.96 continue; 69.97 } 69.98 69.99 - installedClasses.put(className, installer.install(className, code)); 69.100 + installedClasses.put(className, installer.install(className, bytecode)); 69.101 } 69.102 + return installedClasses; 69.103 + } 69.104 + 69.105 + /** 69.106 + * Install this script using the given {@code installer}. 69.107 + * 69.108 + * @param script the compiled script 69.109 + * @return the function initializer 69.110 + */ 69.111 + private FunctionInitializer installStoredScript(final StoredScript script, final CodeInstaller<ScriptEnvironment> newInstaller) { 69.112 + final Map<String, Class<?>> installedClasses = installStoredScriptClasses(script, newInstaller); 69.113 69.114 final Map<Integer, FunctionInitializer> initializers = script.getInitializers(); 69.115 assert initializers != null; 69.116 @@ -523,7 +539,7 @@ 69.117 } 69.118 } 69.119 69.120 - installer.initialize(installedClasses.values(), source, constants); 69.121 + newInstaller.initialize(installedClasses.values(), source, constants); 69.122 initializer.setCode(installedClasses.get(initializer.getClassName())); 69.123 return initializer; 69.124 } 69.125 @@ -588,15 +604,19 @@ 69.126 return lookupCodeMethod(fn.getCompileUnit().getCode(), type); 69.127 } 69.128 69.129 - MethodHandle lookupCodeMethod(final Class<?> code, final MethodType targetType) { 69.130 - log.info("Looking up ", DebugLogger.quote(name), " type=", targetType); 69.131 - return MH.findStatic(LOOKUP, code, functionName, targetType); 69.132 + MethodHandle lookupCodeMethod(final Class<?> codeClass, final MethodType targetType) { 69.133 + if (log.isEnabled()) { 69.134 + log.info("Looking up ", DebugLogger.quote(name), " type=", targetType); 69.135 + } 69.136 + return MH.findStatic(LOOKUP, codeClass, functionName, targetType); 69.137 } 69.138 69.139 /** 69.140 * Initializes this function data with the eagerly generated version of the code. This method can only be invoked 69.141 * by the compiler internals in Nashorn and is public for implementation reasons only. Attempting to invoke it 69.142 * externally will result in an exception. 69.143 + * 69.144 + * @param initializer FunctionInitializer for this data 69.145 */ 69.146 public void initializeCode(final FunctionInitializer initializer) { 69.147 // Since the method is public, we double-check that we aren't invoked with an inappropriate compile unit. 69.148 @@ -658,8 +678,8 @@ 69.149 69.150 69.151 @Override 69.152 - synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope) { 69.153 - CompiledFunction existingBest = super.getBest(callSiteType, runtimeScope); 69.154 + synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) { 69.155 + CompiledFunction existingBest = super.getBest(callSiteType, runtimeScope, forbidden); 69.156 if (existingBest == null) { 69.157 existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope, true), callSiteType); 69.158 } 69.159 @@ -723,6 +743,10 @@ 69.160 return functionNodeId; 69.161 } 69.162 69.163 + /** 69.164 + * Get the source for the script 69.165 + * @return source 69.166 + */ 69.167 public Source getSource() { 69.168 return source; 69.169 }
70.1 --- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Wed Oct 08 14:16:54 2014 -0700 70.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Tue Oct 14 10:20:24 2014 -0700 70.3 @@ -181,9 +181,6 @@ 70.4 /** print symbols and their contents for the script */ 70.5 public final boolean _print_symbols; 70.6 70.7 - /** range analysis for known types */ 70.8 - public final boolean _range_analysis; 70.9 - 70.10 /** is this environment in scripting mode? */ 70.11 public final boolean _scripting; 70.12 70.13 @@ -255,7 +252,6 @@ 70.14 _print_parse = options.getBoolean("print.parse"); 70.15 _print_lower_parse = options.getBoolean("print.lower.parse"); 70.16 _print_symbols = options.getBoolean("print.symbols"); 70.17 - _range_analysis = options.getBoolean("range.analysis"); 70.18 _scripting = options.getBoolean("scripting"); 70.19 _strict = options.getBoolean("strict"); 70.20 _version = options.getBoolean("version");
71.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Oct 08 14:16:54 2014 -0700 71.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java Tue Oct 14 10:20:24 2014 -0700 71.3 @@ -30,26 +30,29 @@ 71.4 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 71.5 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 71.6 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 71.7 - 71.8 import java.lang.invoke.MethodHandle; 71.9 import java.lang.invoke.MethodHandles; 71.10 import java.lang.invoke.MethodType; 71.11 import java.lang.invoke.SwitchPoint; 71.12 +import java.util.ArrayList; 71.13 +import java.util.Arrays; 71.14 +import java.util.Collection; 71.15 import java.util.Collections; 71.16 - 71.17 +import java.util.HashSet; 71.18 +import java.util.List; 71.19 import jdk.internal.dynalink.CallSiteDescriptor; 71.20 import jdk.internal.dynalink.linker.GuardedInvocation; 71.21 import jdk.internal.dynalink.linker.LinkRequest; 71.22 import jdk.internal.dynalink.support.Guards; 71.23 import jdk.nashorn.internal.codegen.ApplySpecialization; 71.24 +import jdk.nashorn.internal.codegen.Compiler; 71.25 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 71.26 import jdk.nashorn.internal.objects.Global; 71.27 import jdk.nashorn.internal.objects.NativeFunction; 71.28 -import jdk.nashorn.internal.runtime.ScriptFunctionData; 71.29 -import jdk.nashorn.internal.runtime.ScriptObject; 71.30 -import jdk.nashorn.internal.runtime.ScriptRuntime; 71.31 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 71.32 import jdk.nashorn.internal.runtime.linker.Bootstrap; 71.33 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; 71.34 +import jdk.nashorn.internal.runtime.logging.DebugLogger; 71.35 71.36 /** 71.37 * Runtime representation of a JavaScript function. 71.38 @@ -114,7 +117,7 @@ 71.39 final MethodHandle methodHandle, 71.40 final PropertyMap map, 71.41 final ScriptObject scope, 71.42 - final MethodHandle[] specs, 71.43 + final Specialization[] specs, 71.44 final int flags) { 71.45 71.46 this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope); 71.47 @@ -468,13 +471,12 @@ 71.48 protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) { 71.49 final MethodType type = desc.getMethodType(); 71.50 assert desc.getMethodType().returnType() == Object.class && !NashornCallSiteDescriptor.isOptimistic(desc); 71.51 - final CompiledFunction cf = data.getBestConstructor(type, scope); 71.52 + final CompiledFunction cf = data.getBestConstructor(type, scope, CompiledFunction.NO_FUNCTIONS); 71.53 final GuardedInvocation bestCtorInv = cf.createConstructorInvocation(); 71.54 //TODO - ClassCastException 71.55 return new GuardedInvocation(pairArguments(bestCtorInv.getInvocation(), type), getFunctionGuard(this, cf.getFlags()), bestCtorInv.getSwitchPoints(), null); 71.56 } 71.57 71.58 - @SuppressWarnings("unused") 71.59 private static Object wrapFilter(final Object obj) { 71.60 if (obj instanceof ScriptObject || !ScriptFunctionData.isPrimitiveThis(obj)) { 71.61 return obj; 71.62 @@ -490,6 +492,35 @@ 71.63 } 71.64 71.65 /** 71.66 + * Some receivers are primitive, in that case, according to the Spec we create a new 71.67 + * native object per callsite with the wrap filter. We can only apply optimistic builtins 71.68 + * if there is no per instance state saved for these wrapped objects (e.g. currently NativeStrings), 71.69 + * otherwise we can't create optimistic versions 71.70 + * 71.71 + * @param self receiver 71.72 + * @param linkLogicClass linkLogicClass, or null if no link logic exists 71.73 + * @return link logic instance, or null if one could not be constructed for this receiver 71.74 + */ 71.75 + private static LinkLogic getLinkLogic(final Object self, final Class<? extends LinkLogic> linkLogicClass) { 71.76 + if (linkLogicClass == null) { 71.77 + return LinkLogic.EMPTY_INSTANCE; //always OK to link this, specialization but without special linking logic 71.78 + } 71.79 + 71.80 + if (!Context.getContextTrusted().getEnv()._optimistic_types) { 71.81 + return null; //if optimistic types are off, optimistic builtins are too 71.82 + } 71.83 + 71.84 + final Object wrappedSelf = wrapFilter(self); 71.85 + if (wrappedSelf instanceof OptimisticBuiltins) { 71.86 + if (wrappedSelf != self && ((OptimisticBuiltins)wrappedSelf).hasPerInstanceAssumptions()) { 71.87 + return null; //pessimistic - we created a wrapped object different from the primitive, but the assumptions have instance state 71.88 + } 71.89 + return ((OptimisticBuiltins)wrappedSelf).getLinkLogic(linkLogicClass); 71.90 + } 71.91 + return null; 71.92 + } 71.93 + 71.94 + /** 71.95 * dyn:call call site signature: (callee, thiz, [args...]) 71.96 * generated method signature: (callee, thiz, [args...]) 71.97 * 71.98 @@ -547,8 +578,53 @@ 71.99 } 71.100 } //else just fall through and link as ordinary function or unstable apply 71.101 71.102 - final int programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ? NashornCallSiteDescriptor.getProgramPoint(desc) : INVALID_PROGRAM_POINT; 71.103 - final CompiledFunction cf = data.getBestInvoker(type, scope); 71.104 + int programPoint = INVALID_PROGRAM_POINT; 71.105 + if (NashornCallSiteDescriptor.isOptimistic(desc)) { 71.106 + programPoint = NashornCallSiteDescriptor.getProgramPoint(desc); 71.107 + } 71.108 + 71.109 + CompiledFunction cf = data.getBestInvoker(type, scope, CompiledFunction.NO_FUNCTIONS); 71.110 + final Object self = request.getArguments()[1]; 71.111 + final Collection<CompiledFunction> forbidden = new HashSet<>(); 71.112 + 71.113 + //check for special fast versions of the compiled function 71.114 + final List<SwitchPoint> sps = new ArrayList<>(); 71.115 + Class<? extends Throwable> exceptionGuard = null; 71.116 + 71.117 + while (cf.isSpecialization()) { 71.118 + final Class<? extends LinkLogic> linkLogicClass = cf.getLinkLogicClass(); 71.119 + //if linklogic is null, we can always link with the standard mechanism, it's still a specialization 71.120 + final LinkLogic linkLogic = getLinkLogic(self, linkLogicClass); 71.121 + 71.122 + if (linkLogic != null && linkLogic.checkLinkable(self, desc, request)) { 71.123 + final DebugLogger log = Context.getContextTrusted().getLogger(Compiler.class); 71.124 + 71.125 + if (log.isEnabled()) { 71.126 + log.info("Linking optimistic builtin function: '", name, "' args=", Arrays.toString(request.getArguments()), " desc=", desc); 71.127 + } 71.128 + 71.129 + final SwitchPoint[] msps = linkLogic.getModificationSwitchPoints(); 71.130 + if (msps != null) { 71.131 + for (final SwitchPoint sp : msps) { 71.132 + if (sp != null) { 71.133 + assert !sp.hasBeenInvalidated(); 71.134 + sps.add(sp); 71.135 + } 71.136 + } 71.137 + } 71.138 + 71.139 + exceptionGuard = linkLogic.getRelinkException(); 71.140 + 71.141 + break; 71.142 + } 71.143 + 71.144 + //could not link this specialization because link check failed 71.145 + forbidden.add(cf); 71.146 + final CompiledFunction oldCf = cf; 71.147 + cf = data.getBestInvoker(type, scope, forbidden); 71.148 + assert oldCf != cf; 71.149 + } 71.150 + 71.151 final GuardedInvocation bestInvoker = cf.createFunctionInvocation(type.returnType(), programPoint); 71.152 final MethodHandle callHandle = bestInvoker.getInvocation(); 71.153 71.154 @@ -588,7 +664,20 @@ 71.155 71.156 boundHandle = pairArguments(boundHandle, type); 71.157 71.158 - return new GuardedInvocation(boundHandle, guard == null ? getFunctionGuard(this, cf.getFlags()) : guard, bestInvoker.getSwitchPoints(), null); 71.159 + if (bestInvoker.getSwitchPoints() != null) { 71.160 + sps.addAll(Arrays.asList(bestInvoker.getSwitchPoints())); 71.161 + } 71.162 + final SwitchPoint[] spsArray = sps.isEmpty() ? null : sps.toArray(new SwitchPoint[sps.size()]); 71.163 + 71.164 + return new GuardedInvocation( 71.165 + boundHandle, 71.166 + guard == null ? 71.167 + getFunctionGuard( 71.168 + this, 71.169 + cf.getFlags()) : 71.170 + guard, 71.171 + spsArray, 71.172 + exceptionGuard); 71.173 } 71.174 71.175 private GuardedInvocation createApplyOrCallCall(final boolean isApply, final CallSiteDescriptor desc, final LinkRequest request, final Object[] args) { 71.176 @@ -610,7 +699,7 @@ 71.177 71.178 //box call back to apply 71.179 CallSiteDescriptor appliedDesc = desc; 71.180 - final SwitchPoint applyToCallSwitchPoint = Global.instance().getChangeCallback("apply"); 71.181 + final SwitchPoint applyToCallSwitchPoint = Global.getBuiltinFunctionApplySwitchPoint(); 71.182 //enough to change the proto switchPoint here 71.183 71.184 final boolean isApplyToCall = NashornCallSiteDescriptor.isApplyToCall(desc); 71.185 @@ -656,7 +745,7 @@ 71.186 } 71.187 } 71.188 71.189 - appliedDesc = appliedDesc.changeMethodType(appliedType); 71.190 + appliedDesc = appliedDesc.changeMethodType(appliedType); //no extra args 71.191 71.192 // Create the same arguments for the delegate linking request that would be passed in an actual apply'd invocation 71.193 final Object[] appliedArgs = new Object[isApply ? 3 : appliedType.parameterCount()]; 71.194 @@ -681,6 +770,7 @@ 71.195 71.196 // Ask the linker machinery for an invocation of the target function 71.197 final LinkRequest appliedRequest = request.replaceArguments(appliedDesc, appliedArgs); 71.198 + 71.199 GuardedInvocation appliedInvocation; 71.200 try { 71.201 appliedInvocation = Bootstrap.getLinkerServices().getGuardedInvocation(appliedRequest); 71.202 @@ -742,7 +832,7 @@ 71.203 // We need to account for the dropped (apply|call) function argument. 71.204 guard = MH.dropArguments(guard, 0, descType.parameterType(0)); 71.205 // Take the "isApplyFunction" guard, and bind it to this function. 71.206 - MethodHandle applyFnGuard = MH.insertArguments(IS_APPLY_FUNCTION, 2, this); 71.207 + MethodHandle applyFnGuard = MH.insertArguments(IS_APPLY_FUNCTION, 2, this); //TODO replace this with switchpoint 71.208 // Adapt the guard to receive all the arguments that the original guard does. 71.209 applyFnGuard = MH.dropArguments(applyFnGuard, 2, guardType.parameterArray()); 71.210 // Fold the original function guard into our apply guard. 71.211 @@ -894,6 +984,7 @@ 71.212 return self instanceof ScriptFunction && ((ScriptFunction)self).data == data && arg instanceof ScriptObject; 71.213 } 71.214 71.215 + //TODO this can probably be removed given that we have builtin switchpoints in the context 71.216 @SuppressWarnings("unused") 71.217 private static boolean isApplyFunction(final boolean appliedFnCondition, final Object self, final Object expectedSelf) { 71.218 // NOTE: we're using self == expectedSelf as we're only using this with built-in functions apply() and call()
72.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Oct 08 14:16:54 2014 -0700 72.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Tue Oct 14 10:20:24 2014 -0700 72.3 @@ -28,13 +28,13 @@ 72.4 import static jdk.nashorn.internal.lookup.Lookup.MH; 72.5 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 72.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 72.7 - 72.8 import java.io.IOException; 72.9 import java.io.ObjectInputStream; 72.10 import java.io.Serializable; 72.11 import java.lang.invoke.MethodHandle; 72.12 import java.lang.invoke.MethodHandles; 72.13 import java.lang.invoke.MethodType; 72.14 +import java.util.Collection; 72.15 import java.util.LinkedList; 72.16 import java.util.List; 72.17 import jdk.nashorn.internal.runtime.linker.LinkerCallSite; 72.18 @@ -136,7 +136,7 @@ 72.19 final MethodHandle boundInvoker = bindInvokeHandle(originalInv.createComposableInvoker(), fn, self, args); 72.20 72.21 if (isConstructor()) { 72.22 - return new CompiledFunction(boundInvoker, bindConstructHandle(originalInv.createComposableConstructor(), fn, args)); 72.23 + return new CompiledFunction(boundInvoker, bindConstructHandle(originalInv.createComposableConstructor(), fn, args), null); 72.24 } 72.25 72.26 return new CompiledFunction(boundInvoker); 72.27 @@ -224,18 +224,22 @@ 72.28 * @param callSiteType callsite type 72.29 * @return compiled function object representing the best invoker. 72.30 */ 72.31 - final CompiledFunction getBestInvoker(final MethodType callSiteType, final ScriptObject runtimeScope) { 72.32 - final CompiledFunction cf = getBest(callSiteType, runtimeScope); 72.33 + final CompiledFunction getBestInvoker(final MethodType callSiteType, final ScriptObject runtimeScope) { 72.34 + return getBestInvoker(callSiteType, runtimeScope, CompiledFunction.NO_FUNCTIONS); 72.35 + } 72.36 + 72.37 + final CompiledFunction getBestInvoker(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) { 72.38 + final CompiledFunction cf = getBest(callSiteType, runtimeScope, forbidden); 72.39 assert cf != null; 72.40 return cf; 72.41 } 72.42 72.43 - final CompiledFunction getBestConstructor(final MethodType callSiteType, final ScriptObject runtimeScope) { 72.44 + final CompiledFunction getBestConstructor(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) { 72.45 if (!isConstructor()) { 72.46 throw typeError("not.a.constructor", toSource()); 72.47 } 72.48 // Constructor call sites don't have a "this", but getBest is meant to operate on "callee, this, ..." style 72.49 - final CompiledFunction cf = getBest(callSiteType.insertParameterTypes(1, Object.class), runtimeScope); 72.50 + final CompiledFunction cf = getBest(callSiteType.insertParameterTypes(1, Object.class), runtimeScope, forbidden); 72.51 return cf; 72.52 } 72.53 72.54 @@ -350,7 +354,7 @@ 72.55 * scope is not known, but that might cause compilation of code that will need more deoptimization passes. 72.56 * @return the best function for the specified call site type. 72.57 */ 72.58 - CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope) { 72.59 + CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) { 72.60 assert callSiteType.parameterCount() >= 2 : callSiteType; // Must have at least (callee, this) 72.61 assert callSiteType.parameterType(0).isAssignableFrom(ScriptFunction.class) : callSiteType; // Callee must be assignable from script function 72.62 72.63 @@ -363,8 +367,8 @@ 72.64 } 72.65 72.66 CompiledFunction best = null; 72.67 - for(final CompiledFunction candidate: code) { 72.68 - if(candidate.betterThanFinal(best, callSiteType)) { 72.69 + for (final CompiledFunction candidate: code) { 72.70 + if (!forbidden.contains(candidate) && candidate.betterThanFinal(best, callSiteType)) { 72.71 best = candidate; 72.72 } 72.73 } 72.74 @@ -376,7 +380,7 @@ 72.75 abstract boolean isRecompilable(); 72.76 72.77 CompiledFunction getGeneric(final ScriptObject runtimeScope) { 72.78 - return getBest(getGenericType(), runtimeScope); 72.79 + return getBest(getGenericType(), runtimeScope, CompiledFunction.NO_FUNCTIONS); 72.80 } 72.81 72.82 /** 72.83 @@ -420,7 +424,7 @@ 72.84 72.85 final List<CompiledFunction> boundList = new LinkedList<>(); 72.86 final ScriptObject runtimeScope = fn.getScope(); 72.87 - final CompiledFunction bindTarget = new CompiledFunction(getGenericInvoker(runtimeScope), getGenericConstructor(runtimeScope)); 72.88 + final CompiledFunction bindTarget = new CompiledFunction(getGenericInvoker(runtimeScope), getGenericConstructor(runtimeScope), null); 72.89 boundList.add(bind(bindTarget, fn, self, allArgs)); 72.90 72.91 return new FinalScriptFunctionData(name, Math.max(0, getArity() - length), boundList, boundFlags);
73.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Oct 08 14:16:54 2014 -0700 73.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Tue Oct 14 10:20:24 2014 -0700 73.3 @@ -47,7 +47,6 @@ 73.4 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex; 73.5 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; 73.6 import static jdk.nashorn.internal.runtime.linker.NashornGuards.explicitInstanceOfCheck; 73.7 - 73.8 import java.lang.invoke.MethodHandle; 73.9 import java.lang.invoke.MethodHandles; 73.10 import java.lang.invoke.MethodType; 73.11 @@ -820,6 +819,19 @@ 73.12 return false; 73.13 } 73.14 73.15 + private SwitchPoint findBuiltinSwitchPoint(final String key) { 73.16 + for (ScriptObject myProto = getProto(); myProto != null; myProto = myProto.getProto()) { 73.17 + final Property prop = myProto.getMap().findProperty(key); 73.18 + if (prop != null) { 73.19 + final SwitchPoint sp = prop.getBuiltinSwitchPoint(); 73.20 + if (sp != null && !sp.hasBeenInvalidated()) { 73.21 + return sp; 73.22 + } 73.23 + } 73.24 + } 73.25 + return null; 73.26 + } 73.27 + 73.28 /** 73.29 * Add a new property to the object. 73.30 * <p> 73.31 @@ -923,10 +935,10 @@ 73.32 * creating setters that probably aren't used. Inject directly into the spill pool 73.33 * the defaults for "arguments" and "caller" 73.34 * 73.35 - * @param key 73.36 - * @param propertyFlags 73.37 - * @param getter 73.38 - * @param setter 73.39 + * @param key property key 73.40 + * @param propertyFlags flags 73.41 + * @param getter getter for {@link UserAccessorProperty}, null if not present or N/A 73.42 + * @param setter setter for {@link UserAccessorProperty}, null if not present or N/A 73.43 */ 73.44 protected final void initUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) { 73.45 final int slot = spillLength; 73.46 @@ -1514,6 +1526,23 @@ 73.47 } 73.48 73.49 /** 73.50 + * Get the {@link ArrayData}, for this ScriptObject, ensuring it is of a type 73.51 + * that can handle elementType 73.52 + * @param elementType elementType 73.53 + * @return array data 73.54 + */ 73.55 + public final ArrayData getArray(final Class<?> elementType) { 73.56 + if (elementType == null) { 73.57 + return arrayData; 73.58 + } 73.59 + final ArrayData newArrayData = arrayData.convert(elementType); 73.60 + if (newArrayData != arrayData) { 73.61 + arrayData = newArrayData; 73.62 + } 73.63 + return newArrayData; 73.64 + } 73.65 + 73.66 + /** 73.67 * Get the {@link ArrayData} for this ScriptObject if it is an array 73.68 * @return array data 73.69 */ 73.70 @@ -1720,8 +1749,8 @@ 73.71 */ 73.72 public Object put(final Object key, final Object value, final boolean strict) { 73.73 final Object oldValue = get(key); 73.74 - final int flags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0; 73.75 - set(key, value, flags); 73.76 + final int scriptObjectFlags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0; 73.77 + set(key, value, scriptObjectFlags); 73.78 return oldValue; 73.79 } 73.80 73.81 @@ -1734,9 +1763,9 @@ 73.82 * @param strict strict mode or not 73.83 */ 73.84 public void putAll(final Map<?, ?> otherMap, final boolean strict) { 73.85 - final int flags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0; 73.86 + final int scriptObjectFlags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0; 73.87 for (final Map.Entry<?, ?> entry : otherMap.entrySet()) { 73.88 - set(entry.getKey(), entry.getValue(), flags); 73.89 + set(entry.getKey(), entry.getValue(), scriptObjectFlags); 73.90 } 73.91 } 73.92 73.93 @@ -1916,17 +1945,6 @@ 73.94 return MH.filterArguments(methodHandle, 0, filter.asType(filter.type().changeReturnType(methodHandle.type().parameterType(0)))); 73.95 } 73.96 73.97 - //this will only return true if apply is still builtin 73.98 - private static SwitchPoint checkReservedName(final CallSiteDescriptor desc, final LinkRequest request) { 73.99 - final boolean isApplyToCall = NashornCallSiteDescriptor.isApplyToCall(desc); 73.100 - final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 73.101 - if ("apply".equals(name) && isApplyToCall && Global.instance().isSpecialNameValid(name)) { 73.102 - assert Global.instance().getChangeCallback("apply") == Global.instance().getChangeCallback("call"); 73.103 - return Global.instance().getChangeCallback("apply"); 73.104 - } 73.105 - return null; 73.106 - } 73.107 - 73.108 /** 73.109 * Find the appropriate GET method for an invoke dynamic call. 73.110 * 73.111 @@ -1938,14 +1956,13 @@ 73.112 */ 73.113 protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) { 73.114 final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request); 73.115 - final String name; 73.116 - final SwitchPoint reservedNameSwitchPoint; 73.117 - 73.118 - reservedNameSwitchPoint = checkReservedName(desc, request); 73.119 - if (reservedNameSwitchPoint != null) { 73.120 - name = "call"; //turn apply into call, it is the builtin apply and has been modified to explode args 73.121 - } else { 73.122 - name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 73.123 + 73.124 + String name; 73.125 + name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 73.126 + if (NashornCallSiteDescriptor.isApplyToCall(desc)) { 73.127 + if (Global.isBuiltinFunctionPrototypeApply()) { 73.128 + name = "call"; 73.129 + } 73.130 } 73.131 73.132 if (request.isCallSiteUnstable() || hasWithScope()) { 73.133 @@ -2006,7 +2023,7 @@ 73.134 assert OBJECT_FIELDS_ONLY || guard != null : "we always need a map guard here"; 73.135 73.136 final GuardedInvocation inv = new GuardedInvocation(mh, guard, protoSwitchPoint, exception); 73.137 - return inv.addSwitchPoint(reservedNameSwitchPoint); 73.138 + return inv.addSwitchPoint(findBuiltinSwitchPoint(name)); 73.139 } 73.140 73.141 private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) { 73.142 @@ -2029,7 +2046,7 @@ 73.143 // Marks a property as declared and sets its value. Used as slow path for block-scoped LET and CONST 73.144 @SuppressWarnings("unused") 73.145 private void declareAndSet(final String key, final Object value) { 73.146 - final PropertyMap map = getMap(); 73.147 + final PropertyMap oldMap = getMap(); 73.148 final FindProperty find = findProperty(key, false); 73.149 assert find != null; 73.150 73.151 @@ -2037,7 +2054,7 @@ 73.152 assert property != null; 73.153 assert property.needsDeclaration(); 73.154 73.155 - final PropertyMap newMap = map.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION)); 73.156 + final PropertyMap newMap = oldMap.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION)); 73.157 setMap(newMap); 73.158 set(key, value, 0); 73.159 } 73.160 @@ -2166,7 +2183,7 @@ 73.161 } 73.162 } 73.163 73.164 - final GuardedInvocation inv = new SetMethodCreator(this, find, desc, request).createGuardedInvocation(); 73.165 + final GuardedInvocation inv = new SetMethodCreator(this, find, desc, request).createGuardedInvocation(findBuiltinSwitchPoint(name)); 73.166 73.167 final GuardedInvocation cinv = Global.getConstants().findSetMethod(find, this, inv, desc, request); 73.168 if (cinv != null) { 73.169 @@ -2429,7 +2446,7 @@ 73.170 73.171 @Override 73.172 public void remove() { 73.173 - throw new UnsupportedOperationException(); 73.174 + throw new UnsupportedOperationException("remove"); 73.175 } 73.176 } 73.177
74.1 --- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Oct 08 14:16:54 2014 -0700 74.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Tue Oct 14 10:20:24 2014 -0700 74.3 @@ -32,9 +32,9 @@ 74.4 import static jdk.nashorn.internal.runtime.ECMAErrors.syntaxError; 74.5 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 74.6 import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt; 74.7 - 74.8 import java.lang.invoke.MethodHandle; 74.9 import java.lang.invoke.MethodHandles; 74.10 +import java.lang.invoke.SwitchPoint; 74.11 import java.lang.reflect.Array; 74.12 import java.util.Collections; 74.13 import java.util.Iterator; 74.14 @@ -46,6 +46,7 @@ 74.15 import jdk.internal.dynalink.beans.StaticClass; 74.16 import jdk.nashorn.api.scripting.JSObject; 74.17 import jdk.nashorn.api.scripting.ScriptObjectMirror; 74.18 +import jdk.nashorn.internal.codegen.ApplySpecialization; 74.19 import jdk.nashorn.internal.codegen.CompilerConstants; 74.20 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 74.21 import jdk.nashorn.internal.ir.debug.JSONWriter; 74.22 @@ -113,6 +114,11 @@ 74.23 public static final Call THROW_REFERENCE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwReferenceError", void.class, String.class); 74.24 74.25 /** 74.26 + * Used to invalidate builtin names, e.g "Function" mapping to all properties in Function.prototype and Function.prototype itself. 74.27 + */ 74.28 + public static final Call INVALIDATE_RESERVED_BUILTIN_NAME = staticCallNoLookup(ScriptRuntime.class, "invalidateReservedBuiltinName", void.class, String.class); 74.29 + 74.30 + /** 74.31 * Converts a switch tag value to a simple integer. deflt value if it can't. 74.32 * 74.33 * @param tag Switch statement tag value. 74.34 @@ -290,7 +296,7 @@ 74.35 74.36 @Override 74.37 public void remove() { 74.38 - throw new UnsupportedOperationException(); 74.39 + throw new UnsupportedOperationException("remove"); 74.40 } 74.41 } 74.42 74.43 @@ -328,7 +334,7 @@ 74.44 74.45 @Override 74.46 public void remove() { 74.47 - throw new UnsupportedOperationException(); 74.48 + throw new UnsupportedOperationException("remove"); 74.49 } 74.50 }; 74.51 } 74.52 @@ -998,4 +1004,19 @@ 74.53 return nx < ny; 74.54 } 74.55 74.56 + /** 74.57 + * Tag a reserved name as invalidated - used when someone writes 74.58 + * to a property with this name - overly conservative, but link time 74.59 + * is too late to apply e.g. apply->call specialization 74.60 + * @param name property name 74.61 + */ 74.62 + public static void invalidateReservedBuiltinName(final String name) { 74.63 + final Context context = Context.getContextTrusted(); 74.64 + final SwitchPoint sp = context.getBuiltinSwitchPoint(name); 74.65 + assert sp != null; 74.66 + if (sp != null) { 74.67 + context.getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint"); 74.68 + SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 74.69 + } 74.70 + } 74.71 }
75.1 --- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Wed Oct 08 14:16:54 2014 -0700 75.2 +++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Tue Oct 14 10:20:24 2014 -0700 75.3 @@ -28,7 +28,6 @@ 75.4 import static jdk.nashorn.internal.lookup.Lookup.MH; 75.5 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; 75.6 import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex; 75.7 - 75.8 import java.lang.invoke.MethodHandle; 75.9 import java.lang.invoke.SwitchPoint; 75.10 import jdk.internal.dynalink.CallSiteDescriptor; 75.11 @@ -81,8 +80,8 @@ 75.12 * Creates the actual guarded invocation that represents the dynamic setter method for the property. 75.13 * @return the actual guarded invocation that represents the dynamic setter method for the property. 75.14 */ 75.15 - GuardedInvocation createGuardedInvocation() { 75.16 - return createSetMethod().createGuardedInvocation(); 75.17 + GuardedInvocation createGuardedInvocation(final SwitchPoint builtinSwitchPoint) { 75.18 + return createSetMethod(builtinSwitchPoint).createGuardedInvocation(); 75.19 } 75.20 75.21 /** 75.22 @@ -119,7 +118,7 @@ 75.23 } 75.24 } 75.25 75.26 - private SetMethod createSetMethod() { 75.27 + private SetMethod createSetMethod(final SwitchPoint builtinSwitchPoint) { 75.28 if (find != null) { 75.29 return createExistingPropertySetter(); 75.30 } 75.31 @@ -130,7 +129,7 @@ 75.32 return createGlobalPropertySetter(); 75.33 } 75.34 75.35 - return createNewPropertySetter(); 75.36 + return createNewPropertySetter(builtinSwitchPoint); 75.37 } 75.38 75.39 private void checkStrictCreateNewVariable() { 75.40 @@ -185,8 +184,8 @@ 75.41 return new SetMethod(MH.filterArguments(global.addSpill(type, getName()), 0, ScriptObject.GLOBALFILTER), null); 75.42 } 75.43 75.44 - private SetMethod createNewPropertySetter() { 75.45 - final SetMethod sm = map.getFreeFieldSlot() > -1 ? createNewFieldSetter() : createNewSpillPropertySetter(); 75.46 + private SetMethod createNewPropertySetter(final SwitchPoint builtinSwitchPoint) { 75.47 + final SetMethod sm = map.getFreeFieldSlot() > -1 ? createNewFieldSetter(builtinSwitchPoint) : createNewSpillPropertySetter(builtinSwitchPoint); 75.48 final PropertyListeners listeners = map.getListeners(); 75.49 if (listeners != null) { 75.50 listeners.propertyAdded(sm.property); 75.51 @@ -194,7 +193,9 @@ 75.52 return sm; 75.53 } 75.54 75.55 - private SetMethod createNewSetter(final Property property) { 75.56 + private SetMethod createNewSetter(final Property property, final SwitchPoint builtinSwitchPoint) { 75.57 + property.setBuiltinSwitchPoint(builtinSwitchPoint); 75.58 + 75.59 final PropertyMap oldMap = getMap(); 75.60 final PropertyMap newMap = getNewMap(property); 75.61 final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc); 75.62 @@ -230,12 +231,12 @@ 75.63 return new SetMethod(MH.asType(MH.guardWithTest(extCheck, casGuard, nop), fastSetter.type()), property); 75.64 } 75.65 75.66 - private SetMethod createNewFieldSetter() { 75.67 - return createNewSetter(new AccessorProperty(getName(), 0, sobj.getClass(), getMap().getFreeFieldSlot(), type)); 75.68 + private SetMethod createNewFieldSetter(final SwitchPoint builtinSwitchPoint) { 75.69 + return createNewSetter(new AccessorProperty(getName(), 0, sobj.getClass(), getMap().getFreeFieldSlot(), type), builtinSwitchPoint); 75.70 } 75.71 75.72 - private SetMethod createNewSpillPropertySetter() { 75.73 - return createNewSetter(new SpillProperty(getName(), 0, getMap().getFreeSpillSlot(), type)); 75.74 + private SetMethod createNewSpillPropertySetter(final SwitchPoint builtinSwitchPoint) { 75.75 + return createNewSetter(new SpillProperty(getName(), 0, getMap().getFreeSpillSlot(), type), builtinSwitchPoint); 75.76 } 75.77 75.78 private PropertyMap getNewMap(final Property property) {
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 76.2 +++ b/src/jdk/nashorn/internal/runtime/Specialization.java Tue Oct 14 10:20:24 2014 -0700 76.3 @@ -0,0 +1,114 @@ 76.4 +/* 76.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 76.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 76.7 + * 76.8 + * This code is free software; you can redistribute it and/or modify it 76.9 + * under the terms of the GNU General Public License version 2 only, as 76.10 + * published by the Free Software Foundation. Oracle designates this 76.11 + * particular file as subject to the "Classpath" exception as provided 76.12 + * by Oracle in the LICENSE file that accompanied this code. 76.13 + * 76.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 76.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 76.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 76.17 + * version 2 for more details (a copy is included in the LICENSE file that 76.18 + * accompanied this code). 76.19 + * 76.20 + * You should have received a copy of the GNU General Public License version 76.21 + * 2 along with this work; if not, write to the Free Software Foundation, 76.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 76.23 + * 76.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 76.25 + * or visit www.oracle.com if you need additional information or have any 76.26 + * questions. 76.27 + */ 76.28 + 76.29 +package jdk.nashorn.internal.runtime; 76.30 + 76.31 +import java.lang.invoke.MethodHandle; 76.32 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 76.33 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 76.34 + 76.35 +/** 76.36 + * Specialization info for a {@link SpecializedFunction} 76.37 + */ 76.38 +public final class Specialization { 76.39 + private final MethodHandle mh; 76.40 + private final Class<? extends LinkLogic> linkLogicClass; 76.41 + private final boolean isOptimistic; 76.42 + 76.43 + /** 76.44 + * Constructor 76.45 + * 76.46 + * @param mh invoker method handler 76.47 + */ 76.48 + public Specialization(final MethodHandle mh) { 76.49 + this(mh, false); 76.50 + } 76.51 + 76.52 + /** 76.53 + * Constructor 76.54 + * 76.55 + * @param mh invoker method handler 76.56 + * @param isOptimistic is this an optimistic native method, i.e. can it throw {@link UnwarrantedOptimismException} 76.57 + * which would have to lead to a relink and return value processing 76.58 + */ 76.59 + public Specialization(final MethodHandle mh, final boolean isOptimistic) { 76.60 + this(mh, null, isOptimistic); 76.61 + } 76.62 + 76.63 + /** 76.64 + * Constructor 76.65 + * 76.66 + * @param mh invoker method handler 76.67 + * @param linkLogicClass extra link logic needed for this function. Instances of this class also contains logic for checking 76.68 + * if this can be linked on its first encounter, which is needed as per our standard linker semantics 76.69 + * @param isOptimistic is this an optimistic native method, i.e. can it throw {@link UnwarrantedOptimismException} 76.70 + * which would have to lead to a relink and return value processing 76.71 + */ 76.72 + public Specialization(final MethodHandle mh, final Class<? extends LinkLogic> linkLogicClass, final boolean isOptimistic) { 76.73 + this.mh = mh; 76.74 + this.isOptimistic = isOptimistic; 76.75 + if (linkLogicClass != null) { 76.76 + //null out the "empty" link logic class for optimization purposes 76.77 + //we only use the empty instance because we can't default class annotations 76.78 + //to null 76.79 + this.linkLogicClass = LinkLogic.isEmpty(linkLogicClass) ? null : linkLogicClass; 76.80 + } else { 76.81 + this.linkLogicClass = null; 76.82 + } 76.83 + } 76.84 + 76.85 + /** 76.86 + * Get the method handle for the invoker of this ScriptFunction 76.87 + * @return the method handle 76.88 + */ 76.89 + public MethodHandle getMethodHandle() { 76.90 + return mh; 76.91 + } 76.92 + 76.93 + /** 76.94 + * Get the link logic class for this ScriptFunction 76.95 + * @return link logic class info, i.e. one whose instance contains stuff like 76.96 + * "do we need exception check for every call", and logic to check if we may link 76.97 + */ 76.98 + public Class<? extends LinkLogic> getLinkLogicClass() { 76.99 + return linkLogicClass; 76.100 + } 76.101 + 76.102 + /** 76.103 + * An optimistic specialization is one that can throw UnwarrantedOptimismException. 76.104 + * This is allowed for native methods, as long as they are functional, i.e. don't change 76.105 + * any state between entering and throwing the UOE. Then we can re-execute a wider version 76.106 + * of the method in the continuation. Rest-of method generation for optimistic builtins is 76.107 + * of course not possible, but this approach works and fits into the same relinking 76.108 + * framework 76.109 + * 76.110 + * @return true if optimistic 76.111 + */ 76.112 + public boolean isOptimistic() { 76.113 + return isOptimistic; 76.114 + } 76.115 + 76.116 +} 76.117 +
77.1 --- a/src/jdk/nashorn/internal/runtime/StoredScript.java Wed Oct 08 14:16:54 2014 -0700 77.2 +++ b/src/jdk/nashorn/internal/runtime/StoredScript.java Tue Oct 14 10:20:24 2014 -0700 77.3 @@ -55,8 +55,10 @@ 77.4 /** 77.5 * Constructor. 77.6 * 77.7 + * @param compilationId compilation id 77.8 * @param mainClassName main class name 77.9 * @param classBytes map of class names to class bytes 77.10 + * @param initializers initializer map, id -> FunctionInitializer 77.11 * @param constants constants array 77.12 */ 77.13 public StoredScript(final int compilationId, final String mainClassName, final Map<String, byte[]> classBytes, final Map<Integer, FunctionInitializer> initializers, final Object[] constants) { 77.14 @@ -67,6 +69,10 @@ 77.15 this.initializers = initializers; 77.16 } 77.17 77.18 + /** 77.19 + * Get the compilation id for this StoredScript 77.20 + * @return compilation id 77.21 + */ 77.22 public int getCompilationId() { 77.23 return compilationId; 77.24 }
78.1 --- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Wed Oct 08 14:16:54 2014 -0700 78.2 +++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Tue Oct 14 10:20:24 2014 -0700 78.3 @@ -25,7 +25,6 @@ 78.4 78.5 package jdk.nashorn.internal.runtime; 78.6 78.7 -import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; 78.8 import static jdk.nashorn.internal.lookup.Lookup.MH; 78.9 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 78.10 import static jdk.nashorn.internal.runtime.JSType.CONVERT_OBJECT_OPTIMISTIC;
79.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Wed Oct 08 14:16:54 2014 -0700 79.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Tue Oct 14 10:20:24 2014 -0700 79.3 @@ -26,7 +26,6 @@ 79.4 package jdk.nashorn.internal.runtime.arrays; 79.5 79.6 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; 79.7 - 79.8 import java.lang.invoke.MethodHandle; 79.9 import java.lang.invoke.MethodHandles; 79.10 import java.nio.ByteBuffer; 79.11 @@ -58,7 +57,7 @@ 79.12 /** 79.13 * Length of the array data. Not necessarily length of the wrapped array. 79.14 */ 79.15 - private long length; 79.16 + protected long length; 79.17 79.18 /** 79.19 * Method handle to throw an {@link UnwarrantedOptimismException} when getting an element 79.20 @@ -520,7 +519,7 @@ 79.21 * @param type new element type 79.22 * @return new array data 79.23 */ 79.24 - protected abstract ArrayData convert(Class<?> type); 79.25 + public abstract ArrayData convert(Class<?> type); 79.26 79.27 /** 79.28 * Push an array of items to the end of the array 79.29 @@ -537,7 +536,7 @@ 79.30 final Class<?> widest = widestType(items); 79.31 79.32 ArrayData newData = convert(widest); 79.33 - long pos = newData.length(); 79.34 + long pos = newData.length; 79.35 for (final Object item : items) { 79.36 newData = newData.ensure(pos); //avoid sparse array 79.37 newData.set((int)pos++, item, strict); 79.38 @@ -655,7 +654,7 @@ 79.39 * @param size current size 79.40 * @return next size to allocate for internal array 79.41 */ 79.42 - protected static int nextSize(final int size) { 79.43 + public static int nextSize(final int size) { 79.44 return alignUp(size + 1) * 2; 79.45 } 79.46 79.47 @@ -681,6 +680,18 @@ 79.48 } 79.49 } 79.50 79.51 + /** 79.52 + * Find a fast call if one exists 79.53 + * 79.54 + * @param clazz array data class 79.55 + * @param desc callsite descriptor 79.56 + * @param request link request 79.57 + * @return fast property getter if one is found 79.58 + */ 79.59 + public GuardedInvocation findFastCallMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { 79.60 + return null; 79.61 + } 79.62 + 79.63 /** 79.64 * Find a fast property getter if one exists 79.65 *
80.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java Wed Oct 08 14:16:54 2014 -0700 80.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java Tue Oct 14 10:20:24 2014 -0700 80.3 @@ -39,7 +39,7 @@ 80.4 protected ArrayData underlying; 80.5 80.6 ArrayFilter(final ArrayData underlying) { 80.7 - super(underlying.length()); 80.8 + super(underlying.length); 80.9 this.underlying = underlying; 80.10 } 80.11 80.12 @@ -70,13 +70,13 @@ 80.13 @Override 80.14 public void shiftLeft(final int by) { 80.15 underlying.shiftLeft(by); 80.16 - setLength(underlying.length()); 80.17 + setLength(underlying.length); 80.18 } 80.19 80.20 @Override 80.21 public ArrayData shiftRight(final int by) { 80.22 underlying = underlying.shiftRight(by); 80.23 - setLength(underlying.length()); 80.24 + setLength(underlying.length); 80.25 80.26 return this; 80.27 } 80.28 @@ -84,7 +84,7 @@ 80.29 @Override 80.30 public ArrayData ensure(final long safeIndex) { 80.31 underlying = underlying.ensure(safeIndex); 80.32 - setLength(underlying.length()); 80.33 + setLength(underlying.length); 80.34 80.35 return this; 80.36 } 80.37 @@ -92,7 +92,7 @@ 80.38 @Override 80.39 public ArrayData shrink(final long newLength) { 80.40 underlying = underlying.shrink(newLength); 80.41 - setLength(underlying.length()); 80.42 + setLength(underlying.length); 80.43 80.44 return this; 80.45 } 80.46 @@ -100,7 +100,7 @@ 80.47 @Override 80.48 public ArrayData set(final int index, final Object value, final boolean strict) { 80.49 underlying = underlying.set(index, value, strict); 80.50 - setLength(underlying.length()); 80.51 + setLength(underlying.length); 80.52 80.53 return this; 80.54 } 80.55 @@ -108,7 +108,7 @@ 80.56 @Override 80.57 public ArrayData set(final int index, final int value, final boolean strict) { 80.58 underlying = underlying.set(index, value, strict); 80.59 - setLength(underlying.length()); 80.60 + setLength(underlying.length); 80.61 80.62 return this; 80.63 } 80.64 @@ -116,7 +116,7 @@ 80.65 @Override 80.66 public ArrayData set(final int index, final long value, final boolean strict) { 80.67 underlying = underlying.set(index, value, strict); 80.68 - setLength(underlying.length()); 80.69 + setLength(underlying.length); 80.70 80.71 return this; 80.72 } 80.73 @@ -124,7 +124,7 @@ 80.74 @Override 80.75 public ArrayData set(final int index, final double value, final boolean strict) { 80.76 underlying = underlying.set(index, value, strict); 80.77 - setLength(underlying.length()); 80.78 + setLength(underlying.length); 80.79 80.80 return this; 80.81 } 80.82 @@ -189,28 +189,28 @@ 80.83 @Override 80.84 public ArrayData delete(final int index) { 80.85 underlying = underlying.delete(index); 80.86 - setLength(underlying.length()); 80.87 + setLength(underlying.length); 80.88 return this; 80.89 } 80.90 80.91 @Override 80.92 public ArrayData delete(final long from, final long to) { 80.93 underlying = underlying.delete(from, to); 80.94 - setLength(underlying.length()); 80.95 + setLength(underlying.length); 80.96 return this; 80.97 } 80.98 80.99 @Override 80.100 - protected ArrayData convert(final Class<?> type) { 80.101 + public ArrayData convert(final Class<?> type) { 80.102 underlying = underlying.convert(type); 80.103 - setLength(underlying.length()); 80.104 + setLength(underlying.length); 80.105 return this; 80.106 } 80.107 80.108 @Override 80.109 public Object pop() { 80.110 final Object value = underlying.pop(); 80.111 - setLength(underlying.length()); 80.112 + setLength(underlying.length); 80.113 80.114 return value; 80.115 }
81.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Wed Oct 08 14:16:54 2014 -0700 81.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Tue Oct 14 10:20:24 2014 -0700 81.3 @@ -30,7 +30,6 @@ 81.4 import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex; 81.5 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 81.6 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; 81.7 - 81.8 import java.lang.invoke.MethodHandle; 81.9 import java.lang.invoke.MethodHandles; 81.10 import java.lang.invoke.MethodType; 81.11 @@ -77,11 +76,11 @@ 81.12 * array without reallocating, or if we are overwriting an already 81.13 * allocated element 81.14 * 81.15 - * @param index 81.16 + * @param index index to check 81.17 * @return true if we don't need to do any array reallocation to fit an element at index 81.18 */ 81.19 public final boolean hasRoomFor(final int index) { 81.20 - return has(index) || (index == length() && ensure(index) == this); 81.21 + return has(index) || (index == length && ensure(index) == this); 81.22 } 81.23 81.24 /** 81.25 @@ -116,6 +115,12 @@ 81.26 } 81.27 81.28 /** 81.29 + * Returns the type used to store an element in this array 81.30 + * @return element type 81.31 + */ 81.32 + public abstract Class<?> getElementType(); 81.33 + 81.34 + /** 81.35 * Look up a continuous array element getter 81.36 * @param get getter, sometimes combined with a has check that throws CCE on failure for relink 81.37 * @param returnType return type 81.38 @@ -175,11 +180,6 @@ 81.39 return MH.asType(setHas, setHas.type().changeParameterType(2, elementType).changeParameterType(0, clazz)); 81.40 } 81.41 81.42 - @Override 81.43 - public GuardedInvocation findFastGetMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request, final String operator) { 81.44 - return null; 81.45 - } 81.46 - 81.47 /** Fast access guard - it is impractical for JIT performance reasons to use only CCE asType as guard :-(, also we need 81.48 the null case explicitly, which is the one that CCE doesn't handle */ 81.49 protected static final MethodHandle FAST_ACCESS_GUARD = 81.50 @@ -269,4 +269,72 @@ 81.51 81.52 return null; 81.53 } 81.54 + 81.55 + /** 81.56 + * Specialization - fast push implementation 81.57 + * @param arg argument 81.58 + * @return new array length 81.59 + */ 81.60 + public long fastPush(final int arg) { 81.61 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 81.62 + } 81.63 + 81.64 + /** 81.65 + * Specialization - fast push implementation 81.66 + * @param arg argument 81.67 + * @return new array length 81.68 + */ 81.69 + public long fastPush(final long arg) { 81.70 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 81.71 + } 81.72 + 81.73 + /** 81.74 + * Specialization - fast push implementation 81.75 + * @param arg argument 81.76 + * @return new array length 81.77 + */ 81.78 + public long fastPush(final double arg) { 81.79 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 81.80 + } 81.81 + 81.82 + /** 81.83 + * Specialization - fast push implementation 81.84 + * @param arg argument 81.85 + * @return new array length 81.86 + */ 81.87 + public long fastPush(final Object arg) { 81.88 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 81.89 + } 81.90 + 81.91 + /** 81.92 + * Specialization - fast pop implementation 81.93 + * @return element value 81.94 + */ 81.95 + public int fastPopInt() { 81.96 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 81.97 + } 81.98 + 81.99 + /** 81.100 + * Specialization - fast pop implementation 81.101 + * @return element value 81.102 + */ 81.103 + public long fastPopLong() { 81.104 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 81.105 + } 81.106 + 81.107 + /** 81.108 + * Specialization - fast pop implementation 81.109 + * @return element value 81.110 + */ 81.111 + public double fastPopDouble() { 81.112 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 81.113 + } 81.114 + 81.115 + /** 81.116 + * Specialization - fast pop implementation 81.117 + * @return element value 81.118 + */ 81.119 + public Object fastPopObject() { 81.120 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 81.121 + } 81.122 }
82.1 --- a/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java Wed Oct 08 14:16:54 2014 -0700 82.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java Tue Oct 14 10:20:24 2014 -0700 82.3 @@ -26,7 +26,6 @@ 82.4 package jdk.nashorn.internal.runtime.arrays; 82.5 82.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 82.7 - 82.8 import java.lang.reflect.Array; 82.9 import jdk.nashorn.internal.runtime.BitVector; 82.10 82.11 @@ -40,7 +39,7 @@ 82.12 DeletedArrayFilter(final ArrayData underlying) { 82.13 super(underlying); 82.14 82.15 - this.deleted = new BitVector(underlying.length()); 82.16 + this.deleted = new BitVector(underlying.length); 82.17 } 82.18 82.19 @Override 82.20 @@ -80,25 +79,25 @@ 82.21 @Override 82.22 public void shiftLeft(final int by) { 82.23 super.shiftLeft(by); 82.24 - deleted.shiftLeft(by, length()); 82.25 + deleted.shiftLeft(by, length); 82.26 } 82.27 82.28 @Override 82.29 public ArrayData shiftRight(final int by) { 82.30 super.shiftRight(by); 82.31 - deleted.shiftRight(by, length()); 82.32 + deleted.shiftRight(by, length); 82.33 82.34 return this; 82.35 } 82.36 82.37 @Override 82.38 public ArrayData ensure(final long safeIndex) { 82.39 - if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) { 82.40 + if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) { 82.41 return new SparseArrayData(this, safeIndex + 1); 82.42 } 82.43 82.44 super.ensure(safeIndex); 82.45 - deleted.resize(length()); 82.46 + deleted.resize(length); 82.47 82.48 return this; 82.49 } 82.50 @@ -106,7 +105,7 @@ 82.51 @Override 82.52 public ArrayData shrink(final long newLength) { 82.53 super.shrink(newLength); 82.54 - deleted.resize(length()); 82.55 + deleted.resize(length); 82.56 82.57 return this; 82.58 } 82.59 @@ -147,7 +146,7 @@ 82.60 @Override 82.61 public ArrayData delete(final int index) { 82.62 final long longIndex = ArrayIndex.toLongIndex(index); 82.63 - assert longIndex >= 0 && longIndex < length(); 82.64 + assert longIndex >= 0 && longIndex < length; 82.65 deleted.set(longIndex); 82.66 underlying.setEmpty(index); 82.67 return this; 82.68 @@ -155,7 +154,7 @@ 82.69 82.70 @Override 82.71 public ArrayData delete(final long fromIndex, final long toIndex) { 82.72 - assert fromIndex >= 0 && fromIndex <= toIndex && toIndex < length(); 82.73 + assert fromIndex >= 0 && fromIndex <= toIndex && toIndex < length; 82.74 deleted.setRange(fromIndex, toIndex + 1); 82.75 underlying.setEmpty(fromIndex, toIndex); 82.76 return this; 82.77 @@ -163,7 +162,7 @@ 82.78 82.79 @Override 82.80 public Object pop() { 82.81 - final long index = length() - 1; 82.82 + final long index = length - 1; 82.83 82.84 if (super.has((int)index)) { 82.85 final boolean isDeleted = deleted.isSet(index); 82.86 @@ -180,7 +179,7 @@ 82.87 final ArrayData newArray = underlying.slice(from, to); 82.88 final DeletedArrayFilter newFilter = new DeletedArrayFilter(newArray); 82.89 newFilter.getDeleted().copy(deleted); 82.90 - newFilter.getDeleted().shiftLeft(from, newFilter.length()); 82.91 + newFilter.getDeleted().shiftLeft(from, newFilter.length); 82.92 82.93 return newFilter; 82.94 }
83.1 --- a/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java Wed Oct 08 14:16:54 2014 -0700 83.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java Tue Oct 14 10:20:24 2014 -0700 83.3 @@ -45,7 +45,7 @@ 83.4 if(hi < SparseArrayData.MAX_DENSE_LENGTH || underlying instanceof SparseArrayData) { 83.5 return underlying; 83.6 } 83.7 - return new SparseArrayData(underlying, underlying.length()); 83.8 + return new SparseArrayData(underlying, underlying.length); 83.9 } 83.10 83.11 private boolean isEmpty() { 83.12 @@ -93,7 +93,7 @@ 83.13 83.14 @Override 83.15 public ArrayData ensure(final long safeIndex) { 83.16 - if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) { 83.17 + if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) { 83.18 return new SparseArrayData(this, safeIndex + 1); 83.19 } 83.20 83.21 @@ -110,8 +110,9 @@ 83.22 @Override 83.23 public ArrayData shiftRight(final int by) { 83.24 super.shiftRight(by); 83.25 - lo = Math.min(length(), lo + by); 83.26 - hi = Math.min(length() - 1, hi + by); 83.27 + final long len = length; 83.28 + lo = Math.min(len, lo + by); 83.29 + hi = Math.min(len - 1, hi + by); 83.30 83.31 return isEmpty() ? getUnderlying() : this; 83.32 } 83.33 @@ -237,7 +238,7 @@ 83.34 83.35 @Override 83.36 public Object pop() { 83.37 - final int index = (int)(length() - 1); 83.38 + final int index = (int)length - 1; 83.39 if (super.has(index)) { 83.40 final boolean isDeleted = isDeleted(index); 83.41 final Object value = super.pop();
84.1 --- a/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Wed Oct 08 14:16:54 2014 -0700 84.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Tue Oct 14 10:20:24 2014 -0700 84.3 @@ -26,7 +26,6 @@ 84.4 package jdk.nashorn.internal.runtime.arrays; 84.5 84.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 84.7 - 84.8 import java.lang.invoke.MethodHandle; 84.9 import java.lang.invoke.MethodHandles; 84.10 import java.util.Arrays; 84.11 @@ -38,7 +37,7 @@ 84.12 * Implementation of {@link ArrayData} as soon as an int has been 84.13 * written to the array. This is the default data for new arrays 84.14 */ 84.15 -final class IntArrayData extends ContinuousArrayData { 84.16 +final class IntArrayData extends ContinuousArrayData implements IntElements { 84.17 /** 84.18 * The wrapped array 84.19 */ 84.20 @@ -64,9 +63,19 @@ 84.21 this.array = array; 84.22 } 84.23 84.24 + @Override 84.25 + public Class<?> getElementType() { 84.26 + return int.class; 84.27 + } 84.28 + 84.29 private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "getElem", int.class, int.class).methodHandle(); 84.30 private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "setElem", void.class, int.class, int.class).methodHandle(); 84.31 84.32 + @Override 84.33 + public Object[] asObjectArray() { 84.34 + return toObjectArray(); 84.35 + } 84.36 + 84.37 @SuppressWarnings("unused") 84.38 private int getElem(final int index) { 84.39 if (has(index)) { 84.40 @@ -96,23 +105,18 @@ 84.41 84.42 @Override 84.43 public ArrayData copy() { 84.44 - return new IntArrayData(array.clone(), (int) length()); 84.45 - } 84.46 - 84.47 - @Override 84.48 - public Object[] asObjectArray() { 84.49 - return toObjectArray(array, (int) length()); 84.50 + return new IntArrayData(array.clone(), (int)length); 84.51 } 84.52 84.53 @Override 84.54 public Object asArrayOfType(final Class<?> componentType) { 84.55 if (componentType == int.class) { 84.56 - return array.length == length() ? array.clone() : Arrays.copyOf(array, (int) length()); 84.57 + return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length); 84.58 } 84.59 return super.asArrayOfType(componentType); 84.60 } 84.61 84.62 - private static Object[] toObjectArray(final int[] array, final int length) { 84.63 + private Object[] toObjectArray() { 84.64 assert length <= array.length : "length exceeds internal array size"; 84.65 final Object[] oarray = new Object[array.length]; 84.66 84.67 @@ -123,7 +127,7 @@ 84.68 return oarray; 84.69 } 84.70 84.71 - private static double[] toDoubleArray(final int[] array, final int length) { 84.72 + private double[] toDoubleArray() { 84.73 assert length <= array.length : "length exceeds internal array size"; 84.74 final double[] darray = new double[array.length]; 84.75 84.76 @@ -134,7 +138,7 @@ 84.77 return darray; 84.78 } 84.79 84.80 - private static long[] toLongArray(final int[] array, final int length) { 84.81 + private long[] toLongArray() { 84.82 assert length <= array.length : "length exceeds internal array size"; 84.83 final long[] larray = new long[array.length]; 84.84 84.85 @@ -145,18 +149,30 @@ 84.86 return larray; 84.87 } 84.88 84.89 + private LongArrayData convertToLong() { 84.90 + return new LongArrayData(toLongArray(), (int)length); 84.91 + } 84.92 + 84.93 + private NumberArrayData convertToDouble() { 84.94 + return new NumberArrayData(toDoubleArray(), (int)length); 84.95 + } 84.96 + 84.97 + private ObjectArrayData convertToObject() { 84.98 + return new ObjectArrayData(toObjectArray(), (int)length); 84.99 + } 84.100 + 84.101 @Override 84.102 public ArrayData convert(final Class<?> type) { 84.103 if (type == Integer.class) { 84.104 return this; 84.105 } 84.106 - final int length = (int) length(); 84.107 if (type == Long.class) { 84.108 - return new LongArrayData(IntArrayData.toLongArray(array, length), length); 84.109 + return convertToLong(); 84.110 } else if (type == Double.class) { 84.111 - return new NumberArrayData(IntArrayData.toDoubleArray(array, length), length); 84.112 + return convertToDouble(); 84.113 } else { 84.114 - return new ObjectArrayData(IntArrayData.toObjectArray(array, length), length); 84.115 + assert type == null || (!Number.class.isAssignableFrom(type) && !type.isPrimitive()); 84.116 + return convertToObject(); 84.117 } 84.118 } 84.119 84.120 @@ -167,7 +183,7 @@ 84.121 84.122 @Override 84.123 public ArrayData shiftRight(final int by) { 84.124 - final ArrayData newData = ensure(by + length() - 1); 84.125 + final ArrayData newData = ensure(by + length - 1); 84.126 if (newData != this) { 84.127 newData.shiftRight(by); 84.128 return newData; 84.129 @@ -213,7 +229,7 @@ 84.130 @Override 84.131 public ArrayData set(final int index, final int value, final boolean strict) { 84.132 array[index] = value; 84.133 - setLength(Math.max(index + 1, length())); 84.134 + setLength(Math.max(index + 1, length)); 84.135 84.136 return this; 84.137 } 84.138 @@ -222,7 +238,7 @@ 84.139 public ArrayData set(final int index, final long value, final boolean strict) { 84.140 if (JSType.isRepresentableAsInt(value)) { 84.141 array[index] = JSType.toInt32(value); 84.142 - setLength(Math.max(index + 1, length())); 84.143 + setLength(Math.max(index + 1, length)); 84.144 return this; 84.145 } 84.146 84.147 @@ -233,7 +249,7 @@ 84.148 public ArrayData set(final int index, final double value, final boolean strict) { 84.149 if (JSType.isRepresentableAsInt(value)) { 84.150 array[index] = (int)(long)value; 84.151 - setLength(Math.max(index + 1, length())); 84.152 + setLength(Math.max(index + 1, length)); 84.153 return this; 84.154 } 84.155 84.156 @@ -282,7 +298,7 @@ 84.157 84.158 @Override 84.159 public boolean has(final int index) { 84.160 - return 0 <= index && index < length(); 84.161 + return 0 <= index && index < length; 84.162 } 84.163 84.164 @Override 84.165 @@ -297,11 +313,11 @@ 84.166 84.167 @Override 84.168 public Object pop() { 84.169 - if (length() == 0) { 84.170 + if (length == 0) { 84.171 return ScriptRuntime.UNDEFINED; 84.172 } 84.173 84.174 - final int newLength = (int) length() - 1; 84.175 + final int newLength = (int)length - 1; 84.176 final int elem = array[newLength]; 84.177 array[newLength] = 0; 84.178 setLength(newLength); 84.179 @@ -311,7 +327,7 @@ 84.180 84.181 @Override 84.182 public ArrayData slice(final long from, final long to) { 84.183 - final long start = from < 0 ? from + length() : from; 84.184 + final long start = from < 0 ? from + length : from; 84.185 final long newLength = to - start; 84.186 84.187 return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); 84.188 @@ -319,18 +335,18 @@ 84.189 84.190 @Override 84.191 public final ArrayData push(final boolean strict, final int item) { 84.192 - final long length = length(); 84.193 - final ArrayData newData = ensure(length); 84.194 + final long len = length; 84.195 + final ArrayData newData = ensure(len); 84.196 if (newData == this) { 84.197 - array[(int)length] = item; 84.198 + array[(int)len] = item; 84.199 return this; 84.200 } 84.201 - return newData.set((int)length, item, strict); 84.202 + return newData.set((int)len, item, strict); 84.203 } 84.204 84.205 @Override 84.206 public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 84.207 - final long oldLength = length(); 84.208 + final long oldLength = length; 84.209 final long newLength = oldLength - removed + added; 84.210 if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 84.211 throw new UnsupportedOperationException(); 84.212 @@ -355,4 +371,41 @@ 84.213 84.214 return returnValue; 84.215 } 84.216 + 84.217 + @Override 84.218 + public long fastPush(final int arg) { 84.219 + final int len = (int)length; 84.220 + if (len == array.length) { 84.221 + array = Arrays.copyOf(array, nextSize(len)); 84.222 + } 84.223 + array[len] = arg; 84.224 + return ++length; 84.225 + } 84.226 + 84.227 + //length must not be zero 84.228 + @Override 84.229 + public int fastPopInt() { 84.230 + if (length == 0) { 84.231 + throw new ClassCastException(); //relink 84.232 + } 84.233 + final int newLength = (int)--length; 84.234 + final int elem = array[newLength]; 84.235 + array[newLength] = 0; 84.236 + return elem; 84.237 + } 84.238 + 84.239 + @Override 84.240 + public long fastPopLong() { 84.241 + return fastPopInt(); 84.242 + } 84.243 + 84.244 + @Override 84.245 + public double fastPopDouble() { 84.246 + return fastPopInt(); 84.247 + } 84.248 + 84.249 + @Override 84.250 + public Object fastPopObject() { 84.251 + return fastPopInt(); 84.252 + } 84.253 }
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 85.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/IntElements.java Tue Oct 14 10:20:24 2014 -0700 85.3 @@ -0,0 +1,34 @@ 85.4 +/* 85.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 85.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 85.7 + * 85.8 + * This code is free software; you can redistribute it and/or modify it 85.9 + * under the terms of the GNU General Public License version 2 only, as 85.10 + * published by the Free Software Foundation. Oracle designates this 85.11 + * particular file as subject to the "Classpath" exception as provided 85.12 + * by Oracle in the LICENSE file that accompanied this code. 85.13 + * 85.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 85.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 85.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 85.17 + * version 2 for more details (a copy is included in the LICENSE file that 85.18 + * accompanied this code). 85.19 + * 85.20 + * You should have received a copy of the GNU General Public License version 85.21 + * 2 along with this work; if not, write to the Free Software Foundation, 85.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 85.23 + * 85.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 85.25 + * or visit www.oracle.com if you need additional information or have any 85.26 + * questions. 85.27 + */ 85.28 +package jdk.nashorn.internal.runtime.arrays; 85.29 + 85.30 +/** 85.31 + * Marker interface for any ContinuousArray with int elements 85.32 + * Used for type checks that throw ClassCastExceptions and force relinks 85.33 + * for fast NativeArray specializations of builtin methods 85.34 + */ 85.35 +public interface IntElements extends IntOrLongElements { 85.36 + //empty 85.37 +}
86.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 86.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/IntOrLongElements.java Tue Oct 14 10:20:24 2014 -0700 86.3 @@ -0,0 +1,34 @@ 86.4 +/* 86.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 86.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 86.7 + * 86.8 + * This code is free software; you can redistribute it and/or modify it 86.9 + * under the terms of the GNU General Public License version 2 only, as 86.10 + * published by the Free Software Foundation. Oracle designates this 86.11 + * particular file as subject to the "Classpath" exception as provided 86.12 + * by Oracle in the LICENSE file that accompanied this code. 86.13 + * 86.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 86.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 86.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 86.17 + * version 2 for more details (a copy is included in the LICENSE file that 86.18 + * accompanied this code). 86.19 + * 86.20 + * You should have received a copy of the GNU General Public License version 86.21 + * 2 along with this work; if not, write to the Free Software Foundation, 86.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 86.23 + * 86.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 86.25 + * or visit www.oracle.com if you need additional information or have any 86.26 + * questions. 86.27 + */ 86.28 +package jdk.nashorn.internal.runtime.arrays; 86.29 + 86.30 +/** 86.31 + * Marker interface for any ContinuousArray with int or long elements 86.32 + * Used for type checks that throw ClassCastExceptions and force relinks 86.33 + * for fast NativeArray specializations of builtin methods 86.34 + */ 86.35 +public interface IntOrLongElements extends NumericElements { 86.36 + //empty 86.37 +}
87.1 --- a/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Wed Oct 08 14:16:54 2014 -0700 87.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Tue Oct 14 10:20:24 2014 -0700 87.3 @@ -27,7 +27,6 @@ 87.4 87.5 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 87.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 87.7 - 87.8 import java.lang.invoke.MethodHandle; 87.9 import java.lang.invoke.MethodHandles; 87.10 import java.util.Arrays; 87.11 @@ -39,7 +38,7 @@ 87.12 * Implementation of {@link ArrayData} as soon as a long has been 87.13 * written to the array 87.14 */ 87.15 -final class LongArrayData extends ContinuousArrayData { 87.16 +final class LongArrayData extends ContinuousArrayData implements IntOrLongElements { 87.17 /** 87.18 * The wrapped array 87.19 */ 87.20 @@ -57,13 +56,18 @@ 87.21 } 87.22 87.23 @Override 87.24 + public Class<?> getElementType() { 87.25 + return long.class; 87.26 + } 87.27 + 87.28 + @Override 87.29 public ArrayData copy() { 87.30 - return new LongArrayData(array.clone(), (int)length()); 87.31 + return new LongArrayData(array.clone(), (int)length); 87.32 } 87.33 87.34 @Override 87.35 public Object[] asObjectArray() { 87.36 - return toObjectArray(array, (int)length()); 87.37 + return toObjectArray(array, (int)length); 87.38 } 87.39 87.40 private static Object[] toObjectArray(final long[] array, final int length) { 87.41 @@ -80,7 +84,7 @@ 87.42 @Override 87.43 public Object asArrayOfType(final Class<?> componentType) { 87.44 if (componentType == long.class) { 87.45 - return array.length == length() ? array.clone() : Arrays.copyOf(array, (int)length()); 87.46 + return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length); 87.47 } 87.48 return super.asArrayOfType(componentType); 87.49 } 87.50 @@ -101,11 +105,11 @@ 87.51 if (type == Integer.class || type == Long.class) { 87.52 return this; 87.53 } 87.54 - final int length = (int) length(); 87.55 + final int len = (int)length; 87.56 if (type == Double.class) { 87.57 - return new NumberArrayData(LongArrayData.toDoubleArray(array, length), length); 87.58 + return new NumberArrayData(LongArrayData.toDoubleArray(array, len), len); 87.59 } 87.60 - return new ObjectArrayData(LongArrayData.toObjectArray(array, length), length); 87.61 + return new ObjectArrayData(LongArrayData.toObjectArray(array, len), len); 87.62 } 87.63 87.64 @Override 87.65 @@ -115,7 +119,7 @@ 87.66 87.67 @Override 87.68 public ArrayData shiftRight(final int by) { 87.69 - final ArrayData newData = ensure(by + length() - 1); 87.70 + final ArrayData newData = ensure(by + length - 1); 87.71 if (newData != this) { 87.72 newData.shiftRight(by); 87.73 return newData; 87.74 @@ -161,14 +165,14 @@ 87.75 @Override 87.76 public ArrayData set(final int index, final int value, final boolean strict) { 87.77 array[index] = value; 87.78 - setLength(Math.max(index + 1, length())); 87.79 + setLength(Math.max(index + 1, length)); 87.80 return this; 87.81 } 87.82 87.83 @Override 87.84 public ArrayData set(final int index, final long value, final boolean strict) { 87.85 array[index] = value; 87.86 - setLength(Math.max(index + 1, length())); 87.87 + setLength(Math.max(index + 1, length)); 87.88 return this; 87.89 } 87.90 87.91 @@ -176,7 +180,7 @@ 87.92 public ArrayData set(final int index, final double value, final boolean strict) { 87.93 if (JSType.isRepresentableAsLong(value)) { 87.94 array[index] = (long)value; 87.95 - setLength(Math.max(index + 1, length())); 87.96 + setLength(Math.max(index + 1, length)); 87.97 return this; 87.98 } 87.99 return convert(Double.class).set(index, value, strict); 87.100 @@ -252,7 +256,7 @@ 87.101 87.102 @Override 87.103 public boolean has(final int index) { 87.104 - return 0 <= index && index < length(); 87.105 + return 0 <= index && index < length; 87.106 } 87.107 87.108 @Override 87.109 @@ -267,11 +271,11 @@ 87.110 87.111 @Override 87.112 public Object pop() { 87.113 - if (length() == 0) { 87.114 + if (length == 0) { 87.115 return ScriptRuntime.UNDEFINED; 87.116 } 87.117 87.118 - final int newLength = (int) (length() - 1); 87.119 + final int newLength = (int)length - 1; 87.120 final long elem = array[newLength]; 87.121 array[newLength] = 0; 87.122 setLength(newLength); 87.123 @@ -281,25 +285,25 @@ 87.124 87.125 @Override 87.126 public ArrayData slice(final long from, final long to) { 87.127 - final long start = from < 0 ? from + length() : from; 87.128 + final long start = from < 0 ? from + length : from; 87.129 final long newLength = to - start; 87.130 return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); 87.131 } 87.132 87.133 @Override 87.134 public final ArrayData push(final boolean strict, final long item) { 87.135 - final long length = length(); 87.136 - final ArrayData newData = ensure(length); 87.137 + final long len = length; 87.138 + final ArrayData newData = ensure(len); 87.139 if (newData == this) { 87.140 - array[(int)length] = item; 87.141 + array[(int)len] = item; 87.142 return this; 87.143 } 87.144 - return newData.set((int)length, item, strict); 87.145 + return newData.set((int)len, item, strict); 87.146 } 87.147 87.148 @Override 87.149 public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 87.150 - final long oldLength = length(); 87.151 + final long oldLength = length; 87.152 final long newLength = oldLength - removed + added; 87.153 if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 87.154 throw new UnsupportedOperationException(); 87.155 @@ -324,4 +328,40 @@ 87.156 87.157 return returnValue; 87.158 } 87.159 + 87.160 + @Override 87.161 + public long fastPush(final int arg) { 87.162 + return fastPush((long)arg); 87.163 + } 87.164 + 87.165 + @Override 87.166 + public long fastPush(final long arg) { 87.167 + final int len = (int)length; 87.168 + if (len == array.length) { 87.169 + array = Arrays.copyOf(array, nextSize(len)); 87.170 + } 87.171 + array[len] = arg; 87.172 + return ++length; 87.173 + } 87.174 + 87.175 + @Override 87.176 + public long fastPopLong() { 87.177 + if (length == 0) { 87.178 + throw new ClassCastException(); 87.179 + } 87.180 + final int newLength = (int)--length; 87.181 + final long elem = array[newLength]; 87.182 + array[newLength] = 0; 87.183 + return elem; 87.184 + } 87.185 + 87.186 + @Override 87.187 + public double fastPopDouble() { 87.188 + return fastPopLong(); 87.189 + } 87.190 + 87.191 + @Override 87.192 + public Object fastPopObject() { 87.193 + return fastPopLong(); 87.194 + } 87.195 }
88.1 --- a/src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java Wed Oct 08 14:16:54 2014 -0700 88.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java Tue Oct 14 10:20:24 2014 -0700 88.3 @@ -58,19 +58,19 @@ 88.4 88.5 @Override 88.6 public ArrayData convert(final Class<?> type) { 88.7 - final long length = length(); 88.8 + final long len = length; 88.9 final ArrayData arrayData; 88.10 if (type == Long.class) { 88.11 - arrayData = new LongArrayData(new long[ArrayData.nextSize((int)length)], (int)length); 88.12 + arrayData = new LongArrayData(new long[ArrayData.nextSize((int)len)], (int)len); 88.13 } else if (type == Double.class) { 88.14 - arrayData = new NumberArrayData(new double[ArrayData.nextSize((int)length)], (int)length); 88.15 + arrayData = new NumberArrayData(new double[ArrayData.nextSize((int)len)], (int)len); 88.16 } else if (type == Integer.class) { 88.17 - arrayData = new IntArrayData(new int[ArrayData.nextSize((int)length)], (int)length); 88.18 + arrayData = new IntArrayData(new int[ArrayData.nextSize((int)len)], (int)len); 88.19 } else { 88.20 assert !type.isPrimitive(); 88.21 - arrayData = new ObjectArrayData(new Object[ArrayData.nextSize((int)length)], (int)length); 88.22 + arrayData = new ObjectArrayData(new Object[ArrayData.nextSize((int)len)], (int)len); 88.23 } 88.24 - return length == 0 ? arrayData : new DeletedRangeArrayFilter(arrayData, 0, length - 1); 88.25 + return length == 0 ? arrayData : new DeletedRangeArrayFilter(arrayData, 0, len - 1); 88.26 } 88.27 88.28 @Override 88.29 @@ -90,11 +90,11 @@ 88.30 } 88.31 88.32 // Don't trample the shared EMPTY_ARRAY. 88.33 - if (length() == 0) { 88.34 - return new NoTypeArrayData(Math.max(safeIndex + 1, length())); 88.35 + if (length == 0) { 88.36 + return new NoTypeArrayData(Math.max(safeIndex + 1, length)); 88.37 } 88.38 88.39 - setLength(Math.max(safeIndex + 1, length())); 88.40 + setLength(Math.max(safeIndex + 1, length)); 88.41 return this; 88.42 } 88.43
89.1 --- a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Wed Oct 08 14:16:54 2014 -0700 89.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Tue Oct 14 10:20:24 2014 -0700 89.3 @@ -28,7 +28,6 @@ 89.4 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 89.5 import static jdk.nashorn.internal.lookup.Lookup.MH; 89.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 89.7 - 89.8 import java.lang.invoke.MethodHandle; 89.9 import java.lang.invoke.MethodHandles; 89.10 import java.util.Arrays; 89.11 @@ -38,7 +37,7 @@ 89.12 * Implementation of {@link ArrayData} as soon as a double has been 89.13 * written to the array 89.14 */ 89.15 -final class NumberArrayData extends ContinuousArrayData { 89.16 +final class NumberArrayData extends ContinuousArrayData implements NumericElements { 89.17 /** 89.18 * The wrapped array 89.19 */ 89.20 @@ -56,13 +55,18 @@ 89.21 } 89.22 89.23 @Override 89.24 + public Class<?> getElementType() { 89.25 + return double.class; 89.26 + } 89.27 + 89.28 + @Override 89.29 public ArrayData copy() { 89.30 - return new NumberArrayData(array.clone(), (int) length()); 89.31 + return new NumberArrayData(array.clone(), (int)length); 89.32 } 89.33 89.34 @Override 89.35 public Object[] asObjectArray() { 89.36 - return toObjectArray(array, (int) length()); 89.37 + return toObjectArray(array, (int)length); 89.38 } 89.39 89.40 private static Object[] toObjectArray(final double[] array, final int length) { 89.41 @@ -78,7 +82,7 @@ 89.42 @Override 89.43 public Object asArrayOfType(final Class<?> componentType) { 89.44 if(componentType == double.class) { 89.45 - return array.length == length() ? array.clone() : Arrays.copyOf(array, (int) length()); 89.46 + return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length); 89.47 } 89.48 return super.asArrayOfType(componentType); 89.49 } 89.50 @@ -86,8 +90,8 @@ 89.51 @Override 89.52 public ArrayData convert(final Class<?> type) { 89.53 if (type != Double.class && type != Integer.class && type != Long.class) { 89.54 - final int length = (int) length(); 89.55 - return new ObjectArrayData(NumberArrayData.toObjectArray(array, length), length); 89.56 + final int len = (int)length; 89.57 + return new ObjectArrayData(NumberArrayData.toObjectArray(array, len), len); 89.58 } 89.59 return this; 89.60 } 89.61 @@ -99,7 +103,7 @@ 89.62 89.63 @Override 89.64 public ArrayData shiftRight(final int by) { 89.65 - final ArrayData newData = ensure(by + length() - 1); 89.66 + final ArrayData newData = ensure(by + length - 1); 89.67 if (newData != this) { 89.68 newData.shiftRight(by); 89.69 return newData; 89.70 @@ -144,21 +148,21 @@ 89.71 @Override 89.72 public ArrayData set(final int index, final int value, final boolean strict) { 89.73 array[index] = value; 89.74 - setLength(Math.max(index + 1, length())); 89.75 + setLength(Math.max(index + 1, length)); 89.76 return this; 89.77 } 89.78 89.79 @Override 89.80 public ArrayData set(final int index, final long value, final boolean strict) { 89.81 array[index] = value; 89.82 - setLength(Math.max(index + 1, length())); 89.83 + setLength(Math.max(index + 1, length)); 89.84 return this; 89.85 } 89.86 89.87 @Override 89.88 public ArrayData set(final int index, final double value, final boolean strict) { 89.89 array[index] = value; 89.90 - setLength(Math.max(index + 1, length())); 89.91 + setLength(Math.max(index + 1, length)); 89.92 return this; 89.93 } 89.94 89.95 @@ -227,7 +231,7 @@ 89.96 89.97 @Override 89.98 public boolean has(final int index) { 89.99 - return 0 <= index && index < length(); 89.100 + return 0 <= index && index < length; 89.101 } 89.102 89.103 @Override 89.104 @@ -242,11 +246,11 @@ 89.105 89.106 @Override 89.107 public Object pop() { 89.108 - if (length() == 0) { 89.109 + if (length == 0) { 89.110 return UNDEFINED; 89.111 } 89.112 89.113 - final int newLength = (int) (length() - 1); 89.114 + final int newLength = (int)length - 1; 89.115 final double elem = array[newLength]; 89.116 array[newLength] = 0; 89.117 setLength(newLength); 89.118 @@ -255,25 +259,25 @@ 89.119 89.120 @Override 89.121 public ArrayData slice(final long from, final long to) { 89.122 - final long start = from < 0 ? from + length() : from; 89.123 + final long start = from < 0 ? from + length : from; 89.124 final long newLength = to - start; 89.125 return new NumberArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); 89.126 } 89.127 89.128 @Override 89.129 public final ArrayData push(final boolean strict, final double item) { 89.130 - final long length = length(); 89.131 - final ArrayData newData = ensure(length); 89.132 + final long len = length; 89.133 + final ArrayData newData = ensure(len); 89.134 if (newData == this) { 89.135 - array[(int)length] = item; 89.136 + array[(int)len] = item; 89.137 return this; 89.138 } 89.139 - return newData.set((int)length, item, strict); 89.140 + return newData.set((int)len, item, strict); 89.141 } 89.142 89.143 @Override 89.144 public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 89.145 - final long oldLength = length(); 89.146 + final long oldLength = length; 89.147 final long newLength = oldLength - removed + added; 89.148 if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 89.149 throw new UnsupportedOperationException(); 89.150 @@ -298,4 +302,41 @@ 89.151 89.152 return returnValue; 89.153 } 89.154 + 89.155 + @Override 89.156 + public long fastPush(final int arg) { 89.157 + return fastPush((double)arg); 89.158 + } 89.159 + 89.160 + @Override 89.161 + public long fastPush(final long arg) { 89.162 + return fastPush((double)arg); 89.163 + } 89.164 + 89.165 + @Override 89.166 + public long fastPush(final double arg) { 89.167 + final int len = (int)length; 89.168 + if (len == array.length) { 89.169 + //note that fastpush never creates spares arrays, there is nothing to gain by that - it will just use even more memory 89.170 + array = Arrays.copyOf(array, nextSize(len)); 89.171 + } 89.172 + array[len] = arg; 89.173 + return ++length; 89.174 + } 89.175 + 89.176 + @Override 89.177 + public double fastPopDouble() { 89.178 + if (length == 0) { 89.179 + throw new ClassCastException(); 89.180 + } 89.181 + final int newLength = (int)--length; 89.182 + final double elem = array[newLength]; 89.183 + array[newLength] = 0; 89.184 + return elem; 89.185 + } 89.186 + 89.187 + @Override 89.188 + public Object fastPopObject() { 89.189 + return fastPopDouble(); 89.190 + } 89.191 }
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 90.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/NumericElements.java Tue Oct 14 10:20:24 2014 -0700 90.3 @@ -0,0 +1,35 @@ 90.4 +/* 90.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 90.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 90.7 + * 90.8 + * This code is free software; you can redistribute it and/or modify it 90.9 + * under the terms of the GNU General Public License version 2 only, as 90.10 + * published by the Free Software Foundation. Oracle designates this 90.11 + * particular file as subject to the "Classpath" exception as provided 90.12 + * by Oracle in the LICENSE file that accompanied this code. 90.13 + * 90.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 90.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 90.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 90.17 + * version 2 for more details (a copy is included in the LICENSE file that 90.18 + * accompanied this code). 90.19 + * 90.20 + * You should have received a copy of the GNU General Public License version 90.21 + * 2 along with this work; if not, write to the Free Software Foundation, 90.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 90.23 + * 90.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 90.25 + * or visit www.oracle.com if you need additional information or have any 90.26 + * questions. 90.27 + */ 90.28 +package jdk.nashorn.internal.runtime.arrays; 90.29 + 90.30 +/** 90.31 + * Marker interface for any ContinuousArray with numeric elements 90.32 + * (int, long or double) 90.33 + * Used for type checks that throw ClassCastExceptions and force relinks 90.34 + * for fast NativeArray specializations of builtin methods 90.35 + */ 90.36 +public interface NumericElements { 90.37 + //empty 90.38 +}
91.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Wed Oct 08 14:16:54 2014 -0700 91.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Tue Oct 14 10:20:24 2014 -0700 91.3 @@ -26,7 +26,6 @@ 91.4 package jdk.nashorn.internal.runtime.arrays; 91.5 91.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 91.7 - 91.8 import java.lang.invoke.MethodHandle; 91.9 import java.lang.invoke.MethodHandles; 91.10 import java.util.Arrays; 91.11 @@ -57,20 +56,25 @@ 91.12 } 91.13 91.14 @Override 91.15 + public Class<?> getElementType() { 91.16 + return Object.class; 91.17 + } 91.18 + 91.19 + @Override 91.20 public ArrayData copy() { 91.21 - return new ObjectArrayData(array.clone(), (int) length()); 91.22 + return new ObjectArrayData(array.clone(), (int)length); 91.23 } 91.24 91.25 @Override 91.26 public Object[] asObjectArray() { 91.27 - return array.length == length() ? array.clone() : asObjectArrayCopy(); 91.28 + return array.length == length ? array.clone() : asObjectArrayCopy(); 91.29 } 91.30 91.31 private Object[] asObjectArrayCopy() { 91.32 - final long l = length(); 91.33 - assert l <= Integer.MAX_VALUE; 91.34 - final Object[] copy = new Object[(int)l]; 91.35 - System.arraycopy(array, 0, copy, 0, (int)l); 91.36 + final long len = length; 91.37 + assert len <= Integer.MAX_VALUE; 91.38 + final Object[] copy = new Object[(int)len]; 91.39 + System.arraycopy(array, 0, copy, 0, (int)len); 91.40 return copy; 91.41 } 91.42 91.43 @@ -86,7 +90,7 @@ 91.44 91.45 @Override 91.46 public ArrayData shiftRight(final int by) { 91.47 - final ArrayData newData = ensure(by + length() - 1); 91.48 + final ArrayData newData = ensure(by + length - 1); 91.49 if (newData != this) { 91.50 newData.shiftRight(by); 91.51 return newData; 91.52 @@ -118,28 +122,28 @@ 91.53 @Override 91.54 public ArrayData set(final int index, final Object value, final boolean strict) { 91.55 array[index] = value; 91.56 - setLength(Math.max(index + 1, length())); 91.57 + setLength(Math.max(index + 1, length)); 91.58 return this; 91.59 } 91.60 91.61 @Override 91.62 public ArrayData set(final int index, final int value, final boolean strict) { 91.63 array[index] = value; 91.64 - setLength(Math.max(index + 1, length())); 91.65 + setLength(Math.max(index + 1, length)); 91.66 return this; 91.67 } 91.68 91.69 @Override 91.70 public ArrayData set(final int index, final long value, final boolean strict) { 91.71 array[index] = value; 91.72 - setLength(Math.max(index + 1, length())); 91.73 + setLength(Math.max(index + 1, length)); 91.74 return this; 91.75 } 91.76 91.77 @Override 91.78 public ArrayData set(final int index, final double value, final boolean strict) { 91.79 array[index] = value; 91.80 - setLength(Math.max(index + 1, length())); 91.81 + setLength(Math.max(index + 1, length)); 91.82 return this; 91.83 } 91.84 91.85 @@ -216,7 +220,7 @@ 91.86 91.87 @Override 91.88 public boolean has(final int index) { 91.89 - return 0 <= index && index < length(); 91.90 + return 0 <= index && index < length; 91.91 } 91.92 91.93 @Override 91.94 @@ -232,12 +236,48 @@ 91.95 } 91.96 91.97 @Override 91.98 + public long fastPush(final int arg) { 91.99 + return fastPush((Object)arg); 91.100 + } 91.101 + 91.102 + @Override 91.103 + public long fastPush(final long arg) { 91.104 + return fastPush((Object)arg); 91.105 + } 91.106 + 91.107 + @Override 91.108 + public long fastPush(final double arg) { 91.109 + return fastPush((Object)arg); 91.110 + } 91.111 + 91.112 + @Override 91.113 + public long fastPush(final Object arg) { 91.114 + final int len = (int)length; 91.115 + if (len == array.length) { 91.116 + array = Arrays.copyOf(array, nextSize(len)); 91.117 + } 91.118 + array[len] = arg; 91.119 + return ++length; 91.120 + } 91.121 + 91.122 + @Override 91.123 + public Object fastPopObject() { 91.124 + if (length == 0) { 91.125 + return ScriptRuntime.UNDEFINED; 91.126 + } 91.127 + final int newLength = (int)--length; 91.128 + final Object elem = array[newLength]; 91.129 + array[newLength] = ScriptRuntime.EMPTY; 91.130 + return elem; 91.131 + } 91.132 + 91.133 + @Override 91.134 public Object pop() { 91.135 - if (length() == 0) { 91.136 + if (length == 0) { 91.137 return ScriptRuntime.UNDEFINED; 91.138 } 91.139 91.140 - final int newLength = (int) (length() - 1); 91.141 + final int newLength = (int)length - 1; 91.142 final Object elem = array[newLength]; 91.143 setEmpty(newLength); 91.144 setLength(newLength); 91.145 @@ -246,25 +286,25 @@ 91.146 91.147 @Override 91.148 public ArrayData slice(final long from, final long to) { 91.149 - final long start = from < 0 ? from + length() : from; 91.150 + final long start = from < 0 ? from + length : from; 91.151 final long newLength = to - start; 91.152 return new ObjectArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); 91.153 } 91.154 91.155 @Override 91.156 public ArrayData push(final boolean strict, final Object item) { 91.157 - final long length = length(); 91.158 - final ArrayData newData = ensure(length); 91.159 + final long len = length; 91.160 + final ArrayData newData = ensure(len); 91.161 if (newData == this) { 91.162 - array[(int)length] = item; 91.163 + array[(int)len] = item; 91.164 return this; 91.165 } 91.166 - return newData.set((int)length, item, strict); 91.167 + return newData.set((int)len, item, strict); 91.168 } 91.169 91.170 @Override 91.171 public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 91.172 - final long oldLength = length(); 91.173 + final long oldLength = length; 91.174 final long newLength = oldLength - removed + added; 91.175 if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 91.176 throw new UnsupportedOperationException();
92.1 --- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Wed Oct 08 14:16:54 2014 -0700 92.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Tue Oct 14 10:20:24 2014 -0700 92.3 @@ -53,28 +53,28 @@ 92.4 92.5 SparseArrayData(final ArrayData underlying, final long length, final TreeMap<Long, Object> sparseMap) { 92.6 super(length); 92.7 - assert underlying.length() <= length; 92.8 + assert underlying.length <= length; 92.9 this.underlying = underlying; 92.10 - this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length()); 92.11 + this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length); 92.12 this.sparseMap = sparseMap; 92.13 } 92.14 92.15 @Override 92.16 public ArrayData copy() { 92.17 - return new SparseArrayData(underlying.copy(), length(), new TreeMap<>(sparseMap)); 92.18 + return new SparseArrayData(underlying.copy(), length, new TreeMap<>(sparseMap)); 92.19 } 92.20 92.21 @Override 92.22 public Object[] asObjectArray() { 92.23 - final int length = (int) Math.min(length(), Integer.MAX_VALUE); 92.24 - final int underlyingLength = (int) Math.min(length, underlying.length()); 92.25 - final Object[] objArray = new Object[length]; 92.26 + final int len = (int)Math.min(length, Integer.MAX_VALUE); 92.27 + final int underlyingLength = (int)Math.min(len, underlying.length); 92.28 + final Object[] objArray = new Object[len]; 92.29 92.30 for (int i = 0; i < underlyingLength; i++) { 92.31 objArray[i] = underlying.getObject(i); 92.32 } 92.33 92.34 - Arrays.fill(objArray, underlyingLength, length, ScriptRuntime.UNDEFINED); 92.35 + Arrays.fill(objArray, underlyingLength, len, ScriptRuntime.UNDEFINED); 92.36 92.37 for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) { 92.38 final long key = entry.getKey(); 92.39 @@ -104,14 +104,14 @@ 92.40 } 92.41 92.42 sparseMap = newSparseMap; 92.43 - setLength(Math.max(length() - by, 0)); 92.44 + setLength(Math.max(length - by, 0)); 92.45 } 92.46 92.47 @Override 92.48 public ArrayData shiftRight(final int by) { 92.49 final TreeMap<Long, Object> newSparseMap = new TreeMap<>(); 92.50 - if (underlying.length() + by > maxDenseLength) { 92.51 - for (long i = maxDenseLength - by; i < underlying.length(); i++) { 92.52 + if (underlying.length + by > maxDenseLength) { 92.53 + for (long i = maxDenseLength - by; i < underlying.length; i++) { 92.54 if (underlying.has((int) i)) { 92.55 newSparseMap.put(Long.valueOf(i + by), underlying.getObject((int) i)); 92.56 } 92.57 @@ -127,23 +127,23 @@ 92.58 } 92.59 92.60 sparseMap = newSparseMap; 92.61 - setLength(length() + by); 92.62 + setLength(length + by); 92.63 92.64 return this; 92.65 } 92.66 92.67 @Override 92.68 public ArrayData ensure(final long safeIndex) { 92.69 - if (safeIndex < maxDenseLength && underlying.length() <= safeIndex) { 92.70 + if (safeIndex < maxDenseLength && underlying.length <= safeIndex) { 92.71 underlying = underlying.ensure(safeIndex); 92.72 } 92.73 - setLength(Math.max(safeIndex + 1, length())); 92.74 + setLength(Math.max(safeIndex + 1, length)); 92.75 return this; 92.76 } 92.77 92.78 @Override 92.79 public ArrayData shrink(final long newLength) { 92.80 - if (newLength < underlying.length()) { 92.81 + if (newLength < underlying.length) { 92.82 underlying = underlying.shrink(newLength); 92.83 underlying.setLength(newLength); 92.84 sparseMap.clear(); 92.85 @@ -160,11 +160,11 @@ 92.86 if (index >= 0 && index < maxDenseLength) { 92.87 ensure(index); 92.88 underlying = underlying.set(index, value, strict); 92.89 - setLength(Math.max(underlying.length(), length())); 92.90 + setLength(Math.max(underlying.length, length)); 92.91 } else { 92.92 final Long longIndex = indexToKey(index); 92.93 sparseMap.put(longIndex, value); 92.94 - setLength(Math.max(longIndex + 1, length())); 92.95 + setLength(Math.max(longIndex + 1, length)); 92.96 } 92.97 92.98 return this; 92.99 @@ -175,11 +175,11 @@ 92.100 if (index >= 0 && index < maxDenseLength) { 92.101 ensure(index); 92.102 underlying = underlying.set(index, value, strict); 92.103 - setLength(Math.max(underlying.length(), length())); 92.104 + setLength(Math.max(underlying.length, length)); 92.105 } else { 92.106 final Long longIndex = indexToKey(index); 92.107 sparseMap.put(longIndex, value); 92.108 - setLength(Math.max(longIndex + 1, length())); 92.109 + setLength(Math.max(longIndex + 1, length)); 92.110 } 92.111 return this; 92.112 } 92.113 @@ -189,11 +189,11 @@ 92.114 if (index >= 0 && index < maxDenseLength) { 92.115 ensure(index); 92.116 underlying = underlying.set(index, value, strict); 92.117 - setLength(Math.max(underlying.length(), length())); 92.118 + setLength(Math.max(underlying.length, length)); 92.119 } else { 92.120 final Long longIndex = indexToKey(index); 92.121 sparseMap.put(longIndex, value); 92.122 - setLength(Math.max(longIndex + 1, length())); 92.123 + setLength(Math.max(longIndex + 1, length)); 92.124 } 92.125 return this; 92.126 } 92.127 @@ -203,11 +203,11 @@ 92.128 if (index >= 0 && index < maxDenseLength) { 92.129 ensure(index); 92.130 underlying = underlying.set(index, value, strict); 92.131 - setLength(Math.max(underlying.length(), length())); 92.132 + setLength(Math.max(underlying.length, length)); 92.133 } else { 92.134 final Long longIndex = indexToKey(index); 92.135 sparseMap.put(longIndex, value); 92.136 - setLength(Math.max(longIndex + 1, length())); 92.137 + setLength(Math.max(longIndex + 1, length)); 92.138 } 92.139 return this; 92.140 } 92.141 @@ -294,7 +294,7 @@ 92.142 @Override 92.143 public boolean has(final int index) { 92.144 if (index >= 0 && index < maxDenseLength) { 92.145 - return index < underlying.length() && underlying.has(index); 92.146 + return index < underlying.length && underlying.has(index); 92.147 } 92.148 92.149 return sparseMap.containsKey(indexToKey(index)); 92.150 @@ -303,7 +303,7 @@ 92.151 @Override 92.152 public ArrayData delete(final int index) { 92.153 if (index >= 0 && index < maxDenseLength) { 92.154 - if (index < underlying.length()) { 92.155 + if (index < underlying.length) { 92.156 underlying = underlying.delete(index); 92.157 } 92.158 } else { 92.159 @@ -315,8 +315,8 @@ 92.160 92.161 @Override 92.162 public ArrayData delete(final long fromIndex, final long toIndex) { 92.163 - if (fromIndex < maxDenseLength && fromIndex < underlying.length()) { 92.164 - underlying = underlying.delete(fromIndex, Math.min(toIndex, underlying.length() - 1)); 92.165 + if (fromIndex < maxDenseLength && fromIndex < underlying.length) { 92.166 + underlying = underlying.delete(fromIndex, Math.min(toIndex, underlying.length - 1)); 92.167 } 92.168 if (toIndex >= maxDenseLength) { 92.169 sparseMap.subMap(fromIndex, true, toIndex, true).clear(); 92.170 @@ -329,37 +329,37 @@ 92.171 } 92.172 92.173 @Override 92.174 - protected ArrayData convert(final Class<?> type) { 92.175 + public ArrayData convert(final Class<?> type) { 92.176 underlying = underlying.convert(type); 92.177 return this; 92.178 } 92.179 92.180 @Override 92.181 public Object pop() { 92.182 - if (length() == 0) { 92.183 + if (length == 0) { 92.184 return ScriptRuntime.UNDEFINED; 92.185 } 92.186 - if (length() == underlying.length()) { 92.187 + if (length == underlying.length) { 92.188 final Object result = underlying.pop(); 92.189 - setLength(underlying.length()); 92.190 + setLength(underlying.length); 92.191 return result; 92.192 } 92.193 - setLength(length() - 1); 92.194 - final Long key = Long.valueOf(length()); 92.195 + setLength(length - 1); 92.196 + final Long key = Long.valueOf(length); 92.197 return sparseMap.containsKey(key) ? sparseMap.remove(key) : ScriptRuntime.UNDEFINED; 92.198 } 92.199 92.200 @Override 92.201 public ArrayData slice(final long from, final long to) { 92.202 - assert to <= length(); 92.203 - final long start = from < 0 ? (from + length()) : from; 92.204 + assert to <= length; 92.205 + final long start = from < 0 ? (from + length) : from; 92.206 final long newLength = to - start; 92.207 92.208 if (start >= 0 && to <= maxDenseLength) { 92.209 - if (newLength <= underlying.length()) { 92.210 + if (newLength <= underlying.length) { 92.211 return underlying.slice(from, to); 92.212 } 92.213 - return underlying.slice(from, to).ensure(newLength - 1).delete(underlying.length(), newLength); 92.214 + return underlying.slice(from, to).ensure(newLength - 1).delete(underlying.length, newLength); 92.215 } 92.216 92.217 ArrayData sliced = EMPTY_ARRAY; 92.218 @@ -369,13 +369,13 @@ 92.219 sliced = sliced.set((int)(i - start), getObject((int)i), false); 92.220 } 92.221 } 92.222 - assert sliced.length() == newLength; 92.223 + assert sliced.length == newLength; 92.224 return sliced; 92.225 } 92.226 92.227 @Override 92.228 public long nextIndex(final long index) { 92.229 - if (index < underlying.length() - 1) { 92.230 + if (index < underlying.length - 1) { 92.231 return underlying.nextIndex(index); 92.232 } 92.233 92.234 @@ -383,6 +383,6 @@ 92.235 if (nextKey != null) { 92.236 return nextKey; 92.237 } 92.238 - return length(); 92.239 + return length; 92.240 } 92.241 }
93.1 --- a/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java Wed Oct 08 14:16:54 2014 -0700 93.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java Tue Oct 14 10:20:24 2014 -0700 93.3 @@ -26,7 +26,6 @@ 93.4 package jdk.nashorn.internal.runtime.arrays; 93.5 93.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 93.7 - 93.8 import java.lang.invoke.MethodHandle; 93.9 import java.nio.Buffer; 93.10 import jdk.internal.dynalink.CallSiteDescriptor; 93.11 @@ -55,11 +54,11 @@ 93.12 } 93.13 93.14 /** 93.15 - * Length in elements. Accessed from {@code ArrayBufferView} 93.16 + * Length in number of elements. Accessed from {@code ArrayBufferView} 93.17 * @return element length 93.18 */ 93.19 public final int getElementLength() { 93.20 - return (int)length(); 93.21 + return (int)length; 93.22 } 93.23 93.24 /** 93.25 @@ -120,7 +119,7 @@ 93.26 93.27 @Override 93.28 public final boolean has(final int index) { 93.29 - return 0 <= index && index < length(); 93.30 + return 0 <= index && index < length; 93.31 } 93.32 93.33 @Override 93.34 @@ -134,7 +133,7 @@ 93.35 } 93.36 93.37 @Override 93.38 - protected ArrayData convert(final Class<?> type) { 93.39 + public ArrayData convert(final Class<?> type) { 93.40 throw new UnsupportedOperationException(); 93.41 } 93.42
94.1 --- a/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java Wed Oct 08 14:16:54 2014 -0700 94.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java Tue Oct 14 10:20:24 2014 -0700 94.3 @@ -26,7 +26,6 @@ 94.4 package jdk.nashorn.internal.runtime.arrays; 94.5 94.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 94.7 - 94.8 import java.lang.reflect.Array; 94.9 import jdk.nashorn.internal.runtime.BitVector; 94.10 import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; 94.11 @@ -41,7 +40,7 @@ 94.12 UndefinedArrayFilter(final ArrayData underlying) { 94.13 super(underlying); 94.14 94.15 - this.undefined = new BitVector(underlying.length()); 94.16 + this.undefined = new BitVector(underlying.length); 94.17 } 94.18 94.19 @Override 94.20 @@ -81,25 +80,25 @@ 94.21 @Override 94.22 public void shiftLeft(final int by) { 94.23 super.shiftLeft(by); 94.24 - undefined.shiftLeft(by, length()); 94.25 + undefined.shiftLeft(by, length); 94.26 } 94.27 94.28 @Override 94.29 public ArrayData shiftRight(final int by) { 94.30 super.shiftRight(by); 94.31 - undefined.shiftRight(by, length()); 94.32 + undefined.shiftRight(by, length); 94.33 94.34 return this; 94.35 } 94.36 94.37 @Override 94.38 public ArrayData ensure(final long safeIndex) { 94.39 - if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) { 94.40 + if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) { 94.41 return new SparseArrayData(this, safeIndex + 1); 94.42 } 94.43 94.44 super.ensure(safeIndex); 94.45 - undefined.resize(length()); 94.46 + undefined.resize(length); 94.47 94.48 return this; 94.49 } 94.50 @@ -107,7 +106,7 @@ 94.51 @Override 94.52 public ArrayData shrink(final long newLength) { 94.53 super.shrink(newLength); 94.54 - undefined.resize(length()); 94.55 + undefined.resize(length); 94.56 94.57 return this; 94.58 } 94.59 @@ -217,7 +216,7 @@ 94.60 94.61 @Override 94.62 public Object pop() { 94.63 - final long index = length() - 1; 94.64 + final long index = length - 1; 94.65 94.66 if (super.has((int)index)) { 94.67 final boolean isUndefined = undefined.isSet(index); 94.68 @@ -234,7 +233,7 @@ 94.69 final ArrayData newArray = underlying.slice(from, to); 94.70 final UndefinedArrayFilter newFilter = new UndefinedArrayFilter(newArray); 94.71 newFilter.getUndefined().copy(undefined); 94.72 - newFilter.getUndefined().shiftLeft(from, newFilter.length()); 94.73 + newFilter.getUndefined().shiftLeft(from, newFilter.length); 94.74 94.75 return newFilter; 94.76 }
95.1 --- a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Wed Oct 08 14:16:54 2014 -0700 95.2 +++ b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Tue Oct 14 10:20:24 2014 -0700 95.3 @@ -26,14 +26,16 @@ 95.4 package jdk.nashorn.internal.runtime.linker; 95.5 95.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 95.7 - 95.8 import java.lang.invoke.MethodHandle; 95.9 import java.lang.invoke.MethodType; 95.10 +import java.lang.invoke.SwitchPoint; 95.11 import jdk.internal.dynalink.CallSiteDescriptor; 95.12 import jdk.internal.dynalink.linker.GuardedInvocation; 95.13 import jdk.internal.dynalink.linker.LinkRequest; 95.14 import jdk.internal.dynalink.support.Guards; 95.15 +import jdk.nashorn.internal.runtime.Context; 95.16 import jdk.nashorn.internal.runtime.FindProperty; 95.17 +import jdk.nashorn.internal.runtime.GlobalConstants; 95.18 import jdk.nashorn.internal.runtime.ScriptObject; 95.19 import jdk.nashorn.internal.runtime.UserAccessorProperty; 95.20 95.21 @@ -86,27 +88,41 @@ 95.22 final MethodHandle protoFilter) { 95.23 final CallSiteDescriptor desc = request.getCallSiteDescriptor(); 95.24 95.25 - if(desc.getNameTokenCount() > 2) { 95.26 + //checks whether the property name is hard-coded in the call-site (i.e. a getProp vs a getElem, or setProp vs setElem) 95.27 + //if it is we can make assumptions on the property: that if it is not defined on primitive wrapper itself it never will be. 95.28 + //so in that case we can skip creation of primitive wrapper and start our search with the prototype. 95.29 + if (desc.getNameTokenCount() > 2) { 95.30 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 95.31 final FindProperty find = wrappedReceiver.findProperty(name, true); 95.32 - if(find == null) { 95.33 + 95.34 + if (find == null) { 95.35 // Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it. 95.36 return null; 95.37 - } else if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) { 95.38 + } 95.39 + 95.40 + final SwitchPoint sp = find.getProperty().getBuiltinSwitchPoint(); //can use this instead of proto filter 95.41 + if (sp instanceof Context.BuiltinSwitchPoint && !sp.hasBeenInvalidated()) { 95.42 + return new GuardedInvocation(GlobalConstants.staticConstantGetter(find.getObjectValue()), guard, sp, null); 95.43 + } 95.44 + 95.45 + if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) { 95.46 // If property is found in the prototype object bind the method handle directly to 95.47 // the proto filter instead of going through wrapper instantiation below. 95.48 final ScriptObject proto = wrappedReceiver.getProto(); 95.49 final GuardedInvocation link = proto.lookup(desc, request); 95.50 95.51 if (link != null) { 95.52 - final MethodHandle invocation = link.getInvocation(); 95.53 + final MethodHandle invocation = link.getInvocation(); //this contains the builtin switchpoint 95.54 + 95.55 final MethodHandle adaptedInvocation = MH.asType(invocation, invocation.type().changeParameterType(0, Object.class)); 95.56 final MethodHandle method = MH.filterArguments(adaptedInvocation, 0, protoFilter); 95.57 final MethodHandle protoGuard = MH.filterArguments(link.getGuard(), 0, protoFilter); 95.58 + 95.59 return new GuardedInvocation(method, NashornGuards.combineGuards(guard, protoGuard)); 95.60 } 95.61 } 95.62 } 95.63 + 95.64 final GuardedInvocation link = wrappedReceiver.lookup(desc, request); 95.65 if (link != null) { 95.66 MethodHandle method = link.getInvocation(); 95.67 @@ -116,8 +132,10 @@ 95.68 assert receiverType.isAssignableFrom(wrapType.returnType()); 95.69 method = MH.filterArguments(method, 0, MH.asType(wrapFilter, wrapType.changeReturnType(receiverType))); 95.70 } 95.71 + 95.72 return new GuardedInvocation(method, guard, link.getSwitchPoints(), null); 95.73 } 95.74 + 95.75 return null; 95.76 } 95.77 }
96.1 --- a/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java Wed Oct 08 14:16:54 2014 -0700 96.2 +++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java Tue Oct 14 10:20:24 2014 -0700 96.3 @@ -25,6 +25,9 @@ 96.4 96.5 package jdk.nashorn.internal.runtime.regexp; 96.6 96.7 +import java.util.Collections; 96.8 +import java.util.Set; 96.9 +import java.util.WeakHashMap; 96.10 import jdk.nashorn.internal.runtime.ParserException; 96.11 import jdk.nashorn.internal.runtime.options.Options; 96.12 96.13 @@ -39,6 +42,15 @@ 96.14 private final static String JDK = "jdk"; 96.15 private final static String JONI = "joni"; 96.16 96.17 + /** Weak cache of already validated regexps - when reparsing, we don't, for example 96.18 + * need to recompile (reverify) all regexps that have previously been parsed by this 96.19 + * RegExpFactory in a previous compilation. This saves significant time in e.g. avatar 96.20 + * startup */ 96.21 + private static final Set<String> VALID_CACHE_SET = 96.22 + Collections.newSetFromMap( 96.23 + Collections.synchronizedMap( 96.24 + new WeakHashMap<String, Boolean>())); 96.25 + 96.26 static { 96.27 final String impl = Options.getStringProperty("nashorn.regexp.impl", JONI); 96.28 switch (impl) { 96.29 @@ -88,7 +100,9 @@ 96.30 */ 96.31 // @SuppressWarnings({"unused"}) 96.32 public static void validate(final String pattern, final String flags) throws ParserException { 96.33 - instance.compile(pattern, flags); 96.34 + if (VALID_CACHE_SET.add(pattern + flags)) { 96.35 + instance.compile(pattern, flags); 96.36 + } 96.37 } 96.38 96.39 /**
97.1 --- a/src/jdk/nashorn/internal/runtime/resources/Options.properties Wed Oct 08 14:16:54 2014 -0700 97.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Options.properties Tue Oct 14 10:20:24 2014 -0700 97.3 @@ -203,9 +203,9 @@ 97.4 97.5 nashorn.option.optimistic.types = { \ 97.6 name="--optimistic-types", \ 97.7 - is_undocumented=true, \ 97.8 - desc="Use optimistic type assumptions with deoptimizing recompilation.", \ 97.9 - default=true \ 97.10 + short_name="-ot", \ 97.11 + desc="Use optimistic type assumptions with deoptimizing recompilation. This makes the compiler try, for any program symbol whose type cannot be proven at compile time, to type it as narrow and primitive as possible. If the runtime encounters an error because symbol type is too narrow, a wider method will be generated until steady stage is reached. While this produces as optimal Java Bytecode as possible, erroneous type guesses will lead to longer warmup. Optimistic typing is currently disabled by default, but can be enabled for significantly better peak performance.", \ 97.12 + default=false \ 97.13 } 97.14 97.15 nashorn.option.loader.per.compile = { \
98.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 98.2 +++ b/test/examples/charcodeat-benchmark.js Tue Oct 14 10:20:24 2014 -0700 98.3 @@ -0,0 +1,63 @@ 98.4 +/* 98.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 98.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 98.7 + * 98.8 + * This code is free software; you can redistribute it and/or modify it 98.9 + * under the terms of the GNU General Public License version 2 only, as 98.10 + * published by the Free Software Foundation. 98.11 + * 98.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 98.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 98.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 98.15 + * version 2 for more details (a copy is included in the LICENSE file that 98.16 + * accompanied this code). 98.17 + * 98.18 + * You should have received a copy of the GNU General Public License version 98.19 + * 2 along with this work; if not, write to the Free Software Foundation, 98.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 98.21 + * 98.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 98.23 + * or visit www.oracle.com if you need additional information or have any 98.24 + * questions. 98.25 + */ 98.26 + 98.27 +/** 98.28 + * Simple benchmark to measure charCodeAt specialized method performance 98.29 + */ 98.30 + 98.31 +var str = "sghjkdsfkjghsdfjkfkjdfkjdfjkdfjkfdjkfdkfldjfhdfpkjdhafgksdjfgldfgjldfkjgdlfjgldkfjgkldfj"; 98.32 +var RESULT1 = 9187; 98.33 +var RESULT2 = 1496; 98.34 + 98.35 +function f() { 98.36 + var len = str.length; 98.37 + var c = 0; 98.38 + for (var i = 0; i < len; i++) { 98.39 + c += str.charCodeAt(i); 98.40 + } 98.41 + return c; 98.42 +} 98.43 + 98.44 +function bench(res) { 98.45 + var d = new Date; 98.46 + var sum = 0; 98.47 + for (var i = 0; i < 1e6; i++) { 98.48 + sum |= f(); 98.49 + } 98.50 + if (sum == res) { 98.51 + print("Verified OK"); 98.52 + } else { 98.53 + print("Verification failed " + sum + " should be " + res); 98.54 + } 98.55 + print((new Date - d) + " ms"); 98.56 +} 98.57 + 98.58 +bench(RESULT1); 98.59 + 98.60 +print("Replacing charCodeAt... "); 98.61 + 98.62 +String.prototype.charCodeAt = function() { return 17; } 98.63 + 98.64 +bench(RESULT2); 98.65 + 98.66 +print("Done");
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 99.2 +++ b/test/examples/push-pop-benchmark.js Tue Oct 14 10:20:24 2014 -0700 99.3 @@ -0,0 +1,59 @@ 99.4 +/* 99.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 99.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 99.7 + * 99.8 + * This code is free software; you can redistribute it and/or modify it 99.9 + * under the terms of the GNU General Public License version 2 only, as 99.10 + * published by the Free Software Foundation. 99.11 + * 99.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 99.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 99.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 99.15 + * version 2 for more details (a copy is included in the LICENSE file that 99.16 + * accompanied this code). 99.17 + * 99.18 + * You should have received a copy of the GNU General Public License version 99.19 + * 2 along with this work; if not, write to the Free Software Foundation, 99.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 99.21 + * 99.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 99.23 + * or visit www.oracle.com if you need additional information or have any 99.24 + * questions. 99.25 + */ 99.26 + 99.27 +/** 99.28 + * Simple benchmark to measure push/pop specialized method performance 99.29 + */ 99.30 + 99.31 +var a = []; 99.32 + 99.33 +var RESULT = 15; 99.34 + 99.35 +function bench() { 99.36 + var sum = 0; 99.37 + for (var i=0;i<10;i++) { 99.38 + a.push(i); 99.39 + } 99.40 + for (var i=0;i<10;i++) { 99.41 + sum |= a.pop(); 99.42 + } 99.43 + return sum; 99.44 +} 99.45 + 99.46 +function runbench() { 99.47 + var sum = 0; 99.48 + for (var iters = 0; iters<1e8; iters++) { 99.49 + sum |= bench(); 99.50 + } 99.51 + return sum; 99.52 +} 99.53 + 99.54 +var d = new Date; 99.55 +var res = runbench(); 99.56 +print((new Date - d) + " ms"); 99.57 +print(); 99.58 +if (res != RESULT) { 99.59 + print("ERROR: Wrong result - should be " + RESULT); 99.60 +} else { 99.61 + print("Verified OK - result is correct"); 99.62 +}
100.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 100.2 +++ b/test/script/basic/apply_to_call/apply_to_call5.js Tue Oct 14 10:20:24 2014 -0700 100.3 @@ -0,0 +1,111 @@ 100.4 +/* 100.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 100.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 100.7 + * 100.8 + * This code is free software; you can redistribute it and/or modify it 100.9 + * under the terms of the GNU General Public License version 2 only, as 100.10 + * published by the Free Software Foundation. 100.11 + * 100.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 100.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 100.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 100.15 + * version 2 for more details (a copy is included in the LICENSE file that 100.16 + * accompanied this code). 100.17 + * 100.18 + * You should have received a copy of the GNU General Public License version 100.19 + * 2 along with this work; if not, write to the Free Software Foundation, 100.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 100.21 + * 100.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 100.23 + * or visit www.oracle.com if you need additional information or have any 100.24 + * questions. 100.25 + */ 100.26 + 100.27 +/** 100.28 + * apply_to_call5.js - do one apply to call specialization, then override, apply and make sure it reverts (i.e. stops 100.29 + * calling call) 100.30 + * 100.31 + * @test 100.32 + * @run 100.33 + */ 100.34 + 100.35 +print("start"); 100.36 + 100.37 +var x = { 100.38 + a : 0, 100.39 + b : 0, 100.40 + c : 0, 100.41 + initialize : function(x,y,z) { 100.42 + this.a = x; 100.43 + this.b = y; 100.44 + this.c = z; 100.45 + } 100.46 +}; 100.47 + 100.48 +function test() { 100.49 + x.initialize.apply(x, arguments); 100.50 +} 100.51 + 100.52 +test(4711,23,17); 100.53 +print(x.a); 100.54 +print(x.b); 100.55 +print(x.c); 100.56 + 100.57 +print("Overwriting apply now"); 100.58 +x.initialize.apply = function() { print("New function for apply - not a property"); } 100.59 + 100.60 +test(4712); 100.61 +print(x.a); 100.62 + 100.63 + 100.64 +var x2 = { 100.65 + a : 0, 100.66 + b : 0, 100.67 + c : 0, 100.68 + initialize : function(x,y,z) { 100.69 + this.a = x; 100.70 + this.b = y; 100.71 + this.c = z; 100.72 + } 100.73 +}; 100.74 + 100.75 +function test2() { 100.76 + x2.initialize.apply(x2, arguments); 100.77 +} 100.78 + 100.79 +test2(4711,23,17); 100.80 +print(x2.a); 100.81 +print(x2.b); 100.82 +print(x2.c); 100.83 + 100.84 +print("Overwriting apply now"); 100.85 +x2.initialize['apply'] = function() { print("New function for apply - not a property"); } 100.86 + 100.87 +test(4712); 100.88 +print(x2.a); 100.89 + 100.90 +var x3 = { 100.91 + a : 0, 100.92 + b : 0, 100.93 + c : 0, 100.94 + initialize : function(x,y,z) { 100.95 + this.a = x; 100.96 + this.b = y; 100.97 + this.c = z; 100.98 + } 100.99 +}; 100.100 + 100.101 +function test3() { 100.102 + x3.initialize.apply(x3, arguments); 100.103 +} 100.104 + 100.105 +test3(4711,23,17); 100.106 +print(x3.a); 100.107 +print(x3.b); 100.108 +print(x3.c); 100.109 + 100.110 +print("Overwriting apply now"); 100.111 +eval("x3.initialize['apply'] = function() { print('New function for apply - not a property'); }"); 100.112 + 100.113 +test(4712); 100.114 +print(x3.a);
101.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 101.2 +++ b/test/script/basic/apply_to_call/apply_to_call5.js.EXPECTED Tue Oct 14 10:20:24 2014 -0700 101.3 @@ -0,0 +1,19 @@ 101.4 +start 101.5 +4711 101.6 +23 101.7 +17 101.8 +Overwriting apply now 101.9 +New function for apply - not a property 101.10 +4711 101.11 +4711 101.12 +23 101.13 +17 101.14 +Overwriting apply now 101.15 +New function for apply - not a property 101.16 +4711 101.17 +4711 101.18 +23 101.19 +17 101.20 +Overwriting apply now 101.21 +New function for apply - not a property 101.22 +4711
102.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 102.2 +++ b/test/script/basic/fastpushpop.js Tue Oct 14 10:20:24 2014 -0700 102.3 @@ -0,0 +1,61 @@ 102.4 +/* 102.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 102.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 102.7 + * 102.8 + * This code is free software; you can redistribute it and/or modify it 102.9 + * under the terms of the GNU General Public License version 2 only, as 102.10 + * published by the Free Software Foundation. 102.11 + * 102.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 102.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 102.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 102.15 + * version 2 for more details (a copy is included in the LICENSE file that 102.16 + * accompanied this code). 102.17 + * 102.18 + * You should have received a copy of the GNU General Public License version 102.19 + * 2 along with this work; if not, write to the Free Software Foundation, 102.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 102.21 + * 102.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 102.23 + * or visit www.oracle.com if you need additional information or have any 102.24 + * questions. 102.25 + */ 102.26 + 102.27 +/** 102.28 + * fastpushpop.js: make sure guards work for fast push implementation 102.29 + * and normal one 102.30 + * 102.31 + * @test 102.32 + * @run 102.33 + */ 102.34 + 102.35 +var a = [1,2,3]; 102.36 +a.push(4); 102.37 +a.push(5); 102.38 +a.push(6); 102.39 +print(a); 102.40 + 102.41 +var a2 = Object.defineProperty(a,"length", { writable: false }); 102.42 +try { 102.43 + a2.push(7); 102.44 +} catch (e) { 102.45 + print("first: " + (e instanceof TypeError)); 102.46 +} 102.47 + 102.48 +print(a2); 102.49 + 102.50 +var b = [1,2,3,,,,4711.17,"dingo!"]; 102.51 +b.push(4); 102.52 +b.push(5); 102.53 +b.push(6); 102.54 +print(b); 102.55 + 102.56 +var b2 = Object.defineProperty(b,"length", { writable: false }); 102.57 +try { 102.58 + b2.push(7); 102.59 +} catch (e) { 102.60 + print("second: " + (e instanceof TypeError)); 102.61 +} 102.62 + 102.63 +print(b2); 102.64 +
103.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 103.2 +++ b/test/script/basic/fastpushpop.js.EXPECTED Tue Oct 14 10:20:24 2014 -0700 103.3 @@ -0,0 +1,6 @@ 103.4 +1,2,3,4,5,6 103.5 +first: true 103.6 +1,2,3,4,5,6,7 103.7 +1,2,3,,,,4711.17,dingo!,4,5,6 103.8 +second: true 103.9 +1,2,3,,,,4711.17,dingo!,4,5,6,7
104.1 --- a/test/script/basic/octane-payload.js Wed Oct 08 14:16:54 2014 -0700 104.2 +++ b/test/script/basic/octane-payload.js Tue Oct 14 10:20:24 2014 -0700 104.3 @@ -40,7 +40,7 @@ 104.4 {name:"gbemu", files:["gbemu-part1.js", "gbemu-part2.js"], suite:"GameboyBenchmark"}, 104.5 {name:"mandreel", files:["mandreel.js"], suite:"MandreelBenchmark"}, 104.6 {name:"navier-stokes", files:["navier-stokes.js"], suite:"NavierStokes"}, 104.7 - {name:"pdfjs", files:["pdfjs.js"], suite:"PdfJS"}, 104.8 + {name:"pdfjs", files:["pdfjs.js"], suite:"PdfJS", cleanUpIteration: function() { canvas_logs = []; }}, 104.9 {name:"raytrace", files:["raytrace.js"], suite:"RayTrace"}, 104.10 {name:"regexp", files:["regexp.js"], suite:"RegExpSuite"}, 104.11 {name:"richards", files:["richards.js"], suite:"Richards"},
105.1 --- a/test/script/basic/run-octane.js Wed Oct 08 14:16:54 2014 -0700 105.2 +++ b/test/script/basic/run-octane.js Tue Oct 14 10:20:24 2014 -0700 105.3 @@ -24,8 +24,8 @@ 105.4 /** 105.5 * @subtest 105.6 */ 105.7 -var payload = __DIR__ + "octane-payload.js"; 105.8 -load(payload); 105.9 +var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__; 105.10 +load(dir + "octane-payload.js"); 105.11 105.12 var runtime = undefined; 105.13 var verbose = false; 105.14 @@ -43,27 +43,27 @@ 105.15 function load_bench(arg) { 105.16 105.17 for (var idx = 0; idx < arg.files.length; idx++) { 105.18 - var f = arg.files[idx]; 105.19 - var file = f.split('/'); 105.20 - var file_name = path + file[file.length - 1]; 105.21 + var f = arg.files[idx]; 105.22 + var file = f.split('/'); 105.23 + var file_name = path + file[file.length - 1]; 105.24 105.25 - var compile_and_return = should_compile_only(file_name); 105.26 - if (compile_and_return) { 105.27 - if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them 105.28 - return true; 105.29 + var compile_and_return = should_compile_only(file_name); 105.30 + if (compile_and_return) { 105.31 + if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them 105.32 + return true; 105.33 + } 105.34 } 105.35 - } 105.36 105.37 - print_verbose(arg, "loading '" + arg.name + "' [" + f + "]..."); 105.38 - load(file_name); 105.39 + print_verbose(arg, "loading '" + arg.name + "' [" + f + "]... " + file_name); 105.40 + load(file_name); 105.41 } 105.42 105.43 if (typeof arg.before !== 'undefined') { 105.44 - arg.before(); 105.45 + arg.before(); 105.46 } 105.47 105.48 if (compile_and_return) { 105.49 - print_always(arg, "Compiled OK"); 105.50 + print_always(arg, "Compiled OK"); 105.51 } 105.52 return !compile_and_return; 105.53 105.54 @@ -73,16 +73,16 @@ 105.55 function run_one_benchmark(arg, iters) { 105.56 105.57 if (!load_bench(arg)) { 105.58 - return; 105.59 + return; 105.60 } 105.61 105.62 var success = true; 105.63 var current_name; 105.64 105.65 if (iters == undefined) { 105.66 - iters = numberOfIterations; 105.67 + iters = numberOfIterations; 105.68 } else { 105.69 - numberOfIterations = iters; 105.70 + numberOfIterations = iters; 105.71 } 105.72 105.73 var benchmarks = eval(arg.suite + ".benchmarks"); 105.74 @@ -91,64 +91,69 @@ 105.75 var mean_score = 0; 105.76 105.77 try { 105.78 - for (var x = 0; x < benchmarks.length ; x++) { 105.79 - //do warmup run 105.80 - //reset random number generator needed as of octane 9 before each run 105.81 + for (var x = 0; x < benchmarks.length ; x++) { 105.82 + //do warmup run 105.83 + //reset random number generator needed as of octane 9 before each run 105.84 + BenchmarkSuite.ResetRNG(); 105.85 + benchmarks[x].Setup(); 105.86 + } 105.87 BenchmarkSuite.ResetRNG(); 105.88 - benchmarks[x].Setup(); 105.89 - } 105.90 - BenchmarkSuite.ResetRNG(); 105.91 - print_verbose(arg, "running '" + arg.name + "' for " + iters + " iterations of no less than " + min_time + " seconds"); 105.92 + print_verbose(arg, "running '" + arg.name + "' for " + iters + " iterations of no less than " + min_time + " seconds"); 105.93 105.94 - var scores = []; 105.95 + var scores = []; 105.96 105.97 - var min_time_ms = min_time * 1000; 105.98 - var len = benchmarks.length; 105.99 + var min_time_ms = min_time * 1000; 105.100 + var len = benchmarks.length; 105.101 105.102 - for (var it = 0; it < iters + 1; it++) { 105.103 - //every iteration must take a minimum of 10 secs 105.104 - var ops = 0; 105.105 - var elapsed = 0; 105.106 - var start = new Date; 105.107 - do { 105.108 - for (var i = 0; i < len; i++) { 105.109 - benchmarks[i].run(); 105.110 - //important - no timing here like elapsed = new Date() - start, as in the 105.111 - //original harness. This will make timing very non-deterministic. 105.112 - //NOTHING else must live in this loop 105.113 + for (var it = 0; it < iters + 1; it++) { 105.114 + //every iteration must take a minimum of 10 secs 105.115 + var ops = 0; 105.116 + var elapsed = 0; 105.117 + var start = new Date; 105.118 + do { 105.119 + for (var i = 0; i < len; i++) { 105.120 + benchmarks[i].run(); 105.121 + //important - no timing here like elapsed = new Date() - start, as in the 105.122 + //original harness. This will make timing very non-deterministic. 105.123 + //NOTHING else must live in this loop 105.124 + } 105.125 + ops += len; 105.126 + elapsed = new Date - start; 105.127 + } while (elapsed < min_time * 1000); 105.128 + 105.129 + var score = ops / elapsed * 1000 * 60; 105.130 + scores.push(score); 105.131 + var name = it == 0 ? "warmup" : "iteration " + it; 105.132 + print_verbose(arg, name + " finished " + score.toFixed(0) + " ops/minute"); 105.133 + 105.134 + // optional per-iteration cleanup hook 105.135 + if (typeof arg.cleanUpIteration == "function") { 105.136 + arg.cleanUpIteration(); 105.137 + } 105.138 } 105.139 - ops += len; 105.140 - elapsed = new Date - start; 105.141 - } while (elapsed < min_time * 1000); 105.142 105.143 - var score = ops / elapsed * 1000 * 60; 105.144 - scores.push(score); 105.145 - var name = it == 0 ? "warmup" : "iteration " + it; 105.146 - print_verbose(arg, name + " finished " + score.toFixed(0) + " ops/minute"); 105.147 - } 105.148 + for (var x = 0; x < benchmarks.length ; x++) { 105.149 + benchmarks[x].TearDown(); 105.150 + } 105.151 105.152 - for (var x = 0; x < benchmarks.length ; x++) { 105.153 - benchmarks[x].TearDown(); 105.154 - } 105.155 - 105.156 - for (var x = 1; x < iters + 1 ; x++) { 105.157 - mean_score += scores[x]; 105.158 - min_score = Math.min(min_score, scores[x]); 105.159 - max_score = Math.max(max_score, scores[x]); 105.160 - } 105.161 - mean_score /= iters; 105.162 + for (var x = 1; x < iters + 1 ; x++) { 105.163 + mean_score += scores[x]; 105.164 + min_score = Math.min(min_score, scores[x]); 105.165 + max_score = Math.max(max_score, scores[x]); 105.166 + } 105.167 + mean_score /= iters; 105.168 } catch (e) { 105.169 - print_always(arg, "*** Aborted and setting score to zero. Reason: " + e); 105.170 - if (e instanceof java.lang.Throwable) { 105.171 - e.printStackTrace(); 105.172 - } 105.173 - mean_score = min_score = max_score = 0; 105.174 - scores = [0]; 105.175 + print_always(arg, "*** Aborted and setting score to zero. Reason: " + e); 105.176 + if (is_this_nashorn() && e instanceof java.lang.Throwable) { 105.177 + e.printStackTrace(); 105.178 + } 105.179 + mean_score = min_score = max_score = 0; 105.180 + scores = [0]; 105.181 } 105.182 105.183 var res = mean_score.toFixed(0); 105.184 if (verbose) { 105.185 - res += " ops/minute (" + min_score.toFixed(0) + "-" + max_score.toFixed(0) + "), warmup=" + scores[0].toFixed(0); 105.186 + res += " ops/minute (" + min_score.toFixed(0) + "-" + max_score.toFixed(0) + "), warmup=" + scores[0].toFixed(0); 105.187 } 105.188 print_always(arg, res); 105.189 } 105.190 @@ -163,13 +168,13 @@ 105.191 105.192 function print_verbose(arg, x) { 105.193 if (verbose) { 105.194 - print_always(arg, x) 105.195 + print_always(arg, x) 105.196 } 105.197 } 105.198 105.199 function run_suite(tests, iters) { 105.200 for (var idx = 0; idx < tests.length; idx++) { 105.201 - run_one_benchmark(tests[idx], iters); 105.202 + run_one_benchmark(tests[idx], iters); 105.203 } 105.204 } 105.205 105.206 @@ -184,13 +189,13 @@ 105.207 var new_args = []; 105.208 for (i in args) { 105.209 if (args[i].toString().indexOf(' ') != -1) { 105.210 - args[i] = args[i].replace(/\/$/, ''); 105.211 - var s = args[i].split(' '); 105.212 - for (j in s) { 105.213 - new_args.push(s[j]); 105.214 - } 105.215 + args[i] = args[i].replace(/\/$/, ''); 105.216 + var s = args[i].split(' '); 105.217 + for (j in s) { 105.218 + new_args.push(s[j]); 105.219 + } 105.220 } else { 105.221 - new_args.push(args[i]); 105.222 + new_args.push(args[i]); 105.223 } 105.224 } 105.225 105.226 @@ -205,46 +210,46 @@ 105.227 for (var i = 0; i < args.length; i++) { 105.228 arg = args[i]; 105.229 if (arg == "--iterations") { 105.230 - iters = +args[++i]; 105.231 - if (isNaN(iters)) { 105.232 - throw "'--iterations' must be followed by integer"; 105.233 - } 105.234 + iters = +args[++i]; 105.235 + if (isNaN(iters)) { 105.236 + throw "'--iterations' must be followed by integer"; 105.237 + } 105.238 } else if (arg == "--runtime") { 105.239 - runtime = args[++i]; 105.240 + runtime = args[++i]; 105.241 } else if (arg == "--verbose") { 105.242 - verbose = true; 105.243 + verbose = true; 105.244 } else if (arg == "--min-time") { 105.245 - min_time = +args[++i]; 105.246 - if (isNaN(iters)) { 105.247 - throw "'--min-time' must be followed by integer"; 105.248 - } 105.249 + min_time = +args[++i]; 105.250 + if (isNaN(iters)) { 105.251 + throw "'--min-time' must be followed by integer"; 105.252 + } 105.253 } else if (arg == "") { 105.254 - continue; //skip 105.255 + continue; //skip 105.256 } else { 105.257 - var found = false; 105.258 - for (j in tests) { 105.259 - if (tests[j].name === arg) { 105.260 - tests_found.push(tests[j]); 105.261 - found = true; 105.262 - break; 105.263 + var found = false; 105.264 + for (j in tests) { 105.265 + if (tests[j].name === arg) { 105.266 + tests_found.push(tests[j]); 105.267 + found = true; 105.268 + break; 105.269 + } 105.270 } 105.271 - } 105.272 - if (!found) { 105.273 - var str = "unknown test name: '" + arg + "' -- valid names are: "; 105.274 - for (j in tests) { 105.275 - if (j != 0) { 105.276 - str += ", "; 105.277 + if (!found) { 105.278 + var str = "unknown test name: '" + arg + "' -- valid names are: "; 105.279 + for (j in tests) { 105.280 + if (j != 0) { 105.281 + str += ", "; 105.282 + } 105.283 + str += "'" + tests[j].name + "'"; 105.284 + } 105.285 + throw str; 105.286 } 105.287 - str += "'" + tests[j].name + "'"; 105.288 - } 105.289 - throw str; 105.290 - } 105.291 } 105.292 } 105.293 105.294 if (tests_found.length == 0) { 105.295 for (i in tests) { 105.296 - tests_found.push(tests[i]); 105.297 + tests_found.push(tests[i]); 105.298 } 105.299 } 105.300 105.301 @@ -255,21 +260,21 @@ 105.302 105.303 if (is_this_nashorn()) { 105.304 try { 105.305 - read = readFully; 105.306 + read = readFully; 105.307 } catch (e) { 105.308 - print("ABORTING: Cannot find 'readFully'. You must have scripting enabled to use this test harness. (-scripting)"); 105.309 - throw e; 105.310 + print("ABORTING: Cannot find 'readFully'. You must have scripting enabled to use this test harness. (-scripting)"); 105.311 + throw e; 105.312 } 105.313 } 105.314 105.315 // run tests in alphabetical order by name 105.316 tests_found.sort(function(a, b) { 105.317 if (a.name < b.name) { 105.318 - return -1; 105.319 + return -1; 105.320 } else if (a.name > b.name) { 105.321 - return 1; 105.322 + return 1; 105.323 } else { 105.324 - return 0; 105.325 + return 0; 105.326 } 105.327 }); 105.328
106.1 --- a/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java Wed Oct 08 14:16:54 2014 -0700 106.2 +++ b/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java Tue Oct 14 10:20:24 2014 -0700 106.3 @@ -25,10 +25,10 @@ 106.4 106.5 package jdk.nashorn.internal.runtime; 106.6 106.7 - 106.8 import jdk.nashorn.api.scripting.ClassFilter; 106.9 import jdk.nashorn.api.scripting.NashornScriptEngineFactory; 106.10 import jdk.nashorn.api.scripting.URLReader; 106.11 +import jdk.nashorn.internal.test.framework.TestFinder; 106.12 import org.testng.annotations.Test; 106.13 106.14 import javax.script.ScriptEngine; 106.15 @@ -126,9 +126,9 @@ 106.16 private void persistentCacheTestImpl() { 106.17 NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); 106.18 ScriptEngine engine = factory.getScriptEngine( 106.19 - new String[]{"--persistent-code-cache"}, 106.20 - getClass().getClassLoader(), 106.21 - getClassFilter() 106.22 + TestFinder.addExplicitOptimisticTypes(new String[]{"--persistent-code-cache", "--optimistic-types=true"}), 106.23 + getClass().getClassLoader(), 106.24 + getClassFilter() 106.25 ); 106.26 String testScript = "var a = Java.type('java.lang.String');" + generateCodeForPersistentStore(); 106.27 try { 106.28 @@ -137,7 +137,7 @@ 106.29 fail(exc.getMessage()); 106.30 } 106.31 ScriptEngine engineSafe = factory.getScriptEngine( 106.32 - new String[]{"--persistent-code-cache"}, 106.33 + TestFinder.addExplicitOptimisticTypes(new String[]{"--persistent-code-cache", "--optimistic-types=true"}), 106.34 getClass().getClassLoader(), 106.35 new ClassFilter() { 106.36 @Override 106.37 @@ -151,7 +151,7 @@ 106.38 fail("ClassNotFoundException should have been thrown"); 106.39 } catch (final Exception exc) { 106.40 if (!(exc.getCause() instanceof ClassNotFoundException)) { 106.41 - fail("ClassNotFoundException expected"); 106.42 + fail("ClassNotFoundException expected, got " + exc.getClass()); 106.43 } 106.44 } 106.45 }
107.1 --- a/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java Wed Oct 08 14:16:54 2014 -0700 107.2 +++ b/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java Tue Oct 14 10:20:24 2014 -0700 107.3 @@ -179,7 +179,7 @@ 107.4 for (final String str : forkJVMOptions) { 107.5 if(!str.isEmpty()) { 107.6 cmd.add(str); 107.7 - } 107.8 + } 107.9 } 107.10 cmd.add(Shell.class.getName()); 107.11 // now add the rest of the "in process" runtime arguments
108.1 --- a/test/src/jdk/nashorn/internal/test/framework/TestFinder.java Wed Oct 08 14:16:54 2014 -0700 108.2 +++ b/test/src/jdk/nashorn/internal/test/framework/TestFinder.java Tue Oct 14 10:20:24 2014 -0700 108.3 @@ -56,6 +56,7 @@ 108.4 import java.nio.file.SimpleFileVisitor; 108.5 import java.nio.file.attribute.BasicFileAttributes; 108.6 import java.util.ArrayList; 108.7 +import java.util.Arrays; 108.8 import java.util.Collections; 108.9 import java.util.EnumSet; 108.10 import java.util.HashMap; 108.11 @@ -75,7 +76,7 @@ 108.12 * Utility class to find/parse script test files and to create 'test' instances. 108.13 * Actual 'test' object type is decided by clients of this class. 108.14 */ 108.15 -final class TestFinder { 108.16 +public final class TestFinder { 108.17 private TestFinder() {} 108.18 108.19 interface TestFactory<T> { 108.20 @@ -215,6 +216,8 @@ 108.21 final List<String> scriptArguments = new ArrayList<>(); 108.22 boolean inComment = false; 108.23 108.24 + boolean explicitOptimistic = false; 108.25 + 108.26 try (Scanner scanner = new Scanner(testFile)) { 108.27 while (scanner.hasNext()) { 108.28 // TODO: Scan for /ref=file qualifiers, etc, to determine run 108.29 @@ -287,7 +290,11 @@ 108.30 scriptArguments.add(scanner.next()); 108.31 break; 108.32 case "@option": 108.33 - engineOptions.add(scanner.next()); 108.34 + final String next = scanner.next(); 108.35 + engineOptions.add(next); 108.36 + if (next.startsWith("--optimistic-types")) { 108.37 + explicitOptimistic = true; 108.38 + } 108.39 break; 108.40 case "@fork": 108.41 fork = true; 108.42 @@ -336,12 +343,61 @@ 108.43 testOptions.put(OPTIONS_FORK, "true"); 108.44 } 108.45 108.46 + //if there are explicit optimistic type settings, use those - do not override 108.47 + //the test might only work with optimistic types on or off. 108.48 + if (!explicitOptimistic) { 108.49 + addExplicitOptimisticTypes(engineOptions); 108.50 + } 108.51 + 108.52 tests.add(factory.createTest(framework, testFile.toFile(), engineOptions, testOptions, scriptArguments)); 108.53 } else if (!isNotTest) { 108.54 orphans.add(name); 108.55 } 108.56 } 108.57 108.58 + //the reverse of the default setting for optimistic types, if enabled, false, otherwise true 108.59 + //thus, true for 8u40, false for 9 108.60 + private static final boolean OPTIMISTIC_OVERRIDE = true; 108.61 + 108.62 + /** 108.63 + * Check if there is an optimistic override, that disables the default 108.64 + * false optimistic types and sets them to true, for testing purposes 108.65 + * 108.66 + * @return true if optimistic type override has been set by test suite 108.67 + */ 108.68 + public static boolean hasOptimisticOverride() { 108.69 + return Boolean.valueOf(OPTIMISTIC_OVERRIDE).toString().equals(System.getProperty("optimistic.override")); 108.70 + } 108.71 + 108.72 + /** 108.73 + * Add an optimistic-types=true option to an argument list if this 108.74 + * is set to override the default false. Add an optimistic-types=true 108.75 + * options to an argument list if this is set to override the default 108.76 + * true 108.77 + * 108.78 + * @args new argument list array 108.79 + */ 108.80 + public static String[] addExplicitOptimisticTypes(String[] args) { 108.81 + if (hasOptimisticOverride()) { 108.82 + final List<String> newList = new ArrayList<>(Arrays.asList(args)); 108.83 + newList.add("--optimistic-types=" + Boolean.valueOf(OPTIMISTIC_OVERRIDE)); 108.84 + return newList.toArray(new String[0]); 108.85 + } 108.86 + return args; 108.87 + } 108.88 + 108.89 + /** 108.90 + * Add an optimistic-types=true option to an argument list if this 108.91 + * is set to override the default false 108.92 + * 108.93 + * @args argument list 108.94 + */ 108.95 + public static void addExplicitOptimisticTypes(List<String> args) { 108.96 + if (hasOptimisticOverride()) { 108.97 + args.add("--optimistic-types=" + Boolean.valueOf(OPTIMISTIC_OVERRIDE)); 108.98 + } 108.99 + } 108.100 + 108.101 private static boolean strictModeEnabled() { 108.102 return Boolean.getBoolean(TEST_JS_ENABLE_STRICT_MODE); 108.103 }