8043632: Parallelize class installation and various script fixes.
authorlagergren
Wed, 21 May 2014 16:12:40 +0200
changeset 24766 7b54e2362c6c
parent 24765 1e533bcca9f8
child 24767 0b8af588070b
8043632: Parallelize class installation and various script fixes. Reviewed-by: sundar, attila
nashorn/bin/run_octane.sh
nashorn/bin/runopt.sh
nashorn/docs/DEVELOPER_README
nashorn/make/build-benchmark.xml
nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java
nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
nashorn/test/script/basic/ranges_disabled.js
nashorn/test/script/basic/ranges_disabled.js.EXPECTED
nashorn/test/script/basic/ranges_enabled.js
nashorn/test/script/basic/ranges_enabled.js.EXPECTED
nashorn/test/script/basic/ranges_payload.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/bin/run_octane.sh	Wed May 21 16:12:40 2014 +0200
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+LOG="./octane_$(date|sed "s/ /_/g"|sed "s/:/_/g").log"
+
+run_one() {
+    sh ../bin/runopt.sh -scripting ../test/script/basic/run-octane.js -- $1 --verbose --iterations 25 | tee -a $LOG
+}
+
+if [ -z $1 ]; then 
+
+    run_one "box2d"
+    run_one "code-load"
+    run_one "crypto"
+    run_one "deltablue"
+    run_one "earley-boyer"
+    run_one "gbemu"
+    run_one "mandreel"
+    run_one "navier-stokes"
+    run_one "pdfjs"
+    run_one "raytrace"
+    run_one "regexp"
+    run_one "richards"
+    run_one "splay"
+    run_one "typescript"
+    run_one "zlib"
+
+else
+    run_one $1
+fi
--- a/nashorn/bin/runopt.sh	Wed May 21 16:12:40 2014 +0200
+++ b/nashorn/bin/runopt.sh	Wed May 21 16:12:40 2014 +0200
@@ -1,4 +1,26 @@
 #!/bin/sh
+#
+# Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
 
 ###########################################################################################
 # This is a helper script to evaluate nashorn with optimistic types
@@ -23,6 +45,7 @@
 # set the "method-sampling-interval" Normal and Maximum sample time as low as you
 # can go (10 ms on most platforms). The default is normally higher. The increased
 # sampling overhead is usually negligible for Nashorn runs, but the data is better
+
 JFR_FILENAME="./nashorn_$(date|sed "s/ /_/g"|sed "s/:/_/g").jfr"
 
 
@@ -44,15 +67,21 @@
 -esa \
 -Xbootclasspath/p:$NASHORN_JAR \
 -Xms2G -Xmx2G \
--XX:+UnlockCommercialFeatures \
--XX:+FlightRecorder \
--XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=$JFR_FILENAME,stackdepth=1024 \
 -XX:TypeProfileLevel=222 \
 -cp $CLASSPATH:../build/test/classes/ \
 jdk.nashorn.tools.Shell ${@}
 
 # Below are flags that may come in handy, but aren't used for default runs
 
+# Testing out new code optimizations using the generic hotspot "new code" parameter
+#-XX:+UnlockDiagnosticVMOptions \
+#-XX:+UseNewCode \
+
+# Flight recorder
+#-XX:+UnlockCommercialFeatures \
+#-XX:+FlightRecorder \
+#-XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=$JFR_FILENAME,stackdepth=1024 \
+
 
 # Type specialization and math intrinsic replacement should be enabled by default in 8u20 and nine,
 # keeping this flag around for experimental reasons. Replace + with - to switch it off
@@ -76,10 +105,6 @@
 # compiler threads is set to 1 for determinsm.
 #-XX:+PrintOptoAssembly -XX:-TieredCompilation -XX:CICompilerCount=1 \
 
+# Tier compile threasholds. Default value is 10. (1-100 is useful for experiments)
+# -XX:IncreaseFirstTierCompileThresholdAt=XX
 
-#[20/05/14 14:05:54] Albert Noll: IncreaseFirstTierCompileThresholdAt=XX
-#[20/05/14 14:06:03] Albert Noll: where X is between 1..100
-#[20/05/14 14:06:33] Albert Noll: The smaller X is, the less methods are being compiled with C1
-#[20/05/14 14:07:37] Albert Noll: You can also do more aggressive sweeping with:
-# NmethodSweepActivity=XX
-#[20/05/14 14:07:47] Albert Noll: The default value is 10
--- a/nashorn/docs/DEVELOPER_README	Wed May 21 16:12:40 2014 +0200
+++ b/nashorn/docs/DEVELOPER_README	Wed May 21 16:12:40 2014 +0200
@@ -737,26 +737,6 @@
 the JRuby project. The default value for this flag is "joni"
 
 
-SYSTEM PROPERTY: -Dnashorn.time
-
-This enables timers for various phases of script compilation. The timers
-will be dumped when the Nashorn process exits. We see a percentage value
-of how much time was spent not executing bytecode (i.e. compilation and
-internal tasks) at the end of the report. 
-
-Here is an example:
-
-[JavaScript Parsing]    61  ms
-[Constant Folding]      11  ms
-[Control Flow Lowering] 26  ms
-[Type Attribution]      81  ms
-[Range Analysis]        0  ms
-[Code Splitting]        29  ms
-[Type Finalization]     19  ms
-[Bytecode Generation]   189  ms
-[Code Installation]     7  ms
-Total runtime: 508 ms (Non-runtime: 423 ms [83%])
-
 ===============
 2. The loggers.
 ===============
@@ -887,6 +867,34 @@
 (Object in the normal case, unless running with the dual field
 representation)
 
+* time
+
+This enables timers for various phases of script compilation. The timers
+will be dumped when the Nashorn process exits. We see a percentage value
+of how much time was spent not executing bytecode (i.e. compilation and
+internal tasks) at the end of the report. 
+
+A finer level than "info" will show individual compilation timings as they
+happen.
+
+Here is an example:
+
+[time] Accumulated complation phase Timings:
+[time] 
+[time] 'JavaScript Parsing'              1076 ms
+[time] 'Constant Folding'                 159 ms
+[time] 'Control Flow Lowering'            303 ms
+[time] 'Program Point Calculation'        282 ms
+[time] 'Builtin Replacement'               71 ms
+[time] 'Code Splitting'                   670 ms
+[time] 'Symbol Assignment'                474 ms
+[time] 'Scope Depth Computation'          249 ms
+[time] 'Optimistic Type Assignment'       186 ms
+[time] 'Local Variable Type Calculation'  526 ms
+[time] 'Bytecode Generation'             5177 ms
+[time] 'Class Installation'              1854 ms
+[time] 
+[time] Total runtime: 11994 ms (Non-runtime: 11027 ms [91%])
 
 =======================
 3. Undocumented options
--- a/nashorn/make/build-benchmark.xml	Wed May 21 16:12:40 2014 +0200
+++ b/nashorn/make/build-benchmark.xml	Wed May 21 16:12:40 2014 +0200
@@ -24,12 +24,12 @@
 <project name="nashorn-benchmarks" default="all" basedir="..">
 
   <target name="octane-init" depends="jar">
-    <property name="octane-tests" value="box2d code-load crypto deltablue earley-boyer gbemu navier-stokes pdfjs raytrace regexp richards splay"/>
+    <property name="octane-tests" value="box2d code-load crypto deltablue earley-boyer gbemu navier-stokes mandreel pdfjs raytrace regexp richards splay typescript zlib"/>
   </target>
   
-  <!-- ignore benchmarks where rhino crashes -->
+  <!-- ignore benchmarks where rhino crashes - the test harness should do this now -->
   <target name="octane-init-rhino" depends="jar">
-    <property name="octane-tests" value="box2d code-load crypto deltablue earley-boyer gbemu navier-stokes raytrace regexp richards splay"/>
+    <property name="octane-tests" value="box2d code-load crypto deltablue earley-boyer gbemu navier-stokes mandreel pdfjs raytrace regexp richards splay typescript zlib"/>
   </target>
 
   <!-- box2d -->
@@ -151,7 +151,6 @@
     </antcall>
   </target>
 
-
   <!-- mandreel -->  
   <target name="octane-mandreel" depends="jar">
     <antcall target="run-octane">
@@ -333,14 +332,13 @@
   <target name="octane-single-process" depends="octane-init">
     <antcall target="run-octane"/>
   </target>
-
-  <!-- zlib excluded due to missing implementation of 'read' -->
+ 
   <target name="octane-separate-process" depends=
      "octane-box2d, octane-code-load, octane-crypto, 
       octane-deltablue, octane-earley-boyer, octane-gbemu,
       octane-mandreel, octane-navier-stokes, octane-pdfjs, 
       octane-raytrace, octane-regexp, octane-richards, 
-      octane-splay, octane-typescript"/>
+      octane-splay, octane-typescript, octane-zlib"/>
 
   <target name="--single-process" unless="${octane-test-sys-prop.separate.process}">
     <antcall target="octane-single-process"/>
@@ -373,12 +371,13 @@
         <propertyref prefix="nashorn."/>
       </syspropertyset>
       <arg value="${octane-test-sys-prop.test.js.framework}"/>
+      <arg value="-scripting"/>
       <arg value="--"/>
       <arg value="${octane-tests}"/>
       <arg value="--runtime"/>
       <arg value="Nashorn"/>
       <arg value="--verbose"/>
-      <arg value="--iterations 8"/>
+      <arg value="--iterations 10"/>
     </java>
   </target>
 
@@ -390,7 +389,7 @@
       <arg value="--runtime"/>
       <arg value="v8"/>
       <arg value="--verbose"/>
-      <arg value="--iterations 8"/>
+      <arg value="--iterations 10"/>
     </exec>
   </target>
 
@@ -407,7 +406,7 @@
       <arg value="--runtime"/>
       <arg value="Rhino"/>
       <arg value="--verbose"/>
-      <arg value="--iterations 8"/>
+      <arg value="--iterations 10"/>
     </java>
   </target>
 
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Wed May 21 16:12:40 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Wed May 21 16:12:40 2014 +0200
@@ -55,6 +55,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.Map.Entry;
+import java.util.function.Consumer;
 
 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
 import jdk.nashorn.internal.ir.FunctionNode;
@@ -513,34 +514,41 @@
                 throw new CompilationException("Internal compiler error: root class not found!");
             }
 
-            // do these in a loop, to use only one privileged action - this significantly
-            // reduces class installation overhead
-            log.fine("Preparing source and constant fields...");
-            try {
-                final Object[] constants = compiler.getConstantData().toArray();
-                // Need doPrivileged because these fields are private
-                AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+            // do these in parallel, this significantly reduces class installation overhead
+            // however - it still means that every thread needs a separate doPrivileged
+            final Object[] constants = compiler.getConstantData().toArray();
+            installedClasses.entrySet().parallelStream().forEach(
+                new Consumer<Entry<String, Class<?>>>() {
                     @Override
-                    public Void run() throws Exception {
-                        for (final Entry<String, Class<?>> entry : installedClasses.entrySet()) {
-                            final Class<?> clazz = entry.getValue();
-                            log.fine("Initializing source for ", clazz);
-                            //use reflection to write source and constants table to installed classes
-                            final Field sourceField    = clazz.getDeclaredField(SOURCE.symbolName());
-                            sourceField.setAccessible(true);
-                            sourceField.set(null, compiler.getSource());
+                    public void accept(final Entry<String, Class<?>> entry) {
+                        try {
+                            AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+                                @Override
+                                public Void run() {
+                                    try {
+                                        final Class<?> clazz = entry.getValue();
+                                        log.fine("Initializing source for ", clazz);
+                                        //use reflection to write source and constants table to installed classes
+                                        final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName());
+                                        sourceField.setAccessible(true);
+                                        sourceField.set(null, compiler.getSource());
 
-                            log.fine("Initializing constants for ", clazz);
-                            final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName());
-                            constantsField.setAccessible(true);
-                            constantsField.set(null, constants);
+                                        log.fine("Initializing constants for ", clazz);
+                                        final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName());
+                                        constantsField.setAccessible(true);
+                                        constantsField.set(null, constants);
+                                    } catch (final IllegalAccessException | NoSuchFieldException e) {
+                                        throw new RuntimeException(e);
+                                    }
+                                    return null;
+                                }
+                            });
+                        } catch (final PrivilegedActionException e) {
+                            throw new RuntimeException(e);
                         }
-                        return null;
                     }
                 });
-            } catch (final PrivilegedActionException e) {
-                throw new RuntimeException(e);
-            }
+            log.fine("Done");
             log.fine("Done");
 
             // index recompilable script function datas in the constant pool
@@ -587,7 +595,8 @@
         @Override
         public String toString() {
             return "'Class Installation'";
-         }
+        }
+
      };
 
     /** pre conditions required for function node to which this transform is to be applied */
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Wed May 21 16:12:40 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Wed May 21 16:12:40 2014 +0200
@@ -95,7 +95,8 @@
     /** Argument passed to compile only if optimistic compilation should take place */
     public static final String COMPILE_ONLY_OPTIMISTIC_ARG = "optimistic";
 
-    /**     * Behavior when encountering a function declaration in a lexical context where only statements are acceptable
+    /**
+     *  Behavior when encountering a function declaration in a lexical context where only statements are acceptable
      * (function declarations are source elements, but not statements).
      */
     public enum FunctionStatementBehavior {
--- a/nashorn/test/script/basic/ranges_disabled.js	Wed May 21 16:12:40 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- * 
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- * 
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- * 
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- * 
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * range analysis test. check that computation return values are correct
- * both with and without range analysis
- *
- * @test 
- * @run 
- */
-
-load(__DIR__ + "ranges_payload.js");
--- a/nashorn/test/script/basic/ranges_disabled.js.EXPECTED	Wed May 21 16:12:40 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-289
-11094405
-4294967293
--4722
--- a/nashorn/test/script/basic/ranges_enabled.js	Wed May 21 16:12:40 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- * 
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- * 
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- * 
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- * 
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * range analysis test. check that computation return values are correct
- * both with and without range analysis
- *
- * @test
- * @option --range-analysis
- * @run 
- */
-
-load(__DIR__ + "ranges_payload.js");
--- a/nashorn/test/script/basic/ranges_enabled.js.EXPECTED	Wed May 21 16:12:40 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-289
-11094405
-4294967293
--4722
--- a/nashorn/test/script/basic/ranges_payload.js	Wed May 21 16:12:40 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- * 
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- * 
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- * 
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- * 
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * range analysis test. check that computation return values are correct
- * both with and without range analysis
- *
- * @subtest
- */
-
-function f(c) {
-    var v = c & 0xffff;
-    var w = v & 0xfff;
-    var x = v * w;
-    return x;
-}
-
-function g() {
-    var sum = 0;
-    for (var x = 0; x < 4711; x++) {
-	sum += x;
-    }
-    return sum;
-}
-
-function g2() {
-    var sum = 0;
-    //make sure we overflow
-    var displacement = 0x7ffffffe;
-    for (var x = displacement; x < (displacement + 2); x++) {
-	sum += x;
-    }
-    return sum;
-}
-
-//mostly provide code coverage for all the range operations    
-function h() {
-    var sum = 0;
-    sum += 4711;
-    sum &= 0xffff;
-    sum /= 2;
-    sum *= 2;
-    sum -= 4;
-    sum |= 2;
-    sum ^= 17;
-    sum = sum % 10000;
-    sum = -sum;
-    return sum
-}
-
-print(f(17));
-print(g());
-print(g2());
-print(h());