Merge jdk8u40-b10

Tue, 14 Oct 2014 10:20:24 -0700

author
asaha
date
Tue, 14 Oct 2014 10:20:24 -0700
changeset 1048
076b1f38a5cc
parent 1047
fdb261020de8
parent 1037
b962745a8ccc
child 1049
57c7b273277e

Merge

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

mercurial