Merge

Thu, 06 Nov 2014 09:50:15 -0800

author
asaha
date
Thu, 06 Nov 2014 09:50:15 -0800
changeset 1282
72c7148acf87
parent 1281
fd5d4ebfe7db
parent 1163
56366e7189c6
child 1283
7b05a206ec6a

Merge

.hgtags file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java file | annotate | diff | comparison | revisions
     1.1 --- a/.hgtags	Mon Oct 27 14:36:13 2014 -0700
     1.2 +++ b/.hgtags	Thu Nov 06 09:50:15 2014 -0800
     1.3 @@ -328,6 +328,8 @@
     1.4  3505d266634ded89bf9617ff6b385ab8a52f78cf jdk8u31-b03
     1.5  96acff2ad9e19aa80c4f7ed60d87a422bca1ea91 jdk8u31-b04
     1.6  5fc3f210872d365c57ed4e8dba3926d9ed5c7e45 jdk8u31-b05
     1.7 +99a3333f7f8489bb3c80f0c0643ae19e549a0941 jdk8u31-b06
     1.8 +5ed4fa732b26b6d8e37dfc5bbd00047c5352719b jdk8u31-b07
     1.9  f2925491b61b22ac42f8c30ee9c6723ffa401a4c jdk8u40-b00
    1.10  62468d841b842769d875bd97d10370585c296eb7 jdk8u40-b01
    1.11  b476c69c820ac1e05071f4de5abab8e2dff80e87 jdk8u40-b02
    1.12 @@ -340,4 +342,6 @@
    1.13  6a8ecdeae4a9a438eed637b5a5d0d18fddb9f711 jdk8u40-b09
    1.14  076b1f38a5ccd4692a6f93939a7fc03bc1a1bbb4 jdk8u40-b10
    1.15  57c7b273277e00f7a98fafb18ff07aa3245808f0 jdk8u40-b11
    1.16 +375a3a3256d041fe7334638a95e69b4c11d6104b jdk8u40-b12
    1.17 +d60fbb5343c186abbf92b0259e67efb3b71377b4 jdk8u40-b13
    1.18  05a3614ed5276e5db2a73cce918be04b1a2922fb jdk8u45-b00
     2.1 --- a/bin/runopt.sh	Mon Oct 27 14:36:13 2014 -0700
     2.2 +++ b/bin/runopt.sh	Thu Nov 06 09:50:15 2014 -0800
     2.3 @@ -28,14 +28,35 @@
     2.4  # known flags for performance for the current configration
     2.5  ###########################################################################################
     2.6  
     2.7 +# Flags to enable assertions, we need the system assertions too, since
     2.8 +# this script runs Nashorn in the BCP to override any nashorn.jar that might
     2.9 +# reside in your $JAVA_HOME/jre/lib/ext/nashorn.jar
    2.10 +#
    2.11 +ENABLE_ASSERTIONS_FLAGS="-ea -esa"
    2.12 +
    2.13  # Flags to instrument lambdaform computation, caching, interpretation and compilation
    2.14  # Default compile threshold for lambdaforms is 30
    2.15 -#FLAGS="-Djava.lang.invoke.MethodHandle.COMPILE_THRESHOLD=3 -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true -Djava.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE=true -Djava.lang.invoke.MethodHandle.TRACE_INTERPRETER=true"
    2.16 -
    2.17 +#
    2.18 +#LAMBDAFORM_FLAGS="\
    2.19 +#    -Djava.lang.invoke.MethodHandle.COMPILE_THRESHOLD=3 \
    2.20 +#    -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true \
    2.21 +#    -Djava.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE=true \
    2.22 +#    -Djava.lang.invoke.MethodHandle.TRACE_INTERPRETER=true"
    2.23  
    2.24  # Flags to run trusted tests from the Nashorn test suite
    2.25 -#FLAGS="-Djava.security.manager -Djava.security.policy=../build/nashorn.policy -Dnashorn.debug"
    2.26 +#
    2.27 +#TRUSTED_TEST_FLAGS="\
    2.28 +#-Djava.security.manager \
    2.29 +#-Djava.security.policy=../build/nashorn.policy -Dnashorn.debug"
    2.30  
    2.31 +# Testing out new code optimizations using the generic hotspot "new code" parameter
    2.32 +#
    2.33 +#USE_NEW_CODE_FLAGS=-XX:+UnlockDiagnosticVMOptions -XX:+UseNewCode
    2.34 +
    2.35 +#
    2.36 +#-Dnashorn.typeInfo.disabled=false \
    2.37 +# and for Nashorn options: 
    2.38 +# --class-cache-size=0 --persistent-code-cache=false 
    2.39  
    2.40  # Unique timestamped file name for JFR recordings. For JFR, we also have to
    2.41  # crank up the stack cutoff depth to 1024, because of ridiculously long lambda form
    2.42 @@ -46,8 +67,42 @@
    2.43  # can go (10 ms on most platforms). The default is normally higher. The increased
    2.44  # sampling overhead is usually negligible for Nashorn runs, but the data is better
    2.45  
    2.46 -JFR_FILENAME="./nashorn_$(date|sed "s/ /_/g"|sed "s/:/_/g").jfr"
    2.47 +if [ -z $JFR_FILENAME ]; then
    2.48 +    JFR_FILENAME="./nashorn_$(date|sed "s/ /_/g"|sed "s/:/_/g").jfr"
    2.49 +fi
    2.50  
    2.51 +# Flight recorder
    2.52 +#
    2.53 +# see above - already in place, copy the flags down here to disable
    2.54 +ENABLE_FLIGHT_RECORDER_FLAGS="\
    2.55 +    -XX:+UnlockCommercialFeatures \
    2.56 +    -XX:+FlightRecorder \
    2.57 +    -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=$JFR_FILENAME,stackdepth=1024"
    2.58 +
    2.59 +# Type specialization and math intrinsic replacement should be enabled by default in 8u20 and nine,
    2.60 +# keeping this flag around for experimental reasons. Replace + with - to switch it off
    2.61 +#
    2.62 +#ENABLE_TYPE_SPECIALIZATION_FLAGS=-XX:+UseTypeSpeculation
    2.63 +
    2.64 +# Same with math intrinsics. They should be enabled by default in 8u20 and 9, so
    2.65 +# this disables them if needed
    2.66 +#
    2.67 +#DISABLE_MATH_INTRINSICS_FLAGS=-XX:-UseMathExactIntrinsics
    2.68 +
    2.69 +# Add timing to time the compilation phases.
    2.70 +#ENABLE_TIME_FLAGS=--log=time
    2.71 +
    2.72 +# Add ShowHiddenFrames to get lambda form internals on the stack traces
    2.73 +#ENABLE_SHOW_HIDDEN_FRAMES_FLAGS=-XX:+ShowHiddenFrames
    2.74 +
    2.75 +# Add print optoassembly to get an asm dump. This requires 1) a debug build, not product,
    2.76 +# That tired compilation is switched off, for C2 only output and that the number of
    2.77 +# compiler threads is set to 1 for determinsm.
    2.78 +#
    2.79 +#PRINT_ASM_FLAGS=-XX:+PrintOptoAssembly -XX:-TieredCompilation -XX:CICompilerCount=1 \
    2.80 +
    2.81 +# Tier compile threasholds. Default value is 10. (1-100 is useful for experiments)
    2.82 +#TIER_COMPILATION_THRESHOLD_FLAGS=-XX:IncreaseFirstTierCompileThresholdAt=10
    2.83  
    2.84  # Directory where to look for nashorn.jar in a dist folder. The default is "..", assuming
    2.85  # that we run the script from the make dir
    2.86 @@ -59,49 +114,23 @@
    2.87  # nashorn.jar in $JAVA_HOME/jre/lib/ext. Thus, we also need -esa, as assertions in
    2.88  # nashorn count as system assertions in this configuration
    2.89  
    2.90 +# Type profiling default level is 111, 222 adds some compile time, but is faster
    2.91 +
    2.92  $JAVA_HOME/bin/java \
    2.93 -$FLAGS \
    2.94 --ea \
    2.95 --esa \
    2.96 +$ENABLE_ASSERTIONS_FLAGS \
    2.97 +$LAMBDAFORM_FLAGS \
    2.98 +$TRUSTED_FLAGS \
    2.99 +$USE_NEW_CODE_FLAGS \
   2.100 +$ENABLE_SHOW_HIDDEN_FRAMES_FLAGS \
   2.101 +$ENABLE_FLIGHT_RECORDER_FLAGS \
   2.102 +$ENABLE_TYPE_SPECIALIZATION_FLAGS \
   2.103 +$TIERED_COMPILATION_THRESOLD_FLAGS \
   2.104 +$DISABLE_MATH_INTRINSICS_FLAGS \
   2.105 +$PRINT_ASM_FLAGS \
   2.106  -Xbootclasspath/p:$NASHORN_JAR \
   2.107  -Xms2G -Xmx2G \
   2.108 +-XX:TypeProfileLevel=222 \
   2.109  -cp $CLASSPATH:../build/test/classes/ \
   2.110 -jdk.nashorn.tools.Shell ${@}
   2.111 +jdk.nashorn.tools.Shell $ENABLE_TIME_FLAGS ${@}
   2.112  
   2.113 -# Below are flags that may come in handy, but aren't used for default runs
   2.114  
   2.115 -
   2.116 -# Type profiling default level is 111, 222 adds some compile time, but produces better code.
   2.117 -# -XX:TypeProfileLevel=222 \
   2.118 -
   2.119 -
   2.120 -# Testing out new code optimizations using the generic hotspot "new code" parameter
   2.121 -#-XX:+UnlockDiagnosticVMOptions \
   2.122 -#-XX:+UseNewCode \
   2.123 -
   2.124 -
   2.125 -# Type specialization and math intrinsic replacement should be enabled by default in 8u20 and nine,
   2.126 -# keeping this flag around for experimental reasons. Replace + with - to switch it off
   2.127 -#-XX:+UseTypeSpeculation \
   2.128 -
   2.129 -
   2.130 -# Same with math intrinsics. They should be enabled by default in 8u20 and 9
   2.131 -#-XX:+UseMathExactIntrinsics \
   2.132 -
   2.133 -
   2.134 -# Add -Dnashorn.time to time the compilation phases.
   2.135 -#-Dnashorn.time \
   2.136 -
   2.137 -
   2.138 -# Add ShowHiddenFrames to get lambda form internals on the stack traces
   2.139 -#-XX:+ShowHiddenFrames \
   2.140 -
   2.141 -
   2.142 -# Add print optoassembly to get an asm dump. This requires 1) a debug build, not product,
   2.143 -# That tired compilation is switched off, for C2 only output and that the number of
   2.144 -# compiler threads is set to 1 for determinsm.
   2.145 -#-XX:+PrintOptoAssembly -XX:-TieredCompilation -XX:CICompilerCount=1 \
   2.146 -
   2.147 -# Tier compile threasholds. Default value is 10. (1-100 is useful for experiments)
   2.148 -# -XX:IncreaseFirstTierCompileThresholdAt=XX
   2.149 -
     3.1 --- a/docs/DEVELOPER_README	Mon Oct 27 14:36:13 2014 -0700
     3.2 +++ b/docs/DEVELOPER_README	Thu Nov 06 09:50:15 2014 -0800
     3.3 @@ -25,6 +25,14 @@
     3.4  > java -Dnashorn.args="--lazy-complation --log=compiler" large-java-app-with-nashorn.jar 
     3.5  > ant -Dnashorn.args="--log=codegen" antjob
     3.6  
     3.7 +SYSTEM PROPERTY: -Dnashorn.args.prepend=<string>
     3.8 +
     3.9 +This property behaves like nashorn.args, but adds the given arguments
    3.10 +before the existing ones instead of after them. Later arguments will
    3.11 +overwrite earlier ones, so this is useful for setting default arguments
    3.12 +that can be overwritten.
    3.13 +
    3.14 +
    3.15  SYSTEM PROPERTY: -Dnashorn.unstable.relink.threshold=x
    3.16  
    3.17  This property controls how many call site misses are allowed before a 
    3.18 @@ -42,533 +50,38 @@
    3.19  The default value is 0x8000 (32768).
    3.20  
    3.21  
    3.22 -SYSTEM PROPERTY: -Dnashorn.compiler.intarithmetic
    3.23 +SYSTEM PROPERTY: -Dnashorn.serialize.compression=<x>
    3.24  
    3.25 -(and integer arithmetic in general)
    3.26 +This property sets the compression level used when deflating serialized
    3.27 +AST structures of anonymous split functions. Valid values range from 0 to 9,
    3.28 +the default value is 4. Higher values will reduce memory size of serialized
    3.29 +AST but increase CPU usage required for compression.
    3.30  
    3.31 -<currently disabled - this is being refactored for update releases> 
    3.32  
    3.33 -Arithmetic operations in Nashorn (except bitwise ones) typically
    3.34 -coerce the operands to doubles (as per the JavaScript spec). To switch
    3.35 -this off and remain in integer mode, for example for "var x = a&b; var
    3.36 -y = c&d; var z = x*y;", use this flag. This will force the
    3.37 -multiplication of variables that are ints to be done with the IMUL
    3.38 -bytecode and the result "z" to become an int.
    3.39 -
    3.40 -WARNING: Note that is is experimental only to ensure that type support
    3.41 -exists for all primitive types. The generated code is unsound. This
    3.42 -will be the case until we do optimizations based on it. There is a CR
    3.43 -in Nashorn to do better range analysis, and ensure that this is only
    3.44 -done where the operation can't overflow into a wider type. Currently
    3.45 -no overflow checking is done, so at the moment, until range analysis
    3.46 -has been completed, this option is turned off.
    3.47 -
    3.48 -We've experimented by using int arithmetic for everything and putting
    3.49 -overflow checks afterwards, which would recompute the operation with
    3.50 -the correct precision, but have yet to find a configuration where this
    3.51 -is faster than just using doubles directly, even if the int operation
    3.52 -does not overflow. Getting access to a JVM intrinsic that does branch
    3.53 -on overflow would probably alleviate this.
    3.54 -
    3.55 -The future:
    3.56 -
    3.57 -We are transitioning to an optimistic type system that uses int
    3.58 -arithmetic everywhere until proven wrong. The problem here is mostly
    3.59 -catch an overflow exception and rolling back the state to a new method
    3.60 -with less optimistic assumptions for an operation at a particular
    3.61 -program point. This will most likely not be in the Java 8.0 release
    3.62 -but likely end up in an update release
    3.63 -
    3.64 -For Java 8, several java.lang.Math methods like addExact, subExact and
    3.65 -mulExact are available to help us. Experiments intrinsifying these
    3.66 -show a lot of promise, and we have devised a system that basically
    3.67 -does on stack replacement with exceptions in bytecode to revert
    3.68 -erroneous assumptions. An explanation of how this works and what we
    3.69 -are doing can be found here:
    3.70 -http://www.slideshare.net/lagergren/lagergren-jvmls2013final
    3.71 -
    3.72 -Experiments with this show significant ~x2-3 performance increases on
    3.73 -pretty much everything, provided that optimistic assumptions don't
    3.74 -fail much. It will affect warmup time negatively, depending on how
    3.75 -many erroneous too optimistic assumptions are placed in the code at
    3.76 -compile time. We don't think this will be much of an issue.
    3.77 -
    3.78 -For example for a small benchmark that repeatedly executes this
    3.79 -method taken from the Crypto Octane benchmark 
    3.80 -
    3.81 -function am3(i,x,w,j,c,n) {
    3.82 -  var this_array = this.array;
    3.83 -  var w_array    = w.array;
    3.84 -  var xl = x&0x3fff, xh = x>>14;
    3.85 -  while(--n >= 0) {
    3.86 -    var l = this_array[i]&0x3fff;
    3.87 -    var h = this_array[i++]>>14;
    3.88 -    var m = xh*l+h*xl;
    3.89 -    l = xl*l+((m&0x3fff)<<14)+w_array[j]+c;
    3.90 -    c = (l>>28)+(m>>14)+xh*h;
    3.91 -    w_array[j++] = l&0xfffffff;
    3.92 -  }
    3.93 -
    3.94 -  return c;
    3.95 -}
    3.96 -
    3.97 -The performance increase more than doubles. We are also working hard
    3.98 -with the code generation team in the Java Virtual Machine to fix
    3.99 -things that are lacking in invokedynamic performance, which is another
   3.100 -area where a lot of ongoing performance work takes place
   3.101 -
   3.102 -"Pessimistic" bytecode for am3, guaranteed to be semantically correct:
   3.103 -
   3.104 -// access flags 0x9
   3.105 -  public static am3(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
   3.106 -   L0
   3.107 -    LINENUMBER 12 L0
   3.108 -    ALOAD 0
   3.109 -    INVOKEDYNAMIC dyn:getProp|getElem|getMethod:array(Ljava/lang/Object;)Ljava/lang/Object; [
   3.110 -      // handle kind 0x6 : INVOKESTATIC
   3.111 -      jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
   3.112 -      // arguments:
   3.113 -      0
   3.114 -    ]
   3.115 -    ASTORE 8
   3.116 -   L1
   3.117 -    LINENUMBER 13 L1
   3.118 -    ALOAD 3
   3.119 -    INVOKEDYNAMIC dyn:getProp|getElem|getMethod:array(Ljava/lang/Object;)Ljava/lang/Object; [
   3.120 -      // handle kind 0x6 : INVOKESTATIC
   3.121 -      jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
   3.122 -      // arguments:
   3.123 -      0
   3.124 -    ]
   3.125 -    ASTORE 9
   3.126 -   L2
   3.127 -    LINENUMBER 14 L2
   3.128 -    ALOAD 2
   3.129 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (Ljava/lang/Object;)I
   3.130 -    SIPUSH 16383
   3.131 -    IAND
   3.132 -    ISTORE 10
   3.133 -    ALOAD 2
   3.134 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (Ljava/lang/Object;)I
   3.135 -    BIPUSH 14
   3.136 -    ISHR
   3.137 -    ISTORE 11
   3.138 -   L3
   3.139 -    LINENUMBER 15 L3
   3.140 -    GOTO L4
   3.141 -   L5
   3.142 -    LINENUMBER 16 L5
   3.143 -   FRAME FULL [java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Double T java/lang/Object java/lang/Object I I] []
   3.144 -    ALOAD 8
   3.145 -    ALOAD 1
   3.146 -    INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;Ljava/lang/Object;)I [
   3.147 -      // handle kind 0x6 : INVOKESTATIC
   3.148 -      jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
   3.149 -      // arguments:
   3.150 -      0
   3.151 -    ]
   3.152 -    SIPUSH 16383
   3.153 -    IAND
   3.154 -    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
   3.155 -    ASTORE 12
   3.156 -   L6
   3.157 -    LINENUMBER 17 L6
   3.158 -    ALOAD 8
   3.159 -    ALOAD 1
   3.160 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
   3.161 -    DUP2
   3.162 -    DCONST_1
   3.163 -    DADD
   3.164 -    INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;
   3.165 -    ASTORE 1
   3.166 -    INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;D)I [
   3.167 -      // handle kind 0x6 : INVOKESTATIC
   3.168 -      jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
   3.169 -      // arguments:
   3.170 -      0
   3.171 -    ]
   3.172 -    BIPUSH 14
   3.173 -    ISHR
   3.174 -    ISTORE 13
   3.175 -   L7
   3.176 -    LINENUMBER 18 L7
   3.177 -    ILOAD 11
   3.178 -    I2D
   3.179 -    ALOAD 12
   3.180 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
   3.181 -    DMUL
   3.182 -    ILOAD 13
   3.183 -    I2D
   3.184 -    ILOAD 10
   3.185 -    I2D
   3.186 -    DMUL
   3.187 -    DADD
   3.188 -    DSTORE 14
   3.189 -   L8
   3.190 -    LINENUMBER 19 L8
   3.191 -    ILOAD 10
   3.192 -    I2D
   3.193 -    ALOAD 12
   3.194 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
   3.195 -    DMUL
   3.196 -    DLOAD 14
   3.197 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (D)I
   3.198 -    SIPUSH 16383
   3.199 -    IAND
   3.200 -    BIPUSH 14
   3.201 -    ISHL
   3.202 -    I2D
   3.203 -    DADD
   3.204 -    ALOAD 9
   3.205 -    ALOAD 4
   3.206 -    INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; [
   3.207 -      // handle kind 0x6 : INVOKESTATIC
   3.208 -      jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
   3.209 -      // arguments:
   3.210 -      0
   3.211 -    ]
   3.212 -    INVOKEDYNAMIC ADD:ODO_D(DLjava/lang/Object;)Ljava/lang/Object; [
   3.213 -      // handle kind 0x6 : INVOKESTATIC
   3.214 -      jdk/nashorn/internal/runtime/linker/Bootstrap.runtimeBootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;)
   3.215 -      // arguments: none
   3.216 -    ]
   3.217 -    ALOAD 5
   3.218 -    INVOKEDYNAMIC ADD:OOO_I(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; [
   3.219 -      // handle kind 0x6 : INVOKESTATIC
   3.220 -      jdk/nashorn/internal/runtime/linker/Bootstrap.runtimeBootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;)
   3.221 -      // arguments: none
   3.222 -    ]
   3.223 -    ASTORE 12
   3.224 -   L9
   3.225 -    LINENUMBER 20 L9
   3.226 -    ALOAD 12
   3.227 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (Ljava/lang/Object;)I
   3.228 -    BIPUSH 28
   3.229 -    ISHR
   3.230 -    I2D
   3.231 -    DLOAD 14
   3.232 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (D)I
   3.233 -    BIPUSH 14
   3.234 -    ISHR
   3.235 -    I2D
   3.236 -    DADD
   3.237 -    ILOAD 11
   3.238 -    I2D
   3.239 -    ILOAD 13
   3.240 -    I2D
   3.241 -    DMUL
   3.242 -    DADD
   3.243 -    INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;
   3.244 -    ASTORE 5
   3.245 -   L10
   3.246 -    LINENUMBER 21 L10
   3.247 -    ALOAD 9
   3.248 -    ALOAD 4
   3.249 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
   3.250 -    DUP2
   3.251 -    DCONST_1
   3.252 -    DADD
   3.253 -    INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;
   3.254 -    ASTORE 4
   3.255 -    ALOAD 12
   3.256 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (Ljava/lang/Object;)I
   3.257 -    LDC 268435455
   3.258 -    IAND
   3.259 -    INVOKEDYNAMIC dyn:setElem|setProp(Ljava/lang/Object;DI)V [
   3.260 -      // handle kind 0x6 : INVOKESTATIC
   3.261 -      jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
   3.262 -      // arguments:
   3.263 -      0
   3.264 -    ]
   3.265 -   L4
   3.266 -   FRAME FULL [java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object T java/lang/Object java/lang/Object I I] []
   3.267 -    ALOAD 6
   3.268 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
   3.269 -    LDC -1.0
   3.270 -    DADD
   3.271 -    DUP2
   3.272 -    INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;
   3.273 -    ASTORE 6
   3.274 -    DCONST_0
   3.275 -    DCMPL
   3.276 -    IFGE L5
   3.277 -   L11
   3.278 -    LINENUMBER 24 L11
   3.279 -    ALOAD 5
   3.280 -    ARETURN
   3.281 -
   3.282 -"Optimistic" bytecode that requires invalidation on e.g overflow. Factor
   3.283 -x2-3 speedup:
   3.284 -
   3.285 -public static am3(Ljava/lang/Object;IILjava/lang/Object;III)I
   3.286 -   L0
   3.287 -    LINENUMBER 12 L0
   3.288 -    ALOAD 0
   3.289 -    INVOKEDYNAMIC dyn:getProp|getElem|getMethod:array(Ljava/lang/Object;)Ljava/lang/Object; [
   3.290 -      // handle kind 0x6 : INVOKESTATIC
   3.291 -      jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
   3.292 -      // arguments:
   3.293 -      0
   3.294 -    ]
   3.295 -    ASTORE 8
   3.296 -   L1
   3.297 -    LINENUMBER 13 L1
   3.298 -    ALOAD 3
   3.299 -    INVOKEDYNAMIC dyn:getProp|getElem|getMethod:array(Ljava/lang/Object;)Ljava/lang/Object; [
   3.300 -      // handle kind 0x6 : INVOKESTATIC
   3.301 -      jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
   3.302 -      // arguments:
   3.303 -      0
   3.304 -    ]
   3.305 -    ASTORE 9
   3.306 -   L2
   3.307 -    LINENUMBER 14 L2
   3.308 -    ILOAD 2
   3.309 -    SIPUSH 16383
   3.310 -    IAND
   3.311 -    ISTORE 10
   3.312 -    ILOAD 2
   3.313 -    BIPUSH 14
   3.314 -    ISHR
   3.315 -    ISTORE 11
   3.316 -   L3
   3.317 -    LINENUMBER 15 L3
   3.318 -    GOTO L4
   3.319 -   L5
   3.320 -    LINENUMBER 16 L5
   3.321 -   FRAME FULL [java/lang/Object I I java/lang/Object I I I T java/lang/Object java/lang/Object I I] []
   3.322 -    ALOAD 8
   3.323 -    ILOAD 1
   3.324 -    INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;I)I [
   3.325 -      // handle kind 0x6 : INVOKESTATIC
   3.326 -      jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
   3.327 -      // arguments:
   3.328 -      0
   3.329 -    ]
   3.330 -    SIPUSH 16383
   3.331 -    IAND
   3.332 -    ISTORE 12
   3.333 -   L6
   3.334 -    LINENUMBER 17 L6
   3.335 -    ALOAD 8
   3.336 -    ILOAD 1
   3.337 -    DUP
   3.338 -    ICONST_1
   3.339 -    IADD
   3.340 -    ISTORE 1
   3.341 -    INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;I)I [
   3.342 -      // handle kind 0x6 : INVOKESTATIC
   3.343 -      jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
   3.344 -      // arguments:
   3.345 -      0
   3.346 -    ]
   3.347 -    BIPUSH 14
   3.348 -    ISHR
   3.349 -    ISTORE 13
   3.350 -   L7
   3.351 -    LINENUMBER 18 L7
   3.352 -    ILOAD 11
   3.353 -    ILOAD 12
   3.354 -    BIPUSH 8
   3.355 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.mulExact (III)I
   3.356 -    ILOAD 13
   3.357 -    ILOAD 10
   3.358 -    BIPUSH 9
   3.359 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.mulExact (III)I
   3.360 -    IADD
   3.361 -    ISTORE 14
   3.362 -   L8
   3.363 -    LINENUMBER 19 L8
   3.364 -    ILOAD 10
   3.365 -    ILOAD 12
   3.366 -    BIPUSH 11
   3.367 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.mulExact (III)I
   3.368 -    ILOAD 14
   3.369 -    SIPUSH 16383
   3.370 -    IAND
   3.371 -    BIPUSH 14
   3.372 -    ISHL
   3.373 -    IADD
   3.374 -    ALOAD 9
   3.375 -    ILOAD 4
   3.376 -    INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;I)I [
   3.377 -      // handle kind 0x6 : INVOKESTATIC
   3.378 -      jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
   3.379 -      // arguments:
   3.380 -      0
   3.381 -    ]
   3.382 -    IADD
   3.383 -    ILOAD 5
   3.384 -    IADD
   3.385 -    ISTORE 12
   3.386 -   L9
   3.387 -    LINENUMBER 20 L9
   3.388 -    ILOAD 12
   3.389 -    BIPUSH 28
   3.390 -    ISHR
   3.391 -    ILOAD 14
   3.392 -    BIPUSH 14
   3.393 -    ISHR
   3.394 -    IADD
   3.395 -    ILOAD 11
   3.396 -    ILOAD 13
   3.397 -    BIPUSH 21
   3.398 -    INVOKESTATIC jdk/nashorn/internal/runtime/JSType.mulExact (III)I
   3.399 -    IADD
   3.400 -    ISTORE 5
   3.401 -   L10
   3.402 -    LINENUMBER 21 L10
   3.403 -    ALOAD 9
   3.404 -    ILOAD 4
   3.405 -    DUP
   3.406 -    ICONST_1
   3.407 -    IADD
   3.408 -    ISTORE 4
   3.409 -    ILOAD 12
   3.410 -    LDC 268435455
   3.411 -    IAND
   3.412 -    INVOKEDYNAMIC dyn:setElem|setProp(Ljava/lang/Object;II)V [
   3.413 -      // handle kind 0x6 : INVOKESTATIC
   3.414 -      jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
   3.415 -      // arguments:
   3.416 -      0
   3.417 -    ]
   3.418 -   L4
   3.419 -   FRAME SAME
   3.420 -    ILOAD 6
   3.421 -    ICONST_M1
   3.422 -    IADD
   3.423 -    DUP
   3.424 -    ISTORE 6
   3.425 -    ICONST_0
   3.426 -    IF_ICMPGE L5
   3.427 -   L11
   3.428 -    LINENUMBER 24 L11
   3.429 -    ILOAD 5
   3.430 -    IRETURN
   3.431 -
   3.432 -
   3.433 -SYSTEM PROPERTY: -Dnashorn.codegen.debug, -Dnashorn.codegen.debug.trace=<x>
   3.434 +SYSTEM PROPERTY: -Dnashorn.codegen.debug.trace=<x>
   3.435  
   3.436  See the description of the codegen logger below.
   3.437  
   3.438  
   3.439 -SYSTEM_PROPERTY: -Dnashorn.fields.debug
   3.440 +SYSTEM PROPERTY: -Dnashorn.fields.objects
   3.441  
   3.442 -See the description on the fields logger below.
   3.443 +When this property is true, Nashorn will only use object fields for
   3.444 +AccessorProperties. This means that primitive values must be boxed
   3.445 +when stored in a field, which is significantly slower than using
   3.446 +primitive fields.
   3.447  
   3.448 -
   3.449 -SYSTEM PROPERTY: -Dnashorn.fields.dual
   3.450 -
   3.451 -When this property is true, Nashorn will attempt to use primitive
   3.452 -fields for AccessorProperties (currently just AccessorProperties, not
   3.453 -spill properties). Memory footprint for script objects will increase,
   3.454 -as we need to maintain both a primitive field (a long) as well as an
   3.455 -Object field for the property value. Ints are represented as the 32
   3.456 -low bits of the long fields. Doubles are represented as the
   3.457 -doubleToLongBits of their value. This way a single field can be used
   3.458 -for all primitive types. Packing and unpacking doubles to their bit
   3.459 -representation is intrinsified by the JVM and extremely fast.
   3.460 -
   3.461 -While dual fields in theory runs significantly faster than Object
   3.462 -fields due to reduction of boxing and memory allocation overhead,
   3.463 -there is still work to be done to make this a general purpose
   3.464 -solution. Research is ongoing.
   3.465 +By default, Nashorn uses dual object and long fields. Ints are
   3.466 +represented as the 32 low bits of the long fields. Doubles are
   3.467 +represented as the doubleToLongBits of their value. This way a
   3.468 +single field can be used for all primitive types. Packing and
   3.469 +unpacking doubles to their bit representation is intrinsified by
   3.470 +the JVM and extremely fast.
   3.471  
   3.472  In the future, this might complement or be replaced by experimental
   3.473  feature sun.misc.TaggedArray, which has been discussed on the mlvm
   3.474  mailing list. TaggedArrays are basically a way to share data space
   3.475  between primitives and references, and have the GC understand this.
   3.476  
   3.477 -As long as only primitive values are written to the fields and enough
   3.478 -type information exists to make sure that any reads don't have to be
   3.479 -uselessly boxed and unboxed, this is significantly faster than the
   3.480 -standard "Objects only" approach that currently is the default. See
   3.481 -test/examples/dual-fields-micro.js for an example that runs twice as
   3.482 -fast with dual fields as without them. Here, the compiler, can
   3.483 -determine that we are dealing with numbers only throughout the entire
   3.484 -property life span of the properties involved.
   3.485 -
   3.486 -If a "real" object (not a boxed primitive) is written to a field that
   3.487 -has a primitive representation, its callsite is relinked and an Object
   3.488 -field is used forevermore for that particular field in that
   3.489 -PropertyMap and its children, even if primitives are later assigned to
   3.490 -it.
   3.491 -
   3.492 -As the amount of compile time type information is very small in a
   3.493 -dynamic language like JavaScript, it is frequently the case that
   3.494 -something has to be treated as an object, because we don't know any
   3.495 -better. In reality though, it is often a boxed primitive is stored to
   3.496 -an AccessorProperty. The fastest way to handle this soundly is to use
   3.497 -a callsite typecheck and avoid blowing the field up to an Object. We
   3.498 -never revert object fields to primitives. Ping-pong:ing back and forth
   3.499 -between primitive representation and Object representation would cause
   3.500 -fatal performance overhead, so this is not an option.
   3.501 -
   3.502 -For a general application the dual fields approach is still slower
   3.503 -than objects only fields in some places, about the same in most cases,
   3.504 -and significantly faster in very few. This is due the program using
   3.505 -primitives, but we still can't prove it. For example "local_var a =
   3.506 -call(); field = a;" may very well write a double to the field, but the
   3.507 -compiler dare not guess a double type if field is a local variable,
   3.508 -due to bytecode variables being strongly typed and later non
   3.509 -interchangeable. To get around this, the entire method would have to
   3.510 -be replaced and a continuation retained to restart from. We believe
   3.511 -that the next steps we should go through are instead:
   3.512 -
   3.513 -1) Implement method specialization based on callsite, as it's quite
   3.514 -frequently the case that numbers are passed around, but currently our
   3.515 -function nodes just have object types visible to the compiler. For
   3.516 -example "var b = 17; func(a,b,17)" is an example where two parameters
   3.517 -can be specialized, but the main version of func might also be called
   3.518 -from another callsite with func(x,y,"string").
   3.519 -
   3.520 -2) This requires lazy jitting as the functions have to be specialized
   3.521 -per callsite.
   3.522 -
   3.523 -Even though "function square(x) { return x*x }" might look like a
   3.524 -trivial function that can always only take doubles, this is not
   3.525 -true. Someone might have overridden the valueOf for x so that the
   3.526 -toNumber coercion has side effects. To fulfil JavaScript semantics,
   3.527 -the coercion has to run twice for both terms of the multiplication
   3.528 -even if they are the same object. This means that call site
   3.529 -specialization is necessary, not parameter specialization on the form
   3.530 -"function square(x) { var xd = (double)x; return xd*xd; }", as one
   3.531 -might first think.
   3.532 -
   3.533 -Generating a method specialization for any variant of a function that
   3.534 -we can determine by types at compile time is a combinatorial explosion
   3.535 -of byte code (try it e.g. on all the variants of am3 in the Octane
   3.536 -benchmark crypto.js). Thus, this needs to be lazy
   3.537 -
   3.538 -3) Optimistic callsite writes, something on the form
   3.539 -
   3.540 -x = y; //x is a field known to be a primitive. y is only an object as
   3.541 -far as we can tell
   3.542 -
   3.543 -turns into
   3.544 -
   3.545 -try {
   3.546 -  x = (int)y;
   3.547 -} catch (X is not an integer field right now | ClassCastException e) {
   3.548 -  x = y;
   3.549 -}
   3.550 -
   3.551 -Mini POC shows that this is the key to a lot of dual field performance
   3.552 -in seemingly trivial micros where one unknown object, in reality
   3.553 -actually a primitive, foils it for us. Very common pattern. Once we
   3.554 -are "all primitives", dual fields runs a lot faster than Object fields
   3.555 -only.
   3.556 -
   3.557 -We still have to deal with objects vs primitives for local bytecode
   3.558 -slots, possibly through code copying and versioning.
   3.559 -
   3.560 -The Future:
   3.561 -
   3.562 -We expect the usefulness of dual fields to increase significantly
   3.563 -after the optimistic type system described in the section on 
   3.564 -integer arithmetic above is implemented.
   3.565 -
   3.566  
   3.567  SYSTEM PROPERTY: -Dnashorn.compiler.symbol.trace=[<x>[,*]], 
   3.568    -Dnashorn.compiler.symbol.stacktrace=[<x>[,*]]
   3.569 @@ -628,6 +141,9 @@
   3.570  "identical" - this method compares two script objects for reference
   3.571  equality. It is a == Java comparison
   3.572  
   3.573 +"equals" - Returns true if two objects are either referentially
   3.574 +identical or equal as defined by java.lang.Object.equals.
   3.575 +
   3.576  "dumpCounters" - will dump the debug counters' current values to
   3.577  stdout.
   3.578  
   3.579 @@ -648,66 +164,66 @@
   3.580  when a callsite has to be relinked, due to a previous assumption of
   3.581  object layout being invalidated.
   3.582  
   3.583 +"getContext" - return the current Nashorn context.
   3.584  
   3.585 -SYSTEM PROPERTY: -Dnashorn.methodhandles.debug,
   3.586 --Dnashorn.methodhandles.debug=create
   3.587 +"equalWithoutType" - Returns true if if the two objects are both
   3.588 +property maps, and they have identical properties in the same order,
   3.589 +but allows the properties to differ in their types.
   3.590  
   3.591 -If this property is enabled, each MethodHandle related call that uses
   3.592 -the java.lang.invoke package gets its MethodHandle intercepted and an
   3.593 -instrumentation printout of arguments and return value appended to
   3.594 -it. This shows exactly which method handles are executed and from
   3.595 -where. (Also MethodTypes and SwitchPoints). This can be augmented with
   3.596 -more information, for example, instance count, by subclassing or
   3.597 -further extending the TraceMethodHandleFactory implementation in
   3.598 -MethodHandleFactory.java.
   3.599 +"diffPropertyMaps" Returns a diagnostic string representing the difference
   3.600 +of two property maps.
   3.601  
   3.602 -If the property is specialized with "=create" as its option,
   3.603 -instrumentation will be shown for method handles upon creation time
   3.604 -rather than at runtime usage.
   3.605 +"getClass" - Returns the Java class of an object, or undefined if null.
   3.606 +
   3.607 +"toJavaString" - Returns the Java toString representation of an object.
   3.608 +
   3.609 +"toIdentString" - Returns a string representation of an object consisting
   3.610 +of its java class name and hash code.
   3.611 +
   3.612 +"getListenerCount" - Return the number of property listeners for a
   3.613 +script object.
   3.614 +
   3.615 +"getEventQueueCapacity" - Get the capacity of the event queue.
   3.616 +
   3.617 +"setEventQueueCapacity" - Set the event queue capacity.
   3.618 +
   3.619 +"addRuntimeEvent" - Add a runtime event to the runtime event queue.
   3.620 +The queue has a fixed size (see -Dnashorn.runtime.event.queue.size)
   3.621 +and the oldest entry will be thrown out of the queue is about to overflow.
   3.622 +
   3.623 +"expandEventQueueCapacity" - Expands the event queue capacity,
   3.624 +or truncates if capacity is lower than current capacity. Then only
   3.625 +the newest entries are kept.
   3.626 +
   3.627 +"clearRuntimeEvents" - Clear the runtime event queue.
   3.628 +
   3.629 +"removeRuntimeEvent" - Remove a specific runtime event from the event queue.
   3.630 +
   3.631 +"getRuntimeEvents" - Return all runtime events in the queue as an array.
   3.632 +
   3.633 +"getLastRuntimeEvent" - Return the last runtime event in the queue.
   3.634  
   3.635  
   3.636  SYSTEM PROPERTY: -Dnashorn.methodhandles.debug.stacktrace
   3.637  
   3.638 -This does the same as nashorn.methodhandles.debug, but when enabled
   3.639 -also dumps the stack trace for every instrumented method handle
   3.640 -operation. Warning: This is enormously verbose, but provides a pretty
   3.641 +This enhances methodhandles logging (see below) to also dump the
   3.642 +stack trace for every instrumented method handle operation.
   3.643 +Warning: This is enormously verbose, but provides a pretty
   3.644  decent "grep:able" picture of where the calls are coming from.
   3.645  
   3.646 -See the description of the codegen logger below for a more verbose
   3.647 -description of this option
   3.648  
   3.649 +SYSTEM PROPERTY: -Dnashorn.cce
   3.650  
   3.651 -SYSTEM PROPERTY: -Dnashorn.scriptfunction.specialization.disable
   3.652 +Setting this system property causes the Nashorn linker to rely on
   3.653 +ClassCastExceptions for triggering a callsite relink. If not set, the linker
   3.654 +will add an explicit instanceof guard.
   3.655  
   3.656 -There are several "fast path" implementations of constructors and
   3.657 -functions in the NativeObject classes that, in their original form,
   3.658 -take a variable amount of arguments. Said functions are also declared
   3.659 -to take Object parameters in their original form, as this is what the
   3.660 -JavaScript specification mandates.
   3.661 -However, we often know quite a lot more at a callsite of one of these
   3.662 -functions. For example, Math.min is called with a fixed number (2) of
   3.663 -integer arguments. The overhead of boxing these ints to Objects and
   3.664 -folding them into an Object array for the generic varargs Math.min
   3.665 -function is an order of magnitude slower than calling a specialized
   3.666 -implementation of Math.min that takes two integers. Specialized
   3.667 -functions and constructors are identified by the tag
   3.668 -@SpecializedFunction and @SpecializedConstructor in the Nashorn
   3.669 -code. The linker will link in the most appropriate (narrowest types,
   3.670 -right number of types and least number of arguments) specialization if
   3.671 -specializations are available.
   3.672  
   3.673 -Every ScriptFunction may carry specializations that the linker can
   3.674 -choose from. This framework will likely be extended for user defined
   3.675 -functions. The compiler can often infer enough parameter type info
   3.676 -from callsites for in order to generate simpler versions with less
   3.677 -generic Object types. This feature depends on future lazy jitting, as
   3.678 -there tend to be many calls to user defined functions, some where the
   3.679 -callsite can be specialized, some where we mostly see object
   3.680 -parameters even at the callsite.
   3.681 +SYSTEM PROPERTY: -Dnashorn.spill.threshold=<x>
   3.682  
   3.683 -If this system property is set to true, the linker will not attempt to
   3.684 -use any specialized function or constructor for native objects, but
   3.685 -just call the generic one.
   3.686 +This property sets the number of fields in an object from which to use
   3.687 +generic array based spill storage instead of Java fields. The default value
   3.688 +is 256.
   3.689  
   3.690  
   3.691  SYSTEM PROPERTY: -Dnashorn.tcs.miss.samplePercent=<x>
   3.692 @@ -719,8 +235,47 @@
   3.693  should be logged. Typically this is set to 1 or 5 (percent). 1% is the
   3.694  default value.
   3.695  
   3.696 +SYSTEM PROPERTY: -Dnashorn.persistent.code.cache
   3.697  
   3.698 -SYSTEM_PROPERTY: -Dnashorn.profilefile=<filename>
   3.699 +This property can be used to set the directory where Nashorn stores
   3.700 +serialized script classes generated with the -pcc/--persistent-code-cache
   3.701 +option. The default directory name is "nashorn_code_cache".
   3.702 +
   3.703 +
   3.704 +SYSTEM PROPERTY: -Dnashorn.typeInfo.maxFiles
   3.705 +
   3.706 +Maximum number of files to store in the type info cache. The type info cache
   3.707 +is used to cache type data of JavaScript functions when running with
   3.708 +optimistic types (-ot/--optimistic-types). There is one file per JavaScript
   3.709 +function in the cache.
   3.710 +
   3.711 +The default value is 0 which means the feature is disabled. Setting this
   3.712 +to something like 20000 is probably good enough for most applications and
   3.713 +will usually cap the cache directory to about 80MB presuming a 4kB
   3.714 +filesystem allocation unit. Set this to "unlimited" to run without limit.
   3.715 +
   3.716 +If the value is not 0 or "unlimited", Nashorn will spawn a cleanup thread
   3.717 +that makes sure the number of files in the cache does not exceed the given
   3.718 +value by deleting the least recently modified files.
   3.719 +
   3.720 +
   3.721 +SYSTEM PROPERTY: -Dnashorn.typeInfo.cacheDir
   3.722 +
   3.723 +This property can be used to set the directory where Nashorn stores the
   3.724 +type info cache when -Dnashorn.typeInfo.maxFiles is set to a nonzero
   3.725 +value. The default location is platform specific. On Windows, it is
   3.726 +"${java.io.tmpdir}\com.oracle.java.NashornTypeInfo". On Linux and
   3.727 +Solaris it is "~/.cache/com.oracle.java.NashornTypeInfo". On Mac OS X,
   3.728 +it is "~/Library/Caches/com.oracle.java.NashornTypeInfo".
   3.729 +
   3.730 +
   3.731 +SYSTEM PROPERTY: -Dnashorn.typeInfo.cleanupDelaySeconds=<value>
   3.732 +
   3.733 +This sets the delay between cleanups of the typeInfo cache, in seconds.
   3.734 +The default delay is 20 seconds.
   3.735 +
   3.736 +
   3.737 +SYSTEM PROPERTY: -Dnashorn.profilefile=<filename>
   3.738  
   3.739  When running with the profile callsite options (-pcs), Nashorn will
   3.740  dump profiling data for all callsites to stderr as a shutdown hook. To
   3.741 @@ -736,6 +291,11 @@
   3.742  an implementation based on Joni, the regular expression engine used by
   3.743  the JRuby project. The default value for this flag is "joni"
   3.744  
   3.745 +SYSTEM PROPERTY: -Dnashorn.runtime.event.queue.size=<value>
   3.746 +
   3.747 +Nashorn provides a fixed sized runtime event queue for debugging purposes.
   3.748 +See -Dnashorn.debug for methods to access the event queue.
   3.749 +The default value is 1024.
   3.750  
   3.751  ===============
   3.752  2. The loggers.
   3.753 @@ -767,7 +327,9 @@
   3.754  For example: --log=codegen,fields:finest is equivalent to
   3.755  --log=codegen:info --log=fields:finest
   3.756  
   3.757 -The subsystems that currently support logging are:
   3.758 +The following is an incomplete list of subsystems that currently
   3.759 +support logging. Look for classes implementing
   3.760 +jdk.nashorn.internal.runtime.logging.Loggable for more loggers.
   3.761  
   3.762  
   3.763  * compiler
   3.764 @@ -780,6 +342,14 @@
   3.765  use.s
   3.766  
   3.767  
   3.768 +* recompile
   3.769 +
   3.770 +This logger shows information about recompilation of scripts and
   3.771 +functions at runtime. Recompilation may happen because a function
   3.772 +was called with different parameter types, or because an optimistic
   3.773 +assumption failed while executing a function with -ot/--optimistic-types.
   3.774 +
   3.775 +
   3.776  * codegen
   3.777  
   3.778  The code generator is the emitter stage of the code pipeline, and
   3.779 @@ -836,25 +406,13 @@
   3.780  Lower is also responsible for determining control flow information
   3.781  like end points.
   3.782  
   3.783 +* symbols
   3.784  
   3.785 -* attr
   3.786 +The symbols logger tracks the assignment os symbols to identifiers.
   3.787  
   3.788 -The lowering annotates a FunctionNode with symbols for each identifier
   3.789 -and transforms high level constructs into lower level ones, that the
   3.790 -CodeGenerator consumes.
   3.791 +* scopedepths
   3.792  
   3.793 -Lower logging typically outputs things like post pass actions,
   3.794 -insertions of casts because symbol types have been changed and type
   3.795 -specialization information. Currently very little info is generated by
   3.796 -this logger. This will probably change.
   3.797 -
   3.798 -
   3.799 -* finalize
   3.800 -
   3.801 -This --log=finalize log option outputs information for type finalization,
   3.802 -the third tier of the compiler. This means things like placement of 
   3.803 -specialized scope nodes or explicit conversions. 
   3.804 -
   3.805 +This logs the calculation of scope depths for non-local symbols.
   3.806  
   3.807  * fields
   3.808  
   3.809 @@ -896,6 +454,21 @@
   3.810  [time] 
   3.811  [time] Total runtime: 11994 ms (Non-runtime: 11027 ms [91%])
   3.812  
   3.813 +* methodhandles
   3.814 +
   3.815 +If this logger is enabled, each MethodHandle related call that uses
   3.816 +the java.lang.invoke package gets its MethodHandle intercepted and an
   3.817 +instrumentation printout of arguments and return value appended to
   3.818 +it. This shows exactly which method handles are executed and from
   3.819 +where. (Also MethodTypes and SwitchPoints).
   3.820 +
   3.821 +* classcache
   3.822 +
   3.823 +This logger shows information about reusing code classes using the
   3.824 +in-memory class cache. Nashorn will try to avoid compilation of
   3.825 +scripts by using existing classes. This can significantly improve
   3.826 +performance when repeatedly evaluating the same script.
   3.827 +
   3.828  =======================
   3.829  3. Undocumented options
   3.830  =======================
     4.1 --- a/make/build-nasgen.xml	Mon Oct 27 14:36:13 2014 -0700
     4.2 +++ b/make/build-nasgen.xml	Thu Nov 06 09:50:15 2014 -0800
     4.3 @@ -25,7 +25,7 @@
     4.4      <description>Builds and runs nasgen.</description>
     4.5      <import file="build.xml"/>
     4.6  
     4.7 -    <target name="build-nasgen" depends="compile-asm">
     4.8 +    <target name="build-nasgen" depends="prepare">
     4.9          <ant inheritAll="false" dir="${basedir}/buildtools/nasgen"
    4.10              antfile="build.xml" target="jar"/>
    4.11      </target>
     5.1 --- a/make/build.xml	Mon Oct 27 14:36:13 2014 -0700
     5.2 +++ b/make/build.xml	Thu Nov 06 09:50:15 2014 -0800
     5.3 @@ -49,8 +49,6 @@
     5.4      <condition property="git.executable" value="/usr/local/bin/git" else="git">
     5.5        <available file="/usr/local/bin/git"/>
     5.6      </condition>
     5.7 -    <!-- check if JDK already has ASM classes -->
     5.8 -    <available property="asm.available" classname="jdk.internal.org.objectweb.asm.Type"/>
     5.9      <!-- check if testng.jar is avaiable -->
    5.10      <available property="testng.available" file="${file.reference.testng.jar}"/>
    5.11      <!-- check if Jemmy ang testng.jar are avaiable -->
    5.12 @@ -78,8 +76,31 @@
    5.13        <istrue value="${jfr}"/>
    5.14      </condition>
    5.15    </target>
    5.16 +
    5.17 +  <!-- check minimum ant version required to be 1.8.4 -->
    5.18 +  <target name="check-ant-version">
    5.19 +    <property name="ant.version.required" value="1.8.4"/>
    5.20 +    <antversion property="ant.current.version" />
    5.21 +    <fail message="The current ant version, ${ant.current.version}, is too old. Please use 1.8.4 or above.">
    5.22 +        <condition>
    5.23 +            <not>
    5.24 +                <antversion atleast="${ant.version.required}"/>
    5.25 +            </not>
    5.26 +        </condition>
    5.27 +    </fail>
    5.28 +  </target>
    5.29 +
    5.30 +  <target name="check-java-version">
    5.31 +    <!-- look for a Class that is available only in jdk1.8 or above -->
    5.32 +    <!-- core/exposed API class is better than an implementation class -->
    5.33 +    <available property="jdk1.8+" classname="java.util.stream.Stream"/>
    5.34 +
    5.35 +    <!-- need jdk1.8 or above -->
    5.36 +    <fail message="Unsupported Java version: ${ant.java.version}. Please use Java version 1.8 or greater." unless="jdk1.8+">
    5.37 +    </fail>
    5.38 +  </target>
    5.39    
    5.40 -  <target name="init" depends="init-conditions, init-cc">
    5.41 +  <target name="init" depends="check-ant-version, check-java-version, init-conditions, init-cc">
    5.42      <!-- extends jvm args -->
    5.43      <property name="run.test.jvmargs" value="${run.test.jvmargs.main} ${run.test.cc.jvmargs} ${jfr.options}"/>
    5.44      <property name="run.test.jvmargs.octane" value="${run.test.jvmargs.octane.main} ${run.test.cc.jvmargs} ${jfr.options}"/>
    5.45 @@ -107,19 +128,7 @@
    5.46      <delete dir="${dist.dir}"/>
    5.47    </target>
    5.48  
    5.49 -  <!-- do it only if ASM is not available -->
    5.50 -  <target name="compile-asm" depends="prepare" unless="asm.available">
    5.51 -    <javac srcdir="${jdk.asm.src.dir}"
    5.52 -           destdir="${build.classes.dir}"
    5.53 -           excludes="**/optimizer/* **/xml/* **/attrs/*"
    5.54 -           source="${javac.source}"
    5.55 -           target="${javac.target}"
    5.56 -           debug="${javac.debug}"
    5.57 -           encoding="${javac.encoding}"
    5.58 -           includeantruntime="false"/>
    5.59 -  </target>
    5.60 -
    5.61 -  <target name="compile" depends="compile-asm" description="Compiles nashorn">
    5.62 +  <target name="compile" depends="prepare" description="Compiles nashorn">
    5.63      <javac srcdir="${src.dir}"
    5.64             destdir="${build.classes.dir}"
    5.65             classpath="${javac.classpath}"
    5.66 @@ -407,7 +416,7 @@
    5.67      <fileset id="test.nosecurity.classes" dir="${build.test.classes.dir}">
    5.68        <include name="**/framework/ScriptTest.class"/>
    5.69      </fileset>
    5.70 -    <testng outputdir="${build.nosecurity.test.results.dir}" classfilesetref="test.nosecurity.classes"
    5.71 +    <testng outputdir="${build.nosecurity.test.results.dir}/${testResultsSubDir}" classfilesetref="test.nosecurity.classes"
    5.72         verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
    5.73        <jvmarg line="${ext.class.path}"/>
    5.74        <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} -Dbuild.dir=${build.dir}"/>
    5.75 @@ -430,7 +439,7 @@
    5.76    <target name="-test-security">
    5.77      <delete dir="${build.dir}/nashorn_code_cache"/>
    5.78      <property name="debug.test.jvmargs" value=""/>
    5.79 -    <testng outputdir="${build.test.results.dir}" classfilesetref="test.classes"
    5.80 +    <testng outputdir="${build.test.results.dir}/${testResultsSubDir}" classfilesetref="test.classes"
    5.81  	    verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
    5.82        <jvmarg line="${ext.class.path}"/>
    5.83        <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
    5.84 @@ -456,9 +465,11 @@
    5.85      <echo message="Running test suite in OPTIMISTIC mode..."/>
    5.86      <antcall target="-test-nosecurity" inheritRefs="true">
    5.87        <param name="optimistic" value="true"/>
    5.88 +      <param name="testResultsSubDir" value="optimistic"/>
    5.89      </antcall>    
    5.90      <antcall target="-test-security" inheritRefs="true">
    5.91        <param name="optimistic" value="true"/>
    5.92 +      <param name="testResultsSubDir" value="optimistic"/>
    5.93      </antcall>
    5.94    </target>
    5.95  
    5.96 @@ -466,9 +477,11 @@
    5.97      <echo message="Running test suite in PESSIMISTIC mode..."/>
    5.98      <antcall target="-test-nosecurity" inheritRefs="true">
    5.99        <param name="optimistic" value="false"/>
   5.100 +      <param name="testResultsSubDir" value="pessimistic"/>
   5.101      </antcall>    
   5.102      <antcall target="-test-security" inheritRefs="true">
   5.103        <param name="optimistic" value="false"/>
   5.104 +      <param name="testResultsSubDir" value="pessimistic"/>
   5.105      </antcall>
   5.106    </target>
   5.107  
     6.1 --- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Mon Oct 27 14:36:13 2014 -0700
     6.2 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Thu Nov 06 09:50:15 2014 -0800
     6.3 @@ -229,6 +229,8 @@
     6.4      }
     6.5  
     6.6      private <T> T getInterfaceInner(final Object thiz, final Class<T> clazz) {
     6.7 +        assert !(thiz instanceof ScriptObject) : "raw ScriptObject not expected here";
     6.8 +
     6.9          if (clazz == null || !clazz.isInterface()) {
    6.10              throw new IllegalArgumentException(getMessage("interface.class.expected"));
    6.11          }
    6.12 @@ -254,17 +256,6 @@
    6.13              if (! isOfContext(realGlobal, nashornContext)) {
    6.14                  throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
    6.15              }
    6.16 -        } else if (thiz instanceof ScriptObject) {
    6.17 -            // called from script code.
    6.18 -            realSelf = (ScriptObject)thiz;
    6.19 -            realGlobal = Context.getGlobal();
    6.20 -            if (realGlobal == null) {
    6.21 -                throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
    6.22 -            }
    6.23 -
    6.24 -            if (! isOfContext(realGlobal, nashornContext)) {
    6.25 -                throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
    6.26 -            }
    6.27          }
    6.28  
    6.29          if (realSelf == null) {
    6.30 @@ -368,6 +359,7 @@
    6.31  
    6.32      private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
    6.33          name.getClass(); // null check
    6.34 +        assert !(selfObject instanceof ScriptObject) : "raw ScriptObject not expected here";
    6.35  
    6.36          Global invokeGlobal = null;
    6.37          ScriptObjectMirror selfMirror = null;
    6.38 @@ -377,20 +369,6 @@
    6.39                  throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
    6.40              }
    6.41              invokeGlobal = selfMirror.getHomeGlobal();
    6.42 -        } else if (selfObject instanceof ScriptObject) {
    6.43 -            // invokeMethod called from script code - in which case we may get 'naked' ScriptObject
    6.44 -            // Wrap it with oldGlobal to make a ScriptObjectMirror for the same.
    6.45 -            final Global oldGlobal = Context.getGlobal();
    6.46 -            invokeGlobal = oldGlobal;
    6.47 -            if (oldGlobal == null) {
    6.48 -                throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
    6.49 -            }
    6.50 -
    6.51 -            if (! isOfContext(oldGlobal, nashornContext)) {
    6.52 -                throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
    6.53 -            }
    6.54 -
    6.55 -            selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(selfObject, oldGlobal);
    6.56          } else if (selfObject == null) {
    6.57              // selfObject is null => global function call
    6.58              final Global ctxtGlobal = getNashornGlobalFrom(context);
     7.1 --- a/src/jdk/nashorn/api/scripting/ScriptUtils.java	Mon Oct 27 14:36:13 2014 -0700
     7.2 +++ b/src/jdk/nashorn/api/scripting/ScriptUtils.java	Thu Nov 06 09:50:15 2014 -0800
     7.3 @@ -75,11 +75,8 @@
     7.4       * @param sync the object to synchronize on
     7.5       * @return a synchronizing wrapper function
     7.6       */
     7.7 -    public static Object makeSynchronizedFunction(final Object func, final Object sync) {
     7.8 -        if (func instanceof ScriptFunction) {
     7.9 -           return ((ScriptFunction)func).makeSynchronizedFunction(sync);
    7.10 -        }
    7.11 -        throw typeError("not.a.function", ScriptRuntime.safeToString(func));
    7.12 +    public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) {
    7.13 +        return func.makeSynchronizedFunction(unwrap(sync));
    7.14      }
    7.15  
    7.16      /**
    7.17 @@ -88,12 +85,8 @@
    7.18       * @param obj object to be wrapped
    7.19       * @return wrapped object
    7.20       */
    7.21 -    public static Object wrap(final Object obj) {
    7.22 -        if (obj instanceof ScriptObject) {
    7.23 -            return ScriptObjectMirror.wrap(obj, Context.getGlobal());
    7.24 -        }
    7.25 -
    7.26 -        return obj;
    7.27 +    public static ScriptObjectMirror wrap(final ScriptObject obj) {
    7.28 +        return (ScriptObjectMirror) ScriptObjectMirror.wrap(obj, Context.getGlobal());
    7.29      }
    7.30  
    7.31      /**
    7.32 @@ -160,14 +153,15 @@
    7.33          }
    7.34  
    7.35          final LinkerServices linker = Bootstrap.getLinkerServices();
    7.36 -        final MethodHandle converter = linker.getTypeConverter(obj.getClass(),  clazz);
    7.37 +        final Object objToConvert = unwrap(obj);
    7.38 +        final MethodHandle converter = linker.getTypeConverter(objToConvert.getClass(),  clazz);
    7.39          if (converter == null) {
    7.40              // no supported conversion!
    7.41              throw new UnsupportedOperationException("conversion not supported");
    7.42          }
    7.43  
    7.44          try {
    7.45 -            return converter.invoke(obj);
    7.46 +            return converter.invoke(objToConvert);
    7.47          } catch (final RuntimeException | Error e) {
    7.48              throw e;
    7.49          } catch (final Throwable t) {
     8.1 --- a/src/jdk/nashorn/internal/codegen/ApplySpecialization.java	Mon Oct 27 14:36:13 2014 -0700
     8.2 +++ b/src/jdk/nashorn/internal/codegen/ApplySpecialization.java	Thu Nov 06 09:50:15 2014 -0800
     8.3 @@ -27,6 +27,7 @@
     8.4  
     8.5  import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR;
     8.6  import static jdk.nashorn.internal.codegen.CompilerConstants.EXPLODED_ARGUMENT_PREFIX;
     8.7 +
     8.8  import java.lang.invoke.MethodType;
     8.9  import java.util.ArrayDeque;
    8.10  import java.util.ArrayList;
    8.11 @@ -38,6 +39,7 @@
    8.12  import jdk.nashorn.internal.ir.CallNode;
    8.13  import jdk.nashorn.internal.ir.Expression;
    8.14  import jdk.nashorn.internal.ir.FunctionNode;
    8.15 +import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
    8.16  import jdk.nashorn.internal.ir.IdentNode;
    8.17  import jdk.nashorn.internal.ir.LexicalContext;
    8.18  import jdk.nashorn.internal.ir.Node;
    8.19 @@ -321,7 +323,7 @@
    8.20  
    8.21          explodedArguments.pop();
    8.22  
    8.23 -        return newFunctionNode;
    8.24 +        return newFunctionNode.setState(lc, CompilationState.BUILTINS_TRANSFORMED);
    8.25      }
    8.26  
    8.27      private static boolean isApply(final CallNode callNode) {
     9.1 --- a/src/jdk/nashorn/internal/codegen/AssignSymbols.java	Mon Oct 27 14:36:13 2014 -0700
     9.2 +++ b/src/jdk/nashorn/internal/codegen/AssignSymbols.java	Thu Nov 06 09:50:15 2014 -0800
     9.3 @@ -76,7 +76,6 @@
     9.4  import jdk.nashorn.internal.ir.Node;
     9.5  import jdk.nashorn.internal.ir.RuntimeNode;
     9.6  import jdk.nashorn.internal.ir.RuntimeNode.Request;
     9.7 -import jdk.nashorn.internal.ir.SplitNode;
     9.8  import jdk.nashorn.internal.ir.Statement;
     9.9  import jdk.nashorn.internal.ir.SwitchNode;
    9.10  import jdk.nashorn.internal.ir.Symbol;
    9.11 @@ -135,9 +134,6 @@
    9.12          if (!(functionNode.hasScopeBlock() || functionNode.needsParentScope())) {
    9.13              functionNode.compilerConstant(SCOPE).setNeedsSlot(false);
    9.14          }
    9.15 -        if (!functionNode.usesReturnSymbol()) {
    9.16 -            functionNode.compilerConstant(RETURN).setNeedsSlot(false);
    9.17 -        }
    9.18          // Named function expressions that end up not referencing themselves won't need a local slot for the self symbol.
    9.19          if(!functionNode.isDeclared() && !functionNode.usesSelfSymbol() && !functionNode.isAnonymous()) {
    9.20              final Symbol selfSymbol = functionNode.getBody().getExistingSymbol(functionNode.getIdent().getName());
    9.21 @@ -511,16 +507,6 @@
    9.22  
    9.23          thisProperties.push(new HashSet<String>());
    9.24  
    9.25 -        if (functionNode.isDeclared()) {
    9.26 -            // Can't use lc.getCurrentBlock() as we can have an outermost function in our lexical context that
    9.27 -            // is not a program - it is a function being compiled on-demand.
    9.28 -            final Iterator<Block> blocks = lc.getBlocks();
    9.29 -            if (blocks.hasNext()) {
    9.30 -                final IdentNode ident = functionNode.getIdent();
    9.31 -                defineSymbol(blocks.next(), ident.getName(), ident, IS_VAR | (functionNode.isAnonymous()? IS_INTERNAL : 0));
    9.32 -            }
    9.33 -        }
    9.34 -
    9.35          // Every function has a body, even the ones skipped on reparse (they have an empty one). We're
    9.36          // asserting this as even for those, enterBlock() must be invoked to correctly process symbols that
    9.37          // are used in them.
    9.38 @@ -532,14 +518,34 @@
    9.39      @Override
    9.40      public boolean enterVarNode(final VarNode varNode) {
    9.41          start(varNode);
    9.42 +        // Normally, a symbol assigned in a var statement is not live for its RHS. Since we also represent function
    9.43 +        // declarations as VarNodes, they are exception to the rule, as they need to have the symbol visible to the
    9.44 +        // body of the declared function for self-reference.
    9.45 +        if (varNode.isFunctionDeclaration()) {
    9.46 +            defineVarIdent(varNode);
    9.47 +        }
    9.48          return true;
    9.49      }
    9.50  
    9.51      @Override
    9.52      public Node leaveVarNode(final VarNode varNode) {
    9.53 +        if (!varNode.isFunctionDeclaration()) {
    9.54 +            defineVarIdent(varNode);
    9.55 +        }
    9.56 +        return super.leaveVarNode(varNode);
    9.57 +    }
    9.58 +
    9.59 +    private void defineVarIdent(final VarNode varNode) {
    9.60          final IdentNode ident = varNode.getName();
    9.61 -        defineSymbol(lc.getCurrentBlock(), ident.getName(), ident, varNode.getSymbolFlags() | (lc.getCurrentFunction().isProgram() ? IS_SCOPE : 0));
    9.62 -        return super.leaveVarNode(varNode);
    9.63 +        final int flags;
    9.64 +        if (varNode.isAnonymousFunctionDeclaration()) {
    9.65 +            flags = IS_INTERNAL;
    9.66 +        } else if (lc.getCurrentFunction().isProgram()) {
    9.67 +            flags = IS_SCOPE;
    9.68 +        } else {
    9.69 +            flags = 0;
    9.70 +        }
    9.71 +        defineSymbol(lc.getCurrentBlock(), ident.getName(), ident, varNode.getSymbolFlags() | flags);
    9.72      }
    9.73  
    9.74      private Symbol exceptionSymbol() {
    9.75 @@ -1004,7 +1010,7 @@
    9.76          boolean previousWasBlock = false;
    9.77          for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
    9.78              final LexicalContextNode node = it.next();
    9.79 -            if (node instanceof FunctionNode || node instanceof SplitNode || isSplitArray(node)) {
    9.80 +            if (node instanceof FunctionNode || isSplitArray(node)) {
    9.81                  // We reached the function boundary or a splitting boundary without seeing a definition for the symbol.
    9.82                  // It needs to be in scope.
    9.83                  return true;
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/jdk/nashorn/internal/codegen/AstSerializer.java	Thu Nov 06 09:50:15 2014 -0800
    10.3 @@ -0,0 +1,71 @@
    10.4 +/*
    10.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
    10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.7 + *
    10.8 + * This code is free software; you can redistribute it and/or modify it
    10.9 + * under the terms of the GNU General Public License version 2 only, as
   10.10 + * published by the Free Software Foundation.  Oracle designates this
   10.11 + * particular file as subject to the "Classpath" exception as provided
   10.12 + * by Oracle in the LICENSE file that accompanied this code.
   10.13 + *
   10.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   10.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   10.17 + * version 2 for more details (a copy is included in the LICENSE file that
   10.18 + * accompanied this code).
   10.19 + *
   10.20 + * You should have received a copy of the GNU General Public License version
   10.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   10.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   10.23 + *
   10.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   10.25 + * or visit www.oracle.com if you need additional information or have any
   10.26 + * questions.
   10.27 + */
   10.28 +package jdk.nashorn.internal.codegen;
   10.29 +
   10.30 +import java.io.ByteArrayOutputStream;
   10.31 +import java.io.IOException;
   10.32 +import java.io.ObjectOutputStream;
   10.33 +import java.util.Collections;
   10.34 +import java.util.zip.Deflater;
   10.35 +import java.util.zip.DeflaterOutputStream;
   10.36 +import jdk.nashorn.internal.ir.Block;
   10.37 +import jdk.nashorn.internal.ir.FunctionNode;
   10.38 +import jdk.nashorn.internal.ir.LexicalContext;
   10.39 +import jdk.nashorn.internal.ir.Node;
   10.40 +import jdk.nashorn.internal.ir.Statement;
   10.41 +import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   10.42 +import jdk.nashorn.internal.runtime.options.Options;
   10.43 +
   10.44 +/**
   10.45 + * This static utility class performs serialization of FunctionNode ASTs to a byte array.
   10.46 + * The format is a standard Java serialization stream, deflated.
   10.47 + */
   10.48 +final class AstSerializer {
   10.49 +    // Experimentally, we concluded that compression level 4 gives a good tradeoff between serialization speed
   10.50 +    // and size.
   10.51 +    private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4);
   10.52 +    static byte[] serialize(final FunctionNode fn) {
   10.53 +        final ByteArrayOutputStream out = new ByteArrayOutputStream();
   10.54 +        try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out,
   10.55 +                new Deflater(COMPRESSION_LEVEL)))) {
   10.56 +            oout.writeObject(removeInnerFunctionBodies(fn));
   10.57 +        } catch (final IOException e) {
   10.58 +            throw new AssertionError("Unexpected exception serializing function", e);
   10.59 +        }
   10.60 +        return out.toByteArray();
   10.61 +    }
   10.62 +
   10.63 +    private static FunctionNode removeInnerFunctionBodies(final FunctionNode fn) {
   10.64 +        return (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   10.65 +            @Override
   10.66 +            public Node leaveBlock(final Block block) {
   10.67 +                if (lc.isFunctionBody() && lc.getFunction(block) != lc.getOutermostFunction()) {
   10.68 +                    return block.setStatements(lc, Collections.<Statement>emptyList());
   10.69 +                }
   10.70 +                return super.leaveBlock(block);
   10.71 +            }
   10.72 +        });
   10.73 +    }
   10.74 +}
    11.1 --- a/src/jdk/nashorn/internal/codegen/ClassEmitter.java	Mon Oct 27 14:36:13 2014 -0700
    11.2 +++ b/src/jdk/nashorn/internal/codegen/ClassEmitter.java	Thu Nov 06 09:50:15 2014 -0800
    11.3 @@ -51,6 +51,7 @@
    11.4  import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
    11.5  import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor;
    11.6  import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
    11.7 +
    11.8  import java.io.ByteArrayOutputStream;
    11.9  import java.io.PrintWriter;
   11.10  import java.security.AccessController;
   11.11 @@ -64,7 +65,6 @@
   11.12  import jdk.internal.org.objectweb.asm.util.TraceClassVisitor;
   11.13  import jdk.nashorn.internal.codegen.types.Type;
   11.14  import jdk.nashorn.internal.ir.FunctionNode;
   11.15 -import jdk.nashorn.internal.ir.SplitNode;
   11.16  import jdk.nashorn.internal.ir.debug.NashornClassReader;
   11.17  import jdk.nashorn.internal.ir.debug.NashornTextifier;
   11.18  import jdk.nashorn.internal.runtime.Context;
   11.19 @@ -476,12 +476,6 @@
   11.20          methodsStarted.remove(method);
   11.21      }
   11.22  
   11.23 -    SplitMethodEmitter method(final SplitNode splitNode, final String methodName, final Class<?> rtype, final Class<?>... ptypes) {
   11.24 -        methodCount++;
   11.25 -        methodNames.add(methodName);
   11.26 -        return new SplitMethodEmitter(this, methodVisitor(EnumSet.of(Flag.PUBLIC, Flag.STATIC), methodName, rtype, ptypes), splitNode);
   11.27 -    }
   11.28 -
   11.29      /**
   11.30       * Add a new method to the class - defaults to public method
   11.31       *
    12.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Mon Oct 27 14:36:13 2014 -0700
    12.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Nov 06 09:50:15 2014 -0800
    12.3 @@ -34,9 +34,7 @@
    12.4  import static jdk.nashorn.internal.codegen.CompilerConstants.GET_STRING;
    12.5  import static jdk.nashorn.internal.codegen.CompilerConstants.QUICK_PREFIX;
    12.6  import static jdk.nashorn.internal.codegen.CompilerConstants.REGEX_PREFIX;
    12.7 -import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
    12.8  import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
    12.9 -import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_ARRAY_ARG;
   12.10  import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_PREFIX;
   12.11  import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
   12.12  import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
   12.13 @@ -99,10 +97,10 @@
   12.14  import jdk.nashorn.internal.ir.ForNode;
   12.15  import jdk.nashorn.internal.ir.FunctionNode;
   12.16  import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
   12.17 +import jdk.nashorn.internal.ir.GetSplitState;
   12.18  import jdk.nashorn.internal.ir.IdentNode;
   12.19  import jdk.nashorn.internal.ir.IfNode;
   12.20  import jdk.nashorn.internal.ir.IndexNode;
   12.21 -import jdk.nashorn.internal.ir.JoinPredecessor;
   12.22  import jdk.nashorn.internal.ir.JoinPredecessorExpression;
   12.23  import jdk.nashorn.internal.ir.JumpStatement;
   12.24  import jdk.nashorn.internal.ir.LabelNode;
   12.25 @@ -121,7 +119,8 @@
   12.26  import jdk.nashorn.internal.ir.ReturnNode;
   12.27  import jdk.nashorn.internal.ir.RuntimeNode;
   12.28  import jdk.nashorn.internal.ir.RuntimeNode.Request;
   12.29 -import jdk.nashorn.internal.ir.SplitNode;
   12.30 +import jdk.nashorn.internal.ir.SetSplitState;
   12.31 +import jdk.nashorn.internal.ir.SplitReturn;
   12.32  import jdk.nashorn.internal.ir.Statement;
   12.33  import jdk.nashorn.internal.ir.SwitchNode;
   12.34  import jdk.nashorn.internal.ir.Symbol;
   12.35 @@ -209,6 +208,8 @@
   12.36      private static final Type ITERATOR_TYPE = Type.typeFor(ITERATOR_CLASS);
   12.37      private static final Type EXCEPTION_TYPE = Type.typeFor(CompilerConstants.EXCEPTION_PREFIX.type());
   12.38  
   12.39 +    private static final Integer INT_ZERO = Integer.valueOf(0);
   12.40 +
   12.41      /** Constant data & installation. The only reason the compiler keeps this is because it is assigned
   12.42       *  by reflection in class installation */
   12.43      private final Compiler compiler;
   12.44 @@ -493,8 +494,7 @@
   12.45          //walk up the chain from starting block and when we bump into the current function boundary, add the external
   12.46          //information.
   12.47          final FunctionNode fn   = lc.getCurrentFunction();
   12.48 -        final int          fnId = fn.getId();
   12.49 -        final int externalDepth = compiler.getScriptFunctionData(fnId).getExternalSymbolDepth(symbol.getName());
   12.50 +        final int externalDepth = compiler.getScriptFunctionData(fn.getId()).getExternalSymbolDepth(symbol.getName());
   12.51  
   12.52          //count the number of scopes from this place to the start of the function
   12.53  
   12.54 @@ -554,10 +554,10 @@
   12.55      }
   12.56  
   12.57      MethodEmitter loadBinaryOperands(final BinaryNode binaryNode) {
   12.58 -        return loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(binaryNode.getWidestOperandType()), false);
   12.59 +        return loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(binaryNode.getWidestOperandType()), false, false);
   12.60      }
   12.61  
   12.62 -    private MethodEmitter loadBinaryOperands(final Expression lhs, final Expression rhs, final TypeBounds explicitOperandBounds, final boolean baseAlreadyOnStack) {
   12.63 +    private MethodEmitter loadBinaryOperands(final Expression lhs, final Expression rhs, final TypeBounds explicitOperandBounds, final boolean baseAlreadyOnStack, final boolean forceConversionSeparation) {
   12.64          // ECMAScript 5.1 specification (sections 11.5-11.11 and 11.13) prescribes that when evaluating a binary
   12.65          // expression "LEFT op RIGHT", the order of operations must be: LOAD LEFT, LOAD RIGHT, CONVERT LEFT, CONVERT
   12.66          // RIGHT, EXECUTE OP. Unfortunately, doing it in this order defeats potential optimizations that arise when we
   12.67 @@ -574,15 +574,34 @@
   12.68          final Type narrowestOperandType = Type.narrowest(Type.widest(lhs.getType(), rhs.getType()), explicitOperandBounds.widest);
   12.69          final TypeBounds operandBounds = explicitOperandBounds.notNarrowerThan(narrowestOperandType);
   12.70          if (noToPrimitiveConversion(lhs.getType(), explicitOperandBounds.widest) || rhs.isLocal()) {
   12.71 -            // Can reorder. Combine load and convert into single operations.
   12.72 -            loadExpression(lhs, operandBounds, baseAlreadyOnStack);
   12.73 -            loadExpression(rhs, operandBounds, false);
   12.74 +            // Can reorder. We might still need to separate conversion, but at least we can do it with reordering
   12.75 +            if (forceConversionSeparation) {
   12.76 +                // Can reorder, but can't move conversion into the operand as the operation depends on operands
   12.77 +                // exact types for its overflow guarantees. E.g. with {L}{%I}expr1 {L}* {L}{%I}expr2 we are not allowed
   12.78 +                // to merge {L}{%I} into {%L}, as that can cause subsequent overflows; test for JDK-8058610 contains
   12.79 +                // concrete cases where this could happen.
   12.80 +                final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
   12.81 +                loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
   12.82 +                method.convert(operandBounds.within(method.peekType()));
   12.83 +                loadExpression(rhs, safeConvertBounds, false);
   12.84 +                method.convert(operandBounds.within(method.peekType()));
   12.85 +            } else {
   12.86 +                // Can reorder and move conversion into the operand. Combine load and convert into single operations.
   12.87 +                loadExpression(lhs, operandBounds, baseAlreadyOnStack);
   12.88 +                loadExpression(rhs, operandBounds, false);
   12.89 +            }
   12.90          } else {
   12.91              // Can't reorder. Load and convert separately.
   12.92              final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
   12.93              loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
   12.94 +            final Type lhsType = method.peekType();
   12.95              loadExpression(rhs, safeConvertBounds, false);
   12.96 -            method.swap().convert(operandBounds.within(method.peekType())).swap().convert(operandBounds.within(method.peekType()));
   12.97 +            final Type convertedLhsType = operandBounds.within(method.peekType());
   12.98 +            if (convertedLhsType != lhsType) {
   12.99 +                // Do it conditionally, so that if conversion is a no-op we don't introduce a SWAP, SWAP.
  12.100 +                method.swap().convert(convertedLhsType).swap();
  12.101 +            }
  12.102 +            method.convert(operandBounds.within(method.peekType()));
  12.103          }
  12.104          assert Type.generic(method.peekType()) == operandBounds.narrowest;
  12.105          assert Type.generic(method.peekType(1)) == operandBounds.narrowest;
  12.106 @@ -633,19 +652,11 @@
  12.107          }
  12.108  
  12.109          TypeBounds booleanToInt() {
  12.110 -            return maybeNew(booleanToInt(narrowest), booleanToInt(widest));
  12.111 +            return maybeNew(CodeGenerator.booleanToInt(narrowest), CodeGenerator.booleanToInt(widest));
  12.112          }
  12.113  
  12.114          TypeBounds objectToNumber() {
  12.115 -            return maybeNew(objectToNumber(narrowest), objectToNumber(widest));
  12.116 -        }
  12.117 -
  12.118 -        private static Type booleanToInt(final Type t) {
  12.119 -            return t == Type.BOOLEAN ? Type.INT : t;
  12.120 -        }
  12.121 -
  12.122 -        private static Type objectToNumber(final Type t) {
  12.123 -            return t.isObject() ? Type.NUMBER : t;
  12.124 +            return maybeNew(CodeGenerator.objectToNumber(narrowest), CodeGenerator.objectToNumber(widest));
  12.125          }
  12.126  
  12.127          Type within(final Type type) {
  12.128 @@ -664,6 +675,14 @@
  12.129          }
  12.130      }
  12.131  
  12.132 +    private static Type booleanToInt(final Type t) {
  12.133 +        return t == Type.BOOLEAN ? Type.INT : t;
  12.134 +    }
  12.135 +
  12.136 +    private static Type objectToNumber(final Type t) {
  12.137 +        return t.isObject() ? Type.NUMBER : t;
  12.138 +    }
  12.139 +
  12.140      MethodEmitter loadExpressionAsType(final Expression expr, final Type type) {
  12.141          if(type == Type.BOOLEAN) {
  12.142              return loadExpressionAsBoolean(expr);
  12.143 @@ -1048,6 +1067,13 @@
  12.144              }
  12.145  
  12.146              @Override
  12.147 +            public boolean enterGetSplitState(final GetSplitState getSplitState) {
  12.148 +                method.loadScope();
  12.149 +                method.invoke(Scope.GET_SPLIT_STATE);
  12.150 +                return false;
  12.151 +            }
  12.152 +
  12.153 +            @Override
  12.154              public boolean enterDefault(final Node otherNode) {
  12.155                  // Must have handled all expressions that can legally be encountered.
  12.156                  throw new AssertionError(otherNode.getClass().getName());
  12.157 @@ -1219,7 +1245,7 @@
  12.158          popScopesUntil(target);
  12.159          final Label targetLabel = jump.getTargetLabel(target);
  12.160          targetLabel.markAsBreakTarget();
  12.161 -        method.splitAwareGoto(lc, targetLabel, target);
  12.162 +        method._goto(targetLabel);
  12.163  
  12.164          return false;
  12.165      }
  12.166 @@ -2029,10 +2055,10 @@
  12.167      }
  12.168  
  12.169      private void lineNumber(final int lineNumber) {
  12.170 -        if (lineNumber != lastLineNumber) {
  12.171 +        if (lineNumber != lastLineNumber && lineNumber != Node.NO_LINE_NUMBER) {
  12.172              method.lineNumber(lineNumber);
  12.173 -        }
  12.174 -        lastLineNumber = lineNumber;
  12.175 +            lastLineNumber = lineNumber;
  12.176 +        }
  12.177      }
  12.178  
  12.179      int getLastLineNumber() {
  12.180 @@ -2079,13 +2105,14 @@
  12.181                  method.begin();
  12.182  
  12.183                  defineCommonSplitMethodParameters();
  12.184 -                defineSplitMethodParameter(3, arrayType);
  12.185 -
  12.186 -                fixScopeSlot(currentFunction);
  12.187 +                defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), arrayType);
  12.188 +
  12.189 +                // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
  12.190 +                // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
  12.191 +                final int arraySlot = fixScopeSlot(currentFunction, 3);
  12.192  
  12.193                  lc.enterSplitNode();
  12.194  
  12.195 -                final int arraySlot = SPLIT_ARRAY_ARG.slot();
  12.196                  for (int i = arrayUnit.getLo(); i < arrayUnit.getHi(); i++) {
  12.197                      method.load(arrayType, arraySlot);
  12.198                      storeElement(nodes, elementType, postsets[i]);
  12.199 @@ -2700,73 +2727,6 @@
  12.200          method.convert(newRuntimeNode.getType());
  12.201      }
  12.202  
  12.203 -    @Override
  12.204 -    public boolean enterSplitNode(final SplitNode splitNode) {
  12.205 -        if(!method.isReachable()) {
  12.206 -            return false;
  12.207 -        }
  12.208 -
  12.209 -        final CompileUnit splitCompileUnit = splitNode.getCompileUnit();
  12.210 -
  12.211 -        final FunctionNode fn   = lc.getCurrentFunction();
  12.212 -        final String className  = splitCompileUnit.getUnitClassName();
  12.213 -        final String name       = splitNode.getName();
  12.214 -
  12.215 -        final Type returnType = fn.getReturnType();
  12.216 -
  12.217 -        final Class<?>   rtype          = fn.getReturnType().getTypeClass();
  12.218 -        final boolean    needsArguments = fn.needsArguments();
  12.219 -        final Class<?>[] ptypes         = needsArguments ?
  12.220 -                new Class<?>[] {ScriptFunction.class, Object.class, ScriptObject.class, ScriptObject.class} :
  12.221 -                new Class<?>[] {ScriptFunction.class, Object.class, ScriptObject.class};
  12.222 -
  12.223 -        final MethodEmitter caller = method;
  12.224 -        unit = lc.pushCompileUnit(splitCompileUnit);
  12.225 -
  12.226 -        final Call splitCall = staticCallNoLookup(
  12.227 -            className,
  12.228 -            name,
  12.229 -            methodDescriptor(rtype, ptypes));
  12.230 -
  12.231 -        final MethodEmitter splitEmitter =
  12.232 -                splitCompileUnit.getClassEmitter().method(
  12.233 -                        splitNode,
  12.234 -                        name,
  12.235 -                        rtype,
  12.236 -                        ptypes);
  12.237 -
  12.238 -        pushMethodEmitter(splitEmitter);
  12.239 -        method.setFunctionNode(fn);
  12.240 -
  12.241 -        assert fn.needsCallee() : "split function should require callee";
  12.242 -        caller.loadCompilerConstant(CALLEE);
  12.243 -        caller.loadCompilerConstant(THIS);
  12.244 -        caller.loadCompilerConstant(SCOPE);
  12.245 -        if (needsArguments) {
  12.246 -            caller.loadCompilerConstant(ARGUMENTS);
  12.247 -        }
  12.248 -        caller.invoke(splitCall);
  12.249 -        caller.storeCompilerConstant(RETURN, returnType);
  12.250 -
  12.251 -        method.begin();
  12.252 -
  12.253 -        defineCommonSplitMethodParameters();
  12.254 -        if(needsArguments) {
  12.255 -            defineSplitMethodParameter(3, ARGUMENTS);
  12.256 -        }
  12.257 -
  12.258 -        // Copy scope to its target slot as first thing because the original slot could be used by return symbol.
  12.259 -        fixScopeSlot(fn);
  12.260 -
  12.261 -        final int returnSlot = fn.compilerConstant(RETURN).getSlot(returnType);
  12.262 -        method.defineBlockLocalVariable(returnSlot, returnSlot + returnType.getSlots());
  12.263 -        method.loadUndefined(returnType);
  12.264 -        method.storeCompilerConstant(RETURN, returnType);
  12.265 -
  12.266 -        lc.enterSplitNode();
  12.267 -        return true;
  12.268 -    }
  12.269 -
  12.270      private void defineCommonSplitMethodParameters() {
  12.271          defineSplitMethodParameter(0, CALLEE);
  12.272          defineSplitMethodParameter(1, THIS);
  12.273 @@ -2782,114 +2742,40 @@
  12.274          method.onLocalStore(type, slot);
  12.275      }
  12.276  
  12.277 -    private void fixScopeSlot(final FunctionNode functionNode) {
  12.278 +    private int fixScopeSlot(final FunctionNode functionNode, final int extraSlot) {
  12.279          // TODO hack to move the scope to the expected slot (needed because split methods reuse the same slots as the root method)
  12.280          final int actualScopeSlot = functionNode.compilerConstant(SCOPE).getSlot(SCOPE_TYPE);
  12.281          final int defaultScopeSlot = SCOPE.slot();
  12.282 +        int newExtraSlot = extraSlot;
  12.283          if (actualScopeSlot != defaultScopeSlot) {
  12.284 -            method.defineBlockLocalVariable(actualScopeSlot, actualScopeSlot + 1);
  12.285 +            if (actualScopeSlot == extraSlot) {
  12.286 +                newExtraSlot = extraSlot + 1;
  12.287 +                method.defineBlockLocalVariable(newExtraSlot, newExtraSlot + 1);
  12.288 +                method.load(Type.OBJECT, extraSlot);
  12.289 +                method.storeHidden(Type.OBJECT, newExtraSlot);
  12.290 +            } else {
  12.291 +                method.defineBlockLocalVariable(actualScopeSlot, actualScopeSlot + 1);
  12.292 +            }
  12.293              method.load(SCOPE_TYPE, defaultScopeSlot);
  12.294              method.storeCompilerConstant(SCOPE);
  12.295          }
  12.296 +        return newExtraSlot;
  12.297      }
  12.298  
  12.299      @Override
  12.300 -    public Node leaveSplitNode(final SplitNode splitNode) {
  12.301 -        assert method instanceof SplitMethodEmitter;
  12.302 -        lc.exitSplitNode();
  12.303 -        final boolean hasReturn = method.hasReturn();
  12.304 -        final SplitMethodEmitter splitMethod = ((SplitMethodEmitter)method);
  12.305 -        final List<Label> targets = splitMethod.getExternalTargets();
  12.306 -        final boolean hasControlFlow = hasReturn || !targets.isEmpty();
  12.307 -        final List<BreakableNode> targetNodes  = splitMethod.getExternalTargetNodes();
  12.308 -        final Type returnType = lc.getCurrentFunction().getReturnType();
  12.309 -
  12.310 -        try {
  12.311 -            // Wrap up this method.
  12.312 -
  12.313 -            if(method.isReachable()) {
  12.314 -                if (hasControlFlow) {
  12.315 -                    method.setSplitState(-1);
  12.316 -                }
  12.317 -                method.loadCompilerConstant(RETURN, returnType);
  12.318 -                method._return(returnType);
  12.319 -            }
  12.320 -            method.end();
  12.321 -
  12.322 -            lc.releaseSlots();
  12.323 -
  12.324 -            unit   = lc.popCompileUnit(splitNode.getCompileUnit());
  12.325 -            popMethodEmitter();
  12.326 -
  12.327 -        } catch (final Throwable t) {
  12.328 -            Context.printStackTrace(t);
  12.329 -            final VerifyError e = new VerifyError("Code generation bug in \"" + splitNode.getName() + "\": likely stack misaligned: " + t + " " + getCurrentSource().getName());
  12.330 -            e.initCause(t);
  12.331 -            throw e;
  12.332 -        }
  12.333 -
  12.334 -        //no external jump targets or return in switch node
  12.335 -        if (!hasControlFlow) {
  12.336 -            return splitNode;
  12.337 -        }
  12.338 -
  12.339 -        // Handle return from split method if there was one.
  12.340 -        final MethodEmitter caller = method;
  12.341 -        final int     targetCount = targets.size();
  12.342 -
  12.343 -        caller.loadScope();
  12.344 -        caller.invoke(Scope.GET_SPLIT_STATE);
  12.345 -
  12.346 -        final Label breakLabel = new Label("no_split_state");
  12.347 -        // Split state is -1 for no split state, 0 for return, 1..n+1 for break/continue
  12.348 -
  12.349 -        //the common case is that we don't need a switch
  12.350 -        if (targetCount == 0) {
  12.351 -            assert hasReturn;
  12.352 -            caller.ifne(breakLabel);
  12.353 -            //has to be zero
  12.354 -            caller.label(new Label("split_return"));
  12.355 -            caller.loadCompilerConstant(RETURN, returnType);
  12.356 -            caller._return(returnType);
  12.357 -            caller.label(breakLabel);
  12.358 -        } else {
  12.359 -            assert !targets.isEmpty();
  12.360 -
  12.361 -            final int     low         = hasReturn ? 0 : 1;
  12.362 -            final int     labelCount  = targetCount + 1 - low;
  12.363 -            final Label[] labels      = new Label[labelCount];
  12.364 -
  12.365 -            for (int i = 0; i < labelCount; i++) {
  12.366 -                labels[i] = new Label(i == 0 ? "split_return" : "split_" + targets.get(i - 1));
  12.367 -            }
  12.368 -            caller.tableswitch(low, targetCount, breakLabel, labels);
  12.369 -            for (int i = low; i <= targetCount; i++) {
  12.370 -                caller.label(labels[i - low]);
  12.371 -                if (i == 0) {
  12.372 -                    caller.loadCompilerConstant(RETURN, returnType);
  12.373 -                    caller._return(returnType);
  12.374 -                } else {
  12.375 -                    final BreakableNode targetNode = targetNodes.get(i - 1);
  12.376 -                    final Label label = targets.get(i - 1);
  12.377 -                    if (!lc.isExternalTarget(splitNode, targetNode)) {
  12.378 -                        final JoinPredecessor jumpOrigin = splitNode.getJumpOrigin(label);
  12.379 -                        if(jumpOrigin != null) {
  12.380 -                            method.beforeJoinPoint(jumpOrigin);
  12.381 -                        }
  12.382 -                        popScopesUntil(targetNode);
  12.383 -                    }
  12.384 -                    caller.splitAwareGoto(lc, label, targetNode);
  12.385 -                }
  12.386 -            }
  12.387 -            caller.label(breakLabel);
  12.388 -        }
  12.389 -
  12.390 -        // If split has a return and caller is itself a split method it needs to propagate the return.
  12.391 -        if (hasReturn) {
  12.392 -            caller.setHasReturn();
  12.393 -        }
  12.394 -
  12.395 -        return splitNode;
  12.396 +    public boolean enterSplitReturn(final SplitReturn splitReturn) {
  12.397 +        if (method.isReachable()) {
  12.398 +            method.loadUndefined(lc.getCurrentFunction().getReturnType())._return();
  12.399 +        }
  12.400 +        return false;
  12.401 +    }
  12.402 +
  12.403 +    @Override
  12.404 +    public boolean enterSetSplitState(final SetSplitState setSplitState) {
  12.405 +        if (method.isReachable()) {
  12.406 +            method.setSplitState(setSplitState.getState());
  12.407 +        }
  12.408 +        return false;
  12.409      }
  12.410  
  12.411      @Override
  12.412 @@ -3678,13 +3564,15 @@
  12.413              void loadStack() {
  12.414                  final TypeBounds operandBounds;
  12.415                  final boolean isOptimistic = isValid(getProgramPoint());
  12.416 +                boolean forceConversionSeparation = false;
  12.417                  if(isOptimistic) {
  12.418                      operandBounds = new TypeBounds(binaryNode.getType(), Type.OBJECT);
  12.419                  } else {
  12.420                      // Non-optimistic, non-FP +. Allow it to overflow.
  12.421                      operandBounds = new TypeBounds(binaryNode.getWidestOperandType(), Type.OBJECT);
  12.422 +                    forceConversionSeparation = binaryNode.getWidestOperationType().narrowerThan(resultBounds.widest);
  12.423                  }
  12.424 -                loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), operandBounds, false);
  12.425 +                loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), operandBounds, false, forceConversionSeparation);
  12.426              }
  12.427  
  12.428              @Override
  12.429 @@ -3795,12 +3683,21 @@
  12.430          @Override
  12.431          protected void evaluate() {
  12.432              final Expression lhs = assignNode.lhs();
  12.433 -            final Type widest = assignNode.isTokenType(TokenType.ASSIGN_ADD) ? Type.OBJECT : assignNode.getWidestOperationType();
  12.434 +            final Expression rhs = assignNode.rhs();
  12.435 +            final Type widestOperationType = assignNode.getWidestOperationType();
  12.436 +            final Type widest = assignNode.isTokenType(TokenType.ASSIGN_ADD) ? Type.OBJECT : widestOperationType;
  12.437              final TypeBounds bounds = new TypeBounds(assignNode.getType(), widest);
  12.438              new OptimisticOperation(assignNode, bounds) {
  12.439                  @Override
  12.440                  void loadStack() {
  12.441 -                    loadBinaryOperands(lhs, assignNode.rhs(), bounds, true);
  12.442 +                    final boolean forceConversionSeparation;
  12.443 +                    if (isValid(getProgramPoint()) || widestOperationType == Type.NUMBER) {
  12.444 +                        forceConversionSeparation = false;
  12.445 +                    } else {
  12.446 +                        final Type operandType = Type.widest(booleanToInt(objectToNumber(lhs.getType())), booleanToInt(objectToNumber(rhs.getType())));
  12.447 +                        forceConversionSeparation = operandType.narrowerThan(widestOperationType);
  12.448 +                    }
  12.449 +                    loadBinaryOperands(lhs, rhs, bounds, true, forceConversionSeparation);
  12.450                  }
  12.451                  @Override
  12.452                  void consumeStack() {
  12.453 @@ -3823,7 +3720,7 @@
  12.454  
  12.455          @Override
  12.456          protected void evaluate() {
  12.457 -            loadBinaryOperands(assignNode.lhs(), assignNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(assignNode.getWidestOperandType()), true);
  12.458 +            loadBinaryOperands(assignNode.lhs(), assignNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(assignNode.getWidestOperandType()), true, false);
  12.459              op();
  12.460          }
  12.461      }
  12.462 @@ -3922,7 +3819,12 @@
  12.463  
  12.464      private void doSHR() {
  12.465          // TODO: make SHR optimistic
  12.466 -        method.shr().convert(Type.LONG).load(JSType.MAX_UINT).and();
  12.467 +        method.shr();
  12.468 +        toUint();
  12.469 +    }
  12.470 +
  12.471 +    private void toUint() {
  12.472 +        JSType.TO_UINT32_I.invoke(method);
  12.473      }
  12.474  
  12.475      private void loadASSIGN_SUB(final BinaryNode binaryNode) {
  12.476 @@ -3946,6 +3848,7 @@
  12.477                  @Override
  12.478                  void loadStack() {
  12.479                      final TypeBounds operandBounds;
  12.480 +                    boolean forceConversionSeparation = false;
  12.481                      if(numericBounds.narrowest == Type.NUMBER) {
  12.482                          // Result should be double always. Propagate it into the operands so we don't have lots of I2D
  12.483                          // and L2D after operand evaluation.
  12.484 @@ -3963,9 +3866,10 @@
  12.485                              // Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow.
  12.486                              operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(),
  12.487                                      numericBounds.widest), Type.NUMBER);
  12.488 +                            forceConversionSeparation = node.getWidestOperationType().narrowerThan(numericBounds.widest);
  12.489                          }
  12.490                      }
  12.491 -                    loadBinaryOperands(node.lhs(), node.rhs(), operandBounds, false);
  12.492 +                    loadBinaryOperands(node.lhs(), node.rhs(), operandBounds, false, forceConversionSeparation);
  12.493                  }
  12.494  
  12.495                  @Override
  12.496 @@ -3982,8 +3886,18 @@
  12.497      }
  12.498  
  12.499      private void loadBIT_OR(final BinaryNode binaryNode) {
  12.500 -        loadBinaryOperands(binaryNode);
  12.501 -        method.or();
  12.502 +        // Optimize x|0 to (int)x
  12.503 +        if (isRhsZero(binaryNode)) {
  12.504 +            loadExpressionAsType(binaryNode.lhs(), Type.INT);
  12.505 +        } else {
  12.506 +            loadBinaryOperands(binaryNode);
  12.507 +            method.or();
  12.508 +        }
  12.509 +    }
  12.510 +
  12.511 +    private static boolean isRhsZero(final BinaryNode binaryNode) {
  12.512 +        final Expression rhs = binaryNode.rhs();
  12.513 +        return rhs instanceof LiteralNode && INT_ZERO.equals(((LiteralNode)rhs).getValue());
  12.514      }
  12.515  
  12.516      private void loadBIT_XOR(final BinaryNode binaryNode) {
  12.517 @@ -4060,8 +3974,14 @@
  12.518      }
  12.519  
  12.520      private void loadSHR(final BinaryNode binaryNode) {
  12.521 -        loadBinaryOperands(binaryNode);
  12.522 -        doSHR();
  12.523 +        // Optimize x >>> 0 to (uint)x
  12.524 +        if (isRhsZero(binaryNode)) {
  12.525 +            loadExpressionAsType(binaryNode.lhs(), Type.INT);
  12.526 +            toUint();
  12.527 +        } else {
  12.528 +            loadBinaryOperands(binaryNode);
  12.529 +            doSHR();
  12.530 +        }
  12.531      }
  12.532  
  12.533      private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) {
  12.534 @@ -4379,11 +4299,7 @@
  12.535      private void newFunctionObject(final FunctionNode functionNode, final boolean addInitializer) {
  12.536          assert lc.peek() == functionNode;
  12.537  
  12.538 -        final int fnId = functionNode.getId();
  12.539 -
  12.540 -        final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(fnId);
  12.541 -
  12.542 -        assert data != null : functionNode.getName() + " has no data";
  12.543 +        final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(functionNode.getId());
  12.544  
  12.545          if (functionNode.isProgram() && !compiler.isOnDemandCompilation()) {
  12.546              final CompileUnit fnUnit = functionNode.getCompileUnit();
    13.1 --- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Mon Oct 27 14:36:13 2014 -0700
    13.2 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu Nov 06 09:50:15 2014 -0800
    13.3 @@ -38,12 +38,11 @@
    13.4  import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SPLIT;
    13.5  import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SYMBOLS_ASSIGNED;
    13.6  import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
    13.7 +
    13.8  import java.io.PrintWriter;
    13.9 -import java.util.ArrayList;
   13.10  import java.util.EnumSet;
   13.11  import java.util.HashMap;
   13.12  import java.util.LinkedHashMap;
   13.13 -import java.util.List;
   13.14  import java.util.Map;
   13.15  import java.util.Map.Entry;
   13.16  import java.util.Set;
   13.17 @@ -53,10 +52,7 @@
   13.18  import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
   13.19  import jdk.nashorn.internal.ir.LexicalContext;
   13.20  import jdk.nashorn.internal.ir.LiteralNode;
   13.21 -import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
   13.22 -import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
   13.23  import jdk.nashorn.internal.ir.Node;
   13.24 -import jdk.nashorn.internal.ir.SplitNode;
   13.25  import jdk.nashorn.internal.ir.debug.ASTWriter;
   13.26  import jdk.nashorn.internal.ir.debug.PrintVisitor;
   13.27  import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   13.28 @@ -81,7 +77,7 @@
   13.29                  PARSED)) {
   13.30          @Override
   13.31          FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
   13.32 -            return (FunctionNode)fn.accept(new FoldConstants(compiler));
   13.33 +            return transformFunction(fn, new FoldConstants(compiler));
   13.34          }
   13.35  
   13.36          @Override
   13.37 @@ -104,7 +100,7 @@
   13.38                  CONSTANT_FOLDED)) {
   13.39          @Override
   13.40          FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
   13.41 -            return (FunctionNode)fn.accept(new Lower(compiler));
   13.42 +            return transformFunction(fn, new Lower(compiler));
   13.43          }
   13.44  
   13.45          @Override
   13.46 @@ -118,23 +114,6 @@
   13.47       * optimistic ops a program point so that an UnwarrantedException knows from where
   13.48       * a guess went wrong when creating the continuation to roll back this execution
   13.49       */
   13.50 -    PROGRAM_POINT_PHASE(
   13.51 -            EnumSet.of(
   13.52 -                INITIALIZED,
   13.53 -                PARSED,
   13.54 -                CONSTANT_FOLDED,
   13.55 -                LOWERED)) {
   13.56 -        @Override
   13.57 -        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
   13.58 -            return (FunctionNode)fn.accept(new ProgramPoints());
   13.59 -        }
   13.60 -
   13.61 -        @Override
   13.62 -        public String toString() {
   13.63 -            return "'Program Point Calculation'";
   13.64 -        }
   13.65 -    },
   13.66 -
   13.67      TRANSFORM_BUILTINS_PHASE(
   13.68              EnumSet.of(
   13.69                      INITIALIZED,
   13.70 @@ -144,13 +123,7 @@
   13.71          //we only do this if we have a param type map, otherwise this is not a specialized recompile
   13.72          @Override
   13.73          FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
   13.74 -            final FunctionNode newFunctionNode = (FunctionNode)fn.accept(new ApplySpecialization(compiler));
   13.75 -            return (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   13.76 -                @Override
   13.77 -                public Node leaveFunctionNode(final FunctionNode node) {
   13.78 -                    return node.setState(lc, BUILTINS_TRANSFORMED);
   13.79 -                }
   13.80 -            });
   13.81 +            return setStates(transformFunction(fn, new ApplySpecialization(compiler)), BUILTINS_TRANSFORMED);
   13.82          }
   13.83  
   13.84          @Override
   13.85 @@ -177,7 +150,7 @@
   13.86              FunctionNode newFunctionNode;
   13.87  
   13.88              //ensure elementTypes, postsets and presets exist for splitter and arraynodes
   13.89 -            newFunctionNode = (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   13.90 +            newFunctionNode = transformFunction(fn, new NodeVisitor<LexicalContext>(new LexicalContext()) {
   13.91                  @Override
   13.92                  public LiteralNode<?> leaveLiteralNode(final LiteralNode<?> literalNode) {
   13.93                      return literalNode.initialize(lc);
   13.94 @@ -185,7 +158,7 @@
   13.95              });
   13.96  
   13.97              newFunctionNode = new Splitter(compiler, newFunctionNode, outermostCompileUnit).split(newFunctionNode, true);
   13.98 -
   13.99 +            newFunctionNode = transformFunction(newFunctionNode, new SplitIntoFunctions(compiler));
  13.100              assert newFunctionNode.getCompileUnit() == outermostCompileUnit : "fn=" + fn.getName() + ", fn.compileUnit (" + newFunctionNode.getCompileUnit() + ") != " + outermostCompileUnit;
  13.101              assert newFunctionNode.isStrict() == compiler.isStrict() : "functionNode.isStrict() != compiler.isStrict() for " + quote(newFunctionNode.getName());
  13.102  
  13.103 @@ -198,6 +171,52 @@
  13.104          }
  13.105      },
  13.106  
  13.107 +    PROGRAM_POINT_PHASE(
  13.108 +            EnumSet.of(
  13.109 +                    INITIALIZED,
  13.110 +                    PARSED,
  13.111 +                    CONSTANT_FOLDED,
  13.112 +                    LOWERED,
  13.113 +                    BUILTINS_TRANSFORMED,
  13.114 +                    SPLIT)) {
  13.115 +        @Override
  13.116 +        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
  13.117 +            return transformFunction(fn, new ProgramPoints());
  13.118 +        }
  13.119 +
  13.120 +        @Override
  13.121 +        public String toString() {
  13.122 +            return "'Program Point Calculation'";
  13.123 +        }
  13.124 +    },
  13.125 +
  13.126 +    SERIALIZE_SPLIT_PHASE(
  13.127 +            EnumSet.of(
  13.128 +                    INITIALIZED,
  13.129 +                    PARSED,
  13.130 +                    CONSTANT_FOLDED,
  13.131 +                    LOWERED,
  13.132 +                    BUILTINS_TRANSFORMED,
  13.133 +                    SPLIT)) {
  13.134 +        @Override
  13.135 +        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
  13.136 +            return transformFunction(fn, new NodeVisitor<LexicalContext>(new LexicalContext()) {
  13.137 +                @Override
  13.138 +                public boolean enterFunctionNode(final FunctionNode functionNode) {
  13.139 +                    if (functionNode.isSplit()) {
  13.140 +                        compiler.serializeAst(functionNode);
  13.141 +                    }
  13.142 +                    return true;
  13.143 +                }
  13.144 +            });
  13.145 +        }
  13.146 +
  13.147 +        @Override
  13.148 +        public String toString() {
  13.149 +            return "'Serialize Split Functions'";
  13.150 +        }
  13.151 +    },
  13.152 +
  13.153      SYMBOL_ASSIGNMENT_PHASE(
  13.154              EnumSet.of(
  13.155                      INITIALIZED,
  13.156 @@ -208,7 +227,7 @@
  13.157                      SPLIT)) {
  13.158          @Override
  13.159          FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
  13.160 -            return (FunctionNode)fn.accept(new AssignSymbols(compiler));
  13.161 +            return transformFunction(fn, new AssignSymbols(compiler));
  13.162          }
  13.163  
  13.164          @Override
  13.165 @@ -228,7 +247,7 @@
  13.166                      SYMBOLS_ASSIGNED)) {
  13.167          @Override
  13.168          FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
  13.169 -            return (FunctionNode)fn.accept(new FindScopeDepths(compiler));
  13.170 +            return transformFunction(fn, new FindScopeDepths(compiler));
  13.171          }
  13.172  
  13.173          @Override
  13.174 @@ -250,7 +269,7 @@
  13.175          @Override
  13.176          FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
  13.177              if (compiler.useOptimisticTypes()) {
  13.178 -                return (FunctionNode)fn.accept(new OptimisticTypesCalculator(compiler));
  13.179 +                return transformFunction(fn, new OptimisticTypesCalculator(compiler));
  13.180              }
  13.181              return setStates(fn, OPTIMISTIC_TYPES_ASSIGNED);
  13.182          }
  13.183 @@ -274,8 +293,7 @@
  13.184                      OPTIMISTIC_TYPES_ASSIGNED)) {
  13.185          @Override
  13.186          FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
  13.187 -            final FunctionNode newFunctionNode = (FunctionNode)fn.accept(new LocalVariableTypesCalculator(compiler));
  13.188 -
  13.189 +            final FunctionNode newFunctionNode = transformFunction(fn, new LocalVariableTypesCalculator(compiler));
  13.190              final ScriptEnvironment senv = compiler.getScriptEnvironment();
  13.191              final PrintWriter       err  = senv.getErr();
  13.192  
  13.193 @@ -330,13 +348,7 @@
  13.194  
  13.195              for (final CompileUnit oldUnit : compiler.getCompileUnits()) {
  13.196                  assert map.get(oldUnit) == null;
  13.197 -                final StringBuilder sb = new StringBuilder(compiler.nextCompileUnitName());
  13.198 -                if (phases.isRestOfCompilation()) {
  13.199 -                    sb.append("$restOf");
  13.200 -                }
  13.201 -                //it's ok to not copy the initCount, methodCount and clinitCount here, as codegen is what
  13.202 -                //fills those out anyway. Thus no need for a copy constructor
  13.203 -                final CompileUnit newUnit = compiler.createCompileUnit(sb.toString(), oldUnit.getWeight());
  13.204 +                final CompileUnit newUnit = createNewCompileUnit(compiler, phases);
  13.205                  log.fine("Creating new compile unit ", oldUnit, " => ", newUnit);
  13.206                  map.put(oldUnit, newUnit);
  13.207                  assert newUnit != null;
  13.208 @@ -350,47 +362,10 @@
  13.209              //replace old compile units in function nodes, if any are assigned,
  13.210              //for example by running the splitter on this function node in a previous
  13.211              //partial code generation
  13.212 -            final FunctionNode newFunctionNode = (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
  13.213 +            final FunctionNode newFunctionNode = transformFunction(fn, new ReplaceCompileUnits() {
  13.214                  @Override
  13.215 -                public Node leaveFunctionNode(final FunctionNode node) {
  13.216 -                    final CompileUnit oldUnit = node.getCompileUnit();
  13.217 -                    assert oldUnit != null : "no compile unit in function node";
  13.218 -
  13.219 -                    final CompileUnit newUnit = map.get(oldUnit);
  13.220 -                    assert newUnit != null : "old unit has no mapping to new unit " + oldUnit;
  13.221 -
  13.222 -                    log.fine("Replacing compile unit: ", oldUnit, " => ", newUnit, " in ", quote(node.getName()));
  13.223 -                    return node.setCompileUnit(lc, newUnit).setState(lc, CompilationState.COMPILE_UNITS_REUSED);
  13.224 -                }
  13.225 -
  13.226 -                @Override
  13.227 -                public Node leaveSplitNode(final SplitNode node) {
  13.228 -                    final CompileUnit oldUnit = node.getCompileUnit();
  13.229 -                    assert oldUnit != null : "no compile unit in function node";
  13.230 -
  13.231 -                    final CompileUnit newUnit = map.get(oldUnit);
  13.232 -                    assert newUnit != null : "old unit has no mapping to new unit " + oldUnit;
  13.233 -
  13.234 -                    log.fine("Replacing compile unit: ", oldUnit, " => ", newUnit, " in ", quote(node.getName()));
  13.235 -                    return node.setCompileUnit(lc, newUnit);
  13.236 -                }
  13.237 -
  13.238 -                @Override
  13.239 -                public Node leaveLiteralNode(final LiteralNode<?> node) {
  13.240 -                    if (node instanceof ArrayLiteralNode) {
  13.241 -                        final ArrayLiteralNode aln = (ArrayLiteralNode)node;
  13.242 -                        if (aln.getUnits() == null) {
  13.243 -                            return node;
  13.244 -                        }
  13.245 -                        final List<ArrayUnit> newArrayUnits = new ArrayList<>();
  13.246 -                        for (final ArrayUnit au : aln.getUnits()) {
  13.247 -                            final CompileUnit newUnit = map.get(au.getCompileUnit());
  13.248 -                            assert newUnit != null;
  13.249 -                            newArrayUnits.add(new ArrayUnit(newUnit, au.getLo(), au.getHi()));
  13.250 -                        }
  13.251 -                        return aln.setUnits(lc, newArrayUnits);
  13.252 -                    }
  13.253 -                    return node;
  13.254 +                CompileUnit getReplacement(CompileUnit original) {
  13.255 +                    return map.get(original);
  13.256                  }
  13.257  
  13.258                  @Override
  13.259 @@ -408,7 +383,59 @@
  13.260          }
  13.261      },
  13.262  
  13.263 -     /**
  13.264 +    REINITIALIZE_SERIALIZED(
  13.265 +            EnumSet.of(
  13.266 +                    INITIALIZED,
  13.267 +                    PARSED,
  13.268 +                    CONSTANT_FOLDED,
  13.269 +                    LOWERED,
  13.270 +                    BUILTINS_TRANSFORMED,
  13.271 +                    SPLIT)) {
  13.272 +        @Override
  13.273 +        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
  13.274 +            final Set<CompileUnit> unitSet = CompileUnit.createCompileUnitSet();
  13.275 +            final Map<CompileUnit, CompileUnit> unitMap = new HashMap<>();
  13.276 +
  13.277 +            // Ensure that the FunctionNode's compile unit is the first in the list of new units. Install phase
  13.278 +            // will use that as the root class.
  13.279 +            createCompileUnit(fn.getCompileUnit(), unitSet, unitMap, compiler, phases);
  13.280 +
  13.281 +            final FunctionNode newFn = transformFunction(fn, new ReplaceCompileUnits() {
  13.282 +                @Override
  13.283 +                CompileUnit getReplacement(final CompileUnit oldUnit) {
  13.284 +                    final CompileUnit existing = unitMap.get(oldUnit);
  13.285 +                    if (existing != null) {
  13.286 +                        return existing;
  13.287 +                    }
  13.288 +                    return createCompileUnit(oldUnit, unitSet, unitMap, compiler, phases);
  13.289 +                }
  13.290 +
  13.291 +                @Override
  13.292 +                public Node leaveFunctionNode(final FunctionNode fn2) {
  13.293 +                    return super.leaveFunctionNode(
  13.294 +                            // restore flags for deserialized nested function nodes
  13.295 +                            compiler.getScriptFunctionData(fn2.getId()).restoreFlags(lc, fn2));
  13.296 +                };
  13.297 +            });
  13.298 +            compiler.replaceCompileUnits(unitSet);
  13.299 +            return newFn;
  13.300 +        }
  13.301 +
  13.302 +        private CompileUnit createCompileUnit(final CompileUnit oldUnit, final Set<CompileUnit> unitSet,
  13.303 +                final Map<CompileUnit, CompileUnit> unitMap, final Compiler compiler, final CompilationPhases phases) {
  13.304 +            final CompileUnit newUnit = createNewCompileUnit(compiler, phases);
  13.305 +            unitMap.put(oldUnit, newUnit);
  13.306 +            unitSet.add(newUnit);
  13.307 +            return newUnit;
  13.308 +        }
  13.309 +
  13.310 +        @Override
  13.311 +        public String toString() {
  13.312 +            return "'Deserialize'";
  13.313 +        }
  13.314 +    },
  13.315 +
  13.316 +    /**
  13.317       * Bytecode generation:
  13.318       *
  13.319       * Generate the byte code class(es) resulting from the compiled FunctionNode
  13.320 @@ -443,7 +470,7 @@
  13.321              try {
  13.322                  // Explicitly set BYTECODE_GENERATED here; it can not be set in case of skipping codegen for :program
  13.323                  // in the lazy + optimistic world. See CodeGenerator.skipFunction().
  13.324 -                newFunctionNode = ((FunctionNode)newFunctionNode.accept(codegen)).setState(null, BYTECODE_GENERATED);
  13.325 +                newFunctionNode = transformFunction(newFunctionNode, codegen).setState(null, BYTECODE_GENERATED);
  13.326                  codegen.generateScopeCalls();
  13.327              } catch (final VerifyError e) {
  13.328                  if (senv._verify_code || senv._print_code) {
  13.329 @@ -615,7 +642,7 @@
  13.330          if (!AssertsEnabled.assertsEnabled()) {
  13.331              return functionNode;
  13.332          }
  13.333 -        return (FunctionNode)functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
  13.334 +        return transformFunction(functionNode, new NodeVisitor<LexicalContext>(new LexicalContext()) {
  13.335              @Override
  13.336              public Node leaveFunctionNode(final FunctionNode fn) {
  13.337                  return fn.setState(lc, state);
  13.338 @@ -701,4 +728,17 @@
  13.339          return end(compiler, transform(compiler, phases, begin(compiler, functionNode)));
  13.340      }
  13.341  
  13.342 +    private static FunctionNode transformFunction(final FunctionNode fn, final NodeVisitor<?> visitor) {
  13.343 +        return (FunctionNode) fn.accept(visitor);
  13.344 +    }
  13.345 +
  13.346 +    private static CompileUnit createNewCompileUnit(final Compiler compiler, final CompilationPhases phases) {
  13.347 +        final StringBuilder sb = new StringBuilder(compiler.nextCompileUnitName());
  13.348 +        if (phases.isRestOfCompilation()) {
  13.349 +            sb.append("$restOf");
  13.350 +        }
  13.351 +        //it's ok to not copy the initCount, methodCount and clinitCount here, as codegen is what
  13.352 +        //fills those out anyway. Thus no need for a copy constructor
  13.353 +        return compiler.createCompileUnit(sb.toString(), 0);
  13.354 +    }
  13.355  }
    14.1 --- a/src/jdk/nashorn/internal/codegen/CompileUnit.java	Mon Oct 27 14:36:13 2014 -0700
    14.2 +++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java	Thu Nov 06 09:50:15 2014 -0800
    14.3 @@ -25,24 +25,31 @@
    14.4  
    14.5  package jdk.nashorn.internal.codegen;
    14.6  
    14.7 +import java.io.Serializable;
    14.8  import java.util.Set;
    14.9  import java.util.TreeSet;
   14.10 +import jdk.nashorn.internal.ir.CompileUnitHolder;
   14.11  
   14.12  /**
   14.13 - * Used to track split class compilation.
   14.14 - */
   14.15 -public final class CompileUnit implements Comparable<CompileUnit> {
   14.16 +  * Used to track split class compilation. Note that instances of the class are serializable, but all fields are
   14.17 +  * transient, making the serialized version of the class only useful for tracking the referential topology of other
   14.18 +  * AST nodes referencing the same or different compile units. We do want to preserve this topology though as
   14.19 +  * {@link CompileUnitHolder}s in a deserialized AST will undergo reinitialization.
   14.20 +  */
   14.21 +public final class CompileUnit implements Comparable<CompileUnit>, Serializable {
   14.22 +    private static final long serialVersionUID = 1L;
   14.23 +
   14.24      /** Current class name */
   14.25 -    private final String className;
   14.26 +    private transient final String className;
   14.27  
   14.28      /** Current class generator */
   14.29 -    private ClassEmitter classEmitter;
   14.30 +    private transient ClassEmitter classEmitter;
   14.31  
   14.32 -    private long weight;
   14.33 +    private transient long weight;
   14.34  
   14.35 -    private Class<?> clazz;
   14.36 +    private transient Class<?> clazz;
   14.37  
   14.38 -    private boolean isUsed;
   14.39 +    private transient boolean isUsed;
   14.40  
   14.41      private static int emittedUnitCount;
   14.42  
   14.43 @@ -122,14 +129,6 @@
   14.44      }
   14.45  
   14.46      /**
   14.47 -     * Get the current weight of the compile unit.
   14.48 -     * @return the unit's weight
   14.49 -     */
   14.50 -    long getWeight() {
   14.51 -        return weight;
   14.52 -    }
   14.53 -
   14.54 -    /**
   14.55       * Check if this compile unit can hold {@code weight} more units of weight
   14.56       * @param w weight to check if can be added
   14.57       * @return true if weight fits in this compile unit
   14.58 @@ -155,7 +154,7 @@
   14.59      }
   14.60  
   14.61      private static String shortName(final String name) {
   14.62 -        return name.lastIndexOf('/') == -1 ? name : name.substring(name.lastIndexOf('/') + 1);
   14.63 +        return name == null ? null : name.lastIndexOf('/') == -1 ? name : name.substring(name.lastIndexOf('/') + 1);
   14.64      }
   14.65  
   14.66      @Override
    15.1 --- a/src/jdk/nashorn/internal/codegen/Compiler.java	Mon Oct 27 14:36:13 2014 -0700
    15.2 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java	Thu Nov 06 09:50:15 2014 -0800
    15.3 @@ -32,15 +32,16 @@
    15.4  import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
    15.5  import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
    15.6  import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
    15.7 +
    15.8  import java.io.File;
    15.9  import java.lang.invoke.MethodType;
   15.10 +import java.util.ArrayList;
   15.11  import java.util.Arrays;
   15.12  import java.util.Collections;
   15.13  import java.util.Comparator;
   15.14  import java.util.HashMap;
   15.15  import java.util.Iterator;
   15.16  import java.util.LinkedHashMap;
   15.17 -import java.util.LinkedList;
   15.18  import java.util.List;
   15.19  import java.util.Map;
   15.20  import java.util.Set;
   15.21 @@ -159,75 +160,142 @@
   15.22       */
   15.23      private static final int COMPILE_UNIT_NAME_BUFFER_SIZE = 32;
   15.24  
   15.25 +    private final Map<Integer, byte[]> serializedAsts = new HashMap<>();
   15.26 +
   15.27      /**
   15.28       * Compilation phases that a compilation goes through
   15.29       */
   15.30      public static class CompilationPhases implements Iterable<CompilationPhase> {
   15.31  
   15.32 -        /** Singleton that describes a standard eager compilation - this includes code installation */
   15.33 -        public final static CompilationPhases COMPILE_ALL = new CompilationPhases(
   15.34 -                "Compile all",
   15.35 -                new CompilationPhase[] {
   15.36 -                        CompilationPhase.CONSTANT_FOLDING_PHASE,
   15.37 -                        CompilationPhase.LOWERING_PHASE,
   15.38 -                        CompilationPhase.PROGRAM_POINT_PHASE,
   15.39 -                        CompilationPhase.TRANSFORM_BUILTINS_PHASE,
   15.40 -                        CompilationPhase.SPLITTING_PHASE,
   15.41 -                        CompilationPhase.SYMBOL_ASSIGNMENT_PHASE,
   15.42 -                        CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE,
   15.43 -                        CompilationPhase.OPTIMISTIC_TYPE_ASSIGNMENT_PHASE,
   15.44 -                        CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE,
   15.45 -                        CompilationPhase.BYTECODE_GENERATION_PHASE,
   15.46 -                        CompilationPhase.INSTALL_PHASE
   15.47 -                });
   15.48 +        /**
   15.49 +         * Singleton that describes compilation up to the phase where a function can be serialized.
   15.50 +         */
   15.51 +        private final static CompilationPhases COMPILE_UPTO_SERIALIZABLE = new CompilationPhases(
   15.52 +                "Common initial phases",
   15.53 +                CompilationPhase.CONSTANT_FOLDING_PHASE,
   15.54 +                CompilationPhase.LOWERING_PHASE,
   15.55 +                CompilationPhase.TRANSFORM_BUILTINS_PHASE,
   15.56 +                CompilationPhase.SPLITTING_PHASE,
   15.57 +                CompilationPhase.PROGRAM_POINT_PHASE,
   15.58 +                CompilationPhase.SERIALIZE_SPLIT_PHASE
   15.59 +                );
   15.60  
   15.61 -        /** Compile all for a rest of method */
   15.62 -        public final static CompilationPhases COMPILE_ALL_RESTOF =
   15.63 -                COMPILE_ALL.setDescription("Compile all, rest of").addAfter(CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE, CompilationPhase.REUSE_COMPILE_UNITS_PHASE);
   15.64 +        private final static CompilationPhases COMPILE_SERIALIZABLE_UPTO_BYTECODE = new CompilationPhases(
   15.65 +                "After common phases, before bytecode generator",
   15.66 +                CompilationPhase.SYMBOL_ASSIGNMENT_PHASE,
   15.67 +                CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE,
   15.68 +                CompilationPhase.OPTIMISTIC_TYPE_ASSIGNMENT_PHASE,
   15.69 +                CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE
   15.70 +                );
   15.71  
   15.72 -        /** Singleton that describes a standard eager compilation, but no installation, for example used by --compile-only */
   15.73 -        public final static CompilationPhases COMPILE_ALL_NO_INSTALL =
   15.74 -                COMPILE_ALL.
   15.75 -                removeLast().
   15.76 -                setDescription("Compile without install");
   15.77 -
   15.78 -        /** Singleton that describes compilation up to the CodeGenerator, but not actually generating code */
   15.79 -        public final static CompilationPhases COMPILE_UPTO_BYTECODE =
   15.80 -                COMPILE_ALL.
   15.81 -                removeLast().
   15.82 -                removeLast().
   15.83 -                setDescription("Compile upto bytecode");
   15.84 +        /**
   15.85 +         * Singleton that describes additional steps to be taken after deserializing, all the way up to (but not
   15.86 +         * including) generating and installing code.
   15.87 +         */
   15.88 +        public final static CompilationPhases RECOMPILE_SERIALIZED_UPTO_BYTECODE = new CompilationPhases(
   15.89 +                "Recompile serialized function up to bytecode",
   15.90 +                CompilationPhase.REINITIALIZE_SERIALIZED,
   15.91 +                COMPILE_SERIALIZABLE_UPTO_BYTECODE
   15.92 +                );
   15.93  
   15.94          /**
   15.95           * Singleton that describes back end of method generation, given that we have generated the normal
   15.96           * method up to CodeGenerator as in {@link CompilationPhases#COMPILE_UPTO_BYTECODE}
   15.97           */
   15.98 -        public final static CompilationPhases COMPILE_FROM_BYTECODE = new CompilationPhases(
   15.99 +        public final static CompilationPhases GENERATE_BYTECODE_AND_INSTALL = new CompilationPhases(
  15.100                  "Generate bytecode and install",
  15.101 -                new CompilationPhase[] {
  15.102 -                        CompilationPhase.BYTECODE_GENERATION_PHASE,
  15.103 -                        CompilationPhase.INSTALL_PHASE
  15.104 -                });
  15.105 +                CompilationPhase.BYTECODE_GENERATION_PHASE,
  15.106 +                CompilationPhase.INSTALL_PHASE
  15.107 +                );
  15.108 +
  15.109 +        /** Singleton that describes compilation up to the CodeGenerator, but not actually generating code */
  15.110 +        public final static CompilationPhases COMPILE_UPTO_BYTECODE = new CompilationPhases(
  15.111 +                "Compile upto bytecode",
  15.112 +                COMPILE_UPTO_SERIALIZABLE,
  15.113 +                COMPILE_SERIALIZABLE_UPTO_BYTECODE);
  15.114 +
  15.115 +        /** Singleton that describes a standard eager compilation, but no installation, for example used by --compile-only */
  15.116 +        public final static CompilationPhases COMPILE_ALL_NO_INSTALL = new CompilationPhases(
  15.117 +                "Compile without install",
  15.118 +                COMPILE_UPTO_BYTECODE,
  15.119 +                CompilationPhase.BYTECODE_GENERATION_PHASE);
  15.120 +
  15.121 +        /** Singleton that describes a standard eager compilation - this includes code installation */
  15.122 +        public final static CompilationPhases COMPILE_ALL = new CompilationPhases(
  15.123 +                "Full eager compilation",
  15.124 +                COMPILE_UPTO_BYTECODE,
  15.125 +                GENERATE_BYTECODE_AND_INSTALL);
  15.126 +
  15.127 +        /** Singleton that describes a full compilation - this includes code installation - from serialized state*/
  15.128 +        public final static CompilationPhases COMPILE_ALL_SERIALIZED = new CompilationPhases(
  15.129 +                "Eager compilation from serializaed state",
  15.130 +                RECOMPILE_SERIALIZED_UPTO_BYTECODE,
  15.131 +                GENERATE_BYTECODE_AND_INSTALL);
  15.132  
  15.133          /**
  15.134           * Singleton that describes restOf method generation, given that we have generated the normal
  15.135           * method up to CodeGenerator as in {@link CompilationPhases#COMPILE_UPTO_BYTECODE}
  15.136           */
  15.137 -        public final static CompilationPhases COMPILE_FROM_BYTECODE_RESTOF =
  15.138 -                COMPILE_FROM_BYTECODE.
  15.139 -                addFirst(CompilationPhase.REUSE_COMPILE_UNITS_PHASE).
  15.140 -                setDescription("Generate bytecode and install - RestOf method");
  15.141 +        public final static CompilationPhases GENERATE_BYTECODE_AND_INSTALL_RESTOF = new CompilationPhases(
  15.142 +                "Generate bytecode and install - RestOf method",
  15.143 +                CompilationPhase.REUSE_COMPILE_UNITS_PHASE,
  15.144 +                GENERATE_BYTECODE_AND_INSTALL);
  15.145 +
  15.146 +        /** Compile all for a rest of method */
  15.147 +        public final static CompilationPhases COMPILE_ALL_RESTOF = new CompilationPhases(
  15.148 +                "Compile all, rest of",
  15.149 +                COMPILE_UPTO_BYTECODE,
  15.150 +                GENERATE_BYTECODE_AND_INSTALL_RESTOF);
  15.151 +
  15.152 +        /** Compile from serialized for a rest of method */
  15.153 +        public final static CompilationPhases COMPILE_SERIALIZED_RESTOF = new CompilationPhases(
  15.154 +                "Compile serialized, rest of",
  15.155 +                RECOMPILE_SERIALIZED_UPTO_BYTECODE,
  15.156 +                GENERATE_BYTECODE_AND_INSTALL_RESTOF);
  15.157  
  15.158          private final List<CompilationPhase> phases;
  15.159  
  15.160          private final String desc;
  15.161  
  15.162          private CompilationPhases(final String desc, final CompilationPhase... phases) {
  15.163 +            this(desc, Arrays.asList(phases));
  15.164 +        }
  15.165 +
  15.166 +        private CompilationPhases(final String desc, final CompilationPhases base, final CompilationPhase... phases) {
  15.167 +            this(desc, concat(base.phases, Arrays.asList(phases)));
  15.168 +        }
  15.169 +
  15.170 +        private CompilationPhases(final String desc, final CompilationPhase first, final CompilationPhases rest) {
  15.171 +            this(desc, concat(Collections.singletonList(first), rest.phases));
  15.172 +        }
  15.173 +
  15.174 +        private CompilationPhases(final String desc, final CompilationPhases base) {
  15.175 +            this(desc, base.phases);
  15.176 +        }
  15.177 +
  15.178 +        private CompilationPhases(final String desc, final CompilationPhases... bases) {
  15.179 +            this(desc, concatPhases(bases));
  15.180 +        }
  15.181 +
  15.182 +        private CompilationPhases(final String desc, final List<CompilationPhase> phases) {
  15.183              this.desc = desc;
  15.184 +            this.phases = phases;
  15.185 +        }
  15.186  
  15.187 -            final List<CompilationPhase> newPhases = new LinkedList<>();
  15.188 -            newPhases.addAll(Arrays.asList(phases));
  15.189 -            this.phases = Collections.unmodifiableList(newPhases);
  15.190 +        private static List<CompilationPhase> concatPhases(final CompilationPhases[] bases) {
  15.191 +            final ArrayList<CompilationPhase> l = new ArrayList<>();
  15.192 +            for(final CompilationPhases base: bases) {
  15.193 +                l.addAll(base.phases);
  15.194 +            }
  15.195 +            l.trimToSize();
  15.196 +            return l;
  15.197 +        }
  15.198 +
  15.199 +        private static <T> List<T> concat(final List<T> l1, final List<T> l2) {
  15.200 +            final ArrayList<T> l = new ArrayList<>(l1);
  15.201 +            l.addAll(l2);
  15.202 +            l.trimToSize();
  15.203 +            return l;
  15.204          }
  15.205  
  15.206          @Override
  15.207 @@ -235,45 +303,6 @@
  15.208              return "'" + desc + "' " + phases.toString();
  15.209          }
  15.210  
  15.211 -        private CompilationPhases setDescription(final String desc) {
  15.212 -            return new CompilationPhases(desc, phases.toArray(new CompilationPhase[phases.size()]));
  15.213 -        }
  15.214 -
  15.215 -        private CompilationPhases removeLast() {
  15.216 -            final LinkedList<CompilationPhase> list = new LinkedList<>(phases);
  15.217 -            list.removeLast();
  15.218 -            return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()]));
  15.219 -        }
  15.220 -
  15.221 -        private CompilationPhases addFirst(final CompilationPhase phase) {
  15.222 -            if (phases.contains(phase)) {
  15.223 -                return this;
  15.224 -            }
  15.225 -            final LinkedList<CompilationPhase> list = new LinkedList<>(phases);
  15.226 -            list.addFirst(phase);
  15.227 -            return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()]));
  15.228 -        }
  15.229 -
  15.230 -        @SuppressWarnings("unused") //TODO I'll use this soon
  15.231 -        private CompilationPhases replace(final CompilationPhase phase, final CompilationPhase newPhase) {
  15.232 -            final LinkedList<CompilationPhase> list = new LinkedList<>();
  15.233 -            for (final CompilationPhase p : phases) {
  15.234 -                list.add(p == phase ? newPhase : p);
  15.235 -            }
  15.236 -            return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()]));
  15.237 -        }
  15.238 -
  15.239 -        private CompilationPhases addAfter(final CompilationPhase phase, final CompilationPhase newPhase) {
  15.240 -            final LinkedList<CompilationPhase> list = new LinkedList<>();
  15.241 -            for (final CompilationPhase p : phases) {
  15.242 -                list.add(p);
  15.243 -                if (p == phase) {
  15.244 -                    list.add(newPhase);
  15.245 -                }
  15.246 -            }
  15.247 -            return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()]));
  15.248 -        }
  15.249 -
  15.250          boolean contains(final CompilationPhase phase) {
  15.251              return phases.contains(phase);
  15.252          }
  15.253 @@ -284,7 +313,7 @@
  15.254          }
  15.255  
  15.256          boolean isRestOfCompilation() {
  15.257 -            return this == COMPILE_ALL_RESTOF || this == COMPILE_FROM_BYTECODE_RESTOF;
  15.258 +            return this == COMPILE_ALL_RESTOF || this == GENERATE_BYTECODE_AND_INSTALL_RESTOF || this == COMPILE_SERIALIZED_RESTOF;
  15.259          }
  15.260  
  15.261          String getDesc() {
  15.262 @@ -410,10 +439,29 @@
  15.263              baseName = baseName + installer.getUniqueScriptId();
  15.264          }
  15.265  
  15.266 -        final String mangled = NameCodec.encode(baseName);
  15.267 +        // ASM's bytecode verifier does not allow JVM allowed safe escapes using '\' as escape char.
  15.268 +        // While ASM accepts such escapes for method names, field names, it enforces Java identifier
  15.269 +        // for class names. Workaround that ASM bug here by replacing JVM 'dangerous' chars with '_'
  15.270 +        // rather than safe encoding using '\'.
  15.271 +        final String mangled = env._verify_code? replaceDangerChars(baseName) : NameCodec.encode(baseName);
  15.272          return mangled != null ? mangled : baseName;
  15.273      }
  15.274  
  15.275 +    private static final String DANGEROUS_CHARS   = "\\/.;:$[]<>";
  15.276 +    private static String replaceDangerChars(final String name) {
  15.277 +        final int len = name.length();
  15.278 +        final StringBuilder buf = new StringBuilder();
  15.279 +        for (int i = 0; i < len; i++) {
  15.280 +            final char ch = name.charAt(i);
  15.281 +            if (DANGEROUS_CHARS.indexOf(ch) != -1) {
  15.282 +                buf.append('_');
  15.283 +            } else {
  15.284 +                buf.append(ch);
  15.285 +            }
  15.286 +        }
  15.287 +        return buf.toString();
  15.288 +    }
  15.289 +
  15.290      private String firstCompileUnitName() {
  15.291          final StringBuilder sb = new StringBuilder(SCRIPTS_PACKAGE).
  15.292                  append('/').
  15.293 @@ -730,6 +778,14 @@
  15.294          compileUnits.addAll(newUnits);
  15.295      }
  15.296  
  15.297 +    void serializeAst(final FunctionNode fn) {
  15.298 +        serializedAsts.put(fn.getId(), AstSerializer.serialize(fn));
  15.299 +    }
  15.300 +
  15.301 +    byte[] removeSerializedAst(final int fnId) {
  15.302 +        return serializedAsts.remove(fnId);
  15.303 +    }
  15.304 +
  15.305      CompileUnit findUnit(final long weight) {
  15.306          for (final CompileUnit unit : compileUnits) {
  15.307              if (unit.canHold(weight)) {
  15.308 @@ -752,7 +808,10 @@
  15.309      }
  15.310  
  15.311      RecompilableScriptFunctionData getScriptFunctionData(final int functionId) {
  15.312 -        return compiledFunction == null ? null : compiledFunction.getScriptFunctionData(functionId);
  15.313 +        assert compiledFunction != null;
  15.314 +        final RecompilableScriptFunctionData fn = compiledFunction.getScriptFunctionData(functionId);
  15.315 +        assert fn != null : functionId;
  15.316 +        return fn;
  15.317      }
  15.318  
  15.319      boolean isGlobalSymbol(final FunctionNode fn, final String name) {
    16.1 --- a/src/jdk/nashorn/internal/codegen/FindScopeDepths.java	Mon Oct 27 14:36:13 2014 -0700
    16.2 +++ b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java	Thu Nov 06 09:50:15 2014 -0800
    16.3 @@ -187,7 +187,6 @@
    16.4  
    16.5          if (compiler.isOnDemandCompilation()) {
    16.6              final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(newFunctionNode.getId());
    16.7 -            assert data != null : newFunctionNode.getName() + " lacks data";
    16.8              if (data.inDynamicContext()) {
    16.9                  log.fine("Reviving scriptfunction ", quote(name), " as defined in previous (now lost) dynamic scope.");
   16.10                  newFunctionNode = newFunctionNode.setInDynamicContext(lc);
   16.11 @@ -202,7 +201,7 @@
   16.12  
   16.13          //create recompilable scriptfunctiondata
   16.14          final int fnId = newFunctionNode.getId();
   16.15 -        final Map<Integer, RecompilableScriptFunctionData> nestedFunctions = fnIdToNestedFunctions.get(fnId);
   16.16 +        final Map<Integer, RecompilableScriptFunctionData> nestedFunctions = fnIdToNestedFunctions.remove(fnId);
   16.17  
   16.18          assert nestedFunctions != null;
   16.19          // Generate the object class and property map in case this function is ever used as constructor
   16.20 @@ -212,8 +211,8 @@
   16.21                  new AllocatorDescriptor(newFunctionNode.getThisProperties()),
   16.22                  nestedFunctions,
   16.23                  externalSymbolDepths.get(fnId),
   16.24 -                internalSymbols.get(fnId)
   16.25 -                );
   16.26 +                internalSymbols.get(fnId),
   16.27 +                compiler.removeSerializedAst(fnId));
   16.28  
   16.29          if (lc.getOutermostFunction() != newFunctionNode) {
   16.30              final FunctionNode parentFn = lc.getParentFunction(newFunctionNode);
    17.1 --- a/src/jdk/nashorn/internal/codegen/FoldConstants.java	Mon Oct 27 14:36:13 2014 -0700
    17.2 +++ b/src/jdk/nashorn/internal/codegen/FoldConstants.java	Thu Nov 06 09:50:15 2014 -0800
    17.3 @@ -291,7 +291,7 @@
    17.4                  value = lhs.getNumber() - rhs.getNumber();
    17.5                  break;
    17.6              case SHR:
    17.7 -                return LiteralNode.newInstance(token, finish, (lhs.getInt32() >>> rhs.getInt32()) & JSType.MAX_UINT);
    17.8 +                return LiteralNode.newInstance(token, finish, JSType.toUint32(lhs.getInt32() >>> rhs.getInt32()));
    17.9              case SAR:
   17.10                  return LiteralNode.newInstance(token, finish, lhs.getInt32() >> rhs.getInt32());
   17.11              case SHL:
    18.1 --- a/src/jdk/nashorn/internal/codegen/Label.java	Mon Oct 27 14:36:13 2014 -0700
    18.2 +++ b/src/jdk/nashorn/internal/codegen/Label.java	Thu Nov 06 09:50:15 2014 -0800
    18.3 @@ -24,6 +24,7 @@
    18.4   */
    18.5  package jdk.nashorn.internal.codegen;
    18.6  
    18.7 +import java.io.Serializable;
    18.8  import java.util.ArrayList;
    18.9  import java.util.Arrays;
   18.10  import java.util.BitSet;
   18.11 @@ -39,7 +40,9 @@
   18.12   *
   18.13   * see -Dnashorn.codegen.debug, --log=codegen
   18.14   */
   18.15 -public final class Label {
   18.16 +public final class Label implements Serializable {
   18.17 +    private static final long serialVersionUID = 1L;
   18.18 +
   18.19      //byte code generation evaluation type stack for consistency check
   18.20      //and correct opcode selection. one per label as a label may be a
   18.21      //join point
   18.22 @@ -491,7 +494,7 @@
   18.23      private final String name;
   18.24  
   18.25      /** Type stack at this label */
   18.26 -    private Label.Stack stack;
   18.27 +    private transient Label.Stack stack;
   18.28  
   18.29      /** ASM representation of this label */
   18.30      private jdk.internal.org.objectweb.asm.Label label;
   18.31 @@ -500,9 +503,9 @@
   18.32      private final int id;
   18.33  
   18.34      /** Is this label reachable (anything ever jumped to it)? */
   18.35 -    private boolean reachable;
   18.36 +    private transient boolean reachable;
   18.37  
   18.38 -    private boolean breakTarget;
   18.39 +    private transient boolean breakTarget;
   18.40  
   18.41      /**
   18.42       * Constructor
    19.1 --- a/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Mon Oct 27 14:36:13 2014 -0700
    19.2 +++ b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Thu Nov 06 09:50:15 2014 -0800
    19.3 @@ -72,7 +72,7 @@
    19.4  import jdk.nashorn.internal.ir.ReturnNode;
    19.5  import jdk.nashorn.internal.ir.RuntimeNode;
    19.6  import jdk.nashorn.internal.ir.RuntimeNode.Request;
    19.7 -import jdk.nashorn.internal.ir.SplitNode;
    19.8 +import jdk.nashorn.internal.ir.SplitReturn;
    19.9  import jdk.nashorn.internal.ir.Statement;
   19.10  import jdk.nashorn.internal.ir.SwitchNode;
   19.11  import jdk.nashorn.internal.ir.Symbol;
   19.12 @@ -361,10 +361,6 @@
   19.13      // Synthetic return node that we must insert at the end of the function if it's end is reachable.
   19.14      private ReturnNode syntheticReturn;
   19.15  
   19.16 -    // Topmost current split node (if any)
   19.17 -    private SplitNode topSplit;
   19.18 -    private boolean split;
   19.19 -
   19.20      private boolean alreadyEnteredTopLevelFunction;
   19.21  
   19.22      // LvarType and conversion information gathered during the top-down pass; applied to nodes in the bottom-up pass.
   19.23 @@ -477,22 +473,7 @@
   19.24              return false;
   19.25          }
   19.26          final BreakableNode target = jump.getTarget(lc);
   19.27 -        return splitAwareJumpToLabel(jump, target, jump.getTargetLabel(target));
   19.28 -    }
   19.29 -
   19.30 -    private boolean splitAwareJumpToLabel(final JumpStatement jumpStatement, final BreakableNode target, final Label targetLabel) {
   19.31 -        final JoinPredecessor jumpOrigin;
   19.32 -        if(topSplit != null && lc.isExternalTarget(topSplit, target)) {
   19.33 -            // If the jump target is outside the topmost split node, then we'll create a synthetic jump origin in the
   19.34 -            // split node.
   19.35 -            jumpOrigin = new JoinPredecessorExpression();
   19.36 -            topSplit.addJump(jumpOrigin, targetLabel);
   19.37 -        } else {
   19.38 -            // Otherwise, the original jump statement is the jump origin
   19.39 -            jumpOrigin = jumpStatement;
   19.40 -        }
   19.41 -
   19.42 -        jumpToLabel(jumpOrigin, targetLabel, getBreakTargetTypes(target));
   19.43 +        jumpToLabel(jump, jump.getTargetLabel(target), getBreakTargetTypes(target));
   19.44          doesNotContinueSequentially();
   19.45          return false;
   19.46      }
   19.47 @@ -703,18 +684,9 @@
   19.48      }
   19.49  
   19.50      @Override
   19.51 -    public boolean enterSplitNode(final SplitNode splitNode) {
   19.52 -        if(!reachable) {
   19.53 -            return false;
   19.54 -        }
   19.55 -        // Need to visit inside of split nodes. While it's true that they don't have local variables, we need to visit
   19.56 -        // breaks, continues, and returns in them.
   19.57 -        if(topSplit == null) {
   19.58 -            topSplit = splitNode;
   19.59 -        }
   19.60 -        split = true;
   19.61 -        setType(getCompilerConstantSymbol(lc.getCurrentFunction(), CompilerConstants.RETURN), LvarType.UNDEFINED);
   19.62 -        return true;
   19.63 +    public boolean enterSplitReturn(final SplitReturn splitReturn) {
   19.64 +        doesNotContinueSequentially();
   19.65 +        return false;
   19.66      }
   19.67  
   19.68      @Override
   19.69 @@ -1116,15 +1088,6 @@
   19.70          if(returnType.isUnknown()) {
   19.71              returnType = Type.OBJECT;
   19.72          }
   19.73 -
   19.74 -        if(split) {
   19.75 -            // If the function is split, the ":return" symbol is used and needs a slot. Note we can't mark the return
   19.76 -            // symbol as used in enterSplitNode, as we don't know the final return type of the function earlier than
   19.77 -            // here.
   19.78 -            final Symbol retSymbol = getCompilerConstantSymbol(lc.getCurrentFunction(), CompilerConstants.RETURN);
   19.79 -            retSymbol.setHasSlotFor(returnType);
   19.80 -            retSymbol.setNeedsSlot(true);
   19.81 -        }
   19.82      }
   19.83  
   19.84      private void createSyntheticReturn(final Block body) {
    20.1 --- a/src/jdk/nashorn/internal/codegen/Lower.java	Mon Oct 27 14:36:13 2014 -0700
    20.2 +++ b/src/jdk/nashorn/internal/codegen/Lower.java	Thu Nov 06 09:50:15 2014 -0800
    20.3 @@ -352,8 +352,6 @@
    20.4      private Node spliceFinally(final TryNode tryNode, final List<ThrowNode> rethrows, final Block finallyBody) {
    20.5          assert tryNode.getFinallyBody() == null;
    20.6  
    20.7 -        final LexicalContext lowerLc = lc;
    20.8 -
    20.9          final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   20.10              final List<Node> insideTry = new ArrayList<>();
   20.11  
   20.12 @@ -406,7 +404,6 @@
   20.13                      //still in the try block, store it in a result value and return it afterwards
   20.14                      resultNode = new IdentNode(Lower.this.compilerConstant(RETURN));
   20.15                      newStatements.add(new ExpressionStatement(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new BinaryNode(Token.recast(returnNode.getToken(), TokenType.ASSIGN), resultNode, expr)));
   20.16 -                    lowerLc.setFlag(lowerLc.getCurrentFunction(), FunctionNode.USES_RETURN_SYMBOL);
   20.17                  } else {
   20.18                      resultNode = null;
   20.19                  }
    21.1 --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Mon Oct 27 14:36:13 2014 -0700
    21.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Thu Nov 06 09:50:15 2014 -0800
    21.3 @@ -71,6 +71,7 @@
    21.4  import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE;
    21.5  import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC;
    21.6  import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
    21.7 +
    21.8  import java.io.PrintStream;
    21.9  import java.lang.reflect.Array;
   21.10  import java.util.Collection;
   21.11 @@ -88,17 +89,16 @@
   21.12  import jdk.nashorn.internal.codegen.types.BitwiseType;
   21.13  import jdk.nashorn.internal.codegen.types.NumericType;
   21.14  import jdk.nashorn.internal.codegen.types.Type;
   21.15 -import jdk.nashorn.internal.ir.BreakableNode;
   21.16  import jdk.nashorn.internal.ir.FunctionNode;
   21.17  import jdk.nashorn.internal.ir.IdentNode;
   21.18  import jdk.nashorn.internal.ir.JoinPredecessor;
   21.19 -import jdk.nashorn.internal.ir.LexicalContext;
   21.20  import jdk.nashorn.internal.ir.LiteralNode;
   21.21  import jdk.nashorn.internal.ir.LocalVariableConversion;
   21.22  import jdk.nashorn.internal.ir.RuntimeNode;
   21.23  import jdk.nashorn.internal.ir.Symbol;
   21.24  import jdk.nashorn.internal.ir.TryNode;
   21.25  import jdk.nashorn.internal.objects.Global;
   21.26 +import jdk.nashorn.internal.objects.NativeArray;
   21.27  import jdk.nashorn.internal.runtime.ArgumentSetter;
   21.28  import jdk.nashorn.internal.runtime.Context;
   21.29  import jdk.nashorn.internal.runtime.Debug;
   21.30 @@ -1663,19 +1663,6 @@
   21.31      }
   21.32  
   21.33      /**
   21.34 -     * Goto, possibly when splitting is taking place. If
   21.35 -     * a splitNode exists, we need to handle the case that the
   21.36 -     * jump target is another method
   21.37 -     *
   21.38 -     * @param label destination label
   21.39 -     * @param targetNode the node to which the destination label belongs (the label is normally a break or continue
   21.40 -     * label)
   21.41 -     */
   21.42 -    void splitAwareGoto(final LexicalContext lc, final Label label, final BreakableNode targetNode) {
   21.43 -        _goto(label);
   21.44 -    }
   21.45 -
   21.46 -    /**
   21.47       * Perform a comparison of two number types that are popped from the stack
   21.48       *
   21.49       * @param isCmpG is this a dcmpg semantic, false if it's a dcmpl semantic
   21.50 @@ -2126,7 +2113,14 @@
   21.51  
   21.52          int pos = 0;
   21.53          for (int i = argCount - 1; i >= 0; i--) {
   21.54 -            paramTypes[i] = stack.peek(pos++);
   21.55 +            Type pt = stack.peek(pos++);
   21.56 +            // "erase" specific ScriptObject subtype info - except for NativeArray.
   21.57 +            // NativeArray is used for array/List/Deque conversion for Java calls.
   21.58 +            if (ScriptObject.class.isAssignableFrom(pt.getTypeClass()) &&
   21.59 +                !NativeArray.class.isAssignableFrom(pt.getTypeClass())) {
   21.60 +                pt = Type.SCRIPT_OBJECT;
   21.61 +            }
   21.62 +            paramTypes[i] = pt;
   21.63          }
   21.64          final String descriptor = Type.getMethodDescriptor(returnType, paramTypes);
   21.65          for (int i = 0; i < argCount; i++) {
    22.1 --- a/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java	Mon Oct 27 14:36:13 2014 -0700
    22.2 +++ b/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java	Thu Nov 06 09:50:15 2014 -0800
    22.3 @@ -30,7 +30,6 @@
    22.4  import java.util.ArrayDeque;
    22.5  import java.util.BitSet;
    22.6  import java.util.Deque;
    22.7 -import jdk.nashorn.internal.IntDeque;
    22.8  import jdk.nashorn.internal.ir.AccessNode;
    22.9  import jdk.nashorn.internal.ir.BinaryNode;
   22.10  import jdk.nashorn.internal.ir.CallNode;
   22.11 @@ -49,7 +48,6 @@
   22.12  import jdk.nashorn.internal.ir.Node;
   22.13  import jdk.nashorn.internal.ir.Optimistic;
   22.14  import jdk.nashorn.internal.ir.PropertyNode;
   22.15 -import jdk.nashorn.internal.ir.SplitNode;
   22.16  import jdk.nashorn.internal.ir.Symbol;
   22.17  import jdk.nashorn.internal.ir.TernaryNode;
   22.18  import jdk.nashorn.internal.ir.UnaryNode;
   22.19 @@ -70,8 +68,6 @@
   22.20  
   22.21      // Per-function bit set of program points that must never be optimistic.
   22.22      final Deque<BitSet> neverOptimistic = new ArrayDeque<>();
   22.23 -    // Per-function depth of split nodes
   22.24 -    final IntDeque splitDepth = new IntDeque();
   22.25  
   22.26      OptimisticTypesCalculator(final Compiler compiler) {
   22.27          super(new LexicalContext());
   22.28 @@ -155,7 +151,6 @@
   22.29              return false;
   22.30          }
   22.31          neverOptimistic.push(new BitSet());
   22.32 -        splitDepth.push(0);
   22.33          return true;
   22.34      }
   22.35  
   22.36 @@ -190,19 +185,6 @@
   22.37      }
   22.38  
   22.39      @Override
   22.40 -    public boolean enterSplitNode(final SplitNode splitNode) {
   22.41 -        splitDepth.getAndIncrement();
   22.42 -        return true;
   22.43 -    }
   22.44 -
   22.45 -    @Override
   22.46 -    public Node leaveSplitNode(final SplitNode splitNode) {
   22.47 -        final int depth = splitDepth.decrementAndGet();
   22.48 -        assert depth >= 0;
   22.49 -        return splitNode;
   22.50 -    }
   22.51 -
   22.52 -    @Override
   22.53      public boolean enterVarNode(final VarNode varNode) {
   22.54          tagNeverOptimistic(varNode.getName());
   22.55          return true;
   22.56 @@ -226,16 +208,11 @@
   22.57      @Override
   22.58      public Node leaveFunctionNode(final FunctionNode functionNode) {
   22.59          neverOptimistic.pop();
   22.60 -        final int lastSplitDepth = splitDepth.pop();
   22.61 -        assert lastSplitDepth == 0;
   22.62          return functionNode.setState(lc, CompilationState.OPTIMISTIC_TYPES_ASSIGNED);
   22.63      }
   22.64  
   22.65      @Override
   22.66      public Node leaveIdentNode(final IdentNode identNode) {
   22.67 -        if(inSplitNode()) {
   22.68 -            return identNode;
   22.69 -        }
   22.70          final Symbol symbol = identNode.getSymbol();
   22.71          if(symbol == null) {
   22.72              assert identNode.isPropertyName();
   22.73 @@ -256,7 +233,7 @@
   22.74  
   22.75      private Expression leaveOptimistic(final Optimistic opt) {
   22.76          final int pp = opt.getProgramPoint();
   22.77 -        if(isValid(pp) && !inSplitNode() && !neverOptimistic.peek().get(pp)) {
   22.78 +        if(isValid(pp) && !neverOptimistic.peek().get(pp)) {
   22.79              return (Expression)opt.setType(compiler.getOptimisticType(opt));
   22.80          }
   22.81          return (Expression)opt;
   22.82 @@ -277,8 +254,4 @@
   22.83              tagNeverOptimistic(test.getExpression());
   22.84          }
   22.85      }
   22.86 -
   22.87 -    private boolean inSplitNode() {
   22.88 -        return splitDepth.peek() > 0;
   22.89 -    }
   22.90  }
    23.1 --- a/src/jdk/nashorn/internal/codegen/ProgramPoints.java	Mon Oct 27 14:36:13 2014 -0700
    23.2 +++ b/src/jdk/nashorn/internal/codegen/ProgramPoints.java	Thu Nov 06 09:50:15 2014 -0800
    23.3 @@ -85,7 +85,7 @@
    23.4  
    23.5      @Override
    23.6      public boolean enterVarNode(final VarNode varNode) {
    23.7 -        noProgramPoint.add(varNode.getAssignmentDest());
    23.8 +        noProgramPoint.add(varNode.getName());
    23.9          return true;
   23.10      }
   23.11  
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java	Thu Nov 06 09:50:15 2014 -0800
    24.3 @@ -0,0 +1,85 @@
    24.4 +/*
    24.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    24.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    24.7 + *
    24.8 + * This code is free software; you can redistribute it and/or modify it
    24.9 + * under the terms of the GNU General Public License version 2 only, as
   24.10 + * published by the Free Software Foundation.  Oracle designates this
   24.11 + * particular file as subject to the "Classpath" exception as provided
   24.12 + * by Oracle in the LICENSE file that accompanied this code.
   24.13 + *
   24.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   24.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   24.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   24.17 + * version 2 for more details (a copy is included in the LICENSE file that
   24.18 + * accompanied this code).
   24.19 + *
   24.20 + * You should have received a copy of the GNU General Public License version
   24.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   24.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   24.23 + *
   24.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   24.25 + * or visit www.oracle.com if you need additional information or have any
   24.26 + * questions.
   24.27 + */
   24.28 +
   24.29 +package jdk.nashorn.internal.codegen;
   24.30 +
   24.31 +import java.util.ArrayList;
   24.32 +import java.util.List;
   24.33 +import jdk.nashorn.internal.ir.CompileUnitHolder;
   24.34 +import jdk.nashorn.internal.ir.FunctionNode;
   24.35 +import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
   24.36 +import jdk.nashorn.internal.ir.LexicalContext;
   24.37 +import jdk.nashorn.internal.ir.LiteralNode;
   24.38 +import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
   24.39 +import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
   24.40 +import jdk.nashorn.internal.ir.Node;
   24.41 +import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   24.42 +
   24.43 +/**
   24.44 + * Base class for a node visitor that replaces {@link CompileUnit}s in {@link CompileUnitHolder}s.
   24.45 + */
   24.46 +abstract class ReplaceCompileUnits extends NodeVisitor<LexicalContext> {
   24.47 +    ReplaceCompileUnits() {
   24.48 +        super(new LexicalContext());
   24.49 +    }
   24.50 +
   24.51 +    /**
   24.52 +     * Override to provide a replacement for an old compile unit.
   24.53 +     * @param oldUnit the old compile unit to replace
   24.54 +     * @return the compile unit's replacement.
   24.55 +     */
   24.56 +    abstract CompileUnit getReplacement(final CompileUnit oldUnit);
   24.57 +
   24.58 +    CompileUnit getExistingReplacement(final CompileUnitHolder node) {
   24.59 +        final CompileUnit oldUnit = node.getCompileUnit();
   24.60 +        assert oldUnit != null;
   24.61 +
   24.62 +        final CompileUnit newUnit = getReplacement(oldUnit);
   24.63 +        assert newUnit != null;
   24.64 +
   24.65 +        return newUnit;
   24.66 +    }
   24.67 +
   24.68 +    @Override
   24.69 +    public Node leaveFunctionNode(final FunctionNode node) {
   24.70 +        return node.setCompileUnit(lc, getExistingReplacement(node)).setState(lc, CompilationState.COMPILE_UNITS_REUSED);
   24.71 +    }
   24.72 +
   24.73 +    @Override
   24.74 +    public Node leaveLiteralNode(final LiteralNode<?> node) {
   24.75 +        if (node instanceof ArrayLiteralNode) {
   24.76 +            final ArrayLiteralNode aln = (ArrayLiteralNode)node;
   24.77 +            if (aln.getUnits() == null) {
   24.78 +                return node;
   24.79 +            }
   24.80 +            final List<ArrayUnit> newArrayUnits = new ArrayList<>();
   24.81 +            for (final ArrayUnit au : aln.getUnits()) {
   24.82 +                newArrayUnits.add(new ArrayUnit(getExistingReplacement(au), au.getLo(), au.getHi()));
   24.83 +            }
   24.84 +            return aln.setUnits(lc, newArrayUnits);
   24.85 +        }
   24.86 +        return node;
   24.87 +    }
   24.88 +}
    25.1 --- a/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java	Mon Oct 27 14:36:13 2014 -0700
    25.2 +++ b/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java	Thu Nov 06 09:50:15 2014 -0800
    25.3 @@ -88,7 +88,7 @@
    25.4                      final Property property = propertyMap.findProperty(key);
    25.5                      if (property != null) {
    25.6                          // normal property key
    25.7 -                        property.setCurrentType(JSType.unboxedFieldType(constantValue));
    25.8 +                        property.setType(JSType.unboxedFieldType(constantValue));
    25.9                          final int slot = property.getSlot();
   25.10                          if (!OBJECT_FIELDS_ONLY && constantValue instanceof Number) {
   25.11                              jpresetValues[slot] = ObjectClassGenerator.pack((Number)constantValue);
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java	Thu Nov 06 09:50:15 2014 -0800
    26.3 @@ -0,0 +1,446 @@
    26.4 +/*
    26.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    26.7 + *
    26.8 + * This code is free software; you can redistribute it and/or modify it
    26.9 + * under the terms of the GNU General Public License version 2 only, as
   26.10 + * published by the Free Software Foundation.  Oracle designates this
   26.11 + * particular file as subject to the "Classpath" exception as provided
   26.12 + * by Oracle in the LICENSE file that accompanied this code.
   26.13 + *
   26.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   26.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   26.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   26.17 + * version 2 for more details (a copy is included in the LICENSE file that
   26.18 + * accompanied this code).
   26.19 + *
   26.20 + * You should have received a copy of the GNU General Public License version
   26.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   26.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   26.23 + *
   26.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   26.25 + * or visit www.oracle.com if you need additional information or have any
   26.26 + * questions.
   26.27 + */
   26.28 +
   26.29 +package jdk.nashorn.internal.codegen;
   26.30 +
   26.31 +import static jdk.nashorn.internal.ir.Node.NO_FINISH;
   26.32 +import static jdk.nashorn.internal.ir.Node.NO_LINE_NUMBER;
   26.33 +import static jdk.nashorn.internal.ir.Node.NO_TOKEN;
   26.34 +
   26.35 +import java.util.ArrayDeque;
   26.36 +import java.util.ArrayList;
   26.37 +import java.util.Arrays;
   26.38 +import java.util.Collections;
   26.39 +import java.util.Deque;
   26.40 +import java.util.List;
   26.41 +import java.util.Objects;
   26.42 +import jdk.nashorn.internal.ir.AccessNode;
   26.43 +import jdk.nashorn.internal.ir.BinaryNode;
   26.44 +import jdk.nashorn.internal.ir.Block;
   26.45 +import jdk.nashorn.internal.ir.BlockLexicalContext;
   26.46 +import jdk.nashorn.internal.ir.BreakNode;
   26.47 +import jdk.nashorn.internal.ir.CallNode;
   26.48 +import jdk.nashorn.internal.ir.CaseNode;
   26.49 +import jdk.nashorn.internal.ir.ContinueNode;
   26.50 +import jdk.nashorn.internal.ir.Expression;
   26.51 +import jdk.nashorn.internal.ir.ExpressionStatement;
   26.52 +import jdk.nashorn.internal.ir.FunctionNode;
   26.53 +import jdk.nashorn.internal.ir.GetSplitState;
   26.54 +import jdk.nashorn.internal.ir.IdentNode;
   26.55 +import jdk.nashorn.internal.ir.IfNode;
   26.56 +import jdk.nashorn.internal.ir.JumpStatement;
   26.57 +import jdk.nashorn.internal.ir.LiteralNode;
   26.58 +import jdk.nashorn.internal.ir.Node;
   26.59 +import jdk.nashorn.internal.ir.ReturnNode;
   26.60 +import jdk.nashorn.internal.ir.SetSplitState;
   26.61 +import jdk.nashorn.internal.ir.SplitNode;
   26.62 +import jdk.nashorn.internal.ir.SplitReturn;
   26.63 +import jdk.nashorn.internal.ir.Statement;
   26.64 +import jdk.nashorn.internal.ir.SwitchNode;
   26.65 +import jdk.nashorn.internal.ir.VarNode;
   26.66 +import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   26.67 +import jdk.nashorn.internal.parser.Token;
   26.68 +import jdk.nashorn.internal.parser.TokenType;
   26.69 +
   26.70 +/**
   26.71 + * A node visitor that replaces {@link SplitNode}s with anonymous function invocations and some additional constructs
   26.72 + * to support control flow across splits. By using this transformation, split functions are translated into ordinary
   26.73 + * JavaScript functions with nested anonymous functions. The transformations however introduce several AST nodes that
   26.74 + * have no JavaScript source representations ({@link GetSplitState}, {@link SetSplitState}, and {@link SplitReturn}),
   26.75 + * and therefore such function is no longer reparseable from its source. For that reason, split functions and their
   26.76 + * fragments are serialized in-memory and deserialized when they need to be recompiled either for deoptimization or
   26.77 + * for type specialization.
   26.78 + * NOTE: all {@code leave*()} methods for statements are returning their input nodes. That way, they will not mutate
   26.79 + * the original statement list in the block containing the statement, which is fine, as it'll be replaced by the
   26.80 + * lexical context when the block is left. If we returned something else (e.g. null), we'd cause a mutation in the
   26.81 + * enclosing block's statement list that is otherwise overwritten later anyway.
   26.82 + */
   26.83 +final class SplitIntoFunctions extends NodeVisitor<BlockLexicalContext> {
   26.84 +    private static final int FALLTHROUGH_STATE = -1;
   26.85 +    private static final int RETURN_STATE = 0;
   26.86 +    private static final int BREAK_STATE = 1;
   26.87 +    private static final int FIRST_JUMP_STATE = 2;
   26.88 +
   26.89 +    private static final String THIS_NAME = CompilerConstants.THIS.symbolName();
   26.90 +    private static final String RETURN_NAME = CompilerConstants.RETURN.symbolName();
   26.91 +    // Used as the name of the formal parameter for passing the current value of :return symbol into a split fragment.
   26.92 +    private static final String RETURN_PARAM_NAME = RETURN_NAME + "-in";
   26.93 +
   26.94 +    private final Deque<FunctionState> functionStates = new ArrayDeque<>();
   26.95 +    private final Deque<SplitState> splitStates = new ArrayDeque<>();
   26.96 +    private final Namespace namespace;
   26.97 +
   26.98 +    private boolean artificialBlock = false;
   26.99 +
  26.100 +    // -1 is program; we need to use negative ones
  26.101 +    private int nextFunctionId = -2;
  26.102 +
  26.103 +    public SplitIntoFunctions(final Compiler compiler) {
  26.104 +        super(new BlockLexicalContext() {
  26.105 +            @Override
  26.106 +            protected Block afterSetStatements(Block block) {
  26.107 +                for(Statement stmt: block.getStatements()) {
  26.108 +                    assert !(stmt instanceof SplitNode);
  26.109 +                }
  26.110 +                return block;
  26.111 +            }
  26.112 +        });
  26.113 +        namespace = new Namespace(compiler.getScriptEnvironment().getNamespace());
  26.114 +    }
  26.115 +
  26.116 +    @Override
  26.117 +    public boolean enterFunctionNode(final FunctionNode functionNode) {
  26.118 +        functionStates.push(new FunctionState(functionNode));
  26.119 +        return true;
  26.120 +    }
  26.121 +
  26.122 +    @Override
  26.123 +    public Node leaveFunctionNode(final FunctionNode functionNode) {
  26.124 +        functionStates.pop();
  26.125 +        return functionNode;
  26.126 +    }
  26.127 +
  26.128 +    @Override
  26.129 +    protected Node leaveDefault(final Node node) {
  26.130 +        if (node instanceof Statement) {
  26.131 +            appendStatement((Statement)node);
  26.132 +        }
  26.133 +        return node;
  26.134 +    }
  26.135 +
  26.136 +    @Override
  26.137 +    public boolean enterSplitNode(final SplitNode splitNode) {
  26.138 +        getCurrentFunctionState().splitDepth++;
  26.139 +        splitStates.push(new SplitState(splitNode));
  26.140 +        return true;
  26.141 +    }
  26.142 +
  26.143 +    @Override
  26.144 +    public Node leaveSplitNode(final SplitNode splitNode) {
  26.145 +        // Replace the split node with an anonymous function expression call.
  26.146 +
  26.147 +        final FunctionState fnState = getCurrentFunctionState();
  26.148 +
  26.149 +        final String name = splitNode.getName();
  26.150 +        Block body = splitNode.getBody();
  26.151 +        final int firstLineNumber = body.getFirstStatementLineNumber();
  26.152 +        final long token = body.getToken();
  26.153 +        final int finish = body.getFinish();
  26.154 +
  26.155 +        final FunctionNode originalFn = fnState.fn;
  26.156 +        assert originalFn == lc.getCurrentFunction();
  26.157 +        final boolean isProgram = originalFn.isProgram();
  26.158 +
  26.159 +        // Change SplitNode({...}) into "function () { ... }", or "function (:return-in) () { ... }" (for program)
  26.160 +        final long newFnToken = Token.toDesc(TokenType.FUNCTION, nextFunctionId--, 0);
  26.161 +        final FunctionNode fn = new FunctionNode(
  26.162 +                originalFn.getSource(),
  26.163 +                body.getFirstStatementLineNumber(),
  26.164 +                newFnToken,
  26.165 +                finish,
  26.166 +                NO_TOKEN,
  26.167 +                namespace,
  26.168 +                createIdent(name),
  26.169 +                originalFn.getName() + "$" + name,
  26.170 +                isProgram ? Collections.singletonList(createReturnParamIdent()) : Collections.<IdentNode>emptyList(),
  26.171 +                FunctionNode.Kind.NORMAL,
  26.172 +                // We only need IS_SPLIT conservatively, in case it contains any array units so that we force
  26.173 +                // the :callee's existence, to force :scope to never be in a slot lower than 2. This is actually
  26.174 +                // quite a horrible hack to do with CodeGenerator.fixScopeSlot not trampling other parameters
  26.175 +                // and should go away once we no longer have array unit handling in codegen. Note however that
  26.176 +                // we still use IS_SPLIT as the criteria in CompilationPhase.SERIALIZE_SPLIT_PHASE.
  26.177 +                FunctionNode.IS_ANONYMOUS | FunctionNode.USES_ANCESTOR_SCOPE | FunctionNode.IS_SPLIT
  26.178 +        )
  26.179 +        .setBody(lc, body)
  26.180 +        .setCompileUnit(lc, splitNode.getCompileUnit())
  26.181 +        .copyCompilationState(lc, originalFn);
  26.182 +
  26.183 +        // Call the function:
  26.184 +        //     either "(function () { ... }).call(this)"
  26.185 +        //     or     "(function (:return-in) { ... }).call(this, :return)"
  26.186 +        // NOTE: Function.call() has optimized linking that basically does a pass-through to the function being invoked.
  26.187 +        // NOTE: CompilationPhase.PROGRAM_POINT_PHASE happens after this, so these calls are subject to optimistic
  26.188 +        // assumptions on their return value (when they return a value), as they should be.
  26.189 +        final IdentNode thisIdent = createIdent(THIS_NAME);
  26.190 +        final CallNode callNode = new CallNode(firstLineNumber, token, finish, new AccessNode(NO_TOKEN, NO_FINISH, fn, "call"),
  26.191 +                isProgram ? Arrays.<Expression>asList(thisIdent, createReturnIdent())
  26.192 +                          : Collections.<Expression>singletonList(thisIdent),
  26.193 +                false);
  26.194 +
  26.195 +        final SplitState splitState = splitStates.pop();
  26.196 +        fnState.splitDepth--;
  26.197 +
  26.198 +        final Expression callWithReturn;
  26.199 +        final boolean hasReturn = splitState.hasReturn;
  26.200 +        if (hasReturn && fnState.splitDepth > 0) {
  26.201 +            final SplitState parentSplit = splitStates.peek();
  26.202 +            if (parentSplit != null) {
  26.203 +                // Propagate hasReturn to parent split
  26.204 +                parentSplit.hasReturn = true;
  26.205 +            }
  26.206 +        }
  26.207 +        if (hasReturn || isProgram) {
  26.208 +            // capture return value: ":return = (function () { ... })();"
  26.209 +            callWithReturn = new BinaryNode(Token.recast(token, TokenType.ASSIGN), createReturnIdent(), callNode);
  26.210 +        } else {
  26.211 +            // no return value, just call : "(function () { ... })();"
  26.212 +            callWithReturn = callNode;
  26.213 +        }
  26.214 +        appendStatement(new ExpressionStatement(firstLineNumber, token, finish, callWithReturn));
  26.215 +
  26.216 +        Statement splitStateHandler;
  26.217 +
  26.218 +        final List<JumpStatement> jumpStatements = splitState.jumpStatements;
  26.219 +        final int jumpCount = jumpStatements.size();
  26.220 +        // There are jumps (breaks or continues) that need to be propagated outside the split node. We need to
  26.221 +        // set up a switch statement for them:
  26.222 +        // switch(:scope.getScopeState()) { ... }
  26.223 +        if (jumpCount > 0) {
  26.224 +            final List<CaseNode> cases = new ArrayList<>(jumpCount + (hasReturn ? 1 : 0));
  26.225 +            if (hasReturn) {
  26.226 +                // If the split node also contained a return, we'll slip it as a case in the switch statement
  26.227 +                addCase(cases, RETURN_STATE, createReturnFromSplit());
  26.228 +            }
  26.229 +            int i = FIRST_JUMP_STATE;
  26.230 +            for (final JumpStatement jump: jumpStatements) {
  26.231 +                addCase(cases, i++, enblockAndVisit(jump));
  26.232 +            }
  26.233 +            splitStateHandler = new SwitchNode(NO_LINE_NUMBER, token, finish, GetSplitState.INSTANCE, cases, null);
  26.234 +        } else {
  26.235 +            splitStateHandler = null;
  26.236 +        }
  26.237 +
  26.238 +        // As the switch statement itself is breakable, an unlabelled break can't be in the switch statement,
  26.239 +        // so we need to test for it separately.
  26.240 +        if (splitState.hasBreak) {
  26.241 +            // if(:scope.getScopeState() == Scope.BREAK) { break; }
  26.242 +            splitStateHandler = makeIfStateEquals(firstLineNumber, token, finish, BREAK_STATE,
  26.243 +                    enblockAndVisit(new BreakNode(NO_LINE_NUMBER, token, finish, null)), splitStateHandler);
  26.244 +        }
  26.245 +
  26.246 +        // Finally, if the split node had a return statement, but there were no external jumps, we didn't have
  26.247 +        // the switch statement to handle the return, so we need a separate if for it.
  26.248 +        if (hasReturn && jumpCount == 0) {
  26.249 +            // if (:scope.getScopeState() == Scope.RETURN) { return :return; }
  26.250 +            splitStateHandler = makeIfStateEquals(NO_LINE_NUMBER, token, finish, RETURN_STATE,
  26.251 +                    createReturnFromSplit(), splitStateHandler);
  26.252 +        }
  26.253 +
  26.254 +        if (splitStateHandler != null) {
  26.255 +            appendStatement(splitStateHandler);
  26.256 +        }
  26.257 +
  26.258 +        return splitNode;
  26.259 +    }
  26.260 +
  26.261 +    private static void addCase(final List<CaseNode> cases, final int i, final Block body) {
  26.262 +        cases.add(new CaseNode(NO_TOKEN, NO_FINISH, intLiteral(i), body));
  26.263 +    }
  26.264 +
  26.265 +    private static LiteralNode<Number> intLiteral(final int i) {
  26.266 +        return LiteralNode.newInstance(NO_TOKEN, NO_FINISH, i);
  26.267 +    }
  26.268 +
  26.269 +    private static Block createReturnFromSplit() {
  26.270 +        return new Block(NO_TOKEN, NO_FINISH, createReturnReturn());
  26.271 +    }
  26.272 +
  26.273 +    private static ReturnNode createReturnReturn() {
  26.274 +        return new ReturnNode(NO_LINE_NUMBER, NO_TOKEN, NO_FINISH, createReturnIdent());
  26.275 +    }
  26.276 +
  26.277 +    private static IdentNode createReturnIdent() {
  26.278 +        return createIdent(RETURN_NAME);
  26.279 +    }
  26.280 +
  26.281 +    private static IdentNode createReturnParamIdent() {
  26.282 +        return createIdent(RETURN_PARAM_NAME);
  26.283 +    }
  26.284 +
  26.285 +    private static IdentNode createIdent(final String name) {
  26.286 +        return new IdentNode(NO_TOKEN, NO_FINISH, name);
  26.287 +    }
  26.288 +
  26.289 +    private Block enblockAndVisit(final JumpStatement jump) {
  26.290 +        artificialBlock = true;
  26.291 +        final Block block = (Block)new Block(NO_TOKEN, NO_FINISH, jump).accept(this);
  26.292 +        artificialBlock = false;
  26.293 +        return block;
  26.294 +    }
  26.295 +
  26.296 +    private static IfNode makeIfStateEquals(final int lineNumber, final long token, final int finish,
  26.297 +            final int value, final Block pass, final Statement fail) {
  26.298 +        return new IfNode(lineNumber, token, finish,
  26.299 +                new BinaryNode(Token.recast(token, TokenType.EQ_STRICT),
  26.300 +                        GetSplitState.INSTANCE, intLiteral(value)),
  26.301 +                pass,
  26.302 +                fail == null ? null : new Block(NO_TOKEN, NO_FINISH, fail));
  26.303 +    }
  26.304 +
  26.305 +    @Override
  26.306 +    public boolean enterVarNode(VarNode varNode) {
  26.307 +        if (!inSplitNode()) {
  26.308 +            return super.enterVarNode(varNode);
  26.309 +        }
  26.310 +        assert !varNode.isBlockScoped(); //TODO: we must handle these too, but we currently don't
  26.311 +
  26.312 +        final Expression init = varNode.getInit();
  26.313 +        if (varNode.isAnonymousFunctionDeclaration()) {
  26.314 +            // We ain't moving anonymous function declarations.
  26.315 +            return super.enterVarNode(varNode);
  26.316 +        }
  26.317 +
  26.318 +        // Move a declaration-only var statement to the top of the outermost function.
  26.319 +        getCurrentFunctionState().varStatements.add(varNode.setInit(null));
  26.320 +        // If it had an initializer, replace it with an assignment expression statement. Note that "var" is a
  26.321 +        // statement, so it doesn't contribute to :return of the programs, therefore we are _not_ adding a
  26.322 +        // ":return = ..." assignment around the original assignment.
  26.323 +        if (init != null) {
  26.324 +            final long token = Token.recast(varNode.getToken(), TokenType.ASSIGN);
  26.325 +            new ExpressionStatement(varNode.getLineNumber(), token, varNode.getFinish(),
  26.326 +                    new BinaryNode(token, varNode.getName(), varNode.getInit())).accept(this);
  26.327 +        }
  26.328 +
  26.329 +        return false;
  26.330 +    }
  26.331 +
  26.332 +    @Override
  26.333 +    public Node leaveBlock(final Block block) {
  26.334 +        if (!artificialBlock) {
  26.335 +            if (lc.isFunctionBody()) {
  26.336 +                // Prepend declaration-only var statements to the top of the statement list.
  26.337 +                lc.prependStatements(getCurrentFunctionState().varStatements);
  26.338 +            } else if (lc.isSplitBody()) {
  26.339 +                appendSplitReturn(FALLTHROUGH_STATE, NO_LINE_NUMBER);
  26.340 +                if (getCurrentFunctionState().fn.isProgram()) {
  26.341 +                    // If we're splitting the program, make sure every shard ends with "return :return" and
  26.342 +                    // begins with ":return = :return-in;".
  26.343 +                    lc.prependStatement(new ExpressionStatement(NO_LINE_NUMBER, NO_TOKEN, NO_FINISH,
  26.344 +                            new BinaryNode(Token.toDesc(TokenType.ASSIGN, 0, 0), createReturnIdent(), createReturnParamIdent())));
  26.345 +                }
  26.346 +            }
  26.347 +        }
  26.348 +        return block;
  26.349 +    }
  26.350 +
  26.351 +    @Override
  26.352 +    public Node leaveBreakNode(final BreakNode breakNode) {
  26.353 +        return leaveJumpNode(breakNode);
  26.354 +    }
  26.355 +
  26.356 +    @Override
  26.357 +    public Node leaveContinueNode(final ContinueNode continueNode) {
  26.358 +        return leaveJumpNode(continueNode);
  26.359 +    }
  26.360 +
  26.361 +    private JumpStatement leaveJumpNode(final JumpStatement jump) {
  26.362 +        if (inSplitNode()) {
  26.363 +            final SplitState splitState = getCurrentSplitState();
  26.364 +            final SplitNode splitNode = splitState.splitNode;
  26.365 +            if (lc.isExternalTarget(splitNode, jump.getTarget(lc))) {
  26.366 +                appendSplitReturn(splitState.getSplitStateIndex(jump), jump.getLineNumber());
  26.367 +                return jump;
  26.368 +            }
  26.369 +        }
  26.370 +        appendStatement(jump);
  26.371 +        return jump;
  26.372 +    }
  26.373 +
  26.374 +    private void appendSplitReturn(final int splitState, final int lineNumber) {
  26.375 +        appendStatement(new SetSplitState(splitState, lineNumber));
  26.376 +        if (getCurrentFunctionState().fn.isProgram()) {
  26.377 +            // If we're splitting the program, make sure every fragment passes back :return
  26.378 +            appendStatement(createReturnReturn());
  26.379 +        } else {
  26.380 +            appendStatement(SplitReturn.INSTANCE);
  26.381 +        }
  26.382 +    }
  26.383 +
  26.384 +    @Override
  26.385 +    public Node leaveReturnNode(final ReturnNode returnNode) {
  26.386 +        if(inSplitNode()) {
  26.387 +            appendStatement(new SetSplitState(RETURN_STATE, returnNode.getLineNumber()));
  26.388 +            getCurrentSplitState().hasReturn = true;
  26.389 +        }
  26.390 +        appendStatement(returnNode);
  26.391 +        return returnNode;
  26.392 +    }
  26.393 +
  26.394 +    private void appendStatement(final Statement statement) {
  26.395 +        lc.appendStatement(statement);
  26.396 +    }
  26.397 +
  26.398 +    private boolean inSplitNode() {
  26.399 +        return getCurrentFunctionState().splitDepth > 0;
  26.400 +    }
  26.401 +
  26.402 +    private FunctionState getCurrentFunctionState() {
  26.403 +        return functionStates.peek();
  26.404 +    }
  26.405 +
  26.406 +    private SplitState getCurrentSplitState() {
  26.407 +        return splitStates.peek();
  26.408 +    }
  26.409 +
  26.410 +    private static class FunctionState {
  26.411 +        final FunctionNode fn;
  26.412 +        final List<Statement> varStatements = new ArrayList<>();
  26.413 +        int splitDepth;
  26.414 +
  26.415 +        FunctionState(final FunctionNode fn) {
  26.416 +            this.fn = fn;
  26.417 +        }
  26.418 +    }
  26.419 +
  26.420 +    private static class SplitState {
  26.421 +        final SplitNode splitNode;
  26.422 +        boolean hasReturn;
  26.423 +        boolean hasBreak;
  26.424 +
  26.425 +        final List<JumpStatement> jumpStatements = new ArrayList<>();
  26.426 +
  26.427 +        int getSplitStateIndex(final JumpStatement jump) {
  26.428 +            if (jump instanceof BreakNode && jump.getLabelName() == null) {
  26.429 +                // Unlabelled break is a special case
  26.430 +                hasBreak = true;
  26.431 +                return BREAK_STATE;
  26.432 +            }
  26.433 +
  26.434 +            int i = 0;
  26.435 +            for(final JumpStatement exJump: jumpStatements) {
  26.436 +                if (jump.getClass() == exJump.getClass() && Objects.equals(jump.getLabelName(), exJump.getLabelName())) {
  26.437 +                    return i + FIRST_JUMP_STATE;
  26.438 +                }
  26.439 +                ++i;
  26.440 +            }
  26.441 +            jumpStatements.add(jump);
  26.442 +            return i + FIRST_JUMP_STATE;
  26.443 +        }
  26.444 +
  26.445 +        SplitState(final SplitNode splitNode) {
  26.446 +            this.splitNode = splitNode;
  26.447 +        }
  26.448 +    }
  26.449 +}
    27.1 --- a/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java	Mon Oct 27 14:36:13 2014 -0700
    27.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.3 @@ -1,102 +0,0 @@
    27.4 -/*
    27.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    27.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    27.7 - *
    27.8 - * This code is free software; you can redistribute it and/or modify it
    27.9 - * under the terms of the GNU General Public License version 2 only, as
   27.10 - * published by the Free Software Foundation.  Oracle designates this
   27.11 - * particular file as subject to the "Classpath" exception as provided
   27.12 - * by Oracle in the LICENSE file that accompanied this code.
   27.13 - *
   27.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
   27.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   27.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   27.17 - * version 2 for more details (a copy is included in the LICENSE file that
   27.18 - * accompanied this code).
   27.19 - *
   27.20 - * You should have received a copy of the GNU General Public License version
   27.21 - * 2 along with this work; if not, write to the Free Software Foundation,
   27.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   27.23 - *
   27.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   27.25 - * or visit www.oracle.com if you need additional information or have any
   27.26 - * questions.
   27.27 - */
   27.28 -
   27.29 -package jdk.nashorn.internal.codegen;
   27.30 -
   27.31 -import java.util.ArrayList;
   27.32 -import java.util.List;
   27.33 -import jdk.internal.org.objectweb.asm.MethodVisitor;
   27.34 -import jdk.nashorn.internal.codegen.types.Type;
   27.35 -import jdk.nashorn.internal.ir.BreakableNode;
   27.36 -import jdk.nashorn.internal.ir.LexicalContext;
   27.37 -import jdk.nashorn.internal.ir.SplitNode;
   27.38 -
   27.39 -/**
   27.40 - * Emitter used for splitting methods. Needs to keep track of if there are jump targets
   27.41 - * outside the current split node. All external jump targets encountered at method
   27.42 - * emission are logged, and {@code CodeGenerator#leaveSplitNode(SplitNode)} creates
   27.43 - * an appropriate jump table when the SplitNode has been iterated through
   27.44 - */
   27.45 -public class SplitMethodEmitter extends MethodEmitter {
   27.46 -
   27.47 -    private final SplitNode splitNode;
   27.48 -
   27.49 -    private final List<Label> externalTargets = new ArrayList<>();
   27.50 -    /**
   27.51 -     * In addition to external target labels, we need to track the target breakables too as the code generator needs to
   27.52 -     * be able to correctly pop the scopes to the target, see {@link CodeGenerator#leaveSplitNode(SplitNode)}. Note that
   27.53 -     * this is only used within CodeGenerator, which doesn't mutate the AST, so keeping pointers to other nodes is not
   27.54 -     * incorrect.
   27.55 -     */
   27.56 -    private final List<BreakableNode> externalTargetNodes = new ArrayList<>();
   27.57 -
   27.58 -    SplitMethodEmitter(final ClassEmitter classEmitter, final MethodVisitor mv, final SplitNode splitNode) {
   27.59 -        super(classEmitter, mv);
   27.60 -        this.splitNode = splitNode;
   27.61 -    }
   27.62 -
   27.63 -    @Override
   27.64 -    void splitAwareGoto(final LexicalContext lc, final Label label, final BreakableNode targetNode) {
   27.65 -        assert splitNode != null;
   27.66 -        final int index = findExternalTarget(lc, label, targetNode);
   27.67 -        if (index >= 0) {
   27.68 -            setSplitState(index + 1); // 0 is ordinary return
   27.69 -            final Type retType = functionNode.getReturnType();
   27.70 -            loadUndefined(retType);
   27.71 -            _return(retType);
   27.72 -        } else {
   27.73 -            super.splitAwareGoto(lc, label, targetNode);
   27.74 -        }
   27.75 -    }
   27.76 -
   27.77 -    private int findExternalTarget(final LexicalContext lc, final Label label, final BreakableNode targetNode) {
   27.78 -        final int index = externalTargets.indexOf(label);
   27.79 -
   27.80 -        if (index >= 0) {
   27.81 -            return index;
   27.82 -        }
   27.83 -
   27.84 -        if (lc.isExternalTarget(splitNode, targetNode)) {
   27.85 -            externalTargets.add(label);
   27.86 -            externalTargetNodes.add(targetNode);
   27.87 -            return externalTargets.size() - 1;
   27.88 -        }
   27.89 -        return -1;
   27.90 -    }
   27.91 -
   27.92 -    @Override
   27.93 -    MethodEmitter registerReturn() {
   27.94 -        setHasReturn();
   27.95 -        return setSplitState(0);
   27.96 -    }
   27.97 -
   27.98 -    final List<Label> getExternalTargets() {
   27.99 -        return externalTargets;
  27.100 -    }
  27.101 -
  27.102 -    final List<BreakableNode> getExternalTargetNodes() {
  27.103 -        return externalTargetNodes;
  27.104 -    }
  27.105 -}
    28.1 --- a/src/jdk/nashorn/internal/codegen/TypeEvaluator.java	Mon Oct 27 14:36:13 2014 -0700
    28.2 +++ b/src/jdk/nashorn/internal/codegen/TypeEvaluator.java	Thu Nov 06 09:50:15 2014 -0800
    28.3 @@ -29,16 +29,22 @@
    28.4  import static jdk.nashorn.internal.runtime.Property.NOT_ENUMERABLE;
    28.5  import static jdk.nashorn.internal.runtime.Property.NOT_WRITABLE;
    28.6  
    28.7 +import java.lang.invoke.MethodType;
    28.8  import jdk.nashorn.internal.codegen.types.Type;
    28.9  import jdk.nashorn.internal.ir.AccessNode;
   28.10 +import jdk.nashorn.internal.ir.CallNode;
   28.11  import jdk.nashorn.internal.ir.Expression;
   28.12 +import jdk.nashorn.internal.ir.FunctionNode;
   28.13  import jdk.nashorn.internal.ir.IdentNode;
   28.14  import jdk.nashorn.internal.ir.IndexNode;
   28.15  import jdk.nashorn.internal.ir.Optimistic;
   28.16 +import jdk.nashorn.internal.objects.ArrayBufferView;
   28.17  import jdk.nashorn.internal.objects.NativeArray;
   28.18  import jdk.nashorn.internal.runtime.FindProperty;
   28.19  import jdk.nashorn.internal.runtime.JSType;
   28.20  import jdk.nashorn.internal.runtime.Property;
   28.21 +import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
   28.22 +import jdk.nashorn.internal.runtime.ScriptFunction;
   28.23  import jdk.nashorn.internal.runtime.ScriptObject;
   28.24  import jdk.nashorn.internal.runtime.ScriptRuntime;
   28.25  
   28.26 @@ -47,6 +53,13 @@
   28.27   * Used during recompilation.
   28.28   */
   28.29  final class TypeEvaluator {
   28.30 +    /**
   28.31 +     * Type signature for invocation of functions without parameters: we must pass (callee, this) of type
   28.32 +     * (ScriptFunction, Object) respectively. We also use Object as the return type (we must pass something,
   28.33 +     * but it'll be ignored; it can't be void, though).
   28.34 +     */
   28.35 +    private static final MethodType EMPTY_INVOCATION_TYPE = MethodType.methodType(Object.class, ScriptFunction.class, Object.class);
   28.36 +
   28.37      private final Compiler compiler;
   28.38      private final ScriptObject runtimeScope;
   28.39  
   28.40 @@ -104,7 +117,7 @@
   28.41          }
   28.42  
   28.43          final Property property      = find.getProperty();
   28.44 -        final Class<?> propertyClass = property.getCurrentType();
   28.45 +        final Class<?> propertyClass = property.getType();
   28.46          if (propertyClass == null) {
   28.47              // propertyClass == null means its value is Undefined. It is probably not initialized yet, so we won't make
   28.48              // a type assumption yet.
   28.49 @@ -190,30 +203,46 @@
   28.50                  return null;
   28.51              }
   28.52              return getPropertyType(runtimeScope, ((IdentNode)expr).getName());
   28.53 -        }
   28.54 -
   28.55 -        if (expr instanceof AccessNode) {
   28.56 +        } else if (expr instanceof AccessNode) {
   28.57              final AccessNode accessNode = (AccessNode)expr;
   28.58              final Object base = evaluateSafely(accessNode.getBase());
   28.59              if (!(base instanceof ScriptObject)) {
   28.60                  return null;
   28.61              }
   28.62              return getPropertyType((ScriptObject)base, accessNode.getProperty());
   28.63 -        }
   28.64 -
   28.65 -        if (expr instanceof IndexNode) {
   28.66 +        } else if (expr instanceof IndexNode) {
   28.67              final IndexNode indexNode = (IndexNode)expr;
   28.68              final Object    base = evaluateSafely(indexNode.getBase());
   28.69 -            if(!(base instanceof NativeArray)) {
   28.70 -                // We only know how to deal with NativeArray. TODO: maybe manage buffers too
   28.71 -                return null;
   28.72 +            if(base instanceof NativeArray || base instanceof ArrayBufferView) {
   28.73 +                // NOTE: optimistic array getters throw UnwarrantedOptimismException based on the type of their
   28.74 +                // underlying array storage, not based on values of individual elements. Thus, a LongArrayData will
   28.75 +                // throw UOE for every optimistic int linkage attempt, even if the long value being returned in the
   28.76 +                // first invocation would be representable as int. That way, we can presume that the array's optimistic
   28.77 +                // type is the most optimistic type for which an element getter has a chance of executing successfully.
   28.78 +                return ((ScriptObject)base).getArray().getOptimisticType();
   28.79              }
   28.80 -            // NOTE: optimistic array getters throw UnwarrantedOptimismException based on the type of their underlying
   28.81 -            // array storage, not based on values of individual elements. Thus, a LongArrayData will throw UOE for every
   28.82 -            // optimistic int linkage attempt, even if the long value being returned in the first invocation would be
   28.83 -            // representable as int. That way, we can presume that the array's optimistic type is the most optimistic
   28.84 -            // type for which an element getter has a chance of executing successfully.
   28.85 -            return ((NativeArray)base).getArray().getOptimisticType();
   28.86 +        } else if (expr instanceof CallNode) {
   28.87 +            // Currently, we'll only try to guess the return type of immediately invoked function expressions with no
   28.88 +            // parameters, that is (function() { ... })(). We could do better, but these are all heuristics and we can
   28.89 +            // gradually introduce them as needed. An easy one would be to do the same for .call(this) idiom.
   28.90 +            final CallNode callExpr = (CallNode)expr;
   28.91 +            final Expression fnExpr = callExpr.getFunction();
   28.92 +            if (fnExpr instanceof FunctionNode) {
   28.93 +                final FunctionNode fn = (FunctionNode)fnExpr;
   28.94 +                if (callExpr.getArgs().isEmpty()) {
   28.95 +                    final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(fn.getId());
   28.96 +                    if (data != null) {
   28.97 +                        final Type returnType = Type.typeFor(data.getReturnType(EMPTY_INVOCATION_TYPE, runtimeScope));
   28.98 +                        if (returnType == Type.BOOLEAN) {
   28.99 +                            // We don't have optimistic booleans. In fact, optimistic call sites getting back boolean
  28.100 +                            // currently deoptimize all the way to Object.
  28.101 +                            return Type.OBJECT;
  28.102 +                        }
  28.103 +                        assert returnType == Type.INT || returnType == Type.LONG || returnType == Type.NUMBER || returnType == Type.OBJECT;
  28.104 +                        return returnType;
  28.105 +                    }
  28.106 +                }
  28.107 +            }
  28.108          }
  28.109  
  28.110          return null;
    29.1 --- a/src/jdk/nashorn/internal/codegen/types/ArrayType.java	Mon Oct 27 14:36:13 2014 -0700
    29.2 +++ b/src/jdk/nashorn/internal/codegen/types/ArrayType.java	Thu Nov 06 09:50:15 2014 -0800
    29.3 @@ -37,6 +37,7 @@
    29.4   * This is an array type, i.e. OBJECT_ARRAY, NUMBER_ARRAY.
    29.5   */
    29.6  public class ArrayType extends ObjectType implements BytecodeArrayOps {
    29.7 +    private static final long serialVersionUID = 1L;
    29.8  
    29.9      /**
   29.10       * Constructor
    30.1 --- a/src/jdk/nashorn/internal/codegen/types/BitwiseType.java	Mon Oct 27 14:36:13 2014 -0700
    30.2 +++ b/src/jdk/nashorn/internal/codegen/types/BitwiseType.java	Thu Nov 06 09:50:15 2014 -0800
    30.3 @@ -29,6 +29,7 @@
    30.4   * This class represents a numeric type that can be used for bit operations.
    30.5   */
    30.6  public abstract class BitwiseType extends NumericType implements BytecodeBitwiseOps {
    30.7 +    private static final long serialVersionUID = 1L;
    30.8  
    30.9      /**
   30.10       * Constructor
    31.1 --- a/src/jdk/nashorn/internal/codegen/types/BooleanType.java	Mon Oct 27 14:36:13 2014 -0700
    31.2 +++ b/src/jdk/nashorn/internal/codegen/types/BooleanType.java	Thu Nov 06 09:50:15 2014 -0800
    31.3 @@ -69,6 +69,7 @@
    31.4   * The boolean type class
    31.5   */
    31.6  public final class BooleanType extends Type {
    31.7 +    private static final long serialVersionUID = 1L;
    31.8  
    31.9      private static final CompilerConstants.Call VALUE_OF = staticCallNoLookup(Boolean.class, "valueOf", Boolean.class, boolean.class);
   31.10      private static final CompilerConstants.Call TO_STRING = staticCallNoLookup(Boolean.class, "toString", String.class, boolean.class);
    32.1 --- a/src/jdk/nashorn/internal/codegen/types/IntType.java	Mon Oct 27 14:36:13 2014 -0700
    32.2 +++ b/src/jdk/nashorn/internal/codegen/types/IntType.java	Thu Nov 06 09:50:15 2014 -0800
    32.3 @@ -60,6 +60,7 @@
    32.4   * Type class: INT
    32.5   */
    32.6  class IntType extends BitwiseType {
    32.7 +    private static final long serialVersionUID = 1L;
    32.8  
    32.9      private static final CompilerConstants.Call TO_STRING = staticCallNoLookup(Integer.class, "toString", String.class, int.class);
   32.10      private static final CompilerConstants.Call VALUE_OF  = staticCallNoLookup(Integer.class, "valueOf", Integer.class, int.class);
    33.1 --- a/src/jdk/nashorn/internal/codegen/types/LongType.java	Mon Oct 27 14:36:13 2014 -0700
    33.2 +++ b/src/jdk/nashorn/internal/codegen/types/LongType.java	Thu Nov 06 09:50:15 2014 -0800
    33.3 @@ -54,6 +54,7 @@
    33.4   * Type class: LONG
    33.5   */
    33.6  class LongType extends BitwiseType {
    33.7 +    private static final long serialVersionUID = 1L;
    33.8  
    33.9      private static final CompilerConstants.Call VALUE_OF = staticCallNoLookup(Long.class, "valueOf", Long.class, long.class);
   33.10  
    34.1 --- a/src/jdk/nashorn/internal/codegen/types/NumberType.java	Mon Oct 27 14:36:13 2014 -0700
    34.2 +++ b/src/jdk/nashorn/internal/codegen/types/NumberType.java	Thu Nov 06 09:50:15 2014 -0800
    34.3 @@ -46,6 +46,7 @@
    34.4  import jdk.nashorn.internal.runtime.JSType;
    34.5  
    34.6  class NumberType extends NumericType {
    34.7 +    private static final long serialVersionUID = 1L;
    34.8  
    34.9      private static final CompilerConstants.Call VALUE_OF = staticCallNoLookup(Double.class, "valueOf", Double.class, double.class);
   34.10  
    35.1 --- a/src/jdk/nashorn/internal/codegen/types/NumericType.java	Mon Oct 27 14:36:13 2014 -0700
    35.2 +++ b/src/jdk/nashorn/internal/codegen/types/NumericType.java	Thu Nov 06 09:50:15 2014 -0800
    35.3 @@ -29,6 +29,8 @@
    35.4   * This is a numeric type, i.e. NUMBER, LONG, INT, INT32.
    35.5   */
    35.6  public abstract class NumericType extends Type implements BytecodeNumericOps {
    35.7 +    private static final long serialVersionUID = 1L;
    35.8 +
    35.9      /**
   35.10       * Constructor
   35.11       *
    36.1 --- a/src/jdk/nashorn/internal/codegen/types/ObjectType.java	Mon Oct 27 14:36:13 2014 -0700
    36.2 +++ b/src/jdk/nashorn/internal/codegen/types/ObjectType.java	Thu Nov 06 09:50:15 2014 -0800
    36.3 @@ -47,6 +47,7 @@
    36.4   * contain a class that is a more specialized object
    36.5   */
    36.6  class ObjectType extends Type {
    36.7 +    private static final long serialVersionUID = 1L;
    36.8  
    36.9      protected ObjectType() {
   36.10          this(Object.class);
    37.1 --- a/src/jdk/nashorn/internal/codegen/types/Type.java	Mon Oct 27 14:36:13 2014 -0700
    37.2 +++ b/src/jdk/nashorn/internal/codegen/types/Type.java	Thu Nov 06 09:50:15 2014 -0800
    37.3 @@ -47,9 +47,11 @@
    37.4  import static jdk.internal.org.objectweb.asm.Opcodes.T_INT;
    37.5  import static jdk.internal.org.objectweb.asm.Opcodes.T_LONG;
    37.6  import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
    37.7 +
    37.8  import java.io.DataInput;
    37.9  import java.io.DataOutput;
   37.10  import java.io.IOException;
   37.11 +import java.io.Serializable;
   37.12  import java.lang.invoke.CallSite;
   37.13  import java.lang.invoke.MethodHandle;
   37.14  import java.lang.invoke.MethodHandles;
   37.15 @@ -88,19 +90,20 @@
   37.16   * INTs rather than OBJECTs
   37.17   */
   37.18  
   37.19 -public abstract class Type implements Comparable<Type>, BytecodeOps {
   37.20 +public abstract class Type implements Comparable<Type>, BytecodeOps, Serializable {
   37.21 +    private static final long serialVersionUID = 1L;
   37.22  
   37.23      /** Human readable name for type */
   37.24 -    private final String name;
   37.25 +    private transient final String name;
   37.26  
   37.27      /** Descriptor for type */
   37.28 -    private final String descriptor;
   37.29 +    private transient final String descriptor;
   37.30  
   37.31      /** The "weight" of the type. Used for picking widest/least specific common type */
   37.32 -    private final int weight;
   37.33 +    private transient final int weight;
   37.34  
   37.35      /** How many bytecode slots does this type occupy */
   37.36 -    private final int slots;
   37.37 +    private transient final int slots;
   37.38  
   37.39      /** The class for this type */
   37.40      private final Class<?> clazz;
   37.41 @@ -113,7 +116,7 @@
   37.42              Collections.synchronizedMap(new WeakHashMap<Class<?>, jdk.internal.org.objectweb.asm.Type>());
   37.43  
   37.44      /** Internal ASM type for this Type - computed once at construction */
   37.45 -    private final jdk.internal.org.objectweb.asm.Type internalType;
   37.46 +    private transient final jdk.internal.org.objectweb.asm.Type internalType;
   37.47  
   37.48      /** Weights are used to decide which types are "wider" than other types */
   37.49      protected static final int MIN_WEIGHT = -1;
   37.50 @@ -583,6 +586,7 @@
   37.51      public int getSlots() {
   37.52          return slots;
   37.53      }
   37.54 +
   37.55      /**
   37.56       * Returns the widest or most common of two types
   37.57       *
   37.58 @@ -606,6 +610,18 @@
   37.59      }
   37.60  
   37.61      /**
   37.62 +     * Returns the widest or most common of two types, given as classes
   37.63 +     *
   37.64 +     * @param type0 type one
   37.65 +     * @param type1 type two
   37.66 +     *
   37.67 +     * @return the widest type
   37.68 +     */
   37.69 +    public static Class<?> widest(final Class<?> type0, final Class<?> type1) {
   37.70 +        return widest(Type.typeFor(type0), Type.typeFor(type1)).getTypeClass();
   37.71 +    }
   37.72 +
   37.73 +    /**
   37.74       * When doing widening for return types of a function or a ternary operator, it is not valid to widen a boolean to
   37.75       * anything other than object. Note that this wouldn't be necessary if {@code Type.widest} did not allow
   37.76       * boolean-to-number widening. Eventually, we should address it there, but it affects too many other parts of the
   37.77 @@ -934,6 +950,8 @@
   37.78       * This is the singleton for integer arrays
   37.79       */
   37.80      public static final ArrayType INT_ARRAY = new ArrayType(int[].class) {
   37.81 +        private static final long serialVersionUID = 1L;
   37.82 +
   37.83          @Override
   37.84          public void astore(final MethodVisitor method) {
   37.85              method.visitInsn(IASTORE);
   37.86 @@ -961,6 +979,8 @@
   37.87       * This is the singleton for long arrays
   37.88       */
   37.89      public static final ArrayType LONG_ARRAY = new ArrayType(long[].class) {
   37.90 +        private static final long serialVersionUID = 1L;
   37.91 +
   37.92          @Override
   37.93          public void astore(final MethodVisitor method) {
   37.94              method.visitInsn(LASTORE);
   37.95 @@ -988,6 +1008,8 @@
   37.96       * This is the singleton for numeric arrays
   37.97       */
   37.98      public static final ArrayType NUMBER_ARRAY = new ArrayType(double[].class) {
   37.99 +        private static final long serialVersionUID = 1L;
  37.100 +
  37.101          @Override
  37.102          public void astore(final MethodVisitor method) {
  37.103              method.visitInsn(DASTORE);
  37.104 @@ -1022,6 +1044,8 @@
  37.105  
  37.106      /** This type, always an object type, just a toString override */
  37.107      public static final Type THIS = new ObjectType() {
  37.108 +        private static final long serialVersionUID = 1L;
  37.109 +
  37.110          @Override
  37.111          public String toString() {
  37.112              return "this";
  37.113 @@ -1030,6 +1054,8 @@
  37.114  
  37.115      /** Scope type, always an object type, just a toString override */
  37.116      public static final Type SCOPE = new ObjectType() {
  37.117 +        private static final long serialVersionUID = 1L;
  37.118 +
  37.119          @Override
  37.120          public String toString() {
  37.121              return "scope";
  37.122 @@ -1041,6 +1067,7 @@
  37.123      }
  37.124  
  37.125      private abstract static class ValueLessType extends Type {
  37.126 +        private static final long serialVersionUID = 1L;
  37.127  
  37.128          ValueLessType(final String name) {
  37.129              super(name, Unknown.class, MIN_WEIGHT, 1);
  37.130 @@ -1092,6 +1119,8 @@
  37.131       * inference. It has the minimum type width
  37.132       */
  37.133      public static final Type UNKNOWN = new ValueLessType("<unknown>") {
  37.134 +        private static final long serialVersionUID = 1L;
  37.135 +
  37.136          @Override
  37.137          public String getDescriptor() {
  37.138              return "<unknown>";
  37.139 @@ -1108,6 +1137,7 @@
  37.140       * inference. It has the minimum type width
  37.141       */
  37.142      public static final Type SLOT_2 = new ValueLessType("<slot_2>") {
  37.143 +        private static final long serialVersionUID = 1L;
  37.144  
  37.145          @Override
  37.146          public String getDescriptor() {
  37.147 @@ -1124,4 +1154,8 @@
  37.148          cache.put(type.getTypeClass(), type);
  37.149          return type;
  37.150      }
  37.151 +
  37.152 +    protected final Object readResolve() {
  37.153 +        return Type.typeFor(clazz);
  37.154 +    }
  37.155  }
    38.1 --- a/src/jdk/nashorn/internal/ir/AccessNode.java	Mon Oct 27 14:36:13 2014 -0700
    38.2 +++ b/src/jdk/nashorn/internal/ir/AccessNode.java	Thu Nov 06 09:50:15 2014 -0800
    38.3 @@ -34,6 +34,8 @@
    38.4   */
    38.5  @Immutable
    38.6  public final class AccessNode extends BaseNode {
    38.7 +    private static final long serialVersionUID = 1L;
    38.8 +
    38.9      /** Property name. */
   38.10      private final String property;
   38.11  
    39.1 --- a/src/jdk/nashorn/internal/ir/BaseNode.java	Mon Oct 27 14:36:13 2014 -0700
    39.2 +++ b/src/jdk/nashorn/internal/ir/BaseNode.java	Thu Nov 06 09:50:15 2014 -0800
    39.3 @@ -39,6 +39,7 @@
    39.4   */
    39.5  @Immutable
    39.6  public abstract class BaseNode extends Expression implements FunctionCall, Optimistic {
    39.7 +    private static final long serialVersionUID = 1L;
    39.8  
    39.9      /** Base Node. */
   39.10      protected final Expression base;
    40.1 --- a/src/jdk/nashorn/internal/ir/BinaryNode.java	Mon Oct 27 14:36:13 2014 -0700
    40.2 +++ b/src/jdk/nashorn/internal/ir/BinaryNode.java	Thu Nov 06 09:50:15 2014 -0800
    40.3 @@ -43,6 +43,8 @@
    40.4   */
    40.5  @Immutable
    40.6  public final class BinaryNode extends Expression implements Assignment<Expression>, Optimistic {
    40.7 +    private static final long serialVersionUID = 1L;
    40.8 +
    40.9      // Placeholder for "undecided optimistic ADD type". Unfortunately, we can't decide the type of ADD during optimistic
   40.10      // type calculation as it can have local variables as its operands that will decide its ultimate type.
   40.11      private static final Type OPTIMISTIC_UNDECIDED_TYPE = Type.typeFor(new Object(){/*empty*/}.getClass());
   40.12 @@ -56,8 +58,8 @@
   40.13  
   40.14      private final Type type;
   40.15  
   40.16 -    private Type cachedType;
   40.17 -    private Object cachedTypeFunction;
   40.18 +    private transient Type cachedType;
   40.19 +    private transient Object cachedTypeFunction;
   40.20  
   40.21      @Ignore
   40.22      private static final Set<TokenType> CAN_OVERFLOW =
    41.1 --- a/src/jdk/nashorn/internal/ir/Block.java	Mon Oct 27 14:36:13 2014 -0700
    41.2 +++ b/src/jdk/nashorn/internal/ir/Block.java	Thu Nov 06 09:50:15 2014 -0800
    41.3 @@ -42,6 +42,8 @@
    41.4   */
    41.5  @Immutable
    41.6  public class Block extends Node implements BreakableNode, Terminal, Flags<Block> {
    41.7 +    private static final long serialVersionUID = 1L;
    41.8 +
    41.9      /** List of statements */
   41.10      protected final List<Statement> statements;
   41.11  
    42.1 --- a/src/jdk/nashorn/internal/ir/BlockLexicalContext.java	Mon Oct 27 14:36:13 2014 -0700
    42.2 +++ b/src/jdk/nashorn/internal/ir/BlockLexicalContext.java	Thu Nov 06 09:50:15 2014 -0800
    42.3 @@ -109,6 +109,16 @@
    42.4      }
    42.5  
    42.6      /**
    42.7 +     * Prepend a list of statement to the block being generated
    42.8 +     * @param statements a list of statements to prepend
    42.9 +     */
   42.10 +    public void prependStatements(final List<Statement> statements) {
   42.11 +        assert statements != null;
   42.12 +        sstack.peek().addAll(0, statements);
   42.13 +    }
   42.14 +
   42.15 +
   42.16 +    /**
   42.17       * Get the last statement that was emitted into a block
   42.18       * @return the last statement emitted
   42.19       */
    43.1 --- a/src/jdk/nashorn/internal/ir/BlockStatement.java	Mon Oct 27 14:36:13 2014 -0700
    43.2 +++ b/src/jdk/nashorn/internal/ir/BlockStatement.java	Thu Nov 06 09:50:15 2014 -0800
    43.3 @@ -32,6 +32,8 @@
    43.4   * Represents a block used as a statement.
    43.5   */
    43.6  public class BlockStatement extends Statement {
    43.7 +    private static final long serialVersionUID = 1L;
    43.8 +
    43.9      /** Block to execute. */
   43.10      private final Block block;
   43.11  
    44.1 --- a/src/jdk/nashorn/internal/ir/BreakNode.java	Mon Oct 27 14:36:13 2014 -0700
    44.2 +++ b/src/jdk/nashorn/internal/ir/BreakNode.java	Thu Nov 06 09:50:15 2014 -0800
    44.3 @@ -34,6 +34,7 @@
    44.4   */
    44.5  @Immutable
    44.6  public final class BreakNode extends JumpStatement {
    44.7 +    private static final long serialVersionUID = 1L;
    44.8  
    44.9      /**
   44.10       * Constructor
    45.1 --- a/src/jdk/nashorn/internal/ir/BreakableStatement.java	Mon Oct 27 14:36:13 2014 -0700
    45.2 +++ b/src/jdk/nashorn/internal/ir/BreakableStatement.java	Thu Nov 06 09:50:15 2014 -0800
    45.3 @@ -32,6 +32,7 @@
    45.4  
    45.5  @Immutable
    45.6  abstract class BreakableStatement extends LexicalContextStatement implements BreakableNode {
    45.7 +    private static final long serialVersionUID = 1L;
    45.8  
    45.9      /** break label. */
   45.10      protected final Label breakLabel;
    46.1 --- a/src/jdk/nashorn/internal/ir/CallNode.java	Mon Oct 27 14:36:13 2014 -0700
    46.2 +++ b/src/jdk/nashorn/internal/ir/CallNode.java	Thu Nov 06 09:50:15 2014 -0800
    46.3 @@ -27,6 +27,7 @@
    46.4  
    46.5  import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
    46.6  
    46.7 +import java.io.Serializable;
    46.8  import java.util.Collections;
    46.9  import java.util.List;
   46.10  import java.util.function.Function;
   46.11 @@ -40,6 +41,7 @@
   46.12   */
   46.13  @Immutable
   46.14  public final class CallNode extends LexicalContextExpression implements Optimistic {
   46.15 +    private static final long serialVersionUID = 1L;
   46.16  
   46.17      /** Function identifier or function body. */
   46.18      private final Expression function;
   46.19 @@ -64,7 +66,8 @@
   46.20      /**
   46.21       * Arguments to be passed to builtin {@code eval} function
   46.22       */
   46.23 -    public static class EvalArgs {
   46.24 +    public static class EvalArgs implements Serializable {
   46.25 +        private static final long serialVersionUID = 1L;
   46.26          private final List<Expression> args;
   46.27  
   46.28          /** location string for the eval call */
    47.1 --- a/src/jdk/nashorn/internal/ir/CaseNode.java	Mon Oct 27 14:36:13 2014 -0700
    47.2 +++ b/src/jdk/nashorn/internal/ir/CaseNode.java	Thu Nov 06 09:50:15 2014 -0800
    47.3 @@ -37,6 +37,8 @@
    47.4   */
    47.5  @Immutable
    47.6  public final class CaseNode extends Node implements JoinPredecessor, Labels, Terminal {
    47.7 +    private static final long serialVersionUID = 1L;
    47.8 +
    47.9      /** Test expression. */
   47.10      private final Expression test;
   47.11  
    48.1 --- a/src/jdk/nashorn/internal/ir/CatchNode.java	Mon Oct 27 14:36:13 2014 -0700
    48.2 +++ b/src/jdk/nashorn/internal/ir/CatchNode.java	Thu Nov 06 09:50:15 2014 -0800
    48.3 @@ -33,6 +33,8 @@
    48.4   */
    48.5  @Immutable
    48.6  public final class CatchNode extends Statement {
    48.7 +    private static final long serialVersionUID = 1L;
    48.8 +
    48.9      /** Exception identifier. */
   48.10      private final IdentNode exception;
   48.11  
    49.1 --- a/src/jdk/nashorn/internal/ir/ContinueNode.java	Mon Oct 27 14:36:13 2014 -0700
    49.2 +++ b/src/jdk/nashorn/internal/ir/ContinueNode.java	Thu Nov 06 09:50:15 2014 -0800
    49.3 @@ -34,6 +34,8 @@
    49.4   */
    49.5  @Immutable
    49.6  public class ContinueNode extends JumpStatement {
    49.7 +    private static final long serialVersionUID = 1L;
    49.8 +
    49.9      /**
   49.10       * Constructor
   49.11       *
   49.12 @@ -80,4 +82,3 @@
   49.13          return ((LoopNode)target).getContinueLabel();
   49.14      }
   49.15  }
   49.16 -
    50.1 --- a/src/jdk/nashorn/internal/ir/EmptyNode.java	Mon Oct 27 14:36:13 2014 -0700
    50.2 +++ b/src/jdk/nashorn/internal/ir/EmptyNode.java	Thu Nov 06 09:50:15 2014 -0800
    50.3 @@ -33,6 +33,7 @@
    50.4   */
    50.5  @Immutable
    50.6  public final class EmptyNode extends Statement {
    50.7 +    private static final long serialVersionUID = 1L;
    50.8  
    50.9      /**
   50.10       * Constructor
    51.1 --- a/src/jdk/nashorn/internal/ir/Expression.java	Mon Oct 27 14:36:13 2014 -0700
    51.2 +++ b/src/jdk/nashorn/internal/ir/Expression.java	Thu Nov 06 09:50:15 2014 -0800
    51.3 @@ -35,6 +35,8 @@
    51.4   *
    51.5   */
    51.6  public abstract class Expression extends Node {
    51.7 +    private static final long serialVersionUID = 1L;
    51.8 +
    51.9      static final String OPT_IDENTIFIER = "%";
   51.10  
   51.11      private static final Function<Symbol, Type> UNKNOWN_LOCALS = new Function<Symbol, Type>() {
    52.1 --- a/src/jdk/nashorn/internal/ir/ExpressionStatement.java	Mon Oct 27 14:36:13 2014 -0700
    52.2 +++ b/src/jdk/nashorn/internal/ir/ExpressionStatement.java	Thu Nov 06 09:50:15 2014 -0800
    52.3 @@ -35,6 +35,8 @@
    52.4   */
    52.5  @Immutable
    52.6  public final class ExpressionStatement extends Statement {
    52.7 +    private static final long serialVersionUID = 1L;
    52.8 +
    52.9      /** Expression to execute. */
   52.10      private final Expression expression;
   52.11  
    53.1 --- a/src/jdk/nashorn/internal/ir/ForNode.java	Mon Oct 27 14:36:13 2014 -0700
    53.2 +++ b/src/jdk/nashorn/internal/ir/ForNode.java	Thu Nov 06 09:50:15 2014 -0800
    53.3 @@ -33,6 +33,8 @@
    53.4   */
    53.5  @Immutable
    53.6  public final class ForNode extends LoopNode {
    53.7 +    private static final long serialVersionUID = 1L;
    53.8 +
    53.9      /** Initialize expression for an ordinary for statement, or the LHS expression receiving iterated-over values in a
   53.10       * for-in statement. */
   53.11      private final Expression init;
    54.1 --- a/src/jdk/nashorn/internal/ir/FunctionNode.java	Mon Oct 27 14:36:13 2014 -0700
    54.2 +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java	Thu Nov 06 09:50:15 2014 -0800
    54.3 @@ -57,6 +57,8 @@
    54.4   */
    54.5  @Immutable
    54.6  public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder {
    54.7 +    private static final long serialVersionUID = 1L;
    54.8 +
    54.9      /** Type used for all FunctionNodes */
   54.10      public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
   54.11  
   54.12 @@ -107,7 +109,7 @@
   54.13      }
   54.14  
   54.15      /** Source of entity. */
   54.16 -    private final Source source;
   54.17 +    private transient final Source source;
   54.18  
   54.19      /**
   54.20       * Opaque object representing parser state at the end of the function. Used when reparsing outer functions
   54.21 @@ -141,7 +143,7 @@
   54.22      private final long lastToken;
   54.23  
   54.24      /** Method's namespace. */
   54.25 -    private final Namespace namespace;
   54.26 +    private transient final Namespace namespace;
   54.27  
   54.28      /** Current compilation state */
   54.29      @Ignore
   54.30 @@ -207,31 +209,23 @@
   54.31      /** Are we vararg, but do we just pass the arguments along to apply or call */
   54.32      public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12;
   54.33  
   54.34 -    /** Does this function explicitly use the {@link CompilerConstants#RETURN} symbol? Some functions are known to
   54.35 -     * always use the return symbol, namely a function that is a program (as it must track its last executed expression
   54.36 -     * statement's value) as well as functions that are split (to communicate return values from inner to outer
   54.37 -     * partitions). Other functions normally don't use the return symbol (so we optimize away its slot), except in some
   54.38 -     * very special cases, e.g. when containing a return statement in a finally block. These special cases set this
   54.39 -     * flag. */
   54.40 -    public static final int USES_RETURN_SYMBOL = 1 << 13;
   54.41 -
   54.42      /**
   54.43       * Is this function the top-level program?
   54.44       */
   54.45 -    public static final int IS_PROGRAM = 1 << 14;
   54.46 +    public static final int IS_PROGRAM = 1 << 13;
   54.47  
   54.48      /**
   54.49       * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
   54.50       * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
   54.51       * use the symbol in their parent scope instead when they reference themselves by name.
   54.52       */
   54.53 -    public static final int USES_SELF_SYMBOL = 1 << 15;
   54.54 +    public static final int USES_SELF_SYMBOL = 1 << 14;
   54.55  
   54.56      /** Does this function use the "this" keyword? */
   54.57 -    public static final int USES_THIS = 1 << 16;
   54.58 +    public static final int USES_THIS = 1 << 15;
   54.59  
   54.60      /** Is this declared in a dynamic context */
   54.61 -    public static final int IN_DYNAMIC_CONTEXT = 1 << 17;
   54.62 +    public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
   54.63  
   54.64      /**
   54.65       * The following flags are derived from directive comments within this function.
   54.66 @@ -239,28 +233,28 @@
   54.67       */
   54.68  
   54.69      /** parser, print parse tree */
   54.70 -    public static final int IS_PRINT_PARSE       = 1 << 18;
   54.71 +    public static final int IS_PRINT_PARSE       = 1 << 17;
   54.72      /** parser, print lower parse tree */
   54.73 -    public static final int IS_PRINT_LOWER_PARSE = 1 << 19;
   54.74 +    public static final int IS_PRINT_LOWER_PARSE = 1 << 18;
   54.75      /** parser, print AST */
   54.76 -    public static final int IS_PRINT_AST         = 1 << 20;
   54.77 +    public static final int IS_PRINT_AST         = 1 << 19;
   54.78      /** parser, print lower AST */
   54.79 -    public static final int IS_PRINT_LOWER_AST   = 1 << 21;
   54.80 +    public static final int IS_PRINT_LOWER_AST   = 1 << 20;
   54.81      /** parser, print symbols */
   54.82 -    public static final int IS_PRINT_SYMBOLS     = 1 << 22;
   54.83 +    public static final int IS_PRINT_SYMBOLS     = 1 << 21;
   54.84  
   54.85      // callsite tracing, profiling within this function
   54.86      /** profile callsites in this function? */
   54.87 -    public static final int IS_PROFILE         = 1 << 23;
   54.88 +    public static final int IS_PROFILE         = 1 << 22;
   54.89  
   54.90      /** trace callsite enterexit in this function? */
   54.91 -    public static final int IS_TRACE_ENTEREXIT = 1 << 24;
   54.92 +    public static final int IS_TRACE_ENTEREXIT = 1 << 23;
   54.93  
   54.94      /** trace callsite misses in this function? */
   54.95 -    public static final int IS_TRACE_MISSES    = 1 << 25;
   54.96 +    public static final int IS_TRACE_MISSES    = 1 << 24;
   54.97  
   54.98      /** trace callsite values in this function? */
   54.99 -    public static final int IS_TRACE_VALUES    = 1 << 26;
  54.100 +    public static final int IS_TRACE_VALUES    = 1 << 25;
  54.101  
  54.102      /**
  54.103       * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
  54.104 @@ -268,7 +262,7 @@
  54.105       * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
  54.106       * will, however, cache the value of this flag.
  54.107       */
  54.108 -    public static final int NEEDS_CALLEE       = 1 << 27;
  54.109 +    public static final int NEEDS_CALLEE       = 1 << 26;
  54.110  
  54.111      /** extension callsite flags mask */
  54.112      public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
  54.113 @@ -285,8 +279,8 @@
  54.114      /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
  54.115      private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
  54.116  
  54.117 -    /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval. */
  54.118 -    private static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL;
  54.119 +    /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval, or it's the program. */
  54.120 +    public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM;
  54.121  
  54.122      /** What is the return type of this function? */
  54.123      private Type returnType = Type.UNKNOWN;
  54.124 @@ -350,7 +344,8 @@
  54.125          final Block body,
  54.126          final List<IdentNode> parameters,
  54.127          final int thisProperties,
  54.128 -        final Class<?> rootClass) {
  54.129 +        final Class<?> rootClass,
  54.130 +        final Source source, Namespace namespace) {
  54.131          super(functionNode);
  54.132  
  54.133          this.endParserState    = endParserState;
  54.134 @@ -365,11 +360,11 @@
  54.135          this.parameters       = parameters;
  54.136          this.thisProperties   = thisProperties;
  54.137          this.rootClass        = rootClass;
  54.138 +        this.source           = source;
  54.139 +        this.namespace        = namespace;
  54.140  
  54.141          // the fields below never change - they are final and assigned in constructor
  54.142 -        this.source          = functionNode.source;
  54.143          this.ident           = functionNode.ident;
  54.144 -        this.namespace       = functionNode.namespace;
  54.145          this.kind            = functionNode.kind;
  54.146          this.firstToken      = functionNode.firstToken;
  54.147      }
  54.148 @@ -435,6 +430,39 @@
  54.149      }
  54.150  
  54.151      /**
  54.152 +     * Sets the source and namespace for this function. It can only set a non-null source and namespace for a function
  54.153 +     * that currently has both a null source and a null namespace. This is used to re-set the source and namespace for
  54.154 +     * a deserialized function node.
  54.155 +     * @param source the source for the function.
  54.156 +     * @param namespace the namespace for the function
  54.157 +     * @return a new function node with the set source and namespace
  54.158 +     * @throws IllegalArgumentException if the specified source or namespace is null
  54.159 +     * @throws IllegalStateException if the function already has either a source or namespace set.
  54.160 +     */
  54.161 +    public FunctionNode initializeDeserialized(final Source source, final Namespace namespace) {
  54.162 +        if (source == null || namespace == null) {
  54.163 +            throw new IllegalArgumentException();
  54.164 +        } else if (this.source == source && this.namespace == namespace) {
  54.165 +            return this;
  54.166 +        } else if (this.source != null || this.namespace != null) {
  54.167 +            throw new IllegalStateException();
  54.168 +        }
  54.169 +        return new FunctionNode(
  54.170 +            this,
  54.171 +            lastToken,
  54.172 +            endParserState,
  54.173 +            flags,
  54.174 +            name,
  54.175 +            returnType,
  54.176 +            compileUnit,
  54.177 +            compilationState,
  54.178 +            body,
  54.179 +            parameters,
  54.180 +            thisProperties,
  54.181 +            rootClass, source, namespace);
  54.182 +    }
  54.183 +
  54.184 +    /**
  54.185       * Get the unique ID for this function within the script file.
  54.186       * @return the id
  54.187       */
  54.188 @@ -535,6 +563,28 @@
  54.189          }
  54.190          final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
  54.191          newState.add(state);
  54.192 +        return setCompilationState(lc, newState);
  54.193 +    }
  54.194 +
  54.195 +    /**
  54.196 +     * Copy a compilation state from an original function to this function. Used when creating synthetic
  54.197 +     * function nodes by the splitter.
  54.198 +     *
  54.199 +     * @param lc lexical context
  54.200 +     * @param original the original function node to copy compilation state from
  54.201 +     * @return function node or a new one if state was changed
  54.202 +     */
  54.203 +    public FunctionNode copyCompilationState(final LexicalContext lc, final FunctionNode original) {
  54.204 +        final EnumSet<CompilationState> origState = original.compilationState;
  54.205 +        if (!AssertsEnabled.assertsEnabled() || this.compilationState.containsAll(origState)) {
  54.206 +            return this;
  54.207 +        }
  54.208 +        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
  54.209 +        newState.addAll(origState);
  54.210 +        return setCompilationState(lc, newState);
  54.211 +    }
  54.212 +
  54.213 +    private FunctionNode setCompilationState(final LexicalContext lc, final EnumSet<CompilationState> compilationState) {
  54.214          return Node.replaceInLexicalContext(
  54.215                  lc,
  54.216                  this,
  54.217 @@ -546,13 +596,14 @@
  54.218                          name,
  54.219                          returnType,
  54.220                          compileUnit,
  54.221 -                        newState,
  54.222 +                        compilationState,
  54.223                          body,
  54.224                          parameters,
  54.225                          thisProperties,
  54.226 -                        rootClass));
  54.227 +                        rootClass, source, namespace));
  54.228      }
  54.229  
  54.230 +
  54.231      /**
  54.232       * Create a unique name in the namespace of this FunctionNode
  54.233       * @param base prefix for name
  54.234 @@ -622,7 +673,7 @@
  54.235                          body,
  54.236                          parameters,
  54.237                          thisProperties,
  54.238 -                        rootClass));
  54.239 +                        rootClass, source, namespace));
  54.240      }
  54.241  
  54.242      @Override
  54.243 @@ -697,18 +748,11 @@
  54.244       * @return true if the function's generated Java method needs a {@code callee} parameter.
  54.245       */
  54.246      public boolean needsCallee() {
  54.247 +        // NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units.
  54.248          return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasOptimisticApplyToCall();
  54.249      }
  54.250  
  54.251      /**
  54.252 -     * Check if this function uses the return symbol
  54.253 -     * @return true if uses the return symbol
  54.254 -     */
  54.255 -    public boolean usesReturnSymbol() {
  54.256 -        return isProgram() || isSplit() || getFlag(USES_RETURN_SYMBOL);
  54.257 -    }
  54.258 -
  54.259 -    /**
  54.260       * Return {@code true} if this function makes use of the {@code this} object.
  54.261       *
  54.262       * @return true if function uses {@code this} object
  54.263 @@ -770,7 +814,7 @@
  54.264                          body,
  54.265                          parameters,
  54.266                          thisProperties,
  54.267 -                        rootClass));
  54.268 +                        rootClass, source, namespace));
  54.269      }
  54.270  
  54.271      /**
  54.272 @@ -838,7 +882,7 @@
  54.273       * @return true if the function needs parent scope.
  54.274       */
  54.275      public boolean needsParentScope() {
  54.276 -        return getFlag(NEEDS_PARENT_SCOPE) || isProgram();
  54.277 +        return getFlag(NEEDS_PARENT_SCOPE);
  54.278      }
  54.279  
  54.280      /**
  54.281 @@ -866,7 +910,7 @@
  54.282                          body,
  54.283                          parameters,
  54.284                          thisProperties,
  54.285 -                        rootClass));
  54.286 +                        rootClass, source, namespace));
  54.287      }
  54.288  
  54.289      /**
  54.290 @@ -927,7 +971,7 @@
  54.291                          body,
  54.292                          parameters,
  54.293                          thisProperties,
  54.294 -                        rootClass));
  54.295 +                        rootClass, source, namespace));
  54.296      }
  54.297  
  54.298      /**
  54.299 @@ -962,7 +1006,10 @@
  54.300                          compilationState,
  54.301                          body,
  54.302                          parameters,
  54.303 -                        thisProperties, rootClass));
  54.304 +                        thisProperties,
  54.305 +                        rootClass,
  54.306 +                        source,
  54.307 +                        namespace));
  54.308      }
  54.309  
  54.310      /**
  54.311 @@ -998,7 +1045,9 @@
  54.312                          body,
  54.313                          parameters,
  54.314                          thisProperties,
  54.315 -                        rootClass));
  54.316 +                        rootClass,
  54.317 +                        source,
  54.318 +                        namespace));
  54.319      }
  54.320  
  54.321      /**
  54.322 @@ -1012,9 +1061,9 @@
  54.323      }
  54.324  
  54.325      /**
  54.326 -     * Checks if this function is a sub-function generated by splitting a larger one
  54.327 +     * Checks if this function is split into several smaller fragments.
  54.328       *
  54.329 -     * @return true if this function is split from a larger one
  54.330 +     * @return true if this function is split into several smaller fragments.
  54.331       */
  54.332      public boolean isSplit() {
  54.333          return getFlag(IS_SPLIT);
  54.334 @@ -1064,7 +1113,7 @@
  54.335                          body,
  54.336                          parameters,
  54.337                          thisProperties,
  54.338 -                        rootClass));
  54.339 +                        rootClass, source, namespace));
  54.340      }
  54.341  
  54.342      /**
  54.343 @@ -1143,7 +1192,7 @@
  54.344                  body,
  54.345                  parameters,
  54.346                  thisProperties,
  54.347 -                rootClass
  54.348 +                rootClass, source, namespace
  54.349                  ));
  54.350     }
  54.351  
  54.352 @@ -1191,7 +1240,7 @@
  54.353                          body,
  54.354                          parameters,
  54.355                          thisProperties,
  54.356 -                        rootClass));
  54.357 +                        rootClass, source, namespace));
  54.358      }
  54.359  
  54.360      /**
  54.361 @@ -1247,6 +1296,6 @@
  54.362                          body,
  54.363                          parameters,
  54.364                          thisProperties,
  54.365 -                        rootClass));
  54.366 +                        rootClass, source, namespace));
  54.367      }
  54.368  }
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/src/jdk/nashorn/internal/ir/GetSplitState.java	Thu Nov 06 09:50:15 2014 -0800
    55.3 @@ -0,0 +1,70 @@
    55.4 +/*
    55.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    55.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    55.7 + *
    55.8 + * This code is free software; you can redistribute it and/or modify it
    55.9 + * under the terms of the GNU General Public License version 2 only, as
   55.10 + * published by the Free Software Foundation.  Oracle designates this
   55.11 + * particular file as subject to the "Classpath" exception as provided
   55.12 + * by Oracle in the LICENSE file that accompanied this code.
   55.13 + *
   55.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   55.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   55.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   55.17 + * version 2 for more details (a copy is included in the LICENSE file that
   55.18 + * accompanied this code).
   55.19 + *
   55.20 + * You should have received a copy of the GNU General Public License version
   55.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   55.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   55.23 + *
   55.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   55.25 + * or visit www.oracle.com if you need additional information or have any
   55.26 + * questions.
   55.27 + */
   55.28 +
   55.29 +package jdk.nashorn.internal.ir;
   55.30 +
   55.31 +import java.util.function.Function;
   55.32 +import jdk.nashorn.internal.codegen.CompilerConstants;
   55.33 +import jdk.nashorn.internal.codegen.types.Type;
   55.34 +import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   55.35 +import jdk.nashorn.internal.runtime.Scope;
   55.36 +
   55.37 +/**
   55.38 + * Synthetic AST node that represents loading of the scope object and invocation of the {@link Scope#getSplitState()}
   55.39 + * method on it. It has no JavaScript source representation and only occurs in synthetic functions created by
   55.40 + * the split-into-functions transformation.
   55.41 + */
   55.42 +public final class GetSplitState extends Expression {
   55.43 +    private static final long serialVersionUID = 1L;
   55.44 +
   55.45 +    /** The sole instance of this AST node. */
   55.46 +    public final static GetSplitState INSTANCE = new GetSplitState();
   55.47 +
   55.48 +    private GetSplitState() {
   55.49 +        super(NO_TOKEN, NO_FINISH);
   55.50 +    }
   55.51 +
   55.52 +    @Override
   55.53 +    public Type getType(final Function<Symbol, Type> localVariableTypes) {
   55.54 +        return Type.INT;
   55.55 +    }
   55.56 +
   55.57 +    @Override
   55.58 +    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
   55.59 +        return visitor.enterGetSplitState(this) ? visitor.leaveGetSplitState(this) : this;
   55.60 +    }
   55.61 +
   55.62 +    @Override
   55.63 +    public void toString(final StringBuilder sb, final boolean printType) {
   55.64 +        if (printType) {
   55.65 +            sb.append("{I}");
   55.66 +        }
   55.67 +        sb.append(CompilerConstants.SCOPE.symbolName()).append('.').append(Scope.GET_SPLIT_STATE.name()).append("()");
   55.68 +    }
   55.69 +
   55.70 +    private Object readResolve() {
   55.71 +        return INSTANCE;
   55.72 +    }
   55.73 +}
    56.1 --- a/src/jdk/nashorn/internal/ir/IdentNode.java	Mon Oct 27 14:36:13 2014 -0700
    56.2 +++ b/src/jdk/nashorn/internal/ir/IdentNode.java	Thu Nov 06 09:50:15 2014 -0800
    56.3 @@ -42,6 +42,8 @@
    56.4   */
    56.5  @Immutable
    56.6  public final class IdentNode extends Expression implements PropertyKey, FunctionCall, Optimistic, JoinPredecessor {
    56.7 +    private static final long serialVersionUID = 1L;
    56.8 +
    56.9      private static final int PROPERTY_NAME     = 1 << 0;
   56.10      private static final int INITIALIZED_HERE  = 1 << 1;
   56.11      private static final int FUNCTION          = 1 << 2;
    57.1 --- a/src/jdk/nashorn/internal/ir/IfNode.java	Mon Oct 27 14:36:13 2014 -0700
    57.2 +++ b/src/jdk/nashorn/internal/ir/IfNode.java	Thu Nov 06 09:50:15 2014 -0800
    57.3 @@ -33,6 +33,8 @@
    57.4   */
    57.5  @Immutable
    57.6  public final class IfNode extends Statement implements JoinPredecessor {
    57.7 +    private static final long serialVersionUID = 1L;
    57.8 +
    57.9      /** Test expression. */
   57.10      private final Expression test;
   57.11  
    58.1 --- a/src/jdk/nashorn/internal/ir/IndexNode.java	Mon Oct 27 14:36:13 2014 -0700
    58.2 +++ b/src/jdk/nashorn/internal/ir/IndexNode.java	Thu Nov 06 09:50:15 2014 -0800
    58.3 @@ -33,6 +33,8 @@
    58.4   */
    58.5  @Immutable
    58.6  public final class IndexNode extends BaseNode {
    58.7 +    private static final long serialVersionUID = 1L;
    58.8 +
    58.9      /** Property index. */
   58.10      private final Expression index;
   58.11  
    59.1 --- a/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java	Mon Oct 27 14:36:13 2014 -0700
    59.2 +++ b/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java	Thu Nov 06 09:50:15 2014 -0800
    59.3 @@ -33,6 +33,7 @@
    59.4   * A wrapper for an expression that is in a position to be a join predecessor.
    59.5   */
    59.6  public class JoinPredecessorExpression extends Expression implements JoinPredecessor {
    59.7 +    private static final long serialVersionUID = 1L;
    59.8  
    59.9      private final Expression expression;
   59.10      private final LocalVariableConversion conversion;
    60.1 --- a/src/jdk/nashorn/internal/ir/JumpStatement.java	Mon Oct 27 14:36:13 2014 -0700
    60.2 +++ b/src/jdk/nashorn/internal/ir/JumpStatement.java	Thu Nov 06 09:50:15 2014 -0800
    60.3 @@ -31,6 +31,7 @@
    60.4   * Common base class for jump statements (e.g. {@code break} and {@code continue}).
    60.5   */
    60.6  public abstract class JumpStatement extends Statement implements JoinPredecessor {
    60.7 +    private static final long serialVersionUID = 1L;
    60.8  
    60.9      private final String labelName;
   60.10      private final LocalVariableConversion conversion;
    61.1 --- a/src/jdk/nashorn/internal/ir/LabelNode.java	Mon Oct 27 14:36:13 2014 -0700
    61.2 +++ b/src/jdk/nashorn/internal/ir/LabelNode.java	Thu Nov 06 09:50:15 2014 -0800
    61.3 @@ -35,6 +35,8 @@
    61.4   */
    61.5  @Immutable
    61.6  public final class LabelNode extends LexicalContextStatement implements JoinPredecessor {
    61.7 +    private static final long serialVersionUID = 1L;
    61.8 +
    61.9      /** Label ident. */
   61.10      private final String labelName;
   61.11  
    62.1 --- a/src/jdk/nashorn/internal/ir/LexicalContext.java	Mon Oct 27 14:36:13 2014 -0700
    62.2 +++ b/src/jdk/nashorn/internal/ir/LexicalContext.java	Thu Nov 06 09:50:15 2014 -0800
    62.3 @@ -440,6 +440,14 @@
    62.4      }
    62.5  
    62.6      /**
    62.7 +     * Is the topmost lexical context element body of a SplitNode?
    62.8 +     * @return true if it's the body of a split node.
    62.9 +     */
   62.10 +    public boolean isSplitBody() {
   62.11 +        return sp >= 2 && stack[sp - 1] instanceof Block && stack[sp - 2] instanceof SplitNode;
   62.12 +    }
   62.13 +
   62.14 +    /**
   62.15       * Get the parent function for a function in the lexical context
   62.16       * @param functionNode function for which to get parent
   62.17       * @return parent function of functionNode or null if none (e.g. if functionNode is the program)
   62.18 @@ -472,9 +480,6 @@
   62.19              final LexicalContextNode node = iter.next();
   62.20              if (node == until) {
   62.21                  break;
   62.22 -            } else if (node instanceof SplitNode) {
   62.23 -                // Don't bother popping scopes if we're going to do a return from a split method anyway.
   62.24 -                return 0;
   62.25              }
   62.26              assert !(node instanceof FunctionNode); // Can't go outside current function
   62.27              if (node instanceof WithNode || node instanceof Block && ((Block)node).needsScope()) {
    63.1 --- a/src/jdk/nashorn/internal/ir/LexicalContextExpression.java	Mon Oct 27 14:36:13 2014 -0700
    63.2 +++ b/src/jdk/nashorn/internal/ir/LexicalContextExpression.java	Thu Nov 06 09:50:15 2014 -0800
    63.3 @@ -28,6 +28,7 @@
    63.4  import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    63.5  
    63.6  abstract class LexicalContextExpression extends Expression implements LexicalContextNode {
    63.7 +    private static final long serialVersionUID = 1L;
    63.8  
    63.9      LexicalContextExpression(final LexicalContextExpression expr) {
   63.10          super(expr);
    64.1 --- a/src/jdk/nashorn/internal/ir/LexicalContextStatement.java	Mon Oct 27 14:36:13 2014 -0700
    64.2 +++ b/src/jdk/nashorn/internal/ir/LexicalContextStatement.java	Thu Nov 06 09:50:15 2014 -0800
    64.3 @@ -28,6 +28,8 @@
    64.4  import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    64.5  
    64.6  abstract class LexicalContextStatement extends Statement implements LexicalContextNode {
    64.7 +    private static final long serialVersionUID = 1L;
    64.8 +
    64.9      /**
   64.10       * Constructor
   64.11       *
    65.1 --- a/src/jdk/nashorn/internal/ir/LiteralNode.java	Mon Oct 27 14:36:13 2014 -0700
    65.2 +++ b/src/jdk/nashorn/internal/ir/LiteralNode.java	Thu Nov 06 09:50:15 2014 -0800
    65.3 @@ -25,6 +25,7 @@
    65.4  
    65.5  package jdk.nashorn.internal.ir;
    65.6  
    65.7 +import java.io.Serializable;
    65.8  import java.util.Arrays;
    65.9  import java.util.Collections;
   65.10  import java.util.List;
   65.11 @@ -49,6 +50,8 @@
   65.12   */
   65.13  @Immutable
   65.14  public abstract class LiteralNode<T> extends Expression implements PropertyKey {
   65.15 +    private static final long serialVersionUID = 1L;
   65.16 +
   65.17      /** Literal value */
   65.18      protected final T value;
   65.19  
   65.20 @@ -270,6 +273,8 @@
   65.21       * @param <T> the literal type
   65.22       */
   65.23      public static class PrimitiveLiteralNode<T> extends LiteralNode<T> {
   65.24 +        private static final long serialVersionUID = 1L;
   65.25 +
   65.26          private PrimitiveLiteralNode(final long token, final int finish, final T value) {
   65.27              super(token, finish, value);
   65.28          }
   65.29 @@ -304,6 +309,7 @@
   65.30  
   65.31      @Immutable
   65.32      private static final class BooleanLiteralNode extends PrimitiveLiteralNode<Boolean> {
   65.33 +        private static final long serialVersionUID = 1L;
   65.34  
   65.35          private BooleanLiteralNode(final long token, final int finish, final boolean value) {
   65.36              super(Token.recast(token, value ? TokenType.TRUE : TokenType.FALSE), finish, value);
   65.37 @@ -356,6 +362,7 @@
   65.38  
   65.39      @Immutable
   65.40      private static final class NumberLiteralNode extends PrimitiveLiteralNode<Number> {
   65.41 +        private static final long serialVersionUID = 1L;
   65.42  
   65.43          private final Type type = numberGetType(value);
   65.44  
   65.45 @@ -418,6 +425,8 @@
   65.46      }
   65.47  
   65.48      private static class UndefinedLiteralNode extends PrimitiveLiteralNode<Undefined> {
   65.49 +        private static final long serialVersionUID = 1L;
   65.50 +
   65.51          private UndefinedLiteralNode(final long token, final int finish) {
   65.52              super(Token.recast(token, TokenType.OBJECT), finish, ScriptRuntime.UNDEFINED);
   65.53          }
   65.54 @@ -454,6 +463,8 @@
   65.55  
   65.56      @Immutable
   65.57      private static class StringLiteralNode extends PrimitiveLiteralNode<String> {
   65.58 +        private static final long serialVersionUID = 1L;
   65.59 +
   65.60          private StringLiteralNode(final long token, final int finish, final String value) {
   65.61              super(Token.recast(token, TokenType.STRING), finish, value);
   65.62          }
   65.63 @@ -497,6 +508,8 @@
   65.64  
   65.65      @Immutable
   65.66      private static class LexerTokenLiteralNode extends LiteralNode<LexerToken> {
   65.67 +        private static final long serialVersionUID = 1L;
   65.68 +
   65.69          private LexerTokenLiteralNode(final long token, final int finish, final LexerToken value) {
   65.70              super(Token.recast(token, TokenType.STRING), finish, value); //TODO is string the correct token type here?
   65.71          }
   65.72 @@ -560,6 +573,7 @@
   65.73      }
   65.74  
   65.75      private static final class NullLiteralNode extends PrimitiveLiteralNode<Object> {
   65.76 +        private static final long serialVersionUID = 1L;
   65.77  
   65.78          private NullLiteralNode(final long token, final int finish) {
   65.79              super(Token.recast(token, TokenType.OBJECT), finish, null);
   65.80 @@ -590,6 +604,7 @@
   65.81       */
   65.82      @Immutable
   65.83      public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode {
   65.84 +        private static final long serialVersionUID = 1L;
   65.85  
   65.86          /** Array element type. */
   65.87          private final Type elementType;
   65.88 @@ -607,7 +622,9 @@
   65.89           * An ArrayUnit is a range in an ArrayLiteral. ArrayLiterals can
   65.90           * be split if they are too large, for bytecode generation reasons
   65.91           */
   65.92 -        public static final class ArrayUnit implements CompileUnitHolder {
   65.93 +        public static final class ArrayUnit implements CompileUnitHolder, Serializable {
   65.94 +            private static final long serialVersionUID = 1L;
   65.95 +
   65.96              /** Compile unit associated with the postsets range. */
   65.97              private final CompileUnit compileUnit;
   65.98  
   65.99 @@ -655,13 +672,13 @@
  65.100          private static final class ArrayLiteralInitializer {
  65.101  
  65.102              static ArrayLiteralNode initialize(final ArrayLiteralNode node) {
  65.103 -                final Type elementType = computeElementType(node.value, node.elementType);
  65.104 +                final Type elementType = computeElementType(node.value);
  65.105                  final int[] postsets = computePostsets(node.value);
  65.106                  final Object presets = computePresets(node.value, elementType, postsets);
  65.107                  return new ArrayLiteralNode(node, node.value, elementType, postsets, presets, node.units);
  65.108              }
  65.109  
  65.110 -            private static Type computeElementType(final Expression[] value, final Type elementType) {
  65.111 +            private static Type computeElementType(final Expression[] value) {
  65.112                  Type widestElementType = Type.INT;
  65.113  
  65.114                  for (final Expression elem : value) {
    66.1 --- a/src/jdk/nashorn/internal/ir/LoopNode.java	Mon Oct 27 14:36:13 2014 -0700
    66.2 +++ b/src/jdk/nashorn/internal/ir/LoopNode.java	Thu Nov 06 09:50:15 2014 -0800
    66.3 @@ -34,6 +34,8 @@
    66.4   * A loop node, for example a while node, do while node or for node
    66.5   */
    66.6  public abstract class LoopNode extends BreakableStatement {
    66.7 +    private static final long serialVersionUID = 1L;
    66.8 +
    66.9      /** loop continue label. */
   66.10      protected final Label continueLabel;
   66.11  
    67.1 --- a/src/jdk/nashorn/internal/ir/Node.java	Mon Oct 27 14:36:13 2014 -0700
    67.2 +++ b/src/jdk/nashorn/internal/ir/Node.java	Thu Nov 06 09:50:15 2014 -0800
    67.3 @@ -25,6 +25,7 @@
    67.4  
    67.5  package jdk.nashorn.internal.ir;
    67.6  
    67.7 +import java.io.Serializable;
    67.8  import java.util.ArrayList;
    67.9  import java.util.List;
   67.10  import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   67.11 @@ -34,7 +35,18 @@
   67.12  /**
   67.13   * Nodes are used to compose Abstract Syntax Trees.
   67.14   */
   67.15 -public abstract class Node implements Cloneable {
   67.16 +public abstract class Node implements Cloneable, Serializable {
   67.17 +    private static final long serialVersionUID = 1L;
   67.18 +
   67.19 +    /** Constant used for synthetic AST nodes that have no line number. */
   67.20 +    public static final int NO_LINE_NUMBER = -1;
   67.21 +
   67.22 +    /** Constant used for synthetic AST nodes that have no token. */
   67.23 +    public static final long NO_TOKEN = 0L;
   67.24 +
   67.25 +    /** Constant used for synthetic AST nodes that have no finish. */
   67.26 +    public static final int NO_FINISH = 0;
   67.27 +
   67.28      /** Start of source range. */
   67.29      protected final int start;
   67.30  
    68.1 --- a/src/jdk/nashorn/internal/ir/ObjectNode.java	Mon Oct 27 14:36:13 2014 -0700
    68.2 +++ b/src/jdk/nashorn/internal/ir/ObjectNode.java	Thu Nov 06 09:50:15 2014 -0800
    68.3 @@ -37,6 +37,7 @@
    68.4   */
    68.5  @Immutable
    68.6  public final class ObjectNode extends Expression {
    68.7 +    private static final long serialVersionUID = 1L;
    68.8  
    68.9      /** Literal elements. */
   68.10      private final List<PropertyNode> elements;
    69.1 --- a/src/jdk/nashorn/internal/ir/PropertyNode.java	Mon Oct 27 14:36:13 2014 -0700
    69.2 +++ b/src/jdk/nashorn/internal/ir/PropertyNode.java	Thu Nov 06 09:50:15 2014 -0800
    69.3 @@ -33,6 +33,7 @@
    69.4   */
    69.5  @Immutable
    69.6  public final class PropertyNode extends Node {
    69.7 +    private static final long serialVersionUID = 1L;
    69.8  
    69.9      /** Property key. */
   69.10      private final PropertyKey key;
    70.1 --- a/src/jdk/nashorn/internal/ir/ReturnNode.java	Mon Oct 27 14:36:13 2014 -0700
    70.2 +++ b/src/jdk/nashorn/internal/ir/ReturnNode.java	Thu Nov 06 09:50:15 2014 -0800
    70.3 @@ -36,6 +36,8 @@
    70.4   */
    70.5  @Immutable
    70.6  public class ReturnNode extends Statement {
    70.7 +    private static final long serialVersionUID = 1L;
    70.8 +
    70.9      /** Optional expression. */
   70.10      private final Expression expression;
   70.11  
    71.1 --- a/src/jdk/nashorn/internal/ir/RuntimeNode.java	Mon Oct 27 14:36:13 2014 -0700
    71.2 +++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java	Thu Nov 06 09:50:15 2014 -0800
    71.3 @@ -42,6 +42,7 @@
    71.4   */
    71.5  @Immutable
    71.6  public class RuntimeNode extends Expression implements Optimistic {
    71.7 +    private static final long serialVersionUID = 1L;
    71.8  
    71.9      /**
   71.10       * Request enum used for meta-information about the runtime request
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/src/jdk/nashorn/internal/ir/SetSplitState.java	Thu Nov 06 09:50:15 2014 -0800
    72.3 @@ -0,0 +1,70 @@
    72.4 +/*
    72.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    72.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    72.7 + *
    72.8 + * This code is free software; you can redistribute it and/or modify it
    72.9 + * under the terms of the GNU General Public License version 2 only, as
   72.10 + * published by the Free Software Foundation.  Oracle designates this
   72.11 + * particular file as subject to the "Classpath" exception as provided
   72.12 + * by Oracle in the LICENSE file that accompanied this code.
   72.13 + *
   72.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   72.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   72.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   72.17 + * version 2 for more details (a copy is included in the LICENSE file that
   72.18 + * accompanied this code).
   72.19 + *
   72.20 + * You should have received a copy of the GNU General Public License version
   72.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   72.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   72.23 + *
   72.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   72.25 + * or visit www.oracle.com if you need additional information or have any
   72.26 + * questions.
   72.27 + */
   72.28 +
   72.29 +package jdk.nashorn.internal.ir;
   72.30 +
   72.31 +import jdk.nashorn.internal.codegen.CompilerConstants;
   72.32 +import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   72.33 +import jdk.nashorn.internal.runtime.Scope;
   72.34 +
   72.35 +/**
   72.36 + * Synthetic AST node that represents loading of the scope object and invocation of the {@link Scope#setSplitState(int)}
   72.37 + * method on it. It has no JavaScript source representation and only occurs in synthetic functions created by
   72.38 + * the split-into-functions transformation.
   72.39 + */
   72.40 +public final class SetSplitState extends Statement {
   72.41 +    private static final long serialVersionUID = 1L;
   72.42 +
   72.43 +    private final int state;
   72.44 +
   72.45 +    /**
   72.46 +     * Creates a new split state setter
   72.47 +     * @param state the state to set
   72.48 +     * @param lineNumber the line number where it is inserted
   72.49 +     */
   72.50 +    public SetSplitState(final int state, final int lineNumber) {
   72.51 +        super(lineNumber, NO_TOKEN, NO_FINISH);
   72.52 +        this.state = state;
   72.53 +    }
   72.54 +
   72.55 +    /**
   72.56 +     * Returns the state this setter sets.
   72.57 +     * @return the state this setter sets.
   72.58 +     */
   72.59 +    public int getState() {
   72.60 +        return state;
   72.61 +    }
   72.62 +
   72.63 +    @Override
   72.64 +    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
   72.65 +        return visitor.enterSetSplitState(this) ? visitor.leaveSetSplitState(this) : this;
   72.66 +    }
   72.67 +
   72.68 +    @Override
   72.69 +    public void toString(final StringBuilder sb, final boolean printType) {
   72.70 +        sb.append(CompilerConstants.SCOPE.symbolName()).append('.').append(Scope.SET_SPLIT_STATE.name())
   72.71 +        .append('(').append(state).append(");");
   72.72 +    }
   72.73 +}
    73.1 --- a/src/jdk/nashorn/internal/ir/SplitNode.java	Mon Oct 27 14:36:13 2014 -0700
    73.2 +++ b/src/jdk/nashorn/internal/ir/SplitNode.java	Thu Nov 06 09:50:15 2014 -0800
    73.3 @@ -25,13 +25,10 @@
    73.4  
    73.5  package jdk.nashorn.internal.ir;
    73.6  
    73.7 -import java.util.ArrayList;
    73.8 -import java.util.Collections;
    73.9 -import java.util.HashMap;
   73.10 -import java.util.List;
   73.11 -import java.util.Map;
   73.12 +import java.io.IOException;
   73.13 +import java.io.NotSerializableException;
   73.14 +import java.io.ObjectOutputStream;
   73.15  import jdk.nashorn.internal.codegen.CompileUnit;
   73.16 -import jdk.nashorn.internal.codegen.Label;
   73.17  import jdk.nashorn.internal.ir.annotations.Immutable;
   73.18  import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   73.19  
   73.20 @@ -39,7 +36,9 @@
   73.21   * Node indicating code is split across classes.
   73.22   */
   73.23  @Immutable
   73.24 -public class SplitNode extends LexicalContextStatement implements Labels, CompileUnitHolder {
   73.25 +public class SplitNode extends LexicalContextStatement implements CompileUnitHolder {
   73.26 +    private static final long serialVersionUID = 1L;
   73.27 +
   73.28      /** Split node method name. */
   73.29      private final String name;
   73.30  
   73.31 @@ -49,8 +48,6 @@
   73.32      /** Body of split code. */
   73.33      private final Block body;
   73.34  
   73.35 -    private Map<Label, JoinPredecessor> jumps;
   73.36 -
   73.37      /**
   73.38       * Constructor
   73.39       *
   73.40 @@ -65,19 +62,18 @@
   73.41          this.compileUnit = compileUnit;
   73.42      }
   73.43  
   73.44 -    private SplitNode(final SplitNode splitNode, final Block body, final CompileUnit compileUnit, final Map<Label, JoinPredecessor> jumps) {
   73.45 +    private SplitNode(final SplitNode splitNode, final Block body, final CompileUnit compileUnit) {
   73.46          super(splitNode);
   73.47          this.name        = splitNode.name;
   73.48          this.body        = body;
   73.49          this.compileUnit = compileUnit;
   73.50 -        this.jumps       = jumps;
   73.51      }
   73.52  
   73.53      /**
   73.54       * Get the body for this split node - i.e. the actual code it encloses
   73.55       * @return body for split node
   73.56       */
   73.57 -    public Node getBody() {
   73.58 +    public Block getBody() {
   73.59          return body;
   73.60      }
   73.61  
   73.62 @@ -85,7 +81,7 @@
   73.63          if (this.body == body) {
   73.64              return this;
   73.65          }
   73.66 -        return Node.replaceInLexicalContext(lc, this, new SplitNode(this, body, compileUnit, jumps));
   73.67 +        return Node.replaceInLexicalContext(lc, this, new SplitNode(this, body, compileUnit));
   73.68      }
   73.69  
   73.70      @Override
   73.71 @@ -131,33 +127,12 @@
   73.72          if (this.compileUnit == compileUnit) {
   73.73              return this;
   73.74          }
   73.75 -        return Node.replaceInLexicalContext(lc, this, new SplitNode(this, body, compileUnit, jumps));
   73.76 +        return Node.replaceInLexicalContext(lc, this, new SplitNode(this, body, compileUnit));
   73.77      }
   73.78  
   73.79 -    /**
   73.80 -     * Adds a jump that crosses this split node's boundary (it originates within the split node, and goes to a target
   73.81 -     * outside of it).
   73.82 -     * @param jumpOrigin the join predecessor that's the origin of the jump
   73.83 -     * @param targetLabel the label that's the target of the jump.
   73.84 -     */
   73.85 -    public void addJump(final JoinPredecessor jumpOrigin, final Label targetLabel) {
   73.86 -        if (jumps == null) {
   73.87 -            jumps = new HashMap<>();
   73.88 -        }
   73.89 -        jumps.put(targetLabel, jumpOrigin);
   73.90 -    }
   73.91 -
   73.92 -    /**
   73.93 -     * Returns the jump origin within this split node for a target.
   73.94 -     * @param targetLabel the target for which a jump origin is sought.
   73.95 -     * @return the jump origin, or null.
   73.96 -     */
   73.97 -    public JoinPredecessor getJumpOrigin(final Label targetLabel) {
   73.98 -        return jumps == null ? null : jumps.get(targetLabel);
   73.99 -    }
  73.100 -
  73.101 -    @Override
  73.102 -    public List<Label> getLabels() {
  73.103 -        return Collections.unmodifiableList(new ArrayList<>(jumps.keySet()));
  73.104 +    private void writeObject(final ObjectOutputStream out) throws IOException {
  73.105 +        // We are only serializing the AST after we run SplitIntoFunctions; no SplitNodes can remain for the
  73.106 +        // serialization.
  73.107 +        throw new NotSerializableException(getClass().getName());
  73.108      }
  73.109  }
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/src/jdk/nashorn/internal/ir/SplitReturn.java	Thu Nov 06 09:50:15 2014 -0800
    74.3 @@ -0,0 +1,64 @@
    74.4 +/*
    74.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    74.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    74.7 + *
    74.8 + * This code is free software; you can redistribute it and/or modify it
    74.9 + * under the terms of the GNU General Public License version 2 only, as
   74.10 + * published by the Free Software Foundation.  Oracle designates this
   74.11 + * particular file as subject to the "Classpath" exception as provided
   74.12 + * by Oracle in the LICENSE file that accompanied this code.
   74.13 + *
   74.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   74.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   74.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   74.17 + * version 2 for more details (a copy is included in the LICENSE file that
   74.18 + * accompanied this code).
   74.19 + *
   74.20 + * You should have received a copy of the GNU General Public License version
   74.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   74.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   74.23 + *
   74.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   74.25 + * or visit www.oracle.com if you need additional information or have any
   74.26 + * questions.
   74.27 + */
   74.28 +
   74.29 +package jdk.nashorn.internal.ir;
   74.30 +
   74.31 +import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   74.32 +
   74.33 +/**
   74.34 + * Synthetic AST node that represents return from a split fragment of a split function for control flow reasons (break
   74.35 + * or continue into a target outside the current fragment). It has no JavaScript source representation and only occurs
   74.36 + * in synthetic functions created by the split-into-functions transformation. It is different from a return node in
   74.37 + * that the return value is irrelevant, and doesn't affect the function's return type calculation.
   74.38 + */
   74.39 +public final class SplitReturn extends Statement {
   74.40 +    private static final long serialVersionUID = 1L;
   74.41 +
   74.42 +    /** The sole instance of this AST node. */
   74.43 +    public static final SplitReturn INSTANCE = new SplitReturn();
   74.44 +
   74.45 +    private SplitReturn() {
   74.46 +        super(NO_LINE_NUMBER, NO_TOKEN, NO_FINISH);
   74.47 +    }
   74.48 +
   74.49 +    @Override
   74.50 +    public boolean isTerminal() {
   74.51 +        return true;
   74.52 +    }
   74.53 +
   74.54 +    @Override
   74.55 +    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
   74.56 +        return visitor.enterSplitReturn(this) ? visitor.leaveSplitReturn(this) : this;
   74.57 +    }
   74.58 +
   74.59 +    @Override
   74.60 +    public void toString(StringBuilder sb, boolean printType) {
   74.61 +        sb.append(":splitreturn;");
   74.62 +    }
   74.63 +
   74.64 +    private Object readResolve() {
   74.65 +        return INSTANCE;
   74.66 +    }
   74.67 +}
    75.1 --- a/src/jdk/nashorn/internal/ir/Statement.java	Mon Oct 27 14:36:13 2014 -0700
    75.2 +++ b/src/jdk/nashorn/internal/ir/Statement.java	Thu Nov 06 09:50:15 2014 -0800
    75.3 @@ -31,6 +31,7 @@
    75.4   * location information is the Statement
    75.5   */
    75.6  public abstract class Statement extends Node implements Terminal {
    75.7 +    private static final long serialVersionUID = 1L;
    75.8  
    75.9      private final int lineNumber;
   75.10  
    76.1 --- a/src/jdk/nashorn/internal/ir/SwitchNode.java	Mon Oct 27 14:36:13 2014 -0700
    76.2 +++ b/src/jdk/nashorn/internal/ir/SwitchNode.java	Thu Nov 06 09:50:15 2014 -0800
    76.3 @@ -37,6 +37,8 @@
    76.4   */
    76.5  @Immutable
    76.6  public final class SwitchNode extends BreakableStatement {
    76.7 +    private static final long serialVersionUID = 1L;
    76.8 +
    76.9      /** Switch expression. */
   76.10      private final Expression expression;
   76.11  
    77.1 --- a/src/jdk/nashorn/internal/ir/Symbol.java	Mon Oct 27 14:36:13 2014 -0700
    77.2 +++ b/src/jdk/nashorn/internal/ir/Symbol.java	Thu Nov 06 09:50:15 2014 -0800
    77.3 @@ -97,7 +97,7 @@
    77.4      private int firstSlot = -1;
    77.5  
    77.6      /** Field number in scope or property; array index in varargs when not using arguments object. */
    77.7 -    private int fieldIndex;
    77.8 +    private int fieldIndex = -1;
    77.9  
   77.10      /** Number of times this symbol is used in code */
   77.11      private int useCount;
   77.12 @@ -135,28 +135,15 @@
   77.13       *
   77.14       * @param name  name of symbol
   77.15       * @param flags symbol flags
   77.16 -     * @param slot  bytecode slot for this symbol
   77.17       */
   77.18 -    protected Symbol(final String name, final int flags, final int slot) {
   77.19 +    public Symbol(final String name, final int flags) {
   77.20          this.name       = name;
   77.21          this.flags      = flags;
   77.22 -        this.firstSlot  = slot;
   77.23 -        this.fieldIndex = -1;
   77.24          if(shouldTrace()) {
   77.25              trace("CREATE SYMBOL " + name);
   77.26          }
   77.27      }
   77.28  
   77.29 -    /**
   77.30 -     * Constructor
   77.31 -     *
   77.32 -     * @param name  name of symbol
   77.33 -     * @param flags symbol flags
   77.34 -     */
   77.35 -    public Symbol(final String name, final int flags) {
   77.36 -        this(name, flags, -1);
   77.37 -    }
   77.38 -
   77.39      private static String align(final String string, final int max) {
   77.40          final StringBuilder sb = new StringBuilder();
   77.41          sb.append(string.substring(0, Math.min(string.length(), max)));
    78.1 --- a/src/jdk/nashorn/internal/ir/TernaryNode.java	Mon Oct 27 14:36:13 2014 -0700
    78.2 +++ b/src/jdk/nashorn/internal/ir/TernaryNode.java	Thu Nov 06 09:50:15 2014 -0800
    78.3 @@ -37,6 +37,8 @@
    78.4   */
    78.5  @Immutable
    78.6  public final class TernaryNode extends Expression {
    78.7 +    private static final long serialVersionUID = 1L;
    78.8 +
    78.9      private final Expression test;
   78.10      private final JoinPredecessorExpression trueExpr;
   78.11      private final JoinPredecessorExpression falseExpr;
    79.1 --- a/src/jdk/nashorn/internal/ir/ThrowNode.java	Mon Oct 27 14:36:13 2014 -0700
    79.2 +++ b/src/jdk/nashorn/internal/ir/ThrowNode.java	Thu Nov 06 09:50:15 2014 -0800
    79.3 @@ -33,6 +33,8 @@
    79.4   */
    79.5  @Immutable
    79.6  public final class ThrowNode extends Statement implements JoinPredecessor {
    79.7 +    private static final long serialVersionUID = 1L;
    79.8 +
    79.9      /** Exception expression. */
   79.10      private final Expression expression;
   79.11  
    80.1 --- a/src/jdk/nashorn/internal/ir/TryNode.java	Mon Oct 27 14:36:13 2014 -0700
    80.2 +++ b/src/jdk/nashorn/internal/ir/TryNode.java	Thu Nov 06 09:50:15 2014 -0800
    80.3 @@ -36,6 +36,8 @@
    80.4   */
    80.5  @Immutable
    80.6  public final class TryNode extends Statement implements JoinPredecessor {
    80.7 +    private static final long serialVersionUID = 1L;
    80.8 +
    80.9      /** Try statements. */
   80.10      private final Block body;
   80.11  
    81.1 --- a/src/jdk/nashorn/internal/ir/UnaryNode.java	Mon Oct 27 14:36:13 2014 -0700
    81.2 +++ b/src/jdk/nashorn/internal/ir/UnaryNode.java	Thu Nov 06 09:50:15 2014 -0800
    81.3 @@ -46,6 +46,8 @@
    81.4   */
    81.5  @Immutable
    81.6  public final class UnaryNode extends Expression implements Assignment<Expression>, Optimistic {
    81.7 +    private static final long serialVersionUID = 1L;
    81.8 +
    81.9      /** Right hand side argument. */
   81.10      private final Expression expression;
   81.11  
    82.1 --- a/src/jdk/nashorn/internal/ir/VarNode.java	Mon Oct 27 14:36:13 2014 -0700
    82.2 +++ b/src/jdk/nashorn/internal/ir/VarNode.java	Thu Nov 06 09:50:15 2014 -0800
    82.3 @@ -34,6 +34,8 @@
    82.4   */
    82.5  @Immutable
    82.6  public final class VarNode extends Statement implements Assignment<IdentNode> {
    82.7 +    private static final long serialVersionUID = 1L;
    82.8 +
    82.9      /** Var name. */
   82.10      private final IdentNode name;
   82.11  
   82.12 @@ -272,4 +274,12 @@
   82.13      public boolean isFunctionDeclaration() {
   82.14          return init instanceof FunctionNode && ((FunctionNode)init).isDeclared();
   82.15      }
   82.16 +
   82.17 +    /**
   82.18 +     * Returns true if this is an anonymous function declaration.
   82.19 +     * @return true if this is an anonymous function declaration.
   82.20 +     */
   82.21 +    public boolean isAnonymousFunctionDeclaration() {
   82.22 +        return isFunctionDeclaration() && ((FunctionNode)init).isAnonymous();
   82.23 +    }
   82.24  }
    83.1 --- a/src/jdk/nashorn/internal/ir/WhileNode.java	Mon Oct 27 14:36:13 2014 -0700
    83.2 +++ b/src/jdk/nashorn/internal/ir/WhileNode.java	Thu Nov 06 09:50:15 2014 -0800
    83.3 @@ -34,6 +34,8 @@
    83.4   */
    83.5  @Immutable
    83.6  public final class WhileNode extends LoopNode {
    83.7 +    private static final long serialVersionUID = 1L;
    83.8 +
    83.9  
   83.10      /** is this a do while node ? */
   83.11      private final boolean isDoWhile;
    84.1 --- a/src/jdk/nashorn/internal/ir/WithNode.java	Mon Oct 27 14:36:13 2014 -0700
    84.2 +++ b/src/jdk/nashorn/internal/ir/WithNode.java	Thu Nov 06 09:50:15 2014 -0800
    84.3 @@ -33,6 +33,8 @@
    84.4   */
    84.5  @Immutable
    84.6  public final class WithNode extends LexicalContextStatement {
    84.7 +    private static final long serialVersionUID = 1L;
    84.8 +
    84.9     /** This expression. */
   84.10      private final Expression expression;
   84.11  
    85.1 --- a/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Mon Oct 27 14:36:13 2014 -0700
    85.2 +++ b/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Thu Nov 06 09:50:15 2014 -0800
    85.3 @@ -38,6 +38,7 @@
    85.4  import jdk.nashorn.internal.ir.ExpressionStatement;
    85.5  import jdk.nashorn.internal.ir.ForNode;
    85.6  import jdk.nashorn.internal.ir.FunctionNode;
    85.7 +import jdk.nashorn.internal.ir.GetSplitState;
    85.8  import jdk.nashorn.internal.ir.IdentNode;
    85.9  import jdk.nashorn.internal.ir.IfNode;
   85.10  import jdk.nashorn.internal.ir.IndexNode;
   85.11 @@ -50,7 +51,9 @@
   85.12  import jdk.nashorn.internal.ir.PropertyNode;
   85.13  import jdk.nashorn.internal.ir.ReturnNode;
   85.14  import jdk.nashorn.internal.ir.RuntimeNode;
   85.15 +import jdk.nashorn.internal.ir.SetSplitState;
   85.16  import jdk.nashorn.internal.ir.SplitNode;
   85.17 +import jdk.nashorn.internal.ir.SplitReturn;
   85.18  import jdk.nashorn.internal.ir.SwitchNode;
   85.19  import jdk.nashorn.internal.ir.TernaryNode;
   85.20  import jdk.nashorn.internal.ir.ThrowNode;
   85.21 @@ -390,6 +393,26 @@
   85.22      }
   85.23  
   85.24      /**
   85.25 +     * Callback for entering a {@link GetSplitState}.
   85.26 +     *
   85.27 +     * @param  getSplitState the get split state expression
   85.28 +     * @return true if traversal should continue and node children be traversed, false otherwise
   85.29 +     */
   85.30 +    public boolean enterGetSplitState(final GetSplitState getSplitState) {
   85.31 +        return enterDefault(getSplitState);
   85.32 +    }
   85.33 +
   85.34 +    /**
   85.35 +     * Callback for leaving a {@link GetSplitState}.
   85.36 +     *
   85.37 +     * @param  getSplitState the get split state expression
   85.38 +     * @return processed node, which will replace the original one, or the original node
   85.39 +     */
   85.40 +    public Node leaveGetSplitState(final GetSplitState getSplitState) {
   85.41 +        return leaveDefault(getSplitState);
   85.42 +    }
   85.43 +
   85.44 +    /**
   85.45       * Callback for entering an IdentNode
   85.46       *
   85.47       * @param  identNode the node
   85.48 @@ -570,6 +593,26 @@
   85.49      }
   85.50  
   85.51      /**
   85.52 +     * Callback for entering a {@link SetSplitState}.
   85.53 +     *
   85.54 +     * @param  setSplitState the set split state statement
   85.55 +     * @return true if traversal should continue and node children be traversed, false otherwise
   85.56 +     */
   85.57 +    public boolean enterSetSplitState(final SetSplitState setSplitState) {
   85.58 +        return enterDefault(setSplitState);
   85.59 +    }
   85.60 +
   85.61 +    /**
   85.62 +     * Callback for leaving a {@link SetSplitState}.
   85.63 +     *
   85.64 +     * @param  setSplitState the set split state expression
   85.65 +     * @return processed node, which will replace the original one, or the original node
   85.66 +     */
   85.67 +    public Node leaveSetSplitState(final SetSplitState setSplitState) {
   85.68 +        return leaveDefault(setSplitState);
   85.69 +    }
   85.70 +
   85.71 +    /**
   85.72       * Callback for entering a SplitNode
   85.73       *
   85.74       * @param  splitNode the node
   85.75 @@ -590,6 +633,26 @@
   85.76      }
   85.77  
   85.78      /**
   85.79 +     * Callback for entering a SplitReturn
   85.80 +     *
   85.81 +     * @param  splitReturn the node
   85.82 +     * @return true if traversal should continue and node children be traversed, false otherwise
   85.83 +     */
   85.84 +    public boolean enterSplitReturn(final SplitReturn splitReturn) {
   85.85 +        return enterDefault(splitReturn);
   85.86 +    }
   85.87 +
   85.88 +    /**
   85.89 +     * Callback for leaving a SplitReturn
   85.90 +     *
   85.91 +     * @param  splitReturn the node
   85.92 +     * @return processed node, which will replace the original one, or the original node
   85.93 +     */
   85.94 +    public Node leaveSplitReturn(final SplitReturn splitReturn) {
   85.95 +        return leaveDefault(splitReturn);
   85.96 +    }
   85.97 +
   85.98 +    /**
   85.99       * Callback for entering a SwitchNode
  85.100       *
  85.101       * @param  switchNode the node
    86.1 --- a/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java	Mon Oct 27 14:36:13 2014 -0700
    86.2 +++ b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java	Thu Nov 06 09:50:15 2014 -0800
    86.3 @@ -48,7 +48,7 @@
    86.4  /**
    86.5   * This class is abstraction for all method handle, switchpoint and method type
    86.6   * operations. This enables the functionality interface to be subclassed and
    86.7 - * intrumensted, as it has been proven vital to keep the number of method
    86.8 + * instrumented, as it has been proven vital to keep the number of method
    86.9   * handles in the system down.
   86.10   *
   86.11   * All operations of the above type should go through this class, and not
    87.1 --- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java	Mon Oct 27 14:36:13 2014 -0700
    87.2 +++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java	Thu Nov 06 09:50:15 2014 -0800
    87.3 @@ -31,7 +31,6 @@
    87.4  
    87.5  import java.nio.ByteBuffer;
    87.6  import java.nio.ByteOrder;
    87.7 -
    87.8  import jdk.internal.dynalink.CallSiteDescriptor;
    87.9  import jdk.internal.dynalink.linker.GuardedInvocation;
   87.10  import jdk.internal.dynalink.linker.LinkRequest;
   87.11 @@ -46,7 +45,7 @@
   87.12  import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
   87.13  
   87.14  @ScriptClass("ArrayBufferView")
   87.15 -abstract class ArrayBufferView extends ScriptObject {
   87.16 +public abstract class ArrayBufferView extends ScriptObject {
   87.17      private final NativeArrayBuffer buffer;
   87.18      private final int byteOffset;
   87.19  
    88.1 --- a/src/jdk/nashorn/internal/objects/NativeArray.java	Mon Oct 27 14:36:13 2014 -0700
    88.2 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java	Thu Nov 06 09:50:15 2014 -0800
    88.3 @@ -33,6 +33,7 @@
    88.4  import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator;
    88.5  import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator;
    88.6  import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
    88.7 +
    88.8  import java.lang.invoke.MethodHandle;
    88.9  import java.lang.invoke.SwitchPoint;
   88.10  import java.util.ArrayList;
   88.11 @@ -92,9 +93,10 @@
   88.12      private static final Object CALL_CMP                 = new Object();
   88.13      private static final Object TO_LOCALE_STRING         = new Object();
   88.14  
   88.15 -    private SwitchPoint   lengthMadeNotWritableSwitchPoint;
   88.16 -    private PushLinkLogic pushLinkLogic;
   88.17 -    private PopLinkLogic  popLinkLogic;
   88.18 +    private SwitchPoint     lengthMadeNotWritableSwitchPoint;
   88.19 +    private PushLinkLogic   pushLinkLogic;
   88.20 +    private PopLinkLogic    popLinkLogic;
   88.21 +    private ConcatLinkLogic concatLinkLogic;
   88.22  
   88.23      /**
   88.24       * Index for the modification SwitchPoint that triggers when length
   88.25 @@ -130,7 +132,9 @@
   88.26          this(ArrayData.allocate(array.length));
   88.27  
   88.28          ArrayData arrayData = this.getArray();
   88.29 -        arrayData.ensure(array.length - 1);
   88.30 +        if (array.length > 0) {
   88.31 +            arrayData.ensure(array.length - 1);
   88.32 +        }
   88.33  
   88.34          for (int index = 0; index < array.length; index++) {
   88.35              final Object value = array[index];
   88.36 @@ -266,7 +270,7 @@
   88.37  
   88.38      @Override
   88.39      public Object getLength() {
   88.40 -        final long length = getArray().length() & JSType.MAX_UINT;
   88.41 +        final long length = JSType.toUint32(getArray().length());
   88.42          if(length < Integer.MAX_VALUE) {
   88.43              return (int)length;
   88.44          }
   88.45 @@ -476,7 +480,7 @@
   88.46      @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
   88.47      public static Object length(final Object self) {
   88.48          if (isArray(self)) {
   88.49 -            return ((ScriptObject) self).getArray().length() & JSType.MAX_UINT;
   88.50 +            return JSType.toUint32(((ScriptObject) self).getArray().length());
   88.51          }
   88.52  
   88.53          return 0;
   88.54 @@ -757,12 +761,86 @@
   88.55       * ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] )
   88.56       *
   88.57       * @param self self reference
   88.58 +     * @param arg argument
   88.59 +     * @return resulting NativeArray
   88.60 +     */
   88.61 +    @SpecializedFunction(linkLogic=ConcatLinkLogic.class)
   88.62 +    public static NativeArray concat(final Object self, final int arg) {
   88.63 +        final ContinuousArrayData newData = getContinuousArrayDataCCE(self, Integer.class).copy(); //get at least an integer data copy of this data
   88.64 +        newData.fastPush(arg); //add an integer to its end
   88.65 +        return new NativeArray(newData);
   88.66 +    }
   88.67 +
   88.68 +    /**
   88.69 +     * ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] )
   88.70 +     *
   88.71 +     * @param self self reference
   88.72 +     * @param arg argument
   88.73 +     * @return resulting NativeArray
   88.74 +     */
   88.75 +    @SpecializedFunction(linkLogic=ConcatLinkLogic.class)
   88.76 +    public static NativeArray concat(final Object self, final long arg) {
   88.77 +        final ContinuousArrayData newData = getContinuousArrayDataCCE(self, Long.class).copy(); //get at least a long array data copy of this data
   88.78 +        newData.fastPush(arg); //add a long at the end
   88.79 +        return new NativeArray(newData);
   88.80 +    }
   88.81 +
   88.82 +    /**
   88.83 +     * ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] )
   88.84 +     *
   88.85 +     * @param self self reference
   88.86 +     * @param arg argument
   88.87 +     * @return resulting NativeArray
   88.88 +     */
   88.89 +    @SpecializedFunction(linkLogic=ConcatLinkLogic.class)
   88.90 +    public static NativeArray concat(final Object self, final double arg) {
   88.91 +        final ContinuousArrayData newData = getContinuousArrayDataCCE(self, Double.class).copy(); //get at least a number array data copy of this data
   88.92 +        newData.fastPush(arg); //add a double at the end
   88.93 +        return new NativeArray(newData);
   88.94 +    }
   88.95 +
   88.96 +    /**
   88.97 +     * ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] )
   88.98 +     *
   88.99 +     * @param self self reference
  88.100 +     * @param arg argument
  88.101 +     * @return resulting NativeArray
  88.102 +     */
  88.103 +    @SpecializedFunction(linkLogic=ConcatLinkLogic.class)
  88.104 +    public static NativeArray concat(final Object self, final Object arg) {
  88.105 +        //arg is [NativeArray] of same type.
  88.106 +        final ContinuousArrayData selfData = getContinuousArrayDataCCE(self);
  88.107 +        final ContinuousArrayData newData;
  88.108 +
  88.109 +        if (arg instanceof NativeArray) {
  88.110 +            final ContinuousArrayData argData = (ContinuousArrayData)((NativeArray)arg).getArray();
  88.111 +            if (argData.isEmpty()) {
  88.112 +                newData = selfData.copy();
  88.113 +            } else if (selfData.isEmpty()) {
  88.114 +                newData = argData.copy();
  88.115 +            } else {
  88.116 +                final Class<?> widestElementType = selfData.widest(argData).getBoxedElementType();
  88.117 +                newData = ((ContinuousArrayData)selfData.convert(widestElementType)).fastConcat((ContinuousArrayData)argData.convert(widestElementType));
  88.118 +            }
  88.119 +        } else {
  88.120 +            newData = getContinuousArrayDataCCE(self, Object.class).copy();
  88.121 +            newData.fastPush(arg);
  88.122 +        }
  88.123 +
  88.124 +        return new NativeArray(newData);
  88.125 +    }
  88.126 +
  88.127 +    /**
  88.128 +     * ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] )
  88.129 +     *
  88.130 +     * @param self self reference
  88.131       * @param args arguments
  88.132       * @return resulting NativeArray
  88.133       */
  88.134      @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
  88.135      public static NativeArray concat(final Object self, final Object... args) {
  88.136          final ArrayList<Object> list = new ArrayList<>();
  88.137 +
  88.138          concatToList(list, Global.toObject(self));
  88.139  
  88.140          for (final Object obj : args) {
  88.141 @@ -1692,13 +1770,15 @@
  88.142              return pushLinkLogic == null ? new PushLinkLogic(this) : pushLinkLogic;
  88.143          } else if (clazz == PopLinkLogic.class) {
  88.144              return popLinkLogic == null ? new PopLinkLogic(this) : pushLinkLogic;
  88.145 +        } else if (clazz == ConcatLinkLogic.class) {
  88.146 +            return concatLinkLogic == null ? new ConcatLinkLogic(this) : concatLinkLogic;
  88.147          }
  88.148          return null;
  88.149      }
  88.150  
  88.151      @Override
  88.152      public boolean hasPerInstanceAssumptions() {
  88.153 -        return true; //length switchpoint
  88.154 +        return true; //length writable switchpoint
  88.155      }
  88.156  
  88.157      /**
  88.158 @@ -1798,6 +1878,40 @@
  88.159      }
  88.160  
  88.161      /**
  88.162 +     * This is linker logic for optimistic concatenations
  88.163 +     */
  88.164 +    private static final class ConcatLinkLogic extends ArrayLinkLogic {
  88.165 +        private ConcatLinkLogic(final NativeArray array) {
  88.166 +            super(array);
  88.167 +        }
  88.168 +
  88.169 +        @Override
  88.170 +        public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
  88.171 +            final Object[] args = request.getArguments();
  88.172 +
  88.173 +            if (args.length != 3) { //single argument check
  88.174 +                return false;
  88.175 +            }
  88.176 +
  88.177 +            final ContinuousArrayData selfData = getContinuousArrayData(self);
  88.178 +            if (selfData == null) {
  88.179 +                return false;
  88.180 +            }
  88.181 +
  88.182 +            final Object arg = args[2];
  88.183 +            //args[2] continuousarray or non arraydata, let past non array datas
  88.184 +            if (arg instanceof NativeArray) {
  88.185 +                final ContinuousArrayData argData = getContinuousArrayData(arg);
  88.186 +                if (argData == null) {
  88.187 +                    return false;
  88.188 +                }
  88.189 +            }
  88.190 +
  88.191 +            return true;
  88.192 +        }
  88.193 +    }
  88.194 +
  88.195 +    /**
  88.196       * This is linker logic for optimistic pushes
  88.197       */
  88.198      private static final class PushLinkLogic extends ArrayLinkLogic {
  88.199 @@ -1864,6 +1978,14 @@
  88.200          throw new ClassCastException();
  88.201      }
  88.202  
  88.203 +    private static final ContinuousArrayData getContinuousArrayDataCCE(final Object self) {
  88.204 +        try {
  88.205 +            return (ContinuousArrayData)((NativeArray)self).getArray();
  88.206 +         } catch (final NullPointerException e) {
  88.207 +             throw new ClassCastException();
  88.208 +         }
  88.209 +    }
  88.210 +
  88.211      private static final ContinuousArrayData getContinuousArrayDataCCE(final Object self, final Class<?> elementType) {
  88.212          try {
  88.213             return (ContinuousArrayData)((NativeArray)self).getArray(elementType); //ensure element type can fit "elementType"
    89.1 --- a/src/jdk/nashorn/internal/objects/NativeDataView.java	Mon Oct 27 14:36:13 2014 -0700
    89.2 +++ b/src/jdk/nashorn/internal/objects/NativeDataView.java	Thu Nov 06 09:50:15 2014 -0800
    89.3 @@ -27,6 +27,7 @@
    89.4  import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
    89.5  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    89.6  import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
    89.7 +
    89.8  import java.nio.ByteBuffer;
    89.9  import java.nio.ByteOrder;
   89.10  import jdk.nashorn.internal.objects.annotations.Attribute;
   89.11 @@ -432,7 +433,7 @@
   89.12      @SpecializedFunction
   89.13      public static long getUint32(final Object self, final int byteOffset) {
   89.14          try {
   89.15 -            return JSType.MAX_UINT & getBuffer(self, false).getInt(JSType.toInt32(byteOffset));
   89.16 +            return JSType.toUint32(getBuffer(self, false).getInt(JSType.toInt32(byteOffset)));
   89.17          } catch (final IllegalArgumentException iae) {
   89.18              throw rangeError(iae, "dataview.offset");
   89.19          }
   89.20 @@ -449,7 +450,7 @@
   89.21      @SpecializedFunction
   89.22      public static long getUint32(final Object self, final int byteOffset, final boolean littleEndian) {
   89.23          try {
   89.24 -            return JSType.MAX_UINT & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset));
   89.25 +            return JSType.toUint32(getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)));
   89.26          } catch (final IllegalArgumentException iae) {
   89.27              throw rangeError(iae, "dataview.offset");
   89.28          }
    90.1 --- a/src/jdk/nashorn/internal/objects/NativeDate.java	Mon Oct 27 14:36:13 2014 -0700
    90.2 +++ b/src/jdk/nashorn/internal/objects/NativeDate.java	Thu Nov 06 09:50:15 2014 -0800
    90.3 @@ -1045,7 +1045,8 @@
    90.4  
    90.5      // ECMA 15.9.1.2 TimeWithinDay (t)
    90.6      private static double timeWithinDay(final double t) {
    90.7 -        return t % msPerDay;
    90.8 +        final double val = t % msPerDay;
    90.9 +        return val < 0? val + msPerDay : val;
   90.10      }
   90.11  
   90.12      // ECMA 15.9.1.3 InLeapYear (t)
    91.1 --- a/src/jdk/nashorn/internal/objects/NativeFloat32Array.java	Mon Oct 27 14:36:13 2014 -0700
    91.2 +++ b/src/jdk/nashorn/internal/objects/NativeFloat32Array.java	Thu Nov 06 09:50:15 2014 -0800
    91.3 @@ -26,6 +26,7 @@
    91.4  package jdk.nashorn.internal.objects;
    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.nio.ByteBuffer;
   91.11 @@ -89,6 +90,11 @@
   91.12          }
   91.13  
   91.14          @Override
   91.15 +        public Class<?> getBoxedElementType() {
   91.16 +            return Double.class;
   91.17 +        }
   91.18 +
   91.19 +        @Override
   91.20          protected MethodHandle getGetElem() {
   91.21              return GET_ELEM;
   91.22          }
   91.23 @@ -141,6 +147,11 @@
   91.24          }
   91.25  
   91.26          @Override
   91.27 +        public double getDoubleOptimistic(final int index, final int programPoint) {
   91.28 +            return getElem(index);
   91.29 +        }
   91.30 +
   91.31 +        @Override
   91.32          public Object getObject(final int index) {
   91.33              return getDouble(index);
   91.34          }
    92.1 --- a/src/jdk/nashorn/internal/objects/NativeFloat64Array.java	Mon Oct 27 14:36:13 2014 -0700
    92.2 +++ b/src/jdk/nashorn/internal/objects/NativeFloat64Array.java	Thu Nov 06 09:50:15 2014 -0800
    92.3 @@ -26,6 +26,7 @@
    92.4  package jdk.nashorn.internal.objects;
    92.5  
    92.6  import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
    92.7 +
    92.8  import java.lang.invoke.MethodHandle;
    92.9  import java.lang.invoke.MethodHandles;
   92.10  import java.nio.ByteBuffer;
   92.11 @@ -98,6 +99,11 @@
   92.12              return double.class;
   92.13          }
   92.14  
   92.15 +        @Override
   92.16 +        public Class<?> getBoxedElementType() {
   92.17 +            return Double.class;
   92.18 +        }
   92.19 +
   92.20          private double getElem(final int index) {
   92.21              try {
   92.22                  return nb.get(index);
   92.23 @@ -141,6 +147,11 @@
   92.24          }
   92.25  
   92.26          @Override
   92.27 +        public double getDoubleOptimistic(final int index, final int programPoint) {
   92.28 +            return getElem(index);
   92.29 +        }
   92.30 +
   92.31 +        @Override
   92.32          public Object getObject(final int index) {
   92.33              return getDouble(index);
   92.34          }
    93.1 --- a/src/jdk/nashorn/internal/objects/NativeInt16Array.java	Mon Oct 27 14:36:13 2014 -0700
    93.2 +++ b/src/jdk/nashorn/internal/objects/NativeInt16Array.java	Thu Nov 06 09:50:15 2014 -0800
    93.3 @@ -26,6 +26,7 @@
    93.4  package jdk.nashorn.internal.objects;
    93.5  
    93.6  import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
    93.7 +
    93.8  import java.lang.invoke.MethodHandle;
    93.9  import java.lang.invoke.MethodHandles;
   93.10  import java.nio.ByteBuffer;
   93.11 @@ -99,6 +100,11 @@
   93.12              return int.class;
   93.13          }
   93.14  
   93.15 +        @Override
   93.16 +        public Class<?> getBoxedElementType() {
   93.17 +            return Integer.class;
   93.18 +        }
   93.19 +
   93.20          private int getElem(final int index) {
   93.21              try {
   93.22                  return nb.get(index);
   93.23 @@ -124,16 +130,31 @@
   93.24          }
   93.25  
   93.26          @Override
   93.27 +        public int getIntOptimistic(final int index, final int programPoint) {
   93.28 +            return getElem(index);
   93.29 +        }
   93.30 +
   93.31 +        @Override
   93.32          public long getLong(final int index) {
   93.33              return getInt(index);
   93.34          }
   93.35  
   93.36          @Override
   93.37 +        public long getLongOptimistic(final int index, final int programPoint) {
   93.38 +            return getElem(index);
   93.39 +        }
   93.40 +
   93.41 +        @Override
   93.42          public double getDouble(final int index) {
   93.43              return getInt(index);
   93.44          }
   93.45  
   93.46          @Override
   93.47 +        public double getDoubleOptimistic(final int index, final int programPoint) {
   93.48 +            return getElem(index);
   93.49 +        }
   93.50 +
   93.51 +        @Override
   93.52          public Object getObject(final int index) {
   93.53              return getInt(index);
   93.54          }
    94.1 --- a/src/jdk/nashorn/internal/objects/NativeInt32Array.java	Mon Oct 27 14:36:13 2014 -0700
    94.2 +++ b/src/jdk/nashorn/internal/objects/NativeInt32Array.java	Thu Nov 06 09:50:15 2014 -0800
    94.3 @@ -26,6 +26,7 @@
    94.4  package jdk.nashorn.internal.objects;
    94.5  
    94.6  import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
    94.7 +
    94.8  import java.lang.invoke.MethodHandle;
    94.9  import java.lang.invoke.MethodHandles;
   94.10  import java.nio.ByteBuffer;
   94.11 @@ -117,21 +118,41 @@
   94.12          }
   94.13  
   94.14          @Override
   94.15 +        public Class<?> getBoxedElementType() {
   94.16 +            return Integer.class;
   94.17 +        }
   94.18 +
   94.19 +        @Override
   94.20          public int getInt(final int index) {
   94.21              return getElem(index);
   94.22          }
   94.23  
   94.24          @Override
   94.25 +        public int getIntOptimistic(final int index, final int programPoint) {
   94.26 +            return getElem(index);
   94.27 +        }
   94.28 +
   94.29 +        @Override
   94.30          public long getLong(final int index) {
   94.31              return getInt(index);
   94.32          }
   94.33  
   94.34          @Override
   94.35 +        public long getLongOptimistic(final int index, final int programPoint) {
   94.36 +            return getElem(index);
   94.37 +        }
   94.38 +
   94.39 +        @Override
   94.40          public double getDouble(final int index) {
   94.41              return getInt(index);
   94.42          }
   94.43  
   94.44          @Override
   94.45 +        public double getDoubleOptimistic(final int index, final int programPoint) {
   94.46 +            return getElem(index);
   94.47 +        }
   94.48 +
   94.49 +        @Override
   94.50          public Object getObject(final int index) {
   94.51              return getInt(index);
   94.52          }
    95.1 --- a/src/jdk/nashorn/internal/objects/NativeInt8Array.java	Mon Oct 27 14:36:13 2014 -0700
    95.2 +++ b/src/jdk/nashorn/internal/objects/NativeInt8Array.java	Thu Nov 06 09:50:15 2014 -0800
    95.3 @@ -26,6 +26,7 @@
    95.4  package jdk.nashorn.internal.objects;
    95.5  
    95.6  import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
    95.7 +
    95.8  import java.lang.invoke.MethodHandle;
    95.9  import java.lang.invoke.MethodHandles;
   95.10  import java.nio.ByteBuffer;
   95.11 @@ -97,6 +98,11 @@
   95.12              return int.class;
   95.13          }
   95.14  
   95.15 +        @Override
   95.16 +        public Class<?> getBoxedElementType() {
   95.17 +            return Integer.class;
   95.18 +        }
   95.19 +
   95.20          private int getElem(final int index) {
   95.21              try {
   95.22                  return nb.get(index);
   95.23 @@ -122,16 +128,31 @@
   95.24          }
   95.25  
   95.26          @Override
   95.27 +        public int getIntOptimistic(final int index, final int programPoint) {
   95.28 +            return getElem(index);
   95.29 +        }
   95.30 +
   95.31 +        @Override
   95.32          public long getLong(final int index) {
   95.33              return getInt(index);
   95.34          }
   95.35  
   95.36          @Override
   95.37 +        public long getLongOptimistic(final int index, final int programPoint) {
   95.38 +            return getElem(index);
   95.39 +        }
   95.40 +
   95.41 +        @Override
   95.42          public double getDouble(final int index) {
   95.43              return getInt(index);
   95.44          }
   95.45  
   95.46          @Override
   95.47 +        public double getDoubleOptimistic(final int index, final int programPoint) {
   95.48 +            return getElem(index);
   95.49 +        }
   95.50 +
   95.51 +        @Override
   95.52          public Object getObject(final int index) {
   95.53              return getInt(index);
   95.54          }
    96.1 --- a/src/jdk/nashorn/internal/objects/NativeJava.java	Mon Oct 27 14:36:13 2014 -0700
    96.2 +++ b/src/jdk/nashorn/internal/objects/NativeJava.java	Thu Nov 06 09:50:15 2014 -0800
    96.3 @@ -90,7 +90,11 @@
    96.4       */
    96.5      @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    96.6      public static Object synchronizedFunc(final Object self, final Object func, final Object obj) {
    96.7 -        return ScriptUtils.makeSynchronizedFunction(func, obj);
    96.8 +        if (func instanceof ScriptFunction) {
    96.9 +            return ((ScriptFunction)func).makeSynchronizedFunction(obj);
   96.10 +        }
   96.11 +
   96.12 +        throw typeError("not.a.function", ScriptRuntime.safeToString(func));
   96.13      }
   96.14  
   96.15      /**
    97.1 --- a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java	Mon Oct 27 14:36:13 2014 -0700
    97.2 +++ b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java	Thu Nov 06 09:50:15 2014 -0800
    97.3 @@ -25,6 +25,7 @@
    97.4  
    97.5  package jdk.nashorn.internal.objects;
    97.6  
    97.7 +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    97.8  import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
    97.9  
   97.10  import jdk.internal.dynalink.CallSiteDescriptor;
   97.11 @@ -36,9 +37,11 @@
   97.12  import jdk.nashorn.internal.objects.annotations.Function;
   97.13  import jdk.nashorn.internal.objects.annotations.ScriptClass;
   97.14  import jdk.nashorn.internal.runtime.Context;
   97.15 +import jdk.nashorn.internal.runtime.JSType;
   97.16  import jdk.nashorn.internal.runtime.NativeJavaPackage;
   97.17  import jdk.nashorn.internal.runtime.PropertyMap;
   97.18  import jdk.nashorn.internal.runtime.ScriptObject;
   97.19 +import jdk.nashorn.internal.runtime.ScriptRuntime;
   97.20  import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
   97.21  
   97.22  /**
   97.23 @@ -94,33 +97,30 @@
   97.24      }
   97.25  
   97.26      /**
   97.27 -     * "No such property" call placeholder.
   97.28 -     *
   97.29 -     * This can never be called as we override {@link ScriptObject#noSuchProperty}. We do declare it here as it's a signal
   97.30 -     * to {@link jdk.nashorn.internal.runtime.WithObject} that it's worth trying doing a {@code noSuchProperty} on this object.
   97.31 +     * "No such property" handler.
   97.32       *
   97.33       * @param self self reference
   97.34       * @param name property name
   97.35 -     * @return never returns
   97.36 +     * @return value of the missing property
   97.37       */
   97.38      @Function(attributes = Attribute.NOT_ENUMERABLE)
   97.39      public static Object __noSuchProperty__(final Object self, final Object name) {
   97.40 -        throw new AssertionError("__noSuchProperty__ placeholder called");
   97.41 +        if (! (self instanceof NativeJavaImporter)) {
   97.42 +            throw typeError("not.a.java.importer", ScriptRuntime.safeToString(self));
   97.43 +        }
   97.44 +        return ((NativeJavaImporter)self).createProperty(JSType.toString(name));
   97.45      }
   97.46  
   97.47      /**
   97.48 -     * "No such method call" placeholder
   97.49 -     *
   97.50 -     * This can never be called as we override {@link ScriptObject#noSuchMethod}. We do declare it here as it's a signal
   97.51 -     * to {@link jdk.nashorn.internal.runtime.WithObject} that it's worth trying doing a noSuchProperty on this object.
   97.52 +     * "No such method call" handler
   97.53       *
   97.54       * @param self self reference
   97.55       * @param args arguments to method
   97.56 -     * @return never returns
   97.57 +     * @return never returns always throw TypeError
   97.58       */
   97.59      @Function(attributes = Attribute.NOT_ENUMERABLE)
   97.60      public static Object __noSuchMethod__(final Object self, final Object... args) {
   97.61 -        throw new AssertionError("__noSuchMethod__ placeholder called");
   97.62 +       throw typeError("not.a.function", ScriptRuntime.safeToString(args[0]));
   97.63      }
   97.64  
   97.65      @Override
    98.1 --- a/src/jdk/nashorn/internal/objects/NativeObject.java	Mon Oct 27 14:36:13 2014 -0700
    98.2 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java	Thu Nov 06 09:50:15 2014 -0800
    98.3 @@ -28,7 +28,6 @@
    98.4  import static jdk.nashorn.internal.lookup.Lookup.MH;
    98.5  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    98.6  import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
    98.7 -
    98.8  import java.lang.invoke.MethodHandle;
    98.9  import java.lang.invoke.MethodHandles;
   98.10  import java.lang.invoke.MethodType;
   98.11 @@ -673,7 +672,7 @@
   98.12              for (final Property prop : properties) {
   98.13                  if (prop.isEnumerable()) {
   98.14                      final Object value = sourceObj.get(prop.getKey());
   98.15 -                    prop.setCurrentType(Object.class);
   98.16 +                    prop.setType(Object.class);
   98.17                      prop.setValue(sourceObj, sourceObj, value, false);
   98.18                      propList.add(prop);
   98.19                  }
    99.1 --- a/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java	Mon Oct 27 14:36:13 2014 -0700
    99.2 +++ b/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java	Thu Nov 06 09:50:15 2014 -0800
    99.3 @@ -74,7 +74,7 @@
    99.4      @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
    99.5      public static Object length(final Object self) {
    99.6          if (self instanceof ScriptObject) {
    99.7 -            return ((ScriptObject)self).getArray().length() & JSType.MAX_UINT;
    99.8 +            return JSType.toUint32(((ScriptObject)self).getArray().length());
    99.9          }
   99.10  
   99.11          return 0;
   100.1 --- a/src/jdk/nashorn/internal/objects/NativeUint16Array.java	Mon Oct 27 14:36:13 2014 -0700
   100.2 +++ b/src/jdk/nashorn/internal/objects/NativeUint16Array.java	Thu Nov 06 09:50:15 2014 -0800
   100.3 @@ -26,6 +26,7 @@
   100.4  package jdk.nashorn.internal.objects;
   100.5  
   100.6  import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
   100.7 +
   100.8  import java.lang.invoke.MethodHandle;
   100.9  import java.lang.invoke.MethodHandles;
  100.10  import java.nio.ByteBuffer;
  100.11 @@ -123,21 +124,41 @@
  100.12          }
  100.13  
  100.14          @Override
  100.15 +        public Class<?> getBoxedElementType() {
  100.16 +            return Integer.class;
  100.17 +        }
  100.18 +
  100.19 +        @Override
  100.20          public int getInt(final int index) {
  100.21              return getElem(index);
  100.22          }
  100.23  
  100.24          @Override
  100.25 +        public int getIntOptimistic(final int index, final int programPoint) {
  100.26 +            return getElem(index);
  100.27 +        }
  100.28 +
  100.29 +        @Override
  100.30          public long getLong(final int index) {
  100.31              return getInt(index);
  100.32          }
  100.33  
  100.34          @Override
  100.35 +        public long getLongOptimistic(final int index, final int programPoint) {
  100.36 +            return getElem(index);
  100.37 +        }
  100.38 +
  100.39 +        @Override
  100.40          public double getDouble(final int index) {
  100.41              return getInt(index);
  100.42          }
  100.43  
  100.44          @Override
  100.45 +        public double getDoubleOptimistic(final int index, final int programPoint) {
  100.46 +            return getElem(index);
  100.47 +        }
  100.48 +
  100.49 +        @Override
  100.50          public Object getObject(final int index) {
  100.51              return getInt(index);
  100.52          }
   101.1 --- a/src/jdk/nashorn/internal/objects/NativeUint32Array.java	Mon Oct 27 14:36:13 2014 -0700
   101.2 +++ b/src/jdk/nashorn/internal/objects/NativeUint32Array.java	Thu Nov 06 09:50:15 2014 -0800
   101.3 @@ -26,6 +26,7 @@
   101.4  package jdk.nashorn.internal.objects;
   101.5  
   101.6  import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
   101.7 +
   101.8  import java.lang.invoke.MethodHandle;
   101.9  import java.lang.invoke.MethodHandles;
  101.10  import java.nio.ByteBuffer;
  101.11 @@ -104,7 +105,7 @@
  101.12  
  101.13          private long getElem(final int index) {
  101.14              try {
  101.15 -                return nb.get(index) & JSType.MAX_UINT;
  101.16 +                return JSType.toUint32(nb.get(index));
  101.17              } catch (final IndexOutOfBoundsException e) {
  101.18                  throw new ClassCastException(); //force relink - this works for unoptimistic too
  101.19              }
  101.20 @@ -128,7 +129,12 @@
  101.21  
  101.22          @Override
  101.23          public Class<?> getElementType() {
  101.24 -            return int.class;
  101.25 +            return long.class;
  101.26 +        }
  101.27 +
  101.28 +        @Override
  101.29 +        public Class<?> getBoxedElementType() {
  101.30 +            return Integer.class;
  101.31          }
  101.32  
  101.33          @Override
  101.34 @@ -142,11 +148,21 @@
  101.35          }
  101.36  
  101.37          @Override
  101.38 +        public long getLongOptimistic(final int index, final int programPoint) {
  101.39 +            return getElem(index);
  101.40 +        }
  101.41 +
  101.42 +        @Override
  101.43          public double getDouble(final int index) {
  101.44              return getLong(index);
  101.45          }
  101.46  
  101.47          @Override
  101.48 +        public double getDoubleOptimistic(final int index, final int programPoint) {
  101.49 +            return getLong(index);
  101.50 +        }
  101.51 +
  101.52 +        @Override
  101.53          public Object getObject(final int index) {
  101.54              return getLong(index);
  101.55          }
   102.1 --- a/src/jdk/nashorn/internal/objects/NativeUint8Array.java	Mon Oct 27 14:36:13 2014 -0700
   102.2 +++ b/src/jdk/nashorn/internal/objects/NativeUint8Array.java	Thu Nov 06 09:50:15 2014 -0800
   102.3 @@ -26,6 +26,7 @@
   102.4  package jdk.nashorn.internal.objects;
   102.5  
   102.6  import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
   102.7 +
   102.8  import java.lang.invoke.MethodHandle;
   102.9  import java.lang.invoke.MethodHandles;
  102.10  import java.nio.ByteBuffer;
  102.11 @@ -123,21 +124,41 @@
  102.12          }
  102.13  
  102.14          @Override
  102.15 +        public Class<?> getBoxedElementType() {
  102.16 +            return Integer.class;
  102.17 +        }
  102.18 +
  102.19 +        @Override
  102.20          public int getInt(final int index) {
  102.21              return getElem(index);
  102.22          }
  102.23  
  102.24          @Override
  102.25 +        public int getIntOptimistic(final int index, final int programPoint) {
  102.26 +            return getElem(index);
  102.27 +        }
  102.28 +
  102.29 +        @Override
  102.30          public long getLong(final int index) {
  102.31              return getInt(index);
  102.32          }
  102.33  
  102.34          @Override
  102.35 +        public long getLongOptimistic(final int index, final int programPoint) {
  102.36 +            return getElem(index);
  102.37 +        }
  102.38 +
  102.39 +        @Override
  102.40          public double getDouble(final int index) {
  102.41              return getInt(index);
  102.42          }
  102.43  
  102.44          @Override
  102.45 +        public double getDoubleOptimistic(final int index, final int programPoint) {
  102.46 +            return getElem(index);
  102.47 +        }
  102.48 +
  102.49 +        @Override
  102.50          public Object getObject(final int index) {
  102.51              return getInt(index);
  102.52          }
   103.1 --- a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java	Mon Oct 27 14:36:13 2014 -0700
   103.2 +++ b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java	Thu Nov 06 09:50:15 2014 -0800
   103.3 @@ -28,6 +28,7 @@
   103.4  import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
   103.5  import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
   103.6  import static jdk.nashorn.internal.lookup.Lookup.MH;
   103.7 +
   103.8  import java.lang.invoke.MethodHandle;
   103.9  import java.lang.invoke.MethodHandles;
  103.10  import java.nio.ByteBuffer;
  103.11 @@ -102,6 +103,11 @@
  103.12              return int.class;
  103.13          }
  103.14  
  103.15 +        @Override
  103.16 +        public Class<?> getBoxedElementType() {
  103.17 +            return int.class;
  103.18 +        }
  103.19 +
  103.20          private int getElem(final int index) {
  103.21              try {
  103.22                  return nb.get(index) & 0xff;
  103.23 @@ -158,16 +164,31 @@
  103.24          }
  103.25  
  103.26          @Override
  103.27 +        public int getIntOptimistic(final int index, final int programPoint) {
  103.28 +            return getElem(index);
  103.29 +        }
  103.30 +
  103.31 +        @Override
  103.32          public long getLong(final int index) {
  103.33              return getInt(index);
  103.34          }
  103.35  
  103.36          @Override
  103.37 +        public long getLongOptimistic(final int index, final int programPoint) {
  103.38 +            return getElem(index);
  103.39 +        }
  103.40 +
  103.41 +        @Override
  103.42          public double getDouble(final int index) {
  103.43              return getInt(index);
  103.44          }
  103.45  
  103.46          @Override
  103.47 +        public double getDoubleOptimistic(final int index, final int programPoint) {
  103.48 +            return getElem(index);
  103.49 +        }
  103.50 +
  103.51 +        @Override
  103.52          public Object getObject(final int index) {
  103.53              return getInt(index);
  103.54          }
   104.1 --- a/src/jdk/nashorn/internal/parser/JSONParser.java	Mon Oct 27 14:36:13 2014 -0700
   104.2 +++ b/src/jdk/nashorn/internal/parser/JSONParser.java	Thu Nov 06 09:50:15 2014 -0800
   104.3 @@ -32,7 +32,6 @@
   104.4  import static jdk.nashorn.internal.parser.TokenType.RBRACE;
   104.5  import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
   104.6  import static jdk.nashorn.internal.parser.TokenType.STRING;
   104.7 -
   104.8  import java.util.ArrayList;
   104.9  import java.util.List;
  104.10  import jdk.nashorn.internal.ir.Expression;
   105.1 --- a/src/jdk/nashorn/internal/parser/Lexer.java	Mon Oct 27 14:36:13 2014 -0700
   105.2 +++ b/src/jdk/nashorn/internal/parser/Lexer.java	Thu Nov 06 09:50:15 2014 -0800
   105.3 @@ -46,6 +46,7 @@
   105.4  import static jdk.nashorn.internal.parser.TokenType.STRING;
   105.5  import static jdk.nashorn.internal.parser.TokenType.XML;
   105.6  
   105.7 +import java.io.Serializable;
   105.8  import jdk.nashorn.internal.runtime.ECMAErrors;
   105.9  import jdk.nashorn.internal.runtime.ErrorManager;
  105.10  import jdk.nashorn.internal.runtime.JSErrorType;
  105.11 @@ -1717,7 +1718,9 @@
  105.12       * Helper class for Lexer tokens, e.g XML or RegExp tokens.
  105.13       * This is the abstract superclass
  105.14       */
  105.15 -    public static abstract class LexerToken {
  105.16 +    public static abstract class LexerToken implements Serializable {
  105.17 +        private static final long serialVersionUID = 1L;
  105.18 +
  105.19          private final String expression;
  105.20  
  105.21          /**
  105.22 @@ -1741,6 +1744,8 @@
  105.23       * Temporary container for regular expressions.
  105.24       */
  105.25      public static class RegexToken extends LexerToken {
  105.26 +        private static final long serialVersionUID = 1L;
  105.27 +
  105.28          /** Options. */
  105.29          private final String options;
  105.30  
  105.31 @@ -1773,6 +1778,7 @@
  105.32       * Temporary container for XML expression.
  105.33       */
  105.34      public static class XMLToken extends LexerToken {
  105.35 +        private static final long serialVersionUID = 1L;
  105.36  
  105.37          /**
  105.38           * Constructor.
   106.1 --- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Mon Oct 27 14:36:13 2014 -0700
   106.2 +++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Thu Nov 06 09:50:15 2014 -0800
   106.3 @@ -145,13 +145,6 @@
   106.4      transient MethodHandle objectSetter;
   106.5  
   106.6      /**
   106.7 -     * Current type of this object, in object only mode, this is an Object.class. In dual-fields mode
   106.8 -     * null means undefined, and primitive types are allowed. The reason a special type is used for
   106.9 -     * undefined, is that are no bits left to represent it in primitive types
  106.10 -     */
  106.11 -    private Class<?> currentType;
  106.12 -
  106.13 -    /**
  106.14       * Delegate constructor for bound properties. This is used for properties created by
  106.15       * {@link ScriptRuntime#mergeScope} and the Nashorn {@code Object.bindProperties} method.
  106.16       * The former is used to add a script's defined globals to the current global scope while
  106.17 @@ -171,7 +164,7 @@
  106.18          this.objectSetter    = bindTo(property.objectSetter, delegate);
  106.19          property.GETTER_CACHE = new MethodHandle[NOOF_TYPES];
  106.20          // Properties created this way are bound to a delegate
  106.21 -        setCurrentType(property.getCurrentType());
  106.22 +        setType(property.getType());
  106.23      }
  106.24  
  106.25      /**
  106.26 @@ -248,7 +241,7 @@
  106.27          objectGetter  = getter.type() != Lookup.GET_OBJECT_TYPE ? MH.asType(getter, Lookup.GET_OBJECT_TYPE) : getter;
  106.28          objectSetter  = setter != null && setter.type() != Lookup.SET_OBJECT_TYPE ? MH.asType(setter, Lookup.SET_OBJECT_TYPE) : setter;
  106.29  
  106.30 -        setCurrentType(OBJECT_FIELDS_ONLY ? Object.class : getterType);
  106.31 +        setType(OBJECT_FIELDS_ONLY ? Object.class : getterType);
  106.32      }
  106.33  
  106.34      /**
  106.35 @@ -317,7 +310,7 @@
  106.36       */
  106.37      public AccessorProperty(final String key, final int flags, final Class<?> structure, final int slot, final Class<?> initialType) {
  106.38          this(key, flags, structure, slot);
  106.39 -        setCurrentType(OBJECT_FIELDS_ONLY ? Object.class : initialType);
  106.40 +        setType(OBJECT_FIELDS_ONLY ? Object.class : initialType);
  106.41      }
  106.42  
  106.43      /**
  106.44 @@ -330,13 +323,13 @@
  106.45      protected AccessorProperty(final AccessorProperty property, final Class<?> newType) {
  106.46          super(property, property.getFlags());
  106.47  
  106.48 -        this.GETTER_CACHE    = newType != property.getCurrentType() ? new MethodHandle[NOOF_TYPES] : property.GETTER_CACHE;
  106.49 +        this.GETTER_CACHE    = newType != property.getLocalType() ? new MethodHandle[NOOF_TYPES] : property.GETTER_CACHE;
  106.50          this.primitiveGetter = property.primitiveGetter;
  106.51          this.primitiveSetter = property.primitiveSetter;
  106.52          this.objectGetter    = property.objectGetter;
  106.53          this.objectSetter    = property.objectSetter;
  106.54  
  106.55 -        setCurrentType(newType);
  106.56 +        setType(newType);
  106.57      }
  106.58  
  106.59      /**
  106.60 @@ -345,7 +338,7 @@
  106.61       * @param property  source property
  106.62       */
  106.63      protected AccessorProperty(final AccessorProperty property) {
  106.64 -        this(property, property.getCurrentType());
  106.65 +        this(property, property.getLocalType());
  106.66      }
  106.67  
  106.68      /**
  106.69 @@ -354,7 +347,7 @@
  106.70       * @param initialValue initial value
  106.71       */
  106.72      protected final void setInitialValue(final ScriptObject owner, final Object initialValue) {
  106.73 -        setCurrentType(JSType.unboxedFieldType(initialValue));
  106.74 +        setType(JSType.unboxedFieldType(initialValue));
  106.75          if (initialValue instanceof Integer) {
  106.76              invokeSetter(owner, ((Integer)initialValue).intValue());
  106.77          } else if (initialValue instanceof Long) {
  106.78 @@ -370,7 +363,7 @@
  106.79       * Initialize the type of a property
  106.80       */
  106.81      protected final void initializeType() {
  106.82 -        setCurrentType(OBJECT_FIELDS_ONLY ? Object.class : null);
  106.83 +        setType(OBJECT_FIELDS_ONLY ? Object.class : null);
  106.84      }
  106.85  
  106.86      private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException {
  106.87 @@ -557,12 +550,12 @@
  106.88          } else {
  106.89              getter = debug(
  106.90                  createGetter(
  106.91 -                    getCurrentType(),
  106.92 +                    getLocalType(),
  106.93                      type,
  106.94                      primitiveGetter,
  106.95                      objectGetter,
  106.96                      INVALID_PROGRAM_POINT),
  106.97 -                getCurrentType(),
  106.98 +                getLocalType(),
  106.99                  type,
 106.100                  "get");
 106.101              getterCache[i] = getter;
 106.102 @@ -582,18 +575,18 @@
 106.103  
 106.104          return debug(
 106.105              createGetter(
 106.106 -                getCurrentType(),
 106.107 +                getLocalType(),
 106.108                  type,
 106.109                  primitiveGetter,
 106.110                  objectGetter,
 106.111                  programPoint),
 106.112 -            getCurrentType(),
 106.113 +            getLocalType(),
 106.114              type,
 106.115              "get");
 106.116      }
 106.117  
 106.118      private MethodHandle getOptimisticPrimitiveGetter(final Class<?> type, final int programPoint) {
 106.119 -        final MethodHandle g = getGetter(getCurrentType());
 106.120 +        final MethodHandle g = getGetter(getLocalType());
 106.121          return MH.asType(OptimisticReturnFilters.filterOptimisticReturnValue(g, type, programPoint), g.type().changeReturnType(type));
 106.122      }
 106.123  
 106.124 @@ -631,7 +624,7 @@
 106.125      }
 106.126  
 106.127      private MethodHandle generateSetter(final Class<?> forType, final Class<?> type) {
 106.128 -        return debug(createSetter(forType, type, primitiveSetter, objectSetter), getCurrentType(), type, "set");
 106.129 +        return debug(createSetter(forType, type, primitiveSetter, objectSetter), getLocalType(), type, "set");
 106.130      }
 106.131  
 106.132      /**
 106.133 @@ -639,7 +632,7 @@
 106.134       * @return true if undefined
 106.135       */
 106.136      protected final boolean isUndefined() {
 106.137 -        return getCurrentType() == null;
 106.138 +        return getLocalType() == null;
 106.139      }
 106.140  
 106.141      @Override
 106.142 @@ -647,7 +640,7 @@
 106.143          checkUndeclared();
 106.144  
 106.145          final int typeIndex        = getAccessorTypeIndex(type);
 106.146 -        final int currentTypeIndex = getAccessorTypeIndex(getCurrentType());
 106.147 +        final int currentTypeIndex = getAccessorTypeIndex(getLocalType());
 106.148  
 106.149          //if we are asking for an object setter, but are still a primitive type, we might try to box it
 106.150          MethodHandle mh;
 106.151 @@ -656,13 +649,13 @@
 106.152              final PropertyMap  newMap      = getWiderMap(currentMap, newProperty);
 106.153  
 106.154              final MethodHandle widerSetter = newProperty.getSetter(type, newMap);
 106.155 -            final Class<?>     ct = getCurrentType();
 106.156 +            final Class<?>     ct = getLocalType();
 106.157              mh = MH.filterArguments(widerSetter, 0, MH.insertArguments(debugReplace(ct, type, currentMap, newMap) , 1, newMap));
 106.158              if (ct != null && ct.isPrimitive() && !type.isPrimitive()) {
 106.159                   mh = ObjectClassGenerator.createGuardBoxedPrimitiveSetter(ct, generateSetter(ct, ct), mh);
 106.160              }
 106.161          } else {
 106.162 -            final Class<?> forType = isUndefined() ? type : getCurrentType();
 106.163 +            final Class<?> forType = isUndefined() ? type : getLocalType();
 106.164              mh = generateSetter(!forType.isPrimitive() ? Object.class : forType, type);
 106.165          }
 106.166  
 106.167 @@ -681,24 +674,13 @@
 106.168              return false;
 106.169          }
 106.170          // Return true for currently undefined even if non-writable/configurable to allow initialization of ES6 CONST.
 106.171 -        return getCurrentType() == null || (getCurrentType() != Object.class && (isConfigurable() || isWritable()));
 106.172 +        return getLocalType() == null || (getLocalType() != Object.class && (isConfigurable() || isWritable()));
 106.173      }
 106.174  
 106.175      private boolean needsInvalidator(final int typeIndex, final int currentTypeIndex) {
 106.176          return canChangeType() && typeIndex > currentTypeIndex;
 106.177      }
 106.178  
 106.179 -    @Override
 106.180 -    public final void setCurrentType(final Class<?> currentType) {
 106.181 -        assert currentType != boolean.class : "no boolean storage support yet - fix this";
 106.182 -        this.currentType = currentType == null ? null : currentType.isPrimitive() ? currentType : Object.class;
 106.183 -    }
 106.184 -
 106.185 -    @Override
 106.186 -    public Class<?> getCurrentType() {
 106.187 -        return currentType;
 106.188 -    }
 106.189 -
 106.190      private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) {
 106.191          if (!Context.DEBUG || !Global.hasInstance()) {
 106.192              return mh;
   107.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   107.2 +++ b/src/jdk/nashorn/internal/runtime/AstDeserializer.java	Thu Nov 06 09:50:15 2014 -0800
   107.3 @@ -0,0 +1,47 @@
   107.4 +/*
   107.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
   107.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   107.7 + *
   107.8 + * This code is free software; you can redistribute it and/or modify it
   107.9 + * under the terms of the GNU General Public License version 2 only, as
  107.10 + * published by the Free Software Foundation.  Oracle designates this
  107.11 + * particular file as subject to the "Classpath" exception as provided
  107.12 + * by Oracle in the LICENSE file that accompanied this code.
  107.13 + *
  107.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  107.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  107.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  107.17 + * version 2 for more details (a copy is included in the LICENSE file that
  107.18 + * accompanied this code).
  107.19 + *
  107.20 + * You should have received a copy of the GNU General Public License version
  107.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  107.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  107.23 + *
  107.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  107.25 + * or visit www.oracle.com if you need additional information or have any
  107.26 + * questions.
  107.27 + */
  107.28 +package jdk.nashorn.internal.runtime;
  107.29 +
  107.30 +import java.io.ByteArrayInputStream;
  107.31 +import java.io.IOException;
  107.32 +import java.io.ObjectInputStream;
  107.33 +import java.util.zip.InflaterInputStream;
  107.34 +import jdk.nashorn.internal.ir.FunctionNode;
  107.35 +
  107.36 +/**
  107.37 + * This static utility class performs deserialization of FunctionNode ASTs from a byte array.
  107.38 + * The format is a standard Java serialization stream, deflated.
  107.39 + */
  107.40 +final class AstDeserializer {
  107.41 +    static FunctionNode deserialize(final byte[] serializedAst) {
  107.42 +        try {
  107.43 +            return (FunctionNode)new ObjectInputStream(new InflaterInputStream(new ByteArrayInputStream(
  107.44 +                    serializedAst))).readObject();
  107.45 +        } catch (final ClassNotFoundException | IOException e) {
  107.46 +            // This is internal, can't happen
  107.47 +            throw new AssertionError("Unexpected exception deserializing function", e);
  107.48 +        }
  107.49 +    }
  107.50 +}
   108.1 --- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Mon Oct 27 14:36:13 2014 -0700
   108.2 +++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Thu Nov 06 09:50:15 2014 -0800
   108.3 @@ -27,6 +27,7 @@
   108.4  import static jdk.nashorn.internal.lookup.Lookup.MH;
   108.5  import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
   108.6  import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
   108.7 +
   108.8  import java.lang.invoke.CallSite;
   108.9  import java.lang.invoke.MethodHandle;
  108.10  import java.lang.invoke.MethodHandles;
  108.11 @@ -786,6 +787,7 @@
  108.12          // isn't available, we'll use the old one bound into the call site.
  108.13          final OptimismInfo effectiveOptInfo = currentOptInfo != null ? currentOptInfo : oldOptInfo;
  108.14          FunctionNode fn = effectiveOptInfo.reparse();
  108.15 +        final boolean serialized = effectiveOptInfo.isSerialized();
  108.16          final Compiler compiler = effectiveOptInfo.getCompiler(fn, callSiteType, re); //set to non rest-of
  108.17  
  108.18          if (!shouldRecompile) {
  108.19 @@ -793,17 +795,17 @@
  108.20              // recompiled a deoptimized version for an inner invocation.
  108.21              // We still need to do the rest of from the beginning
  108.22              logRecompile("Rest-of compilation [STANDALONE] ", fn, callSiteType, effectiveOptInfo.invalidatedProgramPoints);
  108.23 -            return restOfHandle(effectiveOptInfo, compiler.compile(fn, CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null);
  108.24 +            return restOfHandle(effectiveOptInfo, compiler.compile(fn, serialized ? CompilationPhases.COMPILE_SERIALIZED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null);
  108.25          }
  108.26  
  108.27          logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, callSiteType, effectiveOptInfo.invalidatedProgramPoints);
  108.28 -        fn = compiler.compile(fn, CompilationPhases.COMPILE_UPTO_BYTECODE);
  108.29 +        fn = compiler.compile(fn, serialized ? CompilationPhases.RECOMPILE_SERIALIZED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE);
  108.30          log.info("Reusable IR generated");
  108.31  
  108.32          // compile the rest of the function, and install it
  108.33          log.info("Generating and installing bytecode from reusable IR...");
  108.34          logRecompile("Rest-of compilation [CODE PIPELINE REUSE] ", fn, callSiteType, effectiveOptInfo.invalidatedProgramPoints);
  108.35 -        final FunctionNode normalFn = compiler.compile(fn, CompilationPhases.COMPILE_FROM_BYTECODE);
  108.36 +        final FunctionNode normalFn = compiler.compile(fn, CompilationPhases.GENERATE_BYTECODE_AND_INSTALL);
  108.37  
  108.38          if (effectiveOptInfo.data.usePersistentCodeCache()) {
  108.39              final RecompilableScriptFunctionData data = effectiveOptInfo.data;
  108.40 @@ -829,7 +831,7 @@
  108.41          constructor = null; // Will be regenerated when needed
  108.42  
  108.43          log.info("Done: ", invoker);
  108.44 -        final MethodHandle restOf = restOfHandle(effectiveOptInfo, compiler.compile(fn, CompilationPhases.COMPILE_FROM_BYTECODE_RESTOF), canBeDeoptimized);
  108.45 +        final MethodHandle restOf = restOfHandle(effectiveOptInfo, compiler.compile(fn, CompilationPhases.GENERATE_BYTECODE_AND_INSTALL_RESTOF), canBeDeoptimized);
  108.46  
  108.47          // Note that we only adjust the switch point after we set the invoker/constructor. This is important.
  108.48          if (canBeDeoptimized) {
  108.49 @@ -921,6 +923,10 @@
  108.50          FunctionNode reparse() {
  108.51              return data.reparse();
  108.52          }
  108.53 +
  108.54 +        boolean isSerialized() {
  108.55 +            return data.isSerialized();
  108.56 +        }
  108.57      }
  108.58  
  108.59      @SuppressWarnings("unused")
   109.1 --- a/src/jdk/nashorn/internal/runtime/Context.java	Mon Oct 27 14:36:13 2014 -0700
   109.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java	Thu Nov 06 09:50:15 2014 -0800
   109.3 @@ -150,6 +150,13 @@
   109.4          private final Context      context;
   109.5          private final ScriptLoader loader;
   109.6          private final CodeSource   codeSource;
   109.7 +        private int usageCount = 0;
   109.8 +        private int bytesDefined = 0;
   109.9 +
  109.10 +        // We reuse this installer for 10 compilations or 200000 defined bytes. Usually the first condition
  109.11 +        // will occur much earlier, the second is a safety measure for very large scripts/functions.
  109.12 +        private final static int MAX_USAGES = 10;
  109.13 +        private final static int MAX_BYTES_DEFINED = 200_000;
  109.14  
  109.15          private ContextCodeInstaller(final Context context, final ScriptLoader loader, final CodeSource codeSource) {
  109.16              this.context    = context;
  109.17 @@ -168,6 +175,8 @@
  109.18  
  109.19          @Override
  109.20          public Class<?> install(final String className, final byte[] bytecode) {
  109.21 +            usageCount++;
  109.22 +            bytesDefined += bytecode.length;
  109.23              final String   binaryName = Compiler.binaryName(className);
  109.24              return loader.installClass(binaryName, bytecode, codeSource);
  109.25          }
  109.26 @@ -225,6 +234,10 @@
  109.27  
  109.28          @Override
  109.29          public CodeInstaller<ScriptEnvironment> withNewLoader() {
  109.30 +            // Reuse this installer if we're within our limits.
  109.31 +            if (usageCount < MAX_USAGES && bytesDefined < MAX_BYTES_DEFINED) {
  109.32 +                return this;
  109.33 +            }
  109.34              return new ContextCodeInstaller(context, context.createNewLoader(), codeSource);
  109.35          }
  109.36  
   110.1 --- a/src/jdk/nashorn/internal/runtime/ECMAException.java	Mon Oct 27 14:36:13 2014 -0700
   110.2 +++ b/src/jdk/nashorn/internal/runtime/ECMAException.java	Thu Nov 06 09:50:15 2014 -0800
   110.3 @@ -96,15 +96,17 @@
   110.4          // If thrown object is an Error or sub-object like TypeError, then
   110.5          // an ECMAException object has been already initialized at constructor.
   110.6          if (thrown instanceof ScriptObject) {
   110.7 -            final ScriptObject sobj = (ScriptObject)thrown;
   110.8 -            final Object exception = getException(sobj);
   110.9 +            final Object exception = getException((ScriptObject)thrown);
  110.10              if (exception instanceof ECMAException) {
  110.11 -                // copy over file name, line number and column number.
  110.12                  final ECMAException ee = (ECMAException)exception;
  110.13 -                ee.setFileName(fileName);
  110.14 -                ee.setLineNumber(line);
  110.15 -                ee.setColumnNumber(column);
  110.16 -                return ee;
  110.17 +                // Make sure exception has correct thrown reference because that's what will end up getting caught.
  110.18 +                if (ee.getThrown() == thrown) {
  110.19 +                    // copy over file name, line number and column number.
  110.20 +                    ee.setFileName(fileName);
  110.21 +                    ee.setLineNumber(line);
  110.22 +                    ee.setColumnNumber(column);
  110.23 +                    return ee;
  110.24 +                }
  110.25              }
  110.26          }
  110.27  
  110.28 @@ -154,7 +156,11 @@
  110.29       * @return a {@link ECMAException}
  110.30       */
  110.31      public static Object getException(final ScriptObject errObj) {
  110.32 -        return errObj.get(ECMAException.EXCEPTION_PROPERTY);
  110.33 +        // Exclude inherited properties that may belong to errors in the prototype chain.
  110.34 +        if (errObj.hasOwnProperty(ECMAException.EXCEPTION_PROPERTY)) {
  110.35 +            return errObj.get(ECMAException.EXCEPTION_PROPERTY);
  110.36 +        }
  110.37 +        return null;
  110.38      }
  110.39  
  110.40      /**
   111.1 --- a/src/jdk/nashorn/internal/runtime/FindProperty.java	Mon Oct 27 14:36:13 2014 -0700
   111.2 +++ b/src/jdk/nashorn/internal/runtime/FindProperty.java	Thu Nov 06 09:50:15 2014 -0800
   111.3 @@ -84,13 +84,18 @@
   111.4       * @return method handle for the getter
   111.5       */
   111.6      public MethodHandle getGetter(final Class<?> type, final int programPoint, final LinkRequest request) {
   111.7 -        final MethodHandle getter;
   111.8 +        MethodHandle getter;
   111.9          if (isValid(programPoint)) {
  111.10              getter = property.getOptimisticGetter(type, programPoint);
  111.11          } else {
  111.12              getter = property.getGetter(type);
  111.13          }
  111.14          if (property instanceof UserAccessorProperty) {
  111.15 +            getter = MH.insertArguments(getter, 1, UserAccessorProperty.getINVOKE_UA_GETTER(type, programPoint));
  111.16 +            if (isValid(programPoint) && type.isPrimitive()) {
  111.17 +                getter = MH.insertArguments(getter, 1, programPoint);
  111.18 +            }
  111.19 +            property.setType(type);
  111.20              return insertAccessorsGetter((UserAccessorProperty) property, request, getter);
  111.21          }
  111.22          return getter;
  111.23 @@ -111,7 +116,8 @@
  111.24      public MethodHandle getSetter(final Class<?> type, final boolean strict, final LinkRequest request) {
  111.25          MethodHandle setter = property.getSetter(type, getOwner().getMap());
  111.26          if (property instanceof UserAccessorProperty) {
  111.27 -            setter =  MH.insertArguments(setter, 1, strict ? property.getKey() : null);
  111.28 +            setter =  MH.insertArguments(setter, 1, UserAccessorProperty.getINVOKE_UA_SETTER(type), strict ? property.getKey() : null);
  111.29 +            property.setType(type);
  111.30              return insertAccessorsGetter((UserAccessorProperty) property, request, setter);
  111.31          }
  111.32  
   112.1 --- a/src/jdk/nashorn/internal/runtime/GlobalConstants.java	Mon Oct 27 14:36:13 2014 -0700
   112.2 +++ b/src/jdk/nashorn/internal/runtime/GlobalConstants.java	Thu Nov 06 09:50:15 2014 -0800
   112.3 @@ -31,7 +31,6 @@
   112.4  import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
   112.5  import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.getProgramPoint;
   112.6  import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
   112.7 -
   112.8  import java.lang.invoke.MethodHandle;
   112.9  import java.lang.invoke.MethodHandles;
  112.10  import java.lang.invoke.SwitchPoint;
  112.11 @@ -328,7 +327,9 @@
  112.12          }
  112.13  
  112.14          if (!acc.mayRetry()) {
  112.15 -            log.info("*** SET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation());
  112.16 +            if (log.isEnabled()) {
  112.17 +                log.fine("*** SET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation());
  112.18 +            }
  112.19              return null;
  112.20          }
  112.21  
  112.22 @@ -404,7 +405,9 @@
  112.23          }
  112.24  
  112.25          if (acc.hasBeenInvalidated() || acc.guardFailed()) {
  112.26 -            log.fine("*** GET: Giving up on " + quote(name) + " - retry count has exceeded");
  112.27 +            if (log.isEnabled()) {
  112.28 +                log.info("*** GET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation());
  112.29 +            }
  112.30              return null;
  112.31          }
  112.32  
   113.1 --- a/src/jdk/nashorn/internal/runtime/JSType.java	Mon Oct 27 14:36:13 2014 -0700
   113.2 +++ b/src/jdk/nashorn/internal/runtime/JSType.java	Thu Nov 06 09:50:15 2014 -0800
   113.3 @@ -29,7 +29,6 @@
   113.4  import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
   113.5  import static jdk.nashorn.internal.lookup.Lookup.MH;
   113.6  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
   113.7 -
   113.8  import java.lang.invoke.MethodHandle;
   113.9  import java.lang.invoke.MethodHandles;
  113.10  import java.lang.reflect.Array;
  113.11 @@ -115,6 +114,9 @@
  113.12      /** JavaScript compliant conversion function from double to int32 */
  113.13      public static final Call TO_INT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, double.class);
  113.14  
  113.15 +    /** JavaScript compliant conversion function from int to uint32 */
  113.16 +    public static final Call TO_UINT32_I = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, int.class);
  113.17 +
  113.18      /** JavaScript compliant conversion function from Object to uint32 */
  113.19      public static final Call TO_UINT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, Object.class);
  113.20  
  113.21 @@ -1002,6 +1004,16 @@
  113.22      }
  113.23  
  113.24      /**
  113.25 +     * JavaScript compliant int to uint32 conversion
  113.26 +     *
  113.27 +     * @param num an int
  113.28 +     * @return a uint32
  113.29 +     */
  113.30 +    public static long toUint32(final int num) {
  113.31 +        return num & MAX_UINT;
  113.32 +    }
  113.33 +
  113.34 +    /**
  113.35       * JavaScript compliant Object to uint16 conversion
  113.36       * ECMA 9.7 ToUint16: (Unsigned 16 Bit Integer)
  113.37       *
  113.38 @@ -1776,6 +1788,23 @@
  113.39      }
  113.40  
  113.41      /**
  113.42 +     * Returns the boxed version of a primitive class
  113.43 +     * @param clazz the class
  113.44 +     * @return the boxed type of clazz, or unchanged if not primitive
  113.45 +     */
  113.46 +    public static Class<?> getBoxedClass(final Class<?> clazz) {
  113.47 +        if (clazz == int.class) {
  113.48 +            return Integer.class;
  113.49 +        } else if (clazz == long.class) {
  113.50 +            return Long.class;
  113.51 +        } else if (clazz == double.class) {
  113.52 +            return Double.class;
  113.53 +        }
  113.54 +        assert !clazz.isPrimitive();
  113.55 +        return clazz;
  113.56 +    }
  113.57 +
  113.58 +    /**
  113.59       * Create a method handle constant of the correct primitive type
  113.60       * for a constant object
  113.61       * @param o object
   114.1 --- a/src/jdk/nashorn/internal/runtime/Property.java	Mon Oct 27 14:36:13 2014 -0700
   114.2 +++ b/src/jdk/nashorn/internal/runtime/Property.java	Thu Nov 06 09:50:15 2014 -0800
   114.3 @@ -102,6 +102,13 @@
   114.4      /** Property field number or spill slot. */
   114.5      private final int slot;
   114.6  
   114.7 +    /**
   114.8 +     * Current type of this object, in object only mode, this is an Object.class. In dual-fields mode
   114.9 +     * null means undefined, and primitive types are allowed. The reason a special type is used for
  114.10 +     * undefined, is that are no bits left to represent it in primitive types
  114.11 +     */
  114.12 +    private Class<?> type;
  114.13 +
  114.14      /** SwitchPoint that is invalidated when property is changed, optional */
  114.15      protected transient SwitchPoint builtinSwitchPoint;
  114.16  
  114.17 @@ -536,7 +543,7 @@
  114.18       * <p>
  114.19       * see {@link ObjectClassGenerator#createSetter(Class, Class, MethodHandle, MethodHandle)}
  114.20       * if you are interested in the internal details of this. Note that if you
  114.21 -     * are running in default mode, with {@code -Dnashorn.fields.dual=true}, disabled, the setters
  114.22 +     * are running with {@code -Dnashorn.fields.objects=true}, the setters
  114.23       * will currently never change, as all properties are represented as Object field,
  114.24       * the Object fields are Initialized to {@code ScriptRuntime.UNDEFINED} and primitives are
  114.25       * boxed/unboxed upon every access, which is not necessarily optimal
  114.26 @@ -569,7 +576,7 @@
  114.27  
  114.28      @Override
  114.29      public int hashCode() {
  114.30 -        final Class<?> type = getCurrentType();
  114.31 +        final Class<?> type = getLocalType();
  114.32          return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (type == null ? 0 : type.hashCode());
  114.33      }
  114.34  
  114.35 @@ -586,7 +593,7 @@
  114.36          final Property otherProperty = (Property)other;
  114.37  
  114.38          return equalsWithoutType(otherProperty) &&
  114.39 -               getCurrentType() == otherProperty.getCurrentType();
  114.40 +                getLocalType() == otherProperty.getLocalType();
  114.41      }
  114.42  
  114.43      boolean equalsWithoutType(final Property otherProperty) {
  114.44 @@ -615,7 +622,7 @@
  114.45       */
  114.46      public final String toStringShort() {
  114.47          final StringBuilder sb   = new StringBuilder();
  114.48 -        final Class<?>      type = getCurrentType();
  114.49 +        final Class<?>      type = getLocalType();
  114.50          sb.append(getKey()).append(" (").append(type(type)).append(')');
  114.51          return sb.toString();
  114.52      }
  114.53 @@ -632,7 +639,7 @@
  114.54      @Override
  114.55      public String toString() {
  114.56          final StringBuilder sb   = new StringBuilder();
  114.57 -        final Class<?>      type = getCurrentType();
  114.58 +        final Class<?>      type = getLocalType();
  114.59  
  114.60          sb.append(indent(getKey(), 20)).
  114.61              append(" id=").
  114.62 @@ -656,20 +663,40 @@
  114.63      }
  114.64  
  114.65      /**
  114.66 -     * Get the current type of this field. If you are not running with dual fields enabled,
  114.67 +     * Get the current type of this property. If you are running with object fields enabled,
  114.68       * this will always be Object.class. See the value representation explanation in
  114.69       * {@link Property#getSetter(Class, PropertyMap)} and {@link ObjectClassGenerator}
  114.70       * for more information.
  114.71       *
  114.72 +     * <p>Note that for user accessor properties, this returns the type of the last observed
  114.73 +     * value passed to or returned by a user accessor. Use {@link #getLocalType()} to always get
  114.74 +     * the type of the actual value stored in the property slot.</p>
  114.75 +     *
  114.76       * @return current type of property, null means undefined
  114.77       */
  114.78 -    public abstract Class<?> getCurrentType();
  114.79 +    public final Class<?> getType() {
  114.80 +        return type;
  114.81 +    }
  114.82  
  114.83      /**
  114.84 -     * Reset the current type of this property
  114.85 -     * @param currentType new current type
  114.86 +     * Set the type of this property.
  114.87 +     * @param type new type
  114.88       */
  114.89 -    public abstract void setCurrentType(final Class<?> currentType);
  114.90 +    public final void setType(final Class<?> type) {
  114.91 +        assert type != boolean.class : "no boolean storage support yet - fix this";
  114.92 +        this.type = type == null ? null : type.isPrimitive() ? type : Object.class;
  114.93 +    }
  114.94 +
  114.95 +    /**
  114.96 +     * Get the type of the value in the local property slot. This returns the same as
  114.97 +     * {@link #getType()} for normal properties, but always returns {@code Object.class}
  114.98 +     * for {@link UserAccessorProperty}s as their local type is a pair of accessor references.
  114.99 +     *
 114.100 +     * @return the local property type
 114.101 +     */
 114.102 +    protected Class<?> getLocalType() {
 114.103 +        return getType();
 114.104 +    }
 114.105  
 114.106      /**
 114.107       * Check whether this Property can ever change its type. The default is false, and if
   115.1 --- a/src/jdk/nashorn/internal/runtime/PropertyMap.java	Mon Oct 27 14:36:13 2014 -0700
   115.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java	Thu Nov 06 09:50:15 2014 -0800
   115.3 @@ -84,7 +84,7 @@
   115.4      private transient WeakHashMap<Property, SoftReference<PropertyMap>> history;
   115.5  
   115.6      /** History of prototypes, used to limit map duplication. */
   115.7 -    private transient WeakHashMap<PropertyMap, SoftReference<PropertyMap>> protoHistory;
   115.8 +    private transient WeakHashMap<ScriptObject, SoftReference<PropertyMap>> protoHistory;
   115.9  
  115.10      /** property listeners */
  115.11      private transient PropertyListeners listeners;
  115.12 @@ -512,7 +512,7 @@
  115.13          assert sameType ||
  115.14                  oldProperty instanceof AccessorProperty &&
  115.15                  newProperty instanceof UserAccessorProperty :
  115.16 -            "arbitrary replaceProperty attempted " + sameType + " oldProperty=" + oldProperty.getClass() + " newProperty=" + newProperty.getClass() + " [" + oldProperty.getCurrentType() + " => " + newProperty.getCurrentType() + "]";
  115.17 +            "arbitrary replaceProperty attempted " + sameType + " oldProperty=" + oldProperty.getClass() + " newProperty=" + newProperty.getClass() + " [" + oldProperty.getLocalType() + " => " + newProperty.getLocalType() + "]";
  115.18  
  115.19          newMap.flags = flags;
  115.20  
  115.21 @@ -677,14 +677,14 @@
  115.22      /**
  115.23       * Check prototype history for an existing property map with specified prototype.
  115.24       *
  115.25 -     * @param parentMap New prototype object.
  115.26 +     * @param proto New prototype object.
  115.27       *
  115.28       * @return Existing {@link PropertyMap} or {@code null} if not found.
  115.29       */
  115.30 -    private PropertyMap checkProtoHistory(final PropertyMap parentMap) {
  115.31 +    private PropertyMap checkProtoHistory(final ScriptObject proto) {
  115.32          final PropertyMap cachedMap;
  115.33          if (protoHistory != null) {
  115.34 -            final SoftReference<PropertyMap> weakMap = protoHistory.get(parentMap);
  115.35 +            final SoftReference<PropertyMap> weakMap = protoHistory.get(proto);
  115.36              cachedMap = (weakMap != null ? weakMap.get() : null);
  115.37          } else {
  115.38              cachedMap = null;
  115.39 @@ -700,15 +700,15 @@
  115.40      /**
  115.41       * Add a map to the prototype history.
  115.42       *
  115.43 -     * @param parentMap Prototype to add (key.)
  115.44 +     * @param newProto Prototype to add (key.)
  115.45       * @param newMap   {@link PropertyMap} associated with prototype.
  115.46       */
  115.47 -    private void addToProtoHistory(final PropertyMap parentMap, final PropertyMap newMap) {
  115.48 +    private void addToProtoHistory(final ScriptObject newProto, final PropertyMap newMap) {
  115.49          if (protoHistory == null) {
  115.50              protoHistory = new WeakHashMap<>();
  115.51          }
  115.52  
  115.53 -        protoHistory.put(parentMap, new SoftReference<>(newMap));
  115.54 +        protoHistory.put(newProto, new SoftReference<>(newMap));
  115.55      }
  115.56  
  115.57      /**
  115.58 @@ -883,8 +883,7 @@
  115.59       */
  115.60      public PropertyMap changeProto(final ScriptObject newProto) {
  115.61  
  115.62 -        final PropertyMap parentMap = newProto == null ? null : newProto.getMap();
  115.63 -        final PropertyMap nextMap = checkProtoHistory(parentMap);
  115.64 +        final PropertyMap nextMap = checkProtoHistory(newProto);
  115.65          if (nextMap != null) {
  115.66              return nextMap;
  115.67          }
  115.68 @@ -894,7 +893,7 @@
  115.69          }
  115.70  
  115.71          final PropertyMap newMap = new PropertyMap(this);
  115.72 -        addToProtoHistory(parentMap, newMap);
  115.73 +        addToProtoHistory(newProto, newMap);
  115.74  
  115.75          return newMap;
  115.76      }
   116.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Mon Oct 27 14:36:13 2014 -0700
   116.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Thu Nov 06 09:50:15 2014 -0800
   116.3 @@ -43,6 +43,7 @@
   116.4  import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
   116.5  import jdk.nashorn.internal.codegen.CompilerConstants;
   116.6  import jdk.nashorn.internal.codegen.FunctionSignature;
   116.7 +import jdk.nashorn.internal.codegen.Namespace;
   116.8  import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor;
   116.9  import jdk.nashorn.internal.codegen.OptimisticTypesPersistence;
  116.10  import jdk.nashorn.internal.codegen.TypeMap;
  116.11 @@ -79,6 +80,9 @@
  116.12      /** Source from which FunctionNode was parsed. */
  116.13      private transient Source source;
  116.14  
  116.15 +    /** Serialized, compressed form of the AST. Used by split functions as they can't be reparsed from source. */
  116.16 +    private final byte[] serializedAst;
  116.17 +
  116.18      /** Token of this function within the source. */
  116.19      private final long token;
  116.20  
  116.21 @@ -127,6 +131,7 @@
  116.22       * @param nestedFunctions     nested function map
  116.23       * @param externalScopeDepths external scope depths
  116.24       * @param internalSymbols     internal symbols to method, defined in its scope
  116.25 +     * @param serializedAst       a serialized AST representation. Normally only used for split functions.
  116.26       */
  116.27      public RecompilableScriptFunctionData(
  116.28          final FunctionNode functionNode,
  116.29 @@ -134,7 +139,8 @@
  116.30          final AllocatorDescriptor allocationDescriptor,
  116.31          final Map<Integer, RecompilableScriptFunctionData> nestedFunctions,
  116.32          final Map<String, Integer> externalScopeDepths,
  116.33 -        final Set<String> internalSymbols) {
  116.34 +        final Set<String> internalSymbols,
  116.35 +        final byte[] serializedAst) {
  116.36  
  116.37          super(functionName(functionNode),
  116.38                Math.min(functionNode.getParameters().size(), MAX_ARITY),
  116.39 @@ -158,6 +164,7 @@
  116.40              nfn.setParent(this);
  116.41          }
  116.42  
  116.43 +        this.serializedAst = serializedAst;
  116.44          createLogger();
  116.45      }
  116.46  
  116.47 @@ -212,10 +219,7 @@
  116.48       */
  116.49      public int getExternalSymbolDepth(final String symbolName) {
  116.50          final Integer depth = externalScopeDepths.get(symbolName);
  116.51 -        if (depth == null) {
  116.52 -            return -1;
  116.53 -        }
  116.54 -        return depth;
  116.55 +        return depth == null ? -1 : depth;
  116.56      }
  116.57  
  116.58      /**
  116.59 @@ -354,8 +358,15 @@
  116.60          return allocationStrategy.allocate(map);
  116.61      }
  116.62  
  116.63 +    boolean isSerialized() {
  116.64 +        return serializedAst != null;
  116.65 +    }
  116.66 +
  116.67      FunctionNode reparse() {
  116.68 -        // NOTE: If we aren't recompiling the top-level program, we decrease functionNodeId 'cause we'll have a synthetic program node
  116.69 +        if (isSerialized()) {
  116.70 +            return deserialize();
  116.71 +        }
  116.72 +
  116.73          final int descPosition = Token.descPosition(token);
  116.74          final Context context = Context.getContextTrusted();
  116.75          final Parser parser = new Parser(
  116.76 @@ -363,8 +374,10 @@
  116.77              source,
  116.78              new Context.ThrowErrorManager(),
  116.79              isStrict(),
  116.80 +            // source starts at line 0, so even though lineNumber is the correct declaration line, back off
  116.81 +            // one to make it exclusive
  116.82              lineNumber - 1,
  116.83 -            context.getLogger(Parser.class)); // source starts at line 0, so even though lineNumber is the correct declaration line, back off one to make it exclusive
  116.84 +            context.getLogger(Parser.class));
  116.85  
  116.86          if (getFunctionFlag(FunctionNode.IS_ANONYMOUS)) {
  116.87              parser.setFunctionName(functionName);
  116.88 @@ -378,6 +391,17 @@
  116.89          return (isProgram() ? program : extractFunctionFromScript(program)).setName(null, functionName);
  116.90      }
  116.91  
  116.92 +    private FunctionNode deserialize() {
  116.93 +        final ScriptEnvironment env = installer.getOwner();
  116.94 +        final Timing timing = env._timing;
  116.95 +        final long t1 = System.nanoTime();
  116.96 +        try {
  116.97 +            return AstDeserializer.deserialize(serializedAst).initializeDeserialized(source, new Namespace(env.getNamespace()));
  116.98 +        } finally {
  116.99 +            timing.accumulateTime("'Deserialize'", System.nanoTime() - t1);
 116.100 +        }
 116.101 +    }
 116.102 +
 116.103      private boolean getFunctionFlag(final int flag) {
 116.104          return (functionFlags & flag) != 0;
 116.105      }
 116.106 @@ -486,7 +510,8 @@
 116.107  
 116.108          final FunctionNode fn = reparse();
 116.109          final Compiler compiler = getCompiler(fn, actualCallSiteType, runtimeScope);
 116.110 -        final FunctionNode compiledFn = compiler.compile(fn, CompilationPhases.COMPILE_ALL);
 116.111 +        final FunctionNode compiledFn = compiler.compile(fn,
 116.112 +                isSerialized() ? CompilationPhases.COMPILE_ALL_SERIALIZED : CompilationPhases.COMPILE_ALL);
 116.113  
 116.114          if (persist && !compiledFn.getFlag(FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION)) {
 116.115              compiler.persistClassInfo(cacheKey, compiledFn);
 116.116 @@ -606,7 +631,7 @@
 116.117  
 116.118      MethodHandle lookupCodeMethod(final Class<?> codeClass, final MethodType targetType) {
 116.119          if (log.isEnabled()) {
 116.120 -            log.info("Looking up ", DebugLogger.quote(name), " type=", targetType);
 116.121 +            log.info("Looking up ", DebugLogger.quote(functionName), " type=", targetType);
 116.122          }
 116.123          return MH.findStatic(LOOKUP, codeClass, functionName, targetType);
 116.124      }
 116.125 @@ -676,6 +701,22 @@
 116.126          return addCode(lookup(fnInit).asType(toType), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags());
 116.127      }
 116.128  
 116.129 +    /**
 116.130 +     * Returns the return type of a function specialization for particular parameter types.<br>
 116.131 +     * <b>Be aware that the way this is implemented, it forces full materialization (compilation and installation) of
 116.132 +     * code for that specialization.</b>
 116.133 +     * @param callSiteType the parameter types at the call site. It must include the mandatory {@code callee} and
 116.134 +     * {@code this} parameters, so it needs to start with at least {@code ScriptFunction.class} and
 116.135 +     * {@code Object.class} class. Since the return type of the function is calculated from the code itself, it is
 116.136 +     * irrelevant and should be set to {@code Object.class}.
 116.137 +     * @param runtimeScope a current runtime scope. Can be null but when it's present it will be used as a source of
 116.138 +     * current runtime values that can improve the compiler's type speculations (and thus reduce the need for later
 116.139 +     * recompilations) if the specialization is not already present and thus needs to be freshly compiled.
 116.140 +     * @return the return type of the function specialization.
 116.141 +     */
 116.142 +    public Class<?> getReturnType(final MethodType callSiteType, final ScriptObject runtimeScope) {
 116.143 +        return getBest(callSiteType, runtimeScope, CompiledFunction.NO_FUNCTIONS).type().returnType();
 116.144 +    }
 116.145  
 116.146      @Override
 116.147      synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
 116.148 @@ -801,6 +842,26 @@
 116.149          return true;
 116.150      }
 116.151  
 116.152 +    /**
 116.153 +     * Restores the {@link #getFunctionFlags()} flags to a function node. During on-demand compilation, we might need
 116.154 +     * to restore flags to a function node that was otherwise not subjected to a full compile pipeline (e.g. its parse
 116.155 +     * was skipped, or it's a nested function of a deserialized function.
 116.156 +     * @param lc current lexical context
 116.157 +     * @param fn the function node to restore flags onto
 116.158 +     * @return the transformed function node
 116.159 +     */
 116.160 +    public FunctionNode restoreFlags(final LexicalContext lc, final FunctionNode fn) {
 116.161 +        assert fn.getId() == functionNodeId;
 116.162 +        FunctionNode newFn = fn.setFlags(lc, functionFlags);
 116.163 +        // This compensates for missing markEval() in case the function contains an inner function
 116.164 +        // that contains eval(), that now we didn't discover since we skipped the inner function.
 116.165 +        if (newFn.hasNestedEval()) {
 116.166 +            assert newFn.hasScopeBlock();
 116.167 +            newFn = newFn.setBody(lc, newFn.getBody().setNeedsScope(null));
 116.168 +        }
 116.169 +        return newFn;
 116.170 +    }
 116.171 +
 116.172      private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
 116.173          in.defaultReadObject();
 116.174          createLogger();
   117.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Oct 27 14:36:13 2014 -0700
   117.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Thu Nov 06 09:50:15 2014 -0800
   117.3 @@ -692,8 +692,7 @@
   117.4          assert isValidArrayIndex(index) : "invalid array index";
   117.5          final long longIndex = ArrayIndex.toLongIndex(index);
   117.6          doesNotHaveEnsureDelete(longIndex, getArray().length(), false);
   117.7 -        setArray(getArray().ensure(longIndex));
   117.8 -        setArray(getArray().set(index, value, false));
   117.9 +        setArray(getArray().ensure(longIndex).set(index,value, false));
  117.10      }
  117.11  
  117.12      private void checkIntegerKey(final String key) {
  117.13 @@ -970,7 +969,7 @@
  117.14              final UserAccessorProperty uc = (UserAccessorProperty)oldProperty;
  117.15              final int slot = uc.getSlot();
  117.16  
  117.17 -            assert uc.getCurrentType() == Object.class;
  117.18 +            assert uc.getLocalType() == Object.class;
  117.19              if (slot >= spillLength) {
  117.20                  uc.setAccessors(this, getMap(), new UserAccessorProperty.Accessors(getter, setter));
  117.21              } else {
  117.22 @@ -1462,9 +1461,8 @@
  117.23  
  117.24          //invalidate any fast array setters
  117.25          final ArrayData array = getArray();
  117.26 -        if (array != null) {
  117.27 -            array.invalidateSetters();
  117.28 -        }
  117.29 +        assert array != null;
  117.30 +        setArray(ArrayData.preventExtension(array));
  117.31          return this;
  117.32      }
  117.33  
  117.34 @@ -2645,20 +2643,22 @@
  117.35        * @param newLength new length to set
  117.36        */
  117.37      public final void setLength(final long newLength) {
  117.38 -       final long arrayLength = getArray().length();
  117.39 -       if (newLength == arrayLength) {
  117.40 -           return;
  117.41 -       }
  117.42 -
  117.43 -       if (newLength > arrayLength) {
  117.44 -           setArray(getArray().ensure(newLength - 1));
  117.45 -            if (getArray().canDelete(arrayLength, newLength - 1, false)) {
  117.46 -               setArray(getArray().delete(arrayLength, newLength - 1));
  117.47 -           }
  117.48 -           return;
  117.49 -       }
  117.50 -
  117.51 -       if (newLength < arrayLength) {
  117.52 +        ArrayData data = getArray();
  117.53 +        final long arrayLength = data.length();
  117.54 +        if (newLength == arrayLength) {
  117.55 +            return;
  117.56 +        }
  117.57 +
  117.58 +        if (newLength > arrayLength) {
  117.59 +            data = data.ensure(newLength - 1);
  117.60 +            if (data.canDelete(arrayLength, newLength - 1, false)) {
  117.61 +               data = data.delete(arrayLength, newLength - 1);
  117.62 +            }
  117.63 +            setArray(data);
  117.64 +            return;
  117.65 +        }
  117.66 +
  117.67 +        if (newLength < arrayLength) {
  117.68             long actualLength = newLength;
  117.69  
  117.70             // Check for numeric keys in property map and delete them or adjust length, depending on whether
  117.71 @@ -2680,8 +2680,8 @@
  117.72                 }
  117.73             }
  117.74  
  117.75 -           setArray(getArray().shrink(actualLength));
  117.76 -           getArray().setLength(actualLength);
  117.77 +           setArray(data.shrink(actualLength));
  117.78 +           data.setLength(actualLength);
  117.79         }
  117.80      }
  117.81  
  117.82 @@ -3194,8 +3194,9 @@
  117.83          final int    index        = getArrayIndex(primitiveKey);
  117.84  
  117.85          if (isValidArrayIndex(index)) {
  117.86 -            if (getArray().has(index)) {
  117.87 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
  117.88 +            final ArrayData data = getArray();
  117.89 +            if (data.has(index)) {
  117.90 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
  117.91              } else {
  117.92                  doesNotHave(index, value, callSiteFlags);
  117.93              }
  117.94 @@ -3213,8 +3214,9 @@
  117.95          final int    index        = getArrayIndex(primitiveKey);
  117.96  
  117.97          if (isValidArrayIndex(index)) {
  117.98 -            if (getArray().has(index)) {
  117.99 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.100 +            final ArrayData data = getArray();
 117.101 +            if (data.has(index)) {
 117.102 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.103              } else {
 117.104                  doesNotHave(index, value, callSiteFlags);
 117.105              }
 117.106 @@ -3232,8 +3234,9 @@
 117.107          final int    index        = getArrayIndex(primitiveKey);
 117.108  
 117.109          if (isValidArrayIndex(index)) {
 117.110 -            if (getArray().has(index)) {
 117.111 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.112 +            final ArrayData data = getArray();
 117.113 +            if (data.has(index)) {
 117.114 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.115              } else {
 117.116                  doesNotHave(index, value, callSiteFlags);
 117.117              }
 117.118 @@ -3251,8 +3254,9 @@
 117.119          final int    index        = getArrayIndex(primitiveKey);
 117.120  
 117.121          if (isValidArrayIndex(index)) {
 117.122 -            if (getArray().has(index)) {
 117.123 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.124 +            final ArrayData data = getArray();
 117.125 +            if (data.has(index)) {
 117.126 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.127              } else {
 117.128                  doesNotHave(index, value, callSiteFlags);
 117.129              }
 117.130 @@ -3269,8 +3273,9 @@
 117.131          final int index = getArrayIndex(key);
 117.132  
 117.133          if (isValidArrayIndex(index)) {
 117.134 -            if (getArray().has(index)) {
 117.135 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.136 +            final ArrayData data = getArray();
 117.137 +            if (data.has(index)) {
 117.138 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.139              } else {
 117.140                  doesNotHave(index, value, callSiteFlags);
 117.141              }
 117.142 @@ -3287,8 +3292,9 @@
 117.143          final int index = getArrayIndex(key);
 117.144  
 117.145          if (isValidArrayIndex(index)) {
 117.146 -            if (getArray().has(index)) {
 117.147 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.148 +            final ArrayData data = getArray();
 117.149 +            if (data.has(index)) {
 117.150 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.151              } else {
 117.152                  doesNotHave(index, value, callSiteFlags);
 117.153              }
 117.154 @@ -3305,8 +3311,9 @@
 117.155          final int index = getArrayIndex(key);
 117.156  
 117.157          if (isValidArrayIndex(index)) {
 117.158 -            if (getArray().has(index)) {
 117.159 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.160 +            final ArrayData data = getArray();
 117.161 +            if (data.has(index)) {
 117.162 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.163              } else {
 117.164                  doesNotHave(index, value, callSiteFlags);
 117.165              }
 117.166 @@ -3323,8 +3330,9 @@
 117.167          final int index = getArrayIndex(key);
 117.168  
 117.169          if (isValidArrayIndex(index)) {
 117.170 -            if (getArray().has(index)) {
 117.171 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.172 +            final ArrayData data = getArray();
 117.173 +            if (data.has(index)) {
 117.174 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.175              } else {
 117.176                  doesNotHave(index, value, callSiteFlags);
 117.177              }
 117.178 @@ -3341,8 +3349,9 @@
 117.179          final int index = getArrayIndex(key);
 117.180  
 117.181          if (isValidArrayIndex(index)) {
 117.182 -            if (getArray().has(index)) {
 117.183 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.184 +            final ArrayData data = getArray();
 117.185 +            if (data.has(index)) {
 117.186 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.187              } else {
 117.188                  doesNotHave(index, value, callSiteFlags);
 117.189              }
 117.190 @@ -3359,8 +3368,9 @@
 117.191          final int index = getArrayIndex(key);
 117.192  
 117.193          if (isValidArrayIndex(index)) {
 117.194 -            if (getArray().has(index)) {
 117.195 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.196 +            final ArrayData data = getArray();
 117.197 +            if (data.has(index)) {
 117.198 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.199              } else {
 117.200                  doesNotHave(index, value, callSiteFlags);
 117.201              }
 117.202 @@ -3377,8 +3387,9 @@
 117.203          final int index = getArrayIndex(key);
 117.204  
 117.205          if (isValidArrayIndex(index)) {
 117.206 -            if (getArray().has(index)) {
 117.207 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.208 +            final ArrayData data = getArray();
 117.209 +            if (data.has(index)) {
 117.210 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.211              } else {
 117.212                  doesNotHave(index, value, callSiteFlags);
 117.213              }
 117.214 @@ -3395,8 +3406,9 @@
 117.215          final int index = getArrayIndex(key);
 117.216  
 117.217          if (isValidArrayIndex(index)) {
 117.218 -            if (getArray().has(index)) {
 117.219 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.220 +            final ArrayData data = getArray();
 117.221 +            if (data.has(index)) {
 117.222 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.223              } else {
 117.224                  doesNotHave(index, value, callSiteFlags);
 117.225              }
 117.226 @@ -3413,7 +3425,8 @@
 117.227          final int index = getArrayIndex(key);
 117.228          if (isValidArrayIndex(index)) {
 117.229              if (getArray().has(index)) {
 117.230 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.231 +                final ArrayData data = getArray();
 117.232 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.233              } else {
 117.234                  doesNotHave(index, value, callSiteFlags);
 117.235              }
 117.236 @@ -3429,8 +3442,9 @@
 117.237          final int index = getArrayIndex(key);
 117.238  
 117.239          if (isValidArrayIndex(index)) {
 117.240 -            if (getArray().has(index)) {
 117.241 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.242 +            final ArrayData data = getArray();
 117.243 +            if (data.has(index)) {
 117.244 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.245              } else {
 117.246                  doesNotHave(index, value, callSiteFlags);
 117.247              }
 117.248 @@ -3447,8 +3461,9 @@
 117.249          final int index = getArrayIndex(key);
 117.250  
 117.251          if (isValidArrayIndex(index)) {
 117.252 -            if (getArray().has(index)) {
 117.253 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.254 +            final ArrayData data = getArray();
 117.255 +            if (data.has(index)) {
 117.256 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.257              } else {
 117.258                  doesNotHave(index, value, callSiteFlags);
 117.259              }
 117.260 @@ -3465,8 +3480,9 @@
 117.261          final int index = getArrayIndex(key);
 117.262  
 117.263          if (isValidArrayIndex(index)) {
 117.264 -            if (getArray().has(index)) {
 117.265 -                setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.266 +            final ArrayData data = getArray();
 117.267 +            if (data.has(index)) {
 117.268 +                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
 117.269              } else {
 117.270                  doesNotHave(index, value, callSiteFlags);
 117.271              }
   118.1 --- a/src/jdk/nashorn/internal/runtime/SpillProperty.java	Mon Oct 27 14:36:13 2014 -0700
   118.2 +++ b/src/jdk/nashorn/internal/runtime/SpillProperty.java	Thu Nov 06 09:50:15 2014 -0800
   118.3 @@ -161,12 +161,12 @@
   118.4       */
   118.5      public SpillProperty(final String key, final int flags, final int slot) {
   118.6          super(key, flags, slot, primitiveGetter(slot), primitiveSetter(slot), objectGetter(slot), objectSetter(slot));
   118.7 -        assert !OBJECT_FIELDS_ONLY || getCurrentType() == Object.class;
   118.8 +        assert !OBJECT_FIELDS_ONLY || getLocalType() == Object.class;
   118.9      }
  118.10  
  118.11      SpillProperty(final String key, final int flags, final int slot, final Class<?> initialType) {
  118.12          this(key, flags, slot);
  118.13 -        setCurrentType(OBJECT_FIELDS_ONLY ? Object.class : initialType);
  118.14 +        setType(OBJECT_FIELDS_ONLY ? Object.class : initialType);
  118.15      }
  118.16  
  118.17      SpillProperty(final String key, final int flags, final int slot, final ScriptObject owner, final Object initialValue) {
   119.1 --- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Mon Oct 27 14:36:13 2014 -0700
   119.2 +++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Thu Nov 06 09:50:15 2014 -0800
   119.3 @@ -27,16 +27,16 @@
   119.4  
   119.5  import static jdk.nashorn.internal.lookup.Lookup.MH;
   119.6  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
   119.7 -import static jdk.nashorn.internal.runtime.JSType.CONVERT_OBJECT_OPTIMISTIC;
   119.8 -import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
   119.9  import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  119.10 +import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
  119.11 +import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
  119.12  
  119.13  import java.lang.invoke.MethodHandle;
  119.14  import java.lang.invoke.MethodHandles;
  119.15  import java.lang.invoke.MethodType;
  119.16 -import java.util.concurrent.Callable;
  119.17  import jdk.nashorn.internal.lookup.Lookup;
  119.18  import jdk.nashorn.internal.runtime.linker.Bootstrap;
  119.19 +import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
  119.20  
  119.21  /**
  119.22   * Property with user defined getters/setters. Actual getter and setter
  119.23 @@ -69,38 +69,29 @@
  119.24      private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
  119.25  
  119.26      /** Getter method handle */
  119.27 -    private final static MethodHandle INVOKE_GETTER_ACCESSOR = findOwnMH_S("invokeGetterAccessor", Object.class, Accessors.class, Object.class);
  119.28 +    private final static MethodHandle INVOKE_OBJECT_GETTER = findOwnMH_S("invokeObjectGetter", Object.class, Accessors.class, MethodHandle.class, Object.class);
  119.29 +    private final static MethodHandle INVOKE_INT_GETTER  = findOwnMH_S("invokeIntGetter", int.class, Accessors.class, MethodHandle.class, int.class, Object.class);
  119.30 +    private final static MethodHandle INVOKE_LONG_GETTER  = findOwnMH_S("invokeLongGetter", long.class, Accessors.class, MethodHandle.class, int.class, Object.class);
  119.31 +    private final static MethodHandle INVOKE_NUMBER_GETTER  = findOwnMH_S("invokeNumberGetter", double.class, Accessors.class, MethodHandle.class, int.class, Object.class);
  119.32  
  119.33      /** Setter method handle */
  119.34 -    private final static MethodHandle INVOKE_SETTER_ACCESSOR = findOwnMH_S("invokeSetterAccessor", void.class, Accessors.class, String.class, Object.class, Object.class);
  119.35 +    private final static MethodHandle INVOKE_OBJECT_SETTER = findOwnMH_S("invokeObjectSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, Object.class);
  119.36 +    private final static MethodHandle INVOKE_INT_SETTER = findOwnMH_S("invokeIntSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, int.class);
  119.37 +    private final static MethodHandle INVOKE_LONG_SETTER = findOwnMH_S("invokeLongSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, long.class);
  119.38 +    private final static MethodHandle INVOKE_NUMBER_SETTER = findOwnMH_S("invokeNumberSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, double.class);
  119.39  
  119.40 -    /** Dynamic invoker for getter */
  119.41 -    private static final Object GETTER_INVOKER_KEY = new Object();
  119.42  
  119.43 -    private static MethodHandle getINVOKE_UA_GETTER() {
  119.44 -
  119.45 -        return Context.getGlobal().getDynamicInvoker(GETTER_INVOKER_KEY,
  119.46 -                new Callable<MethodHandle>() {
  119.47 -                    @Override
  119.48 -                    public MethodHandle call() {
  119.49 -                        return Bootstrap.createDynamicInvoker("dyn:call", Object.class,
  119.50 -                            Object.class, Object.class);
  119.51 -                    }
  119.52 -                });
  119.53 +    static MethodHandle getINVOKE_UA_GETTER(final Class<?> returnType, final int programPoint) {
  119.54 +        if (UnwarrantedOptimismException.isValid(programPoint)) {
  119.55 +            final int flags = NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC | programPoint << CALLSITE_PROGRAM_POINT_SHIFT;
  119.56 +            return Bootstrap.createDynamicInvoker("dyn:call", flags, returnType, Object.class, Object.class);
  119.57 +        } else {
  119.58 +            return Bootstrap.createDynamicInvoker("dyn:call", Object.class, Object.class, Object.class);
  119.59 +        }
  119.60      }
  119.61  
  119.62 -    /** Dynamic invoker for setter */
  119.63 -    private static Object SETTER_INVOKER_KEY = new Object();
  119.64 -
  119.65 -    private static MethodHandle getINVOKE_UA_SETTER() {
  119.66 -        return Context.getGlobal().getDynamicInvoker(SETTER_INVOKER_KEY,
  119.67 -                new Callable<MethodHandle>() {
  119.68 -                    @Override
  119.69 -                    public MethodHandle call() {
  119.70 -                        return Bootstrap.createDynamicInvoker("dyn:call", void.class,
  119.71 -                            Object.class, Object.class, Object.class);
  119.72 -                    }
  119.73 -                });
  119.74 +    static MethodHandle getINVOKE_UA_SETTER(final Class<?> valueType) {
  119.75 +        return Bootstrap.createDynamicInvoker("dyn:call", void.class, Object.class, Object.class, valueType);
  119.76      }
  119.77  
  119.78      /**
  119.79 @@ -158,7 +149,7 @@
  119.80      }
  119.81  
  119.82      @Override
  119.83 -    public Class<?> getCurrentType() {
  119.84 +    protected Class<?> getLocalType() {
  119.85          return Object.class;
  119.86      }
  119.87  
  119.88 @@ -189,7 +180,13 @@
  119.89  
  119.90      @Override
  119.91      public Object getObjectValue(final ScriptObject self, final ScriptObject owner) {
  119.92 -        return invokeGetterAccessor(getAccessors((owner != null) ? owner : self), self);
  119.93 +        try {
  119.94 +            return invokeObjectGetter(getAccessors((owner != null) ? owner : self), getINVOKE_UA_GETTER(Object.class, INVALID_PROGRAM_POINT), self);
  119.95 +        } catch (final Error | RuntimeException t) {
  119.96 +            throw t;
  119.97 +        } catch (final Throwable t) {
  119.98 +            throw new RuntimeException(t);
  119.99 +        }
 119.100      }
 119.101  
 119.102      @Override
 119.103 @@ -209,41 +206,33 @@
 119.104  
 119.105      @Override
 119.106      public void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) {
 119.107 -        invokeSetterAccessor(getAccessors((owner != null) ? owner : self), strict ? getKey() : null, self, value);
 119.108 +        try {
 119.109 +            invokeObjectSetter(getAccessors((owner != null) ? owner : self), getINVOKE_UA_SETTER(Object.class), strict ? getKey() : null, self, value);
 119.110 +        } catch (final Error | RuntimeException t) {
 119.111 +            throw t;
 119.112 +        } catch (final Throwable t) {
 119.113 +            throw new RuntimeException(t);
 119.114 +        }
 119.115      }
 119.116  
 119.117      @Override
 119.118      public MethodHandle getGetter(final Class<?> type) {
 119.119          //this returns a getter on the format (Accessors, Object receiver)
 119.120 -        return Lookup.filterReturnType(INVOKE_GETTER_ACCESSOR, type);
 119.121 +        return Lookup.filterReturnType(INVOKE_OBJECT_GETTER, type);
 119.122      }
 119.123  
 119.124      @Override
 119.125      public MethodHandle getOptimisticGetter(final Class<?> type, final int programPoint) {
 119.126 -        //fortype is always object, but in the optimistic world we have to throw
 119.127 -        //unwarranted optimism exception for narrower types. We can improve this
 119.128 -        //by checking for boxed types and unboxing them, but it is doubtful that
 119.129 -        //this gives us any performance, as UserAccessorProperties are typically not
 119.130 -        //primitives. Are there? TODO: investigate later. For now we just throw an
 119.131 -        //exception for narrower types than object
 119.132 -
 119.133 -        if (type.isPrimitive()) {
 119.134 -            final MethodHandle getter = getGetter(Object.class);
 119.135 -            final MethodHandle mh =
 119.136 -                    MH.asType(
 119.137 -                            MH.filterReturnValue(
 119.138 -                                    getter,
 119.139 -                                    MH.insertArguments(
 119.140 -                                            CONVERT_OBJECT_OPTIMISTIC.get(getAccessorTypeIndex(type)),
 119.141 -                                            1,
 119.142 -                                            programPoint)),
 119.143 -                                    getter.type().changeReturnType(type));
 119.144 -
 119.145 -            return mh;
 119.146 +        if (type == int.class) {
 119.147 +            return INVOKE_INT_GETTER;
 119.148 +        } else if (type == long.class) {
 119.149 +            return INVOKE_LONG_GETTER;
 119.150 +        } else if (type == double.class) {
 119.151 +            return INVOKE_NUMBER_GETTER;
 119.152 +        } else {
 119.153 +            assert type == Object.class;
 119.154 +            return INVOKE_OBJECT_GETTER;
 119.155          }
 119.156 -
 119.157 -        assert type == Object.class;
 119.158 -        return getGetter(type);
 119.159      }
 119.160  
 119.161      @Override
 119.162 @@ -259,7 +248,16 @@
 119.163  
 119.164      @Override
 119.165      public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) {
 119.166 -        return INVOKE_SETTER_ACCESSOR;
 119.167 +        if (type == int.class) {
 119.168 +            return INVOKE_INT_SETTER;
 119.169 +        } else if (type == long.class) {
 119.170 +            return INVOKE_LONG_SETTER;
 119.171 +        } else if (type == double.class) {
 119.172 +            return INVOKE_NUMBER_SETTER;
 119.173 +        } else {
 119.174 +            assert type == Object.class;
 119.175 +            return INVOKE_OBJECT_SETTER;
 119.176 +        }
 119.177      }
 119.178  
 119.179      @Override
 119.180 @@ -282,31 +280,81 @@
 119.181      // getter/setter may be inherited. If so, proto is bound during lookup. In either
 119.182      // inherited or self case, slot is also bound during lookup. Actual ScriptFunction
 119.183      // to be called is retrieved everytime and applied.
 119.184 -    private static Object invokeGetterAccessor(final Accessors gs, final Object self) {
 119.185 +    @SuppressWarnings("unused")
 119.186 +    private static Object invokeObjectGetter(final Accessors gs, final MethodHandle invoker, final Object self) throws Throwable {
 119.187          final Object func = gs.getter;
 119.188          if (func instanceof ScriptFunction) {
 119.189 -            try {
 119.190 -                return getINVOKE_UA_GETTER().invokeExact(func, self);
 119.191 -            } catch (final Error | RuntimeException t) {
 119.192 -                throw t;
 119.193 -            } catch (final Throwable t) {
 119.194 -                throw new RuntimeException(t);
 119.195 -            }
 119.196 +            return invoker.invokeExact(func, self);
 119.197          }
 119.198  
 119.199          return UNDEFINED;
 119.200      }
 119.201  
 119.202 -    private static void invokeSetterAccessor(final Accessors gs, final String name, final Object self, final Object value) {
 119.203 +    @SuppressWarnings("unused")
 119.204 +    private static int invokeIntGetter(final Accessors gs, final MethodHandle invoker, final int programPoint, final Object self) throws Throwable {
 119.205 +        final Object func = gs.getter;
 119.206 +        if (func instanceof ScriptFunction) {
 119.207 +            return (int) invoker.invokeExact(func, self);
 119.208 +        }
 119.209 +
 119.210 +        throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
 119.211 +    }
 119.212 +
 119.213 +    @SuppressWarnings("unused")
 119.214 +    private static long invokeLongGetter(final Accessors gs, final MethodHandle invoker, final int programPoint, final Object self) throws Throwable {
 119.215 +        final Object func = gs.getter;
 119.216 +        if (func instanceof ScriptFunction) {
 119.217 +            return (long) invoker.invokeExact(func, self);
 119.218 +        }
 119.219 +
 119.220 +        throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
 119.221 +    }
 119.222 +
 119.223 +    @SuppressWarnings("unused")
 119.224 +    private static double invokeNumberGetter(final Accessors gs, final MethodHandle invoker, final int programPoint, final Object self) throws Throwable {
 119.225 +        final Object func = gs.getter;
 119.226 +        if (func instanceof ScriptFunction) {
 119.227 +            return (double) invoker.invokeExact(func, self);
 119.228 +        }
 119.229 +
 119.230 +        throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
 119.231 +    }
 119.232 +
 119.233 +    @SuppressWarnings("unused")
 119.234 +    private static void invokeObjectSetter(final Accessors gs, final MethodHandle invoker, final String name, final Object self, final Object value) throws Throwable {
 119.235          final Object func = gs.setter;
 119.236          if (func instanceof ScriptFunction) {
 119.237 -            try {
 119.238 -                getINVOKE_UA_SETTER().invokeExact(func, self, value);
 119.239 -            } catch (final Error | RuntimeException t) {
 119.240 -                throw t;
 119.241 -            } catch (final Throwable t) {
 119.242 -                throw new RuntimeException(t);
 119.243 -            }
 119.244 +            invoker.invokeExact(func, self, value);
 119.245 +        } else if (name != null) {
 119.246 +            throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self));
 119.247 +        }
 119.248 +    }
 119.249 +
 119.250 +    @SuppressWarnings("unused")
 119.251 +    private static void invokeIntSetter(final Accessors gs, final MethodHandle invoker, final String name, final Object self, final int value) throws Throwable {
 119.252 +        final Object func = gs.setter;
 119.253 +        if (func instanceof ScriptFunction) {
 119.254 +            invoker.invokeExact(func, self, value);
 119.255 +        } else if (name != null) {
 119.256 +            throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self));
 119.257 +        }
 119.258 +    }
 119.259 +
 119.260 +    @SuppressWarnings("unused")
 119.261 +    private static void invokeLongSetter(final Accessors gs, final MethodHandle invoker, final String name, final Object self, final long value) throws Throwable {
 119.262 +        final Object func = gs.setter;
 119.263 +        if (func instanceof ScriptFunction) {
 119.264 +            invoker.invokeExact(func, self, value);
 119.265 +        } else if (name != null) {
 119.266 +            throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self));
 119.267 +        }
 119.268 +    }
 119.269 +
 119.270 +    @SuppressWarnings("unused")
 119.271 +    private static void invokeNumberSetter(final Accessors gs, final MethodHandle invoker, final String name, final Object self, final double value) throws Throwable {
 119.272 +        final Object func = gs.setter;
 119.273 +        if (func instanceof ScriptFunction) {
 119.274 +            invoker.invokeExact(func, self, value);
 119.275          } else if (name != null) {
 119.276              throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self));
 119.277          }
   120.1 --- a/src/jdk/nashorn/internal/runtime/WithObject.java	Mon Oct 27 14:36:13 2014 -0700
   120.2 +++ b/src/jdk/nashorn/internal/runtime/WithObject.java	Thu Nov 06 09:50:15 2014 -0800
   120.3 @@ -210,6 +210,19 @@
   120.4      }
   120.5  
   120.6      @Override
   120.7 +    protected Object invokeNoSuchProperty(final String name, final int programPoint) {
   120.8 +        FindProperty find = expression.findProperty(NO_SUCH_PROPERTY_NAME, true);
   120.9 +        if (find != null) {
  120.10 +            final Object func = find.getObjectValue();
  120.11 +            if (func instanceof ScriptFunction) {
  120.12 +                return ScriptRuntime.apply((ScriptFunction)func, expression, name);
  120.13 +            }
  120.14 +        }
  120.15 +
  120.16 +        return getProto().invokeNoSuchProperty(name, programPoint);
  120.17 +    }
  120.18 +
  120.19 +    @Override
  120.20      public void setSplitState(final int state) {
  120.21          getNonWithParent().setSplitState(state);
  120.22      }
   121.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   121.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/AnyElements.java	Thu Nov 06 09:50:15 2014 -0800
   121.3 @@ -0,0 +1,38 @@
   121.4 +/*
   121.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
   121.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   121.7 + *
   121.8 + * This code is free software; you can redistribute it and/or modify it
   121.9 + * under the terms of the GNU General Public License version 2 only, as
  121.10 + * published by the Free Software Foundation.  Oracle designates this
  121.11 + * particular file as subject to the "Classpath" exception as provided
  121.12 + * by Oracle in the LICENSE file that accompanied this code.
  121.13 + *
  121.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  121.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  121.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  121.17 + * version 2 for more details (a copy is included in the LICENSE file that
  121.18 + * accompanied this code).
  121.19 + *
  121.20 + * You should have received a copy of the GNU General Public License version
  121.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  121.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  121.23 + *
  121.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  121.25 + * or visit www.oracle.com if you need additional information or have any
  121.26 + * questions.
  121.27 + */
  121.28 +package jdk.nashorn.internal.runtime.arrays;
  121.29 +
  121.30 +/**
  121.31 + * Marker interface for any ContinuousArray with any elements
  121.32 + * Used for type checks that throw ClassCastExceptions and force relinks
  121.33 + * for fast NativeArray specializations of builtin methods
  121.34 + */
  121.35 +public interface AnyElements {
  121.36 +    /**
  121.37 +     * Return a numeric weight of the element type - wider is higher
  121.38 +     * @return element type weight
  121.39 +     */
  121.40 +    public int getElementWeight();
  121.41 +}
  121.42 \ No newline at end of file
   122.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Mon Oct 27 14:36:13 2014 -0700
   122.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Thu Nov 06 09:50:15 2014 -0800
   122.3 @@ -28,6 +28,7 @@
   122.4  import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
   122.5  import java.lang.invoke.MethodHandle;
   122.6  import java.lang.invoke.MethodHandles;
   122.7 +import java.lang.reflect.Array;
   122.8  import java.nio.ByteBuffer;
   122.9  import jdk.internal.dynalink.CallSiteDescriptor;
  122.10  import jdk.internal.dynalink.linker.GuardedInvocation;
  122.11 @@ -37,6 +38,7 @@
  122.12  import jdk.nashorn.internal.objects.Global;
  122.13  import jdk.nashorn.internal.runtime.JSType;
  122.14  import jdk.nashorn.internal.runtime.PropertyDescriptor;
  122.15 +import jdk.nashorn.internal.runtime.ScriptRuntime;
  122.16  import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
  122.17  
  122.18  /**
  122.19 @@ -49,10 +51,180 @@
  122.20      /** Mask for getting a chunk */
  122.21      protected static final int CHUNK_MASK = CHUNK_SIZE - 1;
  122.22  
  122.23 +    /** Untouched data - still link callsites as IntArrayData, but expands to
  122.24 +     *  a proper ArrayData when we try to write to it */
  122.25 +    public static final ArrayData EMPTY_ARRAY = new UntouchedArrayData();
  122.26 +
  122.27      /**
  122.28       * Immutable empty array to get ScriptObjects started.
  122.29 +     * Use the same array and convert it to mutable as soon as it is modified
  122.30       */
  122.31 -    public static final ArrayData EMPTY_ARRAY = new NoTypeArrayData();
  122.32 +    private static class UntouchedArrayData extends ContinuousArrayData {
  122.33 +        private UntouchedArrayData() {
  122.34 +            this(0);
  122.35 +        }
  122.36 +
  122.37 +        private UntouchedArrayData(final int length) {
  122.38 +            super(length);
  122.39 +        }
  122.40 +
  122.41 +        private ArrayData toRealArrayData() {
  122.42 +            return toRealArrayData(0);
  122.43 +        }
  122.44 +
  122.45 +        private ArrayData toRealArrayData(final int index) {
  122.46 +            final IntArrayData newData = new IntArrayData(index + 1);
  122.47 +            if (index == 0) {
  122.48 +                return newData;
  122.49 +            }
  122.50 +            return new DeletedRangeArrayFilter(newData, 0, index);
  122.51 +        }
  122.52 +
  122.53 +        @Override
  122.54 +        public ContinuousArrayData copy() {
  122.55 +            return new UntouchedArrayData((int)length);
  122.56 +        }
  122.57 +
  122.58 +        @Override
  122.59 +        public Object asArrayOfType(final Class<?> componentType) {
  122.60 +            return Array.newInstance(componentType, 0);
  122.61 +        }
  122.62 +
  122.63 +        @Override
  122.64 +        public Object[] asObjectArray() {
  122.65 +            return ScriptRuntime.EMPTY_ARRAY;
  122.66 +        }
  122.67 +
  122.68 +        @Override
  122.69 +        public ArrayData ensure(final long safeIndex) {
  122.70 +            if (safeIndex > 0L) {
  122.71 +                return toRealArrayData((int)safeIndex).ensure(safeIndex);
  122.72 +           }
  122.73 +           return this;
  122.74 +        }
  122.75 +
  122.76 +        @Override
  122.77 +        public ArrayData convert(final Class<?> type) {
  122.78 +            return toRealArrayData(0).convert(type);
  122.79 +        }
  122.80 +
  122.81 +        @Override
  122.82 +        public void shiftLeft(final int by) {
  122.83 +            //nop, always empty or we wouldn't be of this class
  122.84 +        }
  122.85 +
  122.86 +        @Override
  122.87 +        public ArrayData shiftRight(final int by) {
  122.88 +            return this; //always empty or we wouldn't be of this class
  122.89 +        }
  122.90 +
  122.91 +        @Override
  122.92 +        public ArrayData shrink(final long newLength) {
  122.93 +            return this;
  122.94 +        }
  122.95 +
  122.96 +        @Override
  122.97 +        public ArrayData set(final int index, final Object value, final boolean strict) {
  122.98 +            return toRealArrayData(index).set(index, value, strict);
  122.99 +        }
 122.100 +
 122.101 +        @Override
 122.102 +        public ArrayData set(final int index, final int value, final boolean strict) {
 122.103 +            return toRealArrayData(index).set(index, value, strict);
 122.104 +        }
 122.105 +
 122.106 +        @Override
 122.107 +        public ArrayData set(final int index, final long value, final boolean strict) {
 122.108 +            return toRealArrayData(index).set(index, value, strict);
 122.109 +        }
 122.110 +
 122.111 +        @Override
 122.112 +        public ArrayData set(final int index, final double value, final boolean strict) {
 122.113 +            return toRealArrayData(index).set(index, value, strict);
 122.114 +        }
 122.115 +
 122.116 +        @Override
 122.117 +        public int getInt(final int index) {
 122.118 +            throw new ArrayIndexOutOfBoundsException(index); //empty
 122.119 +        }
 122.120 +
 122.121 +        @Override
 122.122 +        public long getLong(final int index) {
 122.123 +            throw new ArrayIndexOutOfBoundsException(index); //empty
 122.124 +        }
 122.125 +
 122.126 +        @Override
 122.127 +        public double getDouble(final int index) {
 122.128 +            throw new ArrayIndexOutOfBoundsException(index); //empty
 122.129 +        }
 122.130 +
 122.131 +        @Override
 122.132 +        public Object getObject(final int index) {
 122.133 +            throw new ArrayIndexOutOfBoundsException(index); //empty
 122.134 +        }
 122.135 +
 122.136 +        @Override
 122.137 +        public boolean has(final int index) {
 122.138 +            return false; //empty
 122.139 +        }
 122.140 +
 122.141 +        @Override
 122.142 +        public ArrayData delete(final int index) {
 122.143 +            return new DeletedRangeArrayFilter(this, index, index);
 122.144 +        }
 122.145 +
 122.146 +        @Override
 122.147 +        public ArrayData delete(final long fromIndex, final long toIndex) {
 122.148 +            return new DeletedRangeArrayFilter(this, fromIndex, toIndex);
 122.149 +        }
 122.150 +
 122.151 +        @Override
 122.152 +        public Object pop() {
 122.153 +            return ScriptRuntime.UNDEFINED;
 122.154 +        }
 122.155 +
 122.156 +        @Override
 122.157 +        public ArrayData push(final boolean strict, final Object item) {
 122.158 +            return toRealArrayData().push(strict, item);
 122.159 +        }
 122.160 +
 122.161 +        @Override
 122.162 +        public ArrayData slice(final long from, final long to) {
 122.163 +            return this; //empty
 122.164 +        }
 122.165 +
 122.166 +        @Override
 122.167 +        public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
 122.168 +            return otherData.copy();
 122.169 +        }
 122.170 +
 122.171 +        //no need to override fastPopInt, as the default behavior is to throw classcast exception so we
 122.172 +        //can relink and return an undefined, this is the IntArrayData default behavior
 122.173 +        @Override
 122.174 +        public String toString() {
 122.175 +            return getClass().getSimpleName();
 122.176 +        }
 122.177 +
 122.178 +        @Override
 122.179 +        public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
 122.180 +            return null;
 122.181 +        }
 122.182 +
 122.183 +        @Override
 122.184 +        public MethodHandle getElementSetter(final Class<?> elementType) {
 122.185 +            return null;
 122.186 +        }
 122.187 +
 122.188 +        @Override
 122.189 +        public Class<?> getElementType() {
 122.190 +            return int.class;
 122.191 +        }
 122.192 +
 122.193 +        @Override
 122.194 +        public Class<?> getBoxedElementType() {
 122.195 +            return Integer.class;
 122.196 +        }
 122.197 +    };
 122.198  
 122.199      /**
 122.200       * Length of the array data. Not necessarily length of the wrapped array.
 122.201 @@ -77,7 +249,7 @@
 122.202       * Factory method for unspecified array - start as int
 122.203       * @return ArrayData
 122.204       */
 122.205 -    public static ArrayData initialArray() {
 122.206 +    public final static ArrayData initialArray() {
 122.207          return new IntArrayData();
 122.208      }
 122.209  
 122.210 @@ -92,33 +264,22 @@
 122.211          throw new UnwarrantedOptimismException(data.getObject(index), programPoint);
 122.212      }
 122.213  
 122.214 -    private static int alignUp(final int size) {
 122.215 +    /**
 122.216 +     * Align an array size up to the nearest array chunk size
 122.217 +     * @param size size required
 122.218 +     * @return size given, always >= size
 122.219 +     */
 122.220 +    protected final static int alignUp(final int size) {
 122.221          return size + CHUNK_SIZE - 1 & ~(CHUNK_SIZE - 1);
 122.222      }
 122.223  
 122.224      /**
 122.225 -     * Generic invalidation hook for script object to have call sites to this array indexing
 122.226 -     * relinked, e.g. when a native array is marked as non extensible
 122.227 -     */
 122.228 -    public void invalidateGetters() {
 122.229 -        //subclass responsibility
 122.230 -    }
 122.231 -
 122.232 -    /**
 122.233 -     * Generic invalidation hook for script object to have call sites to this array indexing
 122.234 -     * relinked, e.g. when a native array is marked as non extensible
 122.235 -     */
 122.236 -    public void invalidateSetters() {
 122.237 -        //subclass responsibility
 122.238 -    }
 122.239 -
 122.240 -    /**
 122.241       * Factory method for unspecified array with given length - start as int array data
 122.242       *
 122.243       * @param length the initial length
 122.244       * @return ArrayData
 122.245       */
 122.246 -    public static ArrayData allocate(final int length) {
 122.247 +    public static final ArrayData allocate(final int length) {
 122.248          if (length == 0) {
 122.249              return new IntArrayData();
 122.250          } else if (length >= SparseArrayData.MAX_DENSE_LENGTH) {
 122.251 @@ -134,7 +295,7 @@
 122.252       * @param  array the array
 122.253       * @return ArrayData wrapping this array
 122.254       */
 122.255 -    public static ArrayData allocate(final Object array) {
 122.256 +    public static final ArrayData allocate(final Object array) {
 122.257          final Class<?> clazz = array.getClass();
 122.258  
 122.259          if (clazz == int[].class) {
 122.260 @@ -154,7 +315,7 @@
 122.261       * @param array the array to use for initial elements
 122.262       * @return the ArrayData
 122.263       */
 122.264 -    public static ArrayData allocate(final int[] array) {
 122.265 +    public static final ArrayData allocate(final int[] array) {
 122.266           return new IntArrayData(array, array.length);
 122.267      }
 122.268  
 122.269 @@ -164,7 +325,7 @@
 122.270       * @param array the array to use for initial elements
 122.271       * @return the ArrayData
 122.272       */
 122.273 -    public static ArrayData allocate(final long[] array) {
 122.274 +    public static final ArrayData allocate(final long[] array) {
 122.275          return new LongArrayData(array, array.length);
 122.276      }
 122.277  
 122.278 @@ -174,7 +335,7 @@
 122.279       * @param array the array to use for initial elements
 122.280       * @return the ArrayData
 122.281       */
 122.282 -    public static ArrayData allocate(final double[] array) {
 122.283 +    public static final ArrayData allocate(final double[] array) {
 122.284          return new NumberArrayData(array, array.length);
 122.285      }
 122.286  
 122.287 @@ -184,7 +345,7 @@
 122.288       * @param array the array to use for initial elements
 122.289       * @return the ArrayData
 122.290       */
 122.291 -    public static ArrayData allocate(final Object[] array) {
 122.292 +    public static final ArrayData allocate(final Object[] array) {
 122.293          return new ObjectArrayData(array, array.length);
 122.294      }
 122.295  
 122.296 @@ -194,7 +355,7 @@
 122.297       * @param buf the nio ByteBuffer to wrap
 122.298       * @return the ArrayData
 122.299       */
 122.300 -    public static ArrayData allocate(final ByteBuffer buf) {
 122.301 +    public static final ArrayData allocate(final ByteBuffer buf) {
 122.302          return new ByteBufferArrayData(buf);
 122.303      }
 122.304  
 122.305 @@ -204,7 +365,7 @@
 122.306       * @param underlying  the underlying ArrayData to wrap in the freeze filter
 122.307       * @return the frozen ArrayData
 122.308       */
 122.309 -    public static ArrayData freeze(final ArrayData underlying) {
 122.310 +    public static final ArrayData freeze(final ArrayData underlying) {
 122.311          return new FrozenArrayFilter(underlying);
 122.312      }
 122.313  
 122.314 @@ -214,11 +375,21 @@
 122.315       * @param underlying  the underlying ArrayData to wrap in the seal filter
 122.316       * @return the sealed ArrayData
 122.317       */
 122.318 -    public static ArrayData seal(final ArrayData underlying) {
 122.319 +    public static final ArrayData seal(final ArrayData underlying) {
 122.320          return new SealedArrayFilter(underlying);
 122.321      }
 122.322  
 122.323      /**
 122.324 +     * Prevent this array from being extended
 122.325 +     *
 122.326 +     * @param  underlying the underlying ArrayData to wrap in the non extensible filter
 122.327 +     * @return new array data, filtered
 122.328 +     */
 122.329 +    public static final ArrayData preventExtension(final ArrayData underlying) {
 122.330 +        return new NonExtensibleArrayFilter(underlying);
 122.331 +    }
 122.332 +
 122.333 +    /**
 122.334       * Return the length of the array data. This may differ from the actual
 122.335       * length of the array this wraps as length may be set or gotten as any
 122.336       * other JavaScript Property
 122.337 @@ -728,5 +899,4 @@
 122.338      public GuardedInvocation findFastSetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
 122.339          return null;
 122.340      }
 122.341 -
 122.342  }
   123.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java	Mon Oct 27 14:36:13 2014 -0700
   123.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java	Thu Nov 06 09:50:15 2014 -0800
   123.3 @@ -182,15 +182,15 @@
   123.4      }
   123.5  
   123.6      /**
   123.7 -     * Convert an index to a long value. This basically amounts to ANDing it
   123.8 -     * with {@link JSType#MAX_UINT}, as the maximum array index in JavaScript
   123.9 +     * Convert an index to a long value. This basically amounts to converting it into a
  123.10 +     * {@link JSType#toUint32(int)} uint32} as the maximum array index in JavaScript
  123.11       * is 0xfffffffe
  123.12       *
  123.13       * @param index index to convert to long form
  123.14       * @return index as uint32 in a long
  123.15       */
  123.16      public static long toLongIndex(final int index) {
  123.17 -        return index & JSType.MAX_UINT;
  123.18 +        return JSType.toUint32(index);
  123.19      }
  123.20  
  123.21      /**
  123.22 @@ -201,7 +201,7 @@
  123.23       * @return index as string
  123.24       */
  123.25      public static String toKey(final int index) {
  123.26 -        return Long.toString(index & JSType.MAX_UINT);
  123.27 +        return Long.toString(JSType.toUint32(index));
  123.28      }
  123.29  
  123.30  }
   124.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java	Mon Oct 27 14:36:13 2014 -0700
   124.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java	Thu Nov 06 09:50:15 2014 -0800
   124.3 @@ -1,5 +1,4 @@
   124.4  /*
   124.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   124.6   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   124.7   *
   124.8   * This code is free software; you can redistribute it and/or modify it
   124.9 @@ -37,6 +36,7 @@
  124.10  import jdk.internal.dynalink.CallSiteDescriptor;
  124.11  import jdk.internal.dynalink.linker.GuardedInvocation;
  124.12  import jdk.internal.dynalink.linker.LinkRequest;
  124.13 +import jdk.nashorn.internal.codegen.types.Type;
  124.14  import jdk.nashorn.internal.lookup.Lookup;
  124.15  import jdk.nashorn.internal.runtime.ScriptObject;
  124.16  import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
  124.17 @@ -48,9 +48,6 @@
  124.18   */
  124.19  @Logger(name="arrays")
  124.20  public abstract class ContinuousArrayData extends ArrayData {
  124.21 -
  124.22 -    private SwitchPoint sp;
  124.23 -
  124.24      /**
  124.25       * Constructor
  124.26       * @param length length (elementLength)
  124.27 @@ -59,18 +56,6 @@
  124.28          super(length);
  124.29      }
  124.30  
  124.31 -    private SwitchPoint ensureSwitchPointExists() {
  124.32 -        if (sp == null){
  124.33 -            sp = new SwitchPoint();
  124.34 -        }
  124.35 -        return sp;
  124.36 -    }
  124.37 -
  124.38 -    @Override
  124.39 -    public void invalidateSetters() {
  124.40 -        SwitchPoint.invalidateAll(new SwitchPoint[] { ensureSwitchPointExists() });
  124.41 -    }
  124.42 -
  124.43      /**
  124.44       * Check if we can put one more element at the end of this continous
  124.45       * array without reallocating, or if we are overwriting an already
  124.46 @@ -84,6 +69,14 @@
  124.47      }
  124.48  
  124.49      /**
  124.50 +     * Check if an arraydata is empty
  124.51 +     * @return true if empty
  124.52 +     */
  124.53 +    public boolean isEmpty() {
  124.54 +        return length == 0L;
  124.55 +    }
  124.56 +
  124.57 +    /**
  124.58       * Return element getter for a certain type at a certain program point
  124.59       * @param returnType   return type
  124.60       * @param programPoint program point
  124.61 @@ -107,19 +100,46 @@
  124.62       * @param index index to check - currently only int indexes
  124.63       * @return index
  124.64       */
  124.65 -    protected int throwHas(final int index) {
  124.66 +    protected final int throwHas(final int index) {
  124.67          if (!has(index)) {
  124.68              throw new ClassCastException();
  124.69          }
  124.70          return index;
  124.71      }
  124.72  
  124.73 +    @Override
  124.74 +    public abstract ContinuousArrayData copy();
  124.75 +
  124.76      /**
  124.77       * Returns the type used to store an element in this array
  124.78       * @return element type
  124.79       */
  124.80      public abstract Class<?> getElementType();
  124.81  
  124.82 +    @Override
  124.83 +    public Type getOptimisticType() {
  124.84 +        return Type.typeFor(getElementType());
  124.85 +    }
  124.86 +
  124.87 +    /**
  124.88 +     * Returns the boxed type of the type used to store an element in this array
  124.89 +     * @return element type
  124.90 +     */
  124.91 +    public abstract Class<?> getBoxedElementType();
  124.92 +
  124.93 +    /**
  124.94 +     * Get the widest element type of two arrays. This can be done faster in subclasses, but
  124.95 +     * this works for all ContinuousArrayDatas and for where more optimal checks haven't been
  124.96 +     * implemented.
  124.97 +     *
  124.98 +     * @param otherData another ContinuousArrayData
  124.99 +     * @return the widest boxed element type
 124.100 +     */
 124.101 +    public ContinuousArrayData widest(final ContinuousArrayData otherData) {
 124.102 +        final Class<?> elementType = getElementType();
 124.103 +        return Type.widest(elementType, otherData.getElementType()) == elementType ? this : otherData;
 124.104 +    }
 124.105 +
 124.106      /**
 124.107       * Look up a continuous array element getter
 124.108       * @param get          getter, sometimes combined with a has check that throws CCE on failure for relink
 124.109 @@ -249,12 +269,7 @@
 124.110              final Object[]        args  = request.getArguments();
 124.111              final int             index = (int)args[args.length - 2];
 124.112  
 124.113 -            //sp may be invalidated by e.g. preventExtensions before the first setter is linked
 124.114 -            //then it is already created. otherwise, create it here to guard against future
 124.115 -            //invalidations
 124.116 -            ensureSwitchPointExists();
 124.117 -
 124.118 -            if (!sp.hasBeenInvalidated() && hasRoomFor(index)) {
 124.119 +            if (hasRoomFor(index)) {
 124.120                  MethodHandle setElement = getElementSetter(elementType); //Z(continuousarraydata, int, int), return true if successful
 124.121                  if (setElement != null) {
 124.122                      //else we are dealing with a wider type than supported by this callsite
 124.123 @@ -262,7 +277,7 @@
 124.124                      getArray   = MH.asType(getArray, getArray.type().changeReturnType(getClass()));
 124.125                      setElement = MH.filterArguments(setElement, 0, getArray);
 124.126                      final MethodHandle guard = MH.insertArguments(FAST_ACCESS_GUARD, 0, clazz);
 124.127 -                    return new GuardedInvocation(setElement, guard, sp, ClassCastException.class); //CCE if not a scriptObject anymore
 124.128 +                    return new GuardedInvocation(setElement, guard, (SwitchPoint)null, ClassCastException.class); //CCE if not a scriptObject anymore
 124.129                  }
 124.130              }
 124.131          }
 124.132 @@ -337,4 +352,13 @@
 124.133      public Object fastPopObject() {
 124.134          throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
 124.135      }
 124.136 +
 124.137 +    /**
 124.138 +     * Specialization - fast concat implementation
 124.139 +     * @param otherData data to concat
 124.140 +     * @return new arraydata
 124.141 +     */
 124.142 +    public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
 124.143 +        throw new ClassCastException(String.valueOf(getClass()) + " != " + String.valueOf(otherData.getClass()));
 124.144 +    }
 124.145  }
   125.1 --- a/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java	Mon Oct 27 14:36:13 2014 -0700
   125.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java	Thu Nov 06 09:50:15 2014 -0800
   125.3 @@ -66,9 +66,9 @@
   125.4      public Object[] asObjectArray() {
   125.5          final Object[] value = super.asObjectArray();
   125.6  
   125.7 -        if (lo <= Integer.MAX_VALUE) {
   125.8 -            final int intHi = (int)Math.min(hi, Integer.MAX_VALUE);
   125.9 -            for (int i = (int)lo; i <= intHi; i++) {
  125.10 +        if (lo < Integer.MAX_VALUE) {
  125.11 +            final int end = (int)Math.min(hi + 1, Integer.MAX_VALUE);
  125.12 +            for (int i = (int)lo; i < end; i++) {
  125.13                  value[i] = ScriptRuntime.UNDEFINED;
  125.14              }
  125.15          }
  125.16 @@ -81,9 +81,9 @@
  125.17          final Object value = super.asArrayOfType(componentType);
  125.18          final Object undefValue = convertUndefinedValue(componentType);
  125.19  
  125.20 -        if (lo <= Integer.MAX_VALUE) {
  125.21 -            final int intHi = (int)Math.min(hi, Integer.MAX_VALUE);
  125.22 -            for (int i = (int)lo; i <= intHi; i++) {
  125.23 +        if (lo < Integer.MAX_VALUE) {
  125.24 +            final int end = (int)Math.min(hi + 1, Integer.MAX_VALUE);
  125.25 +            for (int i = (int)lo; i < end; i++) {
  125.26                  Array.set(value, i, undefValue);
  125.27              }
  125.28          }
   126.1 --- a/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java	Mon Oct 27 14:36:13 2014 -0700
   126.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java	Thu Nov 06 09:50:15 2014 -0800
   126.3 @@ -29,7 +29,6 @@
   126.4  import java.lang.invoke.MethodHandle;
   126.5  import java.lang.invoke.MethodHandles;
   126.6  import java.util.Arrays;
   126.7 -import jdk.nashorn.internal.codegen.types.Type;
   126.8  import jdk.nashorn.internal.runtime.JSType;
   126.9  import jdk.nashorn.internal.runtime.ScriptRuntime;
  126.10  
  126.11 @@ -57,23 +56,38 @@
  126.12       * @param array an int array
  126.13       * @param length a length, not necessarily array.length
  126.14       */
  126.15 -    IntArrayData(final int array[], final int length) {
  126.16 +    IntArrayData(final int[] array, final int length) {
  126.17          super(length);
  126.18 -        assert array.length >= length;
  126.19 +        assert array == null || array.length >= length;
  126.20          this.array = array;
  126.21      }
  126.22  
  126.23      @Override
  126.24 -    public Class<?> getElementType() {
  126.25 +    public final Class<?> getElementType() {
  126.26          return int.class;
  126.27      }
  126.28  
  126.29 +    @Override
  126.30 +    public final Class<?> getBoxedElementType() {
  126.31 +        return Integer.class;
  126.32 +    }
  126.33 +
  126.34 +    @Override
  126.35 +    public final int getElementWeight() {
  126.36 +        return 1;
  126.37 +    }
  126.38 +
  126.39 +    @Override
  126.40 +    public final ContinuousArrayData widest(final ContinuousArrayData otherData) {
  126.41 +        return otherData;
  126.42 +    }
  126.43 +
  126.44      private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "getElem", int.class, int.class).methodHandle();
  126.45      private static final MethodHandle SET_ELEM     = specialCall(MethodHandles.lookup(), IntArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
  126.46  
  126.47      @Override
  126.48      public Object[] asObjectArray() {
  126.49 -        return toObjectArray();
  126.50 +        return toObjectArray(true);
  126.51      }
  126.52  
  126.53      @SuppressWarnings("unused")
  126.54 @@ -104,7 +118,7 @@
  126.55      }
  126.56  
  126.57      @Override
  126.58 -    public ArrayData copy() {
  126.59 +    public IntArrayData copy() {
  126.60          return new IntArrayData(array.clone(), (int)length);
  126.61      }
  126.62  
  126.63 @@ -116,9 +130,9 @@
  126.64          return super.asArrayOfType(componentType);
  126.65      }
  126.66  
  126.67 -    private Object[] toObjectArray() {
  126.68 +    private Object[] toObjectArray(final boolean trim) {
  126.69          assert length <= array.length : "length exceeds internal array size";
  126.70 -        final Object[] oarray = new Object[array.length];
  126.71 +        final Object[] oarray = new Object[trim ? (int)length : array.length];
  126.72  
  126.73          for (int index = 0; index < length; index++) {
  126.74              oarray[index] = Integer.valueOf(array[index]);
  126.75 @@ -158,15 +172,14 @@
  126.76      }
  126.77  
  126.78      private ObjectArrayData convertToObject() {
  126.79 -        return new ObjectArrayData(toObjectArray(), (int)length);
  126.80 +        return new ObjectArrayData(toObjectArray(false), (int)length);
  126.81      }
  126.82  
  126.83      @Override
  126.84      public ArrayData convert(final Class<?> type) {
  126.85          if (type == Integer.class) {
  126.86              return this;
  126.87 -        }
  126.88 -        if (type == Long.class) {
  126.89 +        } else if (type == Long.class) {
  126.90              return convertToLong();
  126.91          } else if (type == Double.class) {
  126.92              return convertToDouble();
  126.93 @@ -209,8 +222,7 @@
  126.94  
  126.95      @Override
  126.96      public ArrayData shrink(final long newLength) {
  126.97 -        Arrays.fill(array, (int) newLength, array.length, 0);
  126.98 -
  126.99 +        Arrays.fill(array, (int)newLength, array.length, 0);
 126.100          return this;
 126.101      }
 126.102  
 126.103 @@ -257,11 +269,6 @@
 126.104      }
 126.105  
 126.106      @Override
 126.107 -    public Type getOptimisticType() {
 126.108 -        return Type.INT;
 126.109 -    }
 126.110 -
 126.111 -    @Override
 126.112      public int getInt(final int index) {
 126.113          return array[index];
 126.114      }
 126.115 @@ -327,10 +334,7 @@
 126.116  
 126.117      @Override
 126.118      public ArrayData slice(final long from, final long to) {
 126.119 -        final long start     = from < 0 ? from + length : from;
 126.120 -        final long newLength = to - start;
 126.121 -
 126.122 -        return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
 126.123 +        return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)(to - (from < 0 ? from + length : from)));
 126.124      }
 126.125  
 126.126      @Override
 126.127 @@ -352,7 +356,13 @@
 126.128              throw new UnsupportedOperationException();
 126.129          }
 126.130          final ArrayData returnValue = removed == 0 ?
 126.131 -                EMPTY_ARRAY : new IntArrayData(Arrays.copyOfRange(array, start, start + removed), removed);
 126.132 +                EMPTY_ARRAY :
 126.133 +                new IntArrayData(
 126.134 +                        Arrays.copyOfRange(
 126.135 +                                array,
 126.136 +                                start,
 126.137 +                                start + removed),
 126.138 +                        removed);
 126.139  
 126.140          if (newLength != oldLength) {
 126.141              final int[] newArray;
 126.142 @@ -408,4 +418,26 @@
 126.143      public Object fastPopObject() {
 126.144          return fastPopInt();
 126.145      }
 126.146 +
 126.147 +    @Override
 126.148 +    public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
 126.149 +        final int   otherLength = (int)otherData.length;
 126.150 +        final int   thisLength  = (int)length;
 126.151 +        assert otherLength > 0 && thisLength > 0;
 126.152 +
 126.153 +        final int[] otherArray  = ((IntArrayData)otherData).array;
 126.154 +        final int   newLength   = otherLength + thisLength;
 126.155 +        final int[] newArray    = new int[ArrayData.alignUp(newLength)];
 126.156 +
 126.157 +        System.arraycopy(array, 0, newArray, 0, thisLength);
 126.158 +        System.arraycopy(otherArray, 0, newArray, thisLength, otherLength);
 126.159 +
 126.160 +        return new IntArrayData(newArray, newLength);
 126.161 +    }
 126.162 +
 126.163 +    @Override
 126.164 +    public String toString() {
 126.165 +        assert length <= array.length : length + " > " + array.length;
 126.166 +        return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length));
 126.167 +    }
 126.168  }
   127.1 --- a/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java	Mon Oct 27 14:36:13 2014 -0700
   127.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java	Thu Nov 06 09:50:15 2014 -0800
   127.3 @@ -27,10 +27,10 @@
   127.4  
   127.5  import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
   127.6  import static jdk.nashorn.internal.lookup.Lookup.MH;
   127.7 +
   127.8  import java.lang.invoke.MethodHandle;
   127.9  import java.lang.invoke.MethodHandles;
  127.10  import java.util.Arrays;
  127.11 -import jdk.nashorn.internal.codegen.types.Type;
  127.12  import jdk.nashorn.internal.runtime.JSType;
  127.13  import jdk.nashorn.internal.runtime.ScriptRuntime;
  127.14  
  127.15 @@ -52,27 +52,42 @@
  127.16      LongArrayData(final long array[], final int length) {
  127.17          super(length);
  127.18          assert array.length >= length;
  127.19 -        this.array  = array;
  127.20 +        this.array = array;
  127.21      }
  127.22  
  127.23      @Override
  127.24 -    public Class<?> getElementType() {
  127.25 +    public final Class<?> getElementType() {
  127.26          return long.class;
  127.27      }
  127.28  
  127.29      @Override
  127.30 -    public ArrayData copy() {
  127.31 +    public final Class<?> getBoxedElementType() {
  127.32 +        return Long.class;
  127.33 +    }
  127.34 +
  127.35 +    @Override
  127.36 +    public final ContinuousArrayData widest(final ContinuousArrayData otherData) {
  127.37 +        return otherData instanceof IntElements ? this : otherData;
  127.38 +    }
  127.39 +
  127.40 +    @Override
  127.41 +    public final int getElementWeight() {
  127.42 +        return 2;
  127.43 +    }
  127.44 +
  127.45 +    @Override
  127.46 +    public LongArrayData copy() {
  127.47          return new LongArrayData(array.clone(), (int)length);
  127.48      }
  127.49  
  127.50      @Override
  127.51      public Object[] asObjectArray() {
  127.52 -        return toObjectArray(array, (int)length);
  127.53 +        return toObjectArray(true);
  127.54      }
  127.55  
  127.56 -    private static Object[] toObjectArray(final long[] array, final int length) {
  127.57 +    private Object[] toObjectArray(final boolean trim) {
  127.58          assert length <= array.length : "length exceeds internal array size";
  127.59 -        final Object[] oarray = new Object[array.length];
  127.60 +        final Object[] oarray = new Object[trim ? (int)length : array.length];
  127.61  
  127.62          for (int index = 0; index < length; index++) {
  127.63              oarray[index] = Long.valueOf(array[index]);
  127.64 @@ -89,7 +104,7 @@
  127.65          return super.asArrayOfType(componentType);
  127.66      }
  127.67  
  127.68 -    private static double[] toDoubleArray(final long[] array, final int length) {
  127.69 +    private double[] toDoubleArray() {
  127.70          assert length <= array.length : "length exceeds internal array size";
  127.71          final double[] darray = new double[array.length];
  127.72  
  127.73 @@ -101,15 +116,15 @@
  127.74      }
  127.75  
  127.76      @Override
  127.77 -    public ArrayData convert(final Class<?> type) {
  127.78 +    public ContinuousArrayData convert(final Class<?> type) {
  127.79          if (type == Integer.class || type == Long.class) {
  127.80              return this;
  127.81          }
  127.82          final int len = (int)length;
  127.83          if (type == Double.class) {
  127.84 -            return new NumberArrayData(LongArrayData.toDoubleArray(array, len), len);
  127.85 +            return new NumberArrayData(toDoubleArray(), len);
  127.86          }
  127.87 -        return new ObjectArrayData(LongArrayData.toObjectArray(array, len), len);
  127.88 +        return new ObjectArrayData(toObjectArray(false), len);
  127.89      }
  127.90  
  127.91      @Override
  127.92 @@ -145,8 +160,7 @@
  127.93  
  127.94      @Override
  127.95      public ArrayData shrink(final long newLength) {
  127.96 -        Arrays.fill(array, (int) newLength, array.length, 0);
  127.97 -
  127.98 +        Arrays.fill(array, (int)newLength, array.length, 0L);
  127.99          return this;
 127.100      }
 127.101  
 127.102 @@ -186,11 +200,6 @@
 127.103          return convert(Double.class).set(index, value, strict);
 127.104      }
 127.105  
 127.106 -    @Override
 127.107 -    public Type getOptimisticType() {
 127.108 -        return Type.LONG;
 127.109 -    }
 127.110 -
 127.111      private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "getElem", long.class, int.class).methodHandle();
 127.112      private static final MethodHandle SET_ELEM     = specialCall(MethodHandles.lookup(), LongArrayData.class, "setElem", void.class, int.class, long.class).methodHandle();
 127.113  
 127.114 @@ -364,4 +373,37 @@
 127.115      public Object fastPopObject() {
 127.116          return fastPopLong();
 127.117      }
 127.118 +
 127.119 +    @Override
 127.120 +    public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
 127.121 +        final int   otherLength = (int)otherData.length;
 127.122 +        final int   thisLength  = (int)length;
 127.123 +        assert otherLength > 0 && thisLength > 0;
 127.124 +
 127.125 +        final long[] otherArray  = ((LongArrayData)otherData).array;
 127.126 +        final int    newLength   = otherLength + thisLength;
 127.127 +        final long[] newArray   = new long[ArrayData.alignUp(newLength)];
 127.128 +
 127.129 +        System.arraycopy(array, 0, newArray, 0, thisLength);
 127.130 +        System.arraycopy(otherArray, 0, newArray, thisLength, otherLength);
 127.131 +
 127.132 +        return new LongArrayData(newArray, newLength);
 127.133 +    }
 127.134 +
 127.135 +    @Override
 127.136 +    public String toString() {
 127.137 +        assert length <= array.length : length + " > " + array.length;
 127.138 +
 127.139 +        final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).
 127.140 +                append(": [");
 127.141 +        for (int i = 0; i < length; i++) {
 127.142 +            sb.append(array[i]).append('L'); //make sure L suffix is on elements, to discriminate this from IntArrayData.toString()
 127.143 +            if (i + 1 < length) {
 127.144 +                sb.append(", ");
 127.145 +            }
 127.146 +        }
 127.147 +        sb.append(']');
 127.148 +
 127.149 +        return sb.toString();
 127.150 +    }
 127.151  }
   128.1 --- a/src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java	Mon Oct 27 14:36:13 2014 -0700
   128.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   128.3 @@ -1,186 +0,0 @@
   128.4 -/*
   128.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   128.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   128.7 - *
   128.8 - * This code is free software; you can redistribute it and/or modify it
   128.9 - * under the terms of the GNU General Public License version 2 only, as
  128.10 - * published by the Free Software Foundation.  Oracle designates this
  128.11 - * particular file as subject to the "Classpath" exception as provided
  128.12 - * by Oracle in the LICENSE file that accompanied this code.
  128.13 - *
  128.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  128.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  128.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  128.17 - * version 2 for more details (a copy is included in the LICENSE file that
  128.18 - * accompanied this code).
  128.19 - *
  128.20 - * You should have received a copy of the GNU General Public License version
  128.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  128.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  128.23 - *
  128.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  128.25 - * or visit www.oracle.com if you need additional information or have any
  128.26 - * questions.
  128.27 - */
  128.28 -
  128.29 -package jdk.nashorn.internal.runtime.arrays;
  128.30 -
  128.31 -import java.lang.reflect.Array;
  128.32 -import jdk.nashorn.internal.runtime.ScriptRuntime;
  128.33 -
  128.34 -/**
  128.35 - * Place holding array data for non-array objects.  Activates a true array when
  128.36 - * accessed.  Should only exist as a singleton defined in ArrayData.
  128.37 - */
  128.38 -final class NoTypeArrayData extends ArrayData {
  128.39 -    NoTypeArrayData() {
  128.40 -        super(0);
  128.41 -    }
  128.42 -
  128.43 -    NoTypeArrayData(final long length) {
  128.44 -         super(length);
  128.45 -    }
  128.46 -
  128.47 -    @Override
  128.48 -    public Object[] asObjectArray() {
  128.49 -        return ScriptRuntime.EMPTY_ARRAY;
  128.50 -    }
  128.51 -
  128.52 -    @Override
  128.53 -    public ArrayData copy() {
  128.54 -        return new NoTypeArrayData();
  128.55 -    }
  128.56 -
  128.57 -    @Override
  128.58 -    public Object asArrayOfType(final Class<?> componentType) {
  128.59 -        return Array.newInstance(componentType, 0);
  128.60 -    }
  128.61 -
  128.62 -    @Override
  128.63 -    public ArrayData convert(final Class<?> type) {
  128.64 -        final long len = length;
  128.65 -        final ArrayData arrayData;
  128.66 -        if (type == Long.class) {
  128.67 -            arrayData = new LongArrayData(new long[ArrayData.nextSize((int)len)], (int)len);
  128.68 -        } else if (type == Double.class) {
  128.69 -            arrayData = new NumberArrayData(new double[ArrayData.nextSize((int)len)], (int)len);
  128.70 -        } else if (type == Integer.class) {
  128.71 -            arrayData = new IntArrayData(new int[ArrayData.nextSize((int)len)], (int)len);
  128.72 -        } else {
  128.73 -            assert !type.isPrimitive();
  128.74 -            arrayData = new ObjectArrayData(new Object[ArrayData.nextSize((int)len)], (int)len);
  128.75 -        }
  128.76 -        return length == 0 ? arrayData : new DeletedRangeArrayFilter(arrayData, 0, len - 1);
  128.77 -    }
  128.78 -
  128.79 -    @Override
  128.80 -    public void shiftLeft(final int by) {
  128.81 -        //empty
  128.82 -    }
  128.83 -
  128.84 -    @Override
  128.85 -    public ArrayData shiftRight(final int by) {
  128.86 -        return this;
  128.87 -    }
  128.88 -
  128.89 -    @Override
  128.90 -    public ArrayData ensure(final long safeIndex) {
  128.91 -        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
  128.92 -            return new SparseArrayData(this, safeIndex + 1);
  128.93 -        }
  128.94 -
  128.95 -        // Don't trample the shared EMPTY_ARRAY.
  128.96 -        if (length == 0) {
  128.97 -            return new NoTypeArrayData(Math.max(safeIndex + 1, length));
  128.98 -        }
  128.99 -
 128.100 -        setLength(Math.max(safeIndex + 1, length));
 128.101 -        return this;
 128.102 -    }
 128.103 -
 128.104 -    @Override
 128.105 -    public ArrayData shrink(final long newLength) {
 128.106 -        return this;
 128.107 -    }
 128.108 -
 128.109 -    @Override
 128.110 -    public ArrayData set(final int index, final Object value, final boolean strict) {
 128.111 -        ArrayData newData;
 128.112 -
 128.113 -        if (value instanceof Double) {
 128.114 -            newData = convert(Double.class);
 128.115 -        } else if (value instanceof Long) {
 128.116 -            newData = convert(Long.class);
 128.117 -        } else if (value instanceof Integer) {
 128.118 -            newData = convert(Integer.class);
 128.119 -        } else {
 128.120 -            assert !(value instanceof Number);
 128.121 -            newData = convert(value == null ? Object.class : value.getClass());
 128.122 -        }
 128.123 -
 128.124 -        return newData.set(index, value, strict);
 128.125 -    }
 128.126 -
 128.127 -    @Override
 128.128 -    public ArrayData set(final int index, final int value, final boolean strict) {
 128.129 -        final ArrayData newData = convert(Integer.class);
 128.130 -        return newData.set(index, value, strict);
 128.131 -    }
 128.132 -
 128.133 -    @Override
 128.134 -    public ArrayData set(final int index, final long value, final boolean strict) {
 128.135 -        final ArrayData newData = convert(Long.class);
 128.136 -        return newData.set(index, value, strict);
 128.137 -    }
 128.138 -
 128.139 -    @Override
 128.140 -    public ArrayData set(final int index, final double value, final boolean strict) {
 128.141 -        final ArrayData newData = convert(Double.class);
 128.142 -        return newData.set(index, value, strict);
 128.143 -    }
 128.144 -
 128.145 -    @Override
 128.146 -    public int getInt(final int index) {
 128.147 -        throw new ArrayIndexOutOfBoundsException(index);
 128.148 -    }
 128.149 -
 128.150 -    @Override
 128.151 -    public long getLong(final int index) {
 128.152 -        throw new ArrayIndexOutOfBoundsException(index);
 128.153 -    }
 128.154 -
 128.155 -    @Override
 128.156 -    public double getDouble(final int index) {
 128.157 -        throw new ArrayIndexOutOfBoundsException(index);
 128.158 -    }
 128.159 -
 128.160 -    @Override
 128.161 -    public Object getObject(final int index) {
 128.162 -        throw new ArrayIndexOutOfBoundsException(index);
 128.163 -    }
 128.164 -
 128.165 -    @Override
 128.166 -    public boolean has(final int index) {
 128.167 -        return false;
 128.168 -    }
 128.169 -
 128.170 -    @Override
 128.171 -    public ArrayData delete(final int index) {
 128.172 -        return new DeletedRangeArrayFilter(this, index, index);
 128.173 -    }
 128.174 -
 128.175 -    @Override
 128.176 -    public ArrayData delete(final long fromIndex, final long toIndex) {
 128.177 -        return new DeletedRangeArrayFilter(this, fromIndex, toIndex);
 128.178 -    }
 128.179 -
 128.180 -    @Override
 128.181 -    public Object pop() {
 128.182 -        return ScriptRuntime.UNDEFINED;
 128.183 -    }
 128.184 -
 128.185 -    @Override
 128.186 -    public ArrayData slice(final long from, final long to) {
 128.187 -        return this;
 128.188 -    }
 128.189 -}
   129.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java	Thu Nov 06 09:50:15 2014 -0800
   129.3 @@ -0,0 +1,68 @@
   129.4 +package jdk.nashorn.internal.runtime.arrays;
   129.5 +
   129.6 +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
   129.7 +import jdk.nashorn.internal.objects.Global;
   129.8 +import jdk.nashorn.internal.runtime.ScriptRuntime;
   129.9 +
  129.10 +/**
  129.11 + * Filter class that wrap arrays that have been tagged non extensible
  129.12 + */
  129.13 +public class NonExtensibleArrayFilter extends ArrayFilter {
  129.14 +
  129.15 +    /**
  129.16 +     * Constructor
  129.17 +     * @param underlying array
  129.18 +     */
  129.19 +    public NonExtensibleArrayFilter(final ArrayData underlying) {
  129.20 +        super(underlying);
  129.21 +    }
  129.22 +
  129.23 +    @Override
  129.24 +    public ArrayData copy() {
  129.25 +        return new NonExtensibleArrayFilter(underlying.copy());
  129.26 +    }
  129.27 +
  129.28 +    @Override
  129.29 +    public ArrayData slice(final long from, final long to) {
  129.30 +        return new NonExtensibleArrayFilter(underlying.slice(from, to));
  129.31 +    }
  129.32 +
  129.33 +    private ArrayData extensionCheck(final boolean strict, final int index) {
  129.34 +        if (!strict) {
  129.35 +            return this;
  129.36 +        }
  129.37 +        throw typeError(Global.instance(), "object.non.extensible", String.valueOf(index), ScriptRuntime.safeToString(this));
  129.38 +    }
  129.39 +
  129.40 +    @Override
  129.41 +    public ArrayData set(final int index, final Object value, final boolean strict) {
  129.42 +        if (has(index)) {
  129.43 +            return underlying.set(index, value, strict);
  129.44 +        }
  129.45 +        return extensionCheck(strict, index);
  129.46 +    }
  129.47 +
  129.48 +    @Override
  129.49 +    public ArrayData set(final int index, final int value, final boolean strict) {
  129.50 +        if (has(index)) {
  129.51 +            return underlying.set(index, value, strict);
  129.52 +        }
  129.53 +        return extensionCheck(strict, index);
  129.54 +    }
  129.55 +
  129.56 +    @Override
  129.57 +    public ArrayData set(final int index, final long value, final boolean strict) {
  129.58 +        if (has(index)) {
  129.59 +            return underlying.set(index, value, strict);
  129.60 +        }
  129.61 +        return extensionCheck(strict, index);
  129.62 +    }
  129.63 +
  129.64 +    @Override
  129.65 +    public ArrayData set(final int index, final double value, final boolean strict) {
  129.66 +        if (has(index)) {
  129.67 +            return underlying.set(index, value, strict);
  129.68 +        }
  129.69 +        return extensionCheck(strict, index);
  129.70 +    }
  129.71 +}
   130.1 --- a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java	Mon Oct 27 14:36:13 2014 -0700
   130.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java	Thu Nov 06 09:50:15 2014 -0800
   130.3 @@ -28,10 +28,10 @@
   130.4  import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
   130.5  import static jdk.nashorn.internal.lookup.Lookup.MH;
   130.6  import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
   130.7 +
   130.8  import java.lang.invoke.MethodHandle;
   130.9  import java.lang.invoke.MethodHandles;
  130.10  import java.util.Arrays;
  130.11 -import jdk.nashorn.internal.codegen.types.Type;
  130.12  
  130.13  /**
  130.14   * Implementation of {@link ArrayData} as soon as a double has been
  130.15 @@ -48,30 +48,45 @@
  130.16       * @param array an int array
  130.17       * @param length a length, not necessarily array.length
  130.18       */
  130.19 -    NumberArrayData(final double array[], final int length) {
  130.20 +    NumberArrayData(final double[] array, final int length) {
  130.21          super(length);
  130.22          assert array.length >= length;
  130.23 -        this.array  = array;
  130.24 +        this.array = array;
  130.25      }
  130.26  
  130.27      @Override
  130.28 -    public Class<?> getElementType() {
  130.29 +    public final Class<?> getElementType() {
  130.30          return double.class;
  130.31      }
  130.32  
  130.33      @Override
  130.34 -    public ArrayData copy() {
  130.35 +    public final Class<?> getBoxedElementType() {
  130.36 +        return Double.class;
  130.37 +    }
  130.38 +
  130.39 +    @Override
  130.40 +    public final int getElementWeight() {
  130.41 +        return 3;
  130.42 +    }
  130.43 +
  130.44 +    @Override
  130.45 +    public final ContinuousArrayData widest(final ContinuousArrayData otherData) {
  130.46 +        return otherData instanceof IntOrLongElements ? this : otherData;
  130.47 +    }
  130.48 +
  130.49 +    @Override
  130.50 +    public NumberArrayData copy() {
  130.51          return new NumberArrayData(array.clone(), (int)length);
  130.52      }
  130.53  
  130.54      @Override
  130.55      public Object[] asObjectArray() {
  130.56 -        return toObjectArray(array, (int)length);
  130.57 +        return toObjectArray(true);
  130.58      }
  130.59  
  130.60 -    private static Object[] toObjectArray(final double[] array, final int length) {
  130.61 +    private Object[] toObjectArray(final boolean trim) {
  130.62          assert length <= array.length : "length exceeds internal array size";
  130.63 -        final Object[] oarray = new Object[array.length];
  130.64 +        final Object[] oarray = new Object[trim ? (int)length : array.length];
  130.65  
  130.66          for (int index = 0; index < length; index++) {
  130.67              oarray[index] = Double.valueOf(array[index]);
  130.68 @@ -88,10 +103,10 @@
  130.69      }
  130.70  
  130.71      @Override
  130.72 -    public ArrayData convert(final Class<?> type) {
  130.73 +    public ContinuousArrayData convert(final Class<?> type) {
  130.74          if (type != Double.class && type != Integer.class && type != Long.class) {
  130.75              final int len = (int)length;
  130.76 -            return new ObjectArrayData(NumberArrayData.toObjectArray(array, len), len);
  130.77 +            return new ObjectArrayData(toObjectArray(false), len);
  130.78          }
  130.79          return this;
  130.80      }
  130.81 @@ -129,7 +144,7 @@
  130.82  
  130.83      @Override
  130.84      public ArrayData shrink(final long newLength) {
  130.85 -        Arrays.fill(array, (int) newLength, array.length, 0.0);
  130.86 +        Arrays.fill(array, (int)newLength, array.length, 0.0);
  130.87          return this;
  130.88      }
  130.89  
  130.90 @@ -166,11 +181,6 @@
  130.91          return this;
  130.92      }
  130.93  
  130.94 -    @Override
  130.95 -    public Type getOptimisticType() {
  130.96 -        return Type.NUMBER;
  130.97 -    }
  130.98 -
  130.99      private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), NumberArrayData.class, "getElem", double.class, int.class).methodHandle();
 130.100      private static final MethodHandle SET_ELEM     = specialCall(MethodHandles.lookup(), NumberArrayData.class, "setElem", void.class, int.class, double.class).methodHandle();
 130.101  
 130.102 @@ -339,4 +349,26 @@
 130.103      public Object fastPopObject() {
 130.104          return fastPopDouble();
 130.105      }
 130.106 +
 130.107 +    @Override
 130.108 +    public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
 130.109 +        final int   otherLength = (int)otherData.length;
 130.110 +        final int   thisLength  = (int)length;
 130.111 +        assert otherLength > 0 && thisLength > 0;
 130.112 +
 130.113 +        final double[] otherArray = ((NumberArrayData)otherData).array;
 130.114 +        final int      newLength  = otherLength + thisLength;
 130.115 +        final double[] newArray   = new double[ArrayData.alignUp(newLength)];
 130.116 +
 130.117 +        System.arraycopy(array, 0, newArray, 0, thisLength);
 130.118 +        System.arraycopy(otherArray, 0, newArray, thisLength, otherLength);
 130.119 +
 130.120 +        return new NumberArrayData(newArray, newLength);
 130.121 +    }
 130.122 +
 130.123 +    @Override
 130.124 +    public String toString() {
 130.125 +        assert length <= array.length : length + " > " + array.length;
 130.126 +        return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length));
 130.127 +    }
 130.128  }
   131.1 --- a/src/jdk/nashorn/internal/runtime/arrays/NumericElements.java	Mon Oct 27 14:36:13 2014 -0700
   131.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/NumericElements.java	Thu Nov 06 09:50:15 2014 -0800
   131.3 @@ -30,6 +30,6 @@
   131.4   * Used for type checks that throw ClassCastExceptions and force relinks
   131.5   * for fast NativeArray specializations of builtin methods
   131.6   */
   131.7 -public interface NumericElements {
   131.8 +public interface NumericElements extends AnyElements {
   131.9      //empty
  131.10  }
   132.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java	Mon Oct 27 14:36:13 2014 -0700
   132.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java	Thu Nov 06 09:50:15 2014 -0800
   132.3 @@ -26,10 +26,10 @@
   132.4  package jdk.nashorn.internal.runtime.arrays;
   132.5  
   132.6  import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
   132.7 +
   132.8  import java.lang.invoke.MethodHandle;
   132.9  import java.lang.invoke.MethodHandles;
  132.10  import java.util.Arrays;
  132.11 -import jdk.nashorn.internal.codegen.types.Type;
  132.12  import jdk.nashorn.internal.runtime.JSType;
  132.13  import jdk.nashorn.internal.runtime.ScriptRuntime;
  132.14  
  132.15 @@ -37,7 +37,7 @@
  132.16   * Implementation of {@link ArrayData} as soon as an Object has been
  132.17   * written to the array
  132.18   */
  132.19 -final class ObjectArrayData extends ContinuousArrayData {
  132.20 +final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
  132.21  
  132.22      /**
  132.23       * The wrapped array
  132.24 @@ -49,19 +49,34 @@
  132.25       * @param array an int array
  132.26       * @param length a length, not necessarily array.length
  132.27       */
  132.28 -    ObjectArrayData(final Object array[], final int length) {
  132.29 +    ObjectArrayData(final Object[] array, final int length) {
  132.30          super(length);
  132.31          assert array.length >= length;
  132.32          this.array  = array;
  132.33      }
  132.34  
  132.35      @Override
  132.36 -    public Class<?> getElementType() {
  132.37 +    public final Class<?> getElementType() {
  132.38          return Object.class;
  132.39      }
  132.40  
  132.41      @Override
  132.42 -    public ArrayData copy() {
  132.43 +    public final Class<?> getBoxedElementType() {
  132.44 +        return getElementType();
  132.45 +    }
  132.46 +
  132.47 +    @Override
  132.48 +    public final int getElementWeight() {
  132.49 +        return 4;
  132.50 +    }
  132.51 +
  132.52 +    @Override
  132.53 +    public final ContinuousArrayData widest(final ContinuousArrayData otherData) {
  132.54 +        return otherData instanceof NumericElements ? this : otherData;
  132.55 +    }
  132.56 +
  132.57 +    @Override
  132.58 +    public ObjectArrayData copy() {
  132.59          return new ObjectArrayData(array.clone(), (int)length);
  132.60      }
  132.61  
  132.62 @@ -79,7 +94,7 @@
  132.63      }
  132.64  
  132.65      @Override
  132.66 -    public ArrayData convert(final Class<?> type) {
  132.67 +    public ObjectArrayData convert(final Class<?> type) {
  132.68          return this;
  132.69      }
  132.70  
  132.71 @@ -155,15 +170,11 @@
  132.72  
  132.73      @Override
  132.74      public ArrayData setEmpty(final long lo, final long hi) {
  132.75 -        Arrays.fill(array, (int)Math.max(lo, 0L), (int)Math.min(hi, Integer.MAX_VALUE), ScriptRuntime.EMPTY);
  132.76 +        // hi parameter is inclusive, but Arrays.fill toIndex parameter is exclusive
  132.77 +        Arrays.fill(array, (int)Math.max(lo, 0L), (int)Math.min(hi + 1, Integer.MAX_VALUE), ScriptRuntime.EMPTY);
  132.78          return this;
  132.79      }
  132.80  
  132.81 -    @Override
  132.82 -    public Type getOptimisticType() {
  132.83 -        return Type.OBJECT;
  132.84 -    }
  132.85 -
  132.86      private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), ObjectArrayData.class, "getElem", Object.class, int.class).methodHandle();
  132.87      private static final MethodHandle SET_ELEM     = specialCall(MethodHandles.lookup(), ObjectArrayData.class, "setElem", void.class, int.class, Object.class).methodHandle();
  132.88  
  132.89 @@ -329,4 +340,26 @@
  132.90  
  132.91          return returnValue;
  132.92      }
  132.93 +
  132.94 +    @Override
  132.95 +    public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
  132.96 +        final int   otherLength = (int)otherData.length;
  132.97 +        final int   thisLength  = (int)length;
  132.98 +        assert otherLength > 0 && thisLength > 0;
  132.99 +
 132.100 +        final Object[] otherArray = ((ObjectArrayData)otherData).array;
 132.101 +        final int      newLength  = otherLength + thisLength;
 132.102 +        final Object[] newArray   = new Object[ArrayData.alignUp(newLength)];
 132.103 +
 132.104 +        System.arraycopy(array, 0, newArray, 0, thisLength);
 132.105 +        System.arraycopy(otherArray, 0, newArray, thisLength, otherLength);
 132.106 +
 132.107 +        return new ObjectArrayData(newArray, newLength);
 132.108 +    }
 132.109 +
 132.110 +    @Override
 132.111 +    public String toString() {
 132.112 +        assert length <= array.length : length + " > " + array.length;
 132.113 +        return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length));
 132.114 +    }
 132.115  }
   133.1 --- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Mon Oct 27 14:36:13 2014 -0700
   133.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Thu Nov 06 09:50:15 2014 -0800
   133.3 @@ -78,7 +78,7 @@
   133.4  
   133.5          for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) {
   133.6              final long key = entry.getKey();
   133.7 -            if (key <= Integer.MAX_VALUE) {
   133.8 +            if (key < Integer.MAX_VALUE) {
   133.9                  objArray[(int)key] = entry.getValue();
  133.10              } else {
  133.11                  break; // ascending key order
   134.1 --- a/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java	Mon Oct 27 14:36:13 2014 -0700
   134.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java	Thu Nov 06 09:50:15 2014 -0800
   134.3 @@ -88,7 +88,7 @@
   134.4      }
   134.5  
   134.6      @Override
   134.7 -    public ArrayData copy() {
   134.8 +    public TypedArrayData<T> copy() {
   134.9          throw new UnsupportedOperationException();
  134.10      }
  134.11  
  134.12 @@ -133,7 +133,7 @@
  134.13      }
  134.14  
  134.15      @Override
  134.16 -    public ArrayData convert(final Class<?> type) {
  134.17 +    public TypedArrayData<T> convert(final Class<?> type) {
  134.18          throw new UnsupportedOperationException();
  134.19      }
  134.20  
   135.1 --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Mon Oct 27 14:36:13 2014 -0700
   135.2 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Thu Nov 06 09:50:15 2014 -0800
   135.3 @@ -337,6 +337,20 @@
   135.4  
   135.5      /**
   135.6       * Returns a dynamic invoker for a specified dynamic operation using the public lookup. Similar to
   135.7 +     * {@link #createDynamicInvoker(String, Class, Class...)} but with an additional parameter to
   135.8 +     * set the call site flags of the dynamic invoker.
   135.9 +     * @param opDesc Dynalink dynamic operation descriptor.
  135.10 +     * @param flags the call site flags for the operation
  135.11 +     * @param rtype the return type for the operation
  135.12 +     * @param ptypes the parameter types for the operation
  135.13 +     * @return MethodHandle for invoking the operation.
  135.14 +     */
  135.15 +    public static MethodHandle createDynamicInvoker(final String opDesc, final int flags, final Class<?> rtype, final Class<?>... ptypes) {
  135.16 +        return bootstrap(MethodHandles.publicLookup(), opDesc, MethodType.methodType(rtype, ptypes), flags).dynamicInvoker();
  135.17 +    }
  135.18 +
  135.19 +    /**
  135.20 +     * Returns a dynamic invoker for a specified dynamic operation using the public lookup. Similar to
  135.21       * {@link #createDynamicInvoker(String, Class, Class...)} but with return and parameter types composed into a
  135.22       * method type in the signature. See the discussion of that method for details.
  135.23       * @param opDesc Dynalink dynamic operation descriptor.
   136.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Mon Oct 27 14:36:13 2014 -0700
   136.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Thu Nov 06 09:50:15 2014 -0800
   136.3 @@ -152,6 +152,7 @@
   136.4      static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE);
   136.5      static final String VOID_NOARG_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE);
   136.6  
   136.7 +    private static final Type SCRIPT_OBJECT_TYPE = Type.getType(ScriptObject.class);
   136.8      private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class);
   136.9      private static final Type STRING_TYPE = Type.getType(String.class);
  136.10      private static final Type METHOD_TYPE_TYPE = Type.getType(MethodType.class);
  136.11 @@ -536,8 +537,8 @@
  136.12          final int argLen = originalArgTypes.length;
  136.13          final Type[] newArgTypes = new Type[argLen + 1];
  136.14  
  136.15 -        // Insert ScriptFunction|Object as the last argument to the constructor
  136.16 -        final Type extraArgumentType = fromFunction ? SCRIPT_FUNCTION_TYPE : OBJECT_TYPE;
  136.17 +        // Insert ScriptFunction|ScriptObject as the last argument to the constructor
  136.18 +        final Type extraArgumentType = fromFunction ? SCRIPT_FUNCTION_TYPE : SCRIPT_OBJECT_TYPE;
  136.19          newArgTypes[argLen] = extraArgumentType;
  136.20          System.arraycopy(originalArgTypes, 0, newArgTypes, 0, argLen);
  136.21  
  136.22 @@ -588,6 +589,34 @@
  136.23          // Initialize converters
  136.24          generateConverterInit(mv, fromFunction);
  136.25          endInitMethod(mv);
  136.26 +
  136.27 +        if (! fromFunction) {
  136.28 +            newArgTypes[argLen] = OBJECT_TYPE;
  136.29 +            final InstructionAdapter mv2 = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, INIT,
  136.30 +                Type.getMethodDescriptor(originalCtorType.getReturnType(), newArgTypes), null, null));
  136.31 +            generateOverridingConstructorWithObjectParam(mv2, ctor, originalCtorType.getDescriptor());
  136.32 +        }
  136.33 +    }
  136.34 +
  136.35 +    // Object additional param accepting constructor - generated to handle null and undefined value
  136.36 +    // for script adapters. This is effectively to throw TypeError on such script adapters. See
  136.37 +    // JavaAdapterServices.getHandle as well.
  136.38 +    private void generateOverridingConstructorWithObjectParam(final InstructionAdapter mv, final Constructor<?> ctor, final String ctorDescriptor) {
  136.39 +        mv.visitCode();
  136.40 +        mv.visitVarInsn(ALOAD, 0);
  136.41 +        final Class<?>[] argTypes = ctor.getParameterTypes();
  136.42 +        int offset = 1; // First arg is at position 1, after this.
  136.43 +        for (int i = 0; i < argTypes.length; ++i) {
  136.44 +            final Type argType = Type.getType(argTypes[i]);
  136.45 +            mv.load(offset, argType);
  136.46 +            offset += argType.getSize();
  136.47 +        }
  136.48 +        mv.invokespecial(superClassName, INIT, ctorDescriptor, false);
  136.49 +        mv.visitVarInsn(ALOAD, offset);
  136.50 +        mv.visitInsn(ACONST_NULL);
  136.51 +        mv.visitInsn(ACONST_NULL);
  136.52 +        mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR, false);
  136.53 +        endInitMethod(mv);
  136.54      }
  136.55  
  136.56      private static void endInitMethod(final InstructionAdapter mv) {
   137.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java	Mon Oct 27 14:36:13 2014 -0700
   137.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java	Thu Nov 06 09:50:15 2014 -0800
   137.3 @@ -39,6 +39,7 @@
   137.4  import jdk.nashorn.internal.runtime.Context;
   137.5  import jdk.nashorn.internal.runtime.JSType;
   137.6  import jdk.nashorn.internal.runtime.ScriptFunction;
   137.7 +import jdk.nashorn.internal.runtime.ScriptObject;
   137.8  
   137.9  /**
  137.10   * This class encapsulates the bytecode of the adapter class and can be used to load it into the JVM as an actual Class.
  137.11 @@ -51,7 +52,7 @@
  137.12      private static final AccessControlContext CREATE_LOADER_ACC_CTXT = ClassAndLoader.createPermAccCtxt("createClassLoader");
  137.13      private static final AccessControlContext GET_CONTEXT_ACC_CTXT = ClassAndLoader.createPermAccCtxt(Context.NASHORN_GET_CONTEXT);
  137.14      private static final Collection<String> VISIBLE_INTERNAL_CLASS_NAMES = Collections.unmodifiableCollection(new HashSet<>(
  137.15 -            Arrays.asList(JavaAdapterServices.class.getName(), ScriptFunction.class.getName(), JSType.class.getName())));
  137.16 +            Arrays.asList(JavaAdapterServices.class.getName(), ScriptObject.class.getName(), ScriptFunction.class.getName(), JSType.class.getName())));
  137.17  
  137.18      private final String className;
  137.19      private final byte[] classBytes;
   138.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java	Mon Oct 27 14:36:13 2014 -0700
   138.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java	Thu Nov 06 09:50:15 2014 -0800
   138.3 @@ -47,7 +47,6 @@
   138.4  import jdk.internal.org.objectweb.asm.Opcodes;
   138.5  import jdk.internal.org.objectweb.asm.Type;
   138.6  import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
   138.7 -import jdk.nashorn.api.scripting.ScriptUtils;
   138.8  import jdk.nashorn.internal.runtime.Context;
   138.9  import jdk.nashorn.internal.runtime.ScriptFunction;
  138.10  import jdk.nashorn.internal.runtime.ScriptObject;
  138.11 @@ -220,7 +219,7 @@
  138.12       * @return the filtered return value.
  138.13       */
  138.14      public static Object exportReturnValue(final Object obj) {
  138.15 -        return ScriptUtils.wrap(NashornBeansLinker.exportArgument(obj));
  138.16 +        return NashornBeansLinker.exportArgument(obj, true);
  138.17      }
  138.18  
  138.19      /**
   139.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Mon Oct 27 14:36:13 2014 -0700
   139.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Thu Nov 06 09:50:15 2014 -0800
   139.3 @@ -35,17 +35,28 @@
   139.4  import jdk.internal.dynalink.linker.LinkRequest;
   139.5  import jdk.internal.dynalink.linker.LinkerServices;
   139.6  import jdk.internal.dynalink.support.Lookup;
   139.7 +import jdk.nashorn.api.scripting.ScriptUtils;
   139.8 +import jdk.nashorn.internal.objects.NativeArray;
   139.9  import jdk.nashorn.internal.runtime.ConsString;
  139.10 +import jdk.nashorn.internal.runtime.ScriptObject;
  139.11 +import jdk.nashorn.internal.runtime.options.Options;
  139.12  
  139.13  /**
  139.14   * This linker delegates to a {@code BeansLinker} but passes it a special linker services object that has a modified
  139.15   * {@code asType} method that will ensure that we never pass internal engine objects that should not be externally
  139.16 - * observable (currently only ConsString) to Java APIs, but rather that we flatten it into a String. We can't just add
  139.17 + * observable (currently ConsString and ScriptObject) to Java APIs, but rather that we flatten it into a String. We can't just add
  139.18   * this functionality as custom converters via {@code GuaardingTypeConverterFactory}, since they are not consulted when
  139.19   * the target method handle parameter signature is {@code Object}.
  139.20   */
  139.21  public class NashornBeansLinker implements GuardingDynamicLinker {
  139.22 +    // System property to control whether to wrap ScriptObject->ScriptObjectMirror for
  139.23 +    // Object type arguments of Java method calls, field set and array set.
  139.24 +    private static final boolean MIRROR_ALWAYS = Options.getBooleanProperty("nashorn.mirror.always", true);
  139.25 +
  139.26      private static final MethodHandle EXPORT_ARGUMENT = new Lookup(MethodHandles.lookup()).findOwnStatic("exportArgument", Object.class, Object.class);
  139.27 +    private static final MethodHandle EXPORT_NATIVE_ARRAY = new Lookup(MethodHandles.lookup()).findOwnStatic("exportNativeArray", Object.class, NativeArray.class);
  139.28 +    private static final MethodHandle EXPORT_SCRIPT_OBJECT = new Lookup(MethodHandles.lookup()).findOwnStatic("exportScriptObject", Object.class, ScriptObject.class);
  139.29 +    private static final MethodHandle IMPORT_RESULT = new Lookup(MethodHandles.lookup()).findOwnStatic("importResult", Object.class, Object.class);
  139.30  
  139.31      private final BeansLinker beansLinker = new BeansLinker();
  139.32  
  139.33 @@ -67,8 +78,39 @@
  139.34          return delegateLinker.getGuardedInvocation(linkRequest, new NashornBeansLinkerServices(linkerServices));
  139.35      }
  139.36  
  139.37 -    static Object exportArgument(final Object arg) {
  139.38 -        return arg instanceof ConsString ? arg.toString() : arg;
  139.39 +    @SuppressWarnings("unused")
  139.40 +    private static Object exportArgument(final Object arg) {
  139.41 +        return exportArgument(arg, MIRROR_ALWAYS);
  139.42 +    }
  139.43 +
  139.44 +    @SuppressWarnings("unused")
  139.45 +    private static Object exportNativeArray(final NativeArray arg) {
  139.46 +        return exportArgument(arg, MIRROR_ALWAYS);
  139.47 +    }
  139.48 +
  139.49 +    @SuppressWarnings("unused")
  139.50 +    private static Object exportScriptObject(final ScriptObject arg) {
  139.51 +        return exportArgument(arg, MIRROR_ALWAYS);
  139.52 +    }
  139.53 +
  139.54 +    @SuppressWarnings("unused")
  139.55 +    private static Object exportScriptArray(final NativeArray arg) {
  139.56 +        return exportArgument(arg, MIRROR_ALWAYS);
  139.57 +    }
  139.58 +
  139.59 +    static Object exportArgument(final Object arg, final boolean mirrorAlways) {
  139.60 +        if (arg instanceof ConsString) {
  139.61 +            return arg.toString();
  139.62 +        } else if (mirrorAlways && arg instanceof ScriptObject) {
  139.63 +            return ScriptUtils.wrap((ScriptObject)arg);
  139.64 +        } else {
  139.65 +            return arg;
  139.66 +        }
  139.67 +    }
  139.68 +
  139.69 +    @SuppressWarnings("unused")
  139.70 +    private static Object importResult(final Object arg) {
  139.71 +        return ScriptUtils.unwrap(arg);
  139.72      }
  139.73  
  139.74      private static class NashornBeansLinkerServices implements LinkerServices {
  139.75 @@ -80,23 +122,50 @@
  139.76  
  139.77          @Override
  139.78          public MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
  139.79 -            final MethodHandle typed = linkerServices.asType(handle, fromType);
  139.80 -
  139.81              final MethodType handleType = handle.type();
  139.82              final int paramCount = handleType.parameterCount();
  139.83              assert fromType.parameterCount() == handleType.parameterCount();
  139.84  
  139.85 +            MethodType newFromType = fromType;
  139.86              MethodHandle[] filters = null;
  139.87              for(int i = 0; i < paramCount; ++i) {
  139.88 -                if(shouldConvert(handleType.parameterType(i), fromType.parameterType(i))) {
  139.89 -                    if(filters == null) {
  139.90 +                final MethodHandle filter = argConversionFilter(handleType.parameterType(i), fromType.parameterType(i));
  139.91 +                if (filter != null) {
  139.92 +                    if (filters == null) {
  139.93                          filters = new MethodHandle[paramCount];
  139.94                      }
  139.95 -                    filters[i] = EXPORT_ARGUMENT;
  139.96 +                    // "erase" specific type with Object type or else we'll get filter mismatch
  139.97 +                    newFromType = newFromType.changeParameterType(i, Object.class);
  139.98 +                    filters[i] = filter;
  139.99                  }
 139.100              }
 139.101  
 139.102 -            return filters != null ? MethodHandles.filterArguments(typed, 0, filters) : typed;
 139.103 +            final MethodHandle typed = linkerServices.asType(handle, newFromType);
 139.104 +            MethodHandle result = filters != null ? MethodHandles.filterArguments(typed, 0, filters) : typed;
 139.105 +            // Filter Object typed return value for possible ScriptObjectMirror. We convert
 139.106 +            // ScriptObjectMirror as ScriptObject (if it is mirror from current global).
 139.107 +            if (MIRROR_ALWAYS && areBothObjects(handleType.returnType(), fromType.returnType())) {
 139.108 +                result = MethodHandles.filterReturnValue(result, IMPORT_RESULT);
 139.109 +            }
 139.110 +
 139.111 +            return result;
 139.112 +        }
 139.113 +
 139.114 +        private static MethodHandle argConversionFilter(final Class<?> handleType, final Class<?> fromType) {
 139.115 +            if (handleType == Object.class) {
 139.116 +                if (fromType == Object.class) {
 139.117 +                    return EXPORT_ARGUMENT;
 139.118 +                } else if (fromType == NativeArray.class) {
 139.119 +                    return EXPORT_NATIVE_ARRAY;
 139.120 +                } else if (fromType == ScriptObject.class) {
 139.121 +                    return EXPORT_SCRIPT_OBJECT;
 139.122 +                }
 139.123 +            }
 139.124 +            return null;
 139.125 +        }
 139.126 +
 139.127 +        private static boolean areBothObjects(final Class<?> handleType, final Class<?> fromType) {
 139.128 +            return handleType == Object.class && fromType == Object.class;
 139.129          }
 139.130  
 139.131          @Override
 139.132 @@ -104,10 +173,6 @@
 139.133              return Implementation.asTypeLosslessReturn(this, handle, fromType);
 139.134          }
 139.135  
 139.136 -        private static boolean shouldConvert(final Class<?> handleType, final Class<?> fromType) {
 139.137 -            return handleType == Object.class && fromType == Object.class;
 139.138 -        }
 139.139 -
 139.140          @Override
 139.141          public MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
 139.142              return linkerServices.getTypeConverter(sourceType, targetType);
   140.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java	Mon Oct 27 14:36:13 2014 -0700
   140.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java	Thu Nov 06 09:50:15 2014 -0800
   140.3 @@ -292,7 +292,7 @@
   140.4  
   140.5      @SuppressWarnings("unused")
   140.6      private static Object createMirror(final Object obj) {
   140.7 -        return ScriptUtils.wrap(obj);
   140.8 +        return obj instanceof ScriptObject? ScriptUtils.wrap((ScriptObject)obj) : obj;
   140.9      }
  140.10  
  140.11      private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
   141.1 --- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Mon Oct 27 14:36:13 2014 -0700
   141.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Thu Nov 06 09:50:15 2014 -0800
   141.3 @@ -73,6 +73,7 @@
   141.4  type.error.not.an.object={0} is not an Object
   141.5  type.error.not.a.boolean={0} is not a Boolean
   141.6  type.error.not.a.date={0} is not a Date
   141.7 +type.error.not.a.java.importer={0} is not a JavaImporter object
   141.8  type.error.not.a.number={0} is not a Number
   141.9  type.error.not.a.regexp={0} is not a RegExp
  141.10  type.error.not.a.string={0} is not a String
   142.1 --- a/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js	Mon Oct 27 14:36:13 2014 -0700
   142.2 +++ b/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js	Thu Nov 06 09:50:15 2014 -0800
   142.3 @@ -105,7 +105,7 @@
   142.4          if (arguments.length < 1 || arguments.length > 2 ) {
   142.5              throw "sync(function [,object]) parameter count mismatch";
   142.6          }
   142.7 -        return Packages.jdk.nashorn.api.scripting.ScriptUtils.makeSynchronizedFunction(func, syncobj);
   142.8 +        return Java.synchronized(func, syncobj);
   142.9      }
  142.10  });
  142.11  
  142.12 @@ -160,7 +160,7 @@
  142.13      configurable: true, enumerable: false, writable: true,
  142.14      value: function(state) {
  142.15          if (! state) {
  142.16 -            state = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap());
  142.17 +            state = java.util.Collections.newSetFromMap(new java.util.HashMap());
  142.18          }
  142.19          if (state.contains(this)) {
  142.20              return "{}";
   143.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   143.2 +++ b/test/examples/getter-setter-micro.js	Thu Nov 06 09:50:15 2014 -0800
   143.3 @@ -0,0 +1,81 @@
   143.4 +/*
   143.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   143.6 + *
   143.7 + * Redistribution and use in source and binary forms, with or without
   143.8 + * modification, are permitted provided that the following conditions
   143.9 + * are met:
  143.10 + *
  143.11 + *   - Redistributions of source code must retain the above copyright
  143.12 + *     notice, this list of conditions and the following disclaimer.
  143.13 + *
  143.14 + *   - Redistributions in binary form must reproduce the above copyright
  143.15 + *     notice, this list of conditions and the following disclaimer in the
  143.16 + *     documentation and/or other materials provided with the distribution.
  143.17 + *
  143.18 + *   - Neither the name of Oracle nor the names of its
  143.19 + *     contributors may be used to endorse or promote products derived
  143.20 + *     from this software without specific prior written permission.
  143.21 + *
  143.22 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  143.23 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  143.24 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  143.25 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  143.26 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  143.27 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  143.28 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  143.29 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  143.30 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  143.31 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  143.32 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  143.33 + */
  143.34 +
  143.35 +/*
  143.36 + * A micro-benchmark for getters and setters with primitive values,
  143.37 + * alternating between ints and doubles. Introduction of primitive
  143.38 + * and optimistic user accessors in JDK-8062401 make this faster by
  143.39 + * 10x or more by allowing inlining and other optimizations to take place.
  143.40 + */
  143.41 +
  143.42 +var x = {
  143.43 +    get m() {
  143.44 +        return this._m;
  143.45 +    },
  143.46 +    set m(v) {
  143.47 +        this._m = v;
  143.48 +    },
  143.49 +    get n() {
  143.50 +        return this._n;
  143.51 +    },
  143.52 +    set n(v) {
  143.53 +        this._n = v;
  143.54 +    }
  143.55 +};
  143.56 +
  143.57 +
  143.58 +function bench(v1, v2, result) {
  143.59 +    var start = Date.now();
  143.60 +    x.n = v1;
  143.61 +    for (var i = 0; i < 1e8; i++) {
  143.62 +        x.m = v2;
  143.63 +        if (x.m + x.n !== result) {
  143.64 +            throw "wrong result";
  143.65 +        }
  143.66 +    }
  143.67 +    print("done in", Date.now() - start, "millis");
  143.68 +}
  143.69 +
  143.70 +for (var i = 0; i < 10; i++) {
  143.71 +    bench(i, 4, 4 + i);
  143.72 +}
  143.73 +
  143.74 +for (var i = 0; i < 10; i++) {
  143.75 +    bench(i, 4.5, 4.5 + i);
  143.76 +}
  143.77 +
  143.78 +for (var i = 0; i < 10; i++) {
  143.79 +    bench(i, 5, 5 + i);
  143.80 +}
  143.81 +
  143.82 +for (var i = 0; i < 10; i++) {
  143.83 +    bench(i, 5.5, 5.5 + i);
  143.84 +}
   144.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   144.2 +++ b/test/script/basic/JDK-8058610.js	Thu Nov 06 09:50:15 2014 -0800
   144.3 @@ -0,0 +1,77 @@
   144.4 +/*
   144.5 + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
   144.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   144.7 + * 
   144.8 + * This code is free software; you can redistribute it and/or modify it
   144.9 + * under the terms of the GNU General Public License version 2 only, as
  144.10 + * published by the Free Software Foundation.
  144.11 + * 
  144.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  144.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  144.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  144.15 + * version 2 for more details (a copy is included in the LICENSE file that
  144.16 + * accompanied this code).
  144.17 + * 
  144.18 + * You should have received a copy of the GNU General Public License version
  144.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  144.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  144.21 + * 
  144.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  144.23 + * or visit www.oracle.com if you need additional information or have any
  144.24 + * questions.
  144.25 + */
  144.26 +
  144.27 +/**
  144.28 + * JDK-8058610: must not let long operations overflow
  144.29 + *
  144.30 + * @test
  144.31 + * @run
  144.32 + */
  144.33 +
  144.34 +function mul(x) { 
  144.35 +    return x.foo * x.bar; 
  144.36 +} 
  144.37 +print("=== mul ===")
  144.38 +print(mul({foo: 2147483647,  bar: 2147483647})); // 2^31
  144.39 +print(mul({foo: 17179869184, bar: 2147483647})); // 2^34
  144.40 +
  144.41 +function self_mul(x) {
  144.42 +    return x.foo *= x.bar; 
  144.43 +}
  144.44 +print("=== self_mul ===")
  144.45 +print(self_mul({foo: 2147483647,  bar: 2147483647})); // 2^31
  144.46 +print(self_mul({foo: 17179869184, bar: 2147483647})); // 2^34
  144.47 +
  144.48 +// We'll need to use this function to obtain long values larger in 
  144.49 +// magnitude than those precisely representable in a double (2^53), 
  144.50 +// as Nashorn's parser will reify such literals as a double. For 
  144.51 +// overflow on add and sub we need (2^63)-1.
  144.52 +var parseLong = Java.type("java.lang.Long").parseLong;
  144.53 +
  144.54 +function sub(x) {
  144.55 +    return x.foo - x.bar;
  144.56 +}
  144.57 +print("=== sub ===")
  144.58 +print(sub({foo: 2147483647,  bar: -2147483647})); // 2^31
  144.59 +print(sub({foo: parseLong("9223372036854775807"), bar: parseLong("-9223372036854775807")})); // 2^63-1
  144.60 +
  144.61 +function self_sub(x) {
  144.62 +    return x.foo -= x.bar;
  144.63 +}
  144.64 +print("=== self_sub ===")
  144.65 +print(self_sub({foo: 2147483647,  bar: -2147483647})); // 2^31
  144.66 +print(self_sub({foo: parseLong("9223372036854775807"), bar: parseLong("-9223372036854775807")})); // 2^63-1
  144.67 +
  144.68 +function add(x) {
  144.69 +    return x.foo + x.bar;
  144.70 +}
  144.71 +print("=== add ===")
  144.72 +print(add({foo: 2147483647,  bar: 2147483647})); // 2^31
  144.73 +print(add({foo: parseLong("9223372036854775807"), bar: parseLong("9223372036854775807")})); // 2^63-1
  144.74 +
  144.75 +function self_add(x) {
  144.76 +    return x.foo += x.bar;
  144.77 +}
  144.78 +print("=== self_add ===")
  144.79 +print(self_add({foo: 2147483647,  bar: 2147483647})); // 2^31
  144.80 +print(self_add({foo: parseLong("9223372036854775807"), bar: parseLong("9223372036854775807")})); // 2^63-1
   145.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   145.2 +++ b/test/script/basic/JDK-8058610.js.EXPECTED	Thu Nov 06 09:50:15 2014 -0800
   145.3 @@ -0,0 +1,18 @@
   145.4 +=== mul ===
   145.5 +4611686014132420600
   145.6 +36893488130239234000
   145.7 +=== self_mul ===
   145.8 +4611686014132420600
   145.9 +36893488130239234000
  145.10 +=== sub ===
  145.11 +4294967294
  145.12 +18446744073709552000
  145.13 +=== self_sub ===
  145.14 +4294967294
  145.15 +18446744073709552000
  145.16 +=== add ===
  145.17 +4294967294
  145.18 +18446744073709552000
  145.19 +=== self_add ===
  145.20 +4294967294
  145.21 +18446744073709552000
   146.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   146.2 +++ b/test/script/basic/JDK-8060011.js	Thu Nov 06 09:50:15 2014 -0800
   146.3 @@ -0,0 +1,58 @@
   146.4 +/*
   146.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   146.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   146.7 + * 
   146.8 + * This code is free software; you can redistribute it and/or modify it
   146.9 + * under the terms of the GNU General Public License version 2 only, as
  146.10 + * published by the Free Software Foundation.
  146.11 + * 
  146.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  146.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  146.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  146.15 + * version 2 for more details (a copy is included in the LICENSE file that
  146.16 + * accompanied this code).
  146.17 + * 
  146.18 + * You should have received a copy of the GNU General Public License version
  146.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  146.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  146.21 + * 
  146.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  146.23 + * or visit www.oracle.com if you need additional information or have any
  146.24 + * questions.
  146.25 + */
  146.26 +
  146.27 +/**
  146.28 + * JDK-8060011: Concatenating an array and converting it to Java gives wrong result
  146.29 + *
  146.30 + * @test
  146.31 + * @run
  146.32 + */
  146.33 +
  146.34 +
  146.35 +function compareAsJavaArrays(a1, a2) {
  146.36 +    var ja1 = Java.to(a1);
  146.37 +    var ja2 = Java.to(a2);
  146.38 +    if (ja1.length !== ja2.length) {
  146.39 +        throw "different length";
  146.40 +    }
  146.41 +    for (var i = 0; i < ja1.length; i++) {
  146.42 +        if (ja1[i] !== ja2[i]) {
  146.43 +            throw "different element at " + i;
  146.44 +        }
  146.45 +    }
  146.46 +    if (java.util.Arrays.toString(ja1) !== java.util.Arrays.toString(ja2)) {
  146.47 +        throw "different string representation";
  146.48 +    }
  146.49 +}
  146.50 +
  146.51 +compareAsJavaArrays([0, 1, 2, 3],
  146.52 +                    [0].concat([1, 2, 3]));
  146.53 +compareAsJavaArrays([1000000000, 2000000000, 3000000000, 4000000000],
  146.54 +                    [1000000000].concat([2000000000, 3000000000, 4000000000]));
  146.55 +compareAsJavaArrays([0.5, 1.5, 2.5, 3.5],
  146.56 +                    [0.5].concat([1.5, 2.5, 3.5]));
  146.57 +compareAsJavaArrays(["0", "1", "2", "3"],
  146.58 +                    ["0"].concat(["1", "2", "3"]));
  146.59 +
  146.60 +
  146.61 +
   147.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   147.2 +++ b/test/script/basic/JDK-8060101.js	Thu Nov 06 09:50:15 2014 -0800
   147.3 @@ -0,0 +1,54 @@
   147.4 +/*
   147.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   147.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   147.7 + *
   147.8 + * This code is free software; you can redistribute it and/or modify it
   147.9 + * under the terms of the GNU General Public License version 2 only, as
  147.10 + * published by the Free Software Foundation.
  147.11 + *
  147.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  147.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  147.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  147.15 + * version 2 for more details (a copy is included in the LICENSE file that
  147.16 + * accompanied this code).
  147.17 + *
  147.18 + * You should have received a copy of the GNU General Public License version
  147.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  147.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  147.21 + *
  147.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  147.23 + * or visit www.oracle.com if you need additional information or have any
  147.24 + * questions.
  147.25 + */
  147.26 +
  147.27 +/**
  147.28 + * JDK-8060101: AssertionError: __noSuchProperty__ placeholder called from NativeJavaImporter
  147.29 + *
  147.30 + * @test
  147.31 + * @run
  147.32 + */
  147.33 +
  147.34 +var constant = 0.50;
  147.35 +var ind = 0.0;
  147.36 +
  147.37 +// make sure callsites are exercised quite a few times
  147.38 +// to induce megamorphic callsite for with/JavaImporter
  147.39 +// combo - which triggered that AssertionError.
  147.40 +for (var i = 0; i < 50; i++) {
  147.41 +    var math = new JavaImporter(java.lang.StrictMath);
  147.42 +    ind += 10.0;
  147.43 +    with (math) {
  147.44 +        StrictMath.exp(-constant*ind);
  147.45 +    }
  147.46 +}
  147.47 +
  147.48 +for (var i = 0; i < 50; i++) {
  147.49 +    var math = new JavaImporter(java.lang.StrictMath);
  147.50 +    try {
  147.51 +        math.Foo();
  147.52 +    } catch (e) {
  147.53 +        if (! (e instanceof TypeError)) {
  147.54 +            throw e;
  147.55 +        }
  147.56 +    }
  147.57 +}
   148.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   148.2 +++ b/test/script/basic/JDK-8061113.js	Thu Nov 06 09:50:15 2014 -0800
   148.3 @@ -0,0 +1,35 @@
   148.4 +/*
   148.5 + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
   148.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   148.7 + * 
   148.8 + * This code is free software; you can redistribute it and/or modify it
   148.9 + * under the terms of the GNU General Public License version 2 only, as
  148.10 + * published by the Free Software Foundation.
  148.11 + * 
  148.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  148.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  148.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  148.15 + * version 2 for more details (a copy is included in the LICENSE file that
  148.16 + * accompanied this code).
  148.17 + * 
  148.18 + * You should have received a copy of the GNU General Public License version
  148.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  148.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  148.21 + * 
  148.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  148.23 + * or visit www.oracle.com if you need additional information or have any
  148.24 + * questions.
  148.25 + */
  148.26 +
  148.27 +/**
  148.28 + * JDK-8061113: Boolean used as optimistic call return type
  148.29 + *
  148.30 + * @test
  148.31 + * @run
  148.32 + */
  148.33 +
  148.34 +function testcase() {
  148.35 +    var a = {x:0};
  148.36 +    return (function () {return a.x === 0})();
  148.37 +}
  148.38 +print(testcase());
   149.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   149.2 +++ b/test/script/basic/JDK-8061113.js.EXPECTED	Thu Nov 06 09:50:15 2014 -0800
   149.3 @@ -0,0 +1,1 @@
   149.4 +true
   150.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   150.2 +++ b/test/script/basic/JDK-8061391.js	Thu Nov 06 09:50:15 2014 -0800
   150.3 @@ -0,0 +1,151 @@
   150.4 +/*
   150.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   150.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   150.7 + *
   150.8 + * This code is free software; you can redistribute it and/or modify it
   150.9 + * under the terms of the GNU General Public License version 2 only, as
  150.10 + * published by the Free Software Foundation.
  150.11 + *
  150.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  150.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  150.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  150.15 + * version 2 for more details (a copy is included in the LICENSE file that
  150.16 + * accompanied this code).
  150.17 + *
  150.18 + * You should have received a copy of the GNU General Public License version
  150.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  150.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  150.21 + *
  150.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  150.23 + * or visit www.oracle.com if you need additional information or have any
  150.24 + * questions.
  150.25 + */
  150.26 +
  150.27 +/**
  150.28 + * JDK-8061391 - Checks that the optimistic builtin for concat is semantically
  150.29 + * correct.
  150.30 + *
  150.31 + * @test
  150.32 + * @run
  150.33 + */
  150.34 +
  150.35 +var maxJavaInt = 0x7fffffff;
  150.36 +
  150.37 +var ia = [1, 2, 3, 4];
  150.38 +var la = [maxJavaInt + 1000, maxJavaInt + 2000, maxJavaInt + 3000, maxJavaInt + 4000];
  150.39 +var da = [1.1, 2.2, 3.3, 4.4];
  150.40 +var oa = ["one", "two", "three", "four"];  
  150.41 +
  150.42 +var aa = [ia, la, da, oa];
  150.43 +
  150.44 +function concats() {
  150.45 +    print("shared callsite");
  150.46 +
  150.47 +    print(ia);
  150.48 +    print(la);
  150.49 +    print(da);
  150.50 +    print(oa);
  150.51 +    print(aa);
  150.52 +    
  150.53 +    for (var i = 0; i < aa.length; i++) {
  150.54 +	print(aa[i].concat(aa[i][0]));
  150.55 +	for (var j = 0; j < aa.length ; j++) {
  150.56 +	    print(aa[i].concat(aa[j]));
  150.57 +	}
  150.58 +    }
  150.59 +}
  150.60 +
  150.61 +function concats_inline() {
  150.62 +    print("separate callsites");
  150.63 +
  150.64 +    print(ia);
  150.65 +    print(la);
  150.66 +    print(da);
  150.67 +    print(oa);
  150.68 +    print(aa);
  150.69 +    
  150.70 +    print(aa[0].concat(aa[0]));
  150.71 +    print(aa[0].concat(aa[1]));
  150.72 +    print(aa[0].concat(aa[2]));
  150.73 +    print(aa[0].concat(aa[3]));
  150.74 +    print(aa[0].concat(aa[0][0]));    
  150.75 +
  150.76 +    print(aa[1].concat(aa[0]));
  150.77 +    print(aa[1].concat(aa[1]));
  150.78 +    print(aa[1].concat(aa[2]));
  150.79 +    print(aa[1].concat(aa[3]));
  150.80 +    print(aa[1].concat(aa[1][0]));    
  150.81 +
  150.82 +    print(aa[2].concat(aa[0]));
  150.83 +    print(aa[2].concat(aa[1]));
  150.84 +    print(aa[2].concat(aa[2]));
  150.85 +    print(aa[2].concat(aa[3]));
  150.86 +    print(aa[2].concat(aa[2][0]));    
  150.87 +
  150.88 +    print(aa[3].concat(aa[0]));
  150.89 +    print(aa[3].concat(aa[1]));
  150.90 +    print(aa[3].concat(aa[2]));
  150.91 +    print(aa[3].concat(aa[3]));
  150.92 +    print(aa[3].concat(aa[3][0]));    
  150.93 +}
  150.94 +
  150.95 +concats();
  150.96 +concats_inline();
  150.97 +
  150.98 +print();
  150.99 +var oldia = ia.slice(0); //clone ia
 150.100 +print("oldia = " + oldia);
 150.101 +ia[10] = "sparse";
 150.102 +print("oldia = " + oldia);
 150.103 +
 150.104 +print();
 150.105 +print("Redoing with sparse arrays");
 150.106 +
 150.107 +concats();
 150.108 +concats_inline();
 150.109 +
 150.110 +ia = oldia;
 150.111 +print("Restored ia = " + ia);
 150.112 +
 150.113 +function concat_expand() {
 150.114 +    print("concat type expansion");
 150.115 +    print(ia.concat(la));
 150.116 +    print(ia.concat(da));
 150.117 +    print(ia.concat(oa));
 150.118 +    print(la.concat(ia));
 150.119 +    print(la.concat(da));
 150.120 +    print(la.concat(oa));
 150.121 +    print(da.concat(ia));
 150.122 +    print(da.concat(la));
 150.123 +    print(da.concat(oa));
 150.124 +}
 150.125 +
 150.126 +print();
 150.127 +concat_expand();
 150.128 +
 150.129 +print();
 150.130 +
 150.131 +function concat_varargs() {
 150.132 +    print("concat varargs");
 150.133 +    print(ia.concat(la)); //fast
 150.134 +    print(ia.concat(la, da, oa)); //slow
 150.135 +    var slow = ia.concat(1, maxJavaInt * 2, 4711.17, function() { print("hello, world") }); //slow
 150.136 +    print(slow);
 150.137 +    return slow;
 150.138 +}
 150.139 +
 150.140 +var slow = concat_varargs();
 150.141 +
 150.142 +print();
 150.143 +print("sanity checks");
 150.144 +slow.map(
 150.145 +	 function(elem) {
 150.146 +	     if (elem instanceof Function) {
 150.147 +		 elem();
 150.148 +	     } else {
 150.149 +		 print((typeof elem) + " = " + elem);
 150.150 +	     }
 150.151 +	 });
 150.152 +
 150.153 +print(ia.concat({key: "value"}));
 150.154 +print(ia.concat({key: "value"}, {key2: "value2"}));
   151.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   151.2 +++ b/test/script/basic/JDK-8061391.js.EXPECTED	Thu Nov 06 09:50:15 2014 -0800
   151.3 @@ -0,0 +1,138 @@
   151.4 +shared callsite
   151.5 +1,2,3,4
   151.6 +2147484647,2147485647,2147486647,2147487647
   151.7 +1.1,2.2,3.3,4.4
   151.8 +one,two,three,four
   151.9 +1,2,3,4,2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4,one,two,three,four
  151.10 +1,2,3,4,1
  151.11 +1,2,3,4,1,2,3,4
  151.12 +1,2,3,4,2147484647,2147485647,2147486647,2147487647
  151.13 +1,2,3,4,1.1,2.2,3.3,4.4
  151.14 +1,2,3,4,one,two,three,four
  151.15 +2147484647,2147485647,2147486647,2147487647,2147484647
  151.16 +2147484647,2147485647,2147486647,2147487647,1,2,3,4
  151.17 +2147484647,2147485647,2147486647,2147487647,2147484647,2147485647,2147486647,2147487647
  151.18 +2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4
  151.19 +2147484647,2147485647,2147486647,2147487647,one,two,three,four
  151.20 +1.1,2.2,3.3,4.4,1.1
  151.21 +1.1,2.2,3.3,4.4,1,2,3,4
  151.22 +1.1,2.2,3.3,4.4,2147484647,2147485647,2147486647,2147487647
  151.23 +1.1,2.2,3.3,4.4,1.1,2.2,3.3,4.4
  151.24 +1.1,2.2,3.3,4.4,one,two,three,four
  151.25 +one,two,three,four,one
  151.26 +one,two,three,four,1,2,3,4
  151.27 +one,two,three,four,2147484647,2147485647,2147486647,2147487647
  151.28 +one,two,three,four,1.1,2.2,3.3,4.4
  151.29 +one,two,three,four,one,two,three,four
  151.30 +separate callsites
  151.31 +1,2,3,4
  151.32 +2147484647,2147485647,2147486647,2147487647
  151.33 +1.1,2.2,3.3,4.4
  151.34 +one,two,three,four
  151.35 +1,2,3,4,2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4,one,two,three,four
  151.36 +1,2,3,4,1,2,3,4
  151.37 +1,2,3,4,2147484647,2147485647,2147486647,2147487647
  151.38 +1,2,3,4,1.1,2.2,3.3,4.4
  151.39 +1,2,3,4,one,two,three,four
  151.40 +1,2,3,4,1
  151.41 +2147484647,2147485647,2147486647,2147487647,1,2,3,4
  151.42 +2147484647,2147485647,2147486647,2147487647,2147484647,2147485647,2147486647,2147487647
  151.43 +2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4
  151.44 +2147484647,2147485647,2147486647,2147487647,one,two,three,four
  151.45 +2147484647,2147485647,2147486647,2147487647,2147484647
  151.46 +1.1,2.2,3.3,4.4,1,2,3,4
  151.47 +1.1,2.2,3.3,4.4,2147484647,2147485647,2147486647,2147487647
  151.48 +1.1,2.2,3.3,4.4,1.1,2.2,3.3,4.4
  151.49 +1.1,2.2,3.3,4.4,one,two,three,four
  151.50 +1.1,2.2,3.3,4.4,1.1
  151.51 +one,two,three,four,1,2,3,4
  151.52 +one,two,three,four,2147484647,2147485647,2147486647,2147487647
  151.53 +one,two,three,four,1.1,2.2,3.3,4.4
  151.54 +one,two,three,four,one,two,three,four
  151.55 +one,two,three,four,one
  151.56 +
  151.57 +oldia = 1,2,3,4
  151.58 +oldia = 1,2,3,4
  151.59 +
  151.60 +Redoing with sparse arrays
  151.61 +shared callsite
  151.62 +1,2,3,4,,,,,,,sparse
  151.63 +2147484647,2147485647,2147486647,2147487647
  151.64 +1.1,2.2,3.3,4.4
  151.65 +one,two,three,four
  151.66 +1,2,3,4,,,,,,,sparse,2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4,one,two,three,four
  151.67 +1,2,3,4,,,,,,,sparse,1
  151.68 +1,2,3,4,,,,,,,sparse,1,2,3,4,,,,,,,sparse
  151.69 +1,2,3,4,,,,,,,sparse,2147484647,2147485647,2147486647,2147487647
  151.70 +1,2,3,4,,,,,,,sparse,1.1,2.2,3.3,4.4
  151.71 +1,2,3,4,,,,,,,sparse,one,two,three,four
  151.72 +2147484647,2147485647,2147486647,2147487647,2147484647
  151.73 +2147484647,2147485647,2147486647,2147487647,1,2,3,4,,,,,,,sparse
  151.74 +2147484647,2147485647,2147486647,2147487647,2147484647,2147485647,2147486647,2147487647
  151.75 +2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4
  151.76 +2147484647,2147485647,2147486647,2147487647,one,two,three,four
  151.77 +1.1,2.2,3.3,4.4,1.1
  151.78 +1.1,2.2,3.3,4.4,1,2,3,4,,,,,,,sparse
  151.79 +1.1,2.2,3.3,4.4,2147484647,2147485647,2147486647,2147487647
  151.80 +1.1,2.2,3.3,4.4,1.1,2.2,3.3,4.4
  151.81 +1.1,2.2,3.3,4.4,one,two,three,four
  151.82 +one,two,three,four,one
  151.83 +one,two,three,four,1,2,3,4,,,,,,,sparse
  151.84 +one,two,three,four,2147484647,2147485647,2147486647,2147487647
  151.85 +one,two,three,four,1.1,2.2,3.3,4.4
  151.86 +one,two,three,four,one,two,three,four
  151.87 +separate callsites
  151.88 +1,2,3,4,,,,,,,sparse
  151.89 +2147484647,2147485647,2147486647,2147487647
  151.90 +1.1,2.2,3.3,4.4
  151.91 +one,two,three,four
  151.92 +1,2,3,4,,,,,,,sparse,2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4,one,two,three,four
  151.93 +1,2,3,4,,,,,,,sparse,1,2,3,4,,,,,,,sparse
  151.94 +1,2,3,4,,,,,,,sparse,2147484647,2147485647,2147486647,2147487647
  151.95 +1,2,3,4,,,,,,,sparse,1.1,2.2,3.3,4.4
  151.96 +1,2,3,4,,,,,,,sparse,one,two,three,four
  151.97 +1,2,3,4,,,,,,,sparse,1
  151.98 +2147484647,2147485647,2147486647,2147487647,1,2,3,4,,,,,,,sparse
  151.99 +2147484647,2147485647,2147486647,2147487647,2147484647,2147485647,2147486647,2147487647
 151.100 +2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4
 151.101 +2147484647,2147485647,2147486647,2147487647,one,two,three,four
 151.102 +2147484647,2147485647,2147486647,2147487647,2147484647
 151.103 +1.1,2.2,3.3,4.4,1,2,3,4,,,,,,,sparse
 151.104 +1.1,2.2,3.3,4.4,2147484647,2147485647,2147486647,2147487647
 151.105 +1.1,2.2,3.3,4.4,1.1,2.2,3.3,4.4
 151.106 +1.1,2.2,3.3,4.4,one,two,three,four
 151.107 +1.1,2.2,3.3,4.4,1.1
 151.108 +one,two,three,four,1,2,3,4,,,,,,,sparse
 151.109 +one,two,three,four,2147484647,2147485647,2147486647,2147487647
 151.110 +one,two,three,four,1.1,2.2,3.3,4.4
 151.111 +one,two,three,four,one,two,three,four
 151.112 +one,two,three,four,one
 151.113 +Restored ia = 1,2,3,4
 151.114 +
 151.115 +concat type expansion
 151.116 +1,2,3,4,2147484647,2147485647,2147486647,2147487647
 151.117 +1,2,3,4,1.1,2.2,3.3,4.4
 151.118 +1,2,3,4,one,two,three,four
 151.119 +2147484647,2147485647,2147486647,2147487647,1,2,3,4
 151.120 +2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4
 151.121 +2147484647,2147485647,2147486647,2147487647,one,two,three,four
 151.122 +1.1,2.2,3.3,4.4,1,2,3,4
 151.123 +1.1,2.2,3.3,4.4,2147484647,2147485647,2147486647,2147487647
 151.124 +1.1,2.2,3.3,4.4,one,two,three,four
 151.125 +
 151.126 +concat varargs
 151.127 +1,2,3,4,2147484647,2147485647,2147486647,2147487647
 151.128 +1,2,3,4,2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4,one,two,three,four
 151.129 +1,2,3,4,1,4294967294,4711.17,function() { print("hello, world") }
 151.130 +
 151.131 +sanity checks
 151.132 +number = 1
 151.133 +number = 2
 151.134 +number = 3
 151.135 +number = 4
 151.136 +number = 1
 151.137 +number = 4294967294
 151.138 +number = 4711.17
 151.139 +hello, world
 151.140 +1,2,3,4,[object Object]
 151.141 +1,2,3,4,[object Object],[object Object]
   152.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   152.2 +++ b/test/script/basic/JDK-8061391_2.js	Thu Nov 06 09:50:15 2014 -0800
   152.3 @@ -0,0 +1,52 @@
   152.4 +/*
   152.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
   152.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   152.7 + *
   152.8 + * This code is free software; you can redistribute it and/or modify it
   152.9 + * under the terms of the GNU General Public License version 2 only, as
  152.10 + * published by the Free Software Foundation.
  152.11 + *
  152.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  152.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  152.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  152.15 + * version 2 for more details (a copy is included in the LICENSE file that
  152.16 + * accompanied this code).
  152.17 + *
  152.18 + * You should have received a copy of the GNU General Public License version
  152.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  152.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  152.21 + *
  152.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  152.23 + * or visit www.oracle.com if you need additional information or have any
  152.24 + * questions.
  152.25 + */
  152.26 +
  152.27 +/**
  152.28 + * Array extension check
  152.29 + *
  152.30 + * @test
  152.31 + * @run
  152.32 + */
  152.33 +
  152.34 +"use strict";
  152.35 +var a = [1,2,3];
  152.36 +Object.preventExtensions(a);
  152.37 +try {
  152.38 +    a[4] = 4;
  152.39 +    print(a);
  152.40 +} catch (e) {
  152.41 +    if (!(e instanceof TypeError)) {
  152.42 +	print("TypeError expected but got e");
  152.43 +    }
  152.44 +}
  152.45 +
  152.46 +if (a[0] != 1) {
  152.47 +    throw "element 0 is wrong";
  152.48 +}
  152.49 +if (a[1] != 2) {
  152.50 +    throw "element 1 is wrong";
  152.51 +}
  152.52 +if (a[2] != 3) {
  152.53 +    throw "element 2 is wrong";
  152.54 +}
  152.55 +
   153.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   153.2 +++ b/test/script/basic/JDK-8061391_3.js	Thu Nov 06 09:50:15 2014 -0800
   153.3 @@ -0,0 +1,44 @@
   153.4 +/*
   153.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
   153.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   153.7 + *
   153.8 + * This code is free software; you can redistribute it and/or modify it
   153.9 + * under the terms of the GNU General Public License version 2 only, as
  153.10 + * published by the Free Software Foundation.
  153.11 + *
  153.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  153.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  153.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  153.15 + * version 2 for more details (a copy is included in the LICENSE file that
  153.16 + * accompanied this code).
  153.17 + *
  153.18 + * You should have received a copy of the GNU General Public License version
  153.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  153.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  153.21 + *
  153.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  153.23 + * or visit www.oracle.com if you need additional information or have any
  153.24 + * questions.
  153.25 + */
  153.26 +
  153.27 +/**
  153.28 + * Array extension check
  153.29 + *
  153.30 + * @test
  153.31 + * @run
  153.32 + */
  153.33 +
  153.34 +var a = [1,2,3];
  153.35 +Object.preventExtensions(a);
  153.36 +a[4] = 4;
  153.37 +print(a);
  153.38 +if (a[0] != 1) {
  153.39 +    throw "element 0 is wrong";
  153.40 +}
  153.41 +if (a[1] != 2) {
  153.42 +    throw "element 1 is wrong";
  153.43 +}
  153.44 +if (a[2] != 3) {
  153.45 +    throw "element 2 is wrong";
  153.46 +}
  153.47 +
   154.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   154.2 +++ b/test/script/basic/JDK-8061391_3.js.EXPECTED	Thu Nov 06 09:50:15 2014 -0800
   154.3 @@ -0,0 +1,1 @@
   154.4 +1,2,3
   155.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   155.2 +++ b/test/script/basic/JDK-8062024.js	Thu Nov 06 09:50:15 2014 -0800
   155.3 @@ -0,0 +1,40 @@
   155.4 +/*
   155.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   155.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   155.7 + *
   155.8 + * This code is free software; you can redistribute it and/or modify it
   155.9 + * under the terms of the GNU General Public License version 2 only, as
  155.10 + * published by the Free Software Foundation.
  155.11 + *
  155.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  155.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  155.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  155.15 + * version 2 for more details (a copy is included in the LICENSE file that
  155.16 + * accompanied this code).
  155.17 + *
  155.18 + * You should have received a copy of the GNU General Public License version
  155.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  155.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  155.21 + *
  155.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  155.23 + * or visit www.oracle.com if you need additional information or have any
  155.24 + * questions.
  155.25 + */
  155.26 +
  155.27 +/**
  155.28 + * JDK-8062024: Issue with date.setFullYear when time other than midnight
  155.29 + *
  155.30 + * @test
  155.31 + * @option -timezone=Asia/Calcutta
  155.32 + * @run
  155.33 + */
  155.34 +
  155.35 +var date1 = new Date("January 01, 1950 00:00:00");
  155.36 +print("Before:", date1);
  155.37 +date1.setFullYear(1960);
  155.38 +print("After:", date1);
  155.39 +
  155.40 +var date2 = new Date("January 01, 1950 00:00:01");
  155.41 +print("Before:", date2);
  155.42 +date2.setFullYear(1960);
  155.43 +print("After:", date2);
   156.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   156.2 +++ b/test/script/basic/JDK-8062024.js.EXPECTED	Thu Nov 06 09:50:15 2014 -0800
   156.3 @@ -0,0 +1,4 @@
   156.4 +Before: Sun Jan 01 1950 00:00:00 GMT+0530 (IST)
   156.5 +After: Fri Jan 01 1960 00:00:00 GMT+0530 (IST)
   156.6 +Before: Sun Jan 01 1950 00:00:01 GMT+0530 (IST)
   156.7 +After: Fri Jan 01 1960 00:00:01 GMT+0530 (IST)
   157.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   157.2 +++ b/test/script/basic/JDK-8062132.js	Thu Nov 06 09:50:15 2014 -0800
   157.3 @@ -0,0 +1,80 @@
   157.4 +/*
   157.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
   157.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   157.7 + * 
   157.8 + * This code is free software; you can redistribute it and/or modify it
   157.9 + * under the terms of the GNU General Public License version 2 only, as
  157.10 + * published by the Free Software Foundation.
  157.11 + * 
  157.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  157.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  157.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  157.15 + * version 2 for more details (a copy is included in the LICENSE file that
  157.16 + * accompanied this code).
  157.17 + * 
  157.18 + * You should have received a copy of the GNU General Public License version
  157.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  157.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  157.21 + * 
  157.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  157.23 + * or visit www.oracle.com if you need additional information or have any
  157.24 + * questions.
  157.25 + */
  157.26 +
  157.27 +/**
  157.28 + * 8062132: Nashorn incorrectly binds "this" for constructor created by another function
  157.29 + *
  157.30 + * @test
  157.31 + * @run
  157.32 + */
  157.33 +
  157.34 +function subclass(parentCtor, proto) {
  157.35 +    function C() {
  157.36 +        parentCtor.call(this);
  157.37 +    }
  157.38 +
  157.39 +    C.prototype = Object.create(parentCtor.prototype);
  157.40 +
  157.41 +    for (var prop in proto) {
  157.42 +        if (proto.hasOwnProperty(prop)) {
  157.43 +            C.prototype[prop] = proto[prop];
  157.44 +        }
  157.45 +    }
  157.46 +
  157.47 +    return C;
  157.48 +}
  157.49 +
  157.50 +var Parent = function() {
  157.51 +    this.init();
  157.52 +};
  157.53 +
  157.54 +Parent.prototype = {
  157.55 +    init: null
  157.56 +};
  157.57 +
  157.58 +var Child1 = subclass(Parent, {
  157.59 +    prop1: 1,
  157.60 +    init: function() {
  157.61 +        print('child 1');
  157.62 +    }
  157.63 +});
  157.64 +
  157.65 +var Child2 = subclass(Parent, {
  157.66 +    init: function() {
  157.67 +        print('child 2');
  157.68 +    }
  157.69 +});
  157.70 +
  157.71 +var Child3 = subclass(Parent, {
  157.72 +    prop1: 1,
  157.73 +    init: function() {
  157.74 +        print('child 3');
  157.75 +    }
  157.76 +});
  157.77 +
  157.78 +new Child1();
  157.79 +new Child2();
  157.80 +new Child3();
  157.81 +new Child1();
  157.82 +new Child2();
  157.83 +new Child3();
   158.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   158.2 +++ b/test/script/basic/JDK-8062132.js.EXPECTED	Thu Nov 06 09:50:15 2014 -0800
   158.3 @@ -0,0 +1,6 @@
   158.4 +child 1
   158.5 +child 2
   158.6 +child 3
   158.7 +child 1
   158.8 +child 2
   158.9 +child 3
   159.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   159.2 +++ b/test/script/basic/JDK-8062583.js	Thu Nov 06 09:50:15 2014 -0800
   159.3 @@ -0,0 +1,51 @@
   159.4 +/*
   159.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   159.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   159.7 + * 
   159.8 + * This code is free software; you can redistribute it and/or modify it
   159.9 + * under the terms of the GNU General Public License version 2 only, as
  159.10 + * published by the Free Software Foundation.
  159.11 + * 
  159.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  159.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  159.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  159.15 + * version 2 for more details (a copy is included in the LICENSE file that
  159.16 + * accompanied this code).
  159.17 + * 
  159.18 + * You should have received a copy of the GNU General Public License version
  159.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  159.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  159.21 + * 
  159.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  159.23 + * or visit www.oracle.com if you need additional information or have any
  159.24 + * questions.
  159.25 + */
  159.26 +
  159.27 +/**
  159.28 + * JDK-8062583: Throwing object with error prototype causes error proto to be caught
  159.29 + *
  159.30 + * @test
  159.31 + * @run
  159.32 + */
  159.33 +
  159.34 +function CustomError() {
  159.35 +    this.name = "CustomError";
  159.36 +}
  159.37 +
  159.38 +CustomError.prototype = new Error();
  159.39 +
  159.40 +var c1 = new CustomError();
  159.41 +
  159.42 +try {
  159.43 +    throw c1;
  159.44 +} catch (e) {
  159.45 +    print(e === c1);
  159.46 +    print(e === CustomError.prototype);
  159.47 +    print(e.stack.replace(/\\/g, '/'));
  159.48 +    print(e.nashornException.toString().replace(/\\/g, '/'));
  159.49 +}
  159.50 +
  159.51 +var c2 = new CustomError();
  159.52 +Error.captureStackTrace(c2);
  159.53 +print(c2.stack.replace(/\\/g, '/'));
  159.54 +print(c2.nashornException.toString().replace(/\\/g, '/'));
   160.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   160.2 +++ b/test/script/basic/JDK-8062583.js.EXPECTED	Thu Nov 06 09:50:15 2014 -0800
   160.3 @@ -0,0 +1,8 @@
   160.4 +true
   160.5 +false
   160.6 +CustomError
   160.7 +	at <program> (test/script/basic/JDK-8062583.js:40)
   160.8 +test/script/basic/JDK-8062583.js:40:4 CustomError
   160.9 +CustomError
  160.10 +	at <program> (test/script/basic/JDK-8062583.js:49)
  160.11 +test/script/basic/JDK-8062583.js:49 CustomError
   161.1 --- a/test/script/basic/convert.js	Mon Oct 27 14:36:13 2014 -0700
   161.2 +++ b/test/script/basic/convert.js	Thu Nov 06 09:50:15 2014 -0800
   161.3 @@ -42,7 +42,7 @@
   161.4  
   161.5  // object to Map
   161.6  obj = { foo: 333, bar: 'hello'};
   161.7 -var map = ScriptUtils.convert(obj, java.util.Map.class);
   161.8 +var map = ScriptUtils.wrap(obj);
   161.9  print(map instanceof java.util.Map);
  161.10  for (m in map) {
  161.11     print(m + " " + map[m]);
   162.1 --- a/test/script/nosecurity/JDK-8044798.js	Mon Oct 27 14:36:13 2014 -0700
   162.2 +++ b/test/script/nosecurity/JDK-8044798.js	Thu Nov 06 09:50:15 2014 -0800
   162.3 @@ -25,6 +25,8 @@
   162.4   * JDK-8044798: API for debugging Nashorn
   162.5   *
   162.6   * @test
   162.7 + * @option -Dnashorn.mirror.always=false
   162.8 + * @fork
   162.9   * @run
  162.10   */
  162.11  
   163.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   163.2 +++ b/test/script/nosecurity/JDK-8060688.js	Thu Nov 06 09:50:15 2014 -0800
   163.3 @@ -0,0 +1,56 @@
   163.4 +/*
   163.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   163.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   163.7 + *
   163.8 + * This code is free software; you can redistribute it and/or modify it
   163.9 + * under the terms of the GNU General Public License version 2 only, as
  163.10 + * published by the Free Software Foundation.
  163.11 + *
  163.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  163.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  163.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  163.15 + * version 2 for more details (a copy is included in the LICENSE file that
  163.16 + * accompanied this code).
  163.17 + *
  163.18 + * You should have received a copy of the GNU General Public License version
  163.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  163.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  163.21 + *
  163.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  163.23 + * or visit www.oracle.com if you need additional information or have any
  163.24 + * questions.
  163.25 + */
  163.26 +
  163.27 +/**
  163.28 + * JDK-8060688: Nashorn: Generated script class name fails --verify-code for names with special chars
  163.29 + *
  163.30 + * @test
  163.31 + * @run
  163.32 + */
  163.33 +
  163.34 +var NashornEngineFactory = Java.type("jdk.nashorn.api.scripting.NashornScriptEngineFactory");
  163.35 +var ScriptEngine = Java.type("javax.script.ScriptEngine");
  163.36 +var ScriptContext = Java.type("javax.script.ScriptContext");
  163.37 +
  163.38 +var factory = new NashornEngineFactory();
  163.39 +
  163.40 +var e = factory.getScriptEngine("--verify-code");
  163.41 +
  163.42 +function evalAndCheck(code) {
  163.43 +    try {
  163.44 +        e.eval(code);
  163.45 +    } catch (exp) {
  163.46 +        exp.printStackTrace();
  163.47 +    }
  163.48 +}
  163.49 +
  163.50 +// check default name
  163.51 +evalAndCheck("var a = 3");
  163.52 +// check few names with special chars
  163.53 +var scontext = e.context;
  163.54 +scontext.setAttribute(ScriptEngine.FILENAME, "<myscript>", ScriptContext.ENGINE_SCOPE);
  163.55 +evalAndCheck("var h = 'hello'");
  163.56 +scontext.setAttribute(ScriptEngine.FILENAME, "[myscript]", ScriptContext.ENGINE_SCOPE);
  163.57 +evalAndCheck("var foo = 'world'");
  163.58 +scontext.setAttribute(ScriptEngine.FILENAME, ";/\\$.", ScriptContext.ENGINE_SCOPE);
  163.59 +evalAndCheck("var foo = 'helloworld'");
   164.1 --- a/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java	Mon Oct 27 14:36:13 2014 -0700
   164.2 +++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java	Thu Nov 06 09:50:15 2014 -0800
   164.3 @@ -168,42 +168,6 @@
   164.4          }
   164.5      }
   164.6  
   164.7 -    @Test
   164.8 -    /**
   164.9 -     * Check that script can't implement sensitive package interfaces.
  164.10 -     */
  164.11 -    public void checkSensitiveInterfaceImplTest() throws ScriptException {
  164.12 -        if (System.getSecurityManager() == null) {
  164.13 -            // pass vacuously
  164.14 -            return;
  164.15 -        }
  164.16 -
  164.17 -        final ScriptEngineManager m = new ScriptEngineManager();
  164.18 -        final ScriptEngine e = m.getEngineByName("nashorn");
  164.19 -        final Object[] holder = new Object[1];
  164.20 -        e.put("holder", holder);
  164.21 -        // put an empty script object into array
  164.22 -        e.eval("holder[0] = {}");
  164.23 -        // holder[0] is an object of some subclass of ScriptObject
  164.24 -        final Class<?> ScriptObjectClass = holder[0].getClass().getSuperclass();
  164.25 -        final Class<?> PropertyAccessClass = ScriptObjectClass.getInterfaces()[0];
  164.26 -        // implementation methods for PropertyAccess class
  164.27 -        e.eval("function set() {}; function get() {}; function getInt(){} " +
  164.28 -               "function getDouble(){}; function getLong() {}; " +
  164.29 -               "this.delete = function () {}; function has() {}; " +
  164.30 -               "function hasOwnProperty() {}");
  164.31 -
  164.32 -        // get implementation of a restricted package interface
  164.33 -        try {
  164.34 -            log(Objects.toString(((Invocable)e).getInterface((Class<?>)PropertyAccessClass)));
  164.35 -            fail("should have thrown SecurityException");
  164.36 -        } catch (final Exception exp) {
  164.37 -            if (! (exp instanceof SecurityException)) {
  164.38 -                fail("SecurityException expected, got " + exp);
  164.39 -            }
  164.40 -        }
  164.41 -    }
  164.42 -
  164.43      // @bug 8032948: Nashorn linkages awry
  164.44      public static class FakeProxy extends Proxy {
  164.45          public FakeProxy(final InvocationHandler ih) {
   165.1 --- a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Mon Oct 27 14:36:13 2014 -0700
   165.2 +++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Thu Nov 06 09:50:15 2014 -0800
   165.3 @@ -38,6 +38,7 @@
   165.4  import java.util.concurrent.Callable;
   165.5  import javax.script.Compilable;
   165.6  import javax.script.CompiledScript;
   165.7 +import javax.script.Invocable;
   165.8  import javax.script.ScriptContext;
   165.9  import javax.script.ScriptEngine;
  165.10  import javax.script.ScriptEngineFactory;
  165.11 @@ -629,6 +630,40 @@
  165.12          assertEquals(enumerable, Boolean.FALSE);
  165.13      }
  165.14  
  165.15 +    public static class Context {
  165.16 +        private Object myobj;
  165.17 +
  165.18 +        public void set(Object o) {
  165.19 +            myobj = o;
  165.20 +        }
  165.21 +
  165.22 +        public Object get() {
  165.23 +            return myobj;
  165.24 +        }
  165.25 +    }
  165.26 +
  165.27 +    // @bug 8050977: Java8 Javascript Nashorn exception:
  165.28 +    // no current Global instance for nashorn
  165.29 +    @Test
  165.30 +    public void currentGlobalMissingTest() throws Exception {
  165.31 +        final ScriptEngineManager manager = new ScriptEngineManager();
  165.32 +        final ScriptEngine e = manager.getEngineByName("nashorn");
  165.33 +
  165.34 +        final Context ctx = new Context();
  165.35 +        e.put("ctx", ctx);
  165.36 +        e.eval("var obj = { foo: function(str) { return str.toUpperCase() } }");
  165.37 +        e.eval("ctx.set(obj)");
  165.38 +        final Invocable inv = (Invocable)e;
  165.39 +        assertEquals("HELLO", inv.invokeMethod(ctx.get(), "foo", "hello"));
  165.40 +        // try object literal
  165.41 +        e.eval("ctx.set({ bar: function(str) { return str.toLowerCase() } })");
  165.42 +        assertEquals("hello", inv.invokeMethod(ctx.get(), "bar", "HELLO"));
  165.43 +        // try array literal
  165.44 +        e.eval("var arr = [ 'hello', 'world' ]");
  165.45 +        e.eval("ctx.set(arr)");
  165.46 +        assertEquals("helloworld", inv.invokeMethod(ctx.get(), "join", ""));
  165.47 +    }
  165.48 +
  165.49      private static void checkProperty(final ScriptEngine e, final String name)
  165.50          throws ScriptException {
  165.51          final String value = System.getProperty(name);
   166.1 --- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java	Mon Oct 27 14:36:13 2014 -0700
   166.2 +++ b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java	Thu Nov 06 09:50:15 2014 -0800
   166.3 @@ -72,6 +72,7 @@
   166.4          options.set("print.parse", true);
   166.5          options.set("scripting", true);
   166.6          options.set("const.as.var", true);
   166.7 +        options.set("verify.code", true);
   166.8  
   166.9          final ErrorManager errors = new ErrorManager() {
  166.10              @Override
   167.1 --- a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java	Mon Oct 27 14:36:13 2014 -0700
   167.2 +++ b/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java	Thu Nov 06 09:50:15 2014 -0800
   167.3 @@ -325,4 +325,29 @@
   167.4          );
   167.5          assertEquals(ret, 10, "Parsed and executed OK");
   167.6      }
   167.7 +
   167.8 +    @Test
   167.9 +    public void evalDefaultFileNameTest() throws ScriptException {
  167.10 +        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
  167.11 +        final ScriptEngine engine = fac.getScriptEngine(new String[] { "--verify-code=true" });
  167.12 +        // default FILENAME being "<eval>" make sure generated code bytecode verifies.
  167.13 +        engine.eval("var a = 3;");
  167.14 +    }
  167.15 +
  167.16 +    @Test
  167.17 +    public void evalFileNameWithSpecialCharsTest() throws ScriptException {
  167.18 +        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
  167.19 +        final ScriptEngine engine = fac.getScriptEngine(new String[] { "--verify-code=true" });
  167.20 +        final ScriptContext ctxt = new SimpleScriptContext();
  167.21 +        // use file name with "dangerous" chars.
  167.22 +        ctxt.setAttribute(ScriptEngine.FILENAME, "<myscript>", ScriptContext.ENGINE_SCOPE);
  167.23 +        engine.eval("var a = 3;");
  167.24 +        ctxt.setAttribute(ScriptEngine.FILENAME, "[myscript]", ScriptContext.ENGINE_SCOPE);
  167.25 +        engine.eval("var h = 'hello';");
  167.26 +        ctxt.setAttribute(ScriptEngine.FILENAME, ";/\\$.", ScriptContext.ENGINE_SCOPE);
  167.27 +        engine.eval("var foo = 'world';");
  167.28 +        // name used by jjs shell tool for the interactive mode
  167.29 +        ctxt.setAttribute(ScriptEngine.FILENAME, "<shell>", ScriptContext.ENGINE_SCOPE);
  167.30 +        engine.eval("var foo = 'world';");
  167.31 +    }
  167.32  }
   168.1 --- a/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java	Mon Oct 27 14:36:13 2014 -0700
   168.2 +++ b/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java	Thu Nov 06 09:50:15 2014 -0800
   168.3 @@ -78,7 +78,8 @@
   168.4      // ParallelTestRunner-specific
   168.5      private static final String    TEST_JS_THREADS     = "test.js.threads";
   168.6      private static final String    TEST_JS_REPORT_FILE = "test.js.report.file";
   168.7 -    private static final int       THREADS             = Integer.getInteger(TEST_JS_THREADS, Runtime.getRuntime().availableProcessors());
   168.8 +    // test262 does a lot of eval's and the JVM hates multithreaded class definition, so lower thread count is usually faster.
   168.9 +    private static final int       THREADS = Integer.getInteger(TEST_JS_THREADS, Runtime.getRuntime().availableProcessors() > 4 ? 4 : 2);
  168.10  
  168.11      private final List<ScriptRunnable> tests    = new ArrayList<>();
  168.12      private final Set<String>      orphans  = new TreeSet<>();

mercurial