8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt

Thu, 25 Sep 2014 15:53:47 +0200

author
lagergren
date
Thu, 25 Sep 2014 15:53:47 +0200
changeset 1028
d79265f2fa92
parent 1027
236ce951d1e4
child 1029
70597fd25c61

8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
Reviewed-by: hannesw, attila, sundar

buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java file | annotate | diff | comparison | revisions
buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java file | annotate | diff | comparison | revisions
buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java file | annotate | diff | comparison | revisions
buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java file | annotate | diff | comparison | revisions
buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java file | annotate | diff | comparison | revisions
buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java file | annotate | diff | comparison | revisions
buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java file | annotate | diff | comparison | revisions
samples/BufferArray.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/ApplySpecialization.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/ClassEmitter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/CompilationPhase.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/CompileUnit.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/MethodEmitter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/types/Type.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/FunctionNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/LiteralNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/Symbol.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/lookup/MethodHandleFactory.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/ArrayBufferView.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/Global.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeArray.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeDataView.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeDate.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeDebug.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeFloat32Array.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeFloat64Array.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeInt16Array.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeInt32Array.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeInt8Array.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeJSAdapter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeRegExp.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeString.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeUint16Array.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeUint32Array.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeUint8Array.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/annotations/SpecializedConstructor.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/AccessorProperty.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/CodeInstaller.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/CodeStore.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/CompiledFunction.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/Context.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/Debug.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/FindProperty.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/GlobalConstants.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/GlobalFunctions.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/OptimisticBuiltins.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/Property.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/PropertyMap.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptEnvironment.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptFunction.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptFunctionData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptRuntime.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/SetMethodCreator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/Specialization.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/StoredScript.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/UserAccessorProperty.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ArrayData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/IntElements.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/IntOrLongElements.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/NumericElements.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java file | annotate | diff | comparison | revisions
test/examples/charcodeat-benchmark.js file | annotate | diff | comparison | revisions
test/examples/push-pop-benchmark.js file | annotate | diff | comparison | revisions
test/script/basic/apply_to_call/apply_to_call5.js file | annotate | diff | comparison | revisions
test/script/basic/apply_to_call/apply_to_call5.js.EXPECTED file | annotate | diff | comparison | revisions
test/script/basic/fastpushpop.js file | annotate | diff | comparison | revisions
test/script/basic/fastpushpop.js.EXPECTED file | annotate | diff | comparison | revisions
test/script/basic/run-octane.js file | annotate | diff | comparison | revisions
     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-&gt;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-&gt;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  }

mercurial