Thu, 06 Nov 2014 09:50:15 -0800
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<>();