Thu, 25 Sep 2014 15:53:47 +0200
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
Reviewed-by: hannesw, attila, sundar
1.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Wed Oct 01 12:22:12 2014 +0200 1.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Thu Sep 25 15:53:47 2014 +0200 1.3 @@ -292,7 +292,6 @@ 1.4 mi.push(memInfo.getArity()); 1.5 mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETARITY, SCRIPTFUNCTION_SETARITY_DESC); 1.6 } 1.7 - 1.8 } 1.9 1.10 static void linkerAddGetterSetter(final MethodGenerator mi, final String className, final MemberInfo memInfo) {
2.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Wed Oct 01 12:22:12 2014 +0200 2.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Thu Sep 25 15:53:47 2014 +0200 2.3 @@ -28,7 +28,6 @@ 2.4 import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; 2.5 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_DESC; 2.6 import static jdk.nashorn.internal.tools.nasgen.StringConstants.STRING_DESC; 2.7 - 2.8 import jdk.internal.org.objectweb.asm.Opcodes; 2.9 import jdk.internal.org.objectweb.asm.Type; 2.10 import jdk.nashorn.internal.objects.annotations.Where; 2.11 @@ -75,10 +74,6 @@ 2.12 * This is a specialized version of a function 2.13 */ 2.14 SPECIALIZED_FUNCTION, 2.15 - /** 2.16 - * This is a specialized version of a constructor 2.17 - */ 2.18 - SPECIALIZED_CONSTRUCTOR 2.19 } 2.20 2.21 // keep in sync with jdk.nashorn.internal.objects.annotations.Attribute 2.22 @@ -107,6 +102,12 @@ 2.23 2.24 private Where where; 2.25 2.26 + private Type linkLogicClass; 2.27 + 2.28 + private boolean isSpecializedConstructor; 2.29 + 2.30 + private boolean isOptimistic; 2.31 + 2.32 /** 2.33 * @return the kind 2.34 */ 2.35 @@ -136,6 +137,57 @@ 2.36 } 2.37 2.38 /** 2.39 + * Tag something as specialized constructor or not 2.40 + * @param isSpecializedConstructor boolean, true if specialized constructor 2.41 + */ 2.42 + public void setIsSpecializedConstructor(final boolean isSpecializedConstructor) { 2.43 + this.isSpecializedConstructor = isSpecializedConstructor; 2.44 + } 2.45 + 2.46 + /** 2.47 + * Check if something is a specialized constructor 2.48 + * @return true if specialized constructor 2.49 + */ 2.50 + public boolean isSpecializedConstructor() { 2.51 + return isSpecializedConstructor; 2.52 + } 2.53 + 2.54 + /** 2.55 + * Check if this is an optimistic builtin function 2.56 + * @return true if optimistic builtin 2.57 + */ 2.58 + public boolean isOptimistic() { 2.59 + return isOptimistic; 2.60 + } 2.61 + 2.62 + /** 2.63 + * Tag something as optimitic builtin or not 2.64 + * @param isOptimistic boolean, true if builtin constructor 2.65 + */ 2.66 + public void setIsOptimistic(final boolean isOptimistic) { 2.67 + this.isOptimistic = isOptimistic; 2.68 + } 2.69 + 2.70 + /** 2.71 + * Get the SpecializedFunction guard for specializations, i.e. optimistic 2.72 + * builtins 2.73 + * @return specialization, null if none 2.74 + */ 2.75 + public Type getLinkLogicClass() { 2.76 + return linkLogicClass; 2.77 + } 2.78 + 2.79 + /** 2.80 + * Set thre SpecializedFunction link logic class for specializations, i.e. optimistic 2.81 + * builtins 2.82 + * @param linkLogicClass link logic class 2.83 + */ 2.84 + 2.85 + public void setLinkLogicClass(final Type linkLogicClass) { 2.86 + this.linkLogicClass = linkLogicClass; 2.87 + } 2.88 + 2.89 + /** 2.90 * @return the attributes 2.91 */ 2.92 public int getAttributes() { 2.93 @@ -304,19 +356,6 @@ 2.94 } 2.95 } 2.96 break; 2.97 - case SPECIALIZED_CONSTRUCTOR: { 2.98 - final Type returnType = Type.getReturnType(javaDesc); 2.99 - if (!isJSObjectType(returnType)) { 2.100 - error("return value of a @SpecializedConstructor method should be a valid JS type, found " + returnType); 2.101 - } 2.102 - final Type[] argTypes = Type.getArgumentTypes(javaDesc); 2.103 - for (int i = 0; i < argTypes.length; i++) { 2.104 - if (!isValidJSType(argTypes[i])) { 2.105 - error(i + "'th argument of a @SpecializedConstructor method is not valid JS type, found " + argTypes[i]); 2.106 - } 2.107 - } 2.108 - } 2.109 - break; 2.110 case FUNCTION: { 2.111 final Type returnType = Type.getReturnType(javaDesc); 2.112 if (!(isValidJSType(returnType) || Type.VOID_TYPE == returnType)) { 2.113 @@ -351,7 +390,7 @@ 2.114 break; 2.115 case SPECIALIZED_FUNCTION: { 2.116 final Type returnType = Type.getReturnType(javaDesc); 2.117 - if (!(isValidJSType(returnType) || Type.VOID_TYPE == returnType)) { 2.118 + if (!(isValidJSType(returnType) || (isSpecializedConstructor() && Type.VOID_TYPE == returnType))) { 2.119 error("return value of a @SpecializedFunction method should be a valid JS type, found " + returnType); 2.120 } 2.121 final Type[] argTypes = Type.getArgumentTypes(javaDesc);
3.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java Wed Oct 01 12:22:12 2014 +0200 3.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java Thu Sep 25 15:53:47 2014 +0200 3.3 @@ -56,6 +56,7 @@ 3.4 import static jdk.internal.org.objectweb.asm.Opcodes.IALOAD; 3.5 import static jdk.internal.org.objectweb.asm.Opcodes.IASTORE; 3.6 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_0; 3.7 +import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_1; 3.8 import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD; 3.9 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEINTERFACE; 3.10 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL; 3.11 @@ -76,9 +77,11 @@ 3.12 import static jdk.internal.org.objectweb.asm.Opcodes.SASTORE; 3.13 import static jdk.internal.org.objectweb.asm.Opcodes.SIPUSH; 3.14 import static jdk.internal.org.objectweb.asm.Opcodes.SWAP; 3.15 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.METHODHANDLE_TYPE; 3.16 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_METHODHANDLE; 3.17 - 3.18 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; 3.19 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SPECIALIZATION_INIT2; 3.20 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SPECIALIZATION_INIT3; 3.21 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SPECIALIZATION_TYPE; 3.22 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_SPECIALIZATION; 3.23 import java.util.List; 3.24 import jdk.internal.org.objectweb.asm.Handle; 3.25 import jdk.internal.org.objectweb.asm.MethodVisitor; 3.26 @@ -95,6 +98,8 @@ 3.27 private final Type returnType; 3.28 private final Type[] argumentTypes; 3.29 3.30 + static final Type EMPTY_LINK_LOGIC_TYPE = Type.getType("Ljdk/nashorn/internal/objects/annotations/SpecializedFunction$LinkLogic$Empty;"); 3.31 + 3.32 MethodGenerator(final MethodVisitor mv, final int access, final String name, final String descriptor) { 3.33 super(ASM4, mv); 3.34 this.access = access; 3.35 @@ -380,6 +385,11 @@ 3.36 super.visitFieldInsn(GETFIELD, owner, field, desc); 3.37 } 3.38 3.39 + private static boolean linkLogicIsEmpty(final Type type) { 3.40 + assert EMPTY_LINK_LOGIC_TYPE != null; //type is ok for null if we are a @SpecializedFunction without any attribs 3.41 + return EMPTY_LINK_LOGIC_TYPE.equals(type); 3.42 + } 3.43 + 3.44 void memberInfoArray(final String className, final List<MemberInfo> mis) { 3.45 if (mis.isEmpty()) { 3.46 pushNull(); 3.47 @@ -388,12 +398,22 @@ 3.48 3.49 int pos = 0; 3.50 push(mis.size()); 3.51 - newObjectArray(METHODHANDLE_TYPE); 3.52 + newObjectArray(SPECIALIZATION_TYPE); 3.53 for (final MemberInfo mi : mis) { 3.54 dup(); 3.55 push(pos++); 3.56 + visitTypeInsn(NEW, SPECIALIZATION_TYPE); 3.57 + dup(); 3.58 visitLdcInsn(new Handle(H_INVOKESTATIC, className, mi.getJavaName(), mi.getJavaDesc())); 3.59 - arrayStore(TYPE_METHODHANDLE); 3.60 + final Type linkLogicClass = mi.getLinkLogicClass(); 3.61 + final boolean linkLogic = !linkLogicIsEmpty(linkLogicClass); 3.62 + final String ctor = linkLogic ? SPECIALIZATION_INIT3 : SPECIALIZATION_INIT2; 3.63 + if (linkLogic) { 3.64 + visitLdcInsn(linkLogicClass); 3.65 + } 3.66 + visitInsn(mi.isOptimistic() ? ICONST_1 : ICONST_0); 3.67 + visitMethodInsn(INVOKESPECIAL, SPECIALIZATION_TYPE, INIT, ctor, false); 3.68 + arrayStore(TYPE_SPECIALIZATION); 3.69 } 3.70 } 3.71
4.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java Wed Oct 01 12:22:12 2014 +0200 4.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java Thu Sep 25 15:53:47 2014 +0200 4.3 @@ -37,7 +37,6 @@ 4.4 import jdk.nashorn.internal.objects.annotations.Property; 4.5 import jdk.nashorn.internal.objects.annotations.ScriptClass; 4.6 import jdk.nashorn.internal.objects.annotations.Setter; 4.7 -import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; 4.8 import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 4.9 import jdk.nashorn.internal.objects.annotations.Where; 4.10 import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind; 4.11 @@ -57,7 +56,7 @@ 4.12 static final String PROPERTY_ANNO_DESC = Type.getDescriptor(Property.class); 4.13 static final String WHERE_ENUM_DESC = Type.getDescriptor(Where.class); 4.14 static final String SPECIALIZED_FUNCTION = Type.getDescriptor(SpecializedFunction.class); 4.15 - static final String SPECIALIZED_CONSTRUCTOR = Type.getDescriptor(SpecializedConstructor.class); 4.16 + static final String LINK_LOGIC_DESC = "Ljdk/nashorn/internal/objects/annotations/SpecializedFunction$LinkLogic;"; 4.17 4.18 static final Map<String, Kind> annotations = new HashMap<>(); 4.19 4.20 @@ -69,7 +68,6 @@ 4.21 annotations.put(SETTER_ANNO_DESC, Kind.SETTER); 4.22 annotations.put(PROPERTY_ANNO_DESC, Kind.PROPERTY); 4.23 annotations.put(SPECIALIZED_FUNCTION, Kind.SPECIALIZED_FUNCTION); 4.24 - annotations.put(SPECIALIZED_CONSTRUCTOR, Kind.SPECIALIZED_CONSTRUCTOR); 4.25 } 4.26 4.27 // name of the script class 4.28 @@ -119,11 +117,12 @@ 4.29 List<MemberInfo> getSpecializedConstructors() { 4.30 final List<MemberInfo> res = new LinkedList<>(); 4.31 for (final MemberInfo memInfo : members) { 4.32 - if (memInfo.getKind() == Kind.SPECIALIZED_CONSTRUCTOR) { 4.33 + if (memInfo.isSpecializedConstructor()) { 4.34 + assert memInfo.getKind() == Kind.SPECIALIZED_FUNCTION; 4.35 res.add(memInfo); 4.36 } 4.37 } 4.38 - return res; 4.39 + return Collections.unmodifiableList(res); 4.40 } 4.41 4.42 int getPrototypeMemberCount() { 4.43 @@ -175,7 +174,7 @@ 4.44 res.add(memInfo); 4.45 } 4.46 } 4.47 - return res; 4.48 + return Collections.unmodifiableList(res); 4.49 } 4.50 4.51 MemberInfo findSetter(final MemberInfo getter) {
5.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Wed Oct 01 12:22:12 2014 +0200 5.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Thu Sep 25 15:53:47 2014 +0200 5.3 @@ -27,7 +27,6 @@ 5.4 5.5 import static jdk.nashorn.internal.tools.nasgen.ScriptClassInfo.SCRIPT_CLASS_ANNO_DESC; 5.6 import static jdk.nashorn.internal.tools.nasgen.ScriptClassInfo.WHERE_ENUM_DESC; 5.7 - 5.8 import java.io.BufferedInputStream; 5.9 import java.io.FileInputStream; 5.10 import java.io.IOException; 5.11 @@ -41,6 +40,7 @@ 5.12 import jdk.internal.org.objectweb.asm.FieldVisitor; 5.13 import jdk.internal.org.objectweb.asm.MethodVisitor; 5.14 import jdk.internal.org.objectweb.asm.Opcodes; 5.15 +import jdk.internal.org.objectweb.asm.Type; 5.16 import jdk.nashorn.internal.objects.annotations.Where; 5.17 import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind; 5.18 5.19 @@ -194,6 +194,7 @@ 5.20 5.21 final MemberInfo memInfo = new MemberInfo(); 5.22 5.23 + //annokind == e.g. GETTER or SPECIALIZED_FUNCTION 5.24 memInfo.setKind(annoKind); 5.25 memInfo.setJavaName(methodName); 5.26 memInfo.setJavaDesc(methodDesc); 5.27 @@ -208,12 +209,18 @@ 5.28 private Integer attributes; 5.29 private Integer arity; 5.30 private Where where; 5.31 + private boolean isSpecializedConstructor; 5.32 + private boolean isOptimistic; 5.33 + private Type linkLogicClass = MethodGenerator.EMPTY_LINK_LOGIC_TYPE; 5.34 5.35 @Override 5.36 public void visit(final String annotationName, final Object annotationValue) { 5.37 switch (annotationName) { 5.38 case "name": 5.39 this.name = (String)annotationValue; 5.40 + if (name.isEmpty()) { 5.41 + name = null; 5.42 + } 5.43 break; 5.44 case "attributes": 5.45 this.attributes = (Integer)annotationValue; 5.46 @@ -221,6 +228,17 @@ 5.47 case "arity": 5.48 this.arity = (Integer)annotationValue; 5.49 break; 5.50 + case "isConstructor": 5.51 + assert annoKind == Kind.SPECIALIZED_FUNCTION; 5.52 + this.isSpecializedConstructor = (Boolean)annotationValue; 5.53 + break; 5.54 + case "isOptimistic": 5.55 + assert annoKind == Kind.SPECIALIZED_FUNCTION; 5.56 + this.isOptimistic = (Boolean)annotationValue; 5.57 + break; 5.58 + case "linkLogic": 5.59 + this.linkLogicClass = (Type)annotationValue; 5.60 + break; 5.61 default: 5.62 break; 5.63 } 5.64 @@ -230,12 +248,19 @@ 5.65 5.66 @Override 5.67 public void visitEnum(final String enumName, final String desc, final String enumValue) { 5.68 - if ("where".equals(enumName) && WHERE_ENUM_DESC.equals(desc)) { 5.69 - this.where = Where.valueOf(enumValue); 5.70 + switch (enumName) { 5.71 + case "where": 5.72 + if (WHERE_ENUM_DESC.equals(desc)) { 5.73 + this.where = Where.valueOf(enumValue); 5.74 + } 5.75 + break; 5.76 + default: 5.77 + break; 5.78 } 5.79 super.visitEnum(enumName, desc, enumValue); 5.80 } 5.81 5.82 + @SuppressWarnings("fallthrough") 5.83 @Override 5.84 public void visitEnd() { 5.85 super.visitEnd(); 5.86 @@ -256,7 +281,6 @@ 5.87 case SETTER: 5.88 where = Where.INSTANCE; 5.89 break; 5.90 - case SPECIALIZED_CONSTRUCTOR: 5.91 case CONSTRUCTOR: 5.92 where = Where.CONSTRUCTOR; 5.93 break; 5.94 @@ -264,12 +288,18 @@ 5.95 where = Where.PROTOTYPE; 5.96 break; 5.97 case SPECIALIZED_FUNCTION: 5.98 - //TODO is this correct 5.99 + if (isSpecializedConstructor) { 5.100 + where = Where.CONSTRUCTOR; 5.101 + } 5.102 + //fallthru 5.103 default: 5.104 break; 5.105 } 5.106 } 5.107 memInfo.setWhere(where); 5.108 + memInfo.setLinkLogicClass(linkLogicClass); 5.109 + memInfo.setIsSpecializedConstructor(isSpecializedConstructor); 5.110 + memInfo.setIsOptimistic(isOptimistic); 5.111 } 5.112 }; 5.113 }
6.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java Wed Oct 01 12:22:12 2014 +0200 6.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java Thu Sep 25 15:53:47 2014 +0200 6.3 @@ -38,7 +38,6 @@ 6.4 import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; 6.5 import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; 6.6 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_TYPE; 6.7 - 6.8 import java.io.BufferedInputStream; 6.9 import java.io.FileInputStream; 6.10 import java.io.FileOutputStream;
7.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Wed Oct 01 12:22:12 2014 +0200 7.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Thu Sep 25 15:53:47 2014 +0200 7.3 @@ -37,6 +37,7 @@ 7.4 import jdk.nashorn.internal.runtime.PropertyMap; 7.5 import jdk.nashorn.internal.runtime.ScriptFunction; 7.6 import jdk.nashorn.internal.runtime.ScriptObject; 7.7 +import jdk.nashorn.internal.runtime.Specialization; 7.8 7.9 /** 7.10 * String constants used for code generation/instrumentation. 7.11 @@ -44,20 +45,26 @@ 7.12 @SuppressWarnings("javadoc") 7.13 public interface StringConstants { 7.14 // standard jdk types, methods 7.15 - static final Type TYPE_METHODHANDLE = Type.getType(MethodHandle.class); 7.16 - static final Type TYPE_METHODHANDLE_ARRAY = Type.getType(MethodHandle[].class); 7.17 - static final Type TYPE_OBJECT = Type.getType(Object.class); 7.18 - static final Type TYPE_STRING = Type.getType(String.class); 7.19 - static final Type TYPE_COLLECTION = Type.getType(Collection.class); 7.20 - static final Type TYPE_COLLECTIONS = Type.getType(Collections.class); 7.21 - static final Type TYPE_ARRAYLIST = Type.getType(ArrayList.class); 7.22 - static final Type TYPE_LIST = Type.getType(List.class); 7.23 + static final Type TYPE_METHODHANDLE = Type.getType(MethodHandle.class); 7.24 + static final Type TYPE_METHODHANDLE_ARRAY = Type.getType(MethodHandle[].class); 7.25 + static final Type TYPE_SPECIALIZATION = Type.getType(Specialization.class); 7.26 + static final Type TYPE_SPECIALIZATION_ARRAY = Type.getType(Specialization[].class); 7.27 + static final Type TYPE_OBJECT = Type.getType(Object.class); 7.28 + static final Type TYPE_STRING = Type.getType(String.class); 7.29 + static final Type TYPE_CLASS = Type.getType(Class.class); 7.30 + static final Type TYPE_COLLECTION = Type.getType(Collection.class); 7.31 + static final Type TYPE_COLLECTIONS = Type.getType(Collections.class); 7.32 + static final Type TYPE_ARRAYLIST = Type.getType(ArrayList.class); 7.33 + static final Type TYPE_LIST = Type.getType(List.class); 7.34 7.35 static final String CLINIT = "<clinit>"; 7.36 static final String INIT = "<init>"; 7.37 static final String DEFAULT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE); 7.38 7.39 static final String METHODHANDLE_TYPE = TYPE_METHODHANDLE.getInternalName(); 7.40 + static final String SPECIALIZATION_TYPE = TYPE_SPECIALIZATION.getInternalName(); 7.41 + static final String SPECIALIZATION_INIT2 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, Type.getType(boolean.class)); 7.42 + static final String SPECIALIZATION_INIT3 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, TYPE_CLASS, Type.getType(boolean.class)); 7.43 static final String OBJECT_TYPE = TYPE_OBJECT.getInternalName(); 7.44 static final String OBJECT_DESC = TYPE_OBJECT.getDescriptor(); 7.45 static final String STRING_TYPE = TYPE_STRING.getInternalName(); 7.46 @@ -122,11 +129,11 @@ 7.47 static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC = 7.48 Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE); 7.49 static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC = 7.50 - Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE, TYPE_METHODHANDLE_ARRAY); 7.51 + Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY); 7.52 static final String SCRIPTFUNCTIONIMPL_INIT_DESC3 = 7.53 - Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_METHODHANDLE_ARRAY); 7.54 + Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY); 7.55 static final String SCRIPTFUNCTIONIMPL_INIT_DESC4 = 7.56 - Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_PROPERTYMAP, TYPE_METHODHANDLE_ARRAY); 7.57 + Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_PROPERTYMAP, TYPE_SPECIALIZATION_ARRAY); 7.58 7.59 // ScriptObject 7.60 static final String SCRIPTOBJECT_TYPE = TYPE_SCRIPTOBJECT.getInternalName();
8.1 --- a/samples/BufferArray.java Wed Oct 01 12:22:12 2014 +0200 8.2 +++ b/samples/BufferArray.java Thu Sep 25 15:53:47 2014 +0200 8.3 @@ -29,8 +29,8 @@ 8.4 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 8.5 */ 8.6 8.7 +import java.nio.DoubleBuffer; 8.8 import jdk.nashorn.api.scripting.AbstractJSObject; 8.9 -import java.nio.DoubleBuffer; 8.10 8.11 /** 8.12 * Simple class demonstrating pluggable script object 8.13 @@ -52,41 +52,49 @@ 8.14 // underlying nio buffer 8.15 private final DoubleBuffer buf; 8.16 8.17 - public BufferArray(int size) { 8.18 + /** 8.19 + * Constructor 8.20 + * @param size initial size 8.21 + */ 8.22 + public BufferArray(final int size) { 8.23 buf = DoubleBuffer.allocate(size); 8.24 } 8.25 8.26 - public BufferArray(DoubleBuffer buf) { 8.27 + /** 8.28 + * Constructur 8.29 + * @param buf {@link DoubleBuffer} to link to 8.30 + */ 8.31 + public BufferArray(final DoubleBuffer buf) { 8.32 this.buf = buf; 8.33 } 8.34 8.35 // called to check if indexed property exists 8.36 @Override 8.37 - public boolean hasSlot(int index) { 8.38 + public boolean hasSlot(final int index) { 8.39 return index > 0 && index < buf.capacity(); 8.40 } 8.41 8.42 // get the value from that index 8.43 @Override 8.44 - public Object getSlot(int index) { 8.45 + public Object getSlot(final int index) { 8.46 return buf.get(index); 8.47 } 8.48 8.49 // set the value at that index 8.50 @Override 8.51 - public void setSlot(int index, Object value) { 8.52 + public void setSlot(final int index, final Object value) { 8.53 buf.put(index, ((Number)value).doubleValue()); 8.54 } 8.55 8.56 // do you have a property of that given name? 8.57 @Override 8.58 - public boolean hasMember(String name) { 8.59 + public boolean hasMember(final String name) { 8.60 return "length".equals(name) || "buf".equals(name); 8.61 } 8.62 8.63 // get the value of that named property 8.64 @Override 8.65 - public Object getMember(String name) { 8.66 + public Object getMember(final String name) { 8.67 switch (name) { 8.68 case "length": 8.69 return buf.capacity(); 8.70 @@ -94,7 +102,7 @@ 8.71 // return a 'function' value for this property 8.72 return new AbstractJSObject() { 8.73 @Override 8.74 - public Object call(Object thiz, Object... args) { 8.75 + public Object call(final Object thiz, final Object... args) { 8.76 return BufferArray.this.buf; 8.77 } 8.78 8.79 @@ -104,6 +112,8 @@ 8.80 return true; 8.81 } 8.82 }; 8.83 + default: 8.84 + break; 8.85 } 8.86 return null; 8.87 }
9.1 --- a/src/jdk/nashorn/internal/codegen/ApplySpecialization.java Wed Oct 01 12:22:12 2014 +0200 9.2 +++ b/src/jdk/nashorn/internal/codegen/ApplySpecialization.java Thu Sep 25 15:53:47 2014 +0200 9.3 @@ -27,7 +27,6 @@ 9.4 9.5 import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR; 9.6 import static jdk.nashorn.internal.codegen.CompilerConstants.EXPLODED_ARGUMENT_PREFIX; 9.7 - 9.8 import java.lang.invoke.MethodType; 9.9 import java.util.ArrayDeque; 9.10 import java.util.ArrayList; 9.11 @@ -35,7 +34,6 @@ 9.12 import java.util.HashSet; 9.13 import java.util.List; 9.14 import java.util.Set; 9.15 - 9.16 import jdk.nashorn.internal.ir.AccessNode; 9.17 import jdk.nashorn.internal.ir.CallNode; 9.18 import jdk.nashorn.internal.ir.Expression; 9.19 @@ -131,11 +129,12 @@ 9.20 @SuppressWarnings("serial") 9.21 final UnsupportedOperationException uoe = new UnsupportedOperationException() { 9.22 @Override 9.23 - public Throwable fillInStackTrace() { 9.24 + public synchronized Throwable fillInStackTrace() { 9.25 return null; 9.26 } 9.27 }; 9.28 9.29 + final Set<Expression> argumentsFound = new HashSet<>(); 9.30 final Deque<Set<Expression>> stack = new ArrayDeque<>(); 9.31 //ensure that arguments is only passed as arg to apply 9.32 try { 9.33 @@ -145,7 +144,11 @@ 9.34 } 9.35 9.36 private boolean isArguments(final Expression expr) { 9.37 - return expr instanceof IdentNode && ARGUMENTS.equals(((IdentNode)expr).getName()); 9.38 + if (expr instanceof IdentNode && ARGUMENTS.equals(((IdentNode)expr).getName())) { 9.39 + argumentsFound.add(expr); 9.40 + return true; 9.41 + } 9.42 + return false; 9.43 } 9.44 9.45 private boolean isParam(final String name) { 9.46 @@ -159,7 +162,7 @@ 9.47 9.48 @Override 9.49 public Node leaveIdentNode(final IdentNode identNode) { 9.50 - if (isParam(identNode.getName()) || ARGUMENTS.equals(identNode.getName()) && !isCurrentArg(identNode)) { 9.51 + if (isParam(identNode.getName()) || isArguments(identNode) && !isCurrentArg(identNode)) { 9.52 throw uoe; //avoid filling in stack trace 9.53 } 9.54 return identNode; 9.55 @@ -186,7 +189,9 @@ 9.56 } 9.57 }); 9.58 } catch (final UnsupportedOperationException e) { 9.59 - log.fine("'arguments' escapes, is not used in standard call dispatch, or is reassigned in '" + functionNode.getName() + "'. Aborting"); 9.60 + if (!argumentsFound.isEmpty()) { 9.61 + log.fine("'arguments' is used but escapes, or is reassigned in '" + functionNode.getName() + "'. Aborting"); 9.62 + } 9.63 return true; //bad 9.64 } 9.65 9.66 @@ -267,9 +272,9 @@ 9.67 return false; 9.68 } 9.69 9.70 - if (!Global.instance().isSpecialNameValid("apply")) { 9.71 + if (!Global.isBuiltinFunctionPrototypeApply()) { 9.72 log.fine("Apply transform disabled: apply/call overridden"); 9.73 - assert !Global.instance().isSpecialNameValid("call") : "call and apply should have the same SwitchPoint"; 9.74 + assert !Global.isBuiltinFunctionPrototypeCall() : "call and apply should have the same SwitchPoint"; 9.75 return false; 9.76 } 9.77
10.1 --- a/src/jdk/nashorn/internal/codegen/ClassEmitter.java Wed Oct 01 12:22:12 2014 +0200 10.2 +++ b/src/jdk/nashorn/internal/codegen/ClassEmitter.java Thu Sep 25 15:53:47 2014 +0200 10.3 @@ -51,15 +51,14 @@ 10.4 import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor; 10.5 import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor; 10.6 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup; 10.7 - 10.8 import java.io.ByteArrayOutputStream; 10.9 import java.io.PrintWriter; 10.10 import java.security.AccessController; 10.11 import java.security.PrivilegedAction; 10.12 +import java.util.Collections; 10.13 import java.util.EnumSet; 10.14 import java.util.HashSet; 10.15 import java.util.Set; 10.16 - 10.17 import jdk.internal.org.objectweb.asm.ClassWriter; 10.18 import jdk.internal.org.objectweb.asm.MethodVisitor; 10.19 import jdk.internal.org.objectweb.asm.util.TraceClassVisitor; 10.20 @@ -160,8 +159,12 @@ 10.21 this.methodNames = new HashSet<>(); 10.22 } 10.23 10.24 + /** 10.25 + * Return the method names encountered 10.26 + * @return method names 10.27 + */ 10.28 public Set<String> getMethodNames() { 10.29 - return methodNames; 10.30 + return Collections.unmodifiableSet(methodNames); 10.31 } 10.32 10.33 /**
11.1 --- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java Wed Oct 01 12:22:12 2014 +0200 11.2 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java Thu Sep 25 15:53:47 2014 +0200 11.3 @@ -38,7 +38,6 @@ 11.4 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SPLIT; 11.5 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SYMBOLS_ASSIGNED; 11.6 import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote; 11.7 - 11.8 import java.io.PrintWriter; 11.9 import java.util.ArrayList; 11.10 import java.util.EnumSet; 11.11 @@ -48,7 +47,6 @@ 11.12 import java.util.Map; 11.13 import java.util.Map.Entry; 11.14 import java.util.Set; 11.15 - 11.16 import jdk.nashorn.internal.AssertsEnabled; 11.17 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; 11.18 import jdk.nashorn.internal.ir.FunctionNode; 11.19 @@ -627,7 +625,7 @@ 11.20 11.21 /** 11.22 * Start a compilation phase 11.23 - * @param compiler 11.24 + * @param compiler the compiler to use 11.25 * @param functionNode function to compile 11.26 * @return function node 11.27 */
12.1 --- a/src/jdk/nashorn/internal/codegen/CompileUnit.java Wed Oct 01 12:22:12 2014 +0200 12.2 +++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java Thu Sep 25 15:53:47 2014 +0200 12.3 @@ -60,6 +60,10 @@ 12.4 emittedUnitCount++; 12.5 } 12.6 12.7 + /** 12.8 + * Get the amount of emitted compile units so far in the system 12.9 + * @return emitted compile unit count 12.10 + */ 12.11 public static int getEmittedUnitCount() { 12.12 return emittedUnitCount; 12.13 } 12.14 @@ -72,6 +76,10 @@ 12.15 return isUsed; 12.16 } 12.17 12.18 + /** 12.19 + * Check if a compile unit has code, not counting inits and clinits 12.20 + * @return true of if there is "real code" in the compile unit 12.21 + */ 12.22 public boolean hasCode() { 12.23 return (classEmitter.getMethodCount() - classEmitter.getInitCount() - classEmitter.getClinitCount()) > 0; 12.24 }
13.1 --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Oct 01 12:22:12 2014 +0200 13.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java Thu Sep 25 15:53:47 2014 +0200 13.3 @@ -71,7 +71,6 @@ 13.4 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE; 13.5 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC; 13.6 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT; 13.7 - 13.8 import java.io.PrintStream; 13.9 import java.lang.reflect.Array; 13.10 import java.util.Collection; 13.11 @@ -107,6 +106,7 @@ 13.12 import jdk.nashorn.internal.runtime.RewriteException; 13.13 import jdk.nashorn.internal.runtime.Scope; 13.14 import jdk.nashorn.internal.runtime.ScriptObject; 13.15 +import jdk.nashorn.internal.runtime.ScriptRuntime; 13.16 import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; 13.17 import jdk.nashorn.internal.runtime.linker.Bootstrap; 13.18 import jdk.nashorn.internal.runtime.logging.DebugLogger; 13.19 @@ -181,9 +181,6 @@ 13.20 /** Bootstrap for array populators */ 13.21 private static final Handle POPULATE_ARRAY_BOOTSTRAP = new Handle(H_INVOKESTATIC, RewriteException.BOOTSTRAP.className(), RewriteException.BOOTSTRAP.name(), RewriteException.BOOTSTRAP.descriptor()); 13.22 13.23 - /** Bootstrap for global name invalidation */ 13.24 - private static final Handle INVALIDATE_NAME_BOOTSTRAP = new Handle(H_INVOKESTATIC, Global.BOOTSTRAP.className(), Global.BOOTSTRAP.name(), Global.BOOTSTRAP.descriptor()); 13.25 - 13.26 /** 13.27 * Constructor - internal use from ClassEmitter only 13.28 * @see ClassEmitter#method 13.29 @@ -2140,10 +2137,15 @@ 13.30 } 13.31 13.32 MethodEmitter invalidateSpecialName(final String name) { 13.33 - //this is a nop if the global hasn't registered this as a special name - we can just ignore it 13.34 - if (Global.instance().isSpecialName(name)) { 13.35 - debug("dynamic_invalidate_name", "name=", name); 13.36 - method.visitInvokeDynamicInsn(name, "()V", INVALIDATE_NAME_BOOTSTRAP); 13.37 + switch (name) { 13.38 + case "apply": 13.39 + case "call": 13.40 + debug("invalidate_name", "name=", name); 13.41 + load("Function"); 13.42 + invoke(ScriptRuntime.INVALIDATE_RESERVED_BUILTIN_NAME); 13.43 + break; 13.44 + default: 13.45 + break; 13.46 } 13.47 return this; 13.48 }
14.1 --- a/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java Wed Oct 01 12:22:12 2014 +0200 14.2 +++ b/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java Thu Sep 25 15:53:47 2014 +0200 14.3 @@ -429,7 +429,6 @@ 14.4 } 14.5 14.6 private static void doCleanup() throws IOException { 14.7 - final long start = System.nanoTime(); 14.8 final Path[] files = getAllRegularFilesInLastModifiedOrder(); 14.9 final int nFiles = files.length; 14.10 final int filesToDelete = Math.max(0, nFiles - MAX_FILES); 14.11 @@ -444,8 +443,7 @@ 14.12 // does not increase filesDeleted 14.13 } 14.14 files[i] = null; // gc eligible 14.15 - }; 14.16 - final long duration = System.nanoTime() - start; 14.17 + } 14.18 } 14.19 14.20 private static Path[] getAllRegularFilesInLastModifiedOrder() throws IOException { 14.21 @@ -456,7 +454,7 @@ 14.22 @Override 14.23 public boolean test(final Path path) { 14.24 return !Files.isDirectory(path); 14.25 - }; 14.26 + } 14.27 }) 14.28 .map(new Function<Path, PathAndTime>() { 14.29 @Override 14.30 @@ -497,7 +495,7 @@ 14.31 private static long getTime(final Path path) { 14.32 try { 14.33 return Files.getLastModifiedTime(path).toMillis(); 14.34 - } catch (IOException e) { 14.35 + } catch (final IOException e) { 14.36 // All files for which we can't retrieve the last modified date will be considered oldest. 14.37 return -1L; 14.38 }
15.1 --- a/src/jdk/nashorn/internal/codegen/types/Type.java Wed Oct 01 12:22:12 2014 +0200 15.2 +++ b/src/jdk/nashorn/internal/codegen/types/Type.java Thu Sep 25 15:53:47 2014 +0200 15.3 @@ -47,7 +47,6 @@ 15.4 import static jdk.internal.org.objectweb.asm.Opcodes.T_INT; 15.5 import static jdk.internal.org.objectweb.asm.Opcodes.T_LONG; 15.6 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; 15.7 - 15.8 import java.io.DataInput; 15.9 import java.io.DataOutput; 15.10 import java.io.IOException; 15.11 @@ -299,7 +298,7 @@ 15.12 * 15.13 * @param typeMap the type map 15.14 * @param output data output 15.15 - * @throws IOException 15.16 + * @throws IOException if write cannot be completed 15.17 */ 15.18 public static void writeTypeMap(final Map<Integer, Type> typeMap, final DataOutput output) throws IOException { 15.19 if (typeMap == null) { 15.20 @@ -329,7 +328,7 @@ 15.21 * 15.22 * @param input data input 15.23 * @return type map 15.24 - * @throws IOException 15.25 + * @throws IOException if read cannot be completed 15.26 */ 15.27 public static Map<Integer, Type> readTypeMap(final DataInput input) throws IOException { 15.28 final int size = input.readInt();
16.1 --- a/src/jdk/nashorn/internal/ir/FunctionNode.java Wed Oct 01 12:22:12 2014 +0200 16.2 +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java Thu Sep 25 15:53:47 2014 +0200 16.3 @@ -238,17 +238,21 @@ 16.4 * Note that even IS_STRICT is one such flag but that requires special handling. 16.5 */ 16.6 16.7 - // parser, lower debugging this function 16.8 + /** parser, print parse tree */ 16.9 public static final int IS_PRINT_PARSE = 1 << 18; 16.10 + /** parser, print lower parse tree */ 16.11 public static final int IS_PRINT_LOWER_PARSE = 1 << 19; 16.12 + /** parser, print AST */ 16.13 public static final int IS_PRINT_AST = 1 << 20; 16.14 + /** parser, print lower AST */ 16.15 public static final int IS_PRINT_LOWER_AST = 1 << 21; 16.16 + /** parser, print symbols */ 16.17 public static final int IS_PRINT_SYMBOLS = 1 << 22; 16.18 16.19 + // callsite tracing, profiling within this function 16.20 /** profile callsites in this function? */ 16.21 public static final int IS_PROFILE = 1 << 23; 16.22 16.23 - // callsite tracing, profiling within this function 16.24 /** trace callsite enterexit in this function? */ 16.25 public static final int IS_TRACE_ENTEREXIT = 1 << 24; 16.26 16.27 @@ -337,7 +341,7 @@ 16.28 private FunctionNode( 16.29 final FunctionNode functionNode, 16.30 final long lastToken, 16.31 - Object endParserState, 16.32 + final Object endParserState, 16.33 final int flags, 16.34 final String name, 16.35 final Type returnType,
17.1 --- a/src/jdk/nashorn/internal/ir/LiteralNode.java Wed Oct 01 12:22:12 2014 +0200 17.2 +++ b/src/jdk/nashorn/internal/ir/LiteralNode.java Thu Sep 25 15:53:47 2014 +0200 17.3 @@ -237,6 +237,10 @@ 17.4 return value; 17.5 } 17.6 17.7 + private static Expression[] valueToArray(final List<Expression> value) { 17.8 + return value.toArray(new Expression[value.size()]); 17.9 + } 17.10 + 17.11 /** 17.12 * Create a new null literal 17.13 * 17.14 @@ -981,10 +985,9 @@ 17.15 * @return the new literal node 17.16 */ 17.17 public static LiteralNode<Expression[]> newInstance(final long token, final int finish, final List<Expression> value) { 17.18 - return new ArrayLiteralNode(token, finish, value.toArray(new Expression[value.size()])); 17.19 + return new ArrayLiteralNode(token, finish, valueToArray(value)); 17.20 } 17.21 17.22 - 17.23 /** 17.24 * Create a new array literal based on a parent node (source, token, finish) 17.25 * 17.26 @@ -994,7 +997,7 @@ 17.27 * @return the new literal node 17.28 */ 17.29 public static LiteralNode<?> newInstance(final Node parent, final List<Expression> value) { 17.30 - return new ArrayLiteralNode(parent.getToken(), parent.getFinish(), value.toArray(new Expression[value.size()])); 17.31 + return new ArrayLiteralNode(parent.getToken(), parent.getFinish(), valueToArray(value)); 17.32 } 17.33 17.34 /**
18.1 --- a/src/jdk/nashorn/internal/ir/Symbol.java Wed Oct 01 12:22:12 2014 +0200 18.2 +++ b/src/jdk/nashorn/internal/ir/Symbol.java Thu Sep 25 15:53:47 2014 +0200 18.3 @@ -448,14 +448,25 @@ 18.4 return (flags & IS_FUNCTION_SELF) != 0; 18.5 } 18.6 18.7 + /** 18.8 + * Is this a block scoped symbol 18.9 + * @return true if block scoped 18.10 + */ 18.11 public boolean isBlockScoped() { 18.12 return isLet() || isConst(); 18.13 } 18.14 18.15 + /** 18.16 + * Has this symbol been declared 18.17 + * @return true if declared 18.18 + */ 18.19 public boolean hasBeenDeclared() { 18.20 return (flags & HAS_BEEN_DECLARED) != 0; 18.21 } 18.22 18.23 + /** 18.24 + * Mark this symbol as declared 18.25 + */ 18.26 public void setHasBeenDeclared() { 18.27 if (!hasBeenDeclared()) { 18.28 flags |= HAS_BEEN_DECLARED;
19.1 --- a/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java Wed Oct 01 12:22:12 2014 +0200 19.2 +++ b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java Thu Sep 25 15:53:47 2014 +0200 19.3 @@ -116,6 +116,10 @@ 19.4 19.5 private static final String VOID_TAG = "[VOID]"; 19.6 19.7 + private static void err(final String str) { 19.8 + Context.getContext().getErr().println(str); 19.9 + } 19.10 + 19.11 /** 19.12 * Tracer that is applied before a value is returned from the traced function. It will output the return 19.13 * value and its class 19.14 @@ -124,13 +128,16 @@ 19.15 * @return return value unmodified 19.16 */ 19.17 static Object traceReturn(final DebugLogger logger, final Object value) { 19.18 - if (logger.isEnabled()) { 19.19 - final String str = " return" + 19.20 - (VOID_TAG.equals(value) ? 19.21 - ";" : 19.22 - " " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']')); 19.23 + final String str = " return" + 19.24 + (VOID_TAG.equals(value) ? 19.25 + ";" : 19.26 + " " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']')); 19.27 + if (logger == null) { 19.28 + err(str); 19.29 + } else if (logger.isEnabled()) { 19.30 logger.log(TRACE_LEVEL, str); 19.31 } 19.32 + 19.33 return value; 19.34 } 19.35 19.36 @@ -169,8 +176,11 @@ 19.37 } 19.38 } 19.39 19.40 - assert logger != null; 19.41 - logger.log(TRACE_LEVEL, sb); 19.42 + if (logger == null) { 19.43 + err(sb.toString()); 19.44 + } else { 19.45 + logger.log(TRACE_LEVEL, sb); 19.46 + } 19.47 stacktrace(logger); 19.48 } 19.49 19.50 @@ -181,7 +191,12 @@ 19.51 final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 19.52 final PrintStream ps = new PrintStream(baos); 19.53 new Throwable().printStackTrace(ps); 19.54 - logger.log(TRACE_LEVEL, baos.toString()); 19.55 + final String st = baos.toString(); 19.56 + if (logger == null) { 19.57 + err(st); 19.58 + } else { 19.59 + logger.log(TRACE_LEVEL, st); 19.60 + } 19.61 } 19.62 19.63 private static String argString(final Object arg) { 19.64 @@ -201,7 +216,7 @@ 19.65 if (arg instanceof ScriptObject) { 19.66 return arg.toString() + 19.67 " (map=" + Debug.id(((ScriptObject)arg).getMap()) + 19.68 - ")"; 19.69 + ')'; 19.70 } 19.71 19.72 return arg.toString(); 19.73 @@ -209,6 +224,18 @@ 19.74 19.75 /** 19.76 * Add a debug printout to a method handle, tracing parameters and return values 19.77 + * Output will be unconditional to stderr 19.78 + * 19.79 + * @param mh method handle to trace 19.80 + * @param tag start of trace message 19.81 + * @return traced method handle 19.82 + */ 19.83 + public static MethodHandle addDebugPrintout(final MethodHandle mh, final Object tag) { 19.84 + return addDebugPrintout(null, Level.OFF, mh, 0, true, tag); 19.85 + } 19.86 + 19.87 + /** 19.88 + * Add a debug printout to a method handle, tracing parameters and return values 19.89 * 19.90 * @param logger a specific logger to which to write the output 19.91 * @param level level over which to print 19.92 @@ -222,6 +249,20 @@ 19.93 19.94 /** 19.95 * Add a debug printout to a method handle, tracing parameters and return values 19.96 + * Output will be unconditional to stderr 19.97 + * 19.98 + * @param mh method handle to trace 19.99 + * @param paramStart first param to print/trace 19.100 + * @param printReturnValue should we print/trace return value if available? 19.101 + * @param tag start of trace message 19.102 + * @return traced method handle 19.103 + */ 19.104 + public static MethodHandle addDebugPrintout(final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Object tag) { 19.105 + return addDebugPrintout(null, Level.OFF, mh, paramStart, printReturnValue, tag); 19.106 + } 19.107 + 19.108 + /** 19.109 + * Add a debug printout to a method handle, tracing parameters and return values 19.110 * 19.111 * @param logger a specific logger to which to write the output 19.112 * @param level level over which to print 19.113 @@ -240,7 +281,6 @@ 19.114 return mh; 19.115 } 19.116 19.117 - assert logger != null; 19.118 assert TRACE != null; 19.119 19.120 MethodHandle trace = MethodHandles.insertArguments(TRACE, 0, logger, tag, paramStart); 19.121 @@ -428,6 +468,12 @@ 19.122 } 19.123 19.124 @Override 19.125 + public MethodHandle identity(final Class<?> type) { 19.126 + final MethodHandle mh = MethodHandles.identity(type); 19.127 + return debug(mh, "identity", type); 19.128 + } 19.129 + 19.130 + @Override 19.131 public MethodHandle asCollector(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) { 19.132 final MethodHandle mh = handle.asCollector(arrayType, arrayLength); 19.133 return debug(mh, "asCollector", handle, arrayType, arrayLength);
20.1 --- a/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java Wed Oct 01 12:22:12 2014 +0200 20.2 +++ b/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java Thu Sep 25 15:53:47 2014 +0200 20.3 @@ -173,6 +173,15 @@ 20.4 public MethodHandle constant(Class<?> type, Object value); 20.5 20.6 /** 20.7 + * Wrapper for {@link java.lang.invoke.MethodHandles#identity(Class)} 20.8 + * 20.9 + * @param type type of value 20.10 + * 20.11 + * @return method handle that returns identity argument 20.12 + */ 20.13 + public MethodHandle identity(Class<?> type); 20.14 + 20.15 + /** 20.16 * Wrapper for {@link java.lang.invoke.MethodHandle#asType(MethodType)} 20.17 * 20.18 * @param handle method handle for type conversion
21.1 --- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java Wed Oct 01 12:22:12 2014 +0200 21.2 +++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java Thu Sep 25 15:53:47 2014 +0200 21.3 @@ -31,6 +31,7 @@ 21.4 21.5 import java.nio.ByteBuffer; 21.6 import java.nio.ByteOrder; 21.7 + 21.8 import jdk.internal.dynalink.CallSiteDescriptor; 21.9 import jdk.internal.dynalink.linker.GuardedInvocation; 21.10 import jdk.internal.dynalink.linker.LinkRequest;
22.1 --- a/src/jdk/nashorn/internal/objects/Global.java Wed Oct 01 12:22:12 2014 +0200 22.2 +++ b/src/jdk/nashorn/internal/objects/Global.java Thu Sep 25 15:53:47 2014 +0200 22.3 @@ -25,23 +25,19 @@ 22.4 22.5 package jdk.nashorn.internal.objects; 22.6 22.7 -import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; 22.8 import static jdk.nashorn.internal.lookup.Lookup.MH; 22.9 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; 22.10 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 22.11 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 22.12 - 22.13 import java.io.IOException; 22.14 import java.io.PrintWriter; 22.15 -import java.lang.invoke.CallSite; 22.16 -import java.lang.invoke.ConstantCallSite; 22.17 import java.lang.invoke.MethodHandle; 22.18 import java.lang.invoke.MethodHandles; 22.19 -import java.lang.invoke.MethodType; 22.20 import java.lang.invoke.SwitchPoint; 22.21 import java.lang.reflect.Field; 22.22 +import java.util.ArrayList; 22.23 import java.util.Arrays; 22.24 -import java.util.HashMap; 22.25 +import java.util.List; 22.26 import java.util.Map; 22.27 import java.util.concurrent.Callable; 22.28 import java.util.concurrent.ConcurrentHashMap; 22.29 @@ -52,8 +48,6 @@ 22.30 import jdk.internal.dynalink.linker.LinkRequest; 22.31 import jdk.nashorn.api.scripting.ClassFilter; 22.32 import jdk.nashorn.api.scripting.ScriptObjectMirror; 22.33 -import jdk.nashorn.internal.codegen.ApplySpecialization; 22.34 -import jdk.nashorn.internal.codegen.CompilerConstants.Call; 22.35 import jdk.nashorn.internal.lookup.Lookup; 22.36 import jdk.nashorn.internal.objects.annotations.Attribute; 22.37 import jdk.nashorn.internal.objects.annotations.Property; 22.38 @@ -72,6 +66,7 @@ 22.39 import jdk.nashorn.internal.runtime.ScriptObject; 22.40 import jdk.nashorn.internal.runtime.ScriptRuntime; 22.41 import jdk.nashorn.internal.runtime.ScriptingFunctions; 22.42 +import jdk.nashorn.internal.runtime.Specialization; 22.43 import jdk.nashorn.internal.runtime.arrays.ArrayData; 22.44 import jdk.nashorn.internal.runtime.linker.Bootstrap; 22.45 import jdk.nashorn.internal.runtime.linker.InvokeByName; 22.46 @@ -107,10 +102,6 @@ 22.47 * it's when you start adding property checks for said builtins you have 22.48 * problems with guard speed. 22.49 */ 22.50 - public final Map<String, SwitchPoint> optimisticFunctionMap; 22.51 - 22.52 - /** Name invalidator for things like call/apply */ 22.53 - public static final Call BOOTSTRAP = staticCall(MethodHandles.lookup(), Global.class, "invalidateNameBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class); 22.54 22.55 /** Nashorn extension: arguments array */ 22.56 @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE) 22.57 @@ -428,9 +419,6 @@ 22.58 private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class); 22.59 private static final MethodHandle EXIT = findOwnMH_S("exit", Object.class, Object.class, Object.class); 22.60 22.61 - /** Invalidate a reserved name, such as "apply" or "call" if assigned */ 22.62 - public MethodHandle INVALIDATE_RESERVED_NAME = MH.bindTo(findOwnMH_V("invalidateReservedName", void.class, String.class), this); 22.63 - 22.64 // initialized by nasgen 22.65 private static PropertyMap $nasgenmap$; 22.66 22.67 @@ -482,7 +470,6 @@ 22.68 super(checkAndGetMap(context)); 22.69 this.context = context; 22.70 this.setIsScope(); 22.71 - this.optimisticFunctionMap = new HashMap<>(); 22.72 //we can only share one instance of Global constants between globals, or we consume way too much 22.73 //memory - this is good enough for most programs 22.74 while (gcsInstance.get() == null) { 22.75 @@ -574,6 +561,7 @@ 22.76 * 22.77 * @param engine ScriptEngine to initialize 22.78 */ 22.79 + @SuppressWarnings("hiding") 22.80 public void initBuiltinObjects(final ScriptEngine engine) { 22.81 if (this.builtinObject != null) { 22.82 // already initialized, just return 22.83 @@ -918,10 +906,12 @@ 22.84 } 22.85 22.86 switch (nameStr) { 22.87 - case "context": 22.88 - return sctxt; 22.89 - case "engine": 22.90 - return global.engine; 22.91 + case "context": 22.92 + return sctxt; 22.93 + case "engine": 22.94 + return global.engine; 22.95 + default: 22.96 + break; 22.97 } 22.98 22.99 if (self == UNDEFINED) { 22.100 @@ -1244,6 +1234,40 @@ 22.101 return instance.function == instance.getBuiltinFunction(); 22.102 } 22.103 22.104 + /** 22.105 + * Get the switchpoint used to check property changes for Function.prototype.apply 22.106 + * @return the switchpoint guarding apply (same as guarding call, and everything else in function) 22.107 + */ 22.108 + public static SwitchPoint getBuiltinFunctionApplySwitchPoint() { 22.109 + return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint(); 22.110 + } 22.111 + 22.112 + private static boolean isBuiltinFunctionProperty(final String name) { 22.113 + final Global instance = Global.instance(); 22.114 + final ScriptFunction builtinFunction = instance.getBuiltinFunction(); 22.115 + if (builtinFunction == null) { 22.116 + return false; //conservative for compile-only mode 22.117 + } 22.118 + final boolean isBuiltinFunction = instance.function == builtinFunction; 22.119 + return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin(); 22.120 + } 22.121 + 22.122 + /** 22.123 + * Check if the Function.prototype.apply has not been replaced 22.124 + * @return true if Function.prototype.apply has been replaced 22.125 + */ 22.126 + public static boolean isBuiltinFunctionPrototypeApply() { 22.127 + return isBuiltinFunctionProperty("apply"); 22.128 + } 22.129 + 22.130 + /** 22.131 + * Check if the Function.prototype.apply has not been replaced 22.132 + * @return true if Function.prototype.call has been replaced 22.133 + */ 22.134 + public static boolean isBuiltinFunctionPrototypeCall() { 22.135 + return isBuiltinFunctionProperty("call"); 22.136 + } 22.137 + 22.138 private ScriptFunction getBuiltinJSAdapter() { 22.139 return builtinJSAdapter; 22.140 } 22.141 @@ -1688,6 +1712,13 @@ 22.142 splitState = state; 22.143 } 22.144 22.145 + private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) { 22.146 + final T func = initConstructor(name, clazz); 22.147 + tagBuiltinProperties(name, func); 22.148 + return func; 22.149 + } 22.150 + 22.151 + @SuppressWarnings("hiding") 22.152 private void init(final ScriptEngine engine) { 22.153 assert Context.getGlobal() == this : "this global is not set as current"; 22.154 22.155 @@ -1702,8 +1733,19 @@ 22.156 // initialize global function properties 22.157 this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL); 22.158 22.159 - this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT, 22.160 - new MethodHandle[] { GlobalFunctions.PARSEINT_OI, GlobalFunctions.PARSEINT_O }); 22.161 + this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT, 22.162 + new Specialization[] { 22.163 + new Specialization(GlobalFunctions.PARSEINT_Z), 22.164 + new Specialization(GlobalFunctions.PARSEINT_I), 22.165 + new Specialization(GlobalFunctions.PARSEINT_J), 22.166 + new Specialization(GlobalFunctions.PARSEINT_OI), 22.167 + new Specialization(GlobalFunctions.PARSEINT_O) }); 22.168 + this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT); 22.169 + this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN, 22.170 + new Specialization[] { 22.171 + new Specialization(GlobalFunctions.IS_NAN_I), 22.172 + new Specialization(GlobalFunctions.IS_NAN_J), 22.173 + new Specialization(GlobalFunctions.IS_NAN_D) }); 22.174 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT); 22.175 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN); 22.176 this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE); 22.177 @@ -1720,15 +1762,15 @@ 22.178 this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT); 22.179 22.180 // built-in constructors 22.181 - this.builtinArray = initConstructor("Array", ScriptFunction.class); 22.182 - this.builtinBoolean = initConstructor("Boolean", ScriptFunction.class); 22.183 - this.builtinDate = initConstructor("Date", ScriptFunction.class); 22.184 - this.builtinJSON = initConstructor("JSON", ScriptObject.class); 22.185 - this.builtinJSAdapter = initConstructor("JSAdapter", ScriptFunction.class); 22.186 - this.builtinMath = initConstructor("Math", ScriptObject.class); 22.187 - this.builtinNumber = initConstructor("Number", ScriptFunction.class); 22.188 - this.builtinRegExp = initConstructor("RegExp", ScriptFunction.class); 22.189 - this.builtinString = initConstructor("String", ScriptFunction.class); 22.190 + this.builtinArray = initConstructorAndSwitchPoint("Array", ScriptFunction.class); 22.191 + this.builtinBoolean = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class); 22.192 + this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class); 22.193 + this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class); 22.194 + this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class); 22.195 + this.builtinMath = initConstructorAndSwitchPoint("Math", ScriptObject.class); 22.196 + this.builtinNumber = initConstructorAndSwitchPoint("Number", ScriptFunction.class); 22.197 + this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class); 22.198 + this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class); 22.199 22.200 // initialize String.prototype.length to 0 22.201 // add String.prototype.length 22.202 @@ -1830,6 +1872,8 @@ 22.203 // Error.prototype.message = ""; 22.204 errorProto.set(NativeError.MESSAGE, "", 0); 22.205 22.206 + tagBuiltinProperties("Error", builtinError); 22.207 + 22.208 this.builtinEvalError = initErrorSubtype("EvalError", errorProto); 22.209 this.builtinRangeError = initErrorSubtype("RangeError", errorProto); 22.210 this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto); 22.211 @@ -1844,6 +1888,7 @@ 22.212 prototype.set(NativeError.NAME, name, 0); 22.213 prototype.set(NativeError.MESSAGE, "", 0); 22.214 prototype.setInitialProto(errorProto); 22.215 + tagBuiltinProperties(name, cons); 22.216 return cons; 22.217 } 22.218 22.219 @@ -1910,17 +1955,18 @@ 22.220 } 22.221 22.222 private void initTypedArray() { 22.223 - this.builtinArrayBuffer = initConstructor("ArrayBuffer", ScriptFunction.class); 22.224 - this.builtinDataView = initConstructor("DataView", ScriptFunction.class); 22.225 - this.builtinInt8Array = initConstructor("Int8Array", ScriptFunction.class); 22.226 - this.builtinUint8Array = initConstructor("Uint8Array", ScriptFunction.class); 22.227 - this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray", ScriptFunction.class); 22.228 - this.builtinInt16Array = initConstructor("Int16Array", ScriptFunction.class); 22.229 - this.builtinUint16Array = initConstructor("Uint16Array", ScriptFunction.class); 22.230 - this.builtinInt32Array = initConstructor("Int32Array", ScriptFunction.class); 22.231 - this.builtinUint32Array = initConstructor("Uint32Array", ScriptFunction.class); 22.232 - this.builtinFloat32Array = initConstructor("Float32Array", ScriptFunction.class); 22.233 - this.builtinFloat64Array = initConstructor("Float64Array", ScriptFunction.class); 22.234 + this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class); 22.235 + this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class); 22.236 + this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class); 22.237 + this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class); 22.238 + this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class); 22.239 + this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class); 22.240 + this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class); 22.241 + this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class); 22.242 + this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class); 22.243 + this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class); 22.244 + this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class); 22.245 + 22.246 } 22.247 22.248 private void copyBuiltins() { 22.249 @@ -1993,10 +2039,6 @@ 22.250 return UNDEFINED; 22.251 } 22.252 22.253 - /** 22.254 - * These classes are generated by nasgen tool and so we have to use 22.255 - * reflection to load and create new instance of these classes. 22.256 - */ 22.257 private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) { 22.258 try { 22.259 // Assuming class name pattern for built-in JS constructors. 22.260 @@ -2021,12 +2063,52 @@ 22.261 } 22.262 22.263 res.setIsBuiltin(); 22.264 + 22.265 return res; 22.266 } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) { 22.267 throw new RuntimeException(e); 22.268 } 22.269 } 22.270 22.271 + private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) { 22.272 + final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>(); 22.273 + 22.274 + list.addAll(Arrays.asList(func.getMap().getProperties())); 22.275 + 22.276 + if (func instanceof ScriptFunction) { 22.277 + final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func); 22.278 + if (proto != null) { 22.279 + list.addAll(Arrays.asList(proto.getMap().getProperties())); 22.280 + } 22.281 + } 22.282 + 22.283 + final jdk.nashorn.internal.runtime.Property prop = getProperty(name); 22.284 + if (prop != null) { 22.285 + list.add(prop); 22.286 + } 22.287 + 22.288 + return list; 22.289 + } 22.290 + 22.291 + /** 22.292 + * Given a builtin object, traverse its properties recursively and associate them with a name that 22.293 + * will be a key to their invalidation switchpoint. 22.294 + * @param name name for key 22.295 + * @param func builtin script object 22.296 + */ 22.297 + private void tagBuiltinProperties(final String name, final ScriptObject func) { 22.298 + SwitchPoint sp = context.getBuiltinSwitchPoint(name); 22.299 + if (sp == null) { 22.300 + sp = context.newBuiltinSwitchPoint(name); 22.301 + } 22.302 + 22.303 + //get all builtin properties in this builtin object and register switchpoints keyed on the propery name, 22.304 + //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc 22.305 + for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) { 22.306 + prop.setBuiltinSwitchPoint(sp); 22.307 + } 22.308 + } 22.309 + 22.310 // Function and Object constructors are inter-dependent. Also, 22.311 // Function.prototype 22.312 // functions are not properly initialized. We fix the references here. 22.313 @@ -2035,7 +2117,8 @@ 22.314 // to play with object references carefully!! 22.315 private void initFunctionAndObject() { 22.316 // First-n-foremost is Function 22.317 - this.builtinFunction = initConstructor("Function", ScriptFunction.class); 22.318 + 22.319 + this.builtinFunction = initConstructor("Function", ScriptFunction.class); 22.320 22.321 // create global anonymous function 22.322 final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(); 22.323 @@ -2101,13 +2184,6 @@ 22.324 } 22.325 } 22.326 22.327 - //make sure apply and call have the same invalidation switchpoint 22.328 - final SwitchPoint sp = new SwitchPoint(); 22.329 - optimisticFunctionMap.put("apply", sp); 22.330 - optimisticFunctionMap.put("call", sp); 22.331 - getFunctionPrototype().getProperty("apply").setChangeCallback(sp); 22.332 - getFunctionPrototype().getProperty("call").setChangeCallback(sp); 22.333 - 22.334 properties = getObjectPrototype().getMap().getProperties(); 22.335 22.336 for (final jdk.nashorn.internal.runtime.Property property : properties) { 22.337 @@ -2125,10 +2201,10 @@ 22.338 } 22.339 } 22.340 } 22.341 - } 22.342 22.343 - private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) { 22.344 - return MH.findVirtual(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types)); 22.345 + tagBuiltinProperties("Object", builtinObject); 22.346 + tagBuiltinProperties("Function", builtinFunction); 22.347 + tagBuiltinProperties("Function", anon); 22.348 } 22.349 22.350 private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) { 22.351 @@ -2147,62 +2223,4 @@ 22.352 protected boolean isGlobal() { 22.353 return true; 22.354 } 22.355 - 22.356 - /** 22.357 - * Check if there is a switchpoint for a reserved name. If there 22.358 - * is, it must be invalidated upon properties with this name 22.359 - * @param name property name 22.360 - * @return switchpoint for invalidating this property, or null if not registered 22.361 - */ 22.362 - public SwitchPoint getChangeCallback(final String name) { 22.363 - return optimisticFunctionMap.get(name); 22.364 - } 22.365 - 22.366 - /** 22.367 - * Is this a special name, that might be subject to invalidation 22.368 - * on write, such as "apply" or "call" 22.369 - * @param name name to check 22.370 - * @return true if special name 22.371 - */ 22.372 - public boolean isSpecialName(final String name) { 22.373 - return getChangeCallback(name) != null; 22.374 - } 22.375 - 22.376 - /** 22.377 - * Check if a reserved property name is invalidated 22.378 - * @param name property name 22.379 - * @return true if someone has written to it since Global was instantiated 22.380 - */ 22.381 - public boolean isSpecialNameValid(final String name) { 22.382 - final SwitchPoint sp = getChangeCallback(name); 22.383 - return sp != null && !sp.hasBeenInvalidated(); 22.384 - } 22.385 - 22.386 - /** 22.387 - * Tag a reserved name as invalidated - used when someone writes 22.388 - * to a property with this name - overly conservative, but link time 22.389 - * is too late to apply e.g. apply->call specialization 22.390 - * @param name property name 22.391 - */ 22.392 - public void invalidateReservedName(final String name) { 22.393 - final SwitchPoint sp = getChangeCallback(name); 22.394 - if (sp != null) { 22.395 - getContext().getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint"); 22.396 - SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 22.397 - } 22.398 - } 22.399 - 22.400 - /** 22.401 - * Bootstrapper for invalidating a builtin name 22.402 - * @param lookup lookup 22.403 - * @param name name to invalidate 22.404 - * @param type methodhandle type 22.405 - * @return callsite for invalidator 22.406 - */ 22.407 - public static CallSite invalidateNameBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type) { 22.408 - final MethodHandle target = MH.insertArguments(Global.instance().INVALIDATE_RESERVED_NAME, 0, name); 22.409 - return new ConstantCallSite(target); 22.410 - } 22.411 - 22.412 - 22.413 }
23.1 --- a/src/jdk/nashorn/internal/objects/NativeArray.java Wed Oct 01 12:22:12 2014 +0200 23.2 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java Thu Sep 25 15:53:47 2014 +0200 23.3 @@ -1,5 +1,5 @@ 23.4 /* 23.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 23.6 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 23.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 23.8 * 23.9 * This code is free software; you can redistribute it and/or modify it 23.10 @@ -33,8 +33,8 @@ 23.11 import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator; 23.12 import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator; 23.13 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT; 23.14 - 23.15 import java.lang.invoke.MethodHandle; 23.16 +import java.lang.invoke.SwitchPoint; 23.17 import java.util.ArrayList; 23.18 import java.util.Arrays; 23.19 import java.util.Collections; 23.20 @@ -52,12 +52,13 @@ 23.21 import jdk.nashorn.internal.objects.annotations.Getter; 23.22 import jdk.nashorn.internal.objects.annotations.ScriptClass; 23.23 import jdk.nashorn.internal.objects.annotations.Setter; 23.24 -import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; 23.25 import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 23.26 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 23.27 import jdk.nashorn.internal.objects.annotations.Where; 23.28 import jdk.nashorn.internal.runtime.Context; 23.29 import jdk.nashorn.internal.runtime.Debug; 23.30 import jdk.nashorn.internal.runtime.JSType; 23.31 +import jdk.nashorn.internal.runtime.OptimisticBuiltins; 23.32 import jdk.nashorn.internal.runtime.PropertyDescriptor; 23.33 import jdk.nashorn.internal.runtime.PropertyMap; 23.34 import jdk.nashorn.internal.runtime.ScriptFunction; 23.35 @@ -67,17 +68,20 @@ 23.36 import jdk.nashorn.internal.runtime.arrays.ArrayData; 23.37 import jdk.nashorn.internal.runtime.arrays.ArrayIndex; 23.38 import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator; 23.39 +import jdk.nashorn.internal.runtime.arrays.ContinuousArrayData; 23.40 +import jdk.nashorn.internal.runtime.arrays.IntElements; 23.41 +import jdk.nashorn.internal.runtime.arrays.IntOrLongElements; 23.42 import jdk.nashorn.internal.runtime.arrays.IteratorAction; 23.43 +import jdk.nashorn.internal.runtime.arrays.NumericElements; 23.44 import jdk.nashorn.internal.runtime.linker.Bootstrap; 23.45 import jdk.nashorn.internal.runtime.linker.InvokeByName; 23.46 -import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; 23.47 23.48 /** 23.49 * Runtime representation of a JavaScript array. NativeArray only holds numeric 23.50 * keyed values. All other values are stored in spill. 23.51 */ 23.52 @ScriptClass("Array") 23.53 -public final class NativeArray extends ScriptObject { 23.54 +public final class NativeArray extends ScriptObject implements OptimisticBuiltins { 23.55 private static final Object JOIN = new Object(); 23.56 private static final Object EVERY_CALLBACK_INVOKER = new Object(); 23.57 private static final Object SOME_CALLBACK_INVOKER = new Object(); 23.58 @@ -88,6 +92,16 @@ 23.59 private static final Object CALL_CMP = new Object(); 23.60 private static final Object TO_LOCALE_STRING = new Object(); 23.61 23.62 + private SwitchPoint lengthMadeNotWritableSwitchPoint; 23.63 + private PushLinkLogic pushLinkLogic; 23.64 + private PopLinkLogic popLinkLogic; 23.65 + 23.66 + /** 23.67 + * Index for the modification SwitchPoint that triggers when length 23.68 + * becomes not writable 23.69 + */ 23.70 + private static final int LENGTH_NOT_WRITABLE_SWITCHPOINT = 0; 23.71 + 23.72 /* 23.73 * Constructors. 23.74 */ 23.75 @@ -420,6 +434,28 @@ 23.76 return getArray().asObjectArray(); 23.77 } 23.78 23.79 + @Override 23.80 + public void setIsLengthNotWritable() { 23.81 + super.setIsLengthNotWritable(); 23.82 + /* 23.83 + * Switchpoints are created lazily. If we link any push or pop site, 23.84 + * we need to create the "length made not writable" switchpoint, if it 23.85 + * doesn't exist. 23.86 + * 23.87 + * If the switchpoint already exists, we will find it here, and invalidate 23.88 + * it, invalidating all previous callsites that use it. 23.89 + * 23.90 + * If the switchpoint doesn't exist, no push/pop has been linked so far, 23.91 + * because that would create it too. We invalidate it immediately and the 23.92 + * check link logic for all future callsites will fail immediately at link 23.93 + * time 23.94 + */ 23.95 + if (lengthMadeNotWritableSwitchPoint == null) { 23.96 + lengthMadeNotWritableSwitchPoint = new SwitchPoint(); 23.97 + } 23.98 + SwitchPoint.invalidateAll(new SwitchPoint[] { lengthMadeNotWritableSwitchPoint }); 23.99 + } 23.100 + 23.101 /** 23.102 * ECMA 15.4.3.2 Array.isArray ( arg ) 23.103 * 23.104 @@ -638,7 +674,7 @@ 23.105 * @param self self reference 23.106 * @return the new NativeArray 23.107 */ 23.108 - @SpecializedConstructor 23.109 + @SpecializedFunction(isConstructor=true) 23.110 public static NativeArray construct(final boolean newObj, final Object self) { 23.111 return new NativeArray(0); 23.112 } 23.113 @@ -653,7 +689,7 @@ 23.114 * @param element first element 23.115 * @return the new NativeArray 23.116 */ 23.117 - @SpecializedConstructor 23.118 + @SpecializedFunction(isConstructor=true) 23.119 public static Object construct(final boolean newObj, final Object self, final boolean element) { 23.120 return new NativeArray(new Object[] { element }); 23.121 } 23.122 @@ -668,7 +704,7 @@ 23.123 * @param length array length 23.124 * @return the new NativeArray 23.125 */ 23.126 - @SpecializedConstructor 23.127 + @SpecializedFunction(isConstructor=true) 23.128 public static NativeArray construct(final boolean newObj, final Object self, final int length) { 23.129 if (length >= 0) { 23.130 return new NativeArray(length); 23.131 @@ -687,7 +723,7 @@ 23.132 * @param length array length 23.133 * @return the new NativeArray 23.134 */ 23.135 - @SpecializedConstructor 23.136 + @SpecializedFunction(isConstructor=true) 23.137 public static NativeArray construct(final boolean newObj, final Object self, final long length) { 23.138 if (length >= 0L && length <= JSType.MAX_UINT) { 23.139 return new NativeArray(length); 23.140 @@ -706,7 +742,7 @@ 23.141 * @param length array length 23.142 * @return the new NativeArray 23.143 */ 23.144 - @SpecializedConstructor 23.145 + @SpecializedFunction(isConstructor=true) 23.146 public static NativeArray construct(final boolean newObj, final Object self, final double length) { 23.147 final long uint32length = JSType.toUint32(length); 23.148 23.149 @@ -721,7 +757,7 @@ 23.150 * ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] ) 23.151 * 23.152 * @param self self reference 23.153 - * @param args arguments to concat 23.154 + * @param args arguments 23.155 * @return resulting NativeArray 23.156 */ 23.157 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) 23.158 @@ -793,6 +829,68 @@ 23.159 } 23.160 23.161 /** 23.162 + * Specialization of pop for ContinuousArrayData 23.163 + * The link guard checks that the array is continuous AND not empty. 23.164 + * The runtime guard checks that the guard is continuous (CCE otherwise) 23.165 + * 23.166 + * Primitive specialization, {@link LinkLogic} 23.167 + * 23.168 + * @param self self reference 23.169 + * @return element popped 23.170 + * @throws ClassCastException if array is empty, facilitating Undefined return value 23.171 + */ 23.172 + @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class) 23.173 + public static int popInt(final Object self) { 23.174 + //must be non empty IntArrayData 23.175 + return getContinuousNonEmptyArrayDataCCE(self, IntElements.class).fastPopInt(); 23.176 + } 23.177 + 23.178 + /** 23.179 + * Specialization of pop for ContinuousArrayData 23.180 + * 23.181 + * Primitive specialization, {@link LinkLogic} 23.182 + * 23.183 + * @param self self reference 23.184 + * @return element popped 23.185 + * @throws ClassCastException if array is empty, facilitating Undefined return value 23.186 + */ 23.187 + @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class) 23.188 + public static long popLong(final Object self) { 23.189 + //must be non empty Int or LongArrayData 23.190 + return getContinuousNonEmptyArrayDataCCE(self, IntOrLongElements.class).fastPopLong(); 23.191 + } 23.192 + 23.193 + /** 23.194 + * Specialization of pop for ContinuousArrayData 23.195 + * 23.196 + * Primitive specialization, {@link LinkLogic} 23.197 + * 23.198 + * @param self self reference 23.199 + * @return element popped 23.200 + * @throws ClassCastException if array is empty, facilitating Undefined return value 23.201 + */ 23.202 + @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class) 23.203 + public static double popDouble(final Object self) { 23.204 + //must be non empty int long or double array data 23.205 + return getContinuousNonEmptyArrayDataCCE(self, NumericElements.class).fastPopDouble(); 23.206 + } 23.207 + 23.208 + /** 23.209 + * Specialization of pop for ContinuousArrayData 23.210 + * 23.211 + * Primitive specialization, {@link LinkLogic} 23.212 + * 23.213 + * @param self self reference 23.214 + * @return element popped 23.215 + * @throws ClassCastException if array is empty, facilitating Undefined return value 23.216 + */ 23.217 + @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class) 23.218 + public static Object popObject(final Object self) { 23.219 + //can be any data, because the numeric ones will throw cce and force relink 23.220 + return getContinuousArrayDataCCE(self, null).fastPopObject(); 23.221 + } 23.222 + 23.223 + /** 23.224 * ECMA 15.4.4.6 Array.prototype.pop () 23.225 * 23.226 * @param self self reference 23.227 @@ -829,6 +927,62 @@ 23.228 /** 23.229 * ECMA 15.4.4.7 Array.prototype.push (args...) 23.230 * 23.231 + * Primitive specialization, {@link LinkLogic} 23.232 + * 23.233 + * @param self self reference 23.234 + * @param arg a primitive to push 23.235 + * @return array length after push 23.236 + */ 23.237 + @SpecializedFunction(linkLogic=PushLinkLogic.class) 23.238 + public static long push(final Object self, final int arg) { 23.239 + return getContinuousArrayDataCCE(self, Integer.class).fastPush(arg); 23.240 + } 23.241 + 23.242 + /** 23.243 + * ECMA 15.4.4.7 Array.prototype.push (args...) 23.244 + * 23.245 + * Primitive specialization, {@link LinkLogic} 23.246 + * 23.247 + * @param self self reference 23.248 + * @param arg a primitive to push 23.249 + * @return array length after push 23.250 + */ 23.251 + @SpecializedFunction(linkLogic=PushLinkLogic.class) 23.252 + public static long push(final Object self, final long arg) { 23.253 + return getContinuousArrayDataCCE(self, Long.class).fastPush(arg); 23.254 + } 23.255 + 23.256 + /** 23.257 + * ECMA 15.4.4.7 Array.prototype.push (args...) 23.258 + * 23.259 + * Primitive specialization, {@link LinkLogic} 23.260 + * 23.261 + * @param self self reference 23.262 + * @param arg a primitive to push 23.263 + * @return array length after push 23.264 + */ 23.265 + @SpecializedFunction(linkLogic=PushLinkLogic.class) 23.266 + public static long push(final Object self, final double arg) { 23.267 + return getContinuousArrayDataCCE(self, Double.class).fastPush(arg); 23.268 + } 23.269 + 23.270 + /** 23.271 + * ECMA 15.4.4.7 Array.prototype.push (args...) 23.272 + * 23.273 + * Primitive specialization, {@link LinkLogic} 23.274 + * 23.275 + * @param self self reference 23.276 + * @param arg a primitive to push 23.277 + * @return array length after push 23.278 + */ 23.279 + @SpecializedFunction(name="push", linkLogic=PushLinkLogic.class) 23.280 + public static long pushObject(final Object self, final Object arg) { 23.281 + return getContinuousArrayDataCCE(self, Object.class).fastPush(arg); 23.282 + } 23.283 + 23.284 + /** 23.285 + * ECMA 15.4.4.7 Array.prototype.push (args...) 23.286 + * 23.287 * @param self self reference 23.288 * @param args arguments to push 23.289 * @return array length after pushes 23.290 @@ -857,61 +1011,6 @@ 23.291 } 23.292 23.293 /** 23.294 - * ECMA 15.4.4.7 Array.prototype.push (args...) specialized for single int argument 23.295 - * 23.296 - * @param self self reference 23.297 - * @param arg argument to push 23.298 - * @return array after pushes 23.299 - */ 23.300 -/* @SpecializedFunction 23.301 - public static long push(final Object self, final int arg) { 23.302 - try { 23.303 - final ScriptObject sobj = (ScriptObject)self; 23.304 - final ArrayData arrayData = sobj.getArray(); 23.305 - final long length = arrayData.length(); 23.306 - 23.307 - if (bulkable(sobj) && length + 1 <= JSType.MAX_UINT) { 23.308 - sobj.setArray(arrayData.ensure(length).set(ArrayIndex.getArrayIndex(length), arg, true)); 23.309 - return length + 1; 23.310 - } 23.311 - 23.312 - long len = JSType.toUint32(sobj.getLength()); 23.313 - sobj.set(len++, arg, true); 23.314 - sobj.set("length", len, true); 23.315 - return len; 23.316 - } catch (final ClassCastException | NullPointerException e) { 23.317 - throw typeError("not.an.object", ScriptRuntime.safeToString(self)); 23.318 - } 23.319 - } 23.320 -*/ 23.321 - /** 23.322 - * ECMA 15.4.4.7 Array.prototype.push (args...) specialized for single number argument 23.323 - * 23.324 - * @param self self reference 23.325 - * @param arg argument to push 23.326 - * @return array after pushes 23.327 - */ 23.328 - /* @SpecializedFunction 23.329 - public static long push(final Object self, final double arg) { 23.330 - try { 23.331 - final ScriptObject sobj = (ScriptObject)self; final ArrayData arrayData = sobj.getArray(); 23.332 - final long length = arrayData.length(); 23.333 - 23.334 - if (bulkable(sobj) && length + 1 <= JSType.MAX_UINT) { 23.335 - sobj.setArray(arrayData.ensure(length).set(ArrayIndex.getArrayIndex(length), arg, true)); 23.336 - return length + 1; 23.337 - } 23.338 - 23.339 - long len = JSType.toUint32(sobj.getLength()); 23.340 - sobj.set(len++, arg, true); 23.341 - sobj.set("length", len, true); 23.342 - return len; 23.343 - } catch (final ClassCastException | NullPointerException e) { 23.344 - throw typeError("not.an.object", ScriptRuntime.safeToString(self)); 23.345 - } 23.346 - } 23.347 -*/ 23.348 - /** 23.349 * ECMA 15.4.4.7 Array.prototype.push (args...) specialized for single object argument 23.350 * 23.351 * @param self self reference 23.352 @@ -925,7 +1024,7 @@ 23.353 final ArrayData arrayData = sobj.getArray(); 23.354 final long length = arrayData.length(); 23.355 if (bulkable(sobj) && length < JSType.MAX_UINT) { 23.356 - sobj.setArray(arrayData.push(true, arg)); //ensure(length).set(ArrayIndex.getArrayIndex(length), arg, true)); 23.357 + sobj.setArray(arrayData.push(true, arg)); 23.358 return length + 1; 23.359 } 23.360 23.361 @@ -1584,6 +1683,192 @@ 23.362 23.363 @Override 23.364 public String toString() { 23.365 - return "NativeArray@" + Debug.id(this) + '@' + getArray().getClass().getSimpleName(); 23.366 + return "NativeArray@" + Debug.id(this) + " [" + getArray().getClass().getSimpleName() + ']'; 23.367 + } 23.368 + 23.369 + @Override 23.370 + public SpecializedFunction.LinkLogic getLinkLogic(final Class<? extends LinkLogic> clazz) { 23.371 + if (clazz == PushLinkLogic.class) { 23.372 + return pushLinkLogic == null ? new PushLinkLogic(this) : pushLinkLogic; 23.373 + } else if (clazz == PopLinkLogic.class) { 23.374 + return popLinkLogic == null ? new PopLinkLogic(this) : pushLinkLogic; 23.375 + } 23.376 + return null; 23.377 + } 23.378 + 23.379 + @Override 23.380 + public boolean hasPerInstanceAssumptions() { 23.381 + return true; //length switchpoint 23.382 + } 23.383 + 23.384 + /** 23.385 + * This is an abstract super class that contains common functionality for all 23.386 + * specialized optimistic builtins in NativeArray. For example, it handles the 23.387 + * modification switchpoint which is touched when length is written. 23.388 + */ 23.389 + private static abstract class ArrayLinkLogic extends SpecializedFunction.LinkLogic { 23.390 + private final NativeArray array; 23.391 + 23.392 + protected ArrayLinkLogic(final NativeArray array) { 23.393 + this.array = array; 23.394 + } 23.395 + 23.396 + private SwitchPoint getSwitchPoint() { 23.397 + return array.lengthMadeNotWritableSwitchPoint; 23.398 + } 23.399 + 23.400 + private SwitchPoint newSwitchPoint() { 23.401 + assert array.lengthMadeNotWritableSwitchPoint == null; 23.402 + final SwitchPoint sp = new SwitchPoint(); 23.403 + array.lengthMadeNotWritableSwitchPoint = sp; 23.404 + return sp; 23.405 + } 23.406 + 23.407 + protected static ContinuousArrayData getContinuousArrayData(final Object self) { 23.408 + try { 23.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 23.410 + return (ContinuousArrayData)((NativeArray)self).getArray(); 23.411 + } catch (final Exception e) { 23.412 + return null; 23.413 + } 23.414 + } 23.415 + 23.416 + /** 23.417 + * Push and pop callsites can throw ClassCastException as a mechanism to have them 23.418 + * relinked - this enabled fast checks of the kind of ((IntArrayData)arrayData).push(x) 23.419 + * for an IntArrayData only push - if this fails, a CCE will be thrown and we will relink 23.420 + */ 23.421 + @Override 23.422 + public Class<? extends Throwable> getRelinkException() { 23.423 + return ClassCastException.class; 23.424 + } 23.425 + 23.426 + @Override 23.427 + public boolean hasModificationSwitchPoints() { 23.428 + return getSwitchPoint() != null; 23.429 + } 23.430 + 23.431 + @Override 23.432 + public boolean hasModificationSwitchPoint(final int index) { 23.433 + assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT; 23.434 + return hasModificationSwitchPoints(); 23.435 + } 23.436 + 23.437 + @Override 23.438 + public SwitchPoint getOrCreateModificationSwitchPoint(final int index) { 23.439 + assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT; 23.440 + SwitchPoint sp = getSwitchPoint(); 23.441 + if (sp == null) { 23.442 + sp = newSwitchPoint(); 23.443 + } 23.444 + return sp; 23.445 + } 23.446 + 23.447 + @Override 23.448 + public SwitchPoint[] getOrCreateModificationSwitchPoints() { 23.449 + return new SwitchPoint[] { getOrCreateModificationSwitchPoint(LENGTH_NOT_WRITABLE_SWITCHPOINT) }; 23.450 + } 23.451 + 23.452 + @Override 23.453 + public void invalidateModificationSwitchPoint(final int index) { 23.454 + assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT; 23.455 + invalidateModificationSwitchPoints(); 23.456 + } 23.457 + 23.458 + @Override 23.459 + public void invalidateModificationSwitchPoints() { 23.460 + final SwitchPoint sp = getSwitchPoint(); 23.461 + assert sp != null : "trying to invalidate non-existant modified SwitchPoint"; 23.462 + if (!sp.hasBeenInvalidated()) { 23.463 + SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 23.464 + } 23.465 + } 23.466 + 23.467 + @Override 23.468 + public boolean hasInvalidatedModificationSwitchPoint(final int index) { 23.469 + assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT; 23.470 + return hasInvalidatedModificationSwitchPoints(); 23.471 + } 23.472 + 23.473 + @Override 23.474 + public boolean hasInvalidatedModificationSwitchPoints() { 23.475 + final SwitchPoint sp = getSwitchPoint(); 23.476 + return sp != null && !sp.hasBeenInvalidated(); 23.477 + } 23.478 + } 23.479 + 23.480 + /** 23.481 + * This is linker logic for optimistic pushes 23.482 + */ 23.483 + private static final class PushLinkLogic extends ArrayLinkLogic { 23.484 + private PushLinkLogic(final NativeArray array) { 23.485 + super(array); 23.486 + } 23.487 + 23.488 + @Override 23.489 + public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { 23.490 + return getContinuousArrayData(self) != null; 23.491 + } 23.492 + } 23.493 + 23.494 + /** 23.495 + * This is linker logic for optimistic pops 23.496 + */ 23.497 + private static final class PopLinkLogic extends ArrayLinkLogic { 23.498 + private PopLinkLogic(final NativeArray array) { 23.499 + super(array); 23.500 + } 23.501 + 23.502 + /** 23.503 + * We need to check if we are dealing with a continuous non empty array data here, 23.504 + * as pop with a primitive return value returns undefined for arrays with length 0 23.505 + */ 23.506 + @Override 23.507 + public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { 23.508 + final ContinuousArrayData data = getContinuousNonEmptyArrayData(self); 23.509 + if (data != null) { 23.510 + final Class<?> elementType = data.getElementType(); 23.511 + final Class<?> returnType = desc.getMethodType().returnType(); 23.512 + final boolean typeFits = JSType.getAccessorTypeIndex(returnType) >= JSType.getAccessorTypeIndex(elementType); 23.513 + return typeFits; 23.514 + } 23.515 + return false; 23.516 + } 23.517 + 23.518 + private static ContinuousArrayData getContinuousNonEmptyArrayData(final Object self) { 23.519 + final ContinuousArrayData data = getContinuousArrayData(self); 23.520 + if (data != null) { 23.521 + return data.length() == 0 ? null : data; 23.522 + } 23.523 + return null; 23.524 + } 23.525 + } 23.526 + 23.527 + //runtime calls for push and pops. they could be used as guards, but they also perform the runtime logic, 23.528 + //so rather than synthesizing them into a guard method handle that would also perform the push on the 23.529 + //retrieved receiver, we use this as runtime logic 23.530 + 23.531 + //TODO - fold these into the Link logics, but I'll do that as a later step, as I want to do a checkin 23.532 + //where everything works first 23.533 + 23.534 + private static final <T> ContinuousArrayData getContinuousNonEmptyArrayDataCCE(final Object self, final Class<T> clazz) { 23.535 + try { 23.536 + @SuppressWarnings("unchecked") 23.537 + final ContinuousArrayData data = (ContinuousArrayData)(T)((NativeArray)self).getArray(); 23.538 + if (data.length() != 0L) { 23.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 23.540 + } 23.541 + } catch (final NullPointerException e) { 23.542 + //fallthru 23.543 + } 23.544 + throw new ClassCastException(); 23.545 + } 23.546 + 23.547 + private static final ContinuousArrayData getContinuousArrayDataCCE(final Object self, final Class<?> elementType) { 23.548 + try { 23.549 + return (ContinuousArrayData)((NativeArray)self).getArray(elementType); //ensure element type can fit "elementType" 23.550 + } catch (final NullPointerException e) { 23.551 + throw new ClassCastException(); 23.552 + } 23.553 } 23.554 }
24.1 --- a/src/jdk/nashorn/internal/objects/NativeDataView.java Wed Oct 01 12:22:12 2014 +0200 24.2 +++ b/src/jdk/nashorn/internal/objects/NativeDataView.java Thu Sep 25 15:53:47 2014 +0200 24.3 @@ -27,7 +27,6 @@ 24.4 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError; 24.5 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 24.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 24.7 - 24.8 import java.nio.ByteBuffer; 24.9 import java.nio.ByteOrder; 24.10 import jdk.nashorn.internal.objects.annotations.Attribute; 24.11 @@ -35,7 +34,6 @@ 24.12 import jdk.nashorn.internal.objects.annotations.Function; 24.13 import jdk.nashorn.internal.objects.annotations.Property; 24.14 import jdk.nashorn.internal.objects.annotations.ScriptClass; 24.15 -import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; 24.16 import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 24.17 import jdk.nashorn.internal.runtime.JSType; 24.18 import jdk.nashorn.internal.runtime.PropertyMap; 24.19 @@ -156,7 +154,7 @@ 24.20 * @param offset offset in bytes from the start of the ArrayBuffer 24.21 * @return newly constructed DataView object 24.22 */ 24.23 - @SpecializedConstructor 24.24 + @SpecializedFunction(isConstructor=true) 24.25 public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset) { 24.26 if (!(arrBuf instanceof NativeArrayBuffer)) { 24.27 throw typeError("not.an.arraybuffer.in.dataview"); 24.28 @@ -174,7 +172,7 @@ 24.29 * @param length is the number of bytes from the offset that this DataView will reference 24.30 * @return newly constructed DataView object 24.31 */ 24.32 - @SpecializedConstructor 24.33 + @SpecializedFunction(isConstructor=true) 24.34 public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset, final int length) { 24.35 if (!(arrBuf instanceof NativeArrayBuffer)) { 24.36 throw typeError("not.an.arraybuffer.in.dataview");
25.1 --- a/src/jdk/nashorn/internal/objects/NativeDate.java Wed Oct 01 12:22:12 2014 +0200 25.2 +++ b/src/jdk/nashorn/internal/objects/NativeDate.java Thu Sep 25 15:53:47 2014 +0200 25.3 @@ -30,7 +30,6 @@ 25.4 import static java.lang.Double.isNaN; 25.5 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError; 25.6 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 25.7 - 25.8 import java.util.Locale; 25.9 import java.util.TimeZone; 25.10 import java.util.concurrent.Callable; 25.11 @@ -38,7 +37,7 @@ 25.12 import jdk.nashorn.internal.objects.annotations.Constructor; 25.13 import jdk.nashorn.internal.objects.annotations.Function; 25.14 import jdk.nashorn.internal.objects.annotations.ScriptClass; 25.15 -import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; 25.16 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 25.17 import jdk.nashorn.internal.objects.annotations.Where; 25.18 import jdk.nashorn.internal.parser.DateParser; 25.19 import jdk.nashorn.internal.runtime.ConsString; 25.20 @@ -155,7 +154,7 @@ 25.21 * @param self self references 25.22 * @return Date representing now 25.23 */ 25.24 - @SpecializedConstructor 25.25 + @SpecializedFunction(isConstructor=true) 25.26 public static Object construct(final boolean isNew, final Object self) { 25.27 final NativeDate result = new NativeDate(); 25.28 return isNew ? result : toStringImpl(result, FORMAT_DATE_TIME);
26.1 --- a/src/jdk/nashorn/internal/objects/NativeDebug.java Wed Oct 01 12:22:12 2014 +0200 26.2 +++ b/src/jdk/nashorn/internal/objects/NativeDebug.java Thu Sep 25 15:53:47 2014 +0200 26.3 @@ -26,7 +26,6 @@ 26.4 package jdk.nashorn.internal.objects; 26.5 26.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 26.7 - 26.8 import java.io.PrintWriter; 26.9 import java.util.LinkedList; 26.10 import java.util.Objects; 26.11 @@ -262,8 +261,8 @@ 26.12 26.13 /** 26.14 * Set the event queue capacity 26.15 - * @param self 26.16 - * @param newCapacity 26.17 + * @param self an event queue 26.18 + * @param newCapacity new capacity 26.19 */ 26.20 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 26.21 public static void setEventQueueCapacity(final Object self, final Object newCapacity) {
27.1 --- a/src/jdk/nashorn/internal/objects/NativeFloat32Array.java Wed Oct 01 12:22:12 2014 +0200 27.2 +++ b/src/jdk/nashorn/internal/objects/NativeFloat32Array.java Thu Sep 25 15:53:47 2014 +0200 27.3 @@ -26,7 +26,6 @@ 27.4 package jdk.nashorn.internal.objects; 27.5 27.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 27.7 - 27.8 import java.lang.invoke.MethodHandle; 27.9 import java.lang.invoke.MethodHandles; 27.10 import java.nio.ByteBuffer; 27.11 @@ -85,6 +84,11 @@ 27.12 } 27.13 27.14 @Override 27.15 + public Class<?> getElementType() { 27.16 + return double.class; 27.17 + } 27.18 + 27.19 + @Override 27.20 protected MethodHandle getGetElem() { 27.21 return GET_ELEM; 27.22 }
28.1 --- a/src/jdk/nashorn/internal/objects/NativeFloat64Array.java Wed Oct 01 12:22:12 2014 +0200 28.2 +++ b/src/jdk/nashorn/internal/objects/NativeFloat64Array.java Thu Sep 25 15:53:47 2014 +0200 28.3 @@ -26,7 +26,6 @@ 28.4 package jdk.nashorn.internal.objects; 28.5 28.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 28.7 - 28.8 import java.lang.invoke.MethodHandle; 28.9 import java.lang.invoke.MethodHandles; 28.10 import java.nio.ByteBuffer; 28.11 @@ -94,6 +93,11 @@ 28.12 return SET_ELEM; 28.13 } 28.14 28.15 + @Override 28.16 + public Class<?> getElementType() { 28.17 + return double.class; 28.18 + } 28.19 + 28.20 private double getElem(final int index) { 28.21 try { 28.22 return nb.get(index);
29.1 --- a/src/jdk/nashorn/internal/objects/NativeInt16Array.java Wed Oct 01 12:22:12 2014 +0200 29.2 +++ b/src/jdk/nashorn/internal/objects/NativeInt16Array.java Thu Sep 25 15:53:47 2014 +0200 29.3 @@ -26,7 +26,6 @@ 29.4 package jdk.nashorn.internal.objects; 29.5 29.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 29.7 - 29.8 import java.lang.invoke.MethodHandle; 29.9 import java.lang.invoke.MethodHandles; 29.10 import java.nio.ByteBuffer; 29.11 @@ -95,6 +94,11 @@ 29.12 return SET_ELEM; 29.13 } 29.14 29.15 + @Override 29.16 + public Class<?> getElementType() { 29.17 + return int.class; 29.18 + } 29.19 + 29.20 private int getElem(final int index) { 29.21 try { 29.22 return nb.get(index);
30.1 --- a/src/jdk/nashorn/internal/objects/NativeInt32Array.java Wed Oct 01 12:22:12 2014 +0200 30.2 +++ b/src/jdk/nashorn/internal/objects/NativeInt32Array.java Thu Sep 25 15:53:47 2014 +0200 30.3 @@ -26,7 +26,6 @@ 30.4 package jdk.nashorn.internal.objects; 30.5 30.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 30.7 - 30.8 import java.lang.invoke.MethodHandle; 30.9 import java.lang.invoke.MethodHandles; 30.10 import java.nio.ByteBuffer; 30.11 @@ -113,6 +112,11 @@ 30.12 } 30.13 30.14 @Override 30.15 + public Class<?> getElementType() { 30.16 + return int.class; 30.17 + } 30.18 + 30.19 + @Override 30.20 public int getInt(final int index) { 30.21 return getElem(index); 30.22 }
31.1 --- a/src/jdk/nashorn/internal/objects/NativeInt8Array.java Wed Oct 01 12:22:12 2014 +0200 31.2 +++ b/src/jdk/nashorn/internal/objects/NativeInt8Array.java Thu Sep 25 15:53:47 2014 +0200 31.3 @@ -26,7 +26,6 @@ 31.4 package jdk.nashorn.internal.objects; 31.5 31.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 31.7 - 31.8 import java.lang.invoke.MethodHandle; 31.9 import java.lang.invoke.MethodHandles; 31.10 import java.nio.ByteBuffer; 31.11 @@ -93,6 +92,11 @@ 31.12 return SET_ELEM; 31.13 } 31.14 31.15 + @Override 31.16 + public Class<?> getElementType() { 31.17 + return int.class; 31.18 + } 31.19 + 31.20 private int getElem(final int index) { 31.21 try { 31.22 return nb.get(index);
32.1 --- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Wed Oct 01 12:22:12 2014 +0200 32.2 +++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Thu Sep 25 15:53:47 2014 +0200 32.3 @@ -48,7 +48,6 @@ 32.4 import jdk.nashorn.internal.runtime.ScriptFunction; 32.5 import jdk.nashorn.internal.runtime.ScriptObject; 32.6 import jdk.nashorn.internal.runtime.ScriptRuntime; 32.7 -import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; 32.8 import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator; 32.9 import jdk.nashorn.internal.scripts.JO; 32.10
33.1 --- a/src/jdk/nashorn/internal/objects/NativeRegExp.java Wed Oct 01 12:22:12 2014 +0200 33.2 +++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java Thu Sep 25 15:53:47 2014 +0200 33.3 @@ -33,13 +33,14 @@ 33.4 import java.util.Arrays; 33.5 import java.util.List; 33.6 import java.util.concurrent.Callable; 33.7 + 33.8 import jdk.nashorn.internal.objects.annotations.Attribute; 33.9 import jdk.nashorn.internal.objects.annotations.Constructor; 33.10 import jdk.nashorn.internal.objects.annotations.Function; 33.11 import jdk.nashorn.internal.objects.annotations.Getter; 33.12 import jdk.nashorn.internal.objects.annotations.Property; 33.13 import jdk.nashorn.internal.objects.annotations.ScriptClass; 33.14 -import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; 33.15 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 33.16 import jdk.nashorn.internal.objects.annotations.Where; 33.17 import jdk.nashorn.internal.runtime.BitVector; 33.18 import jdk.nashorn.internal.runtime.JSType; 33.19 @@ -143,7 +144,7 @@ 33.20 * @param self self reference 33.21 * @return new NativeRegExp 33.22 */ 33.23 - @SpecializedConstructor 33.24 + @SpecializedFunction(isConstructor=true) 33.25 public static NativeRegExp constructor(final boolean isNew, final Object self) { 33.26 return new NativeRegExp("", ""); 33.27 } 33.28 @@ -158,7 +159,7 @@ 33.29 * @param pattern pattern 33.30 * @return new NativeRegExp 33.31 */ 33.32 - @SpecializedConstructor 33.33 + @SpecializedFunction(isConstructor=true) 33.34 public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern) { 33.35 return newRegExp(pattern, UNDEFINED); 33.36 } 33.37 @@ -174,7 +175,7 @@ 33.38 * @param flags flags 33.39 * @return new NativeRegExp 33.40 */ 33.41 - @SpecializedConstructor 33.42 + @SpecializedFunction(isConstructor=true) 33.43 public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern, final Object flags) { 33.44 return newRegExp(pattern, flags); 33.45 }
34.1 --- a/src/jdk/nashorn/internal/objects/NativeString.java Wed Oct 01 12:22:12 2014 +0200 34.2 +++ b/src/jdk/nashorn/internal/objects/NativeString.java Thu Sep 25 15:53:47 2014 +0200 34.3 @@ -29,7 +29,6 @@ 34.4 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 34.5 import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt; 34.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 34.7 - 34.8 import java.lang.invoke.MethodHandle; 34.9 import java.lang.invoke.MethodHandles; 34.10 import java.lang.invoke.MethodType; 34.11 @@ -49,11 +48,12 @@ 34.12 import jdk.nashorn.internal.objects.annotations.Function; 34.13 import jdk.nashorn.internal.objects.annotations.Getter; 34.14 import jdk.nashorn.internal.objects.annotations.ScriptClass; 34.15 -import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; 34.16 import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 34.17 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 34.18 import jdk.nashorn.internal.objects.annotations.Where; 34.19 import jdk.nashorn.internal.runtime.ConsString; 34.20 import jdk.nashorn.internal.runtime.JSType; 34.21 +import jdk.nashorn.internal.runtime.OptimisticBuiltins; 34.22 import jdk.nashorn.internal.runtime.PropertyMap; 34.23 import jdk.nashorn.internal.runtime.ScriptFunction; 34.24 import jdk.nashorn.internal.runtime.ScriptObject; 34.25 @@ -67,7 +67,7 @@ 34.26 * ECMA 15.5 String Objects. 34.27 */ 34.28 @ScriptClass("String") 34.29 -public final class NativeString extends ScriptObject { 34.30 +public final class NativeString extends ScriptObject implements OptimisticBuiltins { 34.31 34.32 private final CharSequence value; 34.33 34.34 @@ -568,6 +568,14 @@ 34.35 return pos < 0 || pos >= str.length() ? "" : String.valueOf(str.charAt(pos)); 34.36 } 34.37 34.38 + private static int getValidChar(final Object self, final int pos) { 34.39 + try { 34.40 + return ((CharSequence)self).charAt(pos); 34.41 + } catch (final IndexOutOfBoundsException e) { 34.42 + throw new ClassCastException(); 34.43 + } 34.44 + } 34.45 + 34.46 /** 34.47 * ECMA 15.5.4.5 String.prototype.charCodeAt (pos) 34.48 * @param self self reference 34.49 @@ -576,7 +584,9 @@ 34.50 */ 34.51 @Function(attributes = Attribute.NOT_ENUMERABLE) 34.52 public static double charCodeAt(final Object self, final Object pos) { 34.53 - return charCodeAtImpl(checkObjectToString(self), JSType.toInteger(pos)); 34.54 + final String str = checkObjectToString(self); 34.55 + final int idx = JSType.toInteger(pos); 34.56 + return idx < 0 || idx >= str.length() ? Double.NaN : str.charAt(idx); 34.57 } 34.58 34.59 /** 34.60 @@ -585,9 +595,20 @@ 34.61 * @param pos position in string 34.62 * @return number representing charcode at position 34.63 */ 34.64 - @SpecializedFunction 34.65 - public static double charCodeAt(final Object self, final double pos) { 34.66 - return charCodeAt(self, (int) pos); 34.67 + @SpecializedFunction(linkLogic=CharCodeAtLinkLogic.class) 34.68 + public static int charCodeAt(final Object self, final double pos) { 34.69 + return charCodeAt(self, (int)pos); //toInt pos is ok 34.70 + } 34.71 + 34.72 + /** 34.73 + * ECMA 15.5.4.5 String.prototype.charCodeAt (pos) - specialized version for long position 34.74 + * @param self self reference 34.75 + * @param pos position in string 34.76 + * @return number representing charcode at position 34.77 + */ 34.78 + @SpecializedFunction(linkLogic=CharCodeAtLinkLogic.class) 34.79 + public static int charCodeAt(final Object self, final long pos) { 34.80 + return charCodeAt(self, (int)pos); 34.81 } 34.82 34.83 /** 34.84 @@ -596,13 +617,10 @@ 34.85 * @param pos position in string 34.86 * @return number representing charcode at position 34.87 */ 34.88 - @SpecializedFunction 34.89 - public static double charCodeAt(final Object self, final int pos) { 34.90 - return charCodeAtImpl(checkObjectToString(self), pos); 34.91 - } 34.92 34.93 - private static double charCodeAtImpl(final String str, final int pos) { 34.94 - return pos < 0 || pos >= str.length() ? Double.NaN : str.charAt(pos); 34.95 + @SpecializedFunction(linkLogic=CharCodeAtLinkLogic.class) 34.96 + public static int charCodeAt(final Object self, final int pos) { 34.97 + return getValidChar(self, pos); 34.98 } 34.99 34.100 /** 34.101 @@ -1097,7 +1115,6 @@ 34.102 */ 34.103 @Function(attributes = Attribute.NOT_ENUMERABLE) 34.104 public static String trim(final Object self) { 34.105 - 34.106 final String str = checkObjectToString(self); 34.107 int start = 0; 34.108 int end = str.length() - 1; 34.109 @@ -1181,7 +1198,7 @@ 34.110 * 34.111 * @return new NativeString ("") 34.112 */ 34.113 - @SpecializedConstructor 34.114 + @SpecializedFunction(isConstructor=true) 34.115 public static Object constructor(final boolean newObj, final Object self) { 34.116 return newObj ? newObj("") : ""; 34.117 } 34.118 @@ -1197,7 +1214,7 @@ 34.119 * 34.120 * @return new NativeString (arg) 34.121 */ 34.122 - @SpecializedConstructor 34.123 + @SpecializedFunction(isConstructor=true) 34.124 public static Object constructor(final boolean newObj, final Object self, final Object arg) { 34.125 final CharSequence str = JSType.toCharSequence(arg); 34.126 return newObj ? newObj(str) : str.toString(); 34.127 @@ -1214,8 +1231,42 @@ 34.128 * 34.129 * @return new NativeString containing the string representation of the arg 34.130 */ 34.131 - @SpecializedConstructor 34.132 + @SpecializedFunction(isConstructor=true) 34.133 public static Object constructor(final boolean newObj, final Object self, final int arg) { 34.134 + final String str = Integer.toString(arg); 34.135 + return newObj ? newObj(str) : str; 34.136 + } 34.137 + 34.138 + /** 34.139 + * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code int} arg 34.140 + * 34.141 + * Constructor 34.142 + * 34.143 + * @param newObj is this constructor invoked with the new operator 34.144 + * @param self self reference 34.145 + * @param arg the arg 34.146 + * 34.147 + * @return new NativeString containing the string representation of the arg 34.148 + */ 34.149 + @SpecializedFunction(isConstructor=true) 34.150 + public static Object constructor(final boolean newObj, final Object self, final long arg) { 34.151 + final String str = Long.toString(arg); 34.152 + return newObj ? newObj(str) : str; 34.153 + } 34.154 + 34.155 + /** 34.156 + * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code int} arg 34.157 + * 34.158 + * Constructor 34.159 + * 34.160 + * @param newObj is this constructor invoked with the new operator 34.161 + * @param self self reference 34.162 + * @param arg the arg 34.163 + * 34.164 + * @return new NativeString containing the string representation of the arg 34.165 + */ 34.166 + @SpecializedFunction(isConstructor=true) 34.167 + public static Object constructor(final boolean newObj, final Object self, final double arg) { 34.168 final String str = JSType.toString(arg); 34.169 return newObj ? newObj(str) : str; 34.170 } 34.171 @@ -1231,9 +1282,9 @@ 34.172 * 34.173 * @return new NativeString containing the string representation of the arg 34.174 */ 34.175 - @SpecializedConstructor 34.176 + @SpecializedFunction(isConstructor=true) 34.177 public static Object constructor(final boolean newObj, final Object self, final boolean arg) { 34.178 - final String str = JSType.toString(arg); 34.179 + final String str = Boolean.toString(arg); 34.180 return newObj ? newObj(str) : str; 34.181 } 34.182 34.183 @@ -1281,7 +1332,7 @@ 34.184 } else if (self != null && self == Global.instance().getStringPrototype()) { 34.185 return ""; 34.186 } else { 34.187 - throw typeError( "not.a.string", ScriptRuntime.safeToString(self)); 34.188 + throw typeError("not.a.string", ScriptRuntime.safeToString(self)); 34.189 } 34.190 } 34.191 34.192 @@ -1310,4 +1361,50 @@ 34.193 return MH.findStatic(MethodHandles.lookup(), NativeString.class, name, type); 34.194 } 34.195 34.196 + @Override 34.197 + public LinkLogic getLinkLogic(final Class<? extends LinkLogic> clazz) { 34.198 + if (clazz == CharCodeAtLinkLogic.class) { 34.199 + return CharCodeAtLinkLogic.INSTANCE; 34.200 + } 34.201 + return null; 34.202 + } 34.203 + 34.204 + @Override 34.205 + public boolean hasPerInstanceAssumptions() { 34.206 + return false; 34.207 + } 34.208 + 34.209 + /** 34.210 + * This is linker logic charCodeAt - when we specialize further methods in NativeString 34.211 + * It may be expanded. It's link check makes sure that we are dealing with a char 34.212 + * sequence and that we are in range 34.213 + */ 34.214 + private static final class CharCodeAtLinkLogic extends SpecializedFunction.LinkLogic { 34.215 + 34.216 + private static final CharCodeAtLinkLogic INSTANCE = new CharCodeAtLinkLogic(); 34.217 + 34.218 + @Override 34.219 + public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { 34.220 + try { 34.221 + //check that it's a char sequence or throw cce 34.222 + final CharSequence cs = (CharSequence)self; 34.223 + //check that the index, representable as an int, is inside the array 34.224 + final int intIndex = JSType.toInteger(request.getArguments()[1]); 34.225 + return intIndex >= 0 && intIndex < cs.length(); //can link 34.226 + } catch (final ClassCastException | IndexOutOfBoundsException e) { 34.227 + //fallthru 34.228 + } 34.229 + return false; 34.230 + } 34.231 + 34.232 + /** 34.233 + * charCodeAt callsites can throw ClassCastException as a mechanism to have them 34.234 + * relinked - this enabled fast checks of the kind of ((IntArrayData)arrayData).push(x) 34.235 + * for an IntArrayData only push - if this fails, a CCE will be thrown and we will relink 34.236 + */ 34.237 + @Override 34.238 + public Class<? extends Throwable> getRelinkException() { 34.239 + return ClassCastException.class; 34.240 + } 34.241 + } 34.242 }
35.1 --- a/src/jdk/nashorn/internal/objects/NativeUint16Array.java Wed Oct 01 12:22:12 2014 +0200 35.2 +++ b/src/jdk/nashorn/internal/objects/NativeUint16Array.java Thu Sep 25 15:53:47 2014 +0200 35.3 @@ -26,7 +26,6 @@ 35.4 package jdk.nashorn.internal.objects; 35.5 35.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 35.7 - 35.8 import java.lang.invoke.MethodHandle; 35.9 import java.lang.invoke.MethodHandles; 35.10 import java.nio.ByteBuffer; 35.11 @@ -119,6 +118,11 @@ 35.12 } 35.13 35.14 @Override 35.15 + public Class<?> getElementType() { 35.16 + return int.class; 35.17 + } 35.18 + 35.19 + @Override 35.20 public int getInt(final int index) { 35.21 return getElem(index); 35.22 }
36.1 --- a/src/jdk/nashorn/internal/objects/NativeUint32Array.java Wed Oct 01 12:22:12 2014 +0200 36.2 +++ b/src/jdk/nashorn/internal/objects/NativeUint32Array.java Thu Sep 25 15:53:47 2014 +0200 36.3 @@ -26,7 +26,6 @@ 36.4 package jdk.nashorn.internal.objects; 36.5 36.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 36.7 - 36.8 import java.lang.invoke.MethodHandle; 36.9 import java.lang.invoke.MethodHandles; 36.10 import java.nio.ByteBuffer; 36.11 @@ -128,6 +127,11 @@ 36.12 } 36.13 36.14 @Override 36.15 + public Class<?> getElementType() { 36.16 + return int.class; 36.17 + } 36.18 + 36.19 + @Override 36.20 public int getInt(final int index) { 36.21 return (int)getLong(index); 36.22 }
37.1 --- a/src/jdk/nashorn/internal/objects/NativeUint8Array.java Wed Oct 01 12:22:12 2014 +0200 37.2 +++ b/src/jdk/nashorn/internal/objects/NativeUint8Array.java Thu Sep 25 15:53:47 2014 +0200 37.3 @@ -26,7 +26,6 @@ 37.4 package jdk.nashorn.internal.objects; 37.5 37.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 37.7 - 37.8 import java.lang.invoke.MethodHandle; 37.9 import java.lang.invoke.MethodHandles; 37.10 import java.nio.ByteBuffer; 37.11 @@ -119,6 +118,11 @@ 37.12 } 37.13 37.14 @Override 37.15 + public Class<?> getElementType() { 37.16 + return int.class; 37.17 + } 37.18 + 37.19 + @Override 37.20 public int getInt(final int index) { 37.21 return getElem(index); 37.22 }
38.1 --- a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Wed Oct 01 12:22:12 2014 +0200 38.2 +++ b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Thu Sep 25 15:53:47 2014 +0200 38.3 @@ -28,7 +28,6 @@ 38.4 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 38.5 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; 38.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 38.7 - 38.8 import java.lang.invoke.MethodHandle; 38.9 import java.lang.invoke.MethodHandles; 38.10 import java.nio.ByteBuffer; 38.11 @@ -98,6 +97,11 @@ 38.12 return SET_ELEM; 38.13 } 38.14 38.15 + @Override 38.16 + public Class<?> getElementType() { 38.17 + return int.class; 38.18 + } 38.19 + 38.20 private int getElem(final int index) { 38.21 try { 38.22 return nb.get(index) & 0xff;
39.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Wed Oct 01 12:22:12 2014 +0200 39.2 +++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Thu Sep 25 15:53:47 2014 +0200 39.3 @@ -30,6 +30,7 @@ 39.4 39.5 import java.lang.invoke.MethodHandle; 39.6 import java.util.ArrayList; 39.7 + 39.8 import jdk.nashorn.internal.runtime.AccessorProperty; 39.9 import jdk.nashorn.internal.runtime.GlobalFunctions; 39.10 import jdk.nashorn.internal.runtime.Property; 39.11 @@ -38,6 +39,7 @@ 39.12 import jdk.nashorn.internal.runtime.ScriptFunction; 39.13 import jdk.nashorn.internal.runtime.ScriptFunctionData; 39.14 import jdk.nashorn.internal.runtime.ScriptObject; 39.15 +import jdk.nashorn.internal.runtime.Specialization; 39.16 39.17 /** 39.18 * Concrete implementation of ScriptFunction. This sets correct map for the 39.19 @@ -58,7 +60,7 @@ 39.20 // Marker object for lazily initialized prototype object 39.21 private static final Object LAZY_PROTOTYPE = new Object(); 39.22 39.23 - private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs, final Global global) { 39.24 + private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs, final Global global) { 39.25 super(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); 39.26 init(global); 39.27 } 39.28 @@ -71,11 +73,11 @@ 39.29 * @param invokeHandle handle for invocation 39.30 * @param specs specialized versions of this method, if available, null otherwise 39.31 */ 39.32 - ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs) { 39.33 + ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs) { 39.34 this(name, invokeHandle, specs, Global.instance()); 39.35 } 39.36 39.37 - private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs, final Global global) { 39.38 + private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs, final Global global) { 39.39 super(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); 39.40 init(global); 39.41 } 39.42 @@ -89,11 +91,11 @@ 39.43 * @param map initial property map 39.44 * @param specs specialized versions of this method, if available, null otherwise 39.45 */ 39.46 - ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs) { 39.47 + ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs) { 39.48 this(name, invokeHandle, map, specs, Global.instance()); 39.49 } 39.50 39.51 - private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags, final Global global) { 39.52 + private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags, final Global global) { 39.53 super(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags); 39.54 init(global); 39.55 } 39.56 @@ -107,7 +109,7 @@ 39.57 * @param specs specialized versions of this method, if available, null otherwise 39.58 * @param flags {@link ScriptFunctionData} flags 39.59 */ 39.60 - ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags) { 39.61 + ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags) { 39.62 this(name, methodHandle, scope, specs, flags, Global.instance()); 39.63 } 39.64 39.65 @@ -184,7 +186,7 @@ 39.66 return new AnonymousFunction(); 39.67 } 39.68 39.69 - private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs, final int flags) { 39.70 + private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs, final int flags) { 39.71 final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, flags); 39.72 func.setPrototype(UNDEFINED); 39.73 // Non-constructor built-in functions do not have "prototype" property 39.74 @@ -201,7 +203,7 @@ 39.75 * @param specs specialized versions of function if available, null otherwise 39.76 * @return new ScriptFunction 39.77 */ 39.78 - static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) { 39.79 + static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs) { 39.80 return makeFunction(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN); 39.81 } 39.82
40.1 --- a/src/jdk/nashorn/internal/objects/annotations/SpecializedConstructor.java Wed Oct 01 12:22:12 2014 +0200 40.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 40.3 @@ -1,47 +0,0 @@ 40.4 -/* 40.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 40.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 40.7 - * 40.8 - * This code is free software; you can redistribute it and/or modify it 40.9 - * under the terms of the GNU General Public License version 2 only, as 40.10 - * published by the Free Software Foundation. Oracle designates this 40.11 - * particular file as subject to the "Classpath" exception as provided 40.12 - * by Oracle in the LICENSE file that accompanied this code. 40.13 - * 40.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 40.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 40.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 40.17 - * version 2 for more details (a copy is included in the LICENSE file that 40.18 - * accompanied this code). 40.19 - * 40.20 - * You should have received a copy of the GNU General Public License version 40.21 - * 2 along with this work; if not, write to the Free Software Foundation, 40.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 40.23 - * 40.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 40.25 - * or visit www.oracle.com if you need additional information or have any 40.26 - * questions. 40.27 - */ 40.28 - 40.29 -package jdk.nashorn.internal.objects.annotations; 40.30 - 40.31 -import java.lang.annotation.ElementType; 40.32 -import java.lang.annotation.Retention; 40.33 -import java.lang.annotation.RetentionPolicy; 40.34 -import java.lang.annotation.Target; 40.35 - 40.36 -/** 40.37 - * The SpecializedConstructor annotation is used to flag more type specific constructors than the standard one in 40.38 - * Native objects. For example {@link jdk.nashorn.internal.objects.NativeArray#construct} takes an arbitrary number of 40.39 - * Object elements as an array. Call this constructor, including the varargs collector that allocates the array 40.40 - * upon each invocation, is much more expensive than calling a specialized constructor that takes one arguments 40.41 - * of, e.g. int type from the call site, such as 40.42 - * {@link jdk.nashorn.internal.objects.NativeArray#construct(boolean, Object, int)}. 40.43 - * {@link jdk.nashorn.internal.runtime.ScriptFunction} will try to look up the most specific function when 40.44 - * linking the callsite. 40.45 - */ 40.46 -@Retention(RetentionPolicy.RUNTIME) 40.47 -@Target(ElementType.METHOD) 40.48 -public @interface SpecializedConstructor { 40.49 - //empty 40.50 -}
41.1 --- a/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Wed Oct 01 12:22:12 2014 +0200 41.2 +++ b/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Thu Sep 25 15:53:47 2014 +0200 41.3 @@ -1,5 +1,5 @@ 41.4 /* 41.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 41.6 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 41.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 41.8 * 41.9 * This code is free software; you can redistribute it and/or modify it 41.10 @@ -29,18 +29,315 @@ 41.11 import java.lang.annotation.Retention; 41.12 import java.lang.annotation.RetentionPolicy; 41.13 import java.lang.annotation.Target; 41.14 +import java.lang.invoke.MethodHandle; 41.15 +import java.lang.invoke.SwitchPoint; 41.16 +import jdk.internal.dynalink.CallSiteDescriptor; 41.17 +import jdk.internal.dynalink.linker.LinkRequest; 41.18 +import jdk.nashorn.internal.runtime.ScriptFunction; 41.19 41.20 /** 41.21 - * The SpecializedFunction annotation is used to flag more type specific functions than the standard one in 41.22 - * Native objects. For example {@link jdk.nashorn.internal.objects.NativeMath#max} takes an arbitrary number of 41.23 - * Object elements as an array. Call this function, including the varargs collector that allocates the array 41.24 - * upon each invocation, is much more expensive than calling a specialized function that takes two arguments 41.25 - * of, e.g. int type from the call site, such as {@link jdk.nashorn.internal.objects.NativeMath#max(Object, int, int)}. 41.26 - * {@link jdk.nashorn.internal.runtime.ScriptFunction} will try to look up the most specific function when 41.27 - * linking the callsite. 41.28 + * The SpecializedFunction annotation is used to flag more type specific 41.29 + * functions than the standard one in the native objects 41.30 */ 41.31 @Retention(RetentionPolicy.RUNTIME) 41.32 @Target(ElementType.METHOD) 41.33 public @interface SpecializedFunction { 41.34 - //empty 41.35 + 41.36 + /** 41.37 + * Functionality for testing if we are allowed to link a specialized 41.38 + * function the first time we encounter it. Then the guard will handle the 41.39 + * rest of the invocations 41.40 + * 41.41 + * This is the same for all callsites in Nashorn, the first time callsite is 41.42 + * linked, we have to manually check that the linkage is OK. Even if we add 41.43 + * a guard and it fails upon the first try, this is not good enough. 41.44 + * (Symmetrical to how it works everywhere else in the Nashorn runtime). 41.45 + * 41.46 + * Here we abstract out a few of the most common link guard checks. 41.47 + */ 41.48 + public static abstract class LinkLogic { 41.49 + /** 41.50 + * Empty link logic instance - this is the default 41.51 + * "no special linking or runtime guard behavior" 41.52 + */ 41.53 + public static final LinkLogic EMPTY_INSTANCE = new Empty(); 41.54 + 41.55 + private static final SwitchPoint[] INVALIDATED_SWITCHPOINTS = new SwitchPoint[0]; 41.56 + 41.57 + private SwitchPoint[] modificationSwitchPoints; //cache 41.58 + 41.59 + /** Empty link logic class - allow all linking, no guards */ 41.60 + private static final class Empty extends LinkLogic { 41.61 + @Override 41.62 + public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { 41.63 + return true; 41.64 + } 41.65 + 41.66 + @Override 41.67 + public boolean isEmpty() { 41.68 + return true; 41.69 + } 41.70 + } 41.71 + 41.72 + /** 41.73 + * Get the class representing the empty link logic 41.74 + * @return class representing empty link logic 41.75 + */ 41.76 + public static Class<? extends LinkLogic> getEmptyLinkLogicClass() { 41.77 + return Empty.class; 41.78 + } 41.79 + 41.80 + /** 41.81 + * Should this callsite relink when an exception is thrown 41.82 + * 41.83 + * @return the relink exception, or null if none 41.84 + */ 41.85 + public Class<? extends Throwable> getRelinkException() { 41.86 + return null; 41.87 + } 41.88 + 41.89 + /** 41.90 + * Is this link logic class empty - i.e. no special linking logic 41.91 + * supplied 41.92 + * 41.93 + * @param clazz class to check 41.94 + * 41.95 + * @return true if this link logic is empty 41.96 + */ 41.97 + public static boolean isEmpty(final Class<? extends LinkLogic> clazz) { 41.98 + return clazz == Empty.class; 41.99 + } 41.100 + 41.101 + /** 41.102 + * Is this link logic instance empty - i.e. no special linking logic 41.103 + * supplied 41.104 + * 41.105 + * @return true if this link logic instance is empty 41.106 + */ 41.107 + public boolean isEmpty() { 41.108 + return false; 41.109 + } 41.110 + 41.111 + /** 41.112 + * Given a callsite, can we link this method based on the receiver and 41.113 + * parameters? 41.114 + * 41.115 + * @param self receiver 41.116 + * @param desc callsite descriptor 41.117 + * @param request link request 41.118 + * 41.119 + * @return true if we can link this callsite at this time 41.120 + */ 41.121 + public abstract boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request); 41.122 + 41.123 + /** 41.124 + * Given a callsite, do we require an extra guard for specialization to 41.125 + * go through? 41.126 + * 41.127 + * @param self receiver 41.128 + * 41.129 + * @return true if a guard is to be woven into the callsite 41.130 + */ 41.131 + public boolean needsGuard(final Object self) { 41.132 + return true; 41.133 + } 41.134 + 41.135 + /** 41.136 + * Given a callsite, and optional arguments, do we need an extra guard 41.137 + * for specialization to go through - this guard can be a function of 41.138 + * the arguments too 41.139 + * 41.140 + * @param self receiver 41.141 + * @param args arguments 41.142 + * 41.143 + * @return true if a guard is to be woven into the callsite 41.144 + */ 41.145 + public boolean needsGuard(final Object self, final Object... args) { 41.146 + return true; 41.147 + } 41.148 + 41.149 + /** 41.150 + * Given a callsite, and optional arguments, return any extra guard we 41.151 + * might need for specialization as a method handle. 41.152 + * 41.153 + * @return methodhandle for guard, or null if no guard is needed 41.154 + */ 41.155 + public MethodHandle getGuard() { 41.156 + return null; 41.157 + } 41.158 + 41.159 + /** 41.160 + * Return the modification SwitchPoint of a particular index from this OptimisticBuiltins 41.161 + * If none exists, one is created and that one is return. 41.162 + * 41.163 + * The implementor must map indexes to specific SwitchPoints for specific events and keep 41.164 + * track of what they mean, for example NativeArray.LENGTH_NOT_WRITABLE_SWITCHPOINT 41.165 + * might be a useful index mapping 41.166 + * 41.167 + * @param index index for SwitchPoint to get or create 41.168 + * @return modification SwitchPoint of particular index for the receiver 41.169 + */ 41.170 + public SwitchPoint getOrCreateModificationSwitchPoint(final int index) { 41.171 + return null; 41.172 + } 41.173 + 41.174 + /** 41.175 + * Return the modification SwitchPoint from this OptimisticBuiltins. If none 41.176 + * exists, one is created and that one is return. 41.177 + * 41.178 + * @return modification SwitchPoint for the receiver 41.179 + */ 41.180 + public SwitchPoint[] getOrCreateModificationSwitchPoints() { 41.181 + return null; 41.182 + } 41.183 + 41.184 + /** 41.185 + * Hook to invalidate a modification SwitchPoint by index. 41.186 + * 41.187 + * @param index index for SwitchPoint to invalidate 41.188 + */ 41.189 + public void invalidateModificationSwitchPoint(final int index) { 41.190 + //empty 41.191 + } 41.192 + 41.193 + /** 41.194 + * Hook to invalidate all modification SwitchPoints for a receiver 41.195 + */ 41.196 + public void invalidateModificationSwitchPoints() { 41.197 + //empty 41.198 + } 41.199 + 41.200 + /** 41.201 + * Check whether the receiver has an invalidated modification SwitchPoint. 41.202 + * 41.203 + * @param index index for the modification SwitchPoint 41.204 + * @return true if the particular SwitchPoint at the index is invalidated 41.205 + */ 41.206 + public boolean hasInvalidatedModificationSwitchPoint(final int index) { 41.207 + return false; 41.208 + } 41.209 + 41.210 + /** 41.211 + * Check whether at least one of the modification SwitchPoints has been 41.212 + * invalidated 41.213 + * @return true if one of the SwitchPoints has been invalidated 41.214 + */ 41.215 + public boolean hasInvalidatedModificationSwitchPoints() { 41.216 + return false; 41.217 + } 41.218 + 41.219 + /** 41.220 + * Check whether this OptimisticBuiltins has a SwitchPoints of particular 41.221 + * index. 41.222 + * 41.223 + * As creation overhead for a SwitchPoint is non-zero, we have to create them lazily instead of, 41.224 + * e.g. in the constructor of every subclass. 41.225 + * 41.226 + * @param index index for the modification SwitchPoint 41.227 + * @return true if a modification SwitchPoint exists, no matter if it has been invalidated or not 41.228 + */ 41.229 + public boolean hasModificationSwitchPoint(final int index) { 41.230 + return false; 41.231 + } 41.232 + 41.233 + /** 41.234 + * Check whether this OptimisticBuiltins has SwitchPoints. 41.235 + * 41.236 + * As creation overhead for a SwitchPoint is non-zero, we have to create them lazily instead of, 41.237 + * e.g. in the constructor of every subclass. 41.238 + * 41.239 + * @return true if a modification SwitchPoint exists, no matter if it has been invalidated or not 41.240 + */ 41.241 + public boolean hasModificationSwitchPoints() { 41.242 + return false; 41.243 + } 41.244 + 41.245 + /** 41.246 + * Check, given a link request and a receiver, if this specialization 41.247 + * fits This is used by the linker in {@link ScriptFunction} to figure 41.248 + * out if an optimistic builtin can be linked when first discovered 41.249 + * 41.250 + * @param self receiver 41.251 + * @param desc callsite descriptor 41.252 + * @param request link request 41.253 + 41.254 + * @return true if we can link, false otherwise - that means we have to 41.255 + * pick a non specialized target 41.256 + */ 41.257 + public boolean checkLinkable(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { 41.258 + // no matter what the modification switchpoints are, if any of them are invalidated, 41.259 + // we can't link. Side effect is that if it's the first time we see this callsite, 41.260 + // we have to create the SwitchPoint(s) so future modification switchpoint invalidations 41.261 + // relink it 41.262 + final SwitchPoint[] sps = getOrCreateModificationSwitchPoints(self); 41.263 + if (sps == INVALIDATED_SWITCHPOINTS) { 41.264 + // nope, can't do the fast link as this assumption 41.265 + // has been invalidated already, e.g. length of an 41.266 + // array set to not writable 41.267 + return false; 41.268 + } 41.269 + modificationSwitchPoints = sps; //cache 41.270 + 41.271 + // check the link guard, if it says we can link, go ahead 41.272 + return canLink(self, desc, request); 41.273 + } 41.274 + 41.275 + private SwitchPoint[] getOrCreateModificationSwitchPoints(final Object self) { 41.276 + final SwitchPoint[] sps = getOrCreateModificationSwitchPoints(); //ask for all my switchpoints 41.277 + if (sps != null) { //switchpoint exists, but some may be invalidated 41.278 + for (final SwitchPoint sp : sps) { 41.279 + if (sp.hasBeenInvalidated()) { 41.280 + return INVALIDATED_SWITCHPOINTS; 41.281 + } 41.282 + } 41.283 + } 41.284 + return sps; 41.285 + } 41.286 + 41.287 + /** 41.288 + * Get the cached modification switchpoints. Only possible to do after a link 41.289 + * check call has been performed, one that has answered "true", or you will get the 41.290 + * wrong information. 41.291 + * 41.292 + * Should be used only from {@link ScriptFunction#findCallMethod} 41.293 + * 41.294 + * @return cached modification switchpoints for this callsite, null if none 41.295 + */ 41.296 + public SwitchPoint[] getModificationSwitchPoints() { 41.297 + return modificationSwitchPoints == null ? null : modificationSwitchPoints.clone(); 41.298 + } 41.299 + } 41.300 + 41.301 + /** 41.302 + * name override for return value polymorphism, for example we can't have 41.303 + * pop(V)I and pop(V)D in the same Java class, so they need to be named, 41.304 + * e.g. popInt(V)I and popDouble(V)D for disambiguation, however, their 41.305 + * names still need to resolve to "pop" to JavaScript so we can still 41.306 + * specialize on return values and so that the linker can find them 41.307 + * 41.308 + * @return name, "" means no override, use the Java function name, e.g. 41.309 + * "push" 41.310 + */ 41.311 + String name() default ""; 41.312 + 41.313 + /** 41.314 + * Return the guard for this specialized function. The default is no guard. 41.315 + * 41.316 + * @return guard 41.317 + */ 41.318 + Class<?> linkLogic() default LinkLogic.Empty.class; 41.319 + 41.320 + /** 41.321 + * Is this a specialized constructor? 41.322 + */ 41.323 + boolean isConstructor() default false; 41.324 + 41.325 + /** 41.326 + * Can this function throw UnwarrantedOptimismExceptions? This works just 41.327 + * like the normal functions, but we need the function to be 41.328 + * immutable/non-state modifying, as we can't generate continuations for 41.329 + * native code. Luckily a lot of the methods we want to specialize have this 41.330 + * property 41.331 + */ 41.332 + boolean isOptimistic() default false; 41.333 }
42.1 --- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java Wed Oct 01 12:22:12 2014 +0200 42.2 +++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java Thu Sep 25 15:53:47 2014 +0200 42.3 @@ -36,7 +36,6 @@ 42.4 import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex; 42.5 import static jdk.nashorn.internal.runtime.JSType.getNumberOfAccessorTypes; 42.6 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 42.7 - 42.8 import java.io.IOException; 42.9 import java.io.ObjectInputStream; 42.10 import java.lang.invoke.MethodHandle; 42.11 @@ -57,9 +56,7 @@ 42.12 private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); 42.13 42.14 private static final MethodHandle REPLACE_MAP = findOwnMH_S("replaceMap", Object.class, Object.class, PropertyMap.class); 42.15 - private static final MethodHandle INVALIDATE_SP = findOwnMH_S("invalidateSwitchPoint", Object.class, Object.class, SwitchPoint.class); 42.16 - 42.17 - private static final SwitchPoint NO_CHANGE_CALLBACK = new SwitchPoint(); 42.18 + private static final MethodHandle INVALIDATE_SP = findOwnMH_S("invalidateSwitchPoint", Object.class, AccessorProperty.class, Object.class); 42.19 42.20 private static final int NOOF_TYPES = getNumberOfAccessorTypes(); 42.21 private static final long serialVersionUID = 3371720170182154920L; 42.22 @@ -221,7 +218,7 @@ 42.23 * @param setter the property setter or null if non writable, non configurable 42.24 */ 42.25 private AccessorProperty(final String key, final int flags, final int slot, final MethodHandle getter, final MethodHandle setter) { 42.26 - super(key, flags | (getter.type().returnType().isPrimitive() ? IS_NASGEN_PRIMITIVE : 0), slot); 42.27 + super(key, flags | IS_BUILTIN | (getter.type().returnType().isPrimitive() ? IS_NASGEN_PRIMITIVE : 0), slot); 42.28 assert !isSpill(); 42.29 42.30 // we don't need to prep the setters these will never be invalidated as this is a nasgen 42.31 @@ -602,7 +599,6 @@ 42.32 42.33 private Property getWiderProperty(final Class<?> type) { 42.34 return copy(type); //invalidate cache of new property 42.35 - 42.36 } 42.37 42.38 private PropertyMap getWiderMap(final PropertyMap oldMap, final Property newProperty) { 42.39 @@ -627,8 +623,10 @@ 42.40 } 42.41 42.42 @SuppressWarnings("unused") 42.43 - private static Object invalidateSwitchPoint(final Object obj, final SwitchPoint sp) { 42.44 - SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 42.45 + private static Object invalidateSwitchPoint(final AccessorProperty property, final Object obj) { 42.46 + if (!property.builtinSwitchPoint.hasBeenInvalidated()) { 42.47 + SwitchPoint.invalidateAll(new SwitchPoint[] { property.builtinSwitchPoint }); 42.48 + } 42.49 return obj; 42.50 } 42.51 42.52 @@ -668,12 +666,8 @@ 42.53 mh = generateSetter(!forType.isPrimitive() ? Object.class : forType, type); 42.54 } 42.55 42.56 - /** 42.57 - * Check if this is a special global name that requires switchpoint invalidation 42.58 - */ 42.59 - final SwitchPoint ccb = getChangeCallback(); 42.60 - if (ccb != null && ccb != NO_CHANGE_CALLBACK) { 42.61 - mh = MH.filterArguments(mh, 0, MH.insertArguments(debugInvalidate(getKey(), ccb), 1, changeCallback)); 42.62 + if (isBuiltin()) { 42.63 + mh = MH.filterArguments(mh, 0, debugInvalidate(MH.insertArguments(INVALIDATE_SP, 0, this), getKey())); 42.64 } 42.65 42.66 assert mh.type().returnType() == void.class : mh.type(); 42.67 @@ -681,25 +675,6 @@ 42.68 return mh; 42.69 } 42.70 42.71 - /** 42.72 - * Get the change callback for this property 42.73 - * @return switchpoint that is invalidated when property changes 42.74 - */ 42.75 - protected SwitchPoint getChangeCallback() { 42.76 - if (changeCallback == null) { 42.77 - try { 42.78 - changeCallback = Global.instance().getChangeCallback(getKey()); 42.79 - } catch (final NullPointerException e) { 42.80 - assert !"apply".equals(getKey()) && !"call".equals(getKey()); 42.81 - //empty 42.82 - } 42.83 - if (changeCallback == null) { 42.84 - changeCallback = NO_CHANGE_CALLBACK; 42.85 - } 42.86 - } 42.87 - return changeCallback; 42.88 - } 42.89 - 42.90 @Override 42.91 public final boolean canChangeType() { 42.92 if (OBJECT_FIELDS_ONLY) { 42.93 @@ -724,7 +699,6 @@ 42.94 return currentType; 42.95 } 42.96 42.97 - 42.98 private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) { 42.99 if (!Context.DEBUG || !Global.hasInstance()) { 42.100 return mh; 42.101 @@ -780,9 +754,9 @@ 42.102 return mh; 42.103 } 42.104 42.105 - private static MethodHandle debugInvalidate(final String key, final SwitchPoint sp) { 42.106 + private static MethodHandle debugInvalidate(final MethodHandle invalidator, final String key) { 42.107 if (!Context.DEBUG || !Global.hasInstance()) { 42.108 - return INVALIDATE_SP; 42.109 + return invalidator; 42.110 } 42.111 42.112 final Context context = Context.getContextTrusted(); 42.113 @@ -790,11 +764,11 @@ 42.114 42.115 return context.addLoggingToHandle( 42.116 ObjectClassGenerator.class, 42.117 - INVALIDATE_SP, 42.118 + invalidator, 42.119 new Supplier<String>() { 42.120 @Override 42.121 public String get() { 42.122 - return "Field change callback for " + key + " triggered: " + sp; 42.123 + return "Field change callback for " + key + " triggered "; 42.124 } 42.125 }); 42.126 }
43.1 --- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java Wed Oct 01 12:22:12 2014 +0200 43.2 +++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java Thu Sep 25 15:53:47 2014 +0200 43.3 @@ -81,13 +81,17 @@ 43.4 43.5 /** 43.6 * Store a compiled script for later reuse 43.7 + * 43.8 + * @param cacheKey key to use in cache 43.9 * @param source the script source 43.10 * @param mainClassName the main class name 43.11 * @param classBytes map of class names to class bytes 43.12 + * @param initializers compilation id -> FunctionInitializer map 43.13 * @param constants constants array 43.14 + * @param compilationId compilation id 43.15 */ 43.16 - public void storeScript(String cacheKey, Source source, String mainClassName, Map<String, byte[]> classBytes, 43.17 - Map<Integer, FunctionInitializer> initializers, Object[] constants, int compilationId); 43.18 + public void storeScript(final String cacheKey, final Source source, final String mainClassName, final Map<String, byte[]> classBytes, 43.19 + final Map<Integer, FunctionInitializer> initializers, final Object[] constants, final int compilationId); 43.20 43.21 /** 43.22 * Load a previously compiled script
44.1 --- a/src/jdk/nashorn/internal/runtime/CodeStore.java Wed Oct 01 12:22:12 2014 +0200 44.2 +++ b/src/jdk/nashorn/internal/runtime/CodeStore.java Thu Sep 25 15:53:47 2014 +0200 44.3 @@ -118,6 +118,8 @@ 44.4 * @param initializers the function initializers 44.5 * @param constants the constants array 44.6 * @param compilationId the compilation id 44.7 + * 44.8 + * @return stored script 44.9 */ 44.10 public StoredScript store(final String functionKey, 44.11 final Source source, 44.12 @@ -153,11 +155,13 @@ 44.13 /** 44.14 * Returns a new StoredScript instance. 44.15 * 44.16 + * @param source the source 44.17 * @param mainClassName the main class name 44.18 * @param classBytes a map of class bytes 44.19 * @param initializers function initializers 44.20 * @param constants the constants array 44.21 * @param compilationId the compilation id 44.22 + * 44.23 * @return The compiled script 44.24 */ 44.25 public StoredScript storedScriptFor(final Source source, final String mainClassName, 44.26 @@ -206,7 +210,7 @@ 44.27 /** 44.28 * Constructor 44.29 * 44.30 - * @throws IOException 44.31 + * @throws IOException if there are read/write problems with the cache and cache directory 44.32 */ 44.33 public DirectoryCodeStore() throws IOException { 44.34 this(Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache"), false, DEFAULT_MIN_SIZE); 44.35 @@ -216,8 +220,9 @@ 44.36 * Constructor 44.37 * 44.38 * @param path directory to store code in 44.39 + * @param readOnly is this a read only code store 44.40 * @param minSize minimum file size for caching scripts 44.41 - * @throws IOException 44.42 + * @throws IOException if there are read/write problems with the cache and cache directory 44.43 */ 44.44 public DirectoryCodeStore(final String path, final boolean readOnly, final int minSize) throws IOException { 44.45 this.dir = checkDirectory(path, readOnly);
45.1 --- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java Wed Oct 01 12:22:12 2014 +0200 45.2 +++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java Thu Sep 25 15:53:47 2014 +0200 45.3 @@ -33,12 +33,13 @@ 45.4 import java.lang.invoke.MethodType; 45.5 import java.lang.invoke.MutableCallSite; 45.6 import java.lang.invoke.SwitchPoint; 45.7 +import java.util.Collection; 45.8 +import java.util.Collections; 45.9 import java.util.Iterator; 45.10 import java.util.Map; 45.11 import java.util.TreeMap; 45.12 import java.util.function.Supplier; 45.13 import java.util.logging.Level; 45.14 - 45.15 import jdk.internal.dynalink.linker.GuardedInvocation; 45.16 import jdk.nashorn.internal.codegen.Compiler; 45.17 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; 45.18 @@ -46,6 +47,7 @@ 45.19 import jdk.nashorn.internal.codegen.types.ArrayType; 45.20 import jdk.nashorn.internal.codegen.types.Type; 45.21 import jdk.nashorn.internal.ir.FunctionNode; 45.22 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 45.23 import jdk.nashorn.internal.runtime.events.RecompilationEvent; 45.24 import jdk.nashorn.internal.runtime.linker.Bootstrap; 45.25 import jdk.nashorn.internal.runtime.logging.DebugLogger; 45.26 @@ -63,6 +65,8 @@ 45.27 45.28 private final DebugLogger log; 45.29 45.30 + static final Collection<CompiledFunction> NO_FUNCTIONS = Collections.emptySet(); 45.31 + 45.32 /** 45.33 * The method type may be more specific than the invoker, if. e.g. 45.34 * the invoker is guarded, and a guard with a generic object only 45.35 @@ -75,19 +79,38 @@ 45.36 private final int flags; // from FunctionNode 45.37 private final MethodType callSiteType; 45.38 45.39 + private final Specialization specialization; 45.40 + 45.41 CompiledFunction(final MethodHandle invoker) { 45.42 - this(invoker, null); 45.43 + this(invoker, null, null); 45.44 } 45.45 45.46 - static CompiledFunction createBuiltInConstructor(final MethodHandle invoker) { 45.47 - return new CompiledFunction(MH.insertArguments(invoker, 0, false), createConstructorFromInvoker(MH.insertArguments(invoker, 0, true))); 45.48 + static CompiledFunction createBuiltInConstructor(final MethodHandle invoker, final Specialization specialization) { 45.49 + return new CompiledFunction(MH.insertArguments(invoker, 0, false), createConstructorFromInvoker(MH.insertArguments(invoker, 0, true)), specialization); 45.50 } 45.51 45.52 - CompiledFunction(final MethodHandle invoker, final MethodHandle constructor) { 45.53 - this(invoker, constructor, 0, null, DebugLogger.DISABLED_LOGGER); 45.54 + CompiledFunction(final MethodHandle invoker, final MethodHandle constructor, final Specialization specialization) { 45.55 + this(invoker, constructor, 0, null, specialization, DebugLogger.DISABLED_LOGGER); 45.56 } 45.57 45.58 - CompiledFunction(final MethodHandle invoker, final MethodHandle constructor, final int flags, final MethodType callSiteType, final DebugLogger log) { 45.59 + CompiledFunction(final MethodHandle invoker, final MethodHandle constructor, final int flags, final MethodType callSiteType, final Specialization specialization, final DebugLogger log) { 45.60 + this.specialization = specialization; 45.61 + if (specialization != null && specialization.isOptimistic()) { 45.62 + /* 45.63 + * An optimistic builtin with isOptimistic=true works like any optimistic generated function, i.e. it 45.64 + * can throw unwarranted optimism exceptions. As native functions trivially can't have parts of them 45.65 + * regenerated as restof methods, this only works if the methods are atomic/functional in their behavior 45.66 + * and doesn't modify state before an UOE can be thrown. If they aren't, we can reexecute a wider version 45.67 + * of the same builtin in a recompilation handler for FinalScriptFunctionData. There are several 45.68 + * candidate methods in Native* that would benefit from this, but I haven't had time to implement any 45.69 + * of them currently. In order to fit in with the relinking framework, the current thinking is 45.70 + * that the methods still take a program point to fit in with other optimistic functions, but 45.71 + * it is set to "first", which is the beginning of the method. The relinker can tell the difference 45.72 + * between builtin and JavaScript functions. This might change. TODO 45.73 + */ 45.74 + this.invoker = MH.insertArguments(invoker, invoker.type().parameterCount() - 1, UnwarrantedOptimismException.FIRST_PROGRAM_POINT); 45.75 + throw new AssertionError("Optimistic (UnwarrantedOptimismException throwing) builtin functions are currently not in use"); 45.76 + } 45.77 this.invoker = invoker; 45.78 this.constructor = constructor; 45.79 this.flags = flags; 45.80 @@ -97,7 +120,7 @@ 45.81 45.82 CompiledFunction(final MethodHandle invoker, final RecompilableScriptFunctionData functionData, 45.83 final Map<Integer, Type> invalidatedProgramPoints, final MethodType callSiteType, final int flags) { 45.84 - this(invoker, null, flags, callSiteType, functionData.getLogger()); 45.85 + this(invoker, null, flags, callSiteType, null, functionData.getLogger()); 45.86 if ((flags & FunctionNode.IS_DEOPTIMIZABLE) != 0) { 45.87 optimismInfo = new OptimismInfo(functionData, invalidatedProgramPoints); 45.88 } else { 45.89 @@ -105,10 +128,45 @@ 45.90 } 45.91 } 45.92 45.93 + static CompiledFunction createBuiltInConstructor(final MethodHandle invoker) { 45.94 + return new CompiledFunction(MH.insertArguments(invoker, 0, false), createConstructorFromInvoker(MH.insertArguments(invoker, 0, true)), null); 45.95 + } 45.96 + 45.97 + boolean isSpecialization() { 45.98 + return specialization != null; 45.99 + } 45.100 + 45.101 + boolean hasLinkLogic() { 45.102 + return getLinkLogicClass() != null; 45.103 + } 45.104 + 45.105 + Class<? extends LinkLogic> getLinkLogicClass() { 45.106 + if (isSpecialization()) { 45.107 + final Class<? extends LinkLogic> linkLogicClass = specialization.getLinkLogicClass(); 45.108 + assert !LinkLogic.isEmpty(linkLogicClass) : "empty link logic classes should have been removed by nasgen"; 45.109 + return linkLogicClass; 45.110 + } 45.111 + return null; 45.112 + } 45.113 + 45.114 int getFlags() { 45.115 return flags; 45.116 } 45.117 45.118 + /** 45.119 + * An optimistic specialization is one that can throw UnwarrantedOptimismException. 45.120 + * This is allowed for native methods, as long as they are functional, i.e. don't change 45.121 + * any state between entering and throwing the UOE. Then we can re-execute a wider version 45.122 + * of the method in the continuation. Rest-of method generation for optimistic builtins is 45.123 + * of course not possible, but this approach works and fits into the same relinking 45.124 + * framework 45.125 + * 45.126 + * @return true if optimistic builtin 45.127 + */ 45.128 + boolean isOptimistic() { 45.129 + return isSpecialization() ? specialization.isOptimistic() : false; 45.130 + } 45.131 + 45.132 boolean isApplyToCall() { 45.133 return (flags & FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION) != 0; 45.134 } 45.135 @@ -119,7 +177,19 @@ 45.136 45.137 @Override 45.138 public String toString() { 45.139 - return "[invokerType=" + invoker.type() + " ctor=" + constructor + " weight=" + weight() + " isApplyToCall=" + isApplyToCall() + "]"; 45.140 + final StringBuilder sb = new StringBuilder(); 45.141 + final Class<? extends LinkLogic> linkLogicClass = getLinkLogicClass(); 45.142 + 45.143 + sb.append("[invokerType="). 45.144 + append(invoker.type()). 45.145 + append(" ctor="). 45.146 + append(constructor). 45.147 + append(" weight="). 45.148 + append(weight()). 45.149 + append(" linkLogic="). 45.150 + append(linkLogicClass != null ? linkLogicClass.getSimpleName() : "none"); 45.151 + 45.152 + return sb.toString(); 45.153 } 45.154 45.155 boolean needsCallee() { 45.156 @@ -281,10 +351,12 @@ 45.157 if (other == null) { 45.158 return true; 45.159 } 45.160 - return betterThanFinal(type(), other.type(), callSiteMethodType); 45.161 + return betterThanFinal(this, other, callSiteMethodType); 45.162 } 45.163 45.164 - static boolean betterThanFinal(final MethodType thisMethodType, final MethodType otherMethodType, final MethodType callSiteMethodType) { 45.165 + private static boolean betterThanFinal(final CompiledFunction cf, final CompiledFunction other, final MethodType callSiteMethodType) { 45.166 + final MethodType thisMethodType = cf.type(); 45.167 + final MethodType otherMethodType = other.type(); 45.168 final int thisParamCount = getParamCount(thisMethodType); 45.169 final int otherParamCount = getParamCount(otherMethodType); 45.170 final int callSiteRawParamCount = getParamCount(callSiteMethodType); 45.171 @@ -406,7 +478,17 @@ 45.172 return false; 45.173 } 45.174 45.175 - throw new AssertionError(thisMethodType + " identically applicable to " + otherMethodType + " for " + callSiteMethodType); // Signatures are identical 45.176 + //if they are equal, pick the specialized one first 45.177 + if (cf.isSpecialization() != other.isSpecialization()) { 45.178 + return cf.isSpecialization(); //always pick the specialized version if we can 45.179 + } 45.180 + 45.181 + if (cf.isSpecialization() && other.isSpecialization()) { 45.182 + return cf.getLinkLogicClass() != null; //pick link logic specialization above generic specializations 45.183 + } 45.184 + 45.185 + // Signatures are identical 45.186 + throw new AssertionError(thisMethodType + " identically applicable to " + otherMethodType + " for " + callSiteMethodType); 45.187 } 45.188 45.189 private static Type[] toTypeWithoutCallee(final MethodType type, final int thisIndex) { 45.190 @@ -427,8 +509,8 @@ 45.191 return ((ArrayType)paramTypes[paramTypes.length - 1]).getElementType(); 45.192 } 45.193 45.194 - boolean matchesCallSite(final MethodType callSiteType, final boolean pickVarArg) { 45.195 - if (callSiteType.equals(this.callSiteType)) { 45.196 + boolean matchesCallSite(final MethodType other, final boolean pickVarArg) { 45.197 + if (other.equals(this.callSiteType)) { 45.198 return true; 45.199 } 45.200 final MethodType type = type(); 45.201 @@ -438,7 +520,7 @@ 45.202 return pickVarArg; 45.203 } 45.204 45.205 - final int csParamCount = getParamCount(callSiteType); 45.206 + final int csParamCount = getParamCount(other); 45.207 final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE; 45.208 final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type 45.209 45.210 @@ -447,7 +529,7 @@ 45.211 // We must match all incoming parameters, except "this". Starting from 1 to skip "this". 45.212 for(int i = 1; i < minParams; ++i) { 45.213 final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex)); 45.214 - final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(callSiteType.parameterType(i + 1)); 45.215 + final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1)); 45.216 if(!fnType.isEquivalentTo(csType)) { 45.217 return false; 45.218 } 45.219 @@ -669,9 +751,9 @@ 45.220 return sb.toString(); 45.221 } 45.222 45.223 - private void logRecompile(final String reason, final FunctionNode fn, final MethodType callSiteType, final Map<Integer, Type> ipp) { 45.224 + private void logRecompile(final String reason, final FunctionNode fn, final MethodType type, final Map<Integer, Type> ipp) { 45.225 if (log.isEnabled()) { 45.226 - log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", callSiteType, " ", toStringInvalidations(ipp)); 45.227 + log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", type, " ", toStringInvalidations(ipp)); 45.228 } 45.229 } 45.230
46.1 --- a/src/jdk/nashorn/internal/runtime/Context.java Wed Oct 01 12:22:12 2014 +0200 46.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java Thu Sep 25 15:53:47 2014 +0200 46.3 @@ -33,13 +33,13 @@ 46.4 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 46.5 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 46.6 import static jdk.nashorn.internal.runtime.Source.sourceFor; 46.7 - 46.8 import java.io.File; 46.9 import java.io.IOException; 46.10 import java.io.PrintWriter; 46.11 import java.lang.invoke.MethodHandle; 46.12 import java.lang.invoke.MethodHandles; 46.13 import java.lang.invoke.MethodType; 46.14 +import java.lang.invoke.SwitchPoint; 46.15 import java.lang.ref.ReferenceQueue; 46.16 import java.lang.ref.SoftReference; 46.17 import java.lang.reflect.Field; 46.18 @@ -127,6 +127,16 @@ 46.19 private static MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); 46.20 private static MethodType CREATE_PROGRAM_FUNCTION_TYPE = MethodType.methodType(ScriptFunction.class, ScriptObject.class); 46.21 46.22 + /** 46.23 + * Keeps track of which builtin prototypes and properties have been relinked 46.24 + * Currently we are conservative and associate the name of a builtin class with all 46.25 + * its properties, so it's enough to invalidate a property to break all assumptions 46.26 + * about a prototype. This can be changed to a more fine grained approach, but no one 46.27 + * ever needs this, given the very rare occurance of swapping out only parts of 46.28 + * a builtin v.s. the entire builtin object 46.29 + */ 46.30 + private final Map<String, SwitchPoint> builtinSwitchPoints = new HashMap<>(); 46.31 + 46.32 /* Force DebuggerSupport to be loaded. */ 46.33 static { 46.34 DebuggerSupport.FORCELOAD = true; 46.35 @@ -1371,4 +1381,34 @@ 46.36 return null; 46.37 } 46.38 46.39 + /** 46.40 + * This is a special kind of switchpoint used to guard builtin 46.41 + * properties and prototypes. In the future it might contain 46.42 + * logic to e.g. multiple switchpoint classes. 46.43 + */ 46.44 + public static final class BuiltinSwitchPoint extends SwitchPoint { 46.45 + //empty 46.46 + } 46.47 + 46.48 + /** 46.49 + * Create a new builtin switchpoint and return it 46.50 + * @param name key name 46.51 + * @return new builtin switchpoint 46.52 + */ 46.53 + public SwitchPoint newBuiltinSwitchPoint(final String name) { 46.54 + assert builtinSwitchPoints.get(name) == null; 46.55 + final SwitchPoint sp = new BuiltinSwitchPoint(); 46.56 + builtinSwitchPoints.put(name, sp); 46.57 + return sp; 46.58 + } 46.59 + 46.60 + /** 46.61 + * Return the builtin switchpoint for a particular key name 46.62 + * @param name key name 46.63 + * @return builtin switchpoint or null if none 46.64 + */ 46.65 + public SwitchPoint getBuiltinSwitchPoint(final String name) { 46.66 + return builtinSwitchPoints.get(name); 46.67 + } 46.68 + 46.69 }
47.1 --- a/src/jdk/nashorn/internal/runtime/Debug.java Wed Oct 01 12:22:12 2014 +0200 47.2 +++ b/src/jdk/nashorn/internal/runtime/Debug.java Thu Sep 25 15:53:47 2014 +0200 47.3 @@ -26,7 +26,6 @@ 47.4 package jdk.nashorn.internal.runtime; 47.5 47.6 import static jdk.nashorn.internal.parser.TokenType.EOF; 47.7 - 47.8 import jdk.nashorn.internal.parser.Lexer; 47.9 import jdk.nashorn.internal.parser.Token; 47.10 import jdk.nashorn.internal.parser.TokenStream; 47.11 @@ -42,12 +41,12 @@ 47.12 47.13 /** 47.14 * Return the topmost JavaScript frame in a stack trace 47.15 - * @param e 47.16 + * @param t throwable that contains the stack trace 47.17 * @return line describing the topmost JavaScript frame 47.18 */ 47.19 - public static String firstJSFrame(final Throwable e) { 47.20 - for (final StackTraceElement ste : e.getStackTrace()) { 47.21 - if(ECMAErrors.isScriptFrame(ste)) { 47.22 + public static String firstJSFrame(final Throwable t) { 47.23 + for (final StackTraceElement ste : t.getStackTrace()) { 47.24 + if (ECMAErrors.isScriptFrame(ste)) { 47.25 return ste.toString(); 47.26 } 47.27 }
48.1 --- a/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Wed Oct 01 12:22:12 2014 +0200 48.2 +++ b/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Thu Sep 25 15:53:47 2014 +0200 48.3 @@ -60,13 +60,13 @@ 48.4 * @param specs specializations 48.5 * @param flags {@link ScriptFunctionData} flags 48.6 */ 48.7 - FinalScriptFunctionData(final String name, final MethodHandle mh, final MethodHandle[] specs, final int flags) { 48.8 + FinalScriptFunctionData(final String name, final MethodHandle mh, final Specialization[] specs, final int flags) { 48.9 super(name, methodHandleArity(mh), flags); 48.10 48.11 addInvoker(mh); 48.12 if (specs != null) { 48.13 - for (final MethodHandle spec : specs) { 48.14 - addInvoker(spec); 48.15 + for (final Specialization spec : specs) { 48.16 + addInvoker(spec.getMethodHandle(), spec); 48.17 } 48.18 } 48.19 } 48.20 @@ -114,16 +114,25 @@ 48.21 return MethodType.genericMethodType(max + 1); 48.22 } 48.23 48.24 - private void addInvoker(final MethodHandle mh) { 48.25 + private CompiledFunction addInvoker(final MethodHandle mh, final Specialization specialization) { 48.26 assert !needsCallee(mh); 48.27 + 48.28 + final CompiledFunction invoker; 48.29 if (isConstructor(mh)) { 48.30 // only nasgen constructors: (boolean, self, args) are subject to binding a boolean newObj. isConstructor 48.31 // is too conservative a check. However, isConstructor(mh) always implies isConstructor param 48.32 assert isConstructor(); 48.33 - code.add(CompiledFunction.createBuiltInConstructor(mh)); 48.34 + invoker = CompiledFunction.createBuiltInConstructor(mh); 48.35 } else { 48.36 - code.add(new CompiledFunction(mh)); 48.37 + invoker = new CompiledFunction(mh, null, specialization); 48.38 } 48.39 + code.add(invoker); 48.40 + 48.41 + return invoker; 48.42 + } 48.43 + 48.44 + private CompiledFunction addInvoker(final MethodHandle mh) { 48.45 + return addInvoker(mh, null); 48.46 } 48.47 48.48 private static int methodHandleArity(final MethodHandle mh) {
49.1 --- a/src/jdk/nashorn/internal/runtime/FindProperty.java Wed Oct 01 12:22:12 2014 +0200 49.2 +++ b/src/jdk/nashorn/internal/runtime/FindProperty.java Thu Sep 25 15:53:47 2014 +0200 49.3 @@ -79,6 +79,8 @@ 49.4 * 49.5 * @param type type of getter, e.g. int.class if we want a function with {@code get()I} signature 49.6 * @param programPoint program point, or INVALID_PROGRAM_POINT if pessimistic 49.7 + * @param request link request 49.8 + * 49.9 * @return method handle for the getter 49.10 */ 49.11 public MethodHandle getGetter(final Class<?> type, final int programPoint, final LinkRequest request) { 49.12 @@ -102,6 +104,7 @@ 49.13 * 49.14 * @param type type of setter, e.g. int.class if we want a function with {@code set(I)V} signature 49.15 * @param strict are we in strict mode 49.16 + * @param request link request 49.17 * 49.18 * @return method handle for the getter 49.19 */
50.1 --- a/src/jdk/nashorn/internal/runtime/GlobalConstants.java Wed Oct 01 12:22:12 2014 +0200 50.2 +++ b/src/jdk/nashorn/internal/runtime/GlobalConstants.java Thu Sep 25 15:53:47 2014 +0200 50.3 @@ -358,8 +358,12 @@ 50.4 * @param c constant value 50.5 * @return method handle (with dummy receiver) that returns this constant 50.6 */ 50.7 + public static MethodHandle staticConstantGetter(final Object c) { 50.8 + return MH.dropArguments(JSType.unboxConstant(c), 0, Object.class); 50.9 + } 50.10 + 50.11 private MethodHandle constantGetter(final Object c) { 50.12 - final MethodHandle mh = MH.dropArguments(JSType.unboxConstant(c), 0, Object.class); 50.13 + final MethodHandle mh = staticConstantGetter(c); 50.14 if (log.isEnabled()) { 50.15 return MethodHandleFactory.addDebugPrintout(log, Level.FINEST, mh, "getting as constant"); 50.16 }
51.1 --- a/src/jdk/nashorn/internal/runtime/GlobalFunctions.java Wed Oct 01 12:22:12 2014 +0200 51.2 +++ b/src/jdk/nashorn/internal/runtime/GlobalFunctions.java Thu Sep 25 15:53:47 2014 +0200 51.3 @@ -42,12 +42,30 @@ 51.4 /** Methodhandle (specialized) to implementation of ECMA 15.1.2.2, parseInt */ 51.5 public static final MethodHandle PARSEINT_OI = findOwnMH("parseInt", double.class, Object.class, Object.class, int.class); 51.6 51.7 + /** ParseInt - NaN for booleans (thru string conversion to number conversion) */ 51.8 + public static final MethodHandle PARSEINT_Z = MH.dropArguments(MH.dropArguments(MH.constant(double.class, Double.NaN), 0, boolean.class), 0, Object.class); 51.9 + 51.10 + /** ParseInt - identity for ints */ 51.11 + public static final MethodHandle PARSEINT_I = MH.dropArguments(MH.identity(int.class), 0, Object.class); 51.12 + 51.13 + /** ParseInt - identity for longs */ 51.14 + public static final MethodHandle PARSEINT_J = MH.dropArguments(MH.identity(long.class), 0, Object.class); 51.15 + 51.16 /** Methodhandle (specialized) to implementation of ECMA 15.1.2.2, parseInt */ 51.17 public static final MethodHandle PARSEINT_O = findOwnMH("parseInt", double.class, Object.class, Object.class); 51.18 51.19 /** Methodhandle to implementation of ECMA 15.1.2.3, parseFloat */ 51.20 public static final MethodHandle PARSEFLOAT = findOwnMH("parseFloat", double.class, Object.class, Object.class); 51.21 51.22 + /** isNan for integers - always false */ 51.23 + public static final MethodHandle IS_NAN_I = MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class); 51.24 + 51.25 + /** isNan for longs - always false */ 51.26 + public static final MethodHandle IS_NAN_J = MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class); 51.27 + 51.28 + /** IsNan for doubles - use Double.isNaN */ 51.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); 51.30 + 51.31 /** Methodhandle to implementation of ECMA 15.1.2.4, isNaN */ 51.32 public static final MethodHandle IS_NAN = findOwnMH("isNaN", boolean.class, Object.class, Object.class); 51.33
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 52.2 +++ b/src/jdk/nashorn/internal/runtime/OptimisticBuiltins.java Thu Sep 25 15:53:47 2014 +0200 52.3 @@ -0,0 +1,65 @@ 52.4 +/* 52.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 52.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 52.7 + * 52.8 + * This code is free software; you can redistribute it and/or modify it 52.9 + * under the terms of the GNU General Public License version 2 only, as 52.10 + * published by the Free Software Foundation. Oracle designates this 52.11 + * particular file as subject to the "Classpath" exception as provided 52.12 + * by Oracle in the LICENSE file that accompanied this code. 52.13 + * 52.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 52.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 52.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 52.17 + * version 2 for more details (a copy is included in the LICENSE file that 52.18 + * accompanied this code). 52.19 + * 52.20 + * You should have received a copy of the GNU General Public License version 52.21 + * 2 along with this work; if not, write to the Free Software Foundation, 52.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 52.23 + * 52.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 52.25 + * or visit www.oracle.com if you need additional information or have any 52.26 + * questions. 52.27 + */ 52.28 + 52.29 +package jdk.nashorn.internal.runtime; 52.30 + 52.31 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 52.32 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 52.33 + 52.34 +/** 52.35 + * This is an interface for classes that need custom linkage logic. This means Native objects 52.36 + * that contain optimistic native methods, that need special/extra rules for linking, guards and 52.37 + * SwitchPointing, known and internal to the Native object for its linkage 52.38 + */ 52.39 +public interface OptimisticBuiltins { 52.40 + 52.41 + /** 52.42 + * Return an instance of the linking logic we need for a particular LinkLogic 52.43 + * subclass, gotten from the compile time annotation of a specialized builtin method 52.44 + * No assumptions can be made about the lifetime of the instance. The receiver may 52.45 + * keep it as a perpetual final instance field or create new linking logic depending 52.46 + * on its current state for each call, depending on if the global state has changed 52.47 + * or other factors 52.48 + * 52.49 + * @param clazz linking logic class 52.50 + * @return linking logic instance for this class 52.51 + */ 52.52 + public SpecializedFunction.LinkLogic getLinkLogic(final Class<? extends LinkLogic> clazz); 52.53 + 52.54 + /** 52.55 + * Does this link logic vary depending on which instance we are working with. 52.56 + * Then we have to sort out certain primitives, as they are created as new 52.57 + * objects in the wrapFilter by JavaScript semantics. An example of instance only 52.58 + * assumptions are switchPoints per instance, as in NativeArray. NativeString is 52.59 + * fine, as it's only static. 52.60 + * 52.61 + * TODO: finer granularity on this, on the function level so certain functions 52.62 + * are forbidden only. Currently we don't have enough specialization to bump into this 52.63 + * 52.64 + * @return true if there are per instance assumptions for the optimism 52.65 + */ 52.66 + public boolean hasPerInstanceAssumptions(); 52.67 + 52.68 +}
53.1 --- a/src/jdk/nashorn/internal/runtime/Property.java Wed Oct 01 12:22:12 2014 +0200 53.2 +++ b/src/jdk/nashorn/internal/runtime/Property.java Thu Sep 25 15:53:47 2014 +0200 53.3 @@ -28,7 +28,6 @@ 53.4 import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE; 53.5 import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE; 53.6 import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE; 53.7 - 53.8 import java.io.Serializable; 53.9 import java.lang.invoke.MethodHandle; 53.10 import java.lang.invoke.SwitchPoint; 53.11 @@ -84,6 +83,9 @@ 53.12 */ 53.13 public static final int IS_NASGEN_PRIMITIVE = 1 << 6; 53.14 53.15 + /** Is this a builtin property, e.g. Function.prototype.apply */ 53.16 + public static final int IS_BUILTIN = 1 << 7; 53.17 + 53.18 /** Is this property bound to a receiver? This means get/set operations will be delegated to 53.19 * a statically defined object instead of the object passed as callsite parameter. */ 53.20 public static final int IS_BOUND = 1 << 7; 53.21 @@ -101,7 +103,7 @@ 53.22 private final int slot; 53.23 53.24 /** SwitchPoint that is invalidated when property is changed, optional */ 53.25 - protected transient SwitchPoint changeCallback; 53.26 + protected transient SwitchPoint builtinSwitchPoint; 53.27 53.28 private static final long serialVersionUID = 2099814273074501176L; 53.29 53.30 @@ -125,10 +127,10 @@ 53.31 * @param property source property 53.32 */ 53.33 Property(final Property property, final int flags) { 53.34 - this.key = property.key; 53.35 - this.slot = property.slot; 53.36 - this.changeCallback = property.changeCallback; 53.37 - this.flags = flags; 53.38 + this.key = property.key; 53.39 + this.slot = property.slot; 53.40 + this.builtinSwitchPoint = property.builtinSwitchPoint; 53.41 + this.flags = flags; 53.42 } 53.43 53.44 /** 53.45 @@ -182,8 +184,26 @@ 53.46 * changed 53.47 * @param sp SwitchPoint to use for change callback 53.48 */ 53.49 - public final void setChangeCallback(final SwitchPoint sp) { 53.50 - this.changeCallback = sp; 53.51 + public final void setBuiltinSwitchPoint(final SwitchPoint sp) { 53.52 + this.builtinSwitchPoint = sp; 53.53 + } 53.54 + 53.55 + /** 53.56 + * Builtin properties have an invalidation switchpoint that is 53.57 + * invalidated when they are set, this is a getter for it 53.58 + * @return builtin switchpoint, or null if none 53.59 + */ 53.60 + public final SwitchPoint getBuiltinSwitchPoint() { 53.61 + return builtinSwitchPoint; 53.62 + } 53.63 + 53.64 + /** 53.65 + * Checks if this is a builtin property, this means that it has 53.66 + * a builtin switchpoint that hasn't been invalidated by a setter 53.67 + * @return true if builtin, untouched (unset) property 53.68 + */ 53.69 + public boolean isBuiltin() { 53.70 + return builtinSwitchPoint != null && !builtinSwitchPoint.hasBeenInvalidated(); 53.71 } 53.72 53.73 /**
54.1 --- a/src/jdk/nashorn/internal/runtime/PropertyMap.java Wed Oct 01 12:22:12 2014 +0200 54.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java Thu Sep 25 15:53:47 2014 +0200 54.3 @@ -950,7 +950,7 @@ 54.4 54.5 @Override 54.6 public void remove() { 54.7 - throw new UnsupportedOperationException(); 54.8 + throw new UnsupportedOperationException("remove"); 54.9 } 54.10 } 54.11
55.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Oct 01 12:22:12 2014 +0200 55.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Thu Sep 25 15:53:47 2014 +0200 55.3 @@ -26,11 +26,11 @@ 55.4 package jdk.nashorn.internal.runtime; 55.5 55.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 55.7 - 55.8 import java.io.IOException; 55.9 import java.lang.invoke.MethodHandle; 55.10 import java.lang.invoke.MethodHandles; 55.11 import java.lang.invoke.MethodType; 55.12 +import java.util.Collection; 55.13 import java.util.Collections; 55.14 import java.util.HashMap; 55.15 import java.util.HashSet; 55.16 @@ -454,7 +454,7 @@ 55.17 // CompilationEnvironment#declareLocalSymbol()). 55.18 55.19 if (log.isEnabled()) { 55.20 - log.info("Type specialization of '", functionName, "' signature: ", actualCallSiteType); 55.21 + log.info("Parameter type specialization of '", functionName, "' signature: ", actualCallSiteType); 55.22 } 55.23 55.24 final boolean persistentCache = usePersistentCodeCache() && persist; 55.25 @@ -501,13 +501,13 @@ 55.26 55.27 for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) { 55.28 final String className = entry.getKey(); 55.29 - final byte[] code = entry.getValue(); 55.30 + final byte[] bytecode = entry.getValue(); 55.31 55.32 if (className.equals(mainClassName)) { 55.33 continue; 55.34 } 55.35 55.36 - installedClasses.put(className, installer.install(className, code)); 55.37 + installedClasses.put(className, installer.install(className, bytecode)); 55.38 } 55.39 55.40 final Map<Integer, FunctionInitializer> initializers = script.getInitializers(); 55.41 @@ -588,15 +588,17 @@ 55.42 return lookupCodeMethod(fn.getCompileUnit().getCode(), type); 55.43 } 55.44 55.45 - MethodHandle lookupCodeMethod(final Class<?> code, final MethodType targetType) { 55.46 + MethodHandle lookupCodeMethod(final Class<?> codeClass, final MethodType targetType) { 55.47 log.info("Looking up ", DebugLogger.quote(name), " type=", targetType); 55.48 - return MH.findStatic(LOOKUP, code, functionName, targetType); 55.49 + return MH.findStatic(LOOKUP, codeClass, functionName, targetType); 55.50 } 55.51 55.52 /** 55.53 * Initializes this function data with the eagerly generated version of the code. This method can only be invoked 55.54 * by the compiler internals in Nashorn and is public for implementation reasons only. Attempting to invoke it 55.55 * externally will result in an exception. 55.56 + * 55.57 + * @param initializer FunctionInitializer for this data 55.58 */ 55.59 public void initializeCode(final FunctionInitializer initializer) { 55.60 // Since the method is public, we double-check that we aren't invoked with an inappropriate compile unit. 55.61 @@ -658,8 +660,8 @@ 55.62 55.63 55.64 @Override 55.65 - synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope) { 55.66 - CompiledFunction existingBest = super.getBest(callSiteType, runtimeScope); 55.67 + synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) { 55.68 + CompiledFunction existingBest = super.getBest(callSiteType, runtimeScope, forbidden); 55.69 if (existingBest == null) { 55.70 existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope, true), callSiteType); 55.71 } 55.72 @@ -723,6 +725,10 @@ 55.73 return functionNodeId; 55.74 } 55.75 55.76 + /** 55.77 + * Get the source for the script 55.78 + * @return source 55.79 + */ 55.80 public Source getSource() { 55.81 return source; 55.82 }
56.1 --- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Wed Oct 01 12:22:12 2014 +0200 56.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Thu Sep 25 15:53:47 2014 +0200 56.3 @@ -181,9 +181,6 @@ 56.4 /** print symbols and their contents for the script */ 56.5 public final boolean _print_symbols; 56.6 56.7 - /** range analysis for known types */ 56.8 - public final boolean _range_analysis; 56.9 - 56.10 /** is this environment in scripting mode? */ 56.11 public final boolean _scripting; 56.12 56.13 @@ -255,7 +252,6 @@ 56.14 _print_parse = options.getBoolean("print.parse"); 56.15 _print_lower_parse = options.getBoolean("print.lower.parse"); 56.16 _print_symbols = options.getBoolean("print.symbols"); 56.17 - _range_analysis = options.getBoolean("range.analysis"); 56.18 _scripting = options.getBoolean("scripting"); 56.19 _strict = options.getBoolean("strict"); 56.20 _version = options.getBoolean("version");
57.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Oct 01 12:22:12 2014 +0200 57.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Sep 25 15:53:47 2014 +0200 57.3 @@ -30,26 +30,29 @@ 57.4 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 57.5 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 57.6 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 57.7 - 57.8 import java.lang.invoke.MethodHandle; 57.9 import java.lang.invoke.MethodHandles; 57.10 import java.lang.invoke.MethodType; 57.11 import java.lang.invoke.SwitchPoint; 57.12 +import java.util.ArrayList; 57.13 +import java.util.Arrays; 57.14 +import java.util.Collection; 57.15 import java.util.Collections; 57.16 - 57.17 +import java.util.HashSet; 57.18 +import java.util.List; 57.19 import jdk.internal.dynalink.CallSiteDescriptor; 57.20 import jdk.internal.dynalink.linker.GuardedInvocation; 57.21 import jdk.internal.dynalink.linker.LinkRequest; 57.22 import jdk.internal.dynalink.support.Guards; 57.23 import jdk.nashorn.internal.codegen.ApplySpecialization; 57.24 +import jdk.nashorn.internal.codegen.Compiler; 57.25 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 57.26 import jdk.nashorn.internal.objects.Global; 57.27 import jdk.nashorn.internal.objects.NativeFunction; 57.28 -import jdk.nashorn.internal.runtime.ScriptFunctionData; 57.29 -import jdk.nashorn.internal.runtime.ScriptObject; 57.30 -import jdk.nashorn.internal.runtime.ScriptRuntime; 57.31 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 57.32 import jdk.nashorn.internal.runtime.linker.Bootstrap; 57.33 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; 57.34 +import jdk.nashorn.internal.runtime.logging.DebugLogger; 57.35 57.36 /** 57.37 * Runtime representation of a JavaScript function. 57.38 @@ -114,7 +117,7 @@ 57.39 final MethodHandle methodHandle, 57.40 final PropertyMap map, 57.41 final ScriptObject scope, 57.42 - final MethodHandle[] specs, 57.43 + final Specialization[] specs, 57.44 final int flags) { 57.45 57.46 this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope); 57.47 @@ -468,13 +471,12 @@ 57.48 protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) { 57.49 final MethodType type = desc.getMethodType(); 57.50 assert desc.getMethodType().returnType() == Object.class && !NashornCallSiteDescriptor.isOptimistic(desc); 57.51 - final CompiledFunction cf = data.getBestConstructor(type, scope); 57.52 + final CompiledFunction cf = data.getBestConstructor(type, scope, CompiledFunction.NO_FUNCTIONS); 57.53 final GuardedInvocation bestCtorInv = cf.createConstructorInvocation(); 57.54 //TODO - ClassCastException 57.55 return new GuardedInvocation(pairArguments(bestCtorInv.getInvocation(), type), getFunctionGuard(this, cf.getFlags()), bestCtorInv.getSwitchPoints(), null); 57.56 } 57.57 57.58 - @SuppressWarnings("unused") 57.59 private static Object wrapFilter(final Object obj) { 57.60 if (obj instanceof ScriptObject || !ScriptFunctionData.isPrimitiveThis(obj)) { 57.61 return obj; 57.62 @@ -490,6 +492,35 @@ 57.63 } 57.64 57.65 /** 57.66 + * Some receivers are primitive, in that case, according to the Spec we create a new 57.67 + * native object per callsite with the wrap filter. We can only apply optimistic builtins 57.68 + * if there is no per instance state saved for these wrapped objects (e.g. currently NativeStrings), 57.69 + * otherwise we can't create optimistic versions 57.70 + * 57.71 + * @param self receiver 57.72 + * @param linkLogicClass linkLogicClass, or null if no link logic exists 57.73 + * @return link logic instance, or null if one could not be constructed for this receiver 57.74 + */ 57.75 + private static LinkLogic getLinkLogic(final Object self, final Class<? extends LinkLogic> linkLogicClass) { 57.76 + if (linkLogicClass == null) { 57.77 + return LinkLogic.EMPTY_INSTANCE; //always OK to link this, specialization but without special linking logic 57.78 + } 57.79 + 57.80 + if (!Context.getContextTrusted().getEnv()._optimistic_types) { 57.81 + return null; //if optimistic types are off, optimistic builtins are too 57.82 + } 57.83 + 57.84 + final Object wrappedSelf = wrapFilter(self); 57.85 + if (wrappedSelf instanceof OptimisticBuiltins) { 57.86 + if (wrappedSelf != self && ((OptimisticBuiltins)wrappedSelf).hasPerInstanceAssumptions()) { 57.87 + return null; //pessimistic - we created a wrapped object different from the primitive, but the assumptions have instance state 57.88 + } 57.89 + return ((OptimisticBuiltins)wrappedSelf).getLinkLogic(linkLogicClass); 57.90 + } 57.91 + return null; 57.92 + } 57.93 + 57.94 + /** 57.95 * dyn:call call site signature: (callee, thiz, [args...]) 57.96 * generated method signature: (callee, thiz, [args...]) 57.97 * 57.98 @@ -547,8 +578,53 @@ 57.99 } 57.100 } //else just fall through and link as ordinary function or unstable apply 57.101 57.102 - final int programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ? NashornCallSiteDescriptor.getProgramPoint(desc) : INVALID_PROGRAM_POINT; 57.103 - final CompiledFunction cf = data.getBestInvoker(type, scope); 57.104 + int programPoint = INVALID_PROGRAM_POINT; 57.105 + if (NashornCallSiteDescriptor.isOptimistic(desc)) { 57.106 + programPoint = NashornCallSiteDescriptor.getProgramPoint(desc); 57.107 + } 57.108 + 57.109 + CompiledFunction cf = data.getBestInvoker(type, scope, CompiledFunction.NO_FUNCTIONS); 57.110 + final Object self = request.getArguments()[1]; 57.111 + final Collection<CompiledFunction> forbidden = new HashSet<>(); 57.112 + 57.113 + //check for special fast versions of the compiled function 57.114 + final List<SwitchPoint> sps = new ArrayList<>(); 57.115 + Class<? extends Throwable> exceptionGuard = null; 57.116 + 57.117 + while (cf.isSpecialization()) { 57.118 + final Class<? extends LinkLogic> linkLogicClass = cf.getLinkLogicClass(); 57.119 + //if linklogic is null, we can always link with the standard mechanism, it's still a specialization 57.120 + final LinkLogic linkLogic = getLinkLogic(self, linkLogicClass); 57.121 + 57.122 + if (linkLogic != null && linkLogic.checkLinkable(self, desc, request)) { 57.123 + final DebugLogger log = Context.getContextTrusted().getLogger(Compiler.class); 57.124 + 57.125 + if (log.isEnabled()) { 57.126 + log.info("Linking optimistic builtin function: '", name, "' args=", Arrays.toString(request.getArguments()), " desc=", desc); 57.127 + } 57.128 + 57.129 + final SwitchPoint[] msps = linkLogic.getModificationSwitchPoints(); 57.130 + if (msps != null) { 57.131 + for (final SwitchPoint sp : msps) { 57.132 + if (sp != null) { 57.133 + assert !sp.hasBeenInvalidated(); 57.134 + sps.add(sp); 57.135 + } 57.136 + } 57.137 + } 57.138 + 57.139 + exceptionGuard = linkLogic.getRelinkException(); 57.140 + 57.141 + break; 57.142 + } 57.143 + 57.144 + //could not link this specialization because link check failed 57.145 + forbidden.add(cf); 57.146 + final CompiledFunction oldCf = cf; 57.147 + cf = data.getBestInvoker(type, scope, forbidden); 57.148 + assert oldCf != cf; 57.149 + } 57.150 + 57.151 final GuardedInvocation bestInvoker = cf.createFunctionInvocation(type.returnType(), programPoint); 57.152 final MethodHandle callHandle = bestInvoker.getInvocation(); 57.153 57.154 @@ -588,7 +664,20 @@ 57.155 57.156 boundHandle = pairArguments(boundHandle, type); 57.157 57.158 - return new GuardedInvocation(boundHandle, guard == null ? getFunctionGuard(this, cf.getFlags()) : guard, bestInvoker.getSwitchPoints(), null); 57.159 + if (bestInvoker.getSwitchPoints() != null) { 57.160 + sps.addAll(Arrays.asList(bestInvoker.getSwitchPoints())); 57.161 + } 57.162 + final SwitchPoint[] spsArray = sps.isEmpty() ? null : sps.toArray(new SwitchPoint[sps.size()]); 57.163 + 57.164 + return new GuardedInvocation( 57.165 + boundHandle, 57.166 + guard == null ? 57.167 + getFunctionGuard( 57.168 + this, 57.169 + cf.getFlags()) : 57.170 + guard, 57.171 + spsArray, 57.172 + exceptionGuard); 57.173 } 57.174 57.175 private GuardedInvocation createApplyOrCallCall(final boolean isApply, final CallSiteDescriptor desc, final LinkRequest request, final Object[] args) { 57.176 @@ -610,7 +699,7 @@ 57.177 57.178 //box call back to apply 57.179 CallSiteDescriptor appliedDesc = desc; 57.180 - final SwitchPoint applyToCallSwitchPoint = Global.instance().getChangeCallback("apply"); 57.181 + final SwitchPoint applyToCallSwitchPoint = Global.getBuiltinFunctionApplySwitchPoint(); 57.182 //enough to change the proto switchPoint here 57.183 57.184 final boolean isApplyToCall = NashornCallSiteDescriptor.isApplyToCall(desc); 57.185 @@ -656,7 +745,7 @@ 57.186 } 57.187 } 57.188 57.189 - appliedDesc = appliedDesc.changeMethodType(appliedType); 57.190 + appliedDesc = appliedDesc.changeMethodType(appliedType); //no extra args 57.191 57.192 // Create the same arguments for the delegate linking request that would be passed in an actual apply'd invocation 57.193 final Object[] appliedArgs = new Object[isApply ? 3 : appliedType.parameterCount()]; 57.194 @@ -681,6 +770,7 @@ 57.195 57.196 // Ask the linker machinery for an invocation of the target function 57.197 final LinkRequest appliedRequest = request.replaceArguments(appliedDesc, appliedArgs); 57.198 + 57.199 GuardedInvocation appliedInvocation; 57.200 try { 57.201 appliedInvocation = Bootstrap.getLinkerServices().getGuardedInvocation(appliedRequest); 57.202 @@ -742,7 +832,7 @@ 57.203 // We need to account for the dropped (apply|call) function argument. 57.204 guard = MH.dropArguments(guard, 0, descType.parameterType(0)); 57.205 // Take the "isApplyFunction" guard, and bind it to this function. 57.206 - MethodHandle applyFnGuard = MH.insertArguments(IS_APPLY_FUNCTION, 2, this); 57.207 + MethodHandle applyFnGuard = MH.insertArguments(IS_APPLY_FUNCTION, 2, this); //TODO replace this with switchpoint 57.208 // Adapt the guard to receive all the arguments that the original guard does. 57.209 applyFnGuard = MH.dropArguments(applyFnGuard, 2, guardType.parameterArray()); 57.210 // Fold the original function guard into our apply guard. 57.211 @@ -894,6 +984,7 @@ 57.212 return self instanceof ScriptFunction && ((ScriptFunction)self).data == data && arg instanceof ScriptObject; 57.213 } 57.214 57.215 + //TODO this can probably be removed given that we have builtin switchpoints in the context 57.216 @SuppressWarnings("unused") 57.217 private static boolean isApplyFunction(final boolean appliedFnCondition, final Object self, final Object expectedSelf) { 57.218 // NOTE: we're using self == expectedSelf as we're only using this with built-in functions apply() and call()
58.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Oct 01 12:22:12 2014 +0200 58.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Thu Sep 25 15:53:47 2014 +0200 58.3 @@ -28,13 +28,13 @@ 58.4 import static jdk.nashorn.internal.lookup.Lookup.MH; 58.5 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 58.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 58.7 - 58.8 import java.io.IOException; 58.9 import java.io.ObjectInputStream; 58.10 import java.io.Serializable; 58.11 import java.lang.invoke.MethodHandle; 58.12 import java.lang.invoke.MethodHandles; 58.13 import java.lang.invoke.MethodType; 58.14 +import java.util.Collection; 58.15 import java.util.LinkedList; 58.16 import java.util.List; 58.17 import jdk.nashorn.internal.runtime.linker.LinkerCallSite; 58.18 @@ -136,7 +136,7 @@ 58.19 final MethodHandle boundInvoker = bindInvokeHandle(originalInv.createComposableInvoker(), fn, self, args); 58.20 58.21 if (isConstructor()) { 58.22 - return new CompiledFunction(boundInvoker, bindConstructHandle(originalInv.createComposableConstructor(), fn, args)); 58.23 + return new CompiledFunction(boundInvoker, bindConstructHandle(originalInv.createComposableConstructor(), fn, args), null); 58.24 } 58.25 58.26 return new CompiledFunction(boundInvoker); 58.27 @@ -224,18 +224,22 @@ 58.28 * @param callSiteType callsite type 58.29 * @return compiled function object representing the best invoker. 58.30 */ 58.31 - final CompiledFunction getBestInvoker(final MethodType callSiteType, final ScriptObject runtimeScope) { 58.32 - final CompiledFunction cf = getBest(callSiteType, runtimeScope); 58.33 + final CompiledFunction getBestInvoker(final MethodType callSiteType, final ScriptObject runtimeScope) { 58.34 + return getBestInvoker(callSiteType, runtimeScope, CompiledFunction.NO_FUNCTIONS); 58.35 + } 58.36 + 58.37 + final CompiledFunction getBestInvoker(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) { 58.38 + final CompiledFunction cf = getBest(callSiteType, runtimeScope, forbidden); 58.39 assert cf != null; 58.40 return cf; 58.41 } 58.42 58.43 - final CompiledFunction getBestConstructor(final MethodType callSiteType, final ScriptObject runtimeScope) { 58.44 + final CompiledFunction getBestConstructor(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) { 58.45 if (!isConstructor()) { 58.46 throw typeError("not.a.constructor", toSource()); 58.47 } 58.48 // Constructor call sites don't have a "this", but getBest is meant to operate on "callee, this, ..." style 58.49 - final CompiledFunction cf = getBest(callSiteType.insertParameterTypes(1, Object.class), runtimeScope); 58.50 + final CompiledFunction cf = getBest(callSiteType.insertParameterTypes(1, Object.class), runtimeScope, forbidden); 58.51 return cf; 58.52 } 58.53 58.54 @@ -350,7 +354,7 @@ 58.55 * scope is not known, but that might cause compilation of code that will need more deoptimization passes. 58.56 * @return the best function for the specified call site type. 58.57 */ 58.58 - CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope) { 58.59 + CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) { 58.60 assert callSiteType.parameterCount() >= 2 : callSiteType; // Must have at least (callee, this) 58.61 assert callSiteType.parameterType(0).isAssignableFrom(ScriptFunction.class) : callSiteType; // Callee must be assignable from script function 58.62 58.63 @@ -363,8 +367,8 @@ 58.64 } 58.65 58.66 CompiledFunction best = null; 58.67 - for(final CompiledFunction candidate: code) { 58.68 - if(candidate.betterThanFinal(best, callSiteType)) { 58.69 + for (final CompiledFunction candidate: code) { 58.70 + if (!forbidden.contains(candidate) && candidate.betterThanFinal(best, callSiteType)) { 58.71 best = candidate; 58.72 } 58.73 } 58.74 @@ -376,7 +380,7 @@ 58.75 abstract boolean isRecompilable(); 58.76 58.77 CompiledFunction getGeneric(final ScriptObject runtimeScope) { 58.78 - return getBest(getGenericType(), runtimeScope); 58.79 + return getBest(getGenericType(), runtimeScope, CompiledFunction.NO_FUNCTIONS); 58.80 } 58.81 58.82 /** 58.83 @@ -420,7 +424,7 @@ 58.84 58.85 final List<CompiledFunction> boundList = new LinkedList<>(); 58.86 final ScriptObject runtimeScope = fn.getScope(); 58.87 - final CompiledFunction bindTarget = new CompiledFunction(getGenericInvoker(runtimeScope), getGenericConstructor(runtimeScope)); 58.88 + final CompiledFunction bindTarget = new CompiledFunction(getGenericInvoker(runtimeScope), getGenericConstructor(runtimeScope), null); 58.89 boundList.add(bind(bindTarget, fn, self, allArgs)); 58.90 58.91 return new FinalScriptFunctionData(name, Math.max(0, getArity() - length), boundList, boundFlags);
59.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Oct 01 12:22:12 2014 +0200 59.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Sep 25 15:53:47 2014 +0200 59.3 @@ -47,7 +47,6 @@ 59.4 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex; 59.5 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; 59.6 import static jdk.nashorn.internal.runtime.linker.NashornGuards.explicitInstanceOfCheck; 59.7 - 59.8 import java.lang.invoke.MethodHandle; 59.9 import java.lang.invoke.MethodHandles; 59.10 import java.lang.invoke.MethodType; 59.11 @@ -820,6 +819,19 @@ 59.12 return false; 59.13 } 59.14 59.15 + private SwitchPoint findBuiltinSwitchPoint(final String key) { 59.16 + for (ScriptObject myProto = getProto(); myProto != null; myProto = myProto.getProto()) { 59.17 + final Property prop = myProto.getMap().findProperty(key); 59.18 + if (prop != null) { 59.19 + final SwitchPoint sp = prop.getBuiltinSwitchPoint(); 59.20 + if (sp != null && !sp.hasBeenInvalidated()) { 59.21 + return sp; 59.22 + } 59.23 + } 59.24 + } 59.25 + return null; 59.26 + } 59.27 + 59.28 /** 59.29 * Add a new property to the object. 59.30 * <p> 59.31 @@ -923,10 +935,10 @@ 59.32 * creating setters that probably aren't used. Inject directly into the spill pool 59.33 * the defaults for "arguments" and "caller" 59.34 * 59.35 - * @param key 59.36 - * @param propertyFlags 59.37 - * @param getter 59.38 - * @param setter 59.39 + * @param key property key 59.40 + * @param propertyFlags flags 59.41 + * @param getter getter for {@link UserAccessorProperty}, null if not present or N/A 59.42 + * @param setter setter for {@link UserAccessorProperty}, null if not present or N/A 59.43 */ 59.44 protected final void initUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) { 59.45 final int slot = spillLength; 59.46 @@ -1514,6 +1526,23 @@ 59.47 } 59.48 59.49 /** 59.50 + * Get the {@link ArrayData}, for this ScriptObject, ensuring it is of a type 59.51 + * that can handle elementType 59.52 + * @param elementType elementType 59.53 + * @return array data 59.54 + */ 59.55 + public final ArrayData getArray(final Class<?> elementType) { 59.56 + if (elementType == null) { 59.57 + return arrayData; 59.58 + } 59.59 + final ArrayData newArrayData = arrayData.convert(elementType); 59.60 + if (newArrayData != arrayData) { 59.61 + arrayData = newArrayData; 59.62 + } 59.63 + return newArrayData; 59.64 + } 59.65 + 59.66 + /** 59.67 * Get the {@link ArrayData} for this ScriptObject if it is an array 59.68 * @return array data 59.69 */ 59.70 @@ -1720,8 +1749,8 @@ 59.71 */ 59.72 public Object put(final Object key, final Object value, final boolean strict) { 59.73 final Object oldValue = get(key); 59.74 - final int flags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0; 59.75 - set(key, value, flags); 59.76 + final int scriptObjectFlags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0; 59.77 + set(key, value, scriptObjectFlags); 59.78 return oldValue; 59.79 } 59.80 59.81 @@ -1734,9 +1763,9 @@ 59.82 * @param strict strict mode or not 59.83 */ 59.84 public void putAll(final Map<?, ?> otherMap, final boolean strict) { 59.85 - final int flags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0; 59.86 + final int scriptObjectFlags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0; 59.87 for (final Map.Entry<?, ?> entry : otherMap.entrySet()) { 59.88 - set(entry.getKey(), entry.getValue(), flags); 59.89 + set(entry.getKey(), entry.getValue(), scriptObjectFlags); 59.90 } 59.91 } 59.92 59.93 @@ -1916,17 +1945,6 @@ 59.94 return MH.filterArguments(methodHandle, 0, filter.asType(filter.type().changeReturnType(methodHandle.type().parameterType(0)))); 59.95 } 59.96 59.97 - //this will only return true if apply is still builtin 59.98 - private static SwitchPoint checkReservedName(final CallSiteDescriptor desc, final LinkRequest request) { 59.99 - final boolean isApplyToCall = NashornCallSiteDescriptor.isApplyToCall(desc); 59.100 - final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 59.101 - if ("apply".equals(name) && isApplyToCall && Global.instance().isSpecialNameValid(name)) { 59.102 - assert Global.instance().getChangeCallback("apply") == Global.instance().getChangeCallback("call"); 59.103 - return Global.instance().getChangeCallback("apply"); 59.104 - } 59.105 - return null; 59.106 - } 59.107 - 59.108 /** 59.109 * Find the appropriate GET method for an invoke dynamic call. 59.110 * 59.111 @@ -1938,14 +1956,13 @@ 59.112 */ 59.113 protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) { 59.114 final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request); 59.115 - final String name; 59.116 - final SwitchPoint reservedNameSwitchPoint; 59.117 - 59.118 - reservedNameSwitchPoint = checkReservedName(desc, request); 59.119 - if (reservedNameSwitchPoint != null) { 59.120 - name = "call"; //turn apply into call, it is the builtin apply and has been modified to explode args 59.121 - } else { 59.122 - name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 59.123 + 59.124 + String name; 59.125 + name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 59.126 + if (NashornCallSiteDescriptor.isApplyToCall(desc)) { 59.127 + if (Global.isBuiltinFunctionPrototypeApply()) { 59.128 + name = "call"; 59.129 + } 59.130 } 59.131 59.132 if (request.isCallSiteUnstable() || hasWithScope()) { 59.133 @@ -2006,7 +2023,7 @@ 59.134 assert OBJECT_FIELDS_ONLY || guard != null : "we always need a map guard here"; 59.135 59.136 final GuardedInvocation inv = new GuardedInvocation(mh, guard, protoSwitchPoint, exception); 59.137 - return inv.addSwitchPoint(reservedNameSwitchPoint); 59.138 + return inv.addSwitchPoint(findBuiltinSwitchPoint(name)); 59.139 } 59.140 59.141 private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) { 59.142 @@ -2029,7 +2046,7 @@ 59.143 // Marks a property as declared and sets its value. Used as slow path for block-scoped LET and CONST 59.144 @SuppressWarnings("unused") 59.145 private void declareAndSet(final String key, final Object value) { 59.146 - final PropertyMap map = getMap(); 59.147 + final PropertyMap oldMap = getMap(); 59.148 final FindProperty find = findProperty(key, false); 59.149 assert find != null; 59.150 59.151 @@ -2037,7 +2054,7 @@ 59.152 assert property != null; 59.153 assert property.needsDeclaration(); 59.154 59.155 - final PropertyMap newMap = map.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION)); 59.156 + final PropertyMap newMap = oldMap.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION)); 59.157 setMap(newMap); 59.158 set(key, value, 0); 59.159 } 59.160 @@ -2166,7 +2183,7 @@ 59.161 } 59.162 } 59.163 59.164 - final GuardedInvocation inv = new SetMethodCreator(this, find, desc, request).createGuardedInvocation(); 59.165 + final GuardedInvocation inv = new SetMethodCreator(this, find, desc, request).createGuardedInvocation(findBuiltinSwitchPoint(name)); 59.166 59.167 final GuardedInvocation cinv = Global.getConstants().findSetMethod(find, this, inv, desc, request); 59.168 if (cinv != null) { 59.169 @@ -2429,7 +2446,7 @@ 59.170 59.171 @Override 59.172 public void remove() { 59.173 - throw new UnsupportedOperationException(); 59.174 + throw new UnsupportedOperationException("remove"); 59.175 } 59.176 } 59.177
60.1 --- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Oct 01 12:22:12 2014 +0200 60.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Thu Sep 25 15:53:47 2014 +0200 60.3 @@ -32,9 +32,9 @@ 60.4 import static jdk.nashorn.internal.runtime.ECMAErrors.syntaxError; 60.5 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 60.6 import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt; 60.7 - 60.8 import java.lang.invoke.MethodHandle; 60.9 import java.lang.invoke.MethodHandles; 60.10 +import java.lang.invoke.SwitchPoint; 60.11 import java.lang.reflect.Array; 60.12 import java.util.Collections; 60.13 import java.util.Iterator; 60.14 @@ -46,6 +46,7 @@ 60.15 import jdk.internal.dynalink.beans.StaticClass; 60.16 import jdk.nashorn.api.scripting.JSObject; 60.17 import jdk.nashorn.api.scripting.ScriptObjectMirror; 60.18 +import jdk.nashorn.internal.codegen.ApplySpecialization; 60.19 import jdk.nashorn.internal.codegen.CompilerConstants; 60.20 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 60.21 import jdk.nashorn.internal.ir.debug.JSONWriter; 60.22 @@ -113,6 +114,11 @@ 60.23 public static final Call THROW_REFERENCE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwReferenceError", void.class, String.class); 60.24 60.25 /** 60.26 + * Used to invalidate builtin names, e.g "Function" mapping to all properties in Function.prototype and Function.prototype itself. 60.27 + */ 60.28 + public static final Call INVALIDATE_RESERVED_BUILTIN_NAME = staticCallNoLookup(ScriptRuntime.class, "invalidateReservedBuiltinName", void.class, String.class); 60.29 + 60.30 + /** 60.31 * Converts a switch tag value to a simple integer. deflt value if it can't. 60.32 * 60.33 * @param tag Switch statement tag value. 60.34 @@ -290,7 +296,7 @@ 60.35 60.36 @Override 60.37 public void remove() { 60.38 - throw new UnsupportedOperationException(); 60.39 + throw new UnsupportedOperationException("remove"); 60.40 } 60.41 } 60.42 60.43 @@ -328,7 +334,7 @@ 60.44 60.45 @Override 60.46 public void remove() { 60.47 - throw new UnsupportedOperationException(); 60.48 + throw new UnsupportedOperationException("remove"); 60.49 } 60.50 }; 60.51 } 60.52 @@ -998,4 +1004,19 @@ 60.53 return nx < ny; 60.54 } 60.55 60.56 + /** 60.57 + * Tag a reserved name as invalidated - used when someone writes 60.58 + * to a property with this name - overly conservative, but link time 60.59 + * is too late to apply e.g. apply->call specialization 60.60 + * @param name property name 60.61 + */ 60.62 + public static void invalidateReservedBuiltinName(final String name) { 60.63 + final Context context = Context.getContextTrusted(); 60.64 + final SwitchPoint sp = context.getBuiltinSwitchPoint(name); 60.65 + assert sp != null; 60.66 + if (sp != null) { 60.67 + context.getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint"); 60.68 + SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 60.69 + } 60.70 + } 60.71 }
61.1 --- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Wed Oct 01 12:22:12 2014 +0200 61.2 +++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Thu Sep 25 15:53:47 2014 +0200 61.3 @@ -28,7 +28,6 @@ 61.4 import static jdk.nashorn.internal.lookup.Lookup.MH; 61.5 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; 61.6 import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex; 61.7 - 61.8 import java.lang.invoke.MethodHandle; 61.9 import java.lang.invoke.SwitchPoint; 61.10 import jdk.internal.dynalink.CallSiteDescriptor; 61.11 @@ -81,8 +80,8 @@ 61.12 * Creates the actual guarded invocation that represents the dynamic setter method for the property. 61.13 * @return the actual guarded invocation that represents the dynamic setter method for the property. 61.14 */ 61.15 - GuardedInvocation createGuardedInvocation() { 61.16 - return createSetMethod().createGuardedInvocation(); 61.17 + GuardedInvocation createGuardedInvocation(final SwitchPoint builtinSwitchPoint) { 61.18 + return createSetMethod(builtinSwitchPoint).createGuardedInvocation(); 61.19 } 61.20 61.21 /** 61.22 @@ -119,7 +118,7 @@ 61.23 } 61.24 } 61.25 61.26 - private SetMethod createSetMethod() { 61.27 + private SetMethod createSetMethod(final SwitchPoint builtinSwitchPoint) { 61.28 if (find != null) { 61.29 return createExistingPropertySetter(); 61.30 } 61.31 @@ -130,7 +129,7 @@ 61.32 return createGlobalPropertySetter(); 61.33 } 61.34 61.35 - return createNewPropertySetter(); 61.36 + return createNewPropertySetter(builtinSwitchPoint); 61.37 } 61.38 61.39 private void checkStrictCreateNewVariable() { 61.40 @@ -185,8 +184,8 @@ 61.41 return new SetMethod(MH.filterArguments(global.addSpill(type, getName()), 0, ScriptObject.GLOBALFILTER), null); 61.42 } 61.43 61.44 - private SetMethod createNewPropertySetter() { 61.45 - final SetMethod sm = map.getFreeFieldSlot() > -1 ? createNewFieldSetter() : createNewSpillPropertySetter(); 61.46 + private SetMethod createNewPropertySetter(final SwitchPoint builtinSwitchPoint) { 61.47 + final SetMethod sm = map.getFreeFieldSlot() > -1 ? createNewFieldSetter(builtinSwitchPoint) : createNewSpillPropertySetter(builtinSwitchPoint); 61.48 final PropertyListeners listeners = map.getListeners(); 61.49 if (listeners != null) { 61.50 listeners.propertyAdded(sm.property); 61.51 @@ -194,7 +193,9 @@ 61.52 return sm; 61.53 } 61.54 61.55 - private SetMethod createNewSetter(final Property property) { 61.56 + private SetMethod createNewSetter(final Property property, final SwitchPoint builtinSwitchPoint) { 61.57 + property.setBuiltinSwitchPoint(builtinSwitchPoint); 61.58 + 61.59 final PropertyMap oldMap = getMap(); 61.60 final PropertyMap newMap = getNewMap(property); 61.61 final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc); 61.62 @@ -230,12 +231,12 @@ 61.63 return new SetMethod(MH.asType(MH.guardWithTest(extCheck, casGuard, nop), fastSetter.type()), property); 61.64 } 61.65 61.66 - private SetMethod createNewFieldSetter() { 61.67 - return createNewSetter(new AccessorProperty(getName(), 0, sobj.getClass(), getMap().getFreeFieldSlot(), type)); 61.68 + private SetMethod createNewFieldSetter(final SwitchPoint builtinSwitchPoint) { 61.69 + return createNewSetter(new AccessorProperty(getName(), 0, sobj.getClass(), getMap().getFreeFieldSlot(), type), builtinSwitchPoint); 61.70 } 61.71 61.72 - private SetMethod createNewSpillPropertySetter() { 61.73 - return createNewSetter(new SpillProperty(getName(), 0, getMap().getFreeSpillSlot(), type)); 61.74 + private SetMethod createNewSpillPropertySetter(final SwitchPoint builtinSwitchPoint) { 61.75 + return createNewSetter(new SpillProperty(getName(), 0, getMap().getFreeSpillSlot(), type), builtinSwitchPoint); 61.76 } 61.77 61.78 private PropertyMap getNewMap(final Property property) {
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 62.2 +++ b/src/jdk/nashorn/internal/runtime/Specialization.java Thu Sep 25 15:53:47 2014 +0200 62.3 @@ -0,0 +1,114 @@ 62.4 +/* 62.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 62.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 62.7 + * 62.8 + * This code is free software; you can redistribute it and/or modify it 62.9 + * under the terms of the GNU General Public License version 2 only, as 62.10 + * published by the Free Software Foundation. Oracle designates this 62.11 + * particular file as subject to the "Classpath" exception as provided 62.12 + * by Oracle in the LICENSE file that accompanied this code. 62.13 + * 62.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 62.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 62.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 62.17 + * version 2 for more details (a copy is included in the LICENSE file that 62.18 + * accompanied this code). 62.19 + * 62.20 + * You should have received a copy of the GNU General Public License version 62.21 + * 2 along with this work; if not, write to the Free Software Foundation, 62.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 62.23 + * 62.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 62.25 + * or visit www.oracle.com if you need additional information or have any 62.26 + * questions. 62.27 + */ 62.28 + 62.29 +package jdk.nashorn.internal.runtime; 62.30 + 62.31 +import java.lang.invoke.MethodHandle; 62.32 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 62.33 +import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic; 62.34 + 62.35 +/** 62.36 + * Specialization info for a {@link SpecializedFunction} 62.37 + */ 62.38 +public final class Specialization { 62.39 + private final MethodHandle mh; 62.40 + private final Class<? extends LinkLogic> linkLogicClass; 62.41 + private final boolean isOptimistic; 62.42 + 62.43 + /** 62.44 + * Constructor 62.45 + * 62.46 + * @param mh invoker method handler 62.47 + */ 62.48 + public Specialization(final MethodHandle mh) { 62.49 + this(mh, false); 62.50 + } 62.51 + 62.52 + /** 62.53 + * Constructor 62.54 + * 62.55 + * @param mh invoker method handler 62.56 + * @param isOptimistic is this an optimistic native method, i.e. can it throw {@link UnwarrantedOptimismException} 62.57 + * which would have to lead to a relink and return value processing 62.58 + */ 62.59 + public Specialization(final MethodHandle mh, final boolean isOptimistic) { 62.60 + this(mh, null, isOptimistic); 62.61 + } 62.62 + 62.63 + /** 62.64 + * Constructor 62.65 + * 62.66 + * @param mh invoker method handler 62.67 + * @param linkLogicClass extra link logic needed for this function. Instances of this class also contains logic for checking 62.68 + * if this can be linked on its first encounter, which is needed as per our standard linker semantics 62.69 + * @param isOptimistic is this an optimistic native method, i.e. can it throw {@link UnwarrantedOptimismException} 62.70 + * which would have to lead to a relink and return value processing 62.71 + */ 62.72 + public Specialization(final MethodHandle mh, final Class<? extends LinkLogic> linkLogicClass, final boolean isOptimistic) { 62.73 + this.mh = mh; 62.74 + this.isOptimistic = isOptimistic; 62.75 + if (linkLogicClass != null) { 62.76 + //null out the "empty" link logic class for optimization purposes 62.77 + //we only use the empty instance because we can't default class annotations 62.78 + //to null 62.79 + this.linkLogicClass = LinkLogic.isEmpty(linkLogicClass) ? null : linkLogicClass; 62.80 + } else { 62.81 + this.linkLogicClass = null; 62.82 + } 62.83 + } 62.84 + 62.85 + /** 62.86 + * Get the method handle for the invoker of this ScriptFunction 62.87 + * @return the method handle 62.88 + */ 62.89 + public MethodHandle getMethodHandle() { 62.90 + return mh; 62.91 + } 62.92 + 62.93 + /** 62.94 + * Get the link logic class for this ScriptFunction 62.95 + * @return link logic class info, i.e. one whose instance contains stuff like 62.96 + * "do we need exception check for every call", and logic to check if we may link 62.97 + */ 62.98 + public Class<? extends LinkLogic> getLinkLogicClass() { 62.99 + return linkLogicClass; 62.100 + } 62.101 + 62.102 + /** 62.103 + * An optimistic specialization is one that can throw UnwarrantedOptimismException. 62.104 + * This is allowed for native methods, as long as they are functional, i.e. don't change 62.105 + * any state between entering and throwing the UOE. Then we can re-execute a wider version 62.106 + * of the method in the continuation. Rest-of method generation for optimistic builtins is 62.107 + * of course not possible, but this approach works and fits into the same relinking 62.108 + * framework 62.109 + * 62.110 + * @return true if optimistic 62.111 + */ 62.112 + public boolean isOptimistic() { 62.113 + return isOptimistic; 62.114 + } 62.115 + 62.116 +} 62.117 +
63.1 --- a/src/jdk/nashorn/internal/runtime/StoredScript.java Wed Oct 01 12:22:12 2014 +0200 63.2 +++ b/src/jdk/nashorn/internal/runtime/StoredScript.java Thu Sep 25 15:53:47 2014 +0200 63.3 @@ -55,8 +55,10 @@ 63.4 /** 63.5 * Constructor. 63.6 * 63.7 + * @param compilationId compilation id 63.8 * @param mainClassName main class name 63.9 * @param classBytes map of class names to class bytes 63.10 + * @param initializers initializer map, id -> FunctionInitializer 63.11 * @param constants constants array 63.12 */ 63.13 public StoredScript(final int compilationId, final String mainClassName, final Map<String, byte[]> classBytes, final Map<Integer, FunctionInitializer> initializers, final Object[] constants) { 63.14 @@ -67,6 +69,10 @@ 63.15 this.initializers = initializers; 63.16 } 63.17 63.18 + /** 63.19 + * Get the compilation id for this StoredScript 63.20 + * @return compilation id 63.21 + */ 63.22 public int getCompilationId() { 63.23 return compilationId; 63.24 }
64.1 --- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Wed Oct 01 12:22:12 2014 +0200 64.2 +++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Thu Sep 25 15:53:47 2014 +0200 64.3 @@ -25,7 +25,6 @@ 64.4 64.5 package jdk.nashorn.internal.runtime; 64.6 64.7 -import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; 64.8 import static jdk.nashorn.internal.lookup.Lookup.MH; 64.9 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 64.10 import static jdk.nashorn.internal.runtime.JSType.CONVERT_OBJECT_OPTIMISTIC;
65.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Wed Oct 01 12:22:12 2014 +0200 65.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Thu Sep 25 15:53:47 2014 +0200 65.3 @@ -26,7 +26,6 @@ 65.4 package jdk.nashorn.internal.runtime.arrays; 65.5 65.6 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; 65.7 - 65.8 import java.lang.invoke.MethodHandle; 65.9 import java.lang.invoke.MethodHandles; 65.10 import java.nio.ByteBuffer; 65.11 @@ -58,7 +57,7 @@ 65.12 /** 65.13 * Length of the array data. Not necessarily length of the wrapped array. 65.14 */ 65.15 - private long length; 65.16 + protected long length; 65.17 65.18 /** 65.19 * Method handle to throw an {@link UnwarrantedOptimismException} when getting an element 65.20 @@ -520,7 +519,7 @@ 65.21 * @param type new element type 65.22 * @return new array data 65.23 */ 65.24 - protected abstract ArrayData convert(Class<?> type); 65.25 + public abstract ArrayData convert(Class<?> type); 65.26 65.27 /** 65.28 * Push an array of items to the end of the array 65.29 @@ -537,7 +536,7 @@ 65.30 final Class<?> widest = widestType(items); 65.31 65.32 ArrayData newData = convert(widest); 65.33 - long pos = newData.length(); 65.34 + long pos = newData.length; 65.35 for (final Object item : items) { 65.36 newData = newData.ensure(pos); //avoid sparse array 65.37 newData.set((int)pos++, item, strict); 65.38 @@ -655,7 +654,7 @@ 65.39 * @param size current size 65.40 * @return next size to allocate for internal array 65.41 */ 65.42 - protected static int nextSize(final int size) { 65.43 + public static int nextSize(final int size) { 65.44 return alignUp(size + 1) * 2; 65.45 } 65.46 65.47 @@ -681,6 +680,18 @@ 65.48 } 65.49 } 65.50 65.51 + /** 65.52 + * Find a fast call if one exists 65.53 + * 65.54 + * @param clazz array data class 65.55 + * @param desc callsite descriptor 65.56 + * @param request link request 65.57 + * @return fast property getter if one is found 65.58 + */ 65.59 + public GuardedInvocation findFastCallMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { 65.60 + return null; 65.61 + } 65.62 + 65.63 /** 65.64 * Find a fast property getter if one exists 65.65 *
66.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java Wed Oct 01 12:22:12 2014 +0200 66.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java Thu Sep 25 15:53:47 2014 +0200 66.3 @@ -39,7 +39,7 @@ 66.4 protected ArrayData underlying; 66.5 66.6 ArrayFilter(final ArrayData underlying) { 66.7 - super(underlying.length()); 66.8 + super(underlying.length); 66.9 this.underlying = underlying; 66.10 } 66.11 66.12 @@ -70,13 +70,13 @@ 66.13 @Override 66.14 public void shiftLeft(final int by) { 66.15 underlying.shiftLeft(by); 66.16 - setLength(underlying.length()); 66.17 + setLength(underlying.length); 66.18 } 66.19 66.20 @Override 66.21 public ArrayData shiftRight(final int by) { 66.22 underlying = underlying.shiftRight(by); 66.23 - setLength(underlying.length()); 66.24 + setLength(underlying.length); 66.25 66.26 return this; 66.27 } 66.28 @@ -84,7 +84,7 @@ 66.29 @Override 66.30 public ArrayData ensure(final long safeIndex) { 66.31 underlying = underlying.ensure(safeIndex); 66.32 - setLength(underlying.length()); 66.33 + setLength(underlying.length); 66.34 66.35 return this; 66.36 } 66.37 @@ -92,7 +92,7 @@ 66.38 @Override 66.39 public ArrayData shrink(final long newLength) { 66.40 underlying = underlying.shrink(newLength); 66.41 - setLength(underlying.length()); 66.42 + setLength(underlying.length); 66.43 66.44 return this; 66.45 } 66.46 @@ -100,7 +100,7 @@ 66.47 @Override 66.48 public ArrayData set(final int index, final Object value, final boolean strict) { 66.49 underlying = underlying.set(index, value, strict); 66.50 - setLength(underlying.length()); 66.51 + setLength(underlying.length); 66.52 66.53 return this; 66.54 } 66.55 @@ -108,7 +108,7 @@ 66.56 @Override 66.57 public ArrayData set(final int index, final int value, final boolean strict) { 66.58 underlying = underlying.set(index, value, strict); 66.59 - setLength(underlying.length()); 66.60 + setLength(underlying.length); 66.61 66.62 return this; 66.63 } 66.64 @@ -116,7 +116,7 @@ 66.65 @Override 66.66 public ArrayData set(final int index, final long value, final boolean strict) { 66.67 underlying = underlying.set(index, value, strict); 66.68 - setLength(underlying.length()); 66.69 + setLength(underlying.length); 66.70 66.71 return this; 66.72 } 66.73 @@ -124,7 +124,7 @@ 66.74 @Override 66.75 public ArrayData set(final int index, final double value, final boolean strict) { 66.76 underlying = underlying.set(index, value, strict); 66.77 - setLength(underlying.length()); 66.78 + setLength(underlying.length); 66.79 66.80 return this; 66.81 } 66.82 @@ -189,28 +189,28 @@ 66.83 @Override 66.84 public ArrayData delete(final int index) { 66.85 underlying = underlying.delete(index); 66.86 - setLength(underlying.length()); 66.87 + setLength(underlying.length); 66.88 return this; 66.89 } 66.90 66.91 @Override 66.92 public ArrayData delete(final long from, final long to) { 66.93 underlying = underlying.delete(from, to); 66.94 - setLength(underlying.length()); 66.95 + setLength(underlying.length); 66.96 return this; 66.97 } 66.98 66.99 @Override 66.100 - protected ArrayData convert(final Class<?> type) { 66.101 + public ArrayData convert(final Class<?> type) { 66.102 underlying = underlying.convert(type); 66.103 - setLength(underlying.length()); 66.104 + setLength(underlying.length); 66.105 return this; 66.106 } 66.107 66.108 @Override 66.109 public Object pop() { 66.110 final Object value = underlying.pop(); 66.111 - setLength(underlying.length()); 66.112 + setLength(underlying.length); 66.113 66.114 return value; 66.115 }
67.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Wed Oct 01 12:22:12 2014 +0200 67.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Thu Sep 25 15:53:47 2014 +0200 67.3 @@ -30,7 +30,6 @@ 67.4 import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex; 67.5 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 67.6 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; 67.7 - 67.8 import java.lang.invoke.MethodHandle; 67.9 import java.lang.invoke.MethodHandles; 67.10 import java.lang.invoke.MethodType; 67.11 @@ -77,11 +76,11 @@ 67.12 * array without reallocating, or if we are overwriting an already 67.13 * allocated element 67.14 * 67.15 - * @param index 67.16 + * @param index index to check 67.17 * @return true if we don't need to do any array reallocation to fit an element at index 67.18 */ 67.19 public final boolean hasRoomFor(final int index) { 67.20 - return has(index) || (index == length() && ensure(index) == this); 67.21 + return has(index) || (index == length && ensure(index) == this); 67.22 } 67.23 67.24 /** 67.25 @@ -116,6 +115,12 @@ 67.26 } 67.27 67.28 /** 67.29 + * Returns the type used to store an element in this array 67.30 + * @return element type 67.31 + */ 67.32 + public abstract Class<?> getElementType(); 67.33 + 67.34 + /** 67.35 * Look up a continuous array element getter 67.36 * @param get getter, sometimes combined with a has check that throws CCE on failure for relink 67.37 * @param returnType return type 67.38 @@ -175,11 +180,6 @@ 67.39 return MH.asType(setHas, setHas.type().changeParameterType(2, elementType).changeParameterType(0, clazz)); 67.40 } 67.41 67.42 - @Override 67.43 - public GuardedInvocation findFastGetMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request, final String operator) { 67.44 - return null; 67.45 - } 67.46 - 67.47 /** Fast access guard - it is impractical for JIT performance reasons to use only CCE asType as guard :-(, also we need 67.48 the null case explicitly, which is the one that CCE doesn't handle */ 67.49 protected static final MethodHandle FAST_ACCESS_GUARD = 67.50 @@ -269,4 +269,72 @@ 67.51 67.52 return null; 67.53 } 67.54 + 67.55 + /** 67.56 + * Specialization - fast push implementation 67.57 + * @param arg argument 67.58 + * @return new array length 67.59 + */ 67.60 + public long fastPush(final int arg) { 67.61 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 67.62 + } 67.63 + 67.64 + /** 67.65 + * Specialization - fast push implementation 67.66 + * @param arg argument 67.67 + * @return new array length 67.68 + */ 67.69 + public long fastPush(final long arg) { 67.70 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 67.71 + } 67.72 + 67.73 + /** 67.74 + * Specialization - fast push implementation 67.75 + * @param arg argument 67.76 + * @return new array length 67.77 + */ 67.78 + public long fastPush(final double arg) { 67.79 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 67.80 + } 67.81 + 67.82 + /** 67.83 + * Specialization - fast push implementation 67.84 + * @param arg argument 67.85 + * @return new array length 67.86 + */ 67.87 + public long fastPush(final Object arg) { 67.88 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 67.89 + } 67.90 + 67.91 + /** 67.92 + * Specialization - fast pop implementation 67.93 + * @return element value 67.94 + */ 67.95 + public int fastPopInt() { 67.96 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 67.97 + } 67.98 + 67.99 + /** 67.100 + * Specialization - fast pop implementation 67.101 + * @return element value 67.102 + */ 67.103 + public long fastPopLong() { 67.104 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 67.105 + } 67.106 + 67.107 + /** 67.108 + * Specialization - fast pop implementation 67.109 + * @return element value 67.110 + */ 67.111 + public double fastPopDouble() { 67.112 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 67.113 + } 67.114 + 67.115 + /** 67.116 + * Specialization - fast pop implementation 67.117 + * @return element value 67.118 + */ 67.119 + public Object fastPopObject() { 67.120 + throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink 67.121 + } 67.122 }
68.1 --- a/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java Wed Oct 01 12:22:12 2014 +0200 68.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java Thu Sep 25 15:53:47 2014 +0200 68.3 @@ -26,7 +26,6 @@ 68.4 package jdk.nashorn.internal.runtime.arrays; 68.5 68.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 68.7 - 68.8 import java.lang.reflect.Array; 68.9 import jdk.nashorn.internal.runtime.BitVector; 68.10 68.11 @@ -40,7 +39,7 @@ 68.12 DeletedArrayFilter(final ArrayData underlying) { 68.13 super(underlying); 68.14 68.15 - this.deleted = new BitVector(underlying.length()); 68.16 + this.deleted = new BitVector(underlying.length); 68.17 } 68.18 68.19 @Override 68.20 @@ -80,25 +79,25 @@ 68.21 @Override 68.22 public void shiftLeft(final int by) { 68.23 super.shiftLeft(by); 68.24 - deleted.shiftLeft(by, length()); 68.25 + deleted.shiftLeft(by, length); 68.26 } 68.27 68.28 @Override 68.29 public ArrayData shiftRight(final int by) { 68.30 super.shiftRight(by); 68.31 - deleted.shiftRight(by, length()); 68.32 + deleted.shiftRight(by, length); 68.33 68.34 return this; 68.35 } 68.36 68.37 @Override 68.38 public ArrayData ensure(final long safeIndex) { 68.39 - if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) { 68.40 + if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) { 68.41 return new SparseArrayData(this, safeIndex + 1); 68.42 } 68.43 68.44 super.ensure(safeIndex); 68.45 - deleted.resize(length()); 68.46 + deleted.resize(length); 68.47 68.48 return this; 68.49 } 68.50 @@ -106,7 +105,7 @@ 68.51 @Override 68.52 public ArrayData shrink(final long newLength) { 68.53 super.shrink(newLength); 68.54 - deleted.resize(length()); 68.55 + deleted.resize(length); 68.56 68.57 return this; 68.58 } 68.59 @@ -147,7 +146,7 @@ 68.60 @Override 68.61 public ArrayData delete(final int index) { 68.62 final long longIndex = ArrayIndex.toLongIndex(index); 68.63 - assert longIndex >= 0 && longIndex < length(); 68.64 + assert longIndex >= 0 && longIndex < length; 68.65 deleted.set(longIndex); 68.66 underlying.setEmpty(index); 68.67 return this; 68.68 @@ -155,7 +154,7 @@ 68.69 68.70 @Override 68.71 public ArrayData delete(final long fromIndex, final long toIndex) { 68.72 - assert fromIndex >= 0 && fromIndex <= toIndex && toIndex < length(); 68.73 + assert fromIndex >= 0 && fromIndex <= toIndex && toIndex < length; 68.74 deleted.setRange(fromIndex, toIndex + 1); 68.75 underlying.setEmpty(fromIndex, toIndex); 68.76 return this; 68.77 @@ -163,7 +162,7 @@ 68.78 68.79 @Override 68.80 public Object pop() { 68.81 - final long index = length() - 1; 68.82 + final long index = length - 1; 68.83 68.84 if (super.has((int)index)) { 68.85 final boolean isDeleted = deleted.isSet(index); 68.86 @@ -180,7 +179,7 @@ 68.87 final ArrayData newArray = underlying.slice(from, to); 68.88 final DeletedArrayFilter newFilter = new DeletedArrayFilter(newArray); 68.89 newFilter.getDeleted().copy(deleted); 68.90 - newFilter.getDeleted().shiftLeft(from, newFilter.length()); 68.91 + newFilter.getDeleted().shiftLeft(from, newFilter.length); 68.92 68.93 return newFilter; 68.94 }
69.1 --- a/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java Wed Oct 01 12:22:12 2014 +0200 69.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java Thu Sep 25 15:53:47 2014 +0200 69.3 @@ -45,7 +45,7 @@ 69.4 if(hi < SparseArrayData.MAX_DENSE_LENGTH || underlying instanceof SparseArrayData) { 69.5 return underlying; 69.6 } 69.7 - return new SparseArrayData(underlying, underlying.length()); 69.8 + return new SparseArrayData(underlying, underlying.length); 69.9 } 69.10 69.11 private boolean isEmpty() { 69.12 @@ -93,7 +93,7 @@ 69.13 69.14 @Override 69.15 public ArrayData ensure(final long safeIndex) { 69.16 - if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) { 69.17 + if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) { 69.18 return new SparseArrayData(this, safeIndex + 1); 69.19 } 69.20 69.21 @@ -110,8 +110,9 @@ 69.22 @Override 69.23 public ArrayData shiftRight(final int by) { 69.24 super.shiftRight(by); 69.25 - lo = Math.min(length(), lo + by); 69.26 - hi = Math.min(length() - 1, hi + by); 69.27 + final long len = length; 69.28 + lo = Math.min(len, lo + by); 69.29 + hi = Math.min(len - 1, hi + by); 69.30 69.31 return isEmpty() ? getUnderlying() : this; 69.32 } 69.33 @@ -237,7 +238,7 @@ 69.34 69.35 @Override 69.36 public Object pop() { 69.37 - final int index = (int)(length() - 1); 69.38 + final int index = (int)length - 1; 69.39 if (super.has(index)) { 69.40 final boolean isDeleted = isDeleted(index); 69.41 final Object value = super.pop();
70.1 --- a/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Wed Oct 01 12:22:12 2014 +0200 70.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Thu Sep 25 15:53:47 2014 +0200 70.3 @@ -26,7 +26,6 @@ 70.4 package jdk.nashorn.internal.runtime.arrays; 70.5 70.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 70.7 - 70.8 import java.lang.invoke.MethodHandle; 70.9 import java.lang.invoke.MethodHandles; 70.10 import java.util.Arrays; 70.11 @@ -38,7 +37,7 @@ 70.12 * Implementation of {@link ArrayData} as soon as an int has been 70.13 * written to the array. This is the default data for new arrays 70.14 */ 70.15 -final class IntArrayData extends ContinuousArrayData { 70.16 +final class IntArrayData extends ContinuousArrayData implements IntElements { 70.17 /** 70.18 * The wrapped array 70.19 */ 70.20 @@ -64,9 +63,19 @@ 70.21 this.array = array; 70.22 } 70.23 70.24 + @Override 70.25 + public Class<?> getElementType() { 70.26 + return int.class; 70.27 + } 70.28 + 70.29 private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "getElem", int.class, int.class).methodHandle(); 70.30 private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "setElem", void.class, int.class, int.class).methodHandle(); 70.31 70.32 + @Override 70.33 + public Object[] asObjectArray() { 70.34 + return toObjectArray(); 70.35 + } 70.36 + 70.37 @SuppressWarnings("unused") 70.38 private int getElem(final int index) { 70.39 if (has(index)) { 70.40 @@ -96,23 +105,18 @@ 70.41 70.42 @Override 70.43 public ArrayData copy() { 70.44 - return new IntArrayData(array.clone(), (int) length()); 70.45 - } 70.46 - 70.47 - @Override 70.48 - public Object[] asObjectArray() { 70.49 - return toObjectArray(array, (int) length()); 70.50 + return new IntArrayData(array.clone(), (int)length); 70.51 } 70.52 70.53 @Override 70.54 public Object asArrayOfType(final Class<?> componentType) { 70.55 if (componentType == int.class) { 70.56 - return array.length == length() ? array.clone() : Arrays.copyOf(array, (int) length()); 70.57 + return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length); 70.58 } 70.59 return super.asArrayOfType(componentType); 70.60 } 70.61 70.62 - private static Object[] toObjectArray(final int[] array, final int length) { 70.63 + private Object[] toObjectArray() { 70.64 assert length <= array.length : "length exceeds internal array size"; 70.65 final Object[] oarray = new Object[array.length]; 70.66 70.67 @@ -123,7 +127,7 @@ 70.68 return oarray; 70.69 } 70.70 70.71 - private static double[] toDoubleArray(final int[] array, final int length) { 70.72 + private double[] toDoubleArray() { 70.73 assert length <= array.length : "length exceeds internal array size"; 70.74 final double[] darray = new double[array.length]; 70.75 70.76 @@ -134,7 +138,7 @@ 70.77 return darray; 70.78 } 70.79 70.80 - private static long[] toLongArray(final int[] array, final int length) { 70.81 + private long[] toLongArray() { 70.82 assert length <= array.length : "length exceeds internal array size"; 70.83 final long[] larray = new long[array.length]; 70.84 70.85 @@ -145,18 +149,30 @@ 70.86 return larray; 70.87 } 70.88 70.89 + private LongArrayData convertToLong() { 70.90 + return new LongArrayData(toLongArray(), (int)length); 70.91 + } 70.92 + 70.93 + private NumberArrayData convertToDouble() { 70.94 + return new NumberArrayData(toDoubleArray(), (int)length); 70.95 + } 70.96 + 70.97 + private ObjectArrayData convertToObject() { 70.98 + return new ObjectArrayData(toObjectArray(), (int)length); 70.99 + } 70.100 + 70.101 @Override 70.102 public ArrayData convert(final Class<?> type) { 70.103 if (type == Integer.class) { 70.104 return this; 70.105 } 70.106 - final int length = (int) length(); 70.107 if (type == Long.class) { 70.108 - return new LongArrayData(IntArrayData.toLongArray(array, length), length); 70.109 + return convertToLong(); 70.110 } else if (type == Double.class) { 70.111 - return new NumberArrayData(IntArrayData.toDoubleArray(array, length), length); 70.112 + return convertToDouble(); 70.113 } else { 70.114 - return new ObjectArrayData(IntArrayData.toObjectArray(array, length), length); 70.115 + assert type == null || (!Number.class.isAssignableFrom(type) && !type.isPrimitive()); 70.116 + return convertToObject(); 70.117 } 70.118 } 70.119 70.120 @@ -167,7 +183,7 @@ 70.121 70.122 @Override 70.123 public ArrayData shiftRight(final int by) { 70.124 - final ArrayData newData = ensure(by + length() - 1); 70.125 + final ArrayData newData = ensure(by + length - 1); 70.126 if (newData != this) { 70.127 newData.shiftRight(by); 70.128 return newData; 70.129 @@ -213,7 +229,7 @@ 70.130 @Override 70.131 public ArrayData set(final int index, final int value, final boolean strict) { 70.132 array[index] = value; 70.133 - setLength(Math.max(index + 1, length())); 70.134 + setLength(Math.max(index + 1, length)); 70.135 70.136 return this; 70.137 } 70.138 @@ -222,7 +238,7 @@ 70.139 public ArrayData set(final int index, final long value, final boolean strict) { 70.140 if (JSType.isRepresentableAsInt(value)) { 70.141 array[index] = JSType.toInt32(value); 70.142 - setLength(Math.max(index + 1, length())); 70.143 + setLength(Math.max(index + 1, length)); 70.144 return this; 70.145 } 70.146 70.147 @@ -233,7 +249,7 @@ 70.148 public ArrayData set(final int index, final double value, final boolean strict) { 70.149 if (JSType.isRepresentableAsInt(value)) { 70.150 array[index] = (int)(long)value; 70.151 - setLength(Math.max(index + 1, length())); 70.152 + setLength(Math.max(index + 1, length)); 70.153 return this; 70.154 } 70.155 70.156 @@ -282,7 +298,7 @@ 70.157 70.158 @Override 70.159 public boolean has(final int index) { 70.160 - return 0 <= index && index < length(); 70.161 + return 0 <= index && index < length; 70.162 } 70.163 70.164 @Override 70.165 @@ -297,11 +313,11 @@ 70.166 70.167 @Override 70.168 public Object pop() { 70.169 - if (length() == 0) { 70.170 + if (length == 0) { 70.171 return ScriptRuntime.UNDEFINED; 70.172 } 70.173 70.174 - final int newLength = (int) length() - 1; 70.175 + final int newLength = (int)length - 1; 70.176 final int elem = array[newLength]; 70.177 array[newLength] = 0; 70.178 setLength(newLength); 70.179 @@ -311,7 +327,7 @@ 70.180 70.181 @Override 70.182 public ArrayData slice(final long from, final long to) { 70.183 - final long start = from < 0 ? from + length() : from; 70.184 + final long start = from < 0 ? from + length : from; 70.185 final long newLength = to - start; 70.186 70.187 return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); 70.188 @@ -319,18 +335,18 @@ 70.189 70.190 @Override 70.191 public final ArrayData push(final boolean strict, final int item) { 70.192 - final long length = length(); 70.193 - final ArrayData newData = ensure(length); 70.194 + final long len = length; 70.195 + final ArrayData newData = ensure(len); 70.196 if (newData == this) { 70.197 - array[(int)length] = item; 70.198 + array[(int)len] = item; 70.199 return this; 70.200 } 70.201 - return newData.set((int)length, item, strict); 70.202 + return newData.set((int)len, item, strict); 70.203 } 70.204 70.205 @Override 70.206 public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 70.207 - final long oldLength = length(); 70.208 + final long oldLength = length; 70.209 final long newLength = oldLength - removed + added; 70.210 if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 70.211 throw new UnsupportedOperationException(); 70.212 @@ -355,4 +371,41 @@ 70.213 70.214 return returnValue; 70.215 } 70.216 + 70.217 + @Override 70.218 + public long fastPush(final int arg) { 70.219 + final int len = (int)length; 70.220 + if (len == array.length) { 70.221 + array = Arrays.copyOf(array, nextSize(len)); 70.222 + } 70.223 + array[len] = arg; 70.224 + return ++length; 70.225 + } 70.226 + 70.227 + //length must not be zero 70.228 + @Override 70.229 + public int fastPopInt() { 70.230 + if (length == 0) { 70.231 + throw new ClassCastException(); //relink 70.232 + } 70.233 + final int newLength = (int)--length; 70.234 + final int elem = array[newLength]; 70.235 + array[newLength] = 0; 70.236 + return elem; 70.237 + } 70.238 + 70.239 + @Override 70.240 + public long fastPopLong() { 70.241 + return fastPopInt(); 70.242 + } 70.243 + 70.244 + @Override 70.245 + public double fastPopDouble() { 70.246 + return fastPopInt(); 70.247 + } 70.248 + 70.249 + @Override 70.250 + public Object fastPopObject() { 70.251 + return fastPopInt(); 70.252 + } 70.253 }
71.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 71.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/IntElements.java Thu Sep 25 15:53:47 2014 +0200 71.3 @@ -0,0 +1,34 @@ 71.4 +/* 71.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 71.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 71.7 + * 71.8 + * This code is free software; you can redistribute it and/or modify it 71.9 + * under the terms of the GNU General Public License version 2 only, as 71.10 + * published by the Free Software Foundation. Oracle designates this 71.11 + * particular file as subject to the "Classpath" exception as provided 71.12 + * by Oracle in the LICENSE file that accompanied this code. 71.13 + * 71.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 71.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 71.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 71.17 + * version 2 for more details (a copy is included in the LICENSE file that 71.18 + * accompanied this code). 71.19 + * 71.20 + * You should have received a copy of the GNU General Public License version 71.21 + * 2 along with this work; if not, write to the Free Software Foundation, 71.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 71.23 + * 71.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 71.25 + * or visit www.oracle.com if you need additional information or have any 71.26 + * questions. 71.27 + */ 71.28 +package jdk.nashorn.internal.runtime.arrays; 71.29 + 71.30 +/** 71.31 + * Marker interface for any ContinuousArray with int elements 71.32 + * Used for type checks that throw ClassCastExceptions and force relinks 71.33 + * for fast NativeArray specializations of builtin methods 71.34 + */ 71.35 +public interface IntElements extends IntOrLongElements { 71.36 + //empty 71.37 +}
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 72.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/IntOrLongElements.java Thu Sep 25 15:53:47 2014 +0200 72.3 @@ -0,0 +1,34 @@ 72.4 +/* 72.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 72.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 72.7 + * 72.8 + * This code is free software; you can redistribute it and/or modify it 72.9 + * under the terms of the GNU General Public License version 2 only, as 72.10 + * published by the Free Software Foundation. Oracle designates this 72.11 + * particular file as subject to the "Classpath" exception as provided 72.12 + * by Oracle in the LICENSE file that accompanied this code. 72.13 + * 72.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 72.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 72.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 72.17 + * version 2 for more details (a copy is included in the LICENSE file that 72.18 + * accompanied this code). 72.19 + * 72.20 + * You should have received a copy of the GNU General Public License version 72.21 + * 2 along with this work; if not, write to the Free Software Foundation, 72.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 72.23 + * 72.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 72.25 + * or visit www.oracle.com if you need additional information or have any 72.26 + * questions. 72.27 + */ 72.28 +package jdk.nashorn.internal.runtime.arrays; 72.29 + 72.30 +/** 72.31 + * Marker interface for any ContinuousArray with int or long elements 72.32 + * Used for type checks that throw ClassCastExceptions and force relinks 72.33 + * for fast NativeArray specializations of builtin methods 72.34 + */ 72.35 +public interface IntOrLongElements extends NumericElements { 72.36 + //empty 72.37 +}
73.1 --- a/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Wed Oct 01 12:22:12 2014 +0200 73.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Thu Sep 25 15:53:47 2014 +0200 73.3 @@ -27,7 +27,6 @@ 73.4 73.5 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 73.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 73.7 - 73.8 import java.lang.invoke.MethodHandle; 73.9 import java.lang.invoke.MethodHandles; 73.10 import java.util.Arrays; 73.11 @@ -39,7 +38,7 @@ 73.12 * Implementation of {@link ArrayData} as soon as a long has been 73.13 * written to the array 73.14 */ 73.15 -final class LongArrayData extends ContinuousArrayData { 73.16 +final class LongArrayData extends ContinuousArrayData implements IntOrLongElements { 73.17 /** 73.18 * The wrapped array 73.19 */ 73.20 @@ -57,13 +56,18 @@ 73.21 } 73.22 73.23 @Override 73.24 + public Class<?> getElementType() { 73.25 + return long.class; 73.26 + } 73.27 + 73.28 + @Override 73.29 public ArrayData copy() { 73.30 - return new LongArrayData(array.clone(), (int)length()); 73.31 + return new LongArrayData(array.clone(), (int)length); 73.32 } 73.33 73.34 @Override 73.35 public Object[] asObjectArray() { 73.36 - return toObjectArray(array, (int)length()); 73.37 + return toObjectArray(array, (int)length); 73.38 } 73.39 73.40 private static Object[] toObjectArray(final long[] array, final int length) { 73.41 @@ -80,7 +84,7 @@ 73.42 @Override 73.43 public Object asArrayOfType(final Class<?> componentType) { 73.44 if (componentType == long.class) { 73.45 - return array.length == length() ? array.clone() : Arrays.copyOf(array, (int)length()); 73.46 + return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length); 73.47 } 73.48 return super.asArrayOfType(componentType); 73.49 } 73.50 @@ -101,11 +105,11 @@ 73.51 if (type == Integer.class || type == Long.class) { 73.52 return this; 73.53 } 73.54 - final int length = (int) length(); 73.55 + final int len = (int)length; 73.56 if (type == Double.class) { 73.57 - return new NumberArrayData(LongArrayData.toDoubleArray(array, length), length); 73.58 + return new NumberArrayData(LongArrayData.toDoubleArray(array, len), len); 73.59 } 73.60 - return new ObjectArrayData(LongArrayData.toObjectArray(array, length), length); 73.61 + return new ObjectArrayData(LongArrayData.toObjectArray(array, len), len); 73.62 } 73.63 73.64 @Override 73.65 @@ -115,7 +119,7 @@ 73.66 73.67 @Override 73.68 public ArrayData shiftRight(final int by) { 73.69 - final ArrayData newData = ensure(by + length() - 1); 73.70 + final ArrayData newData = ensure(by + length - 1); 73.71 if (newData != this) { 73.72 newData.shiftRight(by); 73.73 return newData; 73.74 @@ -161,14 +165,14 @@ 73.75 @Override 73.76 public ArrayData set(final int index, final int value, final boolean strict) { 73.77 array[index] = value; 73.78 - setLength(Math.max(index + 1, length())); 73.79 + setLength(Math.max(index + 1, length)); 73.80 return this; 73.81 } 73.82 73.83 @Override 73.84 public ArrayData set(final int index, final long value, final boolean strict) { 73.85 array[index] = value; 73.86 - setLength(Math.max(index + 1, length())); 73.87 + setLength(Math.max(index + 1, length)); 73.88 return this; 73.89 } 73.90 73.91 @@ -176,7 +180,7 @@ 73.92 public ArrayData set(final int index, final double value, final boolean strict) { 73.93 if (JSType.isRepresentableAsLong(value)) { 73.94 array[index] = (long)value; 73.95 - setLength(Math.max(index + 1, length())); 73.96 + setLength(Math.max(index + 1, length)); 73.97 return this; 73.98 } 73.99 return convert(Double.class).set(index, value, strict); 73.100 @@ -252,7 +256,7 @@ 73.101 73.102 @Override 73.103 public boolean has(final int index) { 73.104 - return 0 <= index && index < length(); 73.105 + return 0 <= index && index < length; 73.106 } 73.107 73.108 @Override 73.109 @@ -267,11 +271,11 @@ 73.110 73.111 @Override 73.112 public Object pop() { 73.113 - if (length() == 0) { 73.114 + if (length == 0) { 73.115 return ScriptRuntime.UNDEFINED; 73.116 } 73.117 73.118 - final int newLength = (int) (length() - 1); 73.119 + final int newLength = (int)length - 1; 73.120 final long elem = array[newLength]; 73.121 array[newLength] = 0; 73.122 setLength(newLength); 73.123 @@ -281,25 +285,25 @@ 73.124 73.125 @Override 73.126 public ArrayData slice(final long from, final long to) { 73.127 - final long start = from < 0 ? from + length() : from; 73.128 + final long start = from < 0 ? from + length : from; 73.129 final long newLength = to - start; 73.130 return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); 73.131 } 73.132 73.133 @Override 73.134 public final ArrayData push(final boolean strict, final long item) { 73.135 - final long length = length(); 73.136 - final ArrayData newData = ensure(length); 73.137 + final long len = length; 73.138 + final ArrayData newData = ensure(len); 73.139 if (newData == this) { 73.140 - array[(int)length] = item; 73.141 + array[(int)len] = item; 73.142 return this; 73.143 } 73.144 - return newData.set((int)length, item, strict); 73.145 + return newData.set((int)len, item, strict); 73.146 } 73.147 73.148 @Override 73.149 public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 73.150 - final long oldLength = length(); 73.151 + final long oldLength = length; 73.152 final long newLength = oldLength - removed + added; 73.153 if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 73.154 throw new UnsupportedOperationException(); 73.155 @@ -324,4 +328,40 @@ 73.156 73.157 return returnValue; 73.158 } 73.159 + 73.160 + @Override 73.161 + public long fastPush(final int arg) { 73.162 + return fastPush((long)arg); 73.163 + } 73.164 + 73.165 + @Override 73.166 + public long fastPush(final long arg) { 73.167 + final int len = (int)length; 73.168 + if (len == array.length) { 73.169 + array = Arrays.copyOf(array, nextSize(len)); 73.170 + } 73.171 + array[len] = arg; 73.172 + return ++length; 73.173 + } 73.174 + 73.175 + @Override 73.176 + public long fastPopLong() { 73.177 + if (length == 0) { 73.178 + throw new ClassCastException(); 73.179 + } 73.180 + final int newLength = (int)--length; 73.181 + final long elem = array[newLength]; 73.182 + array[newLength] = 0; 73.183 + return elem; 73.184 + } 73.185 + 73.186 + @Override 73.187 + public double fastPopDouble() { 73.188 + return fastPopLong(); 73.189 + } 73.190 + 73.191 + @Override 73.192 + public Object fastPopObject() { 73.193 + return fastPopLong(); 73.194 + } 73.195 }
74.1 --- a/src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java Wed Oct 01 12:22:12 2014 +0200 74.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java Thu Sep 25 15:53:47 2014 +0200 74.3 @@ -58,19 +58,19 @@ 74.4 74.5 @Override 74.6 public ArrayData convert(final Class<?> type) { 74.7 - final long length = length(); 74.8 + final long len = length; 74.9 final ArrayData arrayData; 74.10 if (type == Long.class) { 74.11 - arrayData = new LongArrayData(new long[ArrayData.nextSize((int)length)], (int)length); 74.12 + arrayData = new LongArrayData(new long[ArrayData.nextSize((int)len)], (int)len); 74.13 } else if (type == Double.class) { 74.14 - arrayData = new NumberArrayData(new double[ArrayData.nextSize((int)length)], (int)length); 74.15 + arrayData = new NumberArrayData(new double[ArrayData.nextSize((int)len)], (int)len); 74.16 } else if (type == Integer.class) { 74.17 - arrayData = new IntArrayData(new int[ArrayData.nextSize((int)length)], (int)length); 74.18 + arrayData = new IntArrayData(new int[ArrayData.nextSize((int)len)], (int)len); 74.19 } else { 74.20 assert !type.isPrimitive(); 74.21 - arrayData = new ObjectArrayData(new Object[ArrayData.nextSize((int)length)], (int)length); 74.22 + arrayData = new ObjectArrayData(new Object[ArrayData.nextSize((int)len)], (int)len); 74.23 } 74.24 - return length == 0 ? arrayData : new DeletedRangeArrayFilter(arrayData, 0, length - 1); 74.25 + return length == 0 ? arrayData : new DeletedRangeArrayFilter(arrayData, 0, len - 1); 74.26 } 74.27 74.28 @Override 74.29 @@ -90,11 +90,11 @@ 74.30 } 74.31 74.32 // Don't trample the shared EMPTY_ARRAY. 74.33 - if (length() == 0) { 74.34 - return new NoTypeArrayData(Math.max(safeIndex + 1, length())); 74.35 + if (length == 0) { 74.36 + return new NoTypeArrayData(Math.max(safeIndex + 1, length)); 74.37 } 74.38 74.39 - setLength(Math.max(safeIndex + 1, length())); 74.40 + setLength(Math.max(safeIndex + 1, length)); 74.41 return this; 74.42 } 74.43
75.1 --- a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Wed Oct 01 12:22:12 2014 +0200 75.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Thu Sep 25 15:53:47 2014 +0200 75.3 @@ -28,7 +28,6 @@ 75.4 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 75.5 import static jdk.nashorn.internal.lookup.Lookup.MH; 75.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 75.7 - 75.8 import java.lang.invoke.MethodHandle; 75.9 import java.lang.invoke.MethodHandles; 75.10 import java.util.Arrays; 75.11 @@ -38,7 +37,7 @@ 75.12 * Implementation of {@link ArrayData} as soon as a double has been 75.13 * written to the array 75.14 */ 75.15 -final class NumberArrayData extends ContinuousArrayData { 75.16 +final class NumberArrayData extends ContinuousArrayData implements NumericElements { 75.17 /** 75.18 * The wrapped array 75.19 */ 75.20 @@ -56,13 +55,18 @@ 75.21 } 75.22 75.23 @Override 75.24 + public Class<?> getElementType() { 75.25 + return double.class; 75.26 + } 75.27 + 75.28 + @Override 75.29 public ArrayData copy() { 75.30 - return new NumberArrayData(array.clone(), (int) length()); 75.31 + return new NumberArrayData(array.clone(), (int)length); 75.32 } 75.33 75.34 @Override 75.35 public Object[] asObjectArray() { 75.36 - return toObjectArray(array, (int) length()); 75.37 + return toObjectArray(array, (int)length); 75.38 } 75.39 75.40 private static Object[] toObjectArray(final double[] array, final int length) { 75.41 @@ -78,7 +82,7 @@ 75.42 @Override 75.43 public Object asArrayOfType(final Class<?> componentType) { 75.44 if(componentType == double.class) { 75.45 - return array.length == length() ? array.clone() : Arrays.copyOf(array, (int) length()); 75.46 + return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length); 75.47 } 75.48 return super.asArrayOfType(componentType); 75.49 } 75.50 @@ -86,8 +90,8 @@ 75.51 @Override 75.52 public ArrayData convert(final Class<?> type) { 75.53 if (type != Double.class && type != Integer.class && type != Long.class) { 75.54 - final int length = (int) length(); 75.55 - return new ObjectArrayData(NumberArrayData.toObjectArray(array, length), length); 75.56 + final int len = (int)length; 75.57 + return new ObjectArrayData(NumberArrayData.toObjectArray(array, len), len); 75.58 } 75.59 return this; 75.60 } 75.61 @@ -99,7 +103,7 @@ 75.62 75.63 @Override 75.64 public ArrayData shiftRight(final int by) { 75.65 - final ArrayData newData = ensure(by + length() - 1); 75.66 + final ArrayData newData = ensure(by + length - 1); 75.67 if (newData != this) { 75.68 newData.shiftRight(by); 75.69 return newData; 75.70 @@ -144,21 +148,21 @@ 75.71 @Override 75.72 public ArrayData set(final int index, final int value, final boolean strict) { 75.73 array[index] = value; 75.74 - setLength(Math.max(index + 1, length())); 75.75 + setLength(Math.max(index + 1, length)); 75.76 return this; 75.77 } 75.78 75.79 @Override 75.80 public ArrayData set(final int index, final long value, final boolean strict) { 75.81 array[index] = value; 75.82 - setLength(Math.max(index + 1, length())); 75.83 + setLength(Math.max(index + 1, length)); 75.84 return this; 75.85 } 75.86 75.87 @Override 75.88 public ArrayData set(final int index, final double value, final boolean strict) { 75.89 array[index] = value; 75.90 - setLength(Math.max(index + 1, length())); 75.91 + setLength(Math.max(index + 1, length)); 75.92 return this; 75.93 } 75.94 75.95 @@ -227,7 +231,7 @@ 75.96 75.97 @Override 75.98 public boolean has(final int index) { 75.99 - return 0 <= index && index < length(); 75.100 + return 0 <= index && index < length; 75.101 } 75.102 75.103 @Override 75.104 @@ -242,11 +246,11 @@ 75.105 75.106 @Override 75.107 public Object pop() { 75.108 - if (length() == 0) { 75.109 + if (length == 0) { 75.110 return UNDEFINED; 75.111 } 75.112 75.113 - final int newLength = (int) (length() - 1); 75.114 + final int newLength = (int)length - 1; 75.115 final double elem = array[newLength]; 75.116 array[newLength] = 0; 75.117 setLength(newLength); 75.118 @@ -255,25 +259,25 @@ 75.119 75.120 @Override 75.121 public ArrayData slice(final long from, final long to) { 75.122 - final long start = from < 0 ? from + length() : from; 75.123 + final long start = from < 0 ? from + length : from; 75.124 final long newLength = to - start; 75.125 return new NumberArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); 75.126 } 75.127 75.128 @Override 75.129 public final ArrayData push(final boolean strict, final double item) { 75.130 - final long length = length(); 75.131 - final ArrayData newData = ensure(length); 75.132 + final long len = length; 75.133 + final ArrayData newData = ensure(len); 75.134 if (newData == this) { 75.135 - array[(int)length] = item; 75.136 + array[(int)len] = item; 75.137 return this; 75.138 } 75.139 - return newData.set((int)length, item, strict); 75.140 + return newData.set((int)len, item, strict); 75.141 } 75.142 75.143 @Override 75.144 public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 75.145 - final long oldLength = length(); 75.146 + final long oldLength = length; 75.147 final long newLength = oldLength - removed + added; 75.148 if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 75.149 throw new UnsupportedOperationException(); 75.150 @@ -298,4 +302,41 @@ 75.151 75.152 return returnValue; 75.153 } 75.154 + 75.155 + @Override 75.156 + public long fastPush(final int arg) { 75.157 + return fastPush((double)arg); 75.158 + } 75.159 + 75.160 + @Override 75.161 + public long fastPush(final long arg) { 75.162 + return fastPush((double)arg); 75.163 + } 75.164 + 75.165 + @Override 75.166 + public long fastPush(final double arg) { 75.167 + final int len = (int)length; 75.168 + if (len == array.length) { 75.169 + //note that fastpush never creates spares arrays, there is nothing to gain by that - it will just use even more memory 75.170 + array = Arrays.copyOf(array, nextSize(len)); 75.171 + } 75.172 + array[len] = arg; 75.173 + return ++length; 75.174 + } 75.175 + 75.176 + @Override 75.177 + public double fastPopDouble() { 75.178 + if (length == 0) { 75.179 + throw new ClassCastException(); 75.180 + } 75.181 + final int newLength = (int)--length; 75.182 + final double elem = array[newLength]; 75.183 + array[newLength] = 0; 75.184 + return elem; 75.185 + } 75.186 + 75.187 + @Override 75.188 + public Object fastPopObject() { 75.189 + return fastPopDouble(); 75.190 + } 75.191 }
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 76.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/NumericElements.java Thu Sep 25 15:53:47 2014 +0200 76.3 @@ -0,0 +1,35 @@ 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 +package jdk.nashorn.internal.runtime.arrays; 76.29 + 76.30 +/** 76.31 + * Marker interface for any ContinuousArray with numeric elements 76.32 + * (int, long or double) 76.33 + * Used for type checks that throw ClassCastExceptions and force relinks 76.34 + * for fast NativeArray specializations of builtin methods 76.35 + */ 76.36 +public interface NumericElements { 76.37 + //empty 76.38 +}
77.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Wed Oct 01 12:22:12 2014 +0200 77.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Thu Sep 25 15:53:47 2014 +0200 77.3 @@ -26,7 +26,6 @@ 77.4 package jdk.nashorn.internal.runtime.arrays; 77.5 77.6 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; 77.7 - 77.8 import java.lang.invoke.MethodHandle; 77.9 import java.lang.invoke.MethodHandles; 77.10 import java.util.Arrays; 77.11 @@ -57,20 +56,25 @@ 77.12 } 77.13 77.14 @Override 77.15 + public Class<?> getElementType() { 77.16 + return Object.class; 77.17 + } 77.18 + 77.19 + @Override 77.20 public ArrayData copy() { 77.21 - return new ObjectArrayData(array.clone(), (int) length()); 77.22 + return new ObjectArrayData(array.clone(), (int)length); 77.23 } 77.24 77.25 @Override 77.26 public Object[] asObjectArray() { 77.27 - return array.length == length() ? array.clone() : asObjectArrayCopy(); 77.28 + return array.length == length ? array.clone() : asObjectArrayCopy(); 77.29 } 77.30 77.31 private Object[] asObjectArrayCopy() { 77.32 - final long l = length(); 77.33 - assert l <= Integer.MAX_VALUE; 77.34 - final Object[] copy = new Object[(int)l]; 77.35 - System.arraycopy(array, 0, copy, 0, (int)l); 77.36 + final long len = length; 77.37 + assert len <= Integer.MAX_VALUE; 77.38 + final Object[] copy = new Object[(int)len]; 77.39 + System.arraycopy(array, 0, copy, 0, (int)len); 77.40 return copy; 77.41 } 77.42 77.43 @@ -86,7 +90,7 @@ 77.44 77.45 @Override 77.46 public ArrayData shiftRight(final int by) { 77.47 - final ArrayData newData = ensure(by + length() - 1); 77.48 + final ArrayData newData = ensure(by + length - 1); 77.49 if (newData != this) { 77.50 newData.shiftRight(by); 77.51 return newData; 77.52 @@ -118,28 +122,28 @@ 77.53 @Override 77.54 public ArrayData set(final int index, final Object value, final boolean strict) { 77.55 array[index] = value; 77.56 - setLength(Math.max(index + 1, length())); 77.57 + setLength(Math.max(index + 1, length)); 77.58 return this; 77.59 } 77.60 77.61 @Override 77.62 public ArrayData set(final int index, final int value, final boolean strict) { 77.63 array[index] = value; 77.64 - setLength(Math.max(index + 1, length())); 77.65 + setLength(Math.max(index + 1, length)); 77.66 return this; 77.67 } 77.68 77.69 @Override 77.70 public ArrayData set(final int index, final long value, final boolean strict) { 77.71 array[index] = value; 77.72 - setLength(Math.max(index + 1, length())); 77.73 + setLength(Math.max(index + 1, length)); 77.74 return this; 77.75 } 77.76 77.77 @Override 77.78 public ArrayData set(final int index, final double value, final boolean strict) { 77.79 array[index] = value; 77.80 - setLength(Math.max(index + 1, length())); 77.81 + setLength(Math.max(index + 1, length)); 77.82 return this; 77.83 } 77.84 77.85 @@ -216,7 +220,7 @@ 77.86 77.87 @Override 77.88 public boolean has(final int index) { 77.89 - return 0 <= index && index < length(); 77.90 + return 0 <= index && index < length; 77.91 } 77.92 77.93 @Override 77.94 @@ -232,12 +236,48 @@ 77.95 } 77.96 77.97 @Override 77.98 + public long fastPush(final int arg) { 77.99 + return fastPush((Object)arg); 77.100 + } 77.101 + 77.102 + @Override 77.103 + public long fastPush(final long arg) { 77.104 + return fastPush((Object)arg); 77.105 + } 77.106 + 77.107 + @Override 77.108 + public long fastPush(final double arg) { 77.109 + return fastPush((Object)arg); 77.110 + } 77.111 + 77.112 + @Override 77.113 + public long fastPush(final Object arg) { 77.114 + final int len = (int)length; 77.115 + if (len == array.length) { 77.116 + array = Arrays.copyOf(array, nextSize(len)); 77.117 + } 77.118 + array[len] = arg; 77.119 + return ++length; 77.120 + } 77.121 + 77.122 + @Override 77.123 + public Object fastPopObject() { 77.124 + if (length == 0) { 77.125 + return ScriptRuntime.UNDEFINED; 77.126 + } 77.127 + final int newLength = (int)--length; 77.128 + final Object elem = array[newLength]; 77.129 + array[newLength] = ScriptRuntime.EMPTY; 77.130 + return elem; 77.131 + } 77.132 + 77.133 + @Override 77.134 public Object pop() { 77.135 - if (length() == 0) { 77.136 + if (length == 0) { 77.137 return ScriptRuntime.UNDEFINED; 77.138 } 77.139 77.140 - final int newLength = (int) (length() - 1); 77.141 + final int newLength = (int)length - 1; 77.142 final Object elem = array[newLength]; 77.143 setEmpty(newLength); 77.144 setLength(newLength); 77.145 @@ -246,25 +286,25 @@ 77.146 77.147 @Override 77.148 public ArrayData slice(final long from, final long to) { 77.149 - final long start = from < 0 ? from + length() : from; 77.150 + final long start = from < 0 ? from + length : from; 77.151 final long newLength = to - start; 77.152 return new ObjectArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); 77.153 } 77.154 77.155 @Override 77.156 public ArrayData push(final boolean strict, final Object item) { 77.157 - final long length = length(); 77.158 - final ArrayData newData = ensure(length); 77.159 + final long len = length; 77.160 + final ArrayData newData = ensure(len); 77.161 if (newData == this) { 77.162 - array[(int)length] = item; 77.163 + array[(int)len] = item; 77.164 return this; 77.165 } 77.166 - return newData.set((int)length, item, strict); 77.167 + return newData.set((int)len, item, strict); 77.168 } 77.169 77.170 @Override 77.171 public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { 77.172 - final long oldLength = length(); 77.173 + final long oldLength = length; 77.174 final long newLength = oldLength - removed + added; 77.175 if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { 77.176 throw new UnsupportedOperationException();
78.1 --- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Wed Oct 01 12:22:12 2014 +0200 78.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Thu Sep 25 15:53:47 2014 +0200 78.3 @@ -53,28 +53,28 @@ 78.4 78.5 SparseArrayData(final ArrayData underlying, final long length, final TreeMap<Long, Object> sparseMap) { 78.6 super(length); 78.7 - assert underlying.length() <= length; 78.8 + assert underlying.length <= length; 78.9 this.underlying = underlying; 78.10 - this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length()); 78.11 + this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length); 78.12 this.sparseMap = sparseMap; 78.13 } 78.14 78.15 @Override 78.16 public ArrayData copy() { 78.17 - return new SparseArrayData(underlying.copy(), length(), new TreeMap<>(sparseMap)); 78.18 + return new SparseArrayData(underlying.copy(), length, new TreeMap<>(sparseMap)); 78.19 } 78.20 78.21 @Override 78.22 public Object[] asObjectArray() { 78.23 - final int length = (int) Math.min(length(), Integer.MAX_VALUE); 78.24 - final int underlyingLength = (int) Math.min(length, underlying.length()); 78.25 - final Object[] objArray = new Object[length]; 78.26 + final int len = (int)Math.min(length, Integer.MAX_VALUE); 78.27 + final int underlyingLength = (int)Math.min(len, underlying.length); 78.28 + final Object[] objArray = new Object[len]; 78.29 78.30 for (int i = 0; i < underlyingLength; i++) { 78.31 objArray[i] = underlying.getObject(i); 78.32 } 78.33 78.34 - Arrays.fill(objArray, underlyingLength, length, ScriptRuntime.UNDEFINED); 78.35 + Arrays.fill(objArray, underlyingLength, len, ScriptRuntime.UNDEFINED); 78.36 78.37 for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) { 78.38 final long key = entry.getKey(); 78.39 @@ -104,14 +104,14 @@ 78.40 } 78.41 78.42 sparseMap = newSparseMap; 78.43 - setLength(Math.max(length() - by, 0)); 78.44 + setLength(Math.max(length - by, 0)); 78.45 } 78.46 78.47 @Override 78.48 public ArrayData shiftRight(final int by) { 78.49 final TreeMap<Long, Object> newSparseMap = new TreeMap<>(); 78.50 - if (underlying.length() + by > maxDenseLength) { 78.51 - for (long i = maxDenseLength - by; i < underlying.length(); i++) { 78.52 + if (underlying.length + by > maxDenseLength) { 78.53 + for (long i = maxDenseLength - by; i < underlying.length; i++) { 78.54 if (underlying.has((int) i)) { 78.55 newSparseMap.put(Long.valueOf(i + by), underlying.getObject((int) i)); 78.56 } 78.57 @@ -127,23 +127,23 @@ 78.58 } 78.59 78.60 sparseMap = newSparseMap; 78.61 - setLength(length() + by); 78.62 + setLength(length + by); 78.63 78.64 return this; 78.65 } 78.66 78.67 @Override 78.68 public ArrayData ensure(final long safeIndex) { 78.69 - if (safeIndex < maxDenseLength && underlying.length() <= safeIndex) { 78.70 + if (safeIndex < maxDenseLength && underlying.length <= safeIndex) { 78.71 underlying = underlying.ensure(safeIndex); 78.72 } 78.73 - setLength(Math.max(safeIndex + 1, length())); 78.74 + setLength(Math.max(safeIndex + 1, length)); 78.75 return this; 78.76 } 78.77 78.78 @Override 78.79 public ArrayData shrink(final long newLength) { 78.80 - if (newLength < underlying.length()) { 78.81 + if (newLength < underlying.length) { 78.82 underlying = underlying.shrink(newLength); 78.83 underlying.setLength(newLength); 78.84 sparseMap.clear(); 78.85 @@ -160,11 +160,11 @@ 78.86 if (index >= 0 && index < maxDenseLength) { 78.87 ensure(index); 78.88 underlying = underlying.set(index, value, strict); 78.89 - setLength(Math.max(underlying.length(), length())); 78.90 + setLength(Math.max(underlying.length, length)); 78.91 } else { 78.92 final Long longIndex = indexToKey(index); 78.93 sparseMap.put(longIndex, value); 78.94 - setLength(Math.max(longIndex + 1, length())); 78.95 + setLength(Math.max(longIndex + 1, length)); 78.96 } 78.97 78.98 return this; 78.99 @@ -175,11 +175,11 @@ 78.100 if (index >= 0 && index < maxDenseLength) { 78.101 ensure(index); 78.102 underlying = underlying.set(index, value, strict); 78.103 - setLength(Math.max(underlying.length(), length())); 78.104 + setLength(Math.max(underlying.length, length)); 78.105 } else { 78.106 final Long longIndex = indexToKey(index); 78.107 sparseMap.put(longIndex, value); 78.108 - setLength(Math.max(longIndex + 1, length())); 78.109 + setLength(Math.max(longIndex + 1, length)); 78.110 } 78.111 return this; 78.112 } 78.113 @@ -189,11 +189,11 @@ 78.114 if (index >= 0 && index < maxDenseLength) { 78.115 ensure(index); 78.116 underlying = underlying.set(index, value, strict); 78.117 - setLength(Math.max(underlying.length(), length())); 78.118 + setLength(Math.max(underlying.length, length)); 78.119 } else { 78.120 final Long longIndex = indexToKey(index); 78.121 sparseMap.put(longIndex, value); 78.122 - setLength(Math.max(longIndex + 1, length())); 78.123 + setLength(Math.max(longIndex + 1, length)); 78.124 } 78.125 return this; 78.126 } 78.127 @@ -203,11 +203,11 @@ 78.128 if (index >= 0 && index < maxDenseLength) { 78.129 ensure(index); 78.130 underlying = underlying.set(index, value, strict); 78.131 - setLength(Math.max(underlying.length(), length())); 78.132 + setLength(Math.max(underlying.length, length)); 78.133 } else { 78.134 final Long longIndex = indexToKey(index); 78.135 sparseMap.put(longIndex, value); 78.136 - setLength(Math.max(longIndex + 1, length())); 78.137 + setLength(Math.max(longIndex + 1, length)); 78.138 } 78.139 return this; 78.140 } 78.141 @@ -294,7 +294,7 @@ 78.142 @Override 78.143 public boolean has(final int index) { 78.144 if (index >= 0 && index < maxDenseLength) { 78.145 - return index < underlying.length() && underlying.has(index); 78.146 + return index < underlying.length && underlying.has(index); 78.147 } 78.148 78.149 return sparseMap.containsKey(indexToKey(index)); 78.150 @@ -303,7 +303,7 @@ 78.151 @Override 78.152 public ArrayData delete(final int index) { 78.153 if (index >= 0 && index < maxDenseLength) { 78.154 - if (index < underlying.length()) { 78.155 + if (index < underlying.length) { 78.156 underlying = underlying.delete(index); 78.157 } 78.158 } else { 78.159 @@ -315,8 +315,8 @@ 78.160 78.161 @Override 78.162 public ArrayData delete(final long fromIndex, final long toIndex) { 78.163 - if (fromIndex < maxDenseLength && fromIndex < underlying.length()) { 78.164 - underlying = underlying.delete(fromIndex, Math.min(toIndex, underlying.length() - 1)); 78.165 + if (fromIndex < maxDenseLength && fromIndex < underlying.length) { 78.166 + underlying = underlying.delete(fromIndex, Math.min(toIndex, underlying.length - 1)); 78.167 } 78.168 if (toIndex >= maxDenseLength) { 78.169 sparseMap.subMap(fromIndex, true, toIndex, true).clear(); 78.170 @@ -329,37 +329,37 @@ 78.171 } 78.172 78.173 @Override 78.174 - protected ArrayData convert(final Class<?> type) { 78.175 + public ArrayData convert(final Class<?> type) { 78.176 underlying = underlying.convert(type); 78.177 return this; 78.178 } 78.179 78.180 @Override 78.181 public Object pop() { 78.182 - if (length() == 0) { 78.183 + if (length == 0) { 78.184 return ScriptRuntime.UNDEFINED; 78.185 } 78.186 - if (length() == underlying.length()) { 78.187 + if (length == underlying.length) { 78.188 final Object result = underlying.pop(); 78.189 - setLength(underlying.length()); 78.190 + setLength(underlying.length); 78.191 return result; 78.192 } 78.193 - setLength(length() - 1); 78.194 - final Long key = Long.valueOf(length()); 78.195 + setLength(length - 1); 78.196 + final Long key = Long.valueOf(length); 78.197 return sparseMap.containsKey(key) ? sparseMap.remove(key) : ScriptRuntime.UNDEFINED; 78.198 } 78.199 78.200 @Override 78.201 public ArrayData slice(final long from, final long to) { 78.202 - assert to <= length(); 78.203 - final long start = from < 0 ? (from + length()) : from; 78.204 + assert to <= length; 78.205 + final long start = from < 0 ? (from + length) : from; 78.206 final long newLength = to - start; 78.207 78.208 if (start >= 0 && to <= maxDenseLength) { 78.209 - if (newLength <= underlying.length()) { 78.210 + if (newLength <= underlying.length) { 78.211 return underlying.slice(from, to); 78.212 } 78.213 - return underlying.slice(from, to).ensure(newLength - 1).delete(underlying.length(), newLength); 78.214 + return underlying.slice(from, to).ensure(newLength - 1).delete(underlying.length, newLength); 78.215 } 78.216 78.217 ArrayData sliced = EMPTY_ARRAY; 78.218 @@ -369,13 +369,13 @@ 78.219 sliced = sliced.set((int)(i - start), getObject((int)i), false); 78.220 } 78.221 } 78.222 - assert sliced.length() == newLength; 78.223 + assert sliced.length == newLength; 78.224 return sliced; 78.225 } 78.226 78.227 @Override 78.228 public long nextIndex(final long index) { 78.229 - if (index < underlying.length() - 1) { 78.230 + if (index < underlying.length - 1) { 78.231 return underlying.nextIndex(index); 78.232 } 78.233 78.234 @@ -383,6 +383,6 @@ 78.235 if (nextKey != null) { 78.236 return nextKey; 78.237 } 78.238 - return length(); 78.239 + return length; 78.240 } 78.241 }
79.1 --- a/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java Wed Oct 01 12:22:12 2014 +0200 79.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java Thu Sep 25 15:53:47 2014 +0200 79.3 @@ -26,7 +26,6 @@ 79.4 package jdk.nashorn.internal.runtime.arrays; 79.5 79.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 79.7 - 79.8 import java.lang.invoke.MethodHandle; 79.9 import java.nio.Buffer; 79.10 import jdk.internal.dynalink.CallSiteDescriptor; 79.11 @@ -55,11 +54,11 @@ 79.12 } 79.13 79.14 /** 79.15 - * Length in elements. Accessed from {@code ArrayBufferView} 79.16 + * Length in number of elements. Accessed from {@code ArrayBufferView} 79.17 * @return element length 79.18 */ 79.19 public final int getElementLength() { 79.20 - return (int)length(); 79.21 + return (int)length; 79.22 } 79.23 79.24 /** 79.25 @@ -120,7 +119,7 @@ 79.26 79.27 @Override 79.28 public final boolean has(final int index) { 79.29 - return 0 <= index && index < length(); 79.30 + return 0 <= index && index < length; 79.31 } 79.32 79.33 @Override 79.34 @@ -134,7 +133,7 @@ 79.35 } 79.36 79.37 @Override 79.38 - protected ArrayData convert(final Class<?> type) { 79.39 + public ArrayData convert(final Class<?> type) { 79.40 throw new UnsupportedOperationException(); 79.41 } 79.42
80.1 --- a/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java Wed Oct 01 12:22:12 2014 +0200 80.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java Thu Sep 25 15:53:47 2014 +0200 80.3 @@ -26,7 +26,6 @@ 80.4 package jdk.nashorn.internal.runtime.arrays; 80.5 80.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 80.7 - 80.8 import java.lang.reflect.Array; 80.9 import jdk.nashorn.internal.runtime.BitVector; 80.10 import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; 80.11 @@ -41,7 +40,7 @@ 80.12 UndefinedArrayFilter(final ArrayData underlying) { 80.13 super(underlying); 80.14 80.15 - this.undefined = new BitVector(underlying.length()); 80.16 + this.undefined = new BitVector(underlying.length); 80.17 } 80.18 80.19 @Override 80.20 @@ -81,25 +80,25 @@ 80.21 @Override 80.22 public void shiftLeft(final int by) { 80.23 super.shiftLeft(by); 80.24 - undefined.shiftLeft(by, length()); 80.25 + undefined.shiftLeft(by, length); 80.26 } 80.27 80.28 @Override 80.29 public ArrayData shiftRight(final int by) { 80.30 super.shiftRight(by); 80.31 - undefined.shiftRight(by, length()); 80.32 + undefined.shiftRight(by, length); 80.33 80.34 return this; 80.35 } 80.36 80.37 @Override 80.38 public ArrayData ensure(final long safeIndex) { 80.39 - if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) { 80.40 + if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) { 80.41 return new SparseArrayData(this, safeIndex + 1); 80.42 } 80.43 80.44 super.ensure(safeIndex); 80.45 - undefined.resize(length()); 80.46 + undefined.resize(length); 80.47 80.48 return this; 80.49 } 80.50 @@ -107,7 +106,7 @@ 80.51 @Override 80.52 public ArrayData shrink(final long newLength) { 80.53 super.shrink(newLength); 80.54 - undefined.resize(length()); 80.55 + undefined.resize(length); 80.56 80.57 return this; 80.58 } 80.59 @@ -217,7 +216,7 @@ 80.60 80.61 @Override 80.62 public Object pop() { 80.63 - final long index = length() - 1; 80.64 + final long index = length - 1; 80.65 80.66 if (super.has((int)index)) { 80.67 final boolean isUndefined = undefined.isSet(index); 80.68 @@ -234,7 +233,7 @@ 80.69 final ArrayData newArray = underlying.slice(from, to); 80.70 final UndefinedArrayFilter newFilter = new UndefinedArrayFilter(newArray); 80.71 newFilter.getUndefined().copy(undefined); 80.72 - newFilter.getUndefined().shiftLeft(from, newFilter.length()); 80.73 + newFilter.getUndefined().shiftLeft(from, newFilter.length); 80.74 80.75 return newFilter; 80.76 }
81.1 --- a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Wed Oct 01 12:22:12 2014 +0200 81.2 +++ b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Thu Sep 25 15:53:47 2014 +0200 81.3 @@ -26,14 +26,16 @@ 81.4 package jdk.nashorn.internal.runtime.linker; 81.5 81.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 81.7 - 81.8 import java.lang.invoke.MethodHandle; 81.9 import java.lang.invoke.MethodType; 81.10 +import java.lang.invoke.SwitchPoint; 81.11 import jdk.internal.dynalink.CallSiteDescriptor; 81.12 import jdk.internal.dynalink.linker.GuardedInvocation; 81.13 import jdk.internal.dynalink.linker.LinkRequest; 81.14 import jdk.internal.dynalink.support.Guards; 81.15 +import jdk.nashorn.internal.runtime.Context; 81.16 import jdk.nashorn.internal.runtime.FindProperty; 81.17 +import jdk.nashorn.internal.runtime.GlobalConstants; 81.18 import jdk.nashorn.internal.runtime.ScriptObject; 81.19 import jdk.nashorn.internal.runtime.UserAccessorProperty; 81.20 81.21 @@ -86,27 +88,41 @@ 81.22 final MethodHandle protoFilter) { 81.23 final CallSiteDescriptor desc = request.getCallSiteDescriptor(); 81.24 81.25 - if(desc.getNameTokenCount() > 2) { 81.26 + //checks whether the property name is hard-coded in the call-site (i.e. a getProp vs a getElem, or setProp vs setElem) 81.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. 81.28 + //so in that case we can skip creation of primitive wrapper and start our search with the prototype. 81.29 + if (desc.getNameTokenCount() > 2) { 81.30 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 81.31 final FindProperty find = wrappedReceiver.findProperty(name, true); 81.32 - if(find == null) { 81.33 + 81.34 + if (find == null) { 81.35 // Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it. 81.36 return null; 81.37 - } else if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) { 81.38 + } 81.39 + 81.40 + final SwitchPoint sp = find.getProperty().getBuiltinSwitchPoint(); //can use this instead of proto filter 81.41 + if (sp instanceof Context.BuiltinSwitchPoint && !sp.hasBeenInvalidated()) { 81.42 + return new GuardedInvocation(GlobalConstants.staticConstantGetter(find.getObjectValue()), guard, sp, null); 81.43 + } 81.44 + 81.45 + if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) { 81.46 // If property is found in the prototype object bind the method handle directly to 81.47 // the proto filter instead of going through wrapper instantiation below. 81.48 final ScriptObject proto = wrappedReceiver.getProto(); 81.49 final GuardedInvocation link = proto.lookup(desc, request); 81.50 81.51 if (link != null) { 81.52 - final MethodHandle invocation = link.getInvocation(); 81.53 + final MethodHandle invocation = link.getInvocation(); //this contains the builtin switchpoint 81.54 + 81.55 final MethodHandle adaptedInvocation = MH.asType(invocation, invocation.type().changeParameterType(0, Object.class)); 81.56 final MethodHandle method = MH.filterArguments(adaptedInvocation, 0, protoFilter); 81.57 final MethodHandle protoGuard = MH.filterArguments(link.getGuard(), 0, protoFilter); 81.58 + 81.59 return new GuardedInvocation(method, NashornGuards.combineGuards(guard, protoGuard)); 81.60 } 81.61 } 81.62 } 81.63 + 81.64 final GuardedInvocation link = wrappedReceiver.lookup(desc, request); 81.65 if (link != null) { 81.66 MethodHandle method = link.getInvocation(); 81.67 @@ -116,8 +132,10 @@ 81.68 assert receiverType.isAssignableFrom(wrapType.returnType()); 81.69 method = MH.filterArguments(method, 0, MH.asType(wrapFilter, wrapType.changeReturnType(receiverType))); 81.70 } 81.71 + 81.72 return new GuardedInvocation(method, guard, link.getSwitchPoints(), null); 81.73 } 81.74 + 81.75 return null; 81.76 } 81.77 }
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 82.2 +++ b/test/examples/charcodeat-benchmark.js Thu Sep 25 15:53:47 2014 +0200 82.3 @@ -0,0 +1,63 @@ 82.4 +/* 82.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 82.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 82.7 + * 82.8 + * This code is free software; you can redistribute it and/or modify it 82.9 + * under the terms of the GNU General Public License version 2 only, as 82.10 + * published by the Free Software Foundation. 82.11 + * 82.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 82.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 82.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 82.15 + * version 2 for more details (a copy is included in the LICENSE file that 82.16 + * accompanied this code). 82.17 + * 82.18 + * You should have received a copy of the GNU General Public License version 82.19 + * 2 along with this work; if not, write to the Free Software Foundation, 82.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 82.21 + * 82.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 82.23 + * or visit www.oracle.com if you need additional information or have any 82.24 + * questions. 82.25 + */ 82.26 + 82.27 +/** 82.28 + * Simple benchmark to measure charCodeAt specialized method performance 82.29 + */ 82.30 + 82.31 +var str = "sghjkdsfkjghsdfjkfkjdfkjdfjkdfjkfdjkfdkfldjfhdfpkjdhafgksdjfgldfgjldfkjgdlfjgldkfjgkldfj"; 82.32 +var RESULT1 = 9187; 82.33 +var RESULT2 = 1496; 82.34 + 82.35 +function f() { 82.36 + var len = str.length; 82.37 + var c = 0; 82.38 + for (var i = 0; i < len; i++) { 82.39 + c += str.charCodeAt(i); 82.40 + } 82.41 + return c; 82.42 +} 82.43 + 82.44 +function bench(res) { 82.45 + var d = new Date; 82.46 + var sum = 0; 82.47 + for (var i = 0; i < 1e6; i++) { 82.48 + sum |= f(); 82.49 + } 82.50 + if (sum == res) { 82.51 + print("Verified OK"); 82.52 + } else { 82.53 + print("Verification failed " + sum + " should be " + res); 82.54 + } 82.55 + print((new Date - d) + " ms"); 82.56 +} 82.57 + 82.58 +bench(RESULT1); 82.59 + 82.60 +print("Replacing charCodeAt... "); 82.61 + 82.62 +String.prototype.charCodeAt = function() { return 17; } 82.63 + 82.64 +bench(RESULT2); 82.65 + 82.66 +print("Done");
83.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 83.2 +++ b/test/examples/push-pop-benchmark.js Thu Sep 25 15:53:47 2014 +0200 83.3 @@ -0,0 +1,59 @@ 83.4 +/* 83.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 83.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 83.7 + * 83.8 + * This code is free software; you can redistribute it and/or modify it 83.9 + * under the terms of the GNU General Public License version 2 only, as 83.10 + * published by the Free Software Foundation. 83.11 + * 83.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 83.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 83.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 83.15 + * version 2 for more details (a copy is included in the LICENSE file that 83.16 + * accompanied this code). 83.17 + * 83.18 + * You should have received a copy of the GNU General Public License version 83.19 + * 2 along with this work; if not, write to the Free Software Foundation, 83.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 83.21 + * 83.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 83.23 + * or visit www.oracle.com if you need additional information or have any 83.24 + * questions. 83.25 + */ 83.26 + 83.27 +/** 83.28 + * Simple benchmark to measure push/pop specialized method performance 83.29 + */ 83.30 + 83.31 +var a = []; 83.32 + 83.33 +var RESULT = 15; 83.34 + 83.35 +function bench() { 83.36 + var sum = 0; 83.37 + for (var i=0;i<10;i++) { 83.38 + a.push(i); 83.39 + } 83.40 + for (var i=0;i<10;i++) { 83.41 + sum |= a.pop(); 83.42 + } 83.43 + return sum; 83.44 +} 83.45 + 83.46 +function runbench() { 83.47 + var sum = 0; 83.48 + for (var iters = 0; iters<1e8; iters++) { 83.49 + sum |= bench(); 83.50 + } 83.51 + return sum; 83.52 +} 83.53 + 83.54 +var d = new Date; 83.55 +var res = runbench(); 83.56 +print((new Date - d) + " ms"); 83.57 +print(); 83.58 +if (res != RESULT) { 83.59 + print("ERROR: Wrong result - should be " + RESULT); 83.60 +} else { 83.61 + print("Verified OK - result is correct"); 83.62 +}
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 84.2 +++ b/test/script/basic/apply_to_call/apply_to_call5.js Thu Sep 25 15:53:47 2014 +0200 84.3 @@ -0,0 +1,111 @@ 84.4 +/* 84.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 84.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 84.7 + * 84.8 + * This code is free software; you can redistribute it and/or modify it 84.9 + * under the terms of the GNU General Public License version 2 only, as 84.10 + * published by the Free Software Foundation. 84.11 + * 84.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 84.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 84.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 84.15 + * version 2 for more details (a copy is included in the LICENSE file that 84.16 + * accompanied this code). 84.17 + * 84.18 + * You should have received a copy of the GNU General Public License version 84.19 + * 2 along with this work; if not, write to the Free Software Foundation, 84.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 84.21 + * 84.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 84.23 + * or visit www.oracle.com if you need additional information or have any 84.24 + * questions. 84.25 + */ 84.26 + 84.27 +/** 84.28 + * apply_to_call5.js - do one apply to call specialization, then override, apply and make sure it reverts (i.e. stops 84.29 + * calling call) 84.30 + * 84.31 + * @test 84.32 + * @run 84.33 + */ 84.34 + 84.35 +print("start"); 84.36 + 84.37 +var x = { 84.38 + a : 0, 84.39 + b : 0, 84.40 + c : 0, 84.41 + initialize : function(x,y,z) { 84.42 + this.a = x; 84.43 + this.b = y; 84.44 + this.c = z; 84.45 + } 84.46 +}; 84.47 + 84.48 +function test() { 84.49 + x.initialize.apply(x, arguments); 84.50 +} 84.51 + 84.52 +test(4711,23,17); 84.53 +print(x.a); 84.54 +print(x.b); 84.55 +print(x.c); 84.56 + 84.57 +print("Overwriting apply now"); 84.58 +x.initialize.apply = function() { print("New function for apply - not a property"); } 84.59 + 84.60 +test(4712); 84.61 +print(x.a); 84.62 + 84.63 + 84.64 +var x2 = { 84.65 + a : 0, 84.66 + b : 0, 84.67 + c : 0, 84.68 + initialize : function(x,y,z) { 84.69 + this.a = x; 84.70 + this.b = y; 84.71 + this.c = z; 84.72 + } 84.73 +}; 84.74 + 84.75 +function test2() { 84.76 + x2.initialize.apply(x2, arguments); 84.77 +} 84.78 + 84.79 +test2(4711,23,17); 84.80 +print(x2.a); 84.81 +print(x2.b); 84.82 +print(x2.c); 84.83 + 84.84 +print("Overwriting apply now"); 84.85 +x2.initialize['apply'] = function() { print("New function for apply - not a property"); } 84.86 + 84.87 +test(4712); 84.88 +print(x2.a); 84.89 + 84.90 +var x3 = { 84.91 + a : 0, 84.92 + b : 0, 84.93 + c : 0, 84.94 + initialize : function(x,y,z) { 84.95 + this.a = x; 84.96 + this.b = y; 84.97 + this.c = z; 84.98 + } 84.99 +}; 84.100 + 84.101 +function test3() { 84.102 + x3.initialize.apply(x3, arguments); 84.103 +} 84.104 + 84.105 +test3(4711,23,17); 84.106 +print(x3.a); 84.107 +print(x3.b); 84.108 +print(x3.c); 84.109 + 84.110 +print("Overwriting apply now"); 84.111 +eval("x3.initialize['apply'] = function() { print('New function for apply - not a property'); }"); 84.112 + 84.113 +test(4712); 84.114 +print(x3.a);
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 85.2 +++ b/test/script/basic/apply_to_call/apply_to_call5.js.EXPECTED Thu Sep 25 15:53:47 2014 +0200 85.3 @@ -0,0 +1,19 @@ 85.4 +start 85.5 +4711 85.6 +23 85.7 +17 85.8 +Overwriting apply now 85.9 +New function for apply - not a property 85.10 +4711 85.11 +4711 85.12 +23 85.13 +17 85.14 +Overwriting apply now 85.15 +New function for apply - not a property 85.16 +4711 85.17 +4711 85.18 +23 85.19 +17 85.20 +Overwriting apply now 85.21 +New function for apply - not a property 85.22 +4711
86.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 86.2 +++ b/test/script/basic/fastpushpop.js Thu Sep 25 15:53:47 2014 +0200 86.3 @@ -0,0 +1,61 @@ 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. 86.11 + * 86.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 86.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 86.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 86.15 + * version 2 for more details (a copy is included in the LICENSE file that 86.16 + * accompanied this code). 86.17 + * 86.18 + * You should have received a copy of the GNU General Public License version 86.19 + * 2 along with this work; if not, write to the Free Software Foundation, 86.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 86.21 + * 86.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 86.23 + * or visit www.oracle.com if you need additional information or have any 86.24 + * questions. 86.25 + */ 86.26 + 86.27 +/** 86.28 + * fastpushpop.js: make sure guards work for fast push implementation 86.29 + * and normal one 86.30 + * 86.31 + * @test 86.32 + * @run 86.33 + */ 86.34 + 86.35 +var a = [1,2,3]; 86.36 +a.push(4); 86.37 +a.push(5); 86.38 +a.push(6); 86.39 +print(a); 86.40 + 86.41 +var a2 = Object.defineProperty(a,"length", { writable: false }); 86.42 +try { 86.43 + a2.push(7); 86.44 +} catch (e) { 86.45 + print("first: " + (e instanceof TypeError)); 86.46 +} 86.47 + 86.48 +print(a2); 86.49 + 86.50 +var b = [1,2,3,,,,4711.17,"dingo!"]; 86.51 +b.push(4); 86.52 +b.push(5); 86.53 +b.push(6); 86.54 +print(b); 86.55 + 86.56 +var b2 = Object.defineProperty(b,"length", { writable: false }); 86.57 +try { 86.58 + b2.push(7); 86.59 +} catch (e) { 86.60 + print("second: " + (e instanceof TypeError)); 86.61 +} 86.62 + 86.63 +print(b2); 86.64 +
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 87.2 +++ b/test/script/basic/fastpushpop.js.EXPECTED Thu Sep 25 15:53:47 2014 +0200 87.3 @@ -0,0 +1,6 @@ 87.4 +1,2,3,4,5,6 87.5 +first: true 87.6 +1,2,3,4,5,6,7 87.7 +1,2,3,,,,4711.17,dingo!,4,5,6 87.8 +second: true 87.9 +1,2,3,,,,4711.17,dingo!,4,5,6,7
88.1 --- a/test/script/basic/run-octane.js Wed Oct 01 12:22:12 2014 +0200 88.2 +++ b/test/script/basic/run-octane.js Thu Sep 25 15:53:47 2014 +0200 88.3 @@ -54,7 +54,7 @@ 88.4 } 88.5 } 88.6 88.7 - print_verbose(arg, "loading '" + arg.name + "' [" + f + "]..."); 88.8 + print_verbose(arg, "loading '" + arg.name + "' [" + f + "]... " + file_name); 88.9 load(file_name); 88.10 } 88.11 88.12 @@ -139,7 +139,7 @@ 88.13 mean_score /= iters; 88.14 } catch (e) { 88.15 print_always(arg, "*** Aborted and setting score to zero. Reason: " + e); 88.16 - if (e instanceof java.lang.Throwable) { 88.17 + if (is_this_nashorn() && e instanceof java.lang.Throwable) { 88.18 e.printStackTrace(); 88.19 } 88.20 mean_score = min_score = max_score = 0; 88.21 @@ -148,7 +148,7 @@ 88.22 88.23 var res = mean_score.toFixed(0); 88.24 if (verbose) { 88.25 - res += " ops/minute (" + min_score.toFixed(0) + "-" + max_score.toFixed(0) + "), warmup=" + scores[0].toFixed(0); 88.26 + res += " ops/minute (" + min_score.toFixed(0) + "-" + max_score.toFixed(0) + "), warmup=" + scores[0].toFixed(0); 88.27 } 88.28 print_always(arg, res); 88.29 }