Mon, 01 Apr 2013 21:42:31 -0700
Merge
1.1 --- a/bin/jjs Thu Mar 28 10:55:17 2013 -0700 1.2 +++ b/bin/jjs Mon Apr 01 21:42:31 2013 -0700 1.3 @@ -26,4 +26,4 @@ 1.4 1.5 [ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1; 1.6 1.7 -$JAVA_HOME/bin/java -server -XX:-TieredCompilation -Xms2G -Xmx2G -esa -ea -Djava.ext.dirs=$JAVA_HOME/jre/lib/ext:`dirname $0`/../dist -XX:+HeapDumpOnOutOfMemoryError -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -Dnashorn.debug=true jdk.nashorn.tools.Shell $* 1.8 +$JAVA_HOME/bin/java -server -XX:-TieredCompilation -Xms2G -Xmx2G -esa -ea -Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -XX:+HeapDumpOnOutOfMemoryError -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -Dnashorn.debug=true jdk.nashorn.tools.Shell $*
2.1 --- a/bin/jjssecure Thu Mar 28 10:55:17 2013 -0700 2.2 +++ b/bin/jjssecure Mon Apr 01 21:42:31 2013 -0700 2.3 @@ -26,4 +26,4 @@ 2.4 2.5 [ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1; 2.6 2.7 -$JAVA_HOME/bin/java -Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -Djava.security.properties=`dirname $0`/../make/java.security.override -Djava.ext.dirs=$JAVA_HOME/jre/lib/ext:`dirname $0`/../dist -XX:+HeapDumpOnOutOfMemoryError -Dnashorn.debug=true -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=true -Dnashorn.home=`dirname $0`/.. -Djava.security.manager jdk.nashorn.tools.Shell $* 2.8 +$JAVA_HOME/bin/java -Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -Djava.security.properties=`dirname $0`/../make/java.security.override -Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -XX:+HeapDumpOnOutOfMemoryError -Dnashorn.debug=true -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=true -Dnashorn.home=`dirname $0`/.. -Djava.security.manager jdk.nashorn.tools.Shell $*
3.1 --- a/bin/nashorn Thu Mar 28 10:55:17 2013 -0700 3.2 +++ b/bin/nashorn Mon Apr 01 21:42:31 2013 -0700 3.3 @@ -26,4 +26,4 @@ 3.4 3.5 [ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1; 3.6 3.7 -$JAVA_HOME/bin/jrunscript -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=$JAVA_HOME/jre/lib/ext:`dirname $0`/../dist -J-XX:+HeapDumpOnOutOfMemoryError -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -J-Dnashorn.debug=true -l nashorn $* 3.8 +$JAVA_HOME/bin/jrunscript -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -J-XX:+HeapDumpOnOutOfMemoryError -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -J-Dnashorn.debug=true -l nashorn $*
4.1 --- a/bin/nashornsecure Thu Mar 28 10:55:17 2013 -0700 4.2 +++ b/bin/nashornsecure Mon Apr 01 21:42:31 2013 -0700 4.3 @@ -26,4 +26,4 @@ 4.4 4.5 [ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1; 4.6 4.7 -$JAVA_HOME/bin/jrunscript -J-Djava.security.properties=`dirname $0`/../make/java.security.override -J-Djava.security.manager -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=$JAVA_HOME/jre/lib/ext:`dirname $0`/../dist -J-XX:+HeapDumpOnOutOfMemoryError -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -J-Dnashorn.debug=true -l nashorn $* 4.8 +$JAVA_HOME/bin/jrunscript -J-Djava.security.properties=`dirname $0`/../make/java.security.override -J-Djava.security.manager -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -J-XX:+HeapDumpOnOutOfMemoryError -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -J-Dnashorn.debug=true -l nashorn $*
5.1 --- a/docs/DEVELOPER_README Thu Mar 28 10:55:17 2013 -0700 5.2 +++ b/docs/DEVELOPER_README Mon Apr 01 21:42:31 2013 -0700 5.3 @@ -13,6 +13,17 @@ 5.4 This documentation of the system property flags assume that the 5.5 default value of the flag is false, unless otherwise specified. 5.6 5.7 +SYSTEM PROPERTY: -Dnashorn.args=<string> 5.8 + 5.9 +This property takes as its value a space separated list of Nashorn 5.10 +command line options that should be passed to Nashorn. This might be useful 5.11 +in environments where it is hard to tell how a nashorn.jar is launched. 5.12 + 5.13 +Example: 5.14 + 5.15 +> java -Dnashorn.args="--lazy-complation --log=compiler" large-java-app-with-nashorn.jar 5.16 +> ant -Dnashorn.args="--log=codegen" antjob 5.17 + 5.18 SYSTEM PROPERTY: -Dnashorn.unstable.relink.threshold=x 5.19 5.20 This property controls how many call site misses are allowed before a
6.1 --- a/docs/JavaScriptingProgrammersGuide.html Thu Mar 28 10:55:17 2013 -0700 6.2 +++ b/docs/JavaScriptingProgrammersGuide.html Mon Apr 01 21:42:31 2013 -0700 6.3 @@ -533,9 +533,8 @@ 6.4 <hr> 6.5 <a name="jsarrays" id="jsarrays"></a> 6.6 <h3>Creating, Converting and Using Java Arrays</h3> 6.7 -<p>While creating a Java object is the same as in Java, to create 6.8 -Java arrays in JavaScript we can use Java reflection 6.9 -explicitly. But once created the element access or length access is 6.10 +<p> 6.11 +Array element access or length access is 6.12 the same as in Java. Also, a script array can be used when a Java 6.13 method expects a Java array (auto conversion). So in most cases we 6.14 don't have to create Java arrays explicitly.</p> 6.15 @@ -543,7 +542,8 @@ 6.16 // <a href="source/javaarray.js">javaarray.js</a> 6.17 6.18 // create Java String array of 5 elements 6.19 -var a = java.lang.reflect.Array.newInstance(java.lang.String.class, 5); 6.20 +var StringArray = Java.type("java.lang.String[]"); 6.21 +var a = new StringArray(5); 6.22 6.23 // Accessing elements and length access is by usual Java syntax 6.24 a[0] = "scripting is great!";
7.1 --- a/docs/source/javaarray.js Thu Mar 28 10:55:17 2013 -0700 7.2 +++ b/docs/source/javaarray.js Mon Apr 01 21:42:31 2013 -0700 7.3 @@ -30,7 +30,8 @@ 7.4 */ 7.5 7.6 // create Java String array of 5 elements 7.7 -var a = java.lang.reflect.Array.newInstance(java.lang.String.class, 5); 7.8 +var StringArray = Java.type("java.lang.String[]"); 7.9 +var a = new StringArray(5); 7.10 7.11 // Accessing elements and length access is by usual Java syntax 7.12 a[0] = "scripting is great!";
8.1 --- a/make/build.xml Thu Mar 28 10:55:17 2013 -0700 8.2 +++ b/make/build.xml Mon Apr 01 21:42:31 2013 -0700 8.3 @@ -124,7 +124,7 @@ 8.4 <echo message="release=${nashorn.version}" file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties" append="true"/> 8.5 </target> 8.6 8.7 - <target name="jar" depends="compile, run-nasgen" description="Creates nashorn.jar"> 8.8 + <target name="jar" depends="compile, run-nasgen, generate-cc-template" description="Creates nashorn.jar"> 8.9 <jar jarfile="${dist.jar}" manifest="${meta.inf.dir}/MANIFEST.MF" index="true" filesetmanifest="merge"> 8.10 <fileset dir="${build.classes.dir}"/> 8.11 <manifest> 8.12 @@ -191,12 +191,12 @@ 8.13 8.14 <!-- tests that check nashorn internals and internal API --> 8.15 <jar jarfile="${nashorn.internal.tests.jar}"> 8.16 - <fileset dir="${build.test.classes.dir}" excludes="**/api/*"/> 8.17 + <fileset dir="${build.test.classes.dir}" excludes="**/api/**"/> 8.18 </jar> 8.19 8.20 <!-- tests that check nashorn script engine (jsr-223) API --> 8.21 <jar jarfile="${nashorn.api.tests.jar}"> 8.22 - <fileset dir="${build.test.classes.dir}" includes="**/api/*"/> 8.23 + <fileset dir="${build.test.classes.dir}" includes="**/api/**"/> 8.24 </jar> 8.25 8.26 </target>
9.1 --- a/make/code_coverage.xml Thu Mar 28 10:55:17 2013 -0700 9.2 +++ b/make/code_coverage.xml Mon Apr 01 21:42:31 2013 -0700 9.3 @@ -36,7 +36,12 @@ 9.4 <equals arg1="${jcov}" arg2="dynamic" trim="true"/> 9.5 </condition> 9.6 9.7 + <condition property="cc.generate.template" value="true"> 9.8 + <equals arg1="${cc.dynamic.genereate.template}" arg2="true" trim="true"/> 9.9 + </condition> 9.10 + 9.11 <mkdir dir="${cc.dir}"/> 9.12 + <mkdir dir="${build.dir}/to_be_instrumented"/> 9.13 9.14 <!-- info --> 9.15 <echo message="jcov=${jcov}"/> 9.16 @@ -51,25 +56,66 @@ 9.17 <property name="run.test.cc.jvmargs" value=""/> 9.18 </target> 9.19 9.20 + <target name="prepare-to-be-instrumented" depends="compile" description="Prepares to_be_instrumented dir"> 9.21 + <copy todir="${build.dir}/to_be_instrumented"> 9.22 + <fileset dir="${build.classes.dir}"> 9.23 + <include name="**/*.class"/> 9.24 + <include name="**/*.clazz"/> 9.25 + </fileset> 9.26 + </copy> 9.27 + 9.28 + <move todir="${build.dir}/to_be_instrumented/jdk/nashorn/internal/objects"> 9.29 + <fileset dir="${build.dir}/to_be_instrumented/jdk/nashorn/internal/objects"> 9.30 + <include name="**/*.clazz"/> 9.31 + </fileset> 9.32 + <mapper type="glob" from="*.clazz" to="*.class"/> 9.33 + </move> 9.34 + </target> 9.35 + 9.36 + <target name="generate-cc-template" depends="prepare-to-be-instrumented" description="Generates code coverage template for dynamic CC" if="cc.generate.template"> 9.37 + <property name="cc.instrumented.path" location="${build.dir}/to_be_instrumented"/> 9.38 + <java classname="com.sun.tdk.jcov.TmplGen"> 9.39 + <arg value="-verbose"/> 9.40 + <arg line="-include ${cc.include}"/> 9.41 + <arg line="-type all"/> 9.42 + <arg line="-template ${cc.template}"/> 9.43 + <arg value="${cc.instrumented.path}"/> 9.44 + <classpath> 9.45 + <pathelement location="${jcov.jar}"/> 9.46 + </classpath> 9.47 + </java> 9.48 + 9.49 + <java classname="com.sun.tdk.jcov.RepGen"> 9.50 + <arg value="-verbose"/> 9.51 + <arg line="-output ${cc.dir}/CC_template_report"/> 9.52 + <arg value="${cc.template}"/> 9.53 + <classpath> 9.54 + <pathelement location="${jcov.jar}"/> 9.55 + </classpath> 9.56 + </java> 9.57 + </target> 9.58 + 9.59 <target name="init-cc" depends="init-cc-disabled, init-cc-enabled"> 9.60 <property name="run.test.cc.jvmargs" value=""/> 9.61 </target> 9.62 9.63 <target name="init-cc-cleanup" if="${cc.enabled}"> 9.64 <delete dir="${cc.dir}" failonerror="false" /> 9.65 + <delete dir="${build.dir}/to_be_instrumented" failonerror="false" /> 9.66 </target> 9.67 9.68 <target name="check-merging-files" depends="init"> 9.69 - <resourcecount property="cc.xmls"> 9.70 - <filelist dir="${cc.dir}" files="*.xml" /> 9.71 - </resourcecount> 9.72 + <echo message="checking avalibility of ${cc.template}"/> 9.73 <condition property="nothing-to-merge" value="true"> 9.74 - <equals arg1="${cc.xmls}" arg2="1" trim="true"/> 9.75 + <not> 9.76 + <available file="${cc.template}"/> 9.77 + </not> 9.78 </condition> 9.79 + <echo message="nothing-to-merge = ${nothing-to-merge}"/> 9.80 </target> 9.81 9.82 <target name="fix-merging-files" depends="check-merging-files" if="${nothing-to-merge}"> 9.83 - <echo message="making pre-merge workaround"/> 9.84 + <echo message="making pre-merge workaround due to missed template"/> 9.85 <move todir="${cc.dir}" includeemptydirs="false"> 9.86 <fileset dir="${cc.dir}"> 9.87 <include name="*.xml"/> 9.88 @@ -81,12 +127,12 @@ 9.89 <target name="merge-code-coverage" depends="fix-merging-files" unless="${nothing-to-merge}"> 9.90 <echo message="merging files"/> 9.91 <fileset dir="${cc.dir}" id="cc.xmls"> 9.92 - <include name="**/*${jcov}*.xml"/> 9.93 + <include name="**/*_${jcov}_*.xml"/> 9.94 <include name="**/CC_template.xml"/> 9.95 </fileset> 9.96 9.97 <pathconvert pathsep=" " property="cc.all.xmls" refid="cc.xmls"/> 9.98 - 9.99 + <echo message="merging files - ${cc.all.xmls}" /> 9.100 <java classname="com.sun.tdk.jcov.Merger"> 9.101 <arg value="-verbose"/> 9.102 <arg value="-output"/>
10.1 --- a/make/java.security.override Thu Mar 28 10:55:17 2013 -0700 10.2 +++ b/make/java.security.override Mon Apr 01 21:42:31 2013 -0700 10.3 @@ -3,7 +3,7 @@ 10.4 # We ensure that by overriding "package.access" security property. 10.5 10.6 # The following "package.access" value was copied from default java.security 10.7 -# of jre/lib/security and appended with nashorn IR, Codegen and Parser packages. 10.8 +# of jre/lib/security and appended with nashorn sensitive packages. 10.9 10.10 # 10.11 # List of comma-separated packages that start with or equal this string 10.12 @@ -11,4 +11,4 @@ 10.13 # passed to checkPackageAccess unless the 10.14 # corresponding RuntimePermission ("accessClassInPackage."+package) has 10.15 # been granted. 10.16 -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.,jdk.nashorn.internal.ir., jdk.nashorn.internal.codegen., jdk.nashorn.internal.lookup., jdk.nashorn.internal.parser. 10.17 +package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.,jdk.nashorn.internal.,jdk.nashorn.tools.
11.1 --- a/make/project.properties Thu Mar 28 10:55:17 2013 -0700 11.2 +++ b/make/project.properties Mon Apr 01 21:42:31 2013 -0700 11.3 @@ -210,7 +210,7 @@ 11.4 # add '-Dtest.js.outofprocess' to run each test in a new sub-process 11.5 run.test.jvmargs.main=-server -Xmx${run.test.xmx} -XX:-TieredCompilation -esa -ea -Dnashorn.debug=true -Dfile.encoding=UTF-8 11.6 #-XX:+HeapDumpOnOutOfMemoryError -XX:-UseCompressedKlassPointers -XX:+PrintHeapAtGC -XX:ClassMetaspaceSize=300M 11.7 -run.test.jvmargs.octane.main=-Xms${run.test.xms} ${run.test.jvmargs} 11.8 +run.test.jvmargs.octane.main=-Xms${run.test.xms} ${run.test.jvmargs.main} 11.9 11.10 run.test.jvmsecurityargs=-Xverify:all -Djava.security.properties=${basedir}/make/java.security.override -Djava.security.manager -Djava.security.policy=${basedir}/build/nashorn.policy 11.11 11.12 @@ -235,10 +235,12 @@ 11.13 #naming of CC results 11.14 #NB directory specified in the cc.dir will be cleaned up!!! 11.15 cc.dir=${basedir}/../Codecoverage_Nashorn 11.16 -cc.result.file.name=cc_nashorn.xml 11.17 +cc.result.file.name=CC_${jcov}_nashorn.xml 11.18 #dynamic CC parameters; please redefine in the ${user.home}/.nashorn.project.local.properties 11.19 jcov2.lib.dir=${basedir}/../jcov2/lib 11.20 jcov.jar=${jcov2.lib.dir}/jcov.jar 11.21 cc.include=jdk\.nashorn\.* 11.22 cc.exclude=jdk\.nashorn\.internal\.scripts\.* 11.23 +cc.dynamic.genereate.template=true 11.24 +cc.template=${cc.dir}/CC_template.xml 11.25 cc.dynamic.args=-javaagent:${jcov.jar}=include=${cc.include},exclude=${cc.exclude},type=all,verbose=0,file=${cc.dir}/${cc.result.file.name}
12.1 --- a/src/jdk/nashorn/api/scripting/Formatter.java Thu Mar 28 10:55:17 2013 -0700 12.2 +++ b/src/jdk/nashorn/api/scripting/Formatter.java Mon Apr 01 21:42:31 2013 -0700 12.3 @@ -46,7 +46,7 @@ 12.4 * <p>Pattern and the logic for parameter position: java.util.Formatter 12.5 * 12.6 */ 12.7 -public final class Formatter { 12.8 +final class Formatter { 12.9 12.10 private Formatter() { 12.11 } 12.12 @@ -59,8 +59,8 @@ 12.13 * @param args arguments referenced by the format specifiers in format 12.14 * @return a formatted string 12.15 */ 12.16 - public static String format(final String format, final Object[] args) { 12.17 - Matcher m = FS_PATTERN.matcher(format); 12.18 + static String format(final String format, final Object[] args) { 12.19 + final Matcher m = FS_PATTERN.matcher(format); 12.20 int positionalParameter = 1; 12.21 12.22 while (m.find()) { 12.23 @@ -143,7 +143,7 @@ 12.24 /** 12.25 * Method to parse the integer of the argument index. 12.26 * 12.27 - * @param s 12.28 + * @param s string to parse 12.29 * @return -1 if parsing failed, 0 if string is null, > 0 integer 12.30 */ 12.31 private static int index(final String s) { 12.32 @@ -166,7 +166,7 @@ 12.33 * Method to check if a string contains '<'. This is used to find out if 12.34 * previous parameter is used. 12.35 * 12.36 - * @param s 12.37 + * @param s string to check 12.38 * @return true if '<' is in the string, else false 12.39 */ 12.40 private static boolean isPreviousArgument(final String s) {
13.1 --- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Thu Mar 28 10:55:17 2013 -0700 13.2 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Mon Apr 01 21:42:31 2013 -0700 13.3 @@ -32,6 +32,7 @@ 13.4 import java.io.InputStream; 13.5 import java.io.InputStreamReader; 13.6 import java.io.Reader; 13.7 +import java.lang.reflect.Method; 13.8 import java.net.URL; 13.9 import java.security.AccessController; 13.10 import java.security.PrivilegedAction; 13.11 @@ -179,14 +180,14 @@ 13.12 } 13.13 13.14 private <T> T getInterfaceInner(final Object self, final Class<T> clazz) { 13.15 - final Object realSelf; 13.16 + final ScriptObject realSelf; 13.17 final ScriptObject ctxtGlobal = getNashornGlobalFrom(context); 13.18 if(self == null) { 13.19 realSelf = ctxtGlobal; 13.20 } else if (!(self instanceof ScriptObject)) { 13.21 - realSelf = ScriptObjectMirror.unwrap(self, ctxtGlobal); 13.22 + realSelf = (ScriptObject)ScriptObjectMirror.unwrap(self, ctxtGlobal); 13.23 } else { 13.24 - realSelf = self; 13.25 + realSelf = (ScriptObject)self; 13.26 } 13.27 try { 13.28 final ScriptObject oldGlobal = getNashornGlobal(); 13.29 @@ -194,6 +195,10 @@ 13.30 if(oldGlobal != ctxtGlobal) { 13.31 setNashornGlobal(ctxtGlobal); 13.32 } 13.33 + 13.34 + if (! isInterfaceImplemented(clazz, realSelf)) { 13.35 + return null; 13.36 + } 13.37 return clazz.cast(JavaAdapterFactory.getConstructor(realSelf.getClass(), clazz).invoke(realSelf)); 13.38 } finally { 13.39 if(oldGlobal != ctxtGlobal) { 13.40 @@ -394,14 +399,6 @@ 13.41 setContextVariables(ctxt); 13.42 final Object val = ctxt.getAttribute(ScriptEngine.FILENAME); 13.43 final String fileName = (val != null) ? val.toString() : "<eval>"; 13.44 - 13.45 - // NOTE: FIXME: If this is jrunscript's init.js, we want to run the replacement. 13.46 - // This should go away once we fix jrunscript's copy of init.js. 13.47 - if ("<system-init>".equals(fileName)) { 13.48 - evalSupportScript("resources/init.js", "nashorn:engine/resources/init.js"); 13.49 - return null; 13.50 - } 13.51 - 13.52 Object res = ScriptRuntime.apply(script, ctxtGlobal); 13.53 return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(res, ctxtGlobal)); 13.54 } catch (final Exception e) { 13.55 @@ -471,6 +468,21 @@ 13.56 } 13.57 } 13.58 13.59 + private static boolean isInterfaceImplemented(final Class<?> iface, final ScriptObject sobj) { 13.60 + for (final Method method : iface.getMethods()) { 13.61 + // ignore methods of java.lang.Object class 13.62 + if (method.getDeclaringClass() == Object.class) { 13.63 + continue; 13.64 + } 13.65 + 13.66 + Object obj = sobj.get(method.getName()); 13.67 + if (! (obj instanceof ScriptFunction)) { 13.68 + return false; 13.69 + } 13.70 + } 13.71 + return true; 13.72 + } 13.73 + 13.74 // don't make this public!! 13.75 static ScriptObject getNashornGlobal() { 13.76 return Context.getGlobal();
14.1 --- a/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Thu Mar 28 10:55:17 2013 -0700 14.2 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Mon Apr 01 21:42:31 2013 -0700 14.3 @@ -147,6 +147,7 @@ 14.4 * @return newly created script engine. 14.5 */ 14.6 public ScriptEngine getScriptEngine(final ClassLoader appLoader) { 14.7 + checkConfigPermission(); 14.8 return new NashornScriptEngine(this, appLoader); 14.9 } 14.10 14.11 @@ -157,6 +158,7 @@ 14.12 * @return newly created script engine. 14.13 */ 14.14 public ScriptEngine getScriptEngine(final String[] args) { 14.15 + checkConfigPermission(); 14.16 return new NashornScriptEngine(this, args, getAppClassLoader()); 14.17 } 14.18 14.19 @@ -168,11 +170,19 @@ 14.20 * @return newly created script engine. 14.21 */ 14.22 public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader) { 14.23 + checkConfigPermission(); 14.24 return new NashornScriptEngine(this, args, appLoader); 14.25 } 14.26 14.27 // -- Internals only below this point 14.28 14.29 + private static void checkConfigPermission() { 14.30 + final SecurityManager sm = System.getSecurityManager(); 14.31 + if (sm != null) { 14.32 + sm.checkPermission(new RuntimePermission("nashorn.setConfig")); 14.33 + } 14.34 + } 14.35 + 14.36 private static final List<String> names; 14.37 private static final List<String> mimeTypes; 14.38 private static final List<String> extensions;
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/src/jdk/nashorn/api/scripting/ScriptUtils.java Mon Apr 01 21:42:31 2013 -0700 15.3 @@ -0,0 +1,60 @@ 15.4 +/* 15.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 15.7 + * 15.8 + * This code is free software; you can redistribute it and/or modify it 15.9 + * under the terms of the GNU General Public License version 2 only, as 15.10 + * published by the Free Software Foundation. Oracle designates this 15.11 + * particular file as subject to the "Classpath" exception as provided 15.12 + * by Oracle in the LICENSE file that accompanied this code. 15.13 + * 15.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 15.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15.17 + * version 2 for more details (a copy is included in the LICENSE file that 15.18 + * accompanied this code). 15.19 + * 15.20 + * You should have received a copy of the GNU General Public License version 15.21 + * 2 along with this work; if not, write to the Free Software Foundation, 15.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 15.23 + * 15.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 15.25 + * or visit www.oracle.com if you need additional information or have any 15.26 + * questions. 15.27 + */ 15.28 + 15.29 +package jdk.nashorn.api.scripting; 15.30 + 15.31 +import jdk.nashorn.internal.runtime.ScriptRuntime; 15.32 + 15.33 +/** 15.34 + * Utilities that are to be called from script code 15.35 + */ 15.36 +public final class ScriptUtils { 15.37 + private ScriptUtils() {} 15.38 + 15.39 + /** 15.40 + * Returns AST as JSON compatible string. This is used to 15.41 + * implement "parse" function in resources/parse.js script. 15.42 + * 15.43 + * @param code code to be parsed 15.44 + * @param name name of the code source (used for location) 15.45 + * @param includeLoc tells whether to include location information for nodes or not 15.46 + * @return JSON string representation of AST of the supplied code 15.47 + */ 15.48 + public static String parse(final String code, final String name, final boolean includeLoc) { 15.49 + return ScriptRuntime.parse(code, name, includeLoc); 15.50 + } 15.51 + 15.52 + /** 15.53 + * Method which converts javascript types to java types for the 15.54 + * String.format method (jrunscript function sprintf). 15.55 + * 15.56 + * @param format a format string 15.57 + * @param args arguments referenced by the format specifiers in format 15.58 + * @return a formatted string 15.59 + */ 15.60 + public static String format(final String format, final Object[] args) { 15.61 + return Formatter.format(format, args); 15.62 + } 15.63 +}
16.1 --- a/src/jdk/nashorn/api/scripting/resources/engine.js Thu Mar 28 10:55:17 2013 -0700 16.2 +++ b/src/jdk/nashorn/api/scripting/resources/engine.js Mon Apr 01 21:42:31 2013 -0700 16.3 @@ -46,3 +46,49 @@ 16.4 } 16.5 writer.println(String(str)); 16.6 } 16.7 + 16.8 +/** 16.9 + * This is C-like printf 16.10 + * 16.11 + * @param format string to format the rest of the print items 16.12 + * @param args variadic argument list 16.13 + */ 16.14 +Object.defineProperty(this, "printf", { 16.15 + configurable: true, 16.16 + enumerable: false, 16.17 + writable: true, 16.18 + value: function (format, args/*, more args*/) { 16.19 + print(sprintf.apply(this, arguments)); 16.20 + } 16.21 +}); 16.22 + 16.23 +/** 16.24 + * This is C-like sprintf 16.25 + * 16.26 + * @param format string to format the rest of the print items 16.27 + * @param args variadic argument list 16.28 + */ 16.29 +Object.defineProperty(this, "sprintf", { 16.30 + configurable: true, 16.31 + enumerable: false, 16.32 + writable: true, 16.33 + value: function (format, args/*, more args*/) { 16.34 + var len = arguments.length - 1; 16.35 + var array = []; 16.36 + 16.37 + if (len < 0) { 16.38 + return ""; 16.39 + } 16.40 + 16.41 + for (var i = 0; i < len; i++) { 16.42 + if (arguments[i+1] instanceof Date) { 16.43 + array[i] = arguments[i+1].getTime(); 16.44 + } else { 16.45 + array[i] = arguments[i+1]; 16.46 + } 16.47 + } 16.48 + 16.49 + array = Java.toJavaArray(array); 16.50 + return Packages.jdk.nashorn.api.scripting.ScriptUtils.format(format, array); 16.51 + } 16.52 +});
17.1 --- a/src/jdk/nashorn/api/scripting/resources/init.js Thu Mar 28 10:55:17 2013 -0700 17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 17.3 @@ -1,939 +0,0 @@ 17.4 -/* 17.5 - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. 17.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 17.7 - * 17.8 - * This code is free software; you can redistribute it and/or modify it 17.9 - * under the terms of the GNU General Public License version 2 only, as 17.10 - * published by the Free Software Foundation. Oracle designates this 17.11 - * particular file as subject to the "Classpath" exception as provided 17.12 - * by Oracle in the LICENSE file that accompanied this code. 17.13 - * 17.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 17.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17.17 - * version 2 for more details (a copy is included in the LICENSE file that 17.18 - * accompanied this code). 17.19 - * 17.20 - * You should have received a copy of the GNU General Public License version 17.21 - * 2 along with this work; if not, write to the Free Software Foundation, 17.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17.23 - * 17.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 17.25 - * or visit www.oracle.com if you need additional information or have any 17.26 - * questions. 17.27 - */ 17.28 - 17.29 -/** 17.30 - * jrunscript JavaScript built-in functions and objects. 17.31 - */ 17.32 - 17.33 -/** 17.34 - * Creates an object that delegates all method calls on 17.35 - * it to the 'invoke' method on the given delegate object.<br> 17.36 - * 17.37 - * Example: 17.38 - * <pre> 17.39 - * <code> 17.40 - * var x = { invoke: function(name, args) { //code...} 17.41 - * var y = new JSInvoker(x); 17.42 - * y.func(3, 3); // calls x.invoke('func', args); where args is array of arguments 17.43 - * </code> 17.44 - * </pre> 17.45 - * @param obj object to be wrapped by JSInvoker 17.46 - * @constructor 17.47 - */ 17.48 -function JSInvoker(obj) { 17.49 - return new JSAdapter({ 17.50 - __get__ : function(name) { 17.51 - return function() { 17.52 - return obj.invoke(name, arguments); 17.53 - } 17.54 - } 17.55 - }); 17.56 -} 17.57 - 17.58 -/** 17.59 - * This variable represents OS environment. Environment 17.60 - * variables can be accessed as fields of this object. For 17.61 - * example, env.PATH will return PATH value configured. 17.62 - */ 17.63 -var env = new JSAdapter({ 17.64 - __get__ : function (name) { 17.65 - return java.lang.System.getenv(name); 17.66 - }, 17.67 - __has__ : function (name) { 17.68 - return java.lang.System.getenv().containsKey(name); 17.69 - }, 17.70 - __getIds__ : function() { 17.71 - return java.lang.System.getenv().keySet().toArray(); 17.72 - }, 17.73 - __delete__ : function(name) { 17.74 - println("can't delete env item"); 17.75 - }, 17.76 - __put__ : function (name, value) { 17.77 - println("can't change env item"); 17.78 - }, 17.79 - toString: function() { 17.80 - return java.lang.System.getenv().toString(); 17.81 - } 17.82 -}); 17.83 - 17.84 -/** 17.85 - * Creates a convenient script object to deal with java.util.Map instances. 17.86 - * The result script object's field names are keys of the Map. For example, 17.87 - * scriptObj.keyName can be used to access value associated with given key.<br> 17.88 - * Example: 17.89 - * <pre> 17.90 - * <code> 17.91 - * var x = java.lang.SystemProperties(); 17.92 - * var y = jmap(x); 17.93 - * println(y['java.class.path']); // prints java.class.path System property 17.94 - * delete y['java.class.path']; // remove java.class.path System property 17.95 - * </code> 17.96 - * </pre> 17.97 - * 17.98 - * @param map java.util.Map instance that will be wrapped 17.99 - * @constructor 17.100 - */ 17.101 -function jmap(map) { 17.102 - return new JSAdapter({ 17.103 - __get__ : function(name) { 17.104 - if (map.containsKey(name)) { 17.105 - return map.get(name); 17.106 - } else { 17.107 - return undefined; 17.108 - } 17.109 - }, 17.110 - __has__ : function(name) { 17.111 - return map.containsKey(name); 17.112 - }, 17.113 - 17.114 - __delete__ : function (name) { 17.115 - return map.remove(name); 17.116 - }, 17.117 - __put__ : function(name, value) { 17.118 - map.put(name, value); 17.119 - }, 17.120 - __getIds__ : function() { 17.121 - return map.keySet().toArray(); 17.122 - }, 17.123 - toString: function() { 17.124 - return map.toString(); 17.125 - } 17.126 - }); 17.127 -} 17.128 - 17.129 -/** 17.130 - * Creates a convenient script object to deal with java.util.List instances. 17.131 - * The result script object behaves like an array. For example, 17.132 - * scriptObj[index] syntax can be used to access values in the List instance. 17.133 - * 'length' field gives size of the List. <br> 17.134 - * 17.135 - * Example: 17.136 - * <pre> 17.137 - * <code> 17.138 - * var x = new java.util.ArrayList(4); 17.139 - * x.add('Java'); 17.140 - * x.add('JavaScript'); 17.141 - * x.add('SQL'); 17.142 - * x.add('XML'); 17.143 - * 17.144 - * var y = jlist(x); 17.145 - * println(y[2]); // prints third element of list 17.146 - * println(y.length); // prints size of the list 17.147 - * 17.148 - * @param map java.util.List instance that will be wrapped 17.149 - * @constructor 17.150 - */ 17.151 -function jlist(list) { 17.152 - function isValid(index) { 17.153 - return typeof(index) == 'number' && 17.154 - index > -1 && index < list.size(); 17.155 - } 17.156 - return new JSAdapter({ 17.157 - __get__ : function(name) { 17.158 - if (isValid(name)) { 17.159 - return list.get(name); 17.160 - } else if (name == 'length') { 17.161 - return list.size(); 17.162 - } else { 17.163 - return undefined; 17.164 - } 17.165 - }, 17.166 - __has__ : function (name) { 17.167 - return isValid(name) || name == 'length'; 17.168 - }, 17.169 - __delete__ : function(name) { 17.170 - if (isValid(name)) { 17.171 - list.remove(name); 17.172 - } 17.173 - }, 17.174 - __put__ : function(name, value) { 17.175 - if (isValid(name)) { 17.176 - list.set(name, value); 17.177 - } 17.178 - }, 17.179 - __getIds__: function() { 17.180 - var res = new Array(list.size()); 17.181 - for (var i = 0; i < res.length; i++) { 17.182 - res[i] = i; 17.183 - } 17.184 - return res; 17.185 - }, 17.186 - toString: function() { 17.187 - return list.toString(); 17.188 - } 17.189 - }); 17.190 -} 17.191 - 17.192 -/** 17.193 - * This is java.lang.System properties wrapped by JSAdapter. 17.194 - * For eg. to access java.class.path property, you can use 17.195 - * the syntax sysProps["java.class.path"] 17.196 - */ 17.197 -var sysProps = new JSAdapter({ 17.198 - __get__ : function (name) { 17.199 - return java.lang.System.getProperty(name); 17.200 - }, 17.201 - __has__ : function (name) { 17.202 - return java.lang.System.getProperty(name) != null; 17.203 - }, 17.204 - __getIds__ : function() { 17.205 - return java.lang.System.getProperties().keySet().toArray(); 17.206 - }, 17.207 - __delete__ : function(name) { 17.208 - java.lang.System.clearProperty(name); 17.209 - return true; 17.210 - }, 17.211 - __put__ : function (name, value) { 17.212 - java.lang.System.setProperty(name, value); 17.213 - }, 17.214 - toString: function() { 17.215 - return "<system properties>"; 17.216 - } 17.217 -}); 17.218 - 17.219 -// stdout, stderr & stdin 17.220 -var out = java.lang.System.out; 17.221 -var err = java.lang.System.err; 17.222 -// can't use 'in' because it is a JavaScript keyword :-( 17.223 -var inp = java.lang.System["in"]; 17.224 - 17.225 -var BufferedInputStream = java.io.BufferedInputStream; 17.226 -var BufferedOutputStream = java.io.BufferedOutputStream; 17.227 -var BufferedReader = java.io.BufferedReader; 17.228 -var DataInputStream = java.io.DataInputStream; 17.229 -var File = java.io.File; 17.230 -var FileInputStream = java.io.FileInputStream; 17.231 -var FileOutputStream = java.io.FileOutputStream; 17.232 -var InputStream = java.io.InputStream; 17.233 -var InputStreamReader = java.io.InputStreamReader; 17.234 -var OutputStream = java.io.OutputStream; 17.235 -var Reader = java.io.Reader; 17.236 -var URL = java.net.URL; 17.237 - 17.238 -/** 17.239 - * Generic any object to input stream mapper 17.240 - * @param str input file name, URL or InputStream 17.241 - * @return InputStream object 17.242 - * @private 17.243 - */ 17.244 -function inStream(str) { 17.245 - if (typeof(str) == "string") { 17.246 - // '-' means standard input 17.247 - if (str == '-') { 17.248 - return java.lang.System["in"]; 17.249 - } 17.250 - // try file first 17.251 - var file = null; 17.252 - try { 17.253 - file = pathToFile(str); 17.254 - } catch (e) { 17.255 - } 17.256 - if (file && file.exists()) { 17.257 - return new FileInputStream(file); 17.258 - } else { 17.259 - try { 17.260 - // treat the string as URL 17.261 - return new URL(str).openStream(); 17.262 - } catch (e) { 17.263 - throw 'file or URL ' + str + ' not found'; 17.264 - } 17.265 - } 17.266 - } else { 17.267 - if (str instanceof InputStream) { 17.268 - return str; 17.269 - } else if (str instanceof URL) { 17.270 - return str.openStream(); 17.271 - } else if (str instanceof File) { 17.272 - return new FileInputStream(str); 17.273 - } 17.274 - } 17.275 - // everything failed, just give input stream 17.276 - return java.lang.System["in"]; 17.277 -} 17.278 - 17.279 -/** 17.280 - * Generic any object to output stream mapper 17.281 - * 17.282 - * @param out output file name or stream 17.283 - * @return OutputStream object 17.284 - * @private 17.285 - */ 17.286 -function outStream(out) { 17.287 - if (typeof(out) == "string") { 17.288 - if (out == '>') { 17.289 - return java.lang.System.out; 17.290 - } else { 17.291 - // treat it as file 17.292 - return new FileOutputStream(pathToFile(out)); 17.293 - } 17.294 - } else { 17.295 - if (out instanceof OutputStream) { 17.296 - return out; 17.297 - } else if (out instanceof File) { 17.298 - return new FileOutputStream(out); 17.299 - } 17.300 - } 17.301 - 17.302 - // everything failed, just return System.out 17.303 - return java.lang.System.out; 17.304 -} 17.305 - 17.306 -/** 17.307 - * stream close takes care not to close stdin, out & err. 17.308 - * @private 17.309 - */ 17.310 -function streamClose(stream) { 17.311 - if (stream) { 17.312 - if (stream != java.lang.System["in"] && 17.313 - stream != java.lang.System.out && 17.314 - stream != java.lang.System.err) { 17.315 - try { 17.316 - stream.close(); 17.317 - } catch (e) { 17.318 - println(e); 17.319 - } 17.320 - } 17.321 - } 17.322 -} 17.323 - 17.324 -/** 17.325 - * Loads and evaluates JavaScript code from a stream or file or URL<br> 17.326 - * 17.327 - * Examples: 17.328 - * <pre> 17.329 - * <code> 17.330 - * load('test.js'); // load script file 'test.js' 17.331 - * load('http://java.sun.com/foo.js'); // load from a URL 17.332 - * </code> 17.333 - * </pre> 17.334 - * 17.335 - * @param str input from which script is loaded and evaluated 17.336 - */ 17.337 -if (typeof(load) == 'undefined') { 17.338 - var load = function(str) { 17.339 - var stream = inStream(str); 17.340 - var bstream = new BufferedInputStream(stream); 17.341 - var reader = new BufferedReader(new InputStreamReader(bstream)); 17.342 - var oldFilename = engine.get(engine.FILENAME); 17.343 - engine.put(engine.FILENAME, str); 17.344 - try { 17.345 - engine.eval(reader); 17.346 - } finally { 17.347 - engine.put(engine.FILENAME, oldFilename); 17.348 - streamClose(stream); 17.349 - } 17.350 - } 17.351 -} 17.352 - 17.353 -// file system utilities 17.354 - 17.355 -/** 17.356 - * Creates a Java byte[] of given length 17.357 - * @param len size of the array to create 17.358 - * @private 17.359 - */ 17.360 -function javaByteArray(len) { 17.361 - return java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, len); 17.362 -} 17.363 - 17.364 -var curDir = new File('.'); 17.365 - 17.366 -/** 17.367 - * Print present working directory 17.368 - */ 17.369 -function pwd() { 17.370 - println(curDir.getAbsolutePath()); 17.371 -} 17.372 - 17.373 -/** 17.374 - * Changes present working directory to given directory 17.375 - * @param target directory to change to. optional, defaults to user's HOME 17.376 - */ 17.377 -function cd(target) { 17.378 - if (target == undefined) { 17.379 - target = sysProps["user.home"]; 17.380 - } 17.381 - if (!(target instanceof File)) { 17.382 - target = pathToFile(target); 17.383 - } 17.384 - if (target.exists() && target.isDirectory()) { 17.385 - curDir = target; 17.386 - } else { 17.387 - println(target + " is not a directory"); 17.388 - } 17.389 -} 17.390 - 17.391 -/** 17.392 - * Converts path to java.io.File taking care of shell present working dir 17.393 - * 17.394 - * @param pathname file path to be converted 17.395 - * @private 17.396 - */ 17.397 -function pathToFile(pathname) { 17.398 - var tmp = pathname; 17.399 - if (!(tmp instanceof File)) { 17.400 - tmp = new File(tmp); 17.401 - } 17.402 - if (!tmp.isAbsolute()) { 17.403 - return new File(curDir, pathname); 17.404 - } else { 17.405 - return tmp; 17.406 - } 17.407 -} 17.408 - 17.409 -/** 17.410 - * Copies a file or URL or stream to another file or stream 17.411 - * 17.412 - * @param from input file or URL or stream 17.413 - * @param to output stream or file 17.414 - */ 17.415 -function cp(from, to) { 17.416 - if (from == to) { 17.417 - println("file " + from + " cannot be copied onto itself!"); 17.418 - return; 17.419 - } 17.420 - var inp = inStream(from); 17.421 - var out = outStream(to); 17.422 - var binp = new BufferedInputStream(inp); 17.423 - var bout = new BufferedOutputStream(out); 17.424 - var buff = javaByteArray(1024); 17.425 - var len; 17.426 - while ((len = binp.read(buff)) > 0 ) 17.427 - bout.write(buff, 0, len); 17.428 - 17.429 - bout.flush(); 17.430 - streamClose(inp); 17.431 - streamClose(out); 17.432 -} 17.433 - 17.434 -/** 17.435 - * Shows the content of a file or URL or any InputStream<br> 17.436 - * Examples: 17.437 - * <pre> 17.438 - * <code> 17.439 - * cat('test.txt'); // show test.txt file contents 17.440 - * cat('http://java.net'); // show the contents from the URL http://java.net 17.441 - * </code> 17.442 - * </pre> 17.443 - * @param obj input to show 17.444 - * @param pattern optional. show only the lines matching the pattern 17.445 - */ 17.446 -function cat(obj, pattern) { 17.447 - if (obj instanceof File && obj.isDirectory()) { 17.448 - ls(obj); 17.449 - return; 17.450 - } 17.451 - 17.452 - var inp = null; 17.453 - if (!(obj instanceof Reader)) { 17.454 - inp = inStream(obj); 17.455 - obj = new BufferedReader(new InputStreamReader(inp)); 17.456 - } 17.457 - var line; 17.458 - if (pattern) { 17.459 - var count = 1; 17.460 - while ((line=obj.readLine()) != null) { 17.461 - if (line.match(pattern)) { 17.462 - println(count + "\t: " + line); 17.463 - } 17.464 - count++; 17.465 - } 17.466 - } else { 17.467 - while ((line=obj.readLine()) != null) { 17.468 - println(line); 17.469 - } 17.470 - } 17.471 -} 17.472 - 17.473 -/** 17.474 - * Returns directory part of a filename 17.475 - * 17.476 - * @param pathname input path name 17.477 - * @return directory part of the given file name 17.478 - */ 17.479 -function dirname(pathname) { 17.480 - var dirName = "."; 17.481 - // Normalize '/' to local file separator before work. 17.482 - var i = pathname.replace('/', File.separatorChar ).lastIndexOf( 17.483 - File.separator ); 17.484 - if ( i != -1 ) 17.485 - dirName = pathname.substring(0, i); 17.486 - return dirName; 17.487 -} 17.488 - 17.489 -/** 17.490 - * Creates a new dir of given name 17.491 - * 17.492 - * @param dir name of the new directory 17.493 - */ 17.494 -function mkdir(dir) { 17.495 - dir = pathToFile(dir); 17.496 - println(dir.mkdir()? "created" : "can not create dir"); 17.497 -} 17.498 - 17.499 -/** 17.500 - * Creates the directory named by given pathname, including 17.501 - * any necessary but nonexistent parent directories. 17.502 - * 17.503 - * @param dir input path name 17.504 - */ 17.505 -function mkdirs(dir) { 17.506 - dir = pathToFile(dir); 17.507 - println(dir.mkdirs()? "created" : "can not create dirs"); 17.508 -} 17.509 - 17.510 -/** 17.511 - * Removes a given file 17.512 - * 17.513 - * @param pathname name of the file 17.514 - */ 17.515 -function rm(pathname) { 17.516 - var file = pathToFile(pathname); 17.517 - if (!file.exists()) { 17.518 - println("file not found: " + pathname); 17.519 - return false; 17.520 - } 17.521 - // note that delete is a keyword in JavaScript! 17.522 - println(file["delete"]()? "deleted" : "can not delete"); 17.523 -} 17.524 - 17.525 -/** 17.526 - * Removes a given directory 17.527 - * 17.528 - * @param pathname name of the directory 17.529 - */ 17.530 -function rmdir(pathname) { 17.531 - rm(pathname); 17.532 -} 17.533 - 17.534 -/** 17.535 - * Synonym for 'rm' 17.536 - */ 17.537 -function del(pathname) { 17.538 - rm(pathname); 17.539 -} 17.540 - 17.541 -/** 17.542 - * Moves a file to another 17.543 - * 17.544 - * @param from original name of the file 17.545 - * @param to new name for the file 17.546 - */ 17.547 -function mv(from, to) { 17.548 - println(pathToFile(from).renameTo(pathToFile(to))? 17.549 - "moved" : "can not move"); 17.550 -} 17.551 - 17.552 -/** 17.553 - * Synonym for 'mv'. 17.554 - */ 17.555 -function ren(from, to) { 17.556 - mv(from, to); 17.557 -} 17.558 - 17.559 -var months = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", 17.560 - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]; 17.561 - 17.562 -/** 17.563 - * Helper function called by ls 17.564 - * @private 17.565 - */ 17.566 -function printFile(f) { 17.567 - var sb = new java.lang.StringBuffer(); 17.568 - sb.append(f.isDirectory()? "d" : "-"); 17.569 - sb.append(f.canRead() ? "r": "-" ); 17.570 - sb.append(f.canWrite() ? "w": "-" ); 17.571 - sb.append(" "); 17.572 - 17.573 - var d = new java.util.Date(f.lastModified()); 17.574 - var c = new java.util.GregorianCalendar(); 17.575 - c.setTime(d); 17.576 - var day = c.get(java.util.Calendar.DAY_OF_MONTH); 17.577 - sb.append(months[c.get(java.util.Calendar.MONTH)] 17.578 - + " " + day ); 17.579 - if (day < 10) { 17.580 - sb.append(" "); 17.581 - } 17.582 - 17.583 - // to get fixed length 'length' field 17.584 - var fieldlen = 8; 17.585 - var len = new java.lang.StringBuffer(); 17.586 - for(var j=0; j<fieldlen; j++) 17.587 - len.append(" "); 17.588 - len.insert(0, java.lang.Long.toString(f.length())); 17.589 - len.setLength(fieldlen); 17.590 - // move the spaces to the front 17.591 - var si = len.toString().indexOf(" "); 17.592 - if ( si != -1 ) { 17.593 - var pad = len.toString().substring(si); 17.594 - len.setLength(si); 17.595 - len.insert(0, pad); 17.596 - } 17.597 - sb.append(len.toString()); 17.598 - sb.append(" "); 17.599 - sb.append(f.getName()); 17.600 - if (f.isDirectory()) { 17.601 - sb.append('/'); 17.602 - } 17.603 - println(sb.toString()); 17.604 -} 17.605 - 17.606 -/** 17.607 - * Lists the files in a directory 17.608 - * 17.609 - * @param dir directory from which to list the files. optional, default to pwd 17.610 - * @param filter pattern to filter the files listed. optional, default is '.'. 17.611 - */ 17.612 -function ls(dir, filter) { 17.613 - if (dir) { 17.614 - dir = pathToFile(dir); 17.615 - } else { 17.616 - dir = curDir; 17.617 - } 17.618 - if (dir.isDirectory()) { 17.619 - var files = dir.listFiles(); 17.620 - for (var i in files) { 17.621 - var f = files[i]; 17.622 - if (filter) { 17.623 - if(!f.getName().match(filter)) { 17.624 - continue; 17.625 - } 17.626 - } 17.627 - printFile(f); 17.628 - } 17.629 - } else { 17.630 - printFile(dir); 17.631 - } 17.632 -} 17.633 - 17.634 -/** 17.635 - * Synonym for 'ls'. 17.636 - */ 17.637 -function dir(d, filter) { 17.638 - ls(d, filter); 17.639 -} 17.640 - 17.641 -/** 17.642 - * Unix-like grep, but accepts JavaScript regex patterns 17.643 - * 17.644 - * @param pattern to search in files 17.645 - * @param files one or more files 17.646 - */ 17.647 -function grep(pattern, files /*, one or more files */) { 17.648 - if (arguments.length < 2) return; 17.649 - for (var i = 1; i < arguments.length; i++) { 17.650 - println(arguments[i] + ":"); 17.651 - cat(arguments[i], pattern); 17.652 - } 17.653 -} 17.654 - 17.655 -/** 17.656 - * Find in files. Calls arbitrary callback function 17.657 - * for each matching file.<br> 17.658 - * 17.659 - * Examples: 17.660 - * <pre> 17.661 - * <code> 17.662 - * find('.') 17.663 - * find('.', '.*\.class', rm); // remove all .class files 17.664 - * find('.', '.*\.java'); // print fullpath of each .java file 17.665 - * find('.', '.*\.java', cat); // print all .java files 17.666 - * </code> 17.667 - * </pre> 17.668 - * 17.669 - * @param dir directory to search files 17.670 - * @param pattern to search in the files 17.671 - * @param callback function to call for matching files 17.672 - */ 17.673 -function find(dir, pattern, callback) { 17.674 - dir = pathToFile(dir); 17.675 - if (!callback) callback = print; 17.676 - var files = dir.listFiles(); 17.677 - for (var f in files) { 17.678 - var file = files[f]; 17.679 - if (file.isDirectory()) { 17.680 - find(file, pattern, callback); 17.681 - } else { 17.682 - if (pattern) { 17.683 - if (file.getName().match(pattern)) { 17.684 - callback(file); 17.685 - } 17.686 - } else { 17.687 - callback(file); 17.688 - } 17.689 - } 17.690 - } 17.691 -} 17.692 - 17.693 -// process utilities 17.694 - 17.695 -/** 17.696 - * Exec's a child process, waits for completion & returns exit code 17.697 - * 17.698 - * @param cmd command to execute in child process 17.699 - */ 17.700 -function exec(cmd) { 17.701 - var process = java.lang.Runtime.getRuntime().exec(cmd); 17.702 - var inp = new DataInputStream(process.getInputStream()); 17.703 - var line = null; 17.704 - while ((line = inp.readLine()) != null) { 17.705 - println(line); 17.706 - } 17.707 - process.waitFor(); 17.708 - $exit = process.exitValue(); 17.709 -} 17.710 - 17.711 -// XML utilities 17.712 - 17.713 -/** 17.714 - * Converts input to DOM Document object 17.715 - * 17.716 - * @param inp file or reader. optional, without this param, 17.717 - * this function returns a new DOM Document. 17.718 - * @return returns a DOM Document object 17.719 - */ 17.720 -function XMLDocument(inp) { 17.721 - var factory = javax.xml.parsers.DocumentBuilderFactory.newInstance(); 17.722 - var builder = factory.newDocumentBuilder(); 17.723 - if (inp) { 17.724 - if (typeof(inp) == "string") { 17.725 - return builder.parse(pathToFile(inp)); 17.726 - } else { 17.727 - return builder.parse(inp); 17.728 - } 17.729 - } else { 17.730 - return builder.newDocument(); 17.731 - } 17.732 -} 17.733 - 17.734 -/** 17.735 - * Converts arbitrary stream, file, URL to XMLSource 17.736 - * 17.737 - * @param inp input stream or file or URL 17.738 - * @return XMLSource object 17.739 - */ 17.740 -function XMLSource(inp) { 17.741 - if (inp instanceof javax.xml.transform.Source) { 17.742 - return inp; 17.743 - } else if (inp instanceof Packages.org.w3c.dom.Document) { 17.744 - return new javax.xml.transform.dom.DOMSource(inp); 17.745 - } else { 17.746 - inp = new BufferedInputStream(inStream(inp)); 17.747 - return new javax.xml.transform.stream.StreamSource(inp); 17.748 - } 17.749 -} 17.750 - 17.751 -/** 17.752 - * Converts arbitrary stream, file to XMLResult 17.753 - * 17.754 - * @param inp output stream or file 17.755 - * @return XMLResult object 17.756 - */ 17.757 -function XMLResult(out) { 17.758 - if (out instanceof javax.xml.transform.Result) { 17.759 - return out; 17.760 - } else if (out instanceof Packages.org.w3c.dom.Document) { 17.761 - return new javax.xml.transform.dom.DOMResult(out); 17.762 - } else { 17.763 - out = new BufferedOutputStream(outStream(out)); 17.764 - return new javax.xml.transform.stream.StreamResult(out); 17.765 - } 17.766 -} 17.767 - 17.768 -/** 17.769 - * Perform XSLT transform 17.770 - * 17.771 - * @param inp Input XML to transform (URL, File or InputStream) 17.772 - * @param style XSL Stylesheet to be used (URL, File or InputStream). optional. 17.773 - * @param out Output XML (File or OutputStream 17.774 - */ 17.775 -function XSLTransform(inp, style, out) { 17.776 - switch (arguments.length) { 17.777 - case 2: 17.778 - inp = arguments[0]; 17.779 - out = arguments[1]; 17.780 - break; 17.781 - case 3: 17.782 - inp = arguments[0]; 17.783 - style = arguments[1]; 17.784 - out = arguments[2]; 17.785 - break; 17.786 - default: 17.787 - println("XSL tranform requires 2 or 3 arguments"); 17.788 - return; 17.789 - } 17.790 - 17.791 - var factory = javax.xml.transform.TransformerFactory.newInstance(); 17.792 - var transformer; 17.793 - if (style) { 17.794 - transformer = factory.newTransformer(XMLSource(style)); 17.795 - } else { 17.796 - transformer = factory.newTransformer(); 17.797 - } 17.798 - var source = XMLSource(inp); 17.799 - var result = XMLResult(out); 17.800 - transformer.transform(source, result); 17.801 - if (source.getInputStream) { 17.802 - streamClose(source.getInputStream()); 17.803 - } 17.804 - if (result.getOutputStream) { 17.805 - streamClose(result.getOutputStream()); 17.806 - } 17.807 -} 17.808 - 17.809 -// miscellaneous utilities 17.810 - 17.811 -/** 17.812 - * Prints which command is selected from PATH 17.813 - * 17.814 - * @param cmd name of the command searched from PATH 17.815 - */ 17.816 -function which(cmd) { 17.817 - var st = new java.util.StringTokenizer(env.PATH, File.pathSeparator); 17.818 - while (st.hasMoreTokens()) { 17.819 - var file = new File(st.nextToken(), cmd); 17.820 - if (file.exists()) { 17.821 - println(file.getAbsolutePath()); 17.822 - return; 17.823 - } 17.824 - } 17.825 -} 17.826 - 17.827 -/** 17.828 - * Prints IP addresses of given domain name 17.829 - * 17.830 - * @param name domain name 17.831 - */ 17.832 -function ip(name) { 17.833 - var addrs = InetAddress.getAllByName(name); 17.834 - for (var i in addrs) { 17.835 - println(addrs[i]); 17.836 - } 17.837 -} 17.838 - 17.839 -/** 17.840 - * Prints current date in current locale 17.841 - */ 17.842 -function date() { 17.843 - println(new Date().toLocaleString()); 17.844 -} 17.845 - 17.846 -/** 17.847 - * Echoes the given string arguments 17.848 - */ 17.849 -function echo(x) { 17.850 - for (var i = 0; i < arguments.length; i++) { 17.851 - println(arguments[i]); 17.852 - } 17.853 -} 17.854 - 17.855 -/** 17.856 - * Reads one or more lines from stdin after printing prompt 17.857 - * 17.858 - * @param prompt optional, default is '>' 17.859 - * @param multiline to tell whether to read single line or multiple lines 17.860 - */ 17.861 -function read(prompt, multiline) { 17.862 - if (!prompt) { 17.863 - prompt = '>'; 17.864 - } 17.865 - var inp = java.lang.System["in"]; 17.866 - var reader = new BufferedReader(new InputStreamReader(inp)); 17.867 - if (multiline) { 17.868 - var line = ''; 17.869 - while (true) { 17.870 - java.lang.System.err.print(prompt); 17.871 - java.lang.System.err.flush(); 17.872 - var tmp = reader.readLine(); 17.873 - if (tmp == '' || tmp == null) break; 17.874 - line += tmp + '\n'; 17.875 - } 17.876 - return line; 17.877 - } else { 17.878 - java.lang.System.err.print(prompt); 17.879 - java.lang.System.err.flush(); 17.880 - return reader.readLine(); 17.881 - } 17.882 -} 17.883 - 17.884 -if (typeof(println) == 'undefined') { 17.885 - var print = function(str, newline) { 17.886 - if (typeof(str) == 'undefined') { 17.887 - str = 'undefined'; 17.888 - } else if (str == null) { 17.889 - str = 'null'; 17.890 - } 17.891 - 17.892 - if (!(out instanceof java.io.PrintWriter)) { 17.893 - out = new java.io.PrintWriter(out); 17.894 - } 17.895 - 17.896 - out.print(String(str)); 17.897 - if (newline) { 17.898 - out.print('\n'); 17.899 - } 17.900 - out.flush(); 17.901 - } 17.902 - 17.903 - var println = function(str) { 17.904 - print(str, true); 17.905 - }; 17.906 -} 17.907 - 17.908 -/** 17.909 - * This is C-like printf 17.910 - * 17.911 - * @param format string to format the rest of the print items 17.912 - * @param args variadic argument list 17.913 - */ 17.914 -function printf(format, args/*, more args*/) { 17.915 - print(sprintf.apply(this, arguments)); 17.916 -} 17.917 - 17.918 -/** 17.919 - * This is C-like sprintf 17.920 - * 17.921 - * @param format string to format the rest of the print items 17.922 - * @param args variadic argument list 17.923 - */ 17.924 -function sprintf(format, args/*, more args*/) { 17.925 - var len = arguments.length - 1; 17.926 - var array = []; 17.927 - 17.928 - if (len < 0) { 17.929 - return ""; 17.930 - } 17.931 - 17.932 - for (var i = 0; i < len; i++) { 17.933 - if (arguments[i+1] instanceof Date) { 17.934 - array[i] = arguments[i+1].getTime(); 17.935 - } else { 17.936 - array[i] = arguments[i+1]; 17.937 - } 17.938 - } 17.939 - 17.940 - array = Java.toJavaArray(array); 17.941 - return Packages.jdk.nashorn.api.scripting.Formatter.format(format, array); 17.942 -}
18.1 --- a/src/jdk/nashorn/internal/codegen/Attr.java Thu Mar 28 10:55:17 2013 -0700 18.2 +++ b/src/jdk/nashorn/internal/codegen/Attr.java Mon Apr 01 21:42:31 2013 -0700 18.3 @@ -37,13 +37,16 @@ 18.4 import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL; 18.5 import static jdk.nashorn.internal.ir.Symbol.IS_LET; 18.6 import static jdk.nashorn.internal.ir.Symbol.IS_PARAM; 18.7 +import static jdk.nashorn.internal.ir.Symbol.IS_SCOPE; 18.8 import static jdk.nashorn.internal.ir.Symbol.IS_THIS; 18.9 import static jdk.nashorn.internal.ir.Symbol.IS_VAR; 18.10 +import static jdk.nashorn.internal.ir.Symbol.KINDMASK; 18.11 18.12 import java.util.ArrayList; 18.13 import java.util.HashSet; 18.14 -import java.util.LinkedList; 18.15 +import java.util.Iterator; 18.16 import java.util.List; 18.17 +import java.util.ListIterator; 18.18 import java.util.Set; 18.19 import jdk.nashorn.internal.codegen.types.Type; 18.20 import jdk.nashorn.internal.ir.AccessNode; 18.21 @@ -55,14 +58,15 @@ 18.22 import jdk.nashorn.internal.ir.CatchNode; 18.23 import jdk.nashorn.internal.ir.ForNode; 18.24 import jdk.nashorn.internal.ir.FunctionNode; 18.25 +import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 18.26 import jdk.nashorn.internal.ir.IdentNode; 18.27 import jdk.nashorn.internal.ir.IndexNode; 18.28 +import jdk.nashorn.internal.ir.LexicalContext; 18.29 import jdk.nashorn.internal.ir.LiteralNode; 18.30 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 18.31 import jdk.nashorn.internal.ir.Node; 18.32 import jdk.nashorn.internal.ir.ObjectNode; 18.33 import jdk.nashorn.internal.ir.PropertyNode; 18.34 -import jdk.nashorn.internal.ir.ReferenceNode; 18.35 import jdk.nashorn.internal.ir.ReturnNode; 18.36 import jdk.nashorn.internal.ir.RuntimeNode; 18.37 import jdk.nashorn.internal.ir.RuntimeNode.Request; 18.38 @@ -115,6 +119,8 @@ 18.39 */ 18.40 private Set<String> localUses; 18.41 18.42 + private final LexicalContext lexicalContext = new LexicalContext(); 18.43 + 18.44 private static final DebugLogger LOG = new DebugLogger("attr"); 18.45 private static final boolean DEBUG = LOG.isEnabled(); 18.46 18.47 @@ -135,14 +141,15 @@ 18.48 } 18.49 18.50 @Override 18.51 - public Node leave(final AccessNode accessNode) { 18.52 + public Node leaveAccessNode(final AccessNode accessNode) { 18.53 newTemporary(Type.OBJECT, accessNode); //While Object type is assigned here, Access Specialization in FinalizeTypes may narrow this 18.54 end(accessNode); 18.55 return accessNode; 18.56 } 18.57 18.58 @Override 18.59 - public Node enter(final Block block) { 18.60 + public Node enterBlock(final Block block) { 18.61 + lexicalContext.push(block); 18.62 start(block); 18.63 18.64 final Set<String> savedLocalDefs = localDefs; 18.65 @@ -158,9 +165,7 @@ 18.66 localDefs = new HashSet<>(savedLocalDefs); 18.67 localUses = new HashSet<>(savedLocalUses); 18.68 18.69 - for (final Node statement : block.getStatements()) { 18.70 - statement.accept(this); 18.71 - } 18.72 + block.visitStatements(this); 18.73 } finally { 18.74 localDefs = savedLocalDefs; 18.75 localUses = savedLocalUses; 18.76 @@ -170,11 +175,12 @@ 18.77 18.78 end(block); 18.79 18.80 + lexicalContext.pop(block); 18.81 return null; 18.82 } 18.83 18.84 @Override 18.85 - public Node enter(final CallNode callNode) { 18.86 + public Node enterCallNode(final CallNode callNode) { 18.87 start(callNode); 18.88 18.89 callNode.getFunction().accept(this); 18.90 @@ -195,8 +201,7 @@ 18.91 evalArgs.setThis(thisNode); 18.92 } 18.93 18.94 - newTemporary(Type.OBJECT, callNode); // object type here, access specialization in FinalizeTypes may narrow it later 18.95 - newType(callNode.getFunction().getSymbol(), Type.OBJECT); 18.96 + newTemporary(callNode.getType(), callNode); // access specialization in FinalizeTypes may narrow it further later 18.97 18.98 end(callNode); 18.99 18.100 @@ -204,29 +209,106 @@ 18.101 } 18.102 18.103 @Override 18.104 - public Node enter(final CatchNode catchNode) { 18.105 + public Node enterCatchNode(final CatchNode catchNode) { 18.106 final IdentNode exception = catchNode.getException(); 18.107 final Block block = getCurrentBlock(); 18.108 18.109 start(catchNode); 18.110 18.111 // define block-local exception variable 18.112 - final Symbol def = block.defineSymbol(exception.getName(), IS_VAR | IS_LET, exception); 18.113 + final Symbol def = defineSymbol(block, exception.getName(), IS_VAR | IS_LET, exception); 18.114 newType(def, Type.OBJECT); 18.115 addLocalDef(exception.getName()); 18.116 18.117 return catchNode; 18.118 } 18.119 18.120 + /** 18.121 + * Declare the definition of a new symbol. 18.122 + * 18.123 + * @param name Name of symbol. 18.124 + * @param symbolFlags Symbol flags. 18.125 + * @param node Defining Node. 18.126 + * 18.127 + * @return Symbol for given name or null for redefinition. 18.128 + */ 18.129 + private Symbol defineSymbol(final Block block, final String name, final int symbolFlags, final Node node) { 18.130 + int flags = symbolFlags; 18.131 + Symbol symbol = findSymbol(block, name); // Locate symbol. 18.132 + 18.133 + if ((flags & KINDMASK) == IS_GLOBAL) { 18.134 + flags |= IS_SCOPE; 18.135 + } 18.136 + 18.137 + final FunctionNode function = lexicalContext.getFunction(block); 18.138 + if (symbol != null) { 18.139 + // Symbol was already defined. Check if it needs to be redefined. 18.140 + if ((flags & KINDMASK) == IS_PARAM) { 18.141 + if (!isLocal(function, symbol)) { 18.142 + // Not defined in this function. Create a new definition. 18.143 + symbol = null; 18.144 + } else if (symbol.isParam()) { 18.145 + // Duplicate parameter. Null return will force an error. 18.146 + assert false : "duplicate parameter"; 18.147 + return null; 18.148 + } 18.149 + } else if ((flags & KINDMASK) == IS_VAR) { 18.150 + if ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET) { 18.151 + assert !((flags & IS_LET) == IS_LET && symbol.getBlock() == block) : "duplicate let variable in block"; 18.152 + // Always create a new definition. 18.153 + symbol = null; 18.154 + } else { 18.155 + // Not defined in this function. Create a new definition. 18.156 + if (!isLocal(function, symbol) || symbol.less(IS_VAR)) { 18.157 + symbol = null; 18.158 + } 18.159 + } 18.160 + } 18.161 + } 18.162 + 18.163 + if (symbol == null) { 18.164 + // If not found, then create a new one. 18.165 + Block symbolBlock; 18.166 + 18.167 + // Determine where to create it. 18.168 + if ((flags & Symbol.KINDMASK) == IS_VAR && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) { 18.169 + symbolBlock = block; 18.170 + } else { 18.171 + symbolBlock = function; 18.172 + } 18.173 + 18.174 + // Create and add to appropriate block. 18.175 + symbol = new Symbol(name, flags, node, symbolBlock); 18.176 + symbolBlock.putSymbol(name, symbol); 18.177 + 18.178 + if ((flags & Symbol.KINDMASK) != IS_GLOBAL) { 18.179 + symbolBlock.getFrame().addSymbol(symbol); 18.180 + symbol.setNeedsSlot(true); 18.181 + } 18.182 + } else if (symbol.less(flags)) { 18.183 + symbol.setFlags(flags); 18.184 + } 18.185 + 18.186 + if (node != null) { 18.187 + node.setSymbol(symbol); 18.188 + } 18.189 + 18.190 + return symbol; 18.191 + } 18.192 + 18.193 @Override 18.194 - public Node enter(final FunctionNode functionNode) { 18.195 + public Node enterFunctionNode(final FunctionNode functionNode) { 18.196 start(functionNode, false); 18.197 if (functionNode.isLazy()) { 18.198 - LOG.info("LAZY: " + functionNode.getName()); 18.199 + LOG.info("LAZY: " + functionNode.getName() + " => Promoting to OBJECT"); 18.200 + newTemporary(lexicalContext.getCurrentFunction(), Type.OBJECT, functionNode); 18.201 + functionNode.setReturnType(Type.OBJECT); 18.202 end(functionNode); 18.203 return null; 18.204 } 18.205 18.206 + lexicalContext.push(functionNode); 18.207 + 18.208 clearLocalDefs(); 18.209 clearLocalUses(); 18.210 18.211 @@ -242,24 +324,36 @@ 18.212 initScope(functionNode); 18.213 initReturn(functionNode); 18.214 18.215 - // Add all nested functions as symbols in this function 18.216 - for (final FunctionNode nestedFunction : functionNode.getFunctions()) { 18.217 + // Add all nested declared functions as symbols in this function 18.218 + for (final FunctionNode nestedFunction : functionNode.getDeclaredFunctions()) { 18.219 final IdentNode ident = nestedFunction.getIdent(); 18.220 - if (ident != null && nestedFunction.isStatement()) { 18.221 - final Symbol functionSymbol = functionNode.defineSymbol(ident.getName(), IS_VAR, nestedFunction); 18.222 + if (ident != null) { 18.223 + assert nestedFunction.isDeclared(); 18.224 + final Symbol functionSymbol = defineSymbol(functionNode, ident.getName(), IS_VAR, nestedFunction); 18.225 newType(functionSymbol, Type.typeFor(ScriptFunction.class)); 18.226 } 18.227 } 18.228 18.229 - if (functionNode.isScript()) { 18.230 + if (functionNode.isProgram()) { 18.231 initFromPropertyMap(functionNode); 18.232 } 18.233 18.234 // Add function name as local symbol 18.235 - if (!functionNode.isStatement() && !functionNode.isAnonymous() && !functionNode.isScript()) { 18.236 - final Symbol selfSymbol = functionNode.defineSymbol(functionNode.getIdent().getName(), IS_VAR, functionNode); 18.237 - newType(selfSymbol, Type.OBJECT); 18.238 - selfSymbol.setNode(functionNode); 18.239 + if (!functionNode.isDeclared() && !functionNode.isProgram()) { 18.240 + if(functionNode.getSymbol() != null) { 18.241 + // a temporary left over from an earlier pass when the function was lazy 18.242 + assert functionNode.getSymbol().isTemp(); 18.243 + // remove it 18.244 + functionNode.setSymbol(null); 18.245 + } 18.246 + final Symbol selfSymbol; 18.247 + if(functionNode.isAnonymous()) { 18.248 + selfSymbol = newTemporary(functionNode, Type.OBJECT, functionNode); 18.249 + } else { 18.250 + selfSymbol = defineSymbol(functionNode, functionNode.getIdent().getName(), IS_VAR, functionNode); 18.251 + newType(selfSymbol, Type.OBJECT); 18.252 + selfSymbol.setNode(functionNode); 18.253 + } 18.254 } 18.255 18.256 /* 18.257 @@ -280,32 +374,26 @@ 18.258 */ 18.259 18.260 final List<Symbol> declaredSymbols = new ArrayList<>(); 18.261 - for (final VarNode decl : functionNode.getDeclarations()) { 18.262 - final IdentNode ident = decl.getName(); 18.263 - // any declared symbols that aren't visited need to be typed as well, hence the list 18.264 - declaredSymbols.add(functionNode.defineSymbol(ident.getName(), IS_VAR, new IdentNode(ident))); 18.265 - } 18.266 + // This visitor will assign symbol to all declared variables, except function declarations (which are taken care 18.267 + // in a separate step above) and "var" declarations in for loop initializers. 18.268 + functionNode.accept(new NodeOperatorVisitor() { 18.269 + @Override 18.270 + public Node enterFunctionNode(FunctionNode nestedFn) { 18.271 + // Don't descend into nested functions 18.272 + return nestedFn == functionNode ? nestedFn : null; 18.273 + } 18.274 + @Override 18.275 + public Node enterVarNode(VarNode varNode) { 18.276 + if(varNode.isStatement() && !varNode.isFunctionDeclaration()) { 18.277 + final IdentNode ident = varNode.getName(); 18.278 + // any declared symbols that aren't visited need to be typed as well, hence the list 18.279 + declaredSymbols.add(defineSymbol(functionNode, ident.getName(), IS_VAR, new IdentNode(ident))); 18.280 + } 18.281 + return null; 18.282 + } 18.283 + }); 18.284 18.285 - // Every nested function needs a definition in the outer function with its name. Add these. 18.286 - for (final FunctionNode nestedFunction : functionNode.getFunctions()) { 18.287 - final VarNode varNode = nestedFunction.getFunctionVarNode(); 18.288 - if (varNode != null) { 18.289 - varNode.accept(this); 18.290 - assert varNode.isFunctionVarNode() : varNode + " should be function var node"; 18.291 - } 18.292 - } 18.293 - 18.294 - for (final Node statement : functionNode.getStatements()) { 18.295 - if (statement instanceof VarNode && ((VarNode)statement).isFunctionVarNode()) { 18.296 - continue; //var nodes have already been processed, skip or they will generate additional defs/uses and false "can be undefined" 18.297 - } 18.298 - statement.accept(this); 18.299 - } 18.300 - 18.301 - for (final FunctionNode nestedFunction : functionNode.getFunctions()) { 18.302 - LOG.info("Going into nested function " + functionNode.getName() + " -> " + nestedFunction.getName()); 18.303 - nestedFunction.accept(this); 18.304 - } 18.305 + visitFunctionStatements(functionNode); 18.306 18.307 //unknown parameters are promoted to object type. 18.308 finalizeParameters(functionNode); 18.309 @@ -332,13 +420,28 @@ 18.310 functionNode.setNeedsSelfSymbol(functionNode.getSelfSymbolInit().accept(this)); 18.311 } 18.312 18.313 + if (functionNode.hasLazyChildren()) { 18.314 + objectifySymbols(functionNode); 18.315 + } 18.316 + 18.317 functionNode.popFrame(); 18.318 18.319 + functionNode.setState(CompilationState.ATTR); 18.320 + 18.321 end(functionNode, false); 18.322 + lexicalContext.pop(functionNode); 18.323 18.324 return null; 18.325 } 18.326 18.327 + private void visitFunctionStatements(final FunctionNode functionNode) { 18.328 + final List<Node> newStatements = new ArrayList<>(functionNode.getStatements()); 18.329 + for(ListIterator<Node> stmts = newStatements.listIterator(); stmts.hasNext();) { 18.330 + stmts.set(stmts.next().accept(this)); 18.331 + } 18.332 + functionNode.setStatements(newStatements); 18.333 + } 18.334 + 18.335 @Override 18.336 public Node leaveCONVERT(final UnaryNode unaryNode) { 18.337 assert false : "There should be no convert operators in IR during Attribution"; 18.338 @@ -347,7 +450,7 @@ 18.339 } 18.340 18.341 @Override 18.342 - public Node enter(final IdentNode identNode) { 18.343 + public Node enterIdentNode(final IdentNode identNode) { 18.344 final String name = identNode.getName(); 18.345 18.346 start(identNode); 18.347 @@ -364,7 +467,7 @@ 18.348 final Block block = getCurrentBlock(); 18.349 final Symbol oldSymbol = identNode.getSymbol(); 18.350 18.351 - Symbol symbol = block.findSymbol(name); 18.352 + Symbol symbol = findSymbol(block, name); 18.353 18.354 //If an existing symbol with the name is found, use that otherwise, declare a new one 18.355 if (symbol != null) { 18.356 @@ -388,22 +491,13 @@ 18.357 } 18.358 18.359 identNode.setSymbol(symbol); 18.360 - if (!getCurrentFunctionNode().isLocal(symbol)) { 18.361 - // non-local: we need to put symbol in scope (if it isn't already) 18.362 - if (!symbol.isScope()) { 18.363 - final List<Block> lookupBlocks = findLookupBlocksHelper(getCurrentFunctionNode(), symbol.findFunction()); 18.364 - for (final Block lookupBlock : lookupBlocks) { 18.365 - final Symbol refSymbol = lookupBlock.findSymbol(name); 18.366 - if (refSymbol != null) { // See NASHORN-837, function declaration in lexical scope: try {} catch (x){ function f() { use(x) } } f() 18.367 - LOG.finest("Found a ref symbol that must be scope " + refSymbol); 18.368 - refSymbol.setIsScope(); 18.369 - } 18.370 - } 18.371 - } 18.372 + // non-local: we need to put symbol in scope (if it isn't already) 18.373 + if (!isLocal(getCurrentFunctionNode(), symbol) && !symbol.isScope()) { 18.374 + symbol.setIsScope(); 18.375 } 18.376 } else { 18.377 LOG.info("No symbol exists. Declare undefined: " + symbol); 18.378 - symbol = block.useSymbol(name, identNode); 18.379 + symbol = useSymbol(block, name, identNode); 18.380 // we have never seen this before, it can be undefined 18.381 newType(symbol, Type.OBJECT); // TODO unknown -we have explicit casts anyway? 18.382 symbol.setCanBeUndefined(); 18.383 @@ -412,9 +506,10 @@ 18.384 18.385 assert symbol != null; 18.386 if(symbol.isGlobal()) { 18.387 - getCurrentFunctionNode().setUsesGlobalSymbol(); 18.388 + setUsesGlobalSymbol(); 18.389 } else if(symbol.isScope()) { 18.390 - getCurrentFunctionNode().setUsesScopeSymbol(symbol); 18.391 + final Iterator<Block> blocks = lexicalContext.getBlocks(); 18.392 + blocks.next().setUsesScopeSymbol(symbol, blocks); 18.393 } 18.394 18.395 if (symbol != oldSymbol && !identNode.isInitializedHere()) { 18.396 @@ -427,15 +522,68 @@ 18.397 return null; 18.398 } 18.399 18.400 + /** 18.401 + * Marks the current function as one using any global symbol. The function and all its parent functions will all be 18.402 + * marked as needing parent scope. 18.403 + * @see #needsParentScope() 18.404 + */ 18.405 + private void setUsesGlobalSymbol() { 18.406 + for(final Iterator<FunctionNode> fns = lexicalContext.getFunctions(); fns.hasNext();) { 18.407 + fns.next().setUsesAncestorScope(); 18.408 + } 18.409 + } 18.410 + 18.411 + /** 18.412 + * Declare the use of a symbol in a block. 18.413 + * 18.414 + * @param block block in which the symbol is used 18.415 + * @param name Name of symbol. 18.416 + * @param node Using node 18.417 + * 18.418 + * @return Symbol for given name. 18.419 + */ 18.420 + private Symbol useSymbol(final Block block, final String name, final Node node) { 18.421 + Symbol symbol = findSymbol(block, name); 18.422 + 18.423 + if (symbol == null) { 18.424 + // If not found, declare as a free var. 18.425 + symbol = defineSymbol(block, name, IS_GLOBAL, node); 18.426 + } else { 18.427 + node.setSymbol(symbol); 18.428 + } 18.429 + 18.430 + return symbol; 18.431 + } 18.432 + 18.433 + 18.434 + /** 18.435 + * Search for symbol in the lexical context starting from the given block. 18.436 + * @param name Symbol name. 18.437 + * @return Found symbol or null if not found. 18.438 + */ 18.439 + private Symbol findSymbol(final Block block, final String name) { 18.440 + // Search up block chain to locate symbol. 18.441 + 18.442 + for(final Iterator<Block> blocks = lexicalContext.getBlocks(block); blocks.hasNext();) { 18.443 + // Find name. 18.444 + final Symbol symbol = blocks.next().getExistingSymbol(name); 18.445 + // If found then we are good. 18.446 + if(symbol != null) { 18.447 + return symbol; 18.448 + } 18.449 + } 18.450 + return null; 18.451 + } 18.452 + 18.453 @Override 18.454 - public Node leave(final IndexNode indexNode) { 18.455 - newTemporary(Type.OBJECT, indexNode); //TORO 18.456 + public Node leaveIndexNode(final IndexNode indexNode) { 18.457 + newTemporary(Type.OBJECT, indexNode); //TODO 18.458 return indexNode; 18.459 } 18.460 18.461 @SuppressWarnings("rawtypes") 18.462 @Override 18.463 - public Node enter(final LiteralNode literalNode) { 18.464 + public Node enterLiteralNode(final LiteralNode literalNode) { 18.465 try { 18.466 start(literalNode); 18.467 assert !literalNode.isTokenType(TokenType.THIS) : "tokentype for " + literalNode + " is this"; //guard against old dead code case. literal nodes should never inherit tokens 18.468 @@ -464,14 +612,14 @@ 18.469 } 18.470 18.471 @Override 18.472 - public Node leave(final ObjectNode objectNode) { 18.473 + public Node leaveObjectNode(final ObjectNode objectNode) { 18.474 newTemporary(Type.OBJECT, objectNode); 18.475 end(objectNode); 18.476 return objectNode; 18.477 } 18.478 18.479 @Override 18.480 - public Node enter(final PropertyNode propertyNode) { 18.481 + public Node enterPropertyNode(final PropertyNode propertyNode) { 18.482 // assign a pseudo symbol to property name, see NASHORN-710 18.483 propertyNode.setSymbol(new Symbol(propertyNode.getKeyName(), 0, Type.OBJECT)); 18.484 end(propertyNode); 18.485 @@ -479,31 +627,7 @@ 18.486 } 18.487 18.488 @Override 18.489 - public Node enter(final ReferenceNode referenceNode) { 18.490 - final FunctionNode functionNode = referenceNode.getReference(); 18.491 - if (functionNode != null) { 18.492 - functionNode.addReferencingParentBlock(getCurrentBlock()); 18.493 - } 18.494 - return referenceNode; 18.495 - } 18.496 - 18.497 - @Override 18.498 - public Node leave(final ReferenceNode referenceNode) { 18.499 - newTemporary(Type.OBJECT, referenceNode); //reference node type is always an object, i.e. the scriptFunction. the function return type varies though 18.500 - 18.501 - final FunctionNode functionNode = referenceNode.getReference(); 18.502 - //assert !functionNode.getType().isUnknown() || functionNode.isLazy() : functionNode.getType(); 18.503 - if (functionNode.isLazy()) { 18.504 - LOG.info("Lazy function node call reference: " + functionNode.getName() + " => Promoting to OBJECT"); 18.505 - functionNode.setReturnType(Type.OBJECT); 18.506 - } 18.507 - end(referenceNode); 18.508 - 18.509 - return referenceNode; 18.510 - } 18.511 - 18.512 - @Override 18.513 - public Node leave(final ReturnNode returnNode) { 18.514 + public Node leaveReturnNode(final ReturnNode returnNode) { 18.515 final Node expr = returnNode.getExpression(); 18.516 18.517 if (expr != null) { 18.518 @@ -522,7 +646,7 @@ 18.519 } 18.520 18.521 @Override 18.522 - public Node leave(final SwitchNode switchNode) { 18.523 + public Node leaveSwitchNode(final SwitchNode switchNode) { 18.524 Type type = Type.UNKNOWN; 18.525 18.526 for (final CaseNode caseNode : switchNode.getCases()) { 18.527 @@ -559,7 +683,7 @@ 18.528 } 18.529 18.530 @Override 18.531 - public Node leave(final TryNode tryNode) { 18.532 + public Node leaveTryNode(final TryNode tryNode) { 18.533 tryNode.setException(exceptionSymbol()); 18.534 18.535 if (tryNode.getFinallyBody() != null) { 18.536 @@ -572,13 +696,13 @@ 18.537 } 18.538 18.539 @Override 18.540 - public Node enter(final VarNode varNode) { 18.541 + public Node enterVarNode(final VarNode varNode) { 18.542 start(varNode); 18.543 18.544 final IdentNode ident = varNode.getName(); 18.545 final String name = ident.getName(); 18.546 18.547 - final Symbol symbol = getCurrentBlock().defineSymbol(name, IS_VAR, ident); 18.548 + final Symbol symbol = defineSymbol(getCurrentBlock(), name, IS_VAR, ident); 18.549 assert symbol != null; 18.550 18.551 LOG.info("VarNode " + varNode + " set symbol " + symbol); 18.552 @@ -590,23 +714,15 @@ 18.553 symbol.setCanBeUndefined(); 18.554 } 18.555 18.556 - if (varNode.getInit() != null) { 18.557 - varNode.getInit().accept(this); 18.558 - } 18.559 - 18.560 return varNode; 18.561 } 18.562 18.563 @Override 18.564 - public Node leave(final VarNode varNode) { 18.565 + public Node leaveVarNode(final VarNode varNode) { 18.566 final Node init = varNode.getInit(); 18.567 final IdentNode ident = varNode.getName(); 18.568 final String name = ident.getName(); 18.569 18.570 - if (init != null) { 18.571 - addLocalDef(name); 18.572 - } 18.573 - 18.574 if (init == null) { 18.575 // var x; with no init will be treated like a use of x by 18.576 // visit(IdentNode) unless we remove the name 18.577 @@ -615,8 +731,10 @@ 18.578 return varNode; 18.579 } 18.580 18.581 + addLocalDef(name); 18.582 + 18.583 final Symbol symbol = varNode.getSymbol(); 18.584 - final boolean isScript = symbol.getBlock().getFunction().isScript(); //see NASHORN-56 18.585 + final boolean isScript = lexicalContext.getFunction(symbol.getBlock()).isProgram(); //see NASHORN-56 18.586 if ((init.getType().isNumeric() || init.getType().isBoolean()) && !isScript) { 18.587 // Forbid integers as local vars for now as we have no way to treat them as undefined 18.588 newType(symbol, init.getType()); 18.589 @@ -710,11 +828,9 @@ 18.590 runtimeNode = new RuntimeNode(unaryNode, request, args); 18.591 assert runtimeNode.getSymbol() == unaryNode.getSymbol(); //clone constructor should do this 18.592 18.593 - runtimeNode.accept(this); 18.594 - return runtimeNode; 18.595 + return leaveRuntimeNode(runtimeNode); 18.596 } 18.597 18.598 - 18.599 @Override 18.600 public Node leaveNEW(final UnaryNode unaryNode) { 18.601 newTemporary(Type.OBJECT, unaryNode); 18.602 @@ -747,7 +863,7 @@ 18.603 runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args); 18.604 assert runtimeNode.getSymbol() == unaryNode.getSymbol(); 18.605 18.606 - runtimeNode.accept(this); 18.607 + runtimeNode = (RuntimeNode)leaveRuntimeNode(runtimeNode); 18.608 18.609 end(unaryNode); 18.610 18.611 @@ -755,7 +871,7 @@ 18.612 } 18.613 18.614 @Override 18.615 - public Node leave(final RuntimeNode runtimeNode) { 18.616 + public Node leaveRuntimeNode(final RuntimeNode runtimeNode) { 18.617 newTemporary(runtimeNode.getRequest().getReturnType(), runtimeNode); 18.618 return runtimeNode; 18.619 } 18.620 @@ -815,12 +931,12 @@ 18.621 final IdentNode ident = (IdentNode)lhs; 18.622 final String name = ident.getName(); 18.623 18.624 - Symbol symbol = getCurrentBlock().findSymbol(name); 18.625 + Symbol symbol = findSymbol(getCurrentBlock(), name); 18.626 18.627 if (symbol == null) { 18.628 - symbol = block.defineSymbol(name, IS_GLOBAL, ident); 18.629 + symbol = defineSymbol(block, name, IS_GLOBAL, ident); 18.630 binaryNode.setSymbol(symbol); 18.631 - } else if (!getCurrentFunctionNode().isLocal(symbol)) { 18.632 + } else if (!isLocal(getCurrentFunctionNode(), symbol)) { 18.633 symbol.setIsScope(); 18.634 } 18.635 18.636 @@ -830,6 +946,12 @@ 18.637 return binaryNode; 18.638 } 18.639 18.640 + private boolean isLocal(FunctionNode function, Symbol symbol) { 18.641 + final Block block = symbol.getBlock(); 18.642 + // some temp symbols have no block, so can be assumed local 18.643 + return block == null || lexicalContext.getFunction(block) == function; 18.644 + } 18.645 + 18.646 @Override 18.647 public Node enterASSIGN(final BinaryNode binaryNode) { 18.648 return enterAssignmentNode(binaryNode); 18.649 @@ -957,20 +1079,17 @@ 18.650 18.651 @Override 18.652 public Node leaveBIT_AND(final BinaryNode binaryNode) { 18.653 - newTemporary(Type.INT, binaryNode); 18.654 - return binaryNode; 18.655 + return end(coerce(binaryNode, Type.INT)); 18.656 } 18.657 18.658 @Override 18.659 public Node leaveBIT_OR(final BinaryNode binaryNode) { 18.660 - newTemporary(Type.INT, binaryNode); 18.661 - return binaryNode; 18.662 + return end(coerce(binaryNode, Type.INT)); 18.663 } 18.664 18.665 @Override 18.666 public Node leaveBIT_XOR(final BinaryNode binaryNode) { 18.667 - newTemporary(Type.INT, binaryNode); 18.668 - return binaryNode; 18.669 + return end(coerce(binaryNode, Type.INT)); 18.670 } 18.671 18.672 @Override 18.673 @@ -990,7 +1109,7 @@ 18.674 return leaveBinaryArithmetic(binaryNode); 18.675 } 18.676 18.677 - private Node leaveCmp(final BinaryNode binaryNode, final RuntimeNode.Request request) { 18.678 + private Node leaveCmp(final BinaryNode binaryNode) { 18.679 final Node lhs = binaryNode.lhs(); 18.680 final Node rhs = binaryNode.rhs(); 18.681 18.682 @@ -1002,49 +1121,64 @@ 18.683 return binaryNode; 18.684 } 18.685 18.686 + private Node coerce(final BinaryNode binaryNode, final Type operandType, final Type destType) { 18.687 + // TODO we currently don't support changing inferred type based on uses, only on 18.688 + // definitions. we would need some additional logic. We probably want to do that 18.689 + // in the future, if e.g. a specialized method gets parameter that is only used 18.690 + // as, say, an int : function(x) { return x & 4711 }, and x is not defined in 18.691 + // the function. to make this work, uncomment the following two type inferences 18.692 + // and debug. 18.693 + 18.694 + //newType(binaryNode.lhs().getSymbol(), operandType); 18.695 + //newType(binaryNode.rhs().getSymbol(), operandType); 18.696 + newTemporary(destType, binaryNode); 18.697 + return binaryNode; 18.698 + } 18.699 + 18.700 + private Node coerce(final BinaryNode binaryNode, final Type type) { 18.701 + return coerce(binaryNode, type, type); 18.702 + } 18.703 + 18.704 //leave a binary node and inherit the widest type of lhs , rhs 18.705 private Node leaveBinaryArithmetic(final BinaryNode binaryNode) { 18.706 - if (!Compiler.shouldUseIntegerArithmetic()) { 18.707 - newTemporary(Type.NUMBER, binaryNode); 18.708 - return binaryNode; 18.709 - } 18.710 - newTemporary(Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType(), Type.NUMBER), binaryNode); 18.711 - return binaryNode; 18.712 + assert !Compiler.shouldUseIntegerArithmetic(); 18.713 + return end(coerce(binaryNode, Type.NUMBER)); 18.714 } 18.715 18.716 @Override 18.717 public Node leaveEQ(final BinaryNode binaryNode) { 18.718 - return leaveCmp(binaryNode, Request.EQ); 18.719 + return leaveCmp(binaryNode); 18.720 } 18.721 18.722 @Override 18.723 public Node leaveEQ_STRICT(final BinaryNode binaryNode) { 18.724 - return leaveCmp(binaryNode, Request.EQ_STRICT); 18.725 + return leaveCmp(binaryNode); 18.726 } 18.727 18.728 @Override 18.729 public Node leaveGE(final BinaryNode binaryNode) { 18.730 - return leaveCmp(binaryNode, Request.GE); 18.731 + return leaveCmp(binaryNode); 18.732 } 18.733 18.734 @Override 18.735 public Node leaveGT(final BinaryNode binaryNode) { 18.736 - return leaveCmp(binaryNode, Request.GT); 18.737 + return leaveCmp(binaryNode); 18.738 } 18.739 18.740 @Override 18.741 public Node leaveIN(final BinaryNode binaryNode) { 18.742 - try { 18.743 - return new RuntimeNode(binaryNode, Request.IN).accept(this); 18.744 - } finally { 18.745 - end(binaryNode); 18.746 - } 18.747 + return leaveBinaryRuntimeOperator(binaryNode, Request.IN); 18.748 } 18.749 18.750 @Override 18.751 public Node leaveINSTANCEOF(final BinaryNode binaryNode) { 18.752 + return leaveBinaryRuntimeOperator(binaryNode, Request.INSTANCEOF); 18.753 + } 18.754 + 18.755 + private Node leaveBinaryRuntimeOperator(final BinaryNode binaryNode, final Request request) { 18.756 try { 18.757 - return new RuntimeNode(binaryNode, Request.INSTANCEOF).accept(this); 18.758 + // Don't do a full RuntimeNode.accept, as we don't want to double-visit the binary node operands 18.759 + return leaveRuntimeNode(new RuntimeNode(binaryNode, request)); 18.760 } finally { 18.761 end(binaryNode); 18.762 } 18.763 @@ -1052,12 +1186,12 @@ 18.764 18.765 @Override 18.766 public Node leaveLE(final BinaryNode binaryNode) { 18.767 - return leaveCmp(binaryNode, Request.LE); 18.768 + return leaveCmp(binaryNode); 18.769 } 18.770 18.771 @Override 18.772 public Node leaveLT(final BinaryNode binaryNode) { 18.773 - return leaveCmp(binaryNode, Request.LT); 18.774 + return leaveCmp(binaryNode); 18.775 } 18.776 18.777 @Override 18.778 @@ -1072,12 +1206,12 @@ 18.779 18.780 @Override 18.781 public Node leaveNE(final BinaryNode binaryNode) { 18.782 - return leaveCmp(binaryNode, Request.NE); 18.783 + return leaveCmp(binaryNode); 18.784 } 18.785 18.786 @Override 18.787 public Node leaveNE_STRICT(final BinaryNode binaryNode) { 18.788 - return leaveCmp(binaryNode, Request.NE_STRICT); 18.789 + return leaveCmp(binaryNode); 18.790 } 18.791 18.792 @Override 18.793 @@ -1089,23 +1223,17 @@ 18.794 18.795 @Override 18.796 public Node leaveSAR(final BinaryNode binaryNode) { 18.797 - newTemporary(Type.INT, binaryNode); 18.798 - end(binaryNode); 18.799 - return binaryNode; 18.800 + return end(coerce(binaryNode, Type.INT)); 18.801 } 18.802 18.803 @Override 18.804 public Node leaveSHL(final BinaryNode binaryNode) { 18.805 - newTemporary(Type.INT, binaryNode); 18.806 - end(binaryNode); 18.807 - return binaryNode; 18.808 + return end(coerce(binaryNode, Type.INT)); 18.809 } 18.810 18.811 @Override 18.812 public Node leaveSHR(final BinaryNode binaryNode) { 18.813 - newTemporary(Type.LONG, binaryNode); 18.814 - end(binaryNode); 18.815 - return binaryNode; 18.816 + return end(coerce(binaryNode, Type.LONG)); 18.817 } 18.818 18.819 @Override 18.820 @@ -1114,9 +1242,9 @@ 18.821 } 18.822 18.823 @Override 18.824 - public Node leave(final ForNode forNode) { 18.825 + public Node leaveForNode(final ForNode forNode) { 18.826 if (forNode.isForIn()) { 18.827 - forNode.setIterator(newInternal(getCurrentFunctionNode(), getCurrentFunctionNode().uniqueName(ITERATOR_PREFIX.tag()), Type.OBJECT)); //NASHORN-73 18.828 + forNode.setIterator(newInternal(getCurrentFunctionNode().uniqueName(ITERATOR_PREFIX.tag()), Type.OBJECT)); //NASHORN-73 18.829 /* 18.830 * Iterators return objects, so we need to widen the scope of the 18.831 * init variable if it, for example, has been assigned double type 18.832 @@ -1131,7 +1259,7 @@ 18.833 } 18.834 18.835 @Override 18.836 - public Node leave(final TernaryNode ternaryNode) { 18.837 + public Node leaveTernaryNode(final TernaryNode ternaryNode) { 18.838 final Node lhs = ternaryNode.rhs(); 18.839 final Node rhs = ternaryNode.third(); 18.840 18.841 @@ -1146,24 +1274,24 @@ 18.842 return ternaryNode; 18.843 } 18.844 18.845 - private static void initThis(final FunctionNode functionNode) { 18.846 - final Symbol thisSymbol = functionNode.defineSymbol(THIS.tag(), IS_PARAM | IS_THIS, null); 18.847 + private void initThis(final FunctionNode functionNode) { 18.848 + final Symbol thisSymbol = defineSymbol(functionNode, THIS.tag(), IS_PARAM | IS_THIS, null); 18.849 newType(thisSymbol, Type.OBJECT); 18.850 thisSymbol.setNeedsSlot(true); 18.851 functionNode.getThisNode().setSymbol(thisSymbol); 18.852 LOG.info("Initialized scope symbol: " + thisSymbol); 18.853 } 18.854 18.855 - private static void initScope(final FunctionNode functionNode) { 18.856 - final Symbol scopeSymbol = functionNode.defineSymbol(SCOPE.tag(), IS_VAR | IS_INTERNAL, null); 18.857 + private void initScope(final FunctionNode functionNode) { 18.858 + final Symbol scopeSymbol = defineSymbol(functionNode, SCOPE.tag(), IS_VAR | IS_INTERNAL, null); 18.859 newType(scopeSymbol, Type.typeFor(ScriptObject.class)); 18.860 scopeSymbol.setNeedsSlot(true); 18.861 functionNode.getScopeNode().setSymbol(scopeSymbol); 18.862 LOG.info("Initialized scope symbol: " + scopeSymbol); 18.863 } 18.864 18.865 - private static void initReturn(final FunctionNode functionNode) { 18.866 - final Symbol returnSymbol = functionNode.defineSymbol(SCRIPT_RETURN.tag(), IS_VAR | IS_INTERNAL, null); 18.867 + private void initReturn(final FunctionNode functionNode) { 18.868 + final Symbol returnSymbol = defineSymbol(functionNode, SCRIPT_RETURN.tag(), IS_VAR | IS_INTERNAL, null); 18.869 newType(returnSymbol, Type.OBJECT); 18.870 returnSymbol.setNeedsSlot(true); 18.871 functionNode.getResultNode().setSymbol(returnSymbol); 18.872 @@ -1173,7 +1301,7 @@ 18.873 18.874 private void initVarArg(final FunctionNode functionNode) { 18.875 if (functionNode.isVarArg()) { 18.876 - final Symbol varArgsSymbol = functionNode.defineSymbol(VARARGS.tag(), IS_PARAM | IS_INTERNAL, null); 18.877 + final Symbol varArgsSymbol = defineSymbol(functionNode, VARARGS.tag(), IS_PARAM | IS_INTERNAL, null); 18.878 varArgsSymbol.setTypeOverride(Type.OBJECT_ARRAY); 18.879 varArgsSymbol.setNeedsSlot(true); 18.880 functionNode.getVarArgsNode().setSymbol(varArgsSymbol); 18.881 @@ -1181,7 +1309,7 @@ 18.882 18.883 if (functionNode.needsArguments()) { 18.884 final String argumentsName = functionNode.getArgumentsNode().getName(); 18.885 - final Symbol argumentsSymbol = functionNode.defineSymbol(argumentsName, IS_VAR | IS_INTERNAL, null); 18.886 + final Symbol argumentsSymbol = defineSymbol(functionNode, argumentsName, IS_VAR | IS_INTERNAL, null); 18.887 newType(argumentsSymbol, Type.typeFor(ScriptObject.class)); 18.888 argumentsSymbol.setNeedsSlot(true); 18.889 functionNode.getArgumentsNode().setSymbol(argumentsSymbol); 18.890 @@ -1191,9 +1319,9 @@ 18.891 } 18.892 } 18.893 18.894 - private static void initCallee(final FunctionNode functionNode) { 18.895 + private void initCallee(final FunctionNode functionNode) { 18.896 assert functionNode.getCalleeNode() != null : functionNode + " has no callee"; 18.897 - final Symbol calleeSymbol = functionNode.defineSymbol(CALLEE.tag(), IS_PARAM | IS_INTERNAL, null); 18.898 + final Symbol calleeSymbol = defineSymbol(functionNode, CALLEE.tag(), IS_PARAM | IS_INTERNAL, null); 18.899 newType(calleeSymbol, Type.typeFor(ScriptFunction.class)); 18.900 calleeSymbol.setNeedsSlot(true); 18.901 functionNode.getCalleeNode().setSymbol(calleeSymbol); 18.902 @@ -1211,11 +1339,17 @@ 18.903 // type or its parameters with the widest (OBJECT) type for safety. 18.904 functionNode.setReturnType(Type.UNKNOWN); 18.905 18.906 - for (final IdentNode ident : functionNode.getParameters()) { 18.907 - addLocalDef(ident.getName()); 18.908 - final Symbol paramSymbol = functionNode.defineSymbol(ident.getName(), IS_PARAM, ident); 18.909 + for (final IdentNode param : functionNode.getParameters()) { 18.910 + addLocalDef(param.getName()); 18.911 + final Symbol paramSymbol = defineSymbol(functionNode, param.getName(), IS_PARAM, param); 18.912 if (paramSymbol != null) { 18.913 - newType(paramSymbol, Type.UNKNOWN); 18.914 + final Type callSiteParamType = functionNode.getSpecializedType(param); 18.915 + if (callSiteParamType != null) { 18.916 + LOG.info("Param " + paramSymbol + " has a callsite type " + callSiteParamType + ". Using that."); 18.917 + 18.918 + System.err.println("Param " + param + " has a callsite type " + callSiteParamType + ". Using that."); 18.919 + } 18.920 + newType(paramSymbol, callSiteParamType == null ? Type.UNKNOWN : callSiteParamType); 18.921 } 18.922 18.923 LOG.info("Initialized param " + paramSymbol); 18.924 @@ -1229,36 +1363,29 @@ 18.925 * @param functionNode functionNode 18.926 */ 18.927 private static void finalizeParameters(final FunctionNode functionNode) { 18.928 - boolean nonObjectParams = false; 18.929 - List<Type> paramSpecializations = new ArrayList<>(); 18.930 + final boolean isVarArg = functionNode.isVarArg(); 18.931 18.932 for (final IdentNode ident : functionNode.getParameters()) { 18.933 final Symbol paramSymbol = ident.getSymbol(); 18.934 - if (paramSymbol != null) { 18.935 - Type type = paramSymbol.getSymbolType(); 18.936 - if (type.isUnknown()) { 18.937 - type = Type.OBJECT; 18.938 - } 18.939 - paramSpecializations.add(type); 18.940 - if (!type.isObject()) { 18.941 - nonObjectParams = true; 18.942 - } 18.943 - newType(paramSymbol, Type.OBJECT); 18.944 + 18.945 + assert paramSymbol != null; 18.946 + Type type = functionNode.getSpecializedType(ident); 18.947 + if (type == null) { 18.948 + type = Type.OBJECT; 18.949 } 18.950 - } 18.951 18.952 - if (!nonObjectParams) { 18.953 - paramSpecializations = null; 18.954 - // Later, when resolving a call to this method, the linker can say "I have a double, an int and an object" as parameters 18.955 - // here. If the callee has parameter specializations, we can regenerate it with those particular types for speed. 18.956 - } else { 18.957 - LOG.info("parameter specialization possible: " + functionNode.getName() + " " + paramSpecializations); 18.958 - } 18.959 + // if we know that a parameter is only used as a certain type throughout 18.960 + // this function, we can tell the runtime system that no matter what the 18.961 + // call site is, use this information. TODO 18.962 + if (!paramSymbol.getSymbolType().isObject()) { 18.963 + LOG.finest("Parameter " + ident + " could profit from specialization to " + paramSymbol.getSymbolType()); 18.964 + } 18.965 18.966 - // parameters should not be slots for a function that uses variable arity signature 18.967 - if (functionNode.isVarArg()) { 18.968 - for (final IdentNode param : functionNode.getParameters()) { 18.969 - param.getSymbol().setNeedsSlot(false); 18.970 + newType(paramSymbol, Type.widest(type, paramSymbol.getSymbolType())); 18.971 + 18.972 + // parameters should not be slots for a function that uses variable arity signature 18.973 + if (isVarArg) { 18.974 + paramSymbol.setNeedsSlot(false); 18.975 } 18.976 } 18.977 } 18.978 @@ -1267,15 +1394,15 @@ 18.979 * Move any properties from a global map into the scope of this method 18.980 * @param functionNode the function node for which to init scope vars 18.981 */ 18.982 - private static void initFromPropertyMap(final FunctionNode functionNode) { 18.983 + private void initFromPropertyMap(final FunctionNode functionNode) { 18.984 // For a script, add scope symbols as defined in the property map 18.985 - assert functionNode.isScript(); 18.986 + assert functionNode.isProgram(); 18.987 18.988 final PropertyMap map = Context.getGlobalMap(); 18.989 18.990 for (final Property property : map.getProperties()) { 18.991 final String key = property.getKey(); 18.992 - final Symbol symbol = functionNode.defineSymbol(key, IS_GLOBAL, null); 18.993 + final Symbol symbol = defineSymbol(functionNode, key, IS_GLOBAL, null); 18.994 newType(symbol, Type.OBJECT); 18.995 LOG.info("Added global symbol from property map " + symbol); 18.996 } 18.997 @@ -1342,9 +1469,14 @@ 18.998 private static void ensureAssignmentSlots(final FunctionNode functionNode, final Node assignmentDest) { 18.999 assignmentDest.accept(new NodeVisitor() { 18.1000 @Override 18.1001 - public Node leave(final IndexNode indexNode) { 18.1002 + public Node leaveIndexNode(final IndexNode indexNode) { 18.1003 + assert indexNode.getSymbol().isTemp(); 18.1004 final Node index = indexNode.getIndex(); 18.1005 - index.getSymbol().setNeedsSlot(!index.getSymbol().isConstant()); 18.1006 + //only temps can be set as needing slots. the others will self resolve 18.1007 + //it is illegal to take a scope var and force it to be a slot, that breaks 18.1008 + if (index.getSymbol().isTemp() && !index.getSymbol().isConstant()) { 18.1009 + index.getSymbol().setNeedsSlot(true); 18.1010 + } 18.1011 return indexNode; 18.1012 } 18.1013 }); 18.1014 @@ -1387,7 +1519,7 @@ 18.1015 } 18.1016 18.1017 @Override 18.1018 - public Node enter(final FunctionNode node) { 18.1019 + public Node enterFunctionNode(final FunctionNode node) { 18.1020 return node.isLazy() ? null : node; 18.1021 } 18.1022 18.1023 @@ -1407,7 +1539,7 @@ 18.1024 */ 18.1025 @SuppressWarnings("fallthrough") 18.1026 @Override 18.1027 - public Node leave(final BinaryNode binaryNode) { 18.1028 + public Node leaveBinaryNode(final BinaryNode binaryNode) { 18.1029 final Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType()); 18.1030 switch (binaryNode.tokenType()) { 18.1031 default: 18.1032 @@ -1465,22 +1597,6 @@ 18.1033 return binaryNode; 18.1034 } 18.1035 18.1036 - private static List<Block> findLookupBlocksHelper(final FunctionNode currentFunction, final FunctionNode topFunction) { 18.1037 - if (currentFunction.findParentFunction() == topFunction) { 18.1038 - final List<Block> blocks = new LinkedList<>(); 18.1039 - 18.1040 - blocks.add(currentFunction.getParent()); 18.1041 - blocks.addAll(currentFunction.getReferencingParentBlocks()); 18.1042 - return blocks; 18.1043 - } 18.1044 - /* 18.1045 - * assumption: all parent blocks of an inner function will always be in the same outer function; 18.1046 - * therefore we can simply skip through intermediate functions. 18.1047 - * @see FunctionNode#addReferencingParentBlock(Block) 18.1048 - */ 18.1049 - return findLookupBlocksHelper(currentFunction.findParentFunction(), topFunction); 18.1050 - } 18.1051 - 18.1052 private static boolean isFunctionExpressionSelfReference(final Symbol symbol) { 18.1053 if (symbol.isVar() && symbol.getNode() == symbol.getBlock() && symbol.getNode() instanceof FunctionNode) { 18.1054 return ((FunctionNode)symbol.getNode()).getIdent().getName().equals(symbol.getName()); 18.1055 @@ -1497,16 +1613,12 @@ 18.1056 return newTemporary(getCurrentFunctionNode(), type, node); 18.1057 } 18.1058 18.1059 - private Symbol newInternal(final FunctionNode functionNode, final String name, final Type type) { 18.1060 - final Symbol iter = getCurrentFunctionNode().defineSymbol(name, IS_VAR | IS_INTERNAL, null); 18.1061 + private Symbol newInternal(final String name, final Type type) { 18.1062 + final Symbol iter = defineSymbol(getCurrentFunctionNode(), name, IS_VAR | IS_INTERNAL, null); 18.1063 iter.setType(type); // NASHORN-73 18.1064 return iter; 18.1065 } 18.1066 18.1067 - private Symbol newInternal(final String name, final Type type) { 18.1068 - return newInternal(getCurrentFunctionNode(), name, type); 18.1069 - } 18.1070 - 18.1071 private static void newType(final Symbol symbol, final Type type) { 18.1072 final Type oldType = symbol.getSymbolType(); 18.1073 symbol.setType(type); 18.1074 @@ -1548,6 +1660,39 @@ 18.1075 localUses.add(name); 18.1076 } 18.1077 18.1078 + /** 18.1079 + * Pessimistically promote all symbols in current function node to Object types 18.1080 + * This is done when the function contains unevaluated black boxes such as 18.1081 + * lazy sub-function nodes that have not been compiled. 18.1082 + * 18.1083 + * @param functionNode function node in whose scope symbols should conservatively be made objects 18.1084 + */ 18.1085 + private static void objectifySymbols(final FunctionNode functionNode) { 18.1086 + functionNode.accept(new NodeVisitor() { 18.1087 + private void toObject(final Block block) { 18.1088 + for (final Iterator<Symbol> iter = block.symbolIterator(); iter.hasNext();) { 18.1089 + final Symbol symbol = iter.next(); 18.1090 + newType(symbol, Type.OBJECT); 18.1091 + } 18.1092 + } 18.1093 + 18.1094 + @Override 18.1095 + public Node enterBlock(final Block block) { 18.1096 + toObject(block); 18.1097 + return block; 18.1098 + } 18.1099 + 18.1100 + @Override 18.1101 + public Node enterFunctionNode(final FunctionNode node) { 18.1102 + toObject(node); 18.1103 + if (node.isLazy()) { 18.1104 + return null; 18.1105 + } 18.1106 + return node; 18.1107 + } 18.1108 + }); 18.1109 + } 18.1110 + 18.1111 private static String name(final Node node) { 18.1112 final String cn = node.getClass().getName(); 18.1113 int lastDot = cn.lastIndexOf('.');
19.1 --- a/src/jdk/nashorn/internal/codegen/BranchOptimizer.java Thu Mar 28 10:55:17 2013 -0700 19.2 +++ b/src/jdk/nashorn/internal/codegen/BranchOptimizer.java Mon Apr 01 21:42:31 2013 -0700 19.3 @@ -32,7 +32,6 @@ 19.4 import static jdk.nashorn.internal.codegen.Condition.LT; 19.5 import static jdk.nashorn.internal.codegen.Condition.NE; 19.6 19.7 -import jdk.nashorn.internal.codegen.Label; 19.8 import jdk.nashorn.internal.codegen.types.Type; 19.9 import jdk.nashorn.internal.ir.BinaryNode; 19.10 import jdk.nashorn.internal.ir.Node;
20.1 --- a/src/jdk/nashorn/internal/codegen/ClassEmitter.java Thu Mar 28 10:55:17 2013 -0700 20.2 +++ b/src/jdk/nashorn/internal/codegen/ClassEmitter.java Mon Apr 01 21:42:31 2013 -0700 20.3 @@ -195,6 +195,14 @@ 20.4 } 20.5 20.6 /** 20.7 + * Returns the name of the compile unit class name. 20.8 + * @return the name of the compile unit class name. 20.9 + */ 20.10 + String getUnitClassName() { 20.11 + return unitClassName; 20.12 + } 20.13 + 20.14 + /** 20.15 * Convert a binary name to a package/class name. 20.16 * 20.17 * @param name Binary name. 20.18 @@ -244,7 +252,7 @@ 20.19 // $getMap - get the ith entry from the constants table and cast to PropertyMap. 20.20 final MethodEmitter getMapMethod = method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), GET_MAP.tag(), PropertyMap.class, int.class); 20.21 getMapMethod.begin(); 20.22 - getMapMethod.loadConstants(unitClassName) 20.23 + getMapMethod.loadConstants() 20.24 .load(Type.INT, 0) 20.25 .arrayload() 20.26 .checkcast(PropertyMap.class) 20.27 @@ -254,7 +262,7 @@ 20.28 // $setMap - overwrite an existing map. 20.29 final MethodEmitter setMapMethod = method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), SET_MAP.tag(), void.class, int.class, PropertyMap.class); 20.30 setMapMethod.begin(); 20.31 - setMapMethod.loadConstants(unitClassName) 20.32 + setMapMethod.loadConstants() 20.33 .load(Type.INT, 0) 20.34 .load(Type.OBJECT, 1) 20.35 .arraystore();
21.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Mar 28 10:55:17 2013 -0700 21.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Mon Apr 01 21:42:31 2013 -0700 21.3 @@ -25,10 +25,8 @@ 21.4 21.5 package jdk.nashorn.internal.codegen; 21.6 21.7 -import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.HANDLE_STATIC; 21.8 import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.PRIVATE; 21.9 import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.STATIC; 21.10 -import static jdk.nashorn.internal.codegen.CompilerConstants.ALLOCATE; 21.11 import static jdk.nashorn.internal.codegen.CompilerConstants.GET_MAP; 21.12 import static jdk.nashorn.internal.codegen.CompilerConstants.GET_STRING; 21.13 import static jdk.nashorn.internal.codegen.CompilerConstants.LEAF; 21.14 @@ -50,7 +48,6 @@ 21.15 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT; 21.16 21.17 import java.io.PrintWriter; 21.18 -import java.lang.invoke.MethodHandle; 21.19 import java.util.ArrayList; 21.20 import java.util.Arrays; 21.21 import java.util.EnumSet; 21.22 @@ -79,9 +76,11 @@ 21.23 import jdk.nashorn.internal.ir.ExecuteNode; 21.24 import jdk.nashorn.internal.ir.ForNode; 21.25 import jdk.nashorn.internal.ir.FunctionNode; 21.26 +import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 21.27 import jdk.nashorn.internal.ir.IdentNode; 21.28 import jdk.nashorn.internal.ir.IfNode; 21.29 import jdk.nashorn.internal.ir.IndexNode; 21.30 +import jdk.nashorn.internal.ir.LexicalContext; 21.31 import jdk.nashorn.internal.ir.LineNumberNode; 21.32 import jdk.nashorn.internal.ir.LiteralNode; 21.33 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 21.34 @@ -89,7 +88,6 @@ 21.35 import jdk.nashorn.internal.ir.Node; 21.36 import jdk.nashorn.internal.ir.ObjectNode; 21.37 import jdk.nashorn.internal.ir.PropertyNode; 21.38 -import jdk.nashorn.internal.ir.ReferenceNode; 21.39 import jdk.nashorn.internal.ir.ReturnNode; 21.40 import jdk.nashorn.internal.ir.RuntimeNode; 21.41 import jdk.nashorn.internal.ir.RuntimeNode.Request; 21.42 @@ -108,14 +106,14 @@ 21.43 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 21.44 import jdk.nashorn.internal.parser.Lexer.RegexToken; 21.45 import jdk.nashorn.internal.parser.TokenType; 21.46 -import jdk.nashorn.internal.runtime.CodeInstaller; 21.47 import jdk.nashorn.internal.runtime.Context; 21.48 +import jdk.nashorn.internal.runtime.DebugLogger; 21.49 import jdk.nashorn.internal.runtime.ECMAException; 21.50 import jdk.nashorn.internal.runtime.Property; 21.51 import jdk.nashorn.internal.runtime.PropertyMap; 21.52 +import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; 21.53 import jdk.nashorn.internal.runtime.Scope; 21.54 import jdk.nashorn.internal.runtime.ScriptFunction; 21.55 -import jdk.nashorn.internal.runtime.ScriptFunctionData; 21.56 import jdk.nashorn.internal.runtime.ScriptObject; 21.57 import jdk.nashorn.internal.runtime.ScriptRuntime; 21.58 import jdk.nashorn.internal.runtime.Source; 21.59 @@ -149,8 +147,6 @@ 21.60 /** Name of the ScriptFunctionImpl, cannot be referred to as .class @see FunctionObjectCreator */ 21.61 private static final String SCRIPTFUNCTION_IMPL_OBJECT = Compiler.OBJECTS_PACKAGE + '/' + "ScriptFunctionImpl"; 21.62 21.63 - private static final String SCRIPTFUNCTION_TRAMPOLINE_OBJECT = Compiler.OBJECTS_PACKAGE + '/' + "ScriptFunctionTrampolineImpl"; 21.64 - 21.65 /** Constant data & installation. The only reason the compiler keeps this is because it is assigned 21.66 * by reflection in class installation */ 21.67 private final Compiler compiler; 21.68 @@ -161,12 +157,20 @@ 21.69 /** How many regexp fields have been emitted */ 21.70 private int regexFieldCount; 21.71 21.72 + /** Used for temporary signaling between enterCallNode and enterFunctionNode to handle the special case of calling 21.73 + * a just-defined anonymous function expression. */ 21.74 + private boolean functionNodeIsCallee; 21.75 + 21.76 /** Map of shared scope call sites */ 21.77 private final Map<SharedScopeCall, SharedScopeCall> scopeCalls = new HashMap<>(); 21.78 21.79 + private final LexicalContext lexicalContext = new LexicalContext(); 21.80 + 21.81 /** When should we stop caching regexp expressions in fields to limit bytecode size? */ 21.82 private static final int MAX_REGEX_FIELDS = 2 * 1024; 21.83 21.84 + private static final DebugLogger LOG = new DebugLogger("codegen", "nashorn.codegen.debug"); 21.85 + 21.86 /** 21.87 * Constructor. 21.88 * 21.89 @@ -215,7 +219,7 @@ 21.90 final int flags = CALLSITE_SCOPE | getCallSiteFlags(); 21.91 method.loadScope(); 21.92 21.93 - if (symbol.isFastScope(getCurrentFunctionNode())) { 21.94 + if (isFastScope(symbol)) { 21.95 // Only generate shared scope getter for fast-scope symbols so we know we can dial in correct scope. 21.96 if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD) { 21.97 return loadSharedScopeVar(identNode.getType(), symbol, flags); 21.98 @@ -226,8 +230,28 @@ 21.99 } 21.100 } 21.101 21.102 + /** 21.103 + * Check if this symbol can be accessed directly with a putfield or getfield or dynamic load 21.104 + * 21.105 + * @param function function to check for fast scope 21.106 + * @return true if fast scope 21.107 + */ 21.108 + private boolean isFastScope(final Symbol symbol) { 21.109 + if (!symbol.isScope() || !symbol.getBlock().needsScope()) { 21.110 + return false; 21.111 + } 21.112 + // Allow fast scope access if no function contains with or eval 21.113 + for(final Iterator<FunctionNode> it = lexicalContext.getFunctions(getCurrentFunctionNode()); it.hasNext();) { 21.114 + final FunctionNode func = it.next(); 21.115 + if (func.hasWith() || func.hasEval()) { 21.116 + return false; 21.117 + } 21.118 + } 21.119 + return true; 21.120 + } 21.121 + 21.122 private MethodEmitter loadSharedScopeVar(final Type valueType, final Symbol symbol, final int flags) { 21.123 - method.load(symbol.isFastScope(getCurrentFunctionNode()) ? getScopeProtoDepth(getCurrentBlock(), symbol) : -1); 21.124 + method.load(isFastScope(symbol) ? getScopeProtoDepth(getCurrentBlock(), symbol) : -1); 21.125 final SharedScopeCall scopeCall = getScopeGet(valueType, symbol, flags | CALLSITE_FAST_SCOPE); 21.126 scopeCall.generateInvoke(method); 21.127 return method; 21.128 @@ -245,30 +269,18 @@ 21.129 return method; 21.130 } 21.131 21.132 - private static int getScopeProtoDepth(final Block currentBlock, final Symbol symbol) { 21.133 - if (currentBlock == symbol.getBlock()) { 21.134 - return 0; 21.135 - } 21.136 - 21.137 - final int delta = currentBlock.needsScope() ? 1 : 0; 21.138 - final Block parentBlock = currentBlock.getParent(); 21.139 - 21.140 - if (parentBlock != null) { 21.141 - final int result = getScopeProtoDepth(parentBlock, symbol); 21.142 - if (result != -1) { 21.143 - return delta + result; 21.144 + private int getScopeProtoDepth(final Block startingBlock, final Symbol symbol) { 21.145 + int depth = 0; 21.146 + final Block definingBlock = symbol.getBlock(); 21.147 + for(final Iterator<Block> blocks = lexicalContext.getBlocks(startingBlock); blocks.hasNext();) { 21.148 + final Block currentBlock = blocks.next(); 21.149 + if (currentBlock == definingBlock) { 21.150 + return depth; 21.151 + } 21.152 + if (currentBlock.needsScope()) { 21.153 + ++depth; 21.154 } 21.155 } 21.156 - 21.157 - if (currentBlock instanceof FunctionNode) { 21.158 - for (final Block lookupBlock : ((FunctionNode)currentBlock).getReferencingParentBlocks()) { 21.159 - final int result = getScopeProtoDepth(lookupBlock, symbol); 21.160 - if (result != -1) { 21.161 - return delta + result; 21.162 - } 21.163 - } 21.164 - } 21.165 - 21.166 return -1; 21.167 } 21.168 21.169 @@ -318,13 +330,13 @@ 21.170 21.171 node.accept(new NodeVisitor(getCurrentCompileUnit(), method) { 21.172 @Override 21.173 - public Node enter(final IdentNode identNode) { 21.174 + public Node enterIdentNode(final IdentNode identNode) { 21.175 loadIdent(identNode); 21.176 return null; 21.177 } 21.178 21.179 @Override 21.180 - public Node enter(final AccessNode accessNode) { 21.181 + public Node enterAccessNode(final AccessNode accessNode) { 21.182 if (!baseAlreadyOnStack) { 21.183 load(accessNode.getBase()).convert(Type.OBJECT); 21.184 } 21.185 @@ -334,7 +346,7 @@ 21.186 } 21.187 21.188 @Override 21.189 - public Node enter(final IndexNode indexNode) { 21.190 + public Node enterIndexNode(final IndexNode indexNode) { 21.191 if (!baseAlreadyOnStack) { 21.192 load(indexNode.getBase()).convert(Type.OBJECT); 21.193 load(indexNode.getIndex()); 21.194 @@ -344,6 +356,14 @@ 21.195 } 21.196 21.197 @Override 21.198 + public Node enterFunctionNode(FunctionNode functionNode) { 21.199 + // function nodes will always leave a constructed function object on stack, no need to load the symbol 21.200 + // separately as in enterDefault() 21.201 + functionNode.accept(codegen); 21.202 + return null; 21.203 + } 21.204 + 21.205 + @Override 21.206 public Node enterDefault(final Node otherNode) { 21.207 otherNode.accept(codegen); // generate code for whatever we are looking at. 21.208 method.load(symbol); // load the final symbol to the stack (or nop if no slot, then result is already there) 21.209 @@ -355,7 +375,7 @@ 21.210 } 21.211 21.212 @Override 21.213 - public Node enter(final AccessNode accessNode) { 21.214 + public Node enterAccessNode(final AccessNode accessNode) { 21.215 if (accessNode.testResolved()) { 21.216 return null; 21.217 } 21.218 @@ -427,10 +447,11 @@ 21.219 } 21.220 21.221 @Override 21.222 - public Node enter(final Block block) { 21.223 + public Node enterBlock(final Block block) { 21.224 if (block.testResolved()) { 21.225 return null; 21.226 } 21.227 + lexicalContext.push(block); 21.228 21.229 method.label(block.getEntryLabel()); 21.230 initLocals(block); 21.231 @@ -439,14 +460,14 @@ 21.232 } 21.233 21.234 @Override 21.235 - public Node leave(final Block block) { 21.236 + public Node leaveBlock(final Block block) { 21.237 method.label(block.getBreakLabel()); 21.238 symbolInfo(block); 21.239 21.240 if (block.needsScope()) { 21.241 popBlockScope(block); 21.242 } 21.243 - 21.244 + lexicalContext.pop(block); 21.245 return block; 21.246 } 21.247 21.248 @@ -472,7 +493,7 @@ 21.249 } 21.250 21.251 @Override 21.252 - public Node enter(final BreakNode breakNode) { 21.253 + public Node enterBreakNode(final BreakNode breakNode) { 21.254 if (breakNode.testResolved()) { 21.255 return null; 21.256 } 21.257 @@ -520,14 +541,13 @@ 21.258 } 21.259 21.260 @Override 21.261 - public Node enter(final CallNode callNode) { 21.262 + public Node enterCallNode(final CallNode callNode) { 21.263 if (callNode.testResolved()) { 21.264 return null; 21.265 } 21.266 21.267 final List<Node> args = callNode.getArgs(); 21.268 final Node function = callNode.getFunction(); 21.269 - final FunctionNode currentFunction = getCurrentFunctionNode(); 21.270 final Block currentBlock = getCurrentBlock(); 21.271 21.272 function.accept(new NodeVisitor(getCurrentCompileUnit(), method) { 21.273 @@ -536,7 +556,7 @@ 21.274 final Symbol symbol = identNode.getSymbol(); 21.275 int scopeCallFlags = flags; 21.276 method.loadScope(); 21.277 - if (symbol.isFastScope(currentFunction)) { 21.278 + if (isFastScope(symbol)) { 21.279 method.load(getScopeProtoDepth(currentBlock, symbol)); 21.280 scopeCallFlags |= CALLSITE_FAST_SCOPE; 21.281 } else { 21.282 @@ -598,7 +618,7 @@ 21.283 } 21.284 21.285 @Override 21.286 - public Node enter(final IdentNode node) { 21.287 + public Node enterIdentNode(final IdentNode node) { 21.288 final Symbol symbol = node.getSymbol(); 21.289 21.290 if (symbol.isScope()) { 21.291 @@ -611,7 +631,7 @@ 21.292 if (callNode.isEval()) { 21.293 evalCall(node, flags); 21.294 } else if (useCount <= SharedScopeCall.FAST_SCOPE_CALL_THRESHOLD 21.295 - || (!symbol.isFastScope(currentFunction) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD) 21.296 + || (!isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD) 21.297 || callNode.inWithBlock()) { 21.298 scopeCall(node, flags); 21.299 } else { 21.300 @@ -626,7 +646,7 @@ 21.301 } 21.302 21.303 @Override 21.304 - public Node enter(final AccessNode node) { 21.305 + public Node enterAccessNode(final AccessNode node) { 21.306 load(node.getBase()); 21.307 method.convert(Type.OBJECT); 21.308 method.dup(); 21.309 @@ -639,8 +659,7 @@ 21.310 } 21.311 21.312 @Override 21.313 - public Node enter(final ReferenceNode node) { 21.314 - final FunctionNode callee = node.getReference(); 21.315 + public Node enterFunctionNode(final FunctionNode callee) { 21.316 final boolean isVarArg = callee.isVarArg(); 21.317 final int argCount = isVarArg ? -1 : callee.getParameters().size(); 21.318 21.319 @@ -658,12 +677,13 @@ 21.320 loadArgs(args, signature, isVarArg, argCount); 21.321 method.invokestatic(callee.getCompileUnit().getUnitClassName(), callee.getName(), signature); 21.322 assert method.peekType().equals(callee.getReturnType()) : method.peekType() + " != " + callee.getReturnType(); 21.323 - 21.324 + functionNodeIsCallee = true; 21.325 + callee.accept(CodeGenerator.this); 21.326 return null; 21.327 } 21.328 21.329 @Override 21.330 - public Node enter(final IndexNode node) { 21.331 + public Node enterIndexNode(final IndexNode node) { 21.332 load(node.getBase()); 21.333 method.convert(Type.OBJECT); 21.334 method.dup(); 21.335 @@ -699,7 +719,7 @@ 21.336 } 21.337 21.338 @Override 21.339 - public Node enter(final ContinueNode continueNode) { 21.340 + public Node enterContinueNode(final ContinueNode continueNode) { 21.341 if (continueNode.testResolved()) { 21.342 return null; 21.343 } 21.344 @@ -714,17 +734,17 @@ 21.345 } 21.346 21.347 @Override 21.348 - public Node enter(final DoWhileNode doWhileNode) { 21.349 - return enter((WhileNode)doWhileNode); 21.350 + public Node enterDoWhileNode(final DoWhileNode doWhileNode) { 21.351 + return enterWhileNode(doWhileNode); 21.352 } 21.353 21.354 @Override 21.355 - public Node enter(final EmptyNode emptyNode) { 21.356 + public Node enterEmptyNode(final EmptyNode emptyNode) { 21.357 return null; 21.358 } 21.359 21.360 @Override 21.361 - public Node enter(final ExecuteNode executeNode) { 21.362 + public Node enterExecuteNode(final ExecuteNode executeNode) { 21.363 if (executeNode.testResolved()) { 21.364 return null; 21.365 } 21.366 @@ -736,7 +756,7 @@ 21.367 } 21.368 21.369 @Override 21.370 - public Node enter(final ForNode forNode) { 21.371 + public Node enterForNode(final ForNode forNode) { 21.372 if (forNode.testResolved()) { 21.373 return null; 21.374 } 21.375 @@ -818,7 +838,7 @@ 21.376 * @param block block with local vars. 21.377 */ 21.378 private void initLocals(final Block block) { 21.379 - final FunctionNode function = block.getFunction(); 21.380 + final FunctionNode function = lexicalContext.getFunction(block); 21.381 final boolean isFunctionNode = block == function; 21.382 21.383 /* 21.384 @@ -920,7 +940,7 @@ 21.385 foc.makeObject(method); 21.386 21.387 // runScript(): merge scope into global 21.388 - if (isFunctionNode && function.isScript()) { 21.389 + if (isFunctionNode && function.isProgram()) { 21.390 method.invoke(ScriptRuntime.MERGE_SCOPE); 21.391 } 21.392 21.393 @@ -963,31 +983,42 @@ 21.394 } 21.395 21.396 @Override 21.397 - public Node enter(final FunctionNode functionNode) { 21.398 + public Node enterFunctionNode(final FunctionNode functionNode) { 21.399 + final boolean isCallee = functionNodeIsCallee; 21.400 + functionNodeIsCallee = false; 21.401 + 21.402 + if (functionNode.testResolved()) { 21.403 + return null; 21.404 + } 21.405 + 21.406 + if(!(isCallee || functionNode == compiler.getFunctionNode())) { 21.407 + newFunctionObject(functionNode); 21.408 + } 21.409 + 21.410 if (functionNode.isLazy()) { 21.411 return null; 21.412 } 21.413 21.414 - if (functionNode.testResolved()) { 21.415 - return null; 21.416 - } 21.417 + LOG.info("=== BEGIN " + functionNode.getName()); 21.418 + lexicalContext.push(functionNode); 21.419 21.420 setCurrentCompileUnit(functionNode.getCompileUnit()); 21.421 assert getCurrentCompileUnit() != null; 21.422 21.423 - method = getCurrentCompileUnit().getClassEmitter().method(functionNode); 21.424 + setCurrentMethodEmitter(getCurrentCompileUnit().getClassEmitter().method(functionNode)); 21.425 functionNode.setMethodEmitter(method); 21.426 // Mark end for variable tables. 21.427 method.begin(); 21.428 method.label(functionNode.getEntryLabel()); 21.429 21.430 initLocals(functionNode); 21.431 + functionNode.setState(CompilationState.EMITTED); 21.432 21.433 return functionNode; 21.434 } 21.435 21.436 @Override 21.437 - public Node leave(final FunctionNode functionNode) { 21.438 + public Node leaveFunctionNode(final FunctionNode functionNode) { 21.439 // Mark end for variable tables. 21.440 method.label(functionNode.getBreakLabel()); 21.441 21.442 @@ -1005,16 +1036,18 @@ 21.443 throw e; 21.444 } 21.445 21.446 + lexicalContext.pop(functionNode); 21.447 + LOG.info("=== END " + functionNode.getName()); 21.448 return functionNode; 21.449 } 21.450 21.451 @Override 21.452 - public Node enter(final IdentNode identNode) { 21.453 + public Node enterIdentNode(final IdentNode identNode) { 21.454 return null; 21.455 } 21.456 21.457 @Override 21.458 - public Node enter(final IfNode ifNode) { 21.459 + public Node enterIfNode(final IfNode ifNode) { 21.460 if (ifNode.testResolved()) { 21.461 return null; 21.462 } 21.463 @@ -1053,7 +1086,7 @@ 21.464 } 21.465 21.466 @Override 21.467 - public Node enter(final IndexNode indexNode) { 21.468 + public Node enterIndexNode(final IndexNode indexNode) { 21.469 if (indexNode.testResolved()) { 21.470 return null; 21.471 } 21.472 @@ -1064,7 +1097,7 @@ 21.473 } 21.474 21.475 @Override 21.476 - public Node enter(final LineNumberNode lineNumberNode) { 21.477 + public Node enterLineNumberNode(final LineNumberNode lineNumberNode) { 21.478 if (lineNumberNode.testResolved()) { 21.479 return null; 21.480 } 21.481 @@ -1072,7 +1105,6 @@ 21.482 final Label label = new Label("line:" + lineNumberNode.getLineNumber() + " (" + getCurrentFunctionNode().getName() + ")"); 21.483 method.label(label); 21.484 method.lineNumber(lineNumberNode.getLineNumber(), label); 21.485 - 21.486 return null; 21.487 } 21.488 21.489 @@ -1110,7 +1142,7 @@ 21.490 final String name = getCurrentFunctionNode().uniqueName(SPLIT_PREFIX.tag()); 21.491 final String signature = methodDescriptor(type, Object.class, ScriptFunction.class, ScriptObject.class, type); 21.492 21.493 - method = getCurrentCompileUnit().getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature); 21.494 + setCurrentMethodEmitter(getCurrentCompileUnit().getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature)); 21.495 method.setFunctionNode(getCurrentFunctionNode()); 21.496 method.begin(); 21.497 21.498 @@ -1216,7 +1248,7 @@ 21.499 method.invokestatic(unitClassName, methodName, methodDescriptor(cls, int.class)); 21.500 classEmitter.needGetConstantMethod(cls); 21.501 } else { 21.502 - method.loadConstants(unitClassName).load(index).arrayload(); 21.503 + method.loadConstants().load(index).arrayload(); 21.504 if (cls != Object.class) { 21.505 method.checkcast(cls); 21.506 } 21.507 @@ -1296,14 +1328,14 @@ 21.508 21.509 @SuppressWarnings("rawtypes") 21.510 @Override 21.511 - public Node enter(final LiteralNode literalNode) { 21.512 + public Node enterLiteralNode(final LiteralNode literalNode) { 21.513 assert literalNode.getSymbol() != null : literalNode + " has no symbol"; 21.514 load(literalNode).store(literalNode.getSymbol()); 21.515 return null; 21.516 } 21.517 21.518 @Override 21.519 - public Node enter(final ObjectNode objectNode) { 21.520 + public Node enterObjectNode(final ObjectNode objectNode) { 21.521 if (objectNode.testResolved()) { 21.522 return null; 21.523 } 21.524 @@ -1376,10 +1408,10 @@ 21.525 } 21.526 21.527 for (final Node element : elements) { 21.528 - final PropertyNode propertyNode = (PropertyNode)element; 21.529 - final Object key = propertyNode.getKey(); 21.530 - final ReferenceNode getter = (ReferenceNode)propertyNode.getGetter(); 21.531 - final ReferenceNode setter = (ReferenceNode)propertyNode.getSetter(); 21.532 + final PropertyNode propertyNode = (PropertyNode)element; 21.533 + final Object key = propertyNode.getKey(); 21.534 + final FunctionNode getter = (FunctionNode)propertyNode.getGetter(); 21.535 + final FunctionNode setter = (FunctionNode)propertyNode.getSetter(); 21.536 21.537 if (getter == null && setter == null) { 21.538 continue; 21.539 @@ -1408,18 +1440,7 @@ 21.540 } 21.541 21.542 @Override 21.543 - public Node enter(final ReferenceNode referenceNode) { 21.544 - if (referenceNode.testResolved()) { 21.545 - return null; 21.546 - } 21.547 - 21.548 - newFunctionObject(referenceNode.getReference()); 21.549 - 21.550 - return null; 21.551 - } 21.552 - 21.553 - @Override 21.554 - public Node enter(final ReturnNode returnNode) { 21.555 + public Node enterReturnNode(final ReturnNode returnNode) { 21.556 if (returnNode.testResolved()) { 21.557 return null; 21.558 } 21.559 @@ -1560,7 +1581,7 @@ 21.560 } 21.561 21.562 @Override 21.563 - public Node enter(final RuntimeNode runtimeNode) { 21.564 + public Node enterRuntimeNode(final RuntimeNode runtimeNode) { 21.565 if (runtimeNode.testResolved()) { 21.566 return null; 21.567 } 21.568 @@ -1641,7 +1662,7 @@ 21.569 } 21.570 21.571 @Override 21.572 - public Node enter(final SplitNode splitNode) { 21.573 + public Node enterSplitNode(final SplitNode splitNode) { 21.574 if (splitNode.testResolved()) { 21.575 return null; 21.576 } 21.577 @@ -1710,7 +1731,7 @@ 21.578 } 21.579 21.580 @Override 21.581 - public Node leave(final SplitNode splitNode) { 21.582 + public Node leaveSplitNode(final SplitNode splitNode) { 21.583 try { 21.584 // Wrap up this method. 21.585 method.loadResult(); 21.586 @@ -1767,7 +1788,7 @@ 21.587 } 21.588 21.589 @Override 21.590 - public Node enter(final SwitchNode switchNode) { 21.591 + public Node enterSwitchNode(final SwitchNode switchNode) { 21.592 if (switchNode.testResolved()) { 21.593 return null; 21.594 } 21.595 @@ -1899,7 +1920,7 @@ 21.596 } 21.597 21.598 @Override 21.599 - public Node enter(final ThrowNode throwNode) { 21.600 + public Node enterThrowNode(final ThrowNode throwNode) { 21.601 if (throwNode.testResolved()) { 21.602 return null; 21.603 } 21.604 @@ -1926,7 +1947,7 @@ 21.605 } 21.606 21.607 @Override 21.608 - public Node enter(final TryNode tryNode) { 21.609 + public Node enterTryNode(final TryNode tryNode) { 21.610 if (tryNode.testResolved()) { 21.611 return null; 21.612 } 21.613 @@ -1959,7 +1980,7 @@ 21.614 setCurrentBlock(catchBlock); 21.615 21.616 try { 21.617 - enter(catchBlock); 21.618 + enterBlock(catchBlock); 21.619 21.620 final CatchNode catchNode = (CatchNode)catchBlocks.get(i).getStatements().get(0); 21.621 final IdentNode exception = catchNode.getException(); 21.622 @@ -1970,6 +1991,7 @@ 21.623 // Generate catch body (inlined finally) and rethrow exception 21.624 catchBody.accept(this); 21.625 method.load(symbol).athrow(); 21.626 + lexicalContext.pop(catchBlock); 21.627 continue; 21.628 } 21.629 21.630 @@ -2016,7 +2038,7 @@ 21.631 } 21.632 } 21.633 21.634 - leave(catchBlock); 21.635 + leaveBlock(catchBlock); 21.636 } finally { 21.637 setCurrentBlock(saveBlock); 21.638 } 21.639 @@ -2031,7 +2053,7 @@ 21.640 } 21.641 21.642 @Override 21.643 - public Node enter(final VarNode varNode) { 21.644 + public Node enterVarNode(final VarNode varNode) { 21.645 final Node init = varNode.getInit(); 21.646 21.647 if (varNode.testResolved() || init == null) { 21.648 @@ -2053,7 +2075,7 @@ 21.649 int flags = CALLSITE_SCOPE | getCallSiteFlags(); 21.650 final IdentNode identNode = varNode.getName(); 21.651 final Type type = identNode.getType(); 21.652 - if (varSymbol.isFastScope(getCurrentFunctionNode())) { 21.653 + if (isFastScope(varSymbol)) { 21.654 storeFastScopeVar(type, varSymbol, flags); 21.655 } else { 21.656 method.dynamicSet(type, identNode.getName(), flags); 21.657 @@ -2069,7 +2091,7 @@ 21.658 } 21.659 21.660 @Override 21.661 - public Node enter(final WhileNode whileNode) { 21.662 + public Node enterWhileNode(final WhileNode whileNode) { 21.663 if (whileNode.testResolved()) { 21.664 return null; 21.665 } 21.666 @@ -2102,7 +2124,7 @@ 21.667 } 21.668 21.669 @Override 21.670 - public Node enter(final WithNode withNode) { 21.671 + public Node enterWithNode(final WithNode withNode) { 21.672 if (withNode.testResolved()) { 21.673 return null; 21.674 } 21.675 @@ -2868,7 +2890,7 @@ 21.676 * Ternary visits. 21.677 */ 21.678 @Override 21.679 - public Node enter(final TernaryNode ternaryNode) { 21.680 + public Node enterTernaryNode(final TernaryNode ternaryNode) { 21.681 if (ternaryNode.testResolved()) { 21.682 return null; 21.683 } 21.684 @@ -3064,7 +3086,7 @@ 21.685 21.686 target.accept(new NodeVisitor(getCurrentCompileUnit(), method) { 21.687 @Override 21.688 - public Node enter(final IdentNode node) { 21.689 + public Node enterIdentNode(final IdentNode node) { 21.690 if (targetSymbol.isScope()) { 21.691 method.load(scopeSymbol); 21.692 depth++; 21.693 @@ -3087,13 +3109,13 @@ 21.694 } 21.695 21.696 @Override 21.697 - public Node enter(final AccessNode node) { 21.698 + public Node enterAccessNode(final AccessNode node) { 21.699 enterBaseNode(); 21.700 return null; 21.701 } 21.702 21.703 @Override 21.704 - public Node enter(final IndexNode node) { 21.705 + public Node enterIndexNode(final IndexNode node) { 21.706 enterBaseNode(); 21.707 21.708 final Node index = node.getIndex(); 21.709 @@ -3159,8 +3181,6 @@ 21.710 } 21.711 21.712 private void epilogue() { 21.713 - final FunctionNode currentFunction = getCurrentFunctionNode(); 21.714 - 21.715 /** 21.716 * Take the original target args from the stack and use them 21.717 * together with the value to be stored to emit the store code 21.718 @@ -3178,7 +3198,7 @@ 21.719 } 21.720 21.721 @Override 21.722 - public Node enter(final UnaryNode node) { 21.723 + public Node enterUnaryNode(final UnaryNode node) { 21.724 if(node.tokenType() == TokenType.CONVERT && node.getSymbol() != null) { 21.725 method.convert(node.rhs().getType()); 21.726 } 21.727 @@ -3186,11 +3206,11 @@ 21.728 } 21.729 21.730 @Override 21.731 - public Node enter(final IdentNode node) { 21.732 + public Node enterIdentNode(final IdentNode node) { 21.733 final Symbol symbol = node.getSymbol(); 21.734 assert symbol != null; 21.735 if (symbol.isScope()) { 21.736 - if (symbol.isFastScope(currentFunction)) { 21.737 + if (isFastScope(symbol)) { 21.738 storeFastScopeVar(node.getType(), symbol, CALLSITE_SCOPE | getCallSiteFlags()); 21.739 } else { 21.740 method.dynamicSet(node.getType(), node.getName(), CALLSITE_SCOPE | getCallSiteFlags()); 21.741 @@ -3203,13 +3223,13 @@ 21.742 } 21.743 21.744 @Override 21.745 - public Node enter(final AccessNode node) { 21.746 + public Node enterAccessNode(final AccessNode node) { 21.747 method.dynamicSet(node.getProperty().getType(), node.getProperty().getName(), getCallSiteFlags()); 21.748 return null; 21.749 } 21.750 21.751 @Override 21.752 - public Node enter(final IndexNode node) { 21.753 + public Node enterIndexNode(final IndexNode node) { 21.754 method.dynamicSetIndex(getCallSiteFlags()); 21.755 return null; 21.756 } 21.757 @@ -3234,42 +3254,22 @@ 21.758 } 21.759 21.760 private void newFunctionObject(final FunctionNode functionNode) { 21.761 - final boolean isLazy = functionNode.isLazy(); 21.762 - final Class<?>[] cparams = new Class<?>[] { ScriptFunctionData.class, ScriptObject.class, MethodHandle.class }; 21.763 + final boolean isLazy = functionNode.isLazy(); 21.764 21.765 new ObjectCreator(this, new ArrayList<String>(), new ArrayList<Symbol>(), false, false) { 21.766 @Override 21.767 - protected void makeObject(final MethodEmitter method) { 21.768 - final String className = isLazy ? SCRIPTFUNCTION_TRAMPOLINE_OBJECT : SCRIPTFUNCTION_IMPL_OBJECT; 21.769 - 21.770 - method._new(className).dup(); 21.771 - if (isLazy) { 21.772 - loadConstant(compiler.getCodeInstaller()); 21.773 - loadConstant(functionNode); 21.774 + protected void makeObject(final MethodEmitter m) { 21.775 + final String className = SCRIPTFUNCTION_IMPL_OBJECT; 21.776 + 21.777 + m._new(className).dup(); 21.778 + loadConstant(new RecompilableScriptFunctionData(functionNode, compiler.getCodeInstaller(), Compiler.binaryName(getClassName()), makeMap())); 21.779 + 21.780 + if (isLazy || functionNode.needsParentScope()) { 21.781 + m.loadScope(); 21.782 } else { 21.783 - final String signature = new FunctionSignature(true, functionNode.needsCallee(), functionNode.getReturnType(), functionNode.isVarArg() ? null : functionNode.getParameters()).toString(); 21.784 - method.loadHandle(functionNode.getCompileUnit().getUnitClassName(), functionNode.getName(), signature, EnumSet.of(HANDLE_STATIC)); // function 21.785 + m.loadNull(); 21.786 } 21.787 - loadConstant(new ScriptFunctionData(functionNode, makeMap())); 21.788 - 21.789 - if (isLazy || functionNode.needsParentScope()) { 21.790 - method.loadScope(); 21.791 - } else { 21.792 - method.loadNull(); 21.793 - } 21.794 - 21.795 - method.loadHandle(getClassName(), ALLOCATE.tag(), methodDescriptor(ScriptObject.class, PropertyMap.class), EnumSet.of(HANDLE_STATIC)); 21.796 - 21.797 - final List<Class<?>> cparamList = new ArrayList<>(); 21.798 - if (isLazy) { 21.799 - cparamList.add(CodeInstaller.class); 21.800 - cparamList.add(FunctionNode.class); 21.801 - } else { 21.802 - cparamList.add(MethodHandle.class); 21.803 - } 21.804 - cparamList.addAll(Arrays.asList(cparams)); 21.805 - 21.806 - method.invoke(constructorNoLookup(className, cparamList.toArray(new Class<?>[cparamList.size()]))); 21.807 + m.invoke(constructorNoLookup(className, RecompilableScriptFunctionData.class, ScriptObject.class)); 21.808 } 21.809 }.makeObject(method); 21.810 }
22.1 --- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java Thu Mar 28 10:55:17 2013 -0700 22.2 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java Mon Apr 01 21:42:31 2013 -0700 22.3 @@ -2,10 +2,10 @@ 22.4 22.5 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.ATTR; 22.6 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.CONSTANT_FOLDED; 22.7 -import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.EMITTED; 22.8 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.FINALIZED; 22.9 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.INITIALIZED; 22.10 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.LOWERED; 22.11 +import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.PARSED; 22.12 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SPLIT; 22.13 22.14 import java.io.File; 22.15 @@ -14,16 +14,16 @@ 22.16 import java.util.EnumSet; 22.17 import java.util.HashSet; 22.18 import java.util.Set; 22.19 - 22.20 import jdk.nashorn.internal.codegen.types.Type; 22.21 import jdk.nashorn.internal.ir.CallNode; 22.22 import jdk.nashorn.internal.ir.FunctionNode; 22.23 import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 22.24 +import jdk.nashorn.internal.ir.LexicalContext; 22.25 import jdk.nashorn.internal.ir.Node; 22.26 -import jdk.nashorn.internal.ir.ReferenceNode; 22.27 -import jdk.nashorn.internal.ir.visitor.NodeVisitor; 22.28 import jdk.nashorn.internal.ir.debug.ASTWriter; 22.29 import jdk.nashorn.internal.ir.debug.PrintVisitor; 22.30 +import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor; 22.31 +import jdk.nashorn.internal.ir.visitor.NodeVisitor; 22.32 import jdk.nashorn.internal.runtime.ECMAErrors; 22.33 import jdk.nashorn.internal.runtime.ScriptEnvironment; 22.34 import jdk.nashorn.internal.runtime.Timing; 22.35 @@ -39,7 +39,7 @@ 22.36 * default policy. The will get trampolines and only be generated when 22.37 * called 22.38 */ 22.39 - LAZY_INITIALIZATION_PHASE(EnumSet.of(FunctionNode.CompilationState.INITIALIZED)) { 22.40 + LAZY_INITIALIZATION_PHASE(EnumSet.of(INITIALIZED, PARSED)) { 22.41 @Override 22.42 void transform(final Compiler compiler, final FunctionNode fn) { 22.43 22.44 @@ -65,23 +65,25 @@ 22.45 outermostFunctionNode.accept(new NodeVisitor() { 22.46 // self references are done with invokestatic and thus cannot have trampolines - never lazy 22.47 @Override 22.48 - public Node enter(final CallNode node) { 22.49 + public Node enterCallNode(final CallNode node) { 22.50 final Node callee = node.getFunction(); 22.51 - if (callee instanceof ReferenceNode) { 22.52 - neverLazy.add(((ReferenceNode)callee).getReference()); 22.53 + if (callee instanceof FunctionNode) { 22.54 + neverLazy.add(((FunctionNode)callee)); 22.55 return null; 22.56 } 22.57 return node; 22.58 } 22.59 22.60 @Override 22.61 - public Node enter(final FunctionNode node) { 22.62 + public Node enterFunctionNode(final FunctionNode node) { 22.63 if (node == outermostFunctionNode) { 22.64 return node; 22.65 } 22.66 - assert Compiler.LAZY_JIT; 22.67 + assert compiler.isLazy(); 22.68 lazy.add(node); 22.69 22.70 + //also needs scope, potentially needs arguments etc etc 22.71 + 22.72 return node; 22.73 } 22.74 }); 22.75 @@ -92,15 +94,24 @@ 22.76 lazy.remove(node); 22.77 } 22.78 22.79 - for (final FunctionNode node : lazy) { 22.80 - Compiler.LOG.fine("Marking " + node.getName() + " as lazy"); 22.81 - node.setIsLazy(true); 22.82 - final FunctionNode parent = node.findParentFunction(); 22.83 - if (parent != null) { 22.84 - Compiler.LOG.fine("Marking " + parent.getName() + " as having lazy children - it needs scope for all variables"); 22.85 - parent.setHasLazyChildren(); 22.86 + outermostFunctionNode.accept(new NodeOperatorVisitor() { 22.87 + private final LexicalContext lexicalContext = new LexicalContext(); 22.88 + @Override 22.89 + public Node enterFunctionNode(FunctionNode functionNode) { 22.90 + lexicalContext.push(functionNode); 22.91 + if(lazy.contains(functionNode)) { 22.92 + Compiler.LOG.fine("Marking " + functionNode.getName() + " as lazy"); 22.93 + functionNode.setIsLazy(true); 22.94 + lexicalContext.getParentFunction(functionNode).setHasLazyChildren(); 22.95 + } 22.96 + return functionNode; 22.97 } 22.98 - } 22.99 + @Override 22.100 + public Node leaveFunctionNode(FunctionNode functionNode) { 22.101 + lexicalContext.pop(functionNode); 22.102 + return functionNode; 22.103 + } 22.104 + }); 22.105 } 22.106 22.107 @Override 22.108 @@ -113,7 +124,7 @@ 22.109 * Constant folding pass 22.110 * Simple constant folding that will make elementary constructs go away 22.111 */ 22.112 - CONSTANT_FOLDING_PHASE(EnumSet.of(INITIALIZED), CONSTANT_FOLDED) { 22.113 + CONSTANT_FOLDING_PHASE(EnumSet.of(INITIALIZED, PARSED)) { 22.114 @Override 22.115 void transform(final Compiler compiler, final FunctionNode fn) { 22.116 fn.accept(new FoldConstants()); 22.117 @@ -134,7 +145,7 @@ 22.118 * as runtime nodes where applicable. 22.119 * 22.120 */ 22.121 - LOWERING_PHASE(EnumSet.of(INITIALIZED, CONSTANT_FOLDED), LOWERED) { 22.122 + LOWERING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED)) { 22.123 @Override 22.124 void transform(final Compiler compiler, final FunctionNode fn) { 22.125 fn.accept(new Lower()); 22.126 @@ -150,19 +161,10 @@ 22.127 * Attribution 22.128 * Assign symbols and types to all nodes. 22.129 */ 22.130 - ATTRIBUTION_PHASE(EnumSet.of(INITIALIZED, CONSTANT_FOLDED, LOWERED), ATTR) { 22.131 + ATTRIBUTION_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED)) { 22.132 @Override 22.133 void transform(final Compiler compiler, final FunctionNode fn) { 22.134 - final ScriptEnvironment env = compiler.getEnv(); 22.135 - 22.136 fn.accept(new Attr()); 22.137 - if (env._print_lower_ast) { 22.138 - env.getErr().println(new ASTWriter(fn)); 22.139 - } 22.140 - 22.141 - if (env._print_lower_parse) { 22.142 - env.getErr().println(new PrintVisitor(fn)); 22.143 - } 22.144 } 22.145 22.146 @Override 22.147 @@ -178,7 +180,7 @@ 22.148 * a + b a ScriptRuntime.ADD with call overhead or a dadd with much 22.149 * less). Split IR can lead to scope information being changed. 22.150 */ 22.151 - SPLITTING_PHASE(EnumSet.of(INITIALIZED, CONSTANT_FOLDED, LOWERED, ATTR), SPLIT) { 22.152 + SPLITTING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR)) { 22.153 @Override 22.154 void transform(final Compiler compiler, final FunctionNode fn) { 22.155 final CompileUnit outermostCompileUnit = compiler.addCompileUnit(compiler.firstCompileUnitName()); 22.156 @@ -212,10 +214,20 @@ 22.157 * Contract: all variables must have slot assignments and scope assignments 22.158 * before type finalization. 22.159 */ 22.160 - TYPE_FINALIZATION_PHASE(EnumSet.of(INITIALIZED, CONSTANT_FOLDED, LOWERED, ATTR, SPLIT), FINALIZED) { 22.161 + TYPE_FINALIZATION_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR, SPLIT)) { 22.162 @Override 22.163 void transform(final Compiler compiler, final FunctionNode fn) { 22.164 + final ScriptEnvironment env = compiler.getEnv(); 22.165 + 22.166 fn.accept(new FinalizeTypes()); 22.167 + 22.168 + if (env._print_lower_ast) { 22.169 + env.getErr().println(new ASTWriter(fn)); 22.170 + } 22.171 + 22.172 + if (env._print_lower_parse) { 22.173 + env.getErr().println(new PrintVisitor(fn)); 22.174 + } 22.175 } 22.176 22.177 @Override 22.178 @@ -229,7 +241,7 @@ 22.179 * 22.180 * Generate the byte code class(es) resulting from the compiled FunctionNode 22.181 */ 22.182 - BYTECODE_GENERATION_PHASE(EnumSet.of(INITIALIZED, CONSTANT_FOLDED, LOWERED, ATTR, SPLIT, FINALIZED), EMITTED) { 22.183 + BYTECODE_GENERATION_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR, SPLIT, FINALIZED)) { 22.184 @Override 22.185 void transform(final Compiler compiler, final FunctionNode fn) { 22.186 final ScriptEnvironment env = compiler.getEnv(); 22.187 @@ -238,6 +250,16 @@ 22.188 final CodeGenerator codegen = new CodeGenerator(compiler); 22.189 fn.accept(codegen); 22.190 codegen.generateScopeCalls(); 22.191 + fn.accept(new NodeOperatorVisitor() { 22.192 + @Override 22.193 + public Node enterFunctionNode(FunctionNode functionNode) { 22.194 + if(functionNode.isLazy()) { 22.195 + functionNode.resetResolved(); 22.196 + return null; 22.197 + } 22.198 + return fn; 22.199 + } 22.200 + }); 22.201 22.202 } catch (final VerifyError e) { 22.203 if (env._verify_code || env._print_code) { 22.204 @@ -306,18 +328,12 @@ 22.205 }; 22.206 22.207 private final EnumSet<CompilationState> pre; 22.208 - private final CompilationState post; 22.209 private long startTime; 22.210 private long endTime; 22.211 private boolean isFinished; 22.212 22.213 private CompilationPhase(final EnumSet<CompilationState> pre) { 22.214 - this(pre, null); 22.215 - } 22.216 - 22.217 - private CompilationPhase(final EnumSet<CompilationState> pre, final CompilationState post) { 22.218 - this.pre = pre; 22.219 - this.post = post; 22.220 + this.pre = pre; 22.221 } 22.222 22.223 boolean isApplicable(final FunctionNode functionNode) { 22.224 @@ -343,10 +359,6 @@ 22.225 endTime = System.currentTimeMillis(); 22.226 Timing.accumulateTime(toString(), endTime - startTime); 22.227 22.228 - if (post != null) { 22.229 - functionNode.setState(post); 22.230 - } 22.231 - 22.232 isFinished = true; 22.233 } 22.234
23.1 --- a/src/jdk/nashorn/internal/codegen/CompileUnit.java Thu Mar 28 10:55:17 2013 -0700 23.2 +++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java Mon Apr 01 21:42:31 2013 -0700 23.3 @@ -37,6 +37,8 @@ 23.4 23.5 private long weight; 23.6 23.7 + private Class<?> clazz; 23.8 + 23.9 CompileUnit(final String className, final ClassEmitter classEmitter) { 23.10 this(className, classEmitter, 0L); 23.11 } 23.12 @@ -48,6 +50,24 @@ 23.13 } 23.14 23.15 /** 23.16 + * Return the class that contains the code for this unit, null if not 23.17 + * generated yet 23.18 + * 23.19 + * @return class with compile unit code 23.20 + */ 23.21 + public Class<?> getCode() { 23.22 + return clazz; 23.23 + } 23.24 + 23.25 + /** 23.26 + * Set class when it exists. Only accessible from compiler 23.27 + * @param clazz class with code for this compile unit 23.28 + */ 23.29 + void setCode(final Class<?> clazz) { 23.30 + this.clazz = clazz; 23.31 + } 23.32 + 23.33 + /** 23.34 * Add weight to this compile unit 23.35 * @param w weight to add 23.36 */
24.1 --- a/src/jdk/nashorn/internal/codegen/Compiler.java Thu Mar 28 10:55:17 2013 -0700 24.2 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java Mon Apr 01 21:42:31 2013 -0700 24.3 @@ -45,11 +45,14 @@ 24.4 import java.util.Map; 24.5 import java.util.Map.Entry; 24.6 import java.util.Set; 24.7 +import java.util.logging.Level; 24.8 import jdk.internal.dynalink.support.NameCodec; 24.9 import jdk.nashorn.internal.codegen.ClassEmitter.Flag; 24.10 import jdk.nashorn.internal.codegen.types.Type; 24.11 import jdk.nashorn.internal.ir.FunctionNode; 24.12 import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 24.13 +import jdk.nashorn.internal.ir.Node; 24.14 +import jdk.nashorn.internal.ir.visitor.NodeVisitor; 24.15 import jdk.nashorn.internal.runtime.CodeInstaller; 24.16 import jdk.nashorn.internal.runtime.DebugLogger; 24.17 import jdk.nashorn.internal.runtime.ScriptEnvironment; 24.18 @@ -71,8 +74,6 @@ 24.19 /** Name of the objects package */ 24.20 public static final String OBJECTS_PACKAGE = "jdk/nashorn/internal/objects"; 24.21 24.22 - static final boolean LAZY_JIT = Options.getBooleanProperty("nashorn.compiler.lazy"); 24.23 - 24.24 private final Map<String, byte[]> bytecode; 24.25 24.26 private final Set<CompileUnit> compileUnits; 24.27 @@ -164,7 +165,7 @@ 24.28 * and JIT it at once. This can lead to long startup time and fewer type 24.29 * specializations 24.30 */ 24.31 - final static CompilationSequence SEQUENCE_NORMAL = new CompilationSequence( 24.32 + final static CompilationSequence SEQUENCE_EAGER = new CompilationSequence( 24.33 CompilationPhase.CONSTANT_FOLDING_PHASE, 24.34 CompilationPhase.LOWERING_PHASE, 24.35 CompilationPhase.ATTRIBUTION_PHASE, 24.36 @@ -173,12 +174,15 @@ 24.37 CompilationPhase.BYTECODE_GENERATION_PHASE); 24.38 24.39 final static CompilationSequence SEQUENCE_LAZY = 24.40 - SEQUENCE_NORMAL.insertFirst(CompilationPhase.LAZY_INITIALIZATION_PHASE); 24.41 + SEQUENCE_EAGER.insertFirst(CompilationPhase.LAZY_INITIALIZATION_PHASE); 24.42 24.43 - final static CompilationSequence SEQUENCE_DEFAULT = 24.44 - LAZY_JIT ? 24.45 - SEQUENCE_LAZY : 24.46 - SEQUENCE_NORMAL; 24.47 + private static CompilationSequence sequence(final boolean lazy) { 24.48 + return lazy ? SEQUENCE_LAZY : SEQUENCE_EAGER; 24.49 + } 24.50 + 24.51 + boolean isLazy() { 24.52 + return sequence == SEQUENCE_LAZY; 24.53 + } 24.54 24.55 private static String lazyTag(final FunctionNode functionNode) { 24.56 if (functionNode.isLazy()) { 24.57 @@ -212,11 +216,6 @@ 24.58 append(safeSourceName(functionNode.getSource())); 24.59 24.60 this.scriptName = sb.toString(); 24.61 - 24.62 - LOG.info("Initializing compiler for '" + functionNode.getName() + "' scriptName = " + scriptName + ", root function: '" + functionNode.getName() + "'"); 24.63 - if (functionNode.isLazy()) { 24.64 - LOG.info(">>> This is a lazy recompilation triggered by a trampoline"); 24.65 - } 24.66 } 24.67 24.68 /** 24.69 @@ -227,7 +226,7 @@ 24.70 * @param strict should this compilation use strict mode semantics 24.71 */ 24.72 public Compiler(final CodeInstaller<ScriptEnvironment> installer, final FunctionNode functionNode, final boolean strict) { 24.73 - this(installer.getOwner(), installer, functionNode, SEQUENCE_DEFAULT, strict); 24.74 + this(installer.getOwner(), installer, functionNode, sequence(installer.getOwner()._lazy_compilation), strict); 24.75 } 24.76 24.77 /** 24.78 @@ -237,7 +236,7 @@ 24.79 * @param functionNode function node (in any available {@link CompilationState}) to compile 24.80 */ 24.81 public Compiler(final CodeInstaller<ScriptEnvironment> installer, final FunctionNode functionNode) { 24.82 - this(installer.getOwner(), installer, functionNode, SEQUENCE_DEFAULT, installer.getOwner()._strict); 24.83 + this(installer.getOwner(), installer, functionNode, sequence(installer.getOwner()._lazy_compilation), installer.getOwner()._strict); 24.84 } 24.85 24.86 /** 24.87 @@ -247,28 +246,104 @@ 24.88 * @param functionNode functionNode to compile 24.89 */ 24.90 public Compiler(final ScriptEnvironment env, final FunctionNode functionNode) { 24.91 - this(env, null, functionNode, SEQUENCE_DEFAULT, env._strict); 24.92 + this(env, null, functionNode, sequence(env._lazy_compilation), env._strict); 24.93 } 24.94 24.95 /** 24.96 * Execute the compilation this Compiler was created with 24.97 + * @params param types if known, for specialization 24.98 * @throws CompilationException if something goes wrong 24.99 + * @return this compiler, for possible chaining 24.100 */ 24.101 - public void compile() throws CompilationException { 24.102 + public Compiler compile() throws CompilationException { 24.103 + return compile(null); 24.104 + } 24.105 + 24.106 + /** 24.107 + * Execute the compilation this Compiler was created with 24.108 + * @param paramTypes param types if known, for specialization 24.109 + * @throws CompilationException if something goes wrong 24.110 + * @return this compiler, for possible chaining 24.111 + */ 24.112 + public Compiler compile(final Class<?> paramTypes) throws CompilationException { 24.113 for (final String reservedName : RESERVED_NAMES) { 24.114 functionNode.uniqueName(reservedName); 24.115 } 24.116 24.117 + final boolean fine = !LOG.levelAbove(Level.FINE); 24.118 + final boolean info = !LOG.levelAbove(Level.INFO); 24.119 + 24.120 + long time = 0L; 24.121 + 24.122 for (final CompilationPhase phase : sequence) { 24.123 phase.apply(this, functionNode); 24.124 - final String end = phase.toString() + " done for function '" + functionNode.getName() + "'"; 24.125 - if (Timing.isEnabled()) { 24.126 - final long duration = phase.getEndTime() - phase.getStartTime(); 24.127 - LOG.info(end + " in " + duration + " ms"); 24.128 - } else { 24.129 - LOG.info(end); 24.130 + 24.131 + final long duration = Timing.isEnabled() ? (phase.getEndTime() - phase.getStartTime()) : 0L; 24.132 + time += duration; 24.133 + 24.134 + if (fine) { 24.135 + final StringBuilder sb = new StringBuilder(); 24.136 + 24.137 + sb.append(phase.toString()). 24.138 + append(" done for function '"). 24.139 + append(functionNode.getName()). 24.140 + append('\''); 24.141 + 24.142 + if (duration > 0L) { 24.143 + sb.append(" in "). 24.144 + append(duration). 24.145 + append(" ms "); 24.146 + } 24.147 + 24.148 + LOG.fine(sb.toString()); 24.149 } 24.150 } 24.151 + 24.152 + if (info) { 24.153 + final StringBuilder sb = new StringBuilder(); 24.154 + sb.append("Compile job for '"). 24.155 + append(functionNode.getName()). 24.156 + append("' finished"); 24.157 + 24.158 + if (time > 0L) { 24.159 + sb.append(" in "). 24.160 + append(time). 24.161 + append(" ms"); 24.162 + } 24.163 + 24.164 + LOG.info(sb.toString()); 24.165 + } 24.166 + 24.167 + return this; 24.168 + } 24.169 + 24.170 + private Class<?> install(final String className, final byte[] code) { 24.171 + LOG.fine("Installing class " + className); 24.172 + 24.173 + final Class<?> clazz = installer.install(Compiler.binaryName(className), code); 24.174 + 24.175 + try { 24.176 + final Source source = getSource(); 24.177 + final Object[] constants = getConstantData().toArray(); 24.178 + // Need doPrivileged because these fields are private 24.179 + AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { 24.180 + @Override 24.181 + public Void run() throws Exception { 24.182 + //use reflection to write source and constants table to installed classes 24.183 + final Field sourceField = clazz.getDeclaredField(SOURCE.tag()); 24.184 + final Field constantsField = clazz.getDeclaredField(CONSTANTS.tag()); 24.185 + sourceField.setAccessible(true); 24.186 + constantsField.setAccessible(true); 24.187 + sourceField.set(null, source); 24.188 + constantsField.set(null, constants); 24.189 + return null; 24.190 + } 24.191 + }); 24.192 + } catch (final PrivilegedActionException e) { 24.193 + throw new RuntimeException(e); 24.194 + } 24.195 + 24.196 + return clazz; 24.197 } 24.198 24.199 /** 24.200 @@ -280,46 +355,68 @@ 24.201 24.202 assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " has no bytecode and cannot be installed"; 24.203 24.204 - Class<?> rootClass = null; 24.205 + final Map<String, Class<?>> installedClasses = new HashMap<>(); 24.206 + 24.207 + final String rootClassName = firstCompileUnitName(); 24.208 + final byte[] rootByteCode = bytecode.get(rootClassName); 24.209 + final Class<?> rootClass = install(rootClassName, rootByteCode); 24.210 + 24.211 + int length = rootByteCode.length; 24.212 + 24.213 + installedClasses.put(rootClassName, rootClass); 24.214 24.215 for (final Entry<String, byte[]> entry : bytecode.entrySet()) { 24.216 - final String className = entry.getKey(); 24.217 - LOG.fine("Installing class " + className); 24.218 + final String className = entry.getKey(); 24.219 + if (className.equals(rootClassName)) { 24.220 + continue; 24.221 + } 24.222 + final byte[] code = entry.getValue(); 24.223 + length += code.length; 24.224 24.225 - final byte[] code = entry.getValue(); 24.226 - final Class<?> clazz = installer.install(Compiler.binaryName(className), code); 24.227 + installedClasses.put(className, install(className, code)); 24.228 + } 24.229 24.230 - if (rootClass == null && firstCompileUnitName().equals(className)) { 24.231 - rootClass = clazz; 24.232 + for (final CompileUnit unit : compileUnits) { 24.233 + unit.setCode(installedClasses.get(unit.getUnitClassName())); 24.234 + } 24.235 + 24.236 + functionNode.accept(new NodeVisitor() { 24.237 + @Override 24.238 + public Node enterFunctionNode(final FunctionNode node) { 24.239 + if (node.isLazy()) { 24.240 + return null; 24.241 + } 24.242 + node.setState(CompilationState.INSTALLED); 24.243 + return node; 24.244 } 24.245 + }); 24.246 24.247 - try { 24.248 - final Source source = getSource(); 24.249 - final Object[] constants = getConstantData().toArray(); 24.250 - // Need doPrivileged because these fields are private 24.251 - AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { 24.252 - @Override 24.253 - public Void run() throws Exception { 24.254 - //use reflection to write source and constants table to installed classes 24.255 - final Field sourceField = clazz.getDeclaredField(SOURCE.tag()); 24.256 - final Field constantsField = clazz.getDeclaredField(CONSTANTS.tag()); 24.257 - sourceField.setAccessible(true); 24.258 - constantsField.setAccessible(true); 24.259 - sourceField.set(null, source); 24.260 - constantsField.set(null, constants); 24.261 - return null; 24.262 - } 24.263 - }); 24.264 - } catch (final PrivilegedActionException e) { 24.265 - throw new RuntimeException(e); 24.266 + final StringBuilder sb; 24.267 + if (LOG.isEnabled()) { 24.268 + sb = new StringBuilder(); 24.269 + sb.append("Installed class '"). 24.270 + append(rootClass.getSimpleName()). 24.271 + append('\''). 24.272 + append(" bytes="). 24.273 + append(length). 24.274 + append('.'); 24.275 + if (bytecode.size() > 1) { 24.276 + sb.append(' ').append(bytecode.size()).append(" compile units."); 24.277 + } 24.278 + } else { 24.279 + sb = null; 24.280 + } 24.281 + 24.282 + if (Timing.isEnabled()) { 24.283 + final long duration = System.currentTimeMillis() - t0; 24.284 + Timing.accumulateTime("[Code Installation]", duration); 24.285 + if (sb != null) { 24.286 + sb.append(" Install time: ").append(duration).append(" ms"); 24.287 } 24.288 } 24.289 24.290 - LOG.info("Installed root class: " + rootClass + " and " + bytecode.size() + " compile unit classes"); 24.291 - if (Timing.isEnabled()) { 24.292 - final long duration = System.currentTimeMillis() - t0; 24.293 - Timing.accumulateTime("[Code Installation]", duration); 24.294 - LOG.info("Installation time: " + duration + " ms"); 24.295 + if (sb != null) { 24.296 + LOG.info(sb.toString()); 24.297 } 24.298 24.299 return rootClass; 24.300 @@ -444,8 +541,6 @@ 24.301 * TODO: We currently generate no overflow checks so this is 24.302 * disabled 24.303 * 24.304 - * @see #shouldUseIntegers() 24.305 - * 24.306 * @return true if arithmetic operations should not widen integer 24.307 * operands by default. 24.308 */ 24.309 @@ -460,4 +555,5 @@ 24.310 assert !USE_INT_ARITH : "Integer arithmetic is not enabled"; 24.311 } 24.312 24.313 + 24.314 }
25.1 --- a/src/jdk/nashorn/internal/codegen/FinalizeTypes.java Thu Mar 28 10:55:17 2013 -0700 25.2 +++ b/src/jdk/nashorn/internal/codegen/FinalizeTypes.java Mon Apr 01 21:42:31 2013 -0700 25.3 @@ -40,13 +40,14 @@ 25.4 import jdk.nashorn.internal.ir.ExecuteNode; 25.5 import jdk.nashorn.internal.ir.ForNode; 25.6 import jdk.nashorn.internal.ir.FunctionNode; 25.7 +import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 25.8 import jdk.nashorn.internal.ir.IdentNode; 25.9 import jdk.nashorn.internal.ir.IfNode; 25.10 import jdk.nashorn.internal.ir.IndexNode; 25.11 +import jdk.nashorn.internal.ir.LexicalContext; 25.12 import jdk.nashorn.internal.ir.LiteralNode; 25.13 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 25.14 import jdk.nashorn.internal.ir.Node; 25.15 -import jdk.nashorn.internal.ir.ReferenceNode; 25.16 import jdk.nashorn.internal.ir.ReturnNode; 25.17 import jdk.nashorn.internal.ir.RuntimeNode; 25.18 import jdk.nashorn.internal.ir.RuntimeNode.Request; 25.19 @@ -84,11 +85,13 @@ 25.20 25.21 private static final DebugLogger LOG = new DebugLogger("finalize"); 25.22 25.23 + private final LexicalContext lexicalContext = new LexicalContext(); 25.24 + 25.25 FinalizeTypes() { 25.26 } 25.27 25.28 @Override 25.29 - public Node leave(final CallNode callNode) { 25.30 + public Node leaveCallNode(final CallNode callNode) { 25.31 final EvalArgs evalArgs = callNode.getEvalArgs(); 25.32 if (evalArgs != null) { 25.33 evalArgs.setCode(evalArgs.getCode().accept(this)); 25.34 @@ -96,15 +99,14 @@ 25.35 25.36 // AccessSpecializer - call return type may change the access for this location 25.37 final Node function = callNode.getFunction(); 25.38 - if (function instanceof ReferenceNode) { 25.39 - setTypeOverride(callNode, ((ReferenceNode)function).getReference().getType()); 25.40 + if (function instanceof FunctionNode) { 25.41 + return setTypeOverride(callNode, ((FunctionNode)function).getReturnType()); 25.42 } 25.43 return callNode; 25.44 } 25.45 25.46 private Node leaveUnary(final UnaryNode unaryNode) { 25.47 - unaryNode.setRHS(convert(unaryNode.rhs(), unaryNode.getType())); 25.48 - return unaryNode; 25.49 + return unaryNode.setRHS(convert(unaryNode.rhs(), unaryNode.getType())); 25.50 } 25.51 25.52 @Override 25.53 @@ -125,8 +127,7 @@ 25.54 25.55 @Override 25.56 public Node leaveDECINC(final UnaryNode unaryNode) { 25.57 - specialize(unaryNode); 25.58 - return unaryNode; 25.59 + return specialize(unaryNode).node; 25.60 } 25.61 25.62 @Override 25.63 @@ -158,9 +159,7 @@ 25.64 } 25.65 } 25.66 25.67 - binaryNode.setLHS(convert(lhs, type)); 25.68 - binaryNode.setRHS(convert(rhs, type)); 25.69 - return binaryNode; 25.70 + return binaryNode.setLHS(convert(lhs, type)).setRHS(convert(rhs, type)); 25.71 } 25.72 25.73 @Override 25.74 @@ -170,12 +169,13 @@ 25.75 25.76 @Override 25.77 public Node leaveASSIGN(final BinaryNode binaryNode) { 25.78 - Type destType = specialize(binaryNode); 25.79 + final SpecializedNode specialized = specialize(binaryNode); 25.80 + final BinaryNode specBinaryNode = (BinaryNode)specialized.node; 25.81 + Type destType = specialized.type; 25.82 if (destType == null) { 25.83 - destType = binaryNode.getType(); 25.84 + destType = specBinaryNode.getType(); 25.85 } 25.86 - binaryNode.setRHS(convert(binaryNode.rhs(), destType)); 25.87 - return binaryNode; 25.88 + return specBinaryNode.setRHS(convert(specBinaryNode.rhs(), destType)); 25.89 } 25.90 25.91 @Override 25.92 @@ -235,40 +235,40 @@ 25.93 25.94 @Override 25.95 public Node leaveBIT_AND(BinaryNode binaryNode) { 25.96 - assert binaryNode.getSymbol() != null && binaryNode.getSymbol().getSymbolType().isInteger() : binaryNode.getSymbol(); 25.97 + assert binaryNode.getSymbol() != null && binaryNode.getSymbol().getSymbolType().isInteger() : "int coercion expected: " + binaryNode.getSymbol(); 25.98 return leaveBinary(binaryNode, Type.INT, Type.INT); 25.99 } 25.100 25.101 @Override 25.102 public Node leaveBIT_OR(BinaryNode binaryNode) { 25.103 - assert binaryNode.getSymbol() != null && binaryNode.getSymbol().getSymbolType().isInteger(); 25.104 + assert binaryNode.getSymbol() != null && binaryNode.getSymbol().getSymbolType().isInteger() : "int coercion expected: " + binaryNode.getSymbol(); 25.105 return leaveBinary(binaryNode, Type.INT, Type.INT); 25.106 } 25.107 25.108 @Override 25.109 public Node leaveBIT_XOR(BinaryNode binaryNode) { 25.110 - assert binaryNode.getSymbol() != null && binaryNode.getSymbol().getSymbolType().isInteger(); 25.111 + assert binaryNode.getSymbol() != null && binaryNode.getSymbol().getSymbolType().isInteger() : "int coercion expected: " + binaryNode.getSymbol(); 25.112 return leaveBinary(binaryNode, Type.INT, Type.INT); 25.113 } 25.114 25.115 @Override 25.116 public Node leaveCOMMALEFT(final BinaryNode binaryNode) { 25.117 assert binaryNode.getSymbol() != null; 25.118 - binaryNode.setRHS(discard(binaryNode.rhs())); 25.119 - // AccessSpecializer - the type of rhs, which is the remaining value of this node may have changed 25.120 + final BinaryNode newBinaryNode = (BinaryNode)binaryNode.setRHS(discard(binaryNode.rhs())); 25.121 + // AccessSpecializer - the type of lhs, which is the remaining value of this node may have changed 25.122 // in that case, update the node type as well 25.123 - propagateType(binaryNode, binaryNode.lhs().getType()); 25.124 - return binaryNode; 25.125 + propagateType(newBinaryNode, newBinaryNode.lhs().getType()); 25.126 + return newBinaryNode; 25.127 } 25.128 25.129 @Override 25.130 public Node leaveCOMMARIGHT(final BinaryNode binaryNode) { 25.131 assert binaryNode.getSymbol() != null; 25.132 - binaryNode.setLHS(discard(binaryNode.lhs())); 25.133 + final BinaryNode newBinaryNode = binaryNode.setLHS(discard(binaryNode.lhs())); 25.134 // AccessSpecializer - the type of rhs, which is the remaining value of this node may have changed 25.135 // in that case, update the node type as well 25.136 - propagateType(binaryNode, binaryNode.rhs().getType()); 25.137 - return binaryNode; 25.138 + propagateType(newBinaryNode, newBinaryNode.rhs().getType()); 25.139 + return newBinaryNode; 25.140 } 25.141 25.142 @Override 25.143 @@ -344,7 +344,7 @@ 25.144 25.145 @Override 25.146 public Node leaveSHR(final BinaryNode binaryNode) { 25.147 - assert binaryNode.getSymbol() != null && binaryNode.getSymbol().getSymbolType().isLong(); 25.148 + assert binaryNode.getSymbol() != null && binaryNode.getSymbol().getSymbolType().isLong() : "long coercion expected: " + binaryNode.getSymbol(); 25.149 return leaveBinary(binaryNode, Type.INT, Type.INT); 25.150 } 25.151 25.152 @@ -354,13 +354,20 @@ 25.153 } 25.154 25.155 @Override 25.156 - public Node enter(final Block block) { 25.157 + public Node enterBlock(final Block block) { 25.158 + lexicalContext.push(block); 25.159 updateSymbols(block); 25.160 return block; 25.161 } 25.162 25.163 @Override 25.164 - public Node leave(final CatchNode catchNode) { 25.165 + public Node leaveBlock(Block block) { 25.166 + lexicalContext.pop(block); 25.167 + return super.leaveBlock(block); 25.168 + } 25.169 + 25.170 + @Override 25.171 + public Node leaveCatchNode(final CatchNode catchNode) { 25.172 final Node exceptionCondition = catchNode.getExceptionCondition(); 25.173 if (exceptionCondition != null) { 25.174 catchNode.setExceptionCondition(convert(exceptionCondition, Type.BOOLEAN)); 25.175 @@ -369,23 +376,23 @@ 25.176 } 25.177 25.178 @Override 25.179 - public Node enter(final DoWhileNode doWhileNode) { 25.180 - return enter((WhileNode)doWhileNode); 25.181 + public Node enterDoWhileNode(final DoWhileNode doWhileNode) { 25.182 + return enterWhileNode(doWhileNode); 25.183 } 25.184 25.185 @Override 25.186 - public Node leave(final DoWhileNode doWhileNode) { 25.187 - return leave((WhileNode)doWhileNode); 25.188 + public Node leaveDoWhileNode(final DoWhileNode doWhileNode) { 25.189 + return leaveWhileNode(doWhileNode); 25.190 } 25.191 25.192 @Override 25.193 - public Node leave(final ExecuteNode executeNode) { 25.194 + public Node leaveExecuteNode(final ExecuteNode executeNode) { 25.195 executeNode.setExpression(discard(executeNode.getExpression())); 25.196 return executeNode; 25.197 } 25.198 25.199 @Override 25.200 - public Node leave(final ForNode forNode) { 25.201 + public Node leaveForNode(final ForNode forNode) { 25.202 final Node init = forNode.getInit(); 25.203 final Node test = forNode.getTest(); 25.204 final Node modify = forNode.getModify(); 25.205 @@ -413,11 +420,12 @@ 25.206 } 25.207 25.208 @Override 25.209 - public Node enter(final FunctionNode functionNode) { 25.210 + public Node enterFunctionNode(final FunctionNode functionNode) { 25.211 if (functionNode.isLazy()) { 25.212 return null; 25.213 } 25.214 25.215 + lexicalContext.push(functionNode); 25.216 // If the function doesn't need a callee, we ensure its __callee__ symbol doesn't get a slot. We can't do 25.217 // this earlier, as access to scoped variables, self symbol, etc. in previous phases can all trigger the 25.218 // need for the callee. 25.219 @@ -432,18 +440,26 @@ 25.220 } 25.221 25.222 updateSymbols(functionNode); 25.223 + functionNode.setState(CompilationState.FINALIZED); 25.224 + 25.225 return functionNode; 25.226 } 25.227 25.228 @Override 25.229 - public Node leave(final IfNode ifNode) { 25.230 + public Node leaveFunctionNode(FunctionNode functionNode) { 25.231 + lexicalContext.pop(functionNode); 25.232 + return super.leaveFunctionNode(functionNode); 25.233 + } 25.234 + 25.235 + @Override 25.236 + public Node leaveIfNode(final IfNode ifNode) { 25.237 ifNode.setTest(convert(ifNode.getTest(), Type.BOOLEAN)); 25.238 return ifNode; 25.239 } 25.240 25.241 @SuppressWarnings("rawtypes") 25.242 @Override 25.243 - public Node enter(final LiteralNode literalNode) { 25.244 + public Node enterLiteralNode(final LiteralNode literalNode) { 25.245 if (literalNode instanceof ArrayLiteralNode) { 25.246 final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode)literalNode; 25.247 final Node[] array = arrayLiteralNode.getValue(); 25.248 @@ -461,7 +477,7 @@ 25.249 } 25.250 25.251 @Override 25.252 - public Node leave(final ReturnNode returnNode) { 25.253 + public Node leaveReturnNode(final ReturnNode returnNode) { 25.254 final Node expr = returnNode.getExpression(); 25.255 if (expr != null) { 25.256 returnNode.setExpression(convert(expr, getCurrentFunctionNode().getReturnType())); 25.257 @@ -470,7 +486,7 @@ 25.258 } 25.259 25.260 @Override 25.261 - public Node leave(final RuntimeNode runtimeNode) { 25.262 + public Node leaveRuntimeNode(final RuntimeNode runtimeNode) { 25.263 final List<Node> args = runtimeNode.getArgs(); 25.264 for (final Node arg : args) { 25.265 assert !arg.getType().isUnknown(); 25.266 @@ -479,7 +495,7 @@ 25.267 } 25.268 25.269 @Override 25.270 - public Node leave(final SwitchNode switchNode) { 25.271 + public Node leaveSwitchNode(final SwitchNode switchNode) { 25.272 final Node expression = switchNode.getExpression(); 25.273 final List<CaseNode> cases = switchNode.getCases(); 25.274 final boolean allInteger = switchNode.getTag().getSymbolType().isInteger(); 25.275 @@ -498,34 +514,34 @@ 25.276 } 25.277 25.278 @Override 25.279 - public Node leave(final TernaryNode ternaryNode) { 25.280 - ternaryNode.setLHS(convert(ternaryNode.lhs(), Type.BOOLEAN)); 25.281 - return ternaryNode; 25.282 + public Node leaveTernaryNode(final TernaryNode ternaryNode) { 25.283 + return ternaryNode.setLHS(convert(ternaryNode.lhs(), Type.BOOLEAN)); 25.284 } 25.285 25.286 @Override 25.287 - public Node leave(final ThrowNode throwNode) { 25.288 + public Node leaveThrowNode(final ThrowNode throwNode) { 25.289 throwNode.setExpression(convert(throwNode.getExpression(), Type.OBJECT)); 25.290 return throwNode; 25.291 } 25.292 25.293 @Override 25.294 - public Node leave(final VarNode varNode) { 25.295 - 25.296 + public Node leaveVarNode(final VarNode varNode) { 25.297 final Node rhs = varNode.getInit(); 25.298 if (rhs != null) { 25.299 - Type destType = specialize(varNode); 25.300 + final SpecializedNode specialized = specialize(varNode); 25.301 + final VarNode specVarNode = (VarNode)specialized.node; 25.302 + Type destType = specialized.type; 25.303 if (destType == null) { 25.304 - destType = varNode.getType(); 25.305 + destType = specVarNode.getType(); 25.306 } 25.307 - assert varNode.hasType() : varNode + " doesn't have a type"; 25.308 - varNode.setInit(convert(rhs, destType)); 25.309 + assert specVarNode.hasType() : specVarNode + " doesn't have a type"; 25.310 + return specVarNode.setInit(convert(rhs, destType)); 25.311 } 25.312 return varNode; 25.313 } 25.314 25.315 @Override 25.316 - public Node leave(final WhileNode whileNode) { 25.317 + public Node leaveWhileNode(final WhileNode whileNode) { 25.318 final Node test = whileNode.getTest(); 25.319 if (test != null) { 25.320 whileNode.setTest(convert(test, Type.BOOLEAN)); 25.321 @@ -534,7 +550,7 @@ 25.322 } 25.323 25.324 @Override 25.325 - public Node leave(final WithNode withNode) { 25.326 + public Node leaveWithNode(final WithNode withNode) { 25.327 withNode.setExpression(convert(withNode.getExpression(), Type.OBJECT)); 25.328 return withNode; 25.329 } 25.330 @@ -553,14 +569,14 @@ 25.331 * that scope and slot information is correct for every symbol 25.332 * @param block block for which to to finalize type info. 25.333 */ 25.334 - private static void updateSymbols(final Block block) { 25.335 + private void updateSymbols(final Block block) { 25.336 if (!block.needsScope()) { 25.337 return; // nothing to do 25.338 } 25.339 25.340 - assert !(block instanceof FunctionNode) || block.getFunction() == block; 25.341 + final FunctionNode functionNode = lexicalContext.getFunction(block); 25.342 + assert !(block instanceof FunctionNode) || functionNode == block; 25.343 25.344 - final FunctionNode functionNode = block.getFunction(); 25.345 final List<Symbol> symbols = block.getFrame().getSymbols(); 25.346 final boolean allVarsInScope = functionNode.allVarsInScope(); 25.347 final boolean isVarArg = functionNode.isVarArg(); 25.348 @@ -629,10 +645,7 @@ 25.349 break; 25.350 } 25.351 25.352 - binaryNode.setLHS(convert(lhs, widest)); 25.353 - binaryNode.setRHS(convert(rhs, widest)); 25.354 - 25.355 - return binaryNode; 25.356 + return binaryNode.setLHS(convert(lhs, widest)).setRHS(convert(rhs, widest)); 25.357 } 25.358 25.359 /** 25.360 @@ -654,9 +667,7 @@ 25.361 } 25.362 25.363 private Node leaveBinary(final BinaryNode binaryNode, final Type lhsType, final Type rhsType) { 25.364 - binaryNode.setLHS(convert(binaryNode.lhs(), lhsType)); 25.365 - binaryNode.setRHS(convert(binaryNode.rhs(), rhsType)); 25.366 - return binaryNode; 25.367 + return binaryNode.setLHS(convert(binaryNode.lhs(), lhsType)).setRHS(convert(binaryNode.rhs(), rhsType)); 25.368 } 25.369 25.370 /** 25.371 @@ -677,7 +688,7 @@ 25.372 } 25.373 25.374 @Override 25.375 - public Node enter(final IdentNode identNode) { 25.376 + public Node enterIdentNode(final IdentNode identNode) { 25.377 if (!exclude.contains(identNode)) { 25.378 setCanBePrimitive(identNode.getSymbol()); 25.379 } 25.380 @@ -685,26 +696,36 @@ 25.381 } 25.382 25.383 @Override 25.384 - public Node enter(final AccessNode accessNode) { 25.385 + public Node enterAccessNode(final AccessNode accessNode) { 25.386 setCanBePrimitive(accessNode.getProperty().getSymbol()); 25.387 return null; 25.388 } 25.389 25.390 @Override 25.391 - public Node enter(final IndexNode indexNode) { 25.392 + public Node enterIndexNode(final IndexNode indexNode) { 25.393 exclude.add(indexNode.getBase()); //prevent array base node to be flagged as primitive, but k in a[k++] is fine 25.394 return indexNode; 25.395 } 25.396 }); 25.397 } 25.398 25.399 - private static Type specialize(final Assignment<?> assignment) { 25.400 + private static class SpecializedNode { 25.401 + final Node node; 25.402 + final Type type; 25.403 + 25.404 + SpecializedNode(Node node, Type type) { 25.405 + this.node = node; 25.406 + this.type = type; 25.407 + } 25.408 + } 25.409 + 25.410 + private static <T extends Node> SpecializedNode specialize(final Assignment<T> assignment) { 25.411 final Node node = ((Node)assignment); 25.412 - final Node lhs = assignment.getAssignmentDest(); 25.413 + final T lhs = assignment.getAssignmentDest(); 25.414 final Node rhs = assignment.getAssignmentSource(); 25.415 25.416 if (!canHaveCallSiteType(lhs)) { 25.417 - return null; 25.418 + return new SpecializedNode(node, null); 25.419 } 25.420 25.421 final Type to; 25.422 @@ -716,13 +737,13 @@ 25.423 25.424 if (!isSupportedCallSiteType(to)) { 25.425 //meaningless to specialize to boolean or object 25.426 - return null; 25.427 + return new SpecializedNode(node, null); 25.428 } 25.429 25.430 - setTypeOverride(lhs, to); 25.431 - propagateType(node, to); 25.432 + final Node newNode = assignment.setAssignmentDest(setTypeOverride(lhs, to)); 25.433 + propagateType(newNode, to); 25.434 25.435 - return to; 25.436 + return new SpecializedNode(newNode, to); 25.437 } 25.438 25.439 25.440 @@ -734,7 +755,7 @@ 25.441 * @return true if node can have a callsite type 25.442 */ 25.443 private static boolean canHaveCallSiteType(final Node node) { 25.444 - return node instanceof TypeOverride && ((TypeOverride)node).canHaveCallSiteType(); 25.445 + return node instanceof TypeOverride && ((TypeOverride<?>)node).canHaveCallSiteType(); 25.446 } 25.447 25.448 /** 25.449 @@ -760,7 +781,8 @@ 25.450 * @param node node for which to change type 25.451 * @param to new type 25.452 */ 25.453 - private static void setTypeOverride(final Node node, final Type to) { 25.454 + @SuppressWarnings("unchecked") 25.455 + private static <T extends Node> T setTypeOverride(final T node, final Type to) { 25.456 final Type from = node.getType(); 25.457 if (!node.getType().equals(to)) { 25.458 LOG.info("Changing call override type for '" + node + "' from " + node.getType() + " to " + to); 25.459 @@ -769,7 +791,7 @@ 25.460 } 25.461 } 25.462 LOG.info("Type override for lhs in '" + node + "' => " + to); 25.463 - ((TypeOverride)node).setType(to); 25.464 + return ((TypeOverride<T>)node).setType(to); 25.465 } 25.466 25.467 /** 25.468 @@ -814,8 +836,8 @@ 25.469 } 25.470 } else { 25.471 if (canHaveCallSiteType(node) && isSupportedCallSiteType(to)) { 25.472 - setTypeOverride(node, to); 25.473 - return resultNode; 25.474 + assert node instanceof TypeOverride; 25.475 + return setTypeOverride(node, to); 25.476 } 25.477 resultNode = new UnaryNode(node.getSource(), Token.recast(node.getToken(), TokenType.CONVERT), node); 25.478 }
26.1 --- a/src/jdk/nashorn/internal/codegen/FoldConstants.java Thu Mar 28 10:55:17 2013 -0700 26.2 +++ b/src/jdk/nashorn/internal/codegen/FoldConstants.java Mon Apr 01 21:42:31 2013 -0700 26.3 @@ -30,6 +30,8 @@ 26.4 import jdk.nashorn.internal.ir.Block; 26.5 import jdk.nashorn.internal.ir.EmptyNode; 26.6 import jdk.nashorn.internal.ir.ExecuteNode; 26.7 +import jdk.nashorn.internal.ir.FunctionNode; 26.8 +import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 26.9 import jdk.nashorn.internal.ir.IfNode; 26.10 import jdk.nashorn.internal.ir.LiteralNode; 26.11 import jdk.nashorn.internal.ir.Node; 26.12 @@ -52,7 +54,7 @@ 26.13 } 26.14 26.15 @Override 26.16 - public Node leave(final UnaryNode unaryNode) { 26.17 + public Node leaveUnaryNode(final UnaryNode unaryNode) { 26.18 final LiteralNode<?> literalNode = new UnaryNodeConstantEvaluator(unaryNode).eval(); 26.19 if (literalNode != null) { 26.20 LOG.info("Unary constant folded " + unaryNode + " to " + literalNode); 26.21 @@ -62,7 +64,7 @@ 26.22 } 26.23 26.24 @Override 26.25 - public Node leave(final BinaryNode binaryNode) { 26.26 + public Node leaveBinaryNode(final BinaryNode binaryNode) { 26.27 final LiteralNode<?> literalNode = new BinaryNodeConstantEvaluator(binaryNode).eval(); 26.28 if (literalNode != null) { 26.29 LOG.info("Binary constant folded " + binaryNode + " to " + literalNode); 26.30 @@ -72,7 +74,21 @@ 26.31 } 26.32 26.33 @Override 26.34 - public Node leave(final IfNode ifNode) { 26.35 + public Node enterFunctionNode(final FunctionNode functionNode) { 26.36 + if (functionNode.isLazy()) { 26.37 + return null; 26.38 + } 26.39 + return functionNode; 26.40 + } 26.41 + 26.42 + @Override 26.43 + public Node leaveFunctionNode(final FunctionNode functionNode) { 26.44 + functionNode.setState(CompilationState.CONSTANT_FOLDED); 26.45 + return functionNode; 26.46 + } 26.47 + 26.48 + @Override 26.49 + public Node leaveIfNode(final IfNode ifNode) { 26.50 final Node test = ifNode.getTest(); 26.51 if (test instanceof LiteralNode) { 26.52 final Block shortCut = ((LiteralNode<?>)test).isTrue() ? ifNode.getPass() : ifNode.getFail(); 26.53 @@ -85,7 +101,7 @@ 26.54 } 26.55 26.56 @Override 26.57 - public Node leave(final TernaryNode ternaryNode) { 26.58 + public Node leaveTernaryNode(final TernaryNode ternaryNode) { 26.59 final Node test = ternaryNode.lhs(); 26.60 if (test instanceof LiteralNode) { 26.61 return ((LiteralNode<?>)test).isTrue() ? ternaryNode.rhs() : ternaryNode.third();
27.1 --- a/src/jdk/nashorn/internal/codegen/FunctionSignature.java Thu Mar 28 10:55:17 2013 -0700 27.2 +++ b/src/jdk/nashorn/internal/codegen/FunctionSignature.java Mon Apr 01 21:42:31 2013 -0700 27.3 @@ -146,7 +146,7 @@ 27.4 27.5 /** 27.6 * Create a function signature given a function node, using as much 27.7 - * type information for parameters and return types that is availabe 27.8 + * type information for parameters and return types that is available 27.9 * 27.10 * @param functionNode the function node 27.11 */ 27.12 @@ -155,7 +155,7 @@ 27.13 true, 27.14 functionNode.needsCallee(), 27.15 functionNode.getReturnType(), 27.16 - (functionNode.isVarArg() && !functionNode.isScript()) ? 27.17 + (functionNode.isVarArg() && !functionNode.isProgram()) ? 27.18 null : 27.19 functionNode.getParameters()); 27.20 } 27.21 @@ -202,6 +202,14 @@ 27.22 return methodType; 27.23 } 27.24 27.25 + /** 27.26 + * Return the return type for this function signature 27.27 + * @return the return type 27.28 + */ 27.29 + public Type getReturnType() { 27.30 + return returnType; 27.31 + } 27.32 + 27.33 private static Type[] objectArgs(final int nArgs) { 27.34 final Type[] array = new Type[nArgs]; 27.35 for (int i = 0; i < nArgs; i++) {
28.1 --- a/src/jdk/nashorn/internal/codegen/Lower.java Thu Mar 28 10:55:17 2013 -0700 28.2 +++ b/src/jdk/nashorn/internal/codegen/Lower.java Mon Apr 01 21:42:31 2013 -0700 28.3 @@ -37,8 +37,8 @@ 28.4 import java.util.ArrayList; 28.5 import java.util.Arrays; 28.6 import java.util.Deque; 28.7 +import java.util.Iterator; 28.8 import java.util.List; 28.9 -import jdk.nashorn.internal.ir.AccessNode; 28.10 import jdk.nashorn.internal.ir.BaseNode; 28.11 import jdk.nashorn.internal.ir.BinaryNode; 28.12 import jdk.nashorn.internal.ir.Block; 28.13 @@ -52,11 +52,12 @@ 28.14 import jdk.nashorn.internal.ir.ExecuteNode; 28.15 import jdk.nashorn.internal.ir.ForNode; 28.16 import jdk.nashorn.internal.ir.FunctionNode; 28.17 +import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 28.18 import jdk.nashorn.internal.ir.IdentNode; 28.19 import jdk.nashorn.internal.ir.IfNode; 28.20 -import jdk.nashorn.internal.ir.IndexNode; 28.21 import jdk.nashorn.internal.ir.LabelNode; 28.22 import jdk.nashorn.internal.ir.LabeledNode; 28.23 +import jdk.nashorn.internal.ir.LexicalContext; 28.24 import jdk.nashorn.internal.ir.LineNumberNode; 28.25 import jdk.nashorn.internal.ir.LiteralNode; 28.26 import jdk.nashorn.internal.ir.Node; 28.27 @@ -102,6 +103,8 @@ 28.28 28.29 private List<Node> statements; 28.30 28.31 + private LexicalContext lexicalContext = new LexicalContext(); 28.32 + 28.33 /** 28.34 * Constructor. 28.35 * 28.36 @@ -113,14 +116,15 @@ 28.37 } 28.38 28.39 @Override 28.40 - public Node enter(final Block block) { 28.41 + public Node enterBlock(final Block block) { 28.42 final Node savedLastStatement = lastStatement; 28.43 final List<Node> savedStatements = statements; 28.44 - 28.45 + lexicalContext.push(block); 28.46 try { 28.47 this.statements = new ArrayList<>(); 28.48 + NodeVisitor visitor = this; 28.49 for (final Node statement : block.getStatements()) { 28.50 - statement.accept(this); 28.51 + statement.accept(visitor); 28.52 /* 28.53 * This is slightly unsound, for example if we have a loop with 28.54 * a guarded statement like if (x) continue in the body and the 28.55 @@ -132,7 +136,7 @@ 28.56 */ 28.57 if (lastStatement != null && lastStatement.isTerminal()) { 28.58 copyTerminal(block, lastStatement); 28.59 - break; 28.60 + visitor = new DeadCodeVarDeclarationVisitor(); 28.61 } 28.62 } 28.63 block.setStatements(statements); 28.64 @@ -140,18 +144,19 @@ 28.65 } finally { 28.66 this.statements = savedStatements; 28.67 this.lastStatement = savedLastStatement; 28.68 + lexicalContext.pop(block); 28.69 } 28.70 28.71 return null; 28.72 } 28.73 28.74 @Override 28.75 - public Node enter(final BreakNode breakNode) { 28.76 + public Node enterBreakNode(final BreakNode breakNode) { 28.77 return enterBreakOrContinue(breakNode); 28.78 } 28.79 28.80 @Override 28.81 - public Node enter(final CallNode callNode) { 28.82 + public Node enterCallNode(final CallNode callNode) { 28.83 final Node function = markerFunction(callNode.getFunction()); 28.84 callNode.setFunction(function); 28.85 checkEval(callNode); //check if this is an eval call and store the information 28.86 @@ -159,44 +164,44 @@ 28.87 } 28.88 28.89 @Override 28.90 - public Node leave(final CaseNode caseNode) { 28.91 + public Node leaveCaseNode(final CaseNode caseNode) { 28.92 caseNode.copyTerminalFlags(caseNode.getBody()); 28.93 return caseNode; 28.94 } 28.95 28.96 @Override 28.97 - public Node leave(final CatchNode catchNode) { 28.98 + public Node leaveCatchNode(final CatchNode catchNode) { 28.99 catchNode.copyTerminalFlags(catchNode.getBody()); 28.100 addStatement(catchNode); 28.101 return catchNode; 28.102 } 28.103 28.104 @Override 28.105 - public Node enter(final ContinueNode continueNode) { 28.106 + public Node enterContinueNode(final ContinueNode continueNode) { 28.107 return enterBreakOrContinue(continueNode); 28.108 } 28.109 28.110 @Override 28.111 - public Node enter(final DoWhileNode doWhileNode) { 28.112 - return enter((WhileNode)doWhileNode); 28.113 + public Node enterDoWhileNode(final DoWhileNode doWhileNode) { 28.114 + return enterWhileNode(doWhileNode); 28.115 } 28.116 28.117 @Override 28.118 - public Node leave(final DoWhileNode doWhileNode) { 28.119 - return leave((WhileNode)doWhileNode); 28.120 + public Node leaveDoWhileNode(final DoWhileNode doWhileNode) { 28.121 + return leaveWhileNode(doWhileNode); 28.122 } 28.123 28.124 @Override 28.125 - public Node enter(final EmptyNode emptyNode) { 28.126 + public Node enterEmptyNode(final EmptyNode emptyNode) { 28.127 return null; 28.128 } 28.129 28.130 @Override 28.131 - public Node leave(final ExecuteNode executeNode) { 28.132 + public Node leaveExecuteNode(final ExecuteNode executeNode) { 28.133 final Node expr = executeNode.getExpression(); 28.134 28.135 - if (getCurrentFunctionNode().isScript()) { 28.136 - if (!(expr instanceof Block)) { 28.137 + if (getCurrentFunctionNode().isProgram()) { 28.138 + if (!(expr instanceof Block) || expr instanceof FunctionNode) { // it's not a block, but can be a function 28.139 if (!isInternalExpression(expr) && !isEvalResultAssignment(expr)) { 28.140 executeNode.setExpression(new BinaryNode(executeNode.getSource(), Token.recast(executeNode.getToken(), TokenType.ASSIGN), 28.141 getCurrentFunctionNode().getResultNode(), 28.142 @@ -212,13 +217,13 @@ 28.143 } 28.144 28.145 @Override 28.146 - public Node enter(final ForNode forNode) { 28.147 + public Node enterForNode(final ForNode forNode) { 28.148 nest(forNode); 28.149 return forNode; 28.150 } 28.151 28.152 @Override 28.153 - public Node leave(final ForNode forNode) { 28.154 + public Node leaveForNode(final ForNode forNode) { 28.155 final Node test = forNode.getTest(); 28.156 final Block body = forNode.getBody(); 28.157 28.158 @@ -236,6 +241,7 @@ 28.159 28.160 if (!forNode.isForIn() && conservativeAlwaysTrue(test)) { 28.161 forNode.setTest(null); 28.162 + setHasGoto(forNode); 28.163 setTerminal(forNode, !escapes); 28.164 } 28.165 28.166 @@ -245,18 +251,16 @@ 28.167 } 28.168 28.169 @Override 28.170 - public Node enter(final FunctionNode functionNode) { 28.171 + public Node enterFunctionNode(final FunctionNode functionNode) { 28.172 LOG.info("START FunctionNode: " + functionNode.getName()); 28.173 28.174 if (functionNode.isLazy()) { 28.175 LOG.info("LAZY: " + functionNode.getName()); 28.176 return null; 28.177 } 28.178 - 28.179 + lexicalContext.push(functionNode); 28.180 initFunctionNode(functionNode); 28.181 28.182 - Node initialEvalResult = LiteralNode.newInstance(functionNode, ScriptRuntime.UNDEFINED); 28.183 - 28.184 nest(functionNode); 28.185 28.186 /* 28.187 @@ -270,60 +274,40 @@ 28.188 statements = new ArrayList<>(); 28.189 lastStatement = null; 28.190 28.191 - // for initial eval result is the last declared function 28.192 - for (final FunctionNode nestedFunction : functionNode.getFunctions()) { 28.193 - final IdentNode ident = nestedFunction.getIdent(); 28.194 - if (ident != null && nestedFunction.isStatement()) { 28.195 - initialEvalResult = new IdentNode(ident); 28.196 - } 28.197 - } 28.198 - 28.199 if (functionNode.needsSelfSymbol()) { 28.200 //function needs to start with var funcIdent = __callee_; 28.201 statements.add(functionNode.getSelfSymbolInit().accept(this)); 28.202 } 28.203 28.204 + NodeVisitor visitor = this; 28.205 try { 28.206 - // Every nested function needs a definition in the outer function with its name. Add these. 28.207 - for (final FunctionNode nestedFunction : functionNode.getFunctions()) { 28.208 - final VarNode varNode = nestedFunction.getFunctionVarNode(); 28.209 - if (varNode != null) { 28.210 - final LineNumberNode lineNumberNode = nestedFunction.getFunctionVarLineNumberNode(); 28.211 - if (lineNumberNode != null) { 28.212 - lineNumberNode.accept(this); 28.213 - } 28.214 - varNode.accept(this); 28.215 - varNode.setIsFunctionVarNode(); 28.216 + //do the statements - this fills the block with code 28.217 + boolean needsInitialEvalResult = functionNode.isProgram(); 28.218 + for (final Node statement : functionNode.getStatements()) { 28.219 + // If this function is a program, then insert an assignment to the initial eval result after all 28.220 + // function declarations. 28.221 + if(needsInitialEvalResult && !(statement instanceof LineNumberNode || (statement instanceof VarNode && ((VarNode)statement).isFunctionDeclaration()))) { 28.222 + addInitialEvalResult(functionNode); 28.223 + needsInitialEvalResult = false; 28.224 } 28.225 - } 28.226 - 28.227 - if (functionNode.isScript()) { 28.228 - new ExecuteNode(functionNode.getSource(), functionNode.getFirstToken(), functionNode.getFinish(), initialEvalResult).accept(this); 28.229 - } 28.230 - 28.231 - //do the statements - this fills the block with code 28.232 - for (final Node statement : functionNode.getStatements()) { 28.233 - statement.accept(this); 28.234 + statement.accept(visitor); 28.235 //If there are unused terminated endpoints in the function, we need 28.236 // to add a "return undefined" in those places for correct semantics 28.237 LOG.info("Checking lastStatement="+lastStatement+" for terminal flags"); 28.238 if (lastStatement != null && lastStatement.hasTerminalFlags()) { 28.239 copyTerminal(functionNode, lastStatement); 28.240 - break; 28.241 + assert !needsInitialEvalResult; 28.242 + visitor = new DeadCodeVarDeclarationVisitor(); 28.243 } 28.244 } 28.245 - 28.246 + if(needsInitialEvalResult) { 28.247 + addInitialEvalResult(functionNode); 28.248 + } 28.249 functionNode.setStatements(statements); 28.250 28.251 if (!functionNode.isTerminal()) { 28.252 guaranteeReturn(functionNode); 28.253 } 28.254 - 28.255 - //lower all nested functions 28.256 - for (final FunctionNode nestedFunction : functionNode.getFunctions()) { 28.257 - nestedFunction.accept(this); 28.258 - } 28.259 - 28.260 } finally { 28.261 statements = savedStatements; 28.262 lastStatement = savedLastStatement; 28.263 @@ -331,17 +315,67 @@ 28.264 28.265 LOG.info("END FunctionNode: " + functionNode.getName()); 28.266 unnest(functionNode); 28.267 + lexicalContext.pop(functionNode); 28.268 + 28.269 + functionNode.setState(CompilationState.LOWERED); 28.270 28.271 return null; 28.272 } 28.273 28.274 + /** 28.275 + * This visitor is used to go over statements after a terminal statement. Those statements are dead code, but the 28.276 + * var declarations in them still have the effect of declaring a local variable on the function level. Therefore, 28.277 + * they aren't really dead code and must be preserved. Note that they're only preserved as no-op declarations; their 28.278 + * initializers are wiped out as those are, in fact, dead code. 28.279 + */ 28.280 + private class DeadCodeVarDeclarationVisitor extends NodeOperatorVisitor { 28.281 + DeadCodeVarDeclarationVisitor() { 28.282 + } 28.283 + 28.284 + @Override 28.285 + public Node enterVarNode(VarNode varNode) { 28.286 + // Can't ever see a function declaration, as this visitor is only ever used after a terminal statement was 28.287 + // encountered, and all function declarations precede any terminal statements. 28.288 + assert !varNode.isFunctionDeclaration(); 28.289 + if(varNode.getInit() == null) { 28.290 + // No initializer, just pass it to Lower. 28.291 + return varNode.accept(Lower.this); 28.292 + } 28.293 + // Wipe out the initializer and then pass it to Lower. 28.294 + return varNode.setInit(null).accept(Lower.this); 28.295 + } 28.296 + } 28.297 + 28.298 + private void addInitialEvalResult(final FunctionNode functionNode) { 28.299 + new ExecuteNode(functionNode.getSource(), functionNode.getFirstToken(), functionNode.getFinish(), 28.300 + getInitialEvalResult(functionNode)).accept(this); 28.301 + } 28.302 + 28.303 + /** 28.304 + * Result of initial result of evaluating a particular program, which is either the last function it declares, or 28.305 + * undefined if it doesn't declare any functions. 28.306 + * @param program 28.307 + * @return the initial result of evaluating the program 28.308 + */ 28.309 + private static Node getInitialEvalResult(final FunctionNode program) { 28.310 + IdentNode lastFnName = null; 28.311 + for (final FunctionNode fn : program.getDeclaredFunctions()) { 28.312 + assert fn.isDeclared(); 28.313 + final IdentNode fnName = fn.getIdent(); 28.314 + if(fnName != null) { 28.315 + lastFnName = fnName; 28.316 + } 28.317 + } 28.318 + return lastFnName != null ? new IdentNode(lastFnName) : LiteralNode.newInstance(program, ScriptRuntime.UNDEFINED); 28.319 + } 28.320 + 28.321 @Override 28.322 - public Node enter(final IfNode ifNode) { 28.323 + public Node enterIfNode(final IfNode ifNode) { 28.324 return nest(ifNode); 28.325 } 28.326 28.327 @Override 28.328 - public Node leave(final IfNode ifNode) { 28.329 + public Node leaveIfNode(final IfNode ifNode) { 28.330 final Node pass = ifNode.getPass(); 28.331 final Node fail = ifNode.getFail(); 28.332 28.333 @@ -356,7 +390,7 @@ 28.334 } 28.335 28.336 @Override 28.337 - public Node enter(LabelNode labelNode) { 28.338 + public Node enterLabelNode(LabelNode labelNode) { 28.339 final Block body = labelNode.getBody(); 28.340 body.accept(this); 28.341 copyTerminal(labelNode, body); 28.342 @@ -365,13 +399,13 @@ 28.343 } 28.344 28.345 @Override 28.346 - public Node enter(final LineNumberNode lineNumberNode) { 28.347 + public Node enterLineNumberNode(final LineNumberNode lineNumberNode) { 28.348 addStatement(lineNumberNode, false); // don't put it in lastStatement cache 28.349 return null; 28.350 } 28.351 28.352 @Override 28.353 - public Node enter(final ReturnNode returnNode) { 28.354 + public Node enterReturnNode(final ReturnNode returnNode) { 28.355 final TryNode tryNode = returnNode.getTryChain(); 28.356 final Node expr = returnNode.getExpression(); 28.357 28.358 @@ -409,19 +443,19 @@ 28.359 } 28.360 28.361 @Override 28.362 - public Node leave(final ReturnNode returnNode) { 28.363 + public Node leaveReturnNode(final ReturnNode returnNode) { 28.364 addStatement(returnNode); //ReturnNodes are always terminal, marked as such in constructor 28.365 return returnNode; 28.366 } 28.367 28.368 @Override 28.369 - public Node enter(final SwitchNode switchNode) { 28.370 + public Node enterSwitchNode(final SwitchNode switchNode) { 28.371 nest(switchNode); 28.372 return switchNode; 28.373 } 28.374 28.375 @Override 28.376 - public Node leave(final SwitchNode switchNode) { 28.377 + public Node leaveSwitchNode(final SwitchNode switchNode) { 28.378 unnest(switchNode); 28.379 28.380 final List<CaseNode> cases = switchNode.getCases(); 28.381 @@ -442,13 +476,13 @@ 28.382 } 28.383 28.384 @Override 28.385 - public Node leave(final ThrowNode throwNode) { 28.386 + public Node leaveThrowNode(final ThrowNode throwNode) { 28.387 addStatement(throwNode); //ThrowNodes are always terminal, marked as such in constructor 28.388 return throwNode; 28.389 } 28.390 28.391 @Override 28.392 - public Node enter(final TryNode tryNode) { 28.393 + public Node enterTryNode(final TryNode tryNode) { 28.394 final Block finallyBody = tryNode.getFinallyBody(); 28.395 final long token = tryNode.getToken(); 28.396 final int finish = tryNode.getFinish(); 28.397 @@ -534,26 +568,19 @@ 28.398 28.399 // set outer tryNode's body to innerTryNode 28.400 final Block outerBody; 28.401 - outerBody = new Block(source, token, finish, tryNode.getBody().getParent(), getCurrentFunctionNode()); 28.402 + outerBody = new Block(source, token, finish); 28.403 outerBody.setStatements(new ArrayList<Node>(Arrays.asList(innerTryNode))); 28.404 tryNode.setBody(outerBody); 28.405 tryNode.setCatchBlocks(null); 28.406 - 28.407 - // now before we go on, we have to fix the block parents 28.408 - // (we repair the block tree after the insertion so that all references are intact) 28.409 - innerTryNode.getBody().setParent(tryNode.getBody()); 28.410 - for (final Block block : innerTryNode.getCatchBlocks()) { 28.411 - block.setParent(tryNode.getBody()); 28.412 - } 28.413 } 28.414 28.415 // create a catch-all that inlines finally and rethrows 28.416 28.417 - final Block catchBlock = new Block(source, token, finish, getCurrentBlock(), getCurrentFunctionNode()); 28.418 + final Block catchBlock = new Block(source, token, finish); 28.419 //this catch block should get define symbol 28.420 28.421 - final Block catchBody = new Block(source, token, finish, catchBlock, getCurrentFunctionNode()); 28.422 - final Node catchAllFinally = finallyBody.clone(); 28.423 + final Block catchBody = new Block(source, token, finish); 28.424 + final Node catchAllFinally = finallyBody.copy(); 28.425 28.426 catchBody.addStatement(new ExecuteNode(source, finallyBody.getToken(), finallyBody.getFinish(), catchAllFinally)); 28.427 setTerminal(catchBody, true); 28.428 @@ -580,7 +607,7 @@ 28.429 } 28.430 28.431 @Override 28.432 - public Node leave(final TryNode tryNode) { 28.433 + public Node leaveTryNode(final TryNode tryNode) { 28.434 final Block finallyBody = tryNode.getFinallyBody(); 28.435 28.436 boolean allTerminal = tryNode.getBody().isTerminal() && (finallyBody == null || finallyBody.isTerminal()); 28.437 @@ -604,18 +631,18 @@ 28.438 } 28.439 28.440 @Override 28.441 - public Node leave(final VarNode varNode) { 28.442 + public Node leaveVarNode(final VarNode varNode) { 28.443 addStatement(varNode); 28.444 return varNode; 28.445 } 28.446 28.447 @Override 28.448 - public Node enter(final WhileNode whileNode) { 28.449 + public Node enterWhileNode(final WhileNode whileNode) { 28.450 return nest(whileNode); 28.451 } 28.452 28.453 @Override 28.454 - public Node leave(final WhileNode whileNode) { 28.455 + public Node leaveWhileNode(final WhileNode whileNode) { 28.456 final Node test = whileNode.getTest(); 28.457 28.458 if (test == null) { 28.459 @@ -636,7 +663,7 @@ 28.460 } else if (conservativeAlwaysTrue(test)) { 28.461 node = new ForNode(whileNode.getSource(), whileNode.getToken(), whileNode.getFinish()); 28.462 ((ForNode)node).setBody(body); 28.463 - ((ForNode)node).accept(this); 28.464 + node.accept(this); 28.465 setTerminal(node, !escapes); 28.466 } 28.467 } 28.468 @@ -649,7 +676,7 @@ 28.469 } 28.470 28.471 @Override 28.472 - public Node leave(final WithNode withNode) { 28.473 + public Node leaveWithNode(final WithNode withNode) { 28.474 if (withNode.getBody().isTerminal()) { 28.475 setTerminal(withNode, true); 28.476 } 28.477 @@ -678,28 +705,10 @@ 28.478 */ 28.479 private static Node markerFunction(final Node function) { 28.480 if (function instanceof IdentNode) { 28.481 - return new IdentNode((IdentNode)function) { 28.482 - @Override 28.483 - public boolean isFunction() { 28.484 - return true; 28.485 - } 28.486 - }; 28.487 - } else if (function instanceof AccessNode) { 28.488 - return new AccessNode((AccessNode)function) { 28.489 - @Override 28.490 - public boolean isFunction() { 28.491 - return true; 28.492 - } 28.493 - }; 28.494 - } else if (function instanceof IndexNode) { 28.495 - return new IndexNode((IndexNode)function) { 28.496 - @Override 28.497 - public boolean isFunction() { 28.498 - return true; 28.499 - } 28.500 - }; 28.501 + return ((IdentNode)function).setIsFunction(); 28.502 + } else if (function instanceof BaseNode) { 28.503 + return ((BaseNode)function).setIsFunction(); 28.504 } 28.505 - 28.506 return function; 28.507 } 28.508 28.509 @@ -742,7 +751,7 @@ 28.510 if (args.size() >= 1 && EVAL.tag().equals(callee.getName())) { 28.511 final CallNode.EvalArgs evalArgs = 28.512 new CallNode.EvalArgs( 28.513 - args.get(0).clone().accept(this), //clone as we use this for the "is eval case". original evaluated separately for "is not eval case" 28.514 + args.get(0).copy().accept(this), //clone as we use this for the "is eval case". original evaluated separately for "is not eval case" 28.515 getCurrentFunctionNode().getThisNode(), 28.516 evalLocation(callee), 28.517 getCurrentFunctionNode().isStrictMode()); 28.518 @@ -769,13 +778,13 @@ 28.519 28.520 loopBody.accept(new NodeVisitor() { 28.521 @Override 28.522 - public Node leave(final BreakNode node) { 28.523 + public Node leaveBreakNode(final BreakNode node) { 28.524 escapes.add(node); 28.525 return node; 28.526 } 28.527 28.528 @Override 28.529 - public Node leave(final ContinueNode node) { 28.530 + public Node leaveContinueNode(final ContinueNode node) { 28.531 // all inner loops have been popped. 28.532 if (nesting.contains(node.getTargetNode())) { 28.533 escapes.add(node); 28.534 @@ -790,7 +799,7 @@ 28.535 private void guaranteeReturn(final FunctionNode functionNode) { 28.536 Node resultNode; 28.537 28.538 - if (functionNode.isScript()) { 28.539 + if (functionNode.isProgram()) { 28.540 resultNode = functionNode.getResultNode(); // the eval result, symbol assigned in Attr 28.541 } else { 28.542 if (lastStatement != null && lastStatement.isTerminal() || lastStatement instanceof ReturnNode) { 28.543 @@ -855,18 +864,15 @@ 28.544 * @return true if try block is inside the target, false otherwise. 28.545 */ 28.546 private boolean isNestedTry(final TryNode tryNode, final Block target) { 28.547 - for (Block current = getCurrentBlock(); current != target; current = current.getParent()) { 28.548 - if (tryNode.getBody() == current) { 28.549 + for(Iterator<Block> blocks = lexicalContext.getBlocks(getCurrentBlock()); blocks.hasNext();) { 28.550 + final Block block = blocks.next(); 28.551 + if(block == target) { 28.552 + return false; 28.553 + } 28.554 + if(tryNode.isChildBlock(block)) { 28.555 return true; 28.556 } 28.557 - 28.558 - for (final Block catchBlock : tryNode.getCatchBlocks()) { 28.559 - if (catchBlock == current) { 28.560 - return true; 28.561 - } 28.562 - } 28.563 } 28.564 - 28.565 return false; 28.566 } 28.567 28.568 @@ -895,7 +901,7 @@ 28.569 continue; 28.570 } 28.571 28.572 - finallyBody = (Block)finallyBody.clone(); 28.573 + finallyBody = (Block)finallyBody.copy(); 28.574 final boolean hasTerminalFlags = finallyBody.hasTerminalFlags(); 28.575 28.576 new ExecuteNode(finallyBody.getSource(), finallyBody.getToken(), finallyBody.getFinish(), finallyBody).accept(this); 28.577 @@ -970,6 +976,3 @@ 28.578 } 28.579 28.580 } 28.581 - 28.582 - 28.583 -
29.1 --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java Thu Mar 28 10:55:17 2013 -0700 29.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java Mon Apr 01 21:42:31 2013 -0700 29.3 @@ -651,11 +651,10 @@ 29.4 29.5 /** 29.6 * Load the constants array 29.7 - * @param unitClassName name of the compile unit from which to load constants 29.8 * @return this method emitter 29.9 */ 29.10 - MethodEmitter loadConstants(final String unitClassName) { 29.11 - getStatic(unitClassName, CONSTANTS.tag(), CONSTANTS.descriptor()); 29.12 + MethodEmitter loadConstants() { 29.13 + getStatic(classEmitter.getUnitClassName(), CONSTANTS.tag(), CONSTANTS.descriptor()); 29.14 assert peekType().isArray() : peekType(); 29.15 return this; 29.16 }
30.1 --- a/src/jdk/nashorn/internal/codegen/Splitter.java Thu Mar 28 10:55:17 2013 -0700 30.2 +++ b/src/jdk/nashorn/internal/codegen/Splitter.java Mon Apr 01 21:42:31 2013 -0700 30.3 @@ -39,7 +39,9 @@ 30.4 import jdk.nashorn.internal.ir.DoWhileNode; 30.5 import jdk.nashorn.internal.ir.ForNode; 30.6 import jdk.nashorn.internal.ir.FunctionNode; 30.7 +import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 30.8 import jdk.nashorn.internal.ir.LabelNode; 30.9 +import jdk.nashorn.internal.ir.LexicalContext; 30.10 import jdk.nashorn.internal.ir.LiteralNode; 30.11 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 30.12 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit; 30.13 @@ -48,6 +50,7 @@ 30.14 import jdk.nashorn.internal.ir.SplitNode; 30.15 import jdk.nashorn.internal.ir.SwitchNode; 30.16 import jdk.nashorn.internal.ir.WhileNode; 30.17 +import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor; 30.18 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 30.19 import jdk.nashorn.internal.runtime.DebugLogger; 30.20 import jdk.nashorn.internal.runtime.Source; 30.21 @@ -69,6 +72,8 @@ 30.22 /** Cache for calculated block weights. */ 30.23 private final Map<Node, Long> weightCache = new HashMap<>(); 30.24 30.25 + private final LexicalContext lexicalContext = new LexicalContext(); 30.26 + 30.27 /** Weight threshold for when to start a split. */ 30.28 public static final long SPLIT_THRESHOLD = Options.getIntProperty("nashorn.compiler.splitter.threshold", 32 * 1024); 30.29 30.30 @@ -92,15 +97,16 @@ 30.31 */ 30.32 void split() { 30.33 if (functionNode.isLazy()) { 30.34 - LOG.fine("Postponing split of '" + functionNode.getName() + "' as it's lazy"); 30.35 + LOG.finest("Postponing split of '" + functionNode.getName() + "' as it's lazy"); 30.36 return; 30.37 } 30.38 - LOG.fine("Initiating split of '" + functionNode.getName() + "'"); 30.39 + 30.40 + LOG.finest("Initiating split of '" + functionNode.getName() + "'"); 30.41 30.42 long weight = WeighNodes.weigh(functionNode); 30.43 30.44 if (weight >= SPLIT_THRESHOLD) { 30.45 - LOG.fine("Splitting '" + functionNode.getName() + "' as its weight " + weight + " exceeds split threshold " + SPLIT_THRESHOLD); 30.46 + LOG.finest("Splitting '" + functionNode.getName() + "' as its weight " + weight + " exceeds split threshold " + SPLIT_THRESHOLD); 30.47 30.48 functionNode.accept(this); 30.49 30.50 @@ -110,7 +116,7 @@ 30.51 } 30.52 30.53 if (weight >= SPLIT_THRESHOLD) { 30.54 - weight = splitBlock(functionNode); 30.55 + weight = splitBlock(functionNode, functionNode); 30.56 } 30.57 30.58 if (functionNode.isSplit()) { 30.59 @@ -130,9 +136,22 @@ 30.60 } 30.61 30.62 // Recursively split nested functions 30.63 - for (final FunctionNode function : functionNode.getFunctions()) { 30.64 - new Splitter(compiler, function, outermostCompileUnit).split(); 30.65 - } 30.66 + functionNode.accept(new NodeOperatorVisitor() { 30.67 + @Override 30.68 + public Node enterFunctionNode(FunctionNode function) { 30.69 + if(function == functionNode) { 30.70 + // Don't process outermost function (it was already processed) but descend into it to find nested 30.71 + // functions. 30.72 + return function; 30.73 + } 30.74 + // Process a nested function 30.75 + new Splitter(compiler, function, outermostCompileUnit).split(); 30.76 + // Don't descend into a a nested function; Splitter.split() has taken care of nested-in-nested functions. 30.77 + return null; 30.78 + } 30.79 + }); 30.80 + 30.81 + functionNode.setState(CompilationState.SPLIT); 30.82 } 30.83 30.84 /** 30.85 @@ -151,7 +170,7 @@ 30.86 * 30.87 * @return new weight for the resulting block. 30.88 */ 30.89 - private long splitBlock(final Block block) { 30.90 + private long splitBlock(final Block block, final FunctionNode function) { 30.91 functionNode.setIsSplit(); 30.92 30.93 final List<Node> splits = new ArrayList<>(); 30.94 @@ -163,7 +182,7 @@ 30.95 30.96 if (statementsWeight + weight >= SPLIT_THRESHOLD || statement.isTerminal()) { 30.97 if (!statements.isEmpty()) { 30.98 - splits.add(createBlockSplitNode(block, statements, statementsWeight)); 30.99 + splits.add(createBlockSplitNode(block, function, statements, statementsWeight)); 30.100 statements = new ArrayList<>(); 30.101 statementsWeight = 0; 30.102 } 30.103 @@ -179,7 +198,7 @@ 30.104 } 30.105 30.106 if (!statements.isEmpty()) { 30.107 - splits.add(createBlockSplitNode(block, statements, statementsWeight)); 30.108 + splits.add(createBlockSplitNode(block, function, statements, statementsWeight)); 30.109 } 30.110 30.111 block.setStatements(splits); 30.112 @@ -195,13 +214,13 @@ 30.113 * 30.114 * @return New split node. 30.115 */ 30.116 - private SplitNode createBlockSplitNode(final Block parent, final List<Node> statements, final long weight) { 30.117 + private SplitNode createBlockSplitNode(final Block parent, final FunctionNode function, final List<Node> statements, final long weight) { 30.118 final Source source = parent.getSource(); 30.119 final long token = parent.getToken(); 30.120 final int finish = parent.getFinish(); 30.121 - final String name = parent.getFunction().uniqueName(SPLIT_PREFIX.tag()); 30.122 + final String name = function.uniqueName(SPLIT_PREFIX.tag()); 30.123 30.124 - final Block newBlock = new Block(source, token, finish, parent, functionNode); 30.125 + final Block newBlock = new Block(source, token, finish); 30.126 newBlock.setFrame(new Frame(parent.getFrame())); 30.127 newBlock.setStatements(statements); 30.128 30.129 @@ -213,15 +232,17 @@ 30.130 } 30.131 30.132 @Override 30.133 - public Node enter(final Block block) { 30.134 + public Node enterBlock(final Block block) { 30.135 if (block.isCatchBlock()) { 30.136 return null; 30.137 } 30.138 + lexicalContext.push(block); 30.139 30.140 final long weight = WeighNodes.weigh(block, weightCache); 30.141 30.142 if (weight < SPLIT_THRESHOLD) { 30.143 weightCache.put(block, weight); 30.144 + lexicalContext.pop(block); 30.145 return null; 30.146 } 30.147 30.148 @@ -229,23 +250,24 @@ 30.149 } 30.150 30.151 @Override 30.152 - public Node leave(final Block block) { 30.153 + public Node leaveBlock(final Block block) { 30.154 assert !block.isCatchBlock(); 30.155 30.156 // Block was heavier than SLIT_THRESHOLD in enter, but a sub-block may have 30.157 // been split already, so weigh again before splitting. 30.158 long weight = WeighNodes.weigh(block, weightCache); 30.159 if (weight >= SPLIT_THRESHOLD) { 30.160 - weight = splitBlock(block); 30.161 + weight = splitBlock(block, lexicalContext.getFunction(block)); 30.162 } 30.163 weightCache.put(block, weight); 30.164 30.165 + lexicalContext.pop(block); 30.166 return block; 30.167 } 30.168 30.169 @SuppressWarnings("rawtypes") 30.170 @Override 30.171 - public Node leave(final LiteralNode literal) { 30.172 + public Node leaveLiteralNode(final LiteralNode literal) { 30.173 long weight = WeighNodes.weigh(literal); 30.174 30.175 if (weight < SPLIT_THRESHOLD) { 30.176 @@ -290,17 +312,12 @@ 30.177 } 30.178 30.179 @Override 30.180 - public Node enter(final FunctionNode node) { 30.181 - if (node.isLazy()) { 30.182 - return null; 30.183 + public Node enterFunctionNode(final FunctionNode node) { 30.184 + if(node == functionNode && !node.isLazy()) { 30.185 + lexicalContext.push(node); 30.186 + node.visitStatements(this); 30.187 + lexicalContext.pop(node); 30.188 } 30.189 - 30.190 - final List<Node> statements = node.getStatements(); 30.191 - 30.192 - for (final Node statement : statements) { 30.193 - statement.accept(this); 30.194 - } 30.195 - 30.196 return null; 30.197 } 30.198 30.199 @@ -317,38 +334,38 @@ 30.200 } 30.201 30.202 @Override 30.203 - public Node enter(final LabelNode labelNode) { 30.204 + public Node enterLabelNode(final LabelNode labelNode) { 30.205 registerJumpTarget(labelNode.getBreakNode()); 30.206 registerJumpTarget(labelNode.getContinueNode()); 30.207 return labelNode; 30.208 } 30.209 30.210 @Override 30.211 - public Node enter(final WhileNode whileNode) { 30.212 + public Node enterWhileNode(final WhileNode whileNode) { 30.213 registerJumpTarget(whileNode); 30.214 return whileNode; 30.215 } 30.216 30.217 @Override 30.218 - public Node enter(final DoWhileNode doWhileNode) { 30.219 + public Node enterDoWhileNode(final DoWhileNode doWhileNode) { 30.220 registerJumpTarget(doWhileNode); 30.221 return doWhileNode; 30.222 } 30.223 30.224 @Override 30.225 - public Node enter(final ForNode forNode) { 30.226 + public Node enterForNode(final ForNode forNode) { 30.227 registerJumpTarget(forNode); 30.228 return forNode; 30.229 } 30.230 30.231 @Override 30.232 - public Node enter(final SwitchNode switchNode) { 30.233 + public Node enterSwitchNode(final SwitchNode switchNode) { 30.234 registerJumpTarget(switchNode); 30.235 return switchNode; 30.236 } 30.237 30.238 @Override 30.239 - public Node enter(final ReturnNode returnNode) { 30.240 + public Node enterReturnNode(final ReturnNode returnNode) { 30.241 for (final SplitNode split : splitStack) { 30.242 split.setHasReturn(true); 30.243 } 30.244 @@ -356,25 +373,25 @@ 30.245 } 30.246 30.247 @Override 30.248 - public Node enter(final ContinueNode continueNode) { 30.249 + public Node enterContinueNode(final ContinueNode continueNode) { 30.250 searchJumpTarget(continueNode.getTargetNode(), continueNode.getTargetLabel()); 30.251 return continueNode; 30.252 } 30.253 30.254 @Override 30.255 - public Node enter(final BreakNode breakNode) { 30.256 + public Node enterBreakNode(final BreakNode breakNode) { 30.257 searchJumpTarget(breakNode.getTargetNode(), breakNode.getTargetLabel()); 30.258 return breakNode; 30.259 } 30.260 30.261 @Override 30.262 - public Node enter(final SplitNode splitNode) { 30.263 + public Node enterSplitNode(final SplitNode splitNode) { 30.264 splitStack.addFirst(splitNode); 30.265 return splitNode; 30.266 } 30.267 30.268 @Override 30.269 - public Node leave(final SplitNode splitNode) { 30.270 + public Node leaveSplitNode(final SplitNode splitNode) { 30.271 assert splitNode == splitStack.peekFirst(); 30.272 splitStack.removeFirst(); 30.273 return splitNode;
31.1 --- a/src/jdk/nashorn/internal/codegen/WeighNodes.java Thu Mar 28 10:55:17 2013 -0700 31.2 +++ b/src/jdk/nashorn/internal/codegen/WeighNodes.java Mon Apr 01 21:42:31 2013 -0700 31.3 @@ -47,7 +47,6 @@ 31.4 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit; 31.5 import jdk.nashorn.internal.ir.Node; 31.6 import jdk.nashorn.internal.ir.PropertyNode; 31.7 -import jdk.nashorn.internal.ir.ReferenceNode; 31.8 import jdk.nashorn.internal.ir.ReturnNode; 31.9 import jdk.nashorn.internal.ir.RuntimeNode; 31.10 import jdk.nashorn.internal.ir.SplitNode; 31.11 @@ -80,7 +79,7 @@ 31.12 private static final long LITERAL_WEIGHT = 10; 31.13 private static final long LOOP_WEIGHT = 4; 31.14 private static final long NEW_WEIGHT = 6; 31.15 - private static final long REFERENCE_WEIGHT = 20; 31.16 + private static final long FUNC_EXPR_WEIGHT = 20; 31.17 private static final long RETURN_WEIGHT = 2; 31.18 private static final long SPLIT_WEIGHT = 40; 31.19 private static final long SWITCH_WEIGHT = 8; 31.20 @@ -94,36 +93,37 @@ 31.21 /** Optional cache for weight of block nodes. */ 31.22 private final Map<Node, Long> weightCache; 31.23 31.24 - /* 31.25 + private final FunctionNode topFunction; 31.26 + 31.27 + /** 31.28 * Constructor 31.29 * 31.30 * @param weightCache cache of already calculated block weights 31.31 */ 31.32 - private WeighNodes(final Map<Node, Long> weightCache) { 31.33 + private WeighNodes(FunctionNode topFunction, final Map<Node, Long> weightCache) { 31.34 super(null, null); 31.35 + this.topFunction = topFunction; 31.36 this.weightCache = weightCache; 31.37 } 31.38 31.39 static long weigh(final Node node) { 31.40 - final WeighNodes weighNodes = new WeighNodes(null); 31.41 - node.accept(weighNodes); 31.42 - return weighNodes.weight; 31.43 + return weigh(node, null); 31.44 } 31.45 31.46 static long weigh(final Node node, final Map<Node, Long> weightCache) { 31.47 - final WeighNodes weighNodes = new WeighNodes(weightCache); 31.48 + final WeighNodes weighNodes = new WeighNodes(node instanceof FunctionNode ? (FunctionNode)node : null, weightCache); 31.49 node.accept(weighNodes); 31.50 return weighNodes.weight; 31.51 } 31.52 31.53 @Override 31.54 - public Node leave(final AccessNode accessNode) { 31.55 + public Node leaveAccessNode(final AccessNode accessNode) { 31.56 weight += ACCESS_WEIGHT; 31.57 return accessNode; 31.58 } 31.59 31.60 @Override 31.61 - public Node enter(final Block block) { 31.62 + public Node enterBlock(final Block block) { 31.63 if (weightCache != null && weightCache.containsKey(block)) { 31.64 weight += weightCache.get(block); 31.65 return null; 31.66 @@ -133,78 +133,79 @@ 31.67 } 31.68 31.69 @Override 31.70 - public Node leave(final BreakNode breakNode) { 31.71 + public Node leaveBreakNode(final BreakNode breakNode) { 31.72 weight += BREAK_WEIGHT; 31.73 return breakNode; 31.74 } 31.75 31.76 @Override 31.77 - public Node leave(final CallNode callNode) { 31.78 + public Node leaveCallNode(final CallNode callNode) { 31.79 weight += CALL_WEIGHT; 31.80 return callNode; 31.81 } 31.82 31.83 @Override 31.84 - public Node leave(final CatchNode catchNode) { 31.85 + public Node leaveCatchNode(final CatchNode catchNode) { 31.86 weight += CATCH_WEIGHT; 31.87 return catchNode; 31.88 } 31.89 31.90 @Override 31.91 - public Node leave(final ContinueNode continueNode) { 31.92 + public Node leaveContinueNode(final ContinueNode continueNode) { 31.93 weight += CONTINUE_WEIGHT; 31.94 return continueNode; 31.95 } 31.96 31.97 @Override 31.98 - public Node leave(final DoWhileNode doWhileNode) { 31.99 + public Node leaveDoWhileNode(final DoWhileNode doWhileNode) { 31.100 weight += LOOP_WEIGHT; 31.101 return doWhileNode; 31.102 } 31.103 31.104 @Override 31.105 - public Node leave(final ExecuteNode executeNode) { 31.106 + public Node leaveExecuteNode(final ExecuteNode executeNode) { 31.107 return executeNode; 31.108 } 31.109 31.110 @Override 31.111 - public Node leave(final ForNode forNode) { 31.112 + public Node leaveForNode(final ForNode forNode) { 31.113 weight += LOOP_WEIGHT; 31.114 return forNode; 31.115 } 31.116 31.117 @Override 31.118 - public Node enter(final FunctionNode functionNode) { 31.119 - final List<Node> statements = functionNode.getStatements(); 31.120 - 31.121 - for (final Node statement : statements) { 31.122 - statement.accept(this); 31.123 + public Node enterFunctionNode(final FunctionNode functionNode) { 31.124 + if(functionNode == topFunction) { 31.125 + // the function being weighted; descend into its statements 31.126 + functionNode.visitStatements(this); 31.127 + } else { 31.128 + // just a reference to inner function from outer function 31.129 + weight += FUNC_EXPR_WEIGHT; 31.130 } 31.131 - 31.132 return null; 31.133 } 31.134 31.135 @Override 31.136 - public Node leave(final IdentNode identNode) { 31.137 + public Node leaveIdentNode(final IdentNode identNode) { 31.138 weight += ACCESS_WEIGHT + identNode.getName().length() * 2; 31.139 return identNode; 31.140 } 31.141 31.142 @Override 31.143 - public Node leave(final IfNode ifNode) { 31.144 + public Node leaveIfNode(final IfNode ifNode) { 31.145 weight += IF_WEIGHT; 31.146 return ifNode; 31.147 } 31.148 31.149 @Override 31.150 - public Node leave(final IndexNode indexNode) { 31.151 + public Node leaveIndexNode(final IndexNode indexNode) { 31.152 weight += ACCESS_WEIGHT; 31.153 return indexNode; 31.154 } 31.155 31.156 @SuppressWarnings("rawtypes") 31.157 @Override 31.158 - public Node enter(final LiteralNode literalNode) { 31.159 + public Node enterLiteralNode(final LiteralNode literalNode) { 31.160 weight += LITERAL_WEIGHT; 31.161 31.162 if (literalNode instanceof ArrayLiteralNode) { 31.163 @@ -230,67 +231,61 @@ 31.164 } 31.165 31.166 @Override 31.167 - public Node leave(final PropertyNode propertyNode) { 31.168 + public Node leavePropertyNode(final PropertyNode propertyNode) { 31.169 weight += LITERAL_WEIGHT; 31.170 return propertyNode; 31.171 } 31.172 31.173 @Override 31.174 - public Node leave(final ReferenceNode referenceNode) { 31.175 - weight += REFERENCE_WEIGHT; 31.176 - return referenceNode; 31.177 - } 31.178 - 31.179 - @Override 31.180 - public Node leave(final ReturnNode returnNode) { 31.181 + public Node leaveReturnNode(final ReturnNode returnNode) { 31.182 weight += RETURN_WEIGHT; 31.183 return returnNode; 31.184 } 31.185 31.186 @Override 31.187 - public Node leave(final RuntimeNode runtimeNode) { 31.188 + public Node leaveRuntimeNode(final RuntimeNode runtimeNode) { 31.189 weight += CALL_WEIGHT; 31.190 return runtimeNode; 31.191 } 31.192 31.193 @Override 31.194 - public Node enter(final SplitNode splitNode) { 31.195 + public Node enterSplitNode(final SplitNode splitNode) { 31.196 weight += SPLIT_WEIGHT; 31.197 return null; 31.198 } 31.199 31.200 @Override 31.201 - public Node leave(final SwitchNode switchNode) { 31.202 + public Node leaveSwitchNode(final SwitchNode switchNode) { 31.203 weight += SWITCH_WEIGHT; 31.204 return switchNode; 31.205 } 31.206 31.207 @Override 31.208 - public Node leave(final ThrowNode throwNode) { 31.209 + public Node leaveThrowNode(final ThrowNode throwNode) { 31.210 weight += THROW_WEIGHT; 31.211 return throwNode; 31.212 } 31.213 31.214 @Override 31.215 - public Node leave(final TryNode tryNode) { 31.216 + public Node leaveTryNode(final TryNode tryNode) { 31.217 weight += THROW_WEIGHT; 31.218 return tryNode; 31.219 } 31.220 31.221 @Override 31.222 - public Node leave(final VarNode varNode) { 31.223 + public Node leaveVarNode(final VarNode varNode) { 31.224 weight += VAR_WEIGHT; 31.225 return varNode; 31.226 } 31.227 31.228 @Override 31.229 - public Node leave(final WhileNode whileNode) { 31.230 + public Node leaveWhileNode(final WhileNode whileNode) { 31.231 weight += LOOP_WEIGHT; 31.232 return whileNode; 31.233 } 31.234 31.235 @Override 31.236 - public Node leave(final WithNode withNode) { 31.237 + public Node leaveWithNode(final WithNode withNode) { 31.238 weight += WITH_WEIGHT; 31.239 return withNode; 31.240 }
32.1 --- a/src/jdk/nashorn/internal/codegen/types/Type.java Thu Mar 28 10:55:17 2013 -0700 32.2 +++ b/src/jdk/nashorn/internal/codegen/types/Type.java Mon Apr 01 21:42:31 2013 -0700 32.3 @@ -647,21 +647,20 @@ 32.4 } 32.5 32.6 private static void swap(final MethodVisitor method, final Type above, final Type below) { 32.7 - final MethodVisitor mv = method; 32.8 if (below.isCategory2()) { 32.9 if (above.isCategory2()) { 32.10 - mv.visitInsn(DUP2_X2); 32.11 - mv.visitInsn(POP2); 32.12 + method.visitInsn(DUP2_X2); 32.13 + method.visitInsn(POP2); 32.14 } else { 32.15 - mv.visitInsn(DUP_X2); 32.16 - mv.visitInsn(POP); 32.17 + method.visitInsn(DUP_X2); 32.18 + method.visitInsn(POP); 32.19 } 32.20 } else { 32.21 if (above.isCategory2()) { 32.22 - mv.visitInsn(DUP2_X1); 32.23 - mv.visitInsn(POP2); 32.24 + method.visitInsn(DUP2_X1); 32.25 + method.visitInsn(POP2); 32.26 } else { 32.27 - mv.visitInsn(SWAP); 32.28 + method.visitInsn(SWAP); 32.29 } 32.30 } 32.31
33.1 --- a/src/jdk/nashorn/internal/ir/AccessNode.java Thu Mar 28 10:55:17 2013 -0700 33.2 +++ b/src/jdk/nashorn/internal/ir/AccessNode.java Mon Apr 01 21:42:31 2013 -0700 33.3 @@ -36,7 +36,7 @@ 33.4 * IR representation of a property access (period operator.) 33.5 * 33.6 */ 33.7 -public class AccessNode extends BaseNode implements TypeOverride { 33.8 +public class AccessNode extends BaseNode implements TypeOverride<AccessNode> { 33.9 /** Property ident. */ 33.10 private IdentNode property; 33.11 33.12 @@ -56,9 +56,7 @@ 33.13 super(source, token, finish, base); 33.14 33.15 this.start = base.getStart(); 33.16 - this.property = property; 33.17 - 33.18 - this.property.setIsPropertyName(); 33.19 + this.property = property.setIsPropertyName(); 33.20 } 33.21 33.22 /** 33.23 @@ -106,10 +104,10 @@ 33.24 */ 33.25 @Override 33.26 public Node accept(final NodeVisitor visitor) { 33.27 - if (visitor.enter(this) != null) { 33.28 + if (visitor.enterAccessNode(this) != null) { 33.29 base = base.accept(visitor); 33.30 property = (IdentNode)property.accept(visitor); 33.31 - return visitor.leave(this); 33.32 + return visitor.leaveAccessNode(this); 33.33 } 33.34 33.35 return this; 33.36 @@ -150,13 +148,14 @@ 33.37 } 33.38 33.39 @Override 33.40 - public void setType(final Type type) { 33.41 + public AccessNode setType(final Type type) { 33.42 if (DEBUG_FIELDS && !Type.areEquivalent(getSymbol().getSymbolType(), type)) { 33.43 ObjectClassGenerator.LOG.info(getClass().getName() + " " + this + " => " + type + " instead of " + getType()); 33.44 } 33.45 - property.setType(type); 33.46 + property = property.setType(type); 33.47 getSymbol().setTypeOverride(type); //always a temp so this is fine. 33.48 hasCallSiteType = true; 33.49 + return this; 33.50 } 33.51 33.52 @Override
34.1 --- a/src/jdk/nashorn/internal/ir/Assignment.java Thu Mar 28 10:55:17 2013 -0700 34.2 +++ b/src/jdk/nashorn/internal/ir/Assignment.java Mon Apr 01 21:42:31 2013 -0700 34.3 @@ -46,4 +46,11 @@ 34.4 * @return get the assignment source node 34.5 */ 34.6 public Node getAssignmentSource(); 34.7 + 34.8 + /** 34.9 + * Set assignment destination node. 34.10 + * @param n the assignment destination node. 34.11 + * @return a node equivalent to this one except for the requested change. 34.12 + */ 34.13 + public Node setAssignmentDest(D n); 34.14 }
35.1 --- a/src/jdk/nashorn/internal/ir/BaseNode.java Thu Mar 28 10:55:17 2013 -0700 35.2 +++ b/src/jdk/nashorn/internal/ir/BaseNode.java Mon Apr 01 21:42:31 2013 -0700 35.3 @@ -38,6 +38,8 @@ 35.4 /** Base Node. */ 35.5 protected Node base; 35.6 35.7 + private boolean function; 35.8 + 35.9 /** 35.10 * Constructor 35.11 * 35.12 @@ -96,6 +98,15 @@ 35.13 35.14 @Override 35.15 public boolean isFunction() { 35.16 - return false; 35.17 + return function; 35.18 + } 35.19 + 35.20 + /** 35.21 + * Mark this node as being the callee operand of a {@link CallNode}. 35.22 + * @return a base node identical to this one in all aspects except with its function flag set. 35.23 + */ 35.24 + public BaseNode setIsFunction() { 35.25 + function = true; 35.26 + return this; 35.27 } 35.28 }
36.1 --- a/src/jdk/nashorn/internal/ir/BinaryNode.java Thu Mar 28 10:55:17 2013 -0700 36.2 +++ b/src/jdk/nashorn/internal/ir/BinaryNode.java Mon Apr 01 21:42:31 2013 -0700 36.3 @@ -35,7 +35,7 @@ 36.4 */ 36.5 public class BinaryNode extends UnaryNode { 36.6 /** Left hand side argument. */ 36.7 - protected Node lhs; 36.8 + private Node lhs; 36.9 36.10 /** 36.11 * Constructor 36.12 @@ -140,6 +140,11 @@ 36.13 } 36.14 36.15 @Override 36.16 + public Node setAssignmentDest(Node n) { 36.17 + return setLHS(n); 36.18 + } 36.19 + 36.20 + @Override 36.21 public Node getAssignmentSource() { 36.22 return rhs(); 36.23 } 36.24 @@ -163,10 +168,9 @@ 36.25 */ 36.26 @Override 36.27 public Node accept(final NodeVisitor visitor) { 36.28 - if (visitor.enter(this) != null) { 36.29 - lhs = lhs.accept(visitor); 36.30 - rhs = rhs.accept(visitor); 36.31 - return visitor.leave(this); 36.32 + if (visitor.enterBinaryNode(this) != null) { 36.33 + // TODO: good cause for a separate visitMembers: we could delegate to UnaryNode.visitMembers 36.34 + return visitor.leaveBinaryNode((BinaryNode)setLHS(lhs.accept(visitor)).setRHS(rhs().accept(visitor))); 36.35 } 36.36 36.37 return this; 36.38 @@ -229,8 +233,12 @@ 36.39 /** 36.40 * Set the left hand side expression for this node 36.41 * @param lhs new left hand side expression 36.42 + * @return a node equivalent to this one except for the requested change. 36.43 */ 36.44 - public void setLHS(final Node lhs) { 36.45 - this.lhs = lhs; 36.46 + public BinaryNode setLHS(final Node lhs) { 36.47 + if(this.lhs == lhs) return this; 36.48 + final BinaryNode n = (BinaryNode)clone(); 36.49 + n.lhs = lhs; 36.50 + return n; 36.51 } 36.52 }
37.1 --- a/src/jdk/nashorn/internal/ir/Block.java Thu Mar 28 10:55:17 2013 -0700 37.2 +++ b/src/jdk/nashorn/internal/ir/Block.java Mon Apr 01 21:42:31 2013 -0700 37.3 @@ -25,41 +25,24 @@ 37.4 37.5 package jdk.nashorn.internal.ir; 37.6 37.7 -import static jdk.nashorn.internal.ir.Symbol.IS_GLOBAL; 37.8 -import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL; 37.9 -import static jdk.nashorn.internal.ir.Symbol.IS_LET; 37.10 -import static jdk.nashorn.internal.ir.Symbol.IS_PARAM; 37.11 -import static jdk.nashorn.internal.ir.Symbol.IS_SCOPE; 37.12 -import static jdk.nashorn.internal.ir.Symbol.IS_VAR; 37.13 -import static jdk.nashorn.internal.ir.Symbol.KINDMASK; 37.14 - 37.15 import java.io.PrintWriter; 37.16 import java.util.ArrayList; 37.17 import java.util.Collections; 37.18 import java.util.Comparator; 37.19 import java.util.HashMap; 37.20 +import java.util.Iterator; 37.21 import java.util.List; 37.22 +import java.util.ListIterator; 37.23 import jdk.nashorn.internal.codegen.Frame; 37.24 import jdk.nashorn.internal.codegen.Label; 37.25 -import jdk.nashorn.internal.ir.annotations.Ignore; 37.26 -import jdk.nashorn.internal.ir.annotations.ParentNode; 37.27 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 37.28 import jdk.nashorn.internal.runtime.Source; 37.29 37.30 /** 37.31 * IR representation for a list of statements and functions. All provides the 37.32 * basis for script body. 37.33 - * 37.34 */ 37.35 public class Block extends Node { 37.36 - /** Parent context */ 37.37 - @ParentNode @Ignore 37.38 - private Block parent; 37.39 - 37.40 - /** Owning function. */ 37.41 - @Ignore //don't print it, it is apparent in the tree 37.42 - protected FunctionNode function; 37.43 - 37.44 /** List of statements */ 37.45 protected List<Node> statements; 37.46 37.47 @@ -84,14 +67,10 @@ 37.48 * @param source source code 37.49 * @param token token 37.50 * @param finish finish 37.51 - * @param parent reference to parent block 37.52 - * @param function function node this block is in 37.53 */ 37.54 - public Block(final Source source, final long token, final int finish, final Block parent, final FunctionNode function) { 37.55 + public Block(final Source source, final long token, final int finish) { 37.56 super(source, token, finish); 37.57 37.58 - this.parent = parent; 37.59 - this.function = function; 37.60 this.statements = new ArrayList<>(); 37.61 this.symbols = new HashMap<>(); 37.62 this.entryLabel = new Label("block_entry"); 37.63 @@ -107,8 +86,6 @@ 37.64 protected Block(final Block block, final CopyState cs) { 37.65 super(block); 37.66 37.67 - this.parent = block.parent; 37.68 - this.function = block.function; 37.69 this.statements = new ArrayList<>(); 37.70 for (final Node statement : block.getStatements()) { 37.71 statements.add(cs.existingOrCopy(statement)); 37.72 @@ -123,55 +100,7 @@ 37.73 37.74 @Override 37.75 protected Node copy(final CopyState cs) { 37.76 - return fixBlockChain(new Block(this, cs)); 37.77 - } 37.78 - 37.79 - /** 37.80 - * Whenever a clone that contains a hierarchy of blocks is created, 37.81 - * this function has to be called to ensure that the parents point 37.82 - * to the correct parent blocks or two different ASTs would not 37.83 - * be completely separated. 37.84 - * 37.85 - * @return the argument 37.86 - */ 37.87 - static Block fixBlockChain(final Block root) { 37.88 - root.accept(new NodeVisitor() { 37.89 - private Block parent = root.getParent(); 37.90 - private final FunctionNode function = root.getFunction(); 37.91 - 37.92 - @Override 37.93 - public Node enter(final Block block) { 37.94 - assert block.getFunction() == function; 37.95 - block.setParent(parent); 37.96 - parent = block; 37.97 - 37.98 - return block; 37.99 - } 37.100 - 37.101 - @Override 37.102 - public Node leave(final Block block) { 37.103 - parent = block.getParent(); 37.104 - 37.105 - return block; 37.106 - } 37.107 - 37.108 - @Override 37.109 - public Node enter(final FunctionNode functionNode) { 37.110 - assert functionNode.getFunction() == function; 37.111 - 37.112 - return enter((Block)functionNode); 37.113 - } 37.114 - 37.115 - @Override 37.116 - public Node leave(final FunctionNode functionNode) { 37.117 - assert functionNode.getFunction() == function; 37.118 - 37.119 - return leave((Block)functionNode); 37.120 - } 37.121 - 37.122 - }); 37.123 - 37.124 - return root; 37.125 + return new Block(this, cs); 37.126 } 37.127 37.128 /** 37.129 @@ -189,17 +118,12 @@ 37.130 } 37.131 37.132 /** 37.133 - * Prepend a statement to the statement list 37.134 + * Prepend statements to the statement list 37.135 * 37.136 - * @param statement Statement node to add 37.137 + * @param prepended statement to add 37.138 */ 37.139 - public void prependStatement(final Node statement) { 37.140 - if (statement != null) { 37.141 - final List<Node> newStatements = new ArrayList<>(); 37.142 - newStatements.add(statement); 37.143 - newStatements.addAll(statements); 37.144 - setStatements(newStatements); 37.145 - } 37.146 + public void prependStatements(final List<Node> prepended) { 37.147 + statements.addAll(0, prepended); 37.148 } 37.149 37.150 /** 37.151 @@ -212,39 +136,6 @@ 37.152 } 37.153 37.154 /** 37.155 - * Add a new function to the function list. 37.156 - * 37.157 - * @param functionNode Function node to add. 37.158 - */ 37.159 - public void addFunction(final FunctionNode functionNode) { 37.160 - assert parent != null : "Parent context missing."; 37.161 - 37.162 - parent.addFunction(functionNode); 37.163 - } 37.164 - 37.165 - /** 37.166 - * Add a list of functions to the function list. 37.167 - * 37.168 - * @param functionNodes Function nodes to add. 37.169 - */ 37.170 - public void addFunctions(final List<FunctionNode> functionNodes) { 37.171 - assert parent != null : "Parent context missing."; 37.172 - 37.173 - parent.addFunctions(functionNodes); 37.174 - } 37.175 - 37.176 - /** 37.177 - * Set the function list to a new one 37.178 - * 37.179 - * @param functionNodes the nodes to set 37.180 - */ 37.181 - public void setFunctions(final List<FunctionNode> functionNodes) { 37.182 - assert parent != null : "Parent context missing."; 37.183 - 37.184 - parent.setFunctions(functionNodes); 37.185 - } 37.186 - 37.187 - /** 37.188 * Assist in IR navigation. 37.189 * 37.190 * @param visitor IR navigating visitor. 37.191 @@ -258,13 +149,9 @@ 37.192 try { 37.193 // Ignore parent to avoid recursion. 37.194 37.195 - if (visitor.enter(this) != null) { 37.196 - for (int i = 0, count = statements.size(); i < count; i++) { 37.197 - final Node statement = statements.get(i); 37.198 - statements.set(i, statement.accept(visitor)); 37.199 - } 37.200 - 37.201 - return visitor.leave(this); 37.202 + if (visitor.enterBlock(this) != null) { 37.203 + visitStatements(visitor); 37.204 + return visitor.leaveBlock(this); 37.205 } 37.206 } finally { 37.207 visitor.setCurrentBlock(saveBlock); 37.208 @@ -274,51 +161,21 @@ 37.209 } 37.210 37.211 /** 37.212 - * Search for symbol. 37.213 - * 37.214 - * @param name Symbol name. 37.215 - * 37.216 - * @return Found symbol or null if not found. 37.217 + * Get an iterator for all the symbols defined in this block 37.218 + * @return symbol iterator 37.219 */ 37.220 - public Symbol findSymbol(final String name) { 37.221 - // Search up block chain to locate symbol. 37.222 - 37.223 - for (Block block = this; block != null; block = block.getParent()) { 37.224 - // Find name. 37.225 - final Symbol symbol = block.symbols.get(name); 37.226 - // If found then we are good. 37.227 - if (symbol != null) { 37.228 - return symbol; 37.229 - } 37.230 - } 37.231 - return null; 37.232 + public Iterator<Symbol> symbolIterator() { 37.233 + return symbols.values().iterator(); 37.234 } 37.235 37.236 /** 37.237 - * Search for symbol in current function. 37.238 - * 37.239 - * @param name Symbol name. 37.240 - * 37.241 - * @return Found symbol or null if not found. 37.242 + * Retrieves an existing symbol defined in the current block. 37.243 + * @param name the name of the symbol 37.244 + * @return an existing symbol with the specified name defined in the current block, or null if this block doesn't 37.245 + * define a symbol with this name. 37.246 */ 37.247 - public Symbol findLocalSymbol(final String name) { 37.248 - // Search up block chain to locate symbol. 37.249 - for (Block block = this; block != null; block = block.getParent()) { 37.250 - // Find name. 37.251 - final Symbol symbol = block.symbols.get(name); 37.252 - // If found then we are good. 37.253 - if (symbol != null) { 37.254 - return symbol; 37.255 - } 37.256 - 37.257 - // If searched function then we are done. 37.258 - if (block == block.function) { 37.259 - break; 37.260 - } 37.261 - } 37.262 - 37.263 - // Not found. 37.264 - return null; 37.265 + public Symbol getExistingSymbol(final String name) { 37.266 + return symbols.get(name); 37.267 } 37.268 37.269 /** 37.270 @@ -331,122 +188,6 @@ 37.271 return statements.size() == 1 && statements.get(0) instanceof CatchNode; 37.272 } 37.273 37.274 - /** 37.275 - * Test to see if a symbol is local to the function. 37.276 - * 37.277 - * @param symbol Symbol to test. 37.278 - * @return True if a local symbol. 37.279 - */ 37.280 - public boolean isLocal(final Symbol symbol) { 37.281 - // some temp symbols have no block, so can be assumed local 37.282 - final Block block = symbol.getBlock(); 37.283 - return block == null || block.getFunction() == function; 37.284 - } 37.285 - 37.286 - /** 37.287 - * Declare the definition of a new symbol. 37.288 - * 37.289 - * @param name Name of symbol. 37.290 - * @param symbolFlags Symbol flags. 37.291 - * @param node Defining Node. 37.292 - * 37.293 - * @return Symbol for given name or null for redefinition. 37.294 - */ 37.295 - public Symbol defineSymbol(final String name, final int symbolFlags, final Node node) { 37.296 - int flags = symbolFlags; 37.297 - Symbol symbol = findSymbol(name); // Locate symbol. 37.298 - 37.299 - if ((flags & KINDMASK) == IS_GLOBAL) { 37.300 - flags |= IS_SCOPE; 37.301 - } 37.302 - 37.303 - if (symbol != null) { 37.304 - // Symbol was already defined. Check if it needs to be redefined. 37.305 - if ((flags & KINDMASK) == IS_PARAM) { 37.306 - if (!function.isLocal(symbol)) { 37.307 - // Not defined in this function. Create a new definition. 37.308 - symbol = null; 37.309 - } else if (symbol.isParam()) { 37.310 - // Duplicate parameter. Null return will force an error. 37.311 - assert false : "duplicate parameter"; 37.312 - return null; 37.313 - } 37.314 - } else if ((flags & KINDMASK) == IS_VAR) { 37.315 - if ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & Symbol.IS_LET) == Symbol.IS_LET) { 37.316 - assert !((flags & IS_LET) == IS_LET && symbol.getBlock() == this) : "duplicate let variable in block"; 37.317 - // Always create a new definition. 37.318 - symbol = null; 37.319 - } else { 37.320 - // Not defined in this function. Create a new definition. 37.321 - if (!function.isLocal(symbol) || symbol.less(IS_VAR)) { 37.322 - symbol = null; 37.323 - } 37.324 - } 37.325 - } 37.326 - } 37.327 - 37.328 - if (symbol == null) { 37.329 - // If not found, then create a new one. 37.330 - Block symbolBlock; 37.331 - 37.332 - // Determine where to create it. 37.333 - if ((flags & Symbol.KINDMASK) == IS_VAR && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) { 37.334 - symbolBlock = this; 37.335 - } else { 37.336 - symbolBlock = getFunction(); 37.337 - } 37.338 - 37.339 - // Create and add to appropriate block. 37.340 - symbol = new Symbol(name, flags, node, symbolBlock); 37.341 - symbolBlock.putSymbol(name, symbol); 37.342 - 37.343 - if ((flags & Symbol.KINDMASK) != IS_GLOBAL) { 37.344 - symbolBlock.getFrame().addSymbol(symbol); 37.345 - symbol.setNeedsSlot(true); 37.346 - } 37.347 - } else if (symbol.less(flags)) { 37.348 - symbol.setFlags(flags); 37.349 - } 37.350 - 37.351 - if (node != null) { 37.352 - node.setSymbol(symbol); 37.353 - } 37.354 - 37.355 - return symbol; 37.356 - } 37.357 - 37.358 - /** 37.359 - * Declare the use of a symbol. 37.360 - * 37.361 - * @param name Name of symbol. 37.362 - * @param node Using node 37.363 - * 37.364 - * @return Symbol for given name. 37.365 - */ 37.366 - public Symbol useSymbol(final String name, final Node node) { 37.367 - Symbol symbol = findSymbol(name); 37.368 - 37.369 - if (symbol == null) { 37.370 - // If not found, declare as a free var. 37.371 - symbol = defineSymbol(name, IS_GLOBAL, node); 37.372 - } else { 37.373 - node.setSymbol(symbol); 37.374 - } 37.375 - 37.376 - return symbol; 37.377 - } 37.378 - 37.379 - /** 37.380 - * Add parent name to the builder. 37.381 - * 37.382 - * @param sb String bulder. 37.383 - */ 37.384 - public void addParentName(final StringBuilder sb) { 37.385 - if (parent != null) { 37.386 - parent.addParentName(sb); 37.387 - } 37.388 - } 37.389 - 37.390 @Override 37.391 public void toString(final StringBuilder sb) { 37.392 for (final Node statement : statements) { 37.393 @@ -505,16 +246,6 @@ 37.394 } 37.395 37.396 /** 37.397 - * Get the FunctionNode for this block, i.e. the function it 37.398 - * belongs to 37.399 - * 37.400 - * @return the function node 37.401 - */ 37.402 - public FunctionNode getFunction() { 37.403 - return function; 37.404 - } 37.405 - 37.406 - /** 37.407 * Reset the frame for this block 37.408 * 37.409 * @param frame the new frame 37.410 @@ -524,24 +255,6 @@ 37.411 } 37.412 37.413 /** 37.414 - * Get the parent block 37.415 - * 37.416 - * @return parent block, or null if none exists 37.417 - */ 37.418 - public Block getParent() { 37.419 - return parent; 37.420 - } 37.421 - 37.422 - /** 37.423 - * Set the parent block 37.424 - * 37.425 - * @param parent the new parent block 37.426 - */ 37.427 - public void setParent(final Block parent) { 37.428 - this.parent = parent; 37.429 - } 37.430 - 37.431 - /** 37.432 * Get the list of statements in this block 37.433 * 37.434 * @return a list of statements 37.435 @@ -551,6 +264,15 @@ 37.436 } 37.437 37.438 /** 37.439 + * Applies the specified visitor to all statements in the block. 37.440 + * @param visitor the visitor. 37.441 + */ 37.442 + public void visitStatements(NodeVisitor visitor) { 37.443 + for (ListIterator<Node> stmts = statements.listIterator(); stmts.hasNext();) { 37.444 + stmts.set(stmts.next().accept(visitor)); 37.445 + } 37.446 + } 37.447 + /** 37.448 * Reset the statement list for this block 37.449 * 37.450 * @param statements new statement list 37.451 @@ -585,4 +307,29 @@ 37.452 needsScope = true; 37.453 } 37.454 37.455 + /** 37.456 + * Marks this block as using a specified scoped symbol. The block and its parent blocks up to but not 37.457 + * including the block defining the symbol will be marked as needing parent scope. The block defining the symbol 37.458 + * will be marked as one that needs to have its own scope. 37.459 + * @param symbol the symbol being used. 37.460 + * @param ancestors the iterator over block's containing lexical context 37.461 + */ 37.462 + public void setUsesScopeSymbol(final Symbol symbol, Iterator<Block> ancestors) { 37.463 + if(symbol.getBlock() == this) { 37.464 + setNeedsScope(); 37.465 + } else { 37.466 + setUsesParentScopeSymbol(symbol, ancestors); 37.467 + } 37.468 + } 37.469 + 37.470 + /** 37.471 + * Invoked when this block uses a scope symbol defined in one of its ancestors. 37.472 + * @param symbol the scope symbol being used 37.473 + * @param ancestors iterator over ancestor blocks 37.474 + */ 37.475 + void setUsesParentScopeSymbol(final Symbol symbol, Iterator<Block> ancestors) { 37.476 + if(ancestors.hasNext()) { 37.477 + ancestors.next().setUsesScopeSymbol(symbol, ancestors); 37.478 + } 37.479 + } 37.480 }
38.1 --- a/src/jdk/nashorn/internal/ir/BreakNode.java Thu Mar 28 10:55:17 2013 -0700 38.2 +++ b/src/jdk/nashorn/internal/ir/BreakNode.java Mon Apr 01 21:42:31 2013 -0700 38.3 @@ -64,8 +64,8 @@ 38.4 */ 38.5 @Override 38.6 public Node accept(final NodeVisitor visitor) { 38.7 - if (visitor.enter(this) != null) { 38.8 - return visitor.leave(this); 38.9 + if (visitor.enterBreakNode(this) != null) { 38.10 + return visitor.leaveBreakNode(this); 38.11 } 38.12 38.13 return this;
39.1 --- a/src/jdk/nashorn/internal/ir/CallNode.java Thu Mar 28 10:55:17 2013 -0700 39.2 +++ b/src/jdk/nashorn/internal/ir/CallNode.java Mon Apr 01 21:42:31 2013 -0700 39.3 @@ -37,7 +37,7 @@ 39.4 * IR representation for a function call. 39.5 * 39.6 */ 39.7 -public class CallNode extends Node implements TypeOverride { 39.8 +public class CallNode extends Node implements TypeOverride<CallNode> { 39.9 39.10 private Type type; 39.11 39.12 @@ -176,13 +176,13 @@ 39.13 if (hasCallSiteType()) { 39.14 return type; 39.15 } 39.16 - assert !function.getType().isUnknown(); 39.17 - return function.getType(); 39.18 + return function instanceof FunctionNode ? ((FunctionNode)function).getReturnType() : Type.OBJECT; 39.19 } 39.20 39.21 @Override 39.22 - public void setType(final Type type) { 39.23 + public CallNode setType(final Type type) { 39.24 this.type = type; 39.25 + return this; 39.26 } 39.27 39.28 private boolean hasCallSiteType() { 39.29 @@ -208,14 +208,14 @@ 39.30 */ 39.31 @Override 39.32 public Node accept(final NodeVisitor visitor) { 39.33 - if (visitor.enter(this) != null) { 39.34 + if (visitor.enterCallNode(this) != null) { 39.35 function = function.accept(visitor); 39.36 39.37 for (int i = 0, count = args.size(); i < count; i++) { 39.38 args.set(i, args.get(i).accept(visitor)); 39.39 } 39.40 39.41 - return visitor.leave(this); 39.42 + return visitor.leaveCallNode(this); 39.43 } 39.44 39.45 return this;
40.1 --- a/src/jdk/nashorn/internal/ir/CaseNode.java Thu Mar 28 10:55:17 2013 -0700 40.2 +++ b/src/jdk/nashorn/internal/ir/CaseNode.java Mon Apr 01 21:42:31 2013 -0700 40.3 @@ -79,7 +79,7 @@ 40.4 */ 40.5 @Override 40.6 public Node accept(final NodeVisitor visitor) { 40.7 - if (visitor.enter(this) != null) { 40.8 + if (visitor.enterCaseNode(this) != null) { 40.9 if (test != null) { 40.10 test = test.accept(visitor); 40.11 } 40.12 @@ -87,7 +87,7 @@ 40.13 body = (Block)body.accept(visitor); 40.14 } 40.15 40.16 - return visitor.leave(this); 40.17 + return visitor.leaveCaseNode(this); 40.18 } 40.19 40.20 return this;
41.1 --- a/src/jdk/nashorn/internal/ir/CatchNode.java Thu Mar 28 10:55:17 2013 -0700 41.2 +++ b/src/jdk/nashorn/internal/ir/CatchNode.java Mon Apr 01 21:42:31 2013 -0700 41.3 @@ -84,7 +84,7 @@ 41.4 */ 41.5 @Override 41.6 public Node accept(final NodeVisitor visitor) { 41.7 - if (visitor.enter(this) != null) { 41.8 + if (visitor.enterCatchNode(this) != null) { 41.9 exception = (IdentNode)exception.accept(visitor); 41.10 41.11 if (exceptionCondition != null) { 41.12 @@ -92,7 +92,7 @@ 41.13 } 41.14 41.15 body = (Block)body.accept(visitor); 41.16 - return visitor.leave(this); 41.17 + return visitor.leaveCatchNode(this); 41.18 } 41.19 41.20 return this;
42.1 --- a/src/jdk/nashorn/internal/ir/ContinueNode.java Thu Mar 28 10:55:17 2013 -0700 42.2 +++ b/src/jdk/nashorn/internal/ir/ContinueNode.java Mon Apr 01 21:42:31 2013 -0700 42.3 @@ -61,8 +61,8 @@ 42.4 42.5 @Override 42.6 public Node accept(final NodeVisitor visitor) { 42.7 - if (visitor.enter(this) != null) { 42.8 - return visitor.leave(this); 42.9 + if (visitor.enterContinueNode(this) != null) { 42.10 + return visitor.leaveContinueNode(this); 42.11 } 42.12 42.13 return this;
43.1 --- a/src/jdk/nashorn/internal/ir/DoWhileNode.java Thu Mar 28 10:55:17 2013 -0700 43.2 +++ b/src/jdk/nashorn/internal/ir/DoWhileNode.java Mon Apr 01 21:42:31 2013 -0700 43.3 @@ -63,11 +63,11 @@ 43.4 43.5 @Override 43.6 public Node accept(final NodeVisitor visitor) { 43.7 - if (visitor.enter(this) != null) { 43.8 + if (visitor.enterDoWhileNode(this) != null) { 43.9 body = (Block)body.accept(visitor); 43.10 test = test.accept(visitor); 43.11 43.12 - return visitor.leave(this); 43.13 + return visitor.leaveDoWhileNode(this); 43.14 } 43.15 43.16 return this;
44.1 --- a/src/jdk/nashorn/internal/ir/EmptyNode.java Thu Mar 28 10:55:17 2013 -0700 44.2 +++ b/src/jdk/nashorn/internal/ir/EmptyNode.java Mon Apr 01 21:42:31 2013 -0700 44.3 @@ -57,8 +57,8 @@ 44.4 44.5 @Override 44.6 public Node accept(final NodeVisitor visitor) { 44.7 - if (visitor.enter(this) != null) { 44.8 - return visitor.leave(this); 44.9 + if (visitor.enterEmptyNode(this) != null) { 44.10 + return visitor.leaveEmptyNode(this); 44.11 } 44.12 return this; 44.13 }
45.1 --- a/src/jdk/nashorn/internal/ir/ExecuteNode.java Thu Mar 28 10:55:17 2013 -0700 45.2 +++ b/src/jdk/nashorn/internal/ir/ExecuteNode.java Mon Apr 01 21:42:31 2013 -0700 45.3 @@ -85,9 +85,9 @@ 45.4 45.5 @Override 45.6 public Node accept(final NodeVisitor visitor) { 45.7 - if (visitor.enter(this) != null) { 45.8 + if (visitor.enterExecuteNode(this) != null) { 45.9 setExpression(expression.accept(visitor)); 45.10 - return visitor.leave(this); 45.11 + return visitor.leaveExecuteNode(this); 45.12 } 45.13 45.14 return this;
46.1 --- a/src/jdk/nashorn/internal/ir/ForNode.java Thu Mar 28 10:55:17 2013 -0700 46.2 +++ b/src/jdk/nashorn/internal/ir/ForNode.java Mon Apr 01 21:42:31 2013 -0700 46.3 @@ -76,7 +76,7 @@ 46.4 46.5 @Override 46.6 public Node accept(final NodeVisitor visitor) { 46.7 - if (visitor.enter(this) != null) { 46.8 + if (visitor.enterForNode(this) != null) { 46.9 if (init != null) { 46.10 init = init.accept(visitor); 46.11 } 46.12 @@ -91,7 +91,7 @@ 46.13 46.14 body = (Block)body.accept(visitor); 46.15 46.16 - return visitor.leave(this); 46.17 + return visitor.leaveForNode(this); 46.18 } 46.19 46.20 return this;
47.1 --- a/src/jdk/nashorn/internal/ir/FunctionNode.java Thu Mar 28 10:55:17 2013 -0700 47.2 +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java Mon Apr 01 21:42:31 2013 -0700 47.3 @@ -33,8 +33,10 @@ 47.4 import java.util.ArrayList; 47.5 import java.util.Collections; 47.6 import java.util.EnumSet; 47.7 -import java.util.LinkedList; 47.8 +import java.util.HashMap; 47.9 +import java.util.Iterator; 47.10 import java.util.List; 47.11 +import java.util.Map; 47.12 import java.util.Stack; 47.13 import jdk.nashorn.internal.codegen.CompileUnit; 47.14 import jdk.nashorn.internal.codegen.Compiler; 47.15 @@ -45,16 +47,18 @@ 47.16 import jdk.nashorn.internal.ir.annotations.Ignore; 47.17 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 47.18 import jdk.nashorn.internal.parser.Parser; 47.19 +import jdk.nashorn.internal.runtime.ScriptFunction; 47.20 import jdk.nashorn.internal.runtime.Source; 47.21 import jdk.nashorn.internal.runtime.UserAccessorProperty; 47.22 import jdk.nashorn.internal.runtime.linker.LinkerCallSite; 47.23 47.24 /** 47.25 * IR representation for function (or script.) 47.26 - * 47.27 */ 47.28 public class FunctionNode extends Block { 47.29 47.30 + private static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class); 47.31 + 47.32 /** Function kinds */ 47.33 public enum Kind { 47.34 /** a normal function - nothing special */ 47.35 @@ -86,7 +90,9 @@ 47.36 /** method has had its types finalized */ 47.37 FINALIZED, 47.38 /** method has been emitted to bytecode */ 47.39 - EMITTED 47.40 + EMITTED, 47.41 + /** code installed in a class loader */ 47.42 + INSTALLED 47.43 } 47.44 47.45 /** External function identifier. */ 47.46 @@ -108,9 +114,6 @@ 47.47 /** List of parameters. */ 47.48 private List<IdentNode> parameters; 47.49 47.50 - /** List of nested functions. */ 47.51 - private List<FunctionNode> functions; 47.52 - 47.53 /** First token of function. **/ 47.54 private long firstToken; 47.55 47.56 @@ -153,10 +156,6 @@ 47.57 /** Pending control list. */ 47.58 private final Stack<Node> controlStack; 47.59 47.60 - /** Variable declarations in the function's scope */ 47.61 - @Ignore 47.62 - private final List<VarNode> declarations; 47.63 - 47.64 /** VarNode for this function statement */ 47.65 @Ignore //this is explicit code anyway and should not be traversed after lower 47.66 private VarNode funcVarNode; 47.67 @@ -173,37 +172,42 @@ 47.68 @Ignore 47.69 private final EnumSet<CompilationState> compilationState; 47.70 47.71 + /** Type hints, e.g based on parameters at call site */ 47.72 + private final Map<IdentNode, Type> specializedTypes; 47.73 + 47.74 /** Function flags. */ 47.75 private int flags; 47.76 47.77 /** Is anonymous function flag. */ 47.78 - private static final int IS_ANONYMOUS = 0b0000_0000_0000_0001; 47.79 - /** Is statement flag */ 47.80 - private static final int IS_STATEMENT = 0b0000_0000_0000_0010; 47.81 + private static final int IS_ANONYMOUS = 1 << 0; 47.82 + /** Is the function created in a function declaration (as opposed to a function expression) */ 47.83 + private static final int IS_DECLARED = 1 << 1; 47.84 /** is this a strict mode function? */ 47.85 - private static final int IS_STRICT_MODE = 0b0000_0000_0000_0100; 47.86 + private static final int IS_STRICT_MODE = 1 << 2; 47.87 /** Does the function use the "arguments" identifier ? */ 47.88 - private static final int USES_ARGUMENTS = 0b0000_0000_0000_1000; 47.89 + private static final int USES_ARGUMENTS = 1 << 3; 47.90 /** Are we lowered ? */ 47.91 - private static final int IS_LOWERED = 0b0000_0000_0001_0000; 47.92 + private static final int IS_LOWERED = 1 << 4; 47.93 /** Has this node been split because it was too large? */ 47.94 - private static final int IS_SPLIT = 0b0000_0000_0010_0000; 47.95 + private static final int IS_SPLIT = 1 << 5; 47.96 /** Does the function call eval? */ 47.97 - private static final int HAS_EVAL = 0b0000_0000_0100_0000; 47.98 + private static final int HAS_EVAL = 1 << 6; 47.99 /** Does the function contain a with block ? */ 47.100 - private static final int HAS_WITH = 0b0000_0000_1000_0000; 47.101 + private static final int HAS_WITH = 1 << 7; 47.102 /** Does a descendant function contain a with or eval? */ 47.103 - private static final int HAS_DESCENDANT_WITH_OR_EVAL = 0b0000_0001_0000_0000; 47.104 + private static final int HAS_DESCENDANT_WITH_OR_EVAL = 1 << 8; 47.105 /** Does the function define "arguments" identifier as a parameter of nested function name? */ 47.106 - private static final int DEFINES_ARGUMENTS = 0b0000_0010_0000_0000; 47.107 + private static final int DEFINES_ARGUMENTS = 1 << 9; 47.108 /** Does the function need a self symbol? */ 47.109 - private static final int NEEDS_SELF_SYMBOL = 0b0000_0100_0000_0000; 47.110 + private static final int NEEDS_SELF_SYMBOL = 1 << 10; 47.111 /** Does this function or any of its descendants use variables from an ancestor function's scope (incl. globals)? */ 47.112 - private static final int USES_ANCESTOR_SCOPE = 0b0000_1000_0000_0000; 47.113 + private static final int USES_ANCESTOR_SCOPE = 1 << 11; 47.114 /** Is this function lazily compiled? */ 47.115 - private static final int IS_LAZY = 0b0001_0000_0000_0000; 47.116 + private static final int IS_LAZY = 1 << 12; 47.117 /** Does this function have lazy, yet uncompiled children */ 47.118 - private static final int HAS_LAZY_CHILDREN = 0b0010_0000_0000_0000; 47.119 + private static final int HAS_LAZY_CHILDREN = 1 << 13; 47.120 + /** Does this function have lazy, yet uncompiled children */ 47.121 + private static final int IS_PROGRAM = 1 << 14; 47.122 47.123 /** Does this function or any nested functions contain a with or an eval? */ 47.124 private static final int HAS_DEEP_WITH_OR_EVAL = HAS_EVAL | HAS_WITH | HAS_DESCENDANT_WITH_OR_EVAL; 47.125 @@ -211,54 +215,39 @@ 47.126 private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_WITH_OR_EVAL | IS_SPLIT | HAS_LAZY_CHILDREN; 47.127 /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */ 47.128 private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL; 47.129 - /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep with or eval. */ 47.130 - private static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_WITH_OR_EVAL; 47.131 + /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep with or eval. 47.132 + * We also pessimistically need a parent scope if we have lazy children that have not yet been compiled */ 47.133 + private static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_WITH_OR_EVAL | HAS_LAZY_CHILDREN; 47.134 47.135 /** What is the return type of this function? */ 47.136 private Type returnType = Type.UNKNOWN; 47.137 47.138 /** 47.139 - * Used to keep track of a function's parent blocks. 47.140 - * This is needed when a (finally body) block is cloned than contains inner functions. 47.141 - * Does not include function.getParent(). 47.142 - */ 47.143 - @Ignore 47.144 - private List<Block> referencingParentBlocks; 47.145 - 47.146 - /** 47.147 * Constructor 47.148 * 47.149 * @param source the source 47.150 * @param token token 47.151 * @param finish finish 47.152 * @param namespace the namespace 47.153 - * @param parent the parent block 47.154 * @param ident the identifier 47.155 * @param name the name of the function 47.156 */ 47.157 - @SuppressWarnings("LeakingThisInConstructor") 47.158 - public FunctionNode(final Source source, final long token, final int finish, final Namespace namespace, final Block parent, final IdentNode ident, final String name) { 47.159 - super(source, token, finish, parent, null); 47.160 + public FunctionNode(final Source source, final long token, final int finish, final Namespace namespace, final IdentNode ident, final String name) { 47.161 + super(source, token, finish); 47.162 47.163 this.ident = ident; 47.164 this.name = name; 47.165 this.kind = Kind.NORMAL; 47.166 this.parameters = new ArrayList<>(); 47.167 - this.functions = new ArrayList<>(); 47.168 this.firstToken = token; 47.169 this.lastToken = token; 47.170 this.namespace = namespace; 47.171 this.labelStack = new Stack<>(); 47.172 this.controlStack = new Stack<>(); 47.173 - this.declarations = new ArrayList<>(); 47.174 - // my block -> function is this. We added @SuppressWarnings("LeakingThisInConstructor") as NetBeans identifies 47.175 - // it as such a leak - this is a false positive as we're setting this into a field of the object being 47.176 - // constructed, so it can't be seen from other threads. 47.177 - this.function = this; 47.178 this.compilationState = EnumSet.of(CompilationState.INITIALIZED); 47.179 + this.specializedTypes = new HashMap<>(); 47.180 } 47.181 47.182 - @SuppressWarnings("LeakingThisInConstructor") 47.183 private FunctionNode(final FunctionNode functionNode, final CopyState cs) { 47.184 super(functionNode, cs); 47.185 47.186 @@ -268,10 +257,9 @@ 47.187 47.188 this.parameters = new ArrayList<>(); 47.189 for (final IdentNode param : functionNode.getParameters()) { 47.190 - this.parameters.add((IdentNode) cs.existingOrCopy(param)); 47.191 + this.parameters.add((IdentNode)cs.existingOrCopy(param)); 47.192 } 47.193 47.194 - this.functions = new ArrayList<>(); 47.195 this.firstToken = functionNode.firstToken; 47.196 this.lastToken = functionNode.lastToken; 47.197 this.namespace = functionNode.getNamespace(); 47.198 @@ -283,43 +271,34 @@ 47.199 this.calleeNode = (IdentNode)cs.existingOrCopy(functionNode.calleeNode); 47.200 this.labelStack = new Stack<>(); 47.201 this.controlStack = new Stack<>(); 47.202 - this.declarations = new ArrayList<>(); 47.203 - 47.204 - for (final VarNode decl : functionNode.getDeclarations()) { 47.205 - declarations.add((VarNode) cs.existingOrCopy(decl)); //TODO same? 47.206 - } 47.207 47.208 this.flags = functionNode.flags; 47.209 47.210 this.funcVarNode = (VarNode)cs.existingOrCopy(functionNode.funcVarNode); 47.211 /** VarNode for this function statement */ 47.212 47.213 - // my block -> function is this. We added @SuppressWarnings("LeakingThisInConstructor") as NetBeans identifies 47.214 - // it as such a leak - this is a false positive as we're setting this into a field of the object being 47.215 - // constructed, so it can't be seen from other threads. 47.216 - this.function = this; 47.217 - 47.218 this.compilationState = EnumSet.copyOf(functionNode.compilationState); 47.219 + this.specializedTypes = new HashMap<>(); 47.220 } 47.221 47.222 @Override 47.223 protected Node copy(final CopyState cs) { 47.224 // deep clone all parent blocks 47.225 - return fixBlockChain(new FunctionNode(this, cs)); 47.226 + return new FunctionNode(this, cs); 47.227 } 47.228 47.229 @Override 47.230 public Node accept(final NodeVisitor visitor) { 47.231 - final FunctionNode saveFunctionNode = visitor.getCurrentFunctionNode(); 47.232 - final Block saveBlock = visitor.getCurrentBlock(); 47.233 + final FunctionNode saveFunctionNode = visitor.getCurrentFunctionNode(); 47.234 + final Block saveBlock = visitor.getCurrentBlock(); 47.235 + final MethodEmitter saveMethodEmitter = visitor.getCurrentMethodEmitter(); 47.236 + final CompileUnit saveCompileUnit = visitor.getCurrentCompileUnit(); 47.237 47.238 visitor.setCurrentFunctionNode(this); 47.239 - visitor.setCurrentCompileUnit(getCompileUnit()); 47.240 - visitor.setCurrentMethodEmitter(getMethodEmitter()); 47.241 visitor.setCurrentBlock(this); 47.242 47.243 try { 47.244 - if (visitor.enter(this) != null) { 47.245 + if (visitor.enterFunctionNode(this) != null) { 47.246 if (ident != null) { 47.247 ident = (IdentNode)ident.accept(visitor); 47.248 } 47.249 @@ -328,51 +307,25 @@ 47.250 parameters.set(i, (IdentNode)parameters.get(i).accept(visitor)); 47.251 } 47.252 47.253 - for (int i = 0, count = functions.size(); i < count; i++) { 47.254 - functions.set(i, (FunctionNode)functions.get(i).accept(visitor)); 47.255 - } 47.256 - 47.257 for (int i = 0, count = statements.size(); i < count; i++) { 47.258 statements.set(i, statements.get(i).accept(visitor)); 47.259 } 47.260 47.261 - return visitor.leave(this); 47.262 + return visitor.leaveFunctionNode(this); 47.263 } 47.264 } finally { 47.265 visitor.setCurrentBlock(saveBlock); 47.266 visitor.setCurrentFunctionNode(saveFunctionNode); 47.267 - visitor.setCurrentCompileUnit(saveFunctionNode != null ? saveFunctionNode.getCompileUnit() : null); 47.268 - visitor.setCurrentMethodEmitter(saveFunctionNode != null ? saveFunctionNode.getMethodEmitter() : null); 47.269 + visitor.setCurrentCompileUnit(saveCompileUnit); 47.270 + visitor.setCurrentMethodEmitter(saveMethodEmitter); 47.271 } 47.272 47.273 return this; 47.274 } 47.275 47.276 - /** 47.277 - * Locate the parent function. 47.278 - * 47.279 - * @return Parent function. 47.280 - */ 47.281 - public FunctionNode findParentFunction() { 47.282 - return getParent() != null ? getParent().getFunction() : null; 47.283 - } 47.284 - 47.285 - /** 47.286 - * Add parent name to the builder. 47.287 - * 47.288 - * @param sb String builder. 47.289 - */ 47.290 - @Override 47.291 - public void addParentName(final StringBuilder sb) { 47.292 - if (!isScript()) { 47.293 - sb.append(getName()); 47.294 - sb.append("$"); 47.295 - } 47.296 - } 47.297 - 47.298 @Override 47.299 public boolean needsScope() { 47.300 - return super.needsScope() || isScript(); 47.301 + return super.needsScope() || isProgram(); 47.302 } 47.303 47.304 /** 47.305 @@ -530,12 +483,18 @@ 47.306 } 47.307 47.308 /** 47.309 - * Determine if script function. 47.310 - * 47.311 - * @return True if script function. 47.312 + * Returns true if the function is the top-level program. 47.313 + * @return True if this function node represents the top-level program. 47.314 */ 47.315 - public boolean isScript() { 47.316 - return getParent() == null; 47.317 + public boolean isProgram() { 47.318 + return (flags & IS_PROGRAM) != 0; 47.319 + } 47.320 + 47.321 + /** 47.322 + * Marks the function as representing the top-level program. 47.323 + */ 47.324 + public void setProgram() { 47.325 + flags |= IS_PROGRAM; 47.326 } 47.327 47.328 /** 47.329 @@ -575,31 +534,31 @@ 47.330 47.331 /** 47.332 * Flag this function as using the {@code with} keyword 47.333 + * @param ancestors the iterator over functions in this functions's containing lexical context 47.334 */ 47.335 - public void setHasWith() { 47.336 + public void setHasWith(final Iterator<FunctionNode> ancestors) { 47.337 if(!hasWith()) { 47.338 this.flags |= HAS_WITH; 47.339 // with requires scope in parents. 47.340 // TODO: refine this. with should not force all variables in parents to be in scope, only those that are 47.341 // actually referenced as identifiers by name 47.342 - markParentForWithOrEval(); 47.343 + markParentForWithOrEval(ancestors); 47.344 } 47.345 } 47.346 47.347 - private void markParentForWithOrEval() { 47.348 + private void markParentForWithOrEval(final Iterator<FunctionNode> ancestors) { 47.349 // If this is invoked, then either us or a descendant uses with or eval, meaning we must have our own scope. 47.350 setNeedsScope(); 47.351 47.352 - final FunctionNode parentFunction = findParentFunction(); 47.353 - if(parentFunction != null) { 47.354 - parentFunction.setDescendantHasWithOrEval(); 47.355 + if(ancestors.hasNext()) { 47.356 + ancestors.next().setDescendantHasWithOrEval(ancestors); 47.357 } 47.358 } 47.359 47.360 - private void setDescendantHasWithOrEval() { 47.361 + private void setDescendantHasWithOrEval(final Iterator<FunctionNode> ancestors) { 47.362 if((flags & HAS_DESCENDANT_WITH_OR_EVAL) == 0) { 47.363 flags |= HAS_DESCENDANT_WITH_OR_EVAL; 47.364 - markParentForWithOrEval(); 47.365 + markParentForWithOrEval(ancestors); 47.366 } 47.367 } 47.368 47.369 @@ -614,11 +573,12 @@ 47.370 47.371 /** 47.372 * Flag this function as calling the {@code eval} function 47.373 + * @param ancestors the iterator over functions in this functions's containing lexical context 47.374 */ 47.375 - public void setHasEval() { 47.376 + public void setHasEval(final Iterator<FunctionNode> ancestors) { 47.377 if(!hasEval()) { 47.378 this.flags |= HAS_EVAL; 47.379 - markParentForWithOrEval(); 47.380 + markParentForWithOrEval(ancestors); 47.381 } 47.382 } 47.383 47.384 @@ -651,11 +611,34 @@ 47.385 } 47.386 47.387 /** 47.388 - * Get all nested functions 47.389 - * @return list of nested functions in this function 47.390 + * Returns a list of functions declared by this function. Only includes declared functions, and does not include any 47.391 + * function expressions that might occur in its body. 47.392 + * @return a list of functions declared by this function. 47.393 */ 47.394 - public List<FunctionNode> getFunctions() { 47.395 - return Collections.unmodifiableList(functions); 47.396 + public List<FunctionNode> getDeclaredFunctions() { 47.397 + // Note that the function does not have a dedicated list of declared functions, but rather relies on the 47.398 + // invariant that all function declarations are at the beginning of the statement list as VarNode with a 47.399 + // FunctionNode marked as statement with its variable initializer. Every VarNode is also preceded by a 47.400 + // LineNumberNode. This invariant is established by the parser and has to be preserved in visitors. 47.401 + final List<FunctionNode> fns = new ArrayList<>(); 47.402 + for (final Node stmt : statements) { 47.403 + if(stmt instanceof LineNumberNode) { 47.404 + continue; 47.405 + } else if(stmt instanceof VarNode) { 47.406 + final Node init = ((VarNode)stmt).getInit(); 47.407 + if(init instanceof FunctionNode) { 47.408 + final FunctionNode fn = (FunctionNode)init; 47.409 + if(fn.isDeclared()) { 47.410 + fns.add(fn); 47.411 + continue; 47.412 + } 47.413 + } 47.414 + } 47.415 + // Node is neither a LineNumberNode, nor a function declaration VarNode. Since all function declarations are 47.416 + // at the start of the function, we've reached the end of function declarations. 47.417 + break; 47.418 + } 47.419 + return fns; 47.420 } 47.421 47.422 /** 47.423 @@ -710,6 +693,7 @@ 47.424 * Check if this function's generated Java method needs a {@code callee} parameter. Functions that need access to 47.425 * their parent scope, functions that reference themselves, and non-strict functions that need an Arguments object 47.426 * (since it exposes {@code arguments.callee} property) will need to have a callee parameter. 47.427 + * 47.428 * @return true if the function's generated Java method needs a {@code callee} parameter. 47.429 */ 47.430 public boolean needsCallee() { 47.431 @@ -786,7 +770,7 @@ 47.432 public boolean needsArguments() { 47.433 // uses "arguments" or calls eval, but it does not redefine "arguments", and finally, it's not a script, since 47.434 // for top-level script, "arguments" is picked up from Context by Global.init() instead. 47.435 - return (flags & MAYBE_NEEDS_ARGUMENTS) != 0 && (flags & DEFINES_ARGUMENTS) == 0 && !isScript(); 47.436 + return (flags & MAYBE_NEEDS_ARGUMENTS) != 0 && (flags & DEFINES_ARGUMENTS) == 0 && !isProgram(); 47.437 } 47.438 47.439 /** 47.440 @@ -805,7 +789,7 @@ 47.441 * @return true if the function needs parent scope. 47.442 */ 47.443 public boolean needsParentScope() { 47.444 - return (flags & NEEDS_PARENT_SCOPE) != 0 || isScript(); 47.445 + return (flags & NEEDS_PARENT_SCOPE) != 0 || isProgram(); 47.446 } 47.447 47.448 /** 47.449 @@ -865,7 +849,7 @@ 47.450 * @return true if all variables should be in scope 47.451 */ 47.452 public boolean allVarsInScope() { 47.453 - return isScript() || (flags & HAS_ALL_VARS_IN_SCOPE) != 0; 47.454 + return isProgram() || (flags & HAS_ALL_VARS_IN_SCOPE) != 0; 47.455 } 47.456 47.457 /** 47.458 @@ -919,6 +903,27 @@ 47.459 } 47.460 47.461 /** 47.462 + * Get a specialized type for an identity, if one exists 47.463 + * @param node node to check specialized type for 47.464 + * @return null if no specialization exists, otherwise type 47.465 + */ 47.466 + public Type getSpecializedType(final IdentNode node) { 47.467 + return specializedTypes.get(node); 47.468 + } 47.469 + 47.470 + /** 47.471 + * Set parameter type hints for specialization. 47.472 + * @param types types array of length equal to parameter list size 47.473 + */ 47.474 + public void setParameterTypes(final Class<?>[] types) { 47.475 + assert types.length == parameters.size() : "Type vector length doesn't correspond to parameter types"; 47.476 + //diff - skip the callee and this etc, they are not explicit params in the parse tree 47.477 + for (int i = 0; i < types.length ; i++) { 47.478 + specializedTypes.put(parameters.get(i), Type.typeFor(types[i])); 47.479 + } 47.480 + } 47.481 + 47.482 + /** 47.483 * Get the identifier for the variable in which the function return value 47.484 * should be stored 47.485 * @return an IdentNode representing the return value 47.486 @@ -953,19 +958,19 @@ 47.487 } 47.488 47.489 /** 47.490 - * Check if this function is a statement 47.491 - * @return true if function is a statement 47.492 + * Check if this function is created as a function declaration (as opposed to function expression) 47.493 + * @return true if function is declared. 47.494 */ 47.495 - public boolean isStatement() { 47.496 - return (flags & IS_STATEMENT) != 0; 47.497 + public boolean isDeclared() { 47.498 + return (flags & IS_DECLARED) != 0; 47.499 } 47.500 47.501 /** 47.502 - * Flag this function as a statement 47.503 + * Flag this function as being created as a function declaration (as opposed to a function expression). 47.504 * @see Parser 47.505 */ 47.506 - public void setIsStatement() { 47.507 - this.flags |= IS_STATEMENT; 47.508 + public void setIsDeclared() { 47.509 + this.flags |= IS_DECLARED; 47.510 } 47.511 47.512 /** 47.513 @@ -1013,35 +1018,16 @@ 47.514 } 47.515 47.516 /** 47.517 - * Marks this function as one using any global symbol. The function and all its parent functions will all be marked 47.518 - * as needing parent scope. 47.519 - * @see #needsParentScope() 47.520 + * Marks this function as using any of its ancestors' scopes. 47.521 */ 47.522 - public void setUsesGlobalSymbol() { 47.523 + public void setUsesAncestorScope() { 47.524 this.flags |= USES_ANCESTOR_SCOPE; 47.525 - final FunctionNode parentFn = findParentFunction(); 47.526 - if(parentFn != null) { 47.527 - parentFn.setUsesGlobalSymbol(); 47.528 - } 47.529 } 47.530 47.531 - /** 47.532 - * Marks this function as using a specified scoped symbol. The function and its parent functions up to but not 47.533 - * including the function defining the symbol will be marked as needing parent scope. The function defining the 47.534 - * symbol will be marked as one that needs to have its own scope. 47.535 - * @param symbol the symbol being used. 47.536 - * @see #needsParentScope() 47.537 - */ 47.538 - public void setUsesScopeSymbol(final Symbol symbol) { 47.539 - if(symbol.getBlock() == this) { 47.540 - setNeedsScope(); 47.541 - } else { 47.542 - this.flags |= USES_ANCESTOR_SCOPE; 47.543 - final FunctionNode parentFn = findParentFunction(); 47.544 - if(parentFn != null) { 47.545 - parentFn.setUsesScopeSymbol(symbol); 47.546 - } 47.547 - } 47.548 + @Override 47.549 + void setUsesParentScopeSymbol(Symbol symbol, Iterator<Block> ancestors) { 47.550 + setUsesAncestorScope(); 47.551 + super.setUsesParentScopeSymbol(symbol, ancestors); 47.552 } 47.553 47.554 /** 47.555 @@ -1116,7 +1102,7 @@ 47.556 47.557 @Override 47.558 public Type getType() { 47.559 - return getReturnType(); 47.560 + return FUNCTION_TYPE; 47.561 } 47.562 47.563 /** 47.564 @@ -1176,56 +1162,6 @@ 47.565 } 47.566 47.567 /** 47.568 - * Add a new function to the function list. 47.569 - * 47.570 - * @param functionNode Function node to add. 47.571 - */ 47.572 - @Override 47.573 - public void addFunction(final FunctionNode functionNode) { 47.574 - assert functionNode != null; 47.575 - functions.add(functionNode); 47.576 - } 47.577 - 47.578 - /** 47.579 - * Add a list of functions to the function list. 47.580 - * 47.581 - * @param functionNodes Function nodes to add. 47.582 - */ 47.583 - @Override 47.584 - public void addFunctions(final List<FunctionNode> functionNodes) { 47.585 - functions.addAll(functionNodes); 47.586 - } 47.587 - 47.588 - /** 47.589 - * Set a function list 47.590 - * 47.591 - * @param functionNodes to set 47.592 - */ 47.593 - @Override 47.594 - public void setFunctions(final List<FunctionNode> functionNodes) { 47.595 - this.functions = functionNodes; 47.596 - } 47.597 - 47.598 - /** 47.599 - * Add a variable declaration that should be visible to the entire function 47.600 - * scope. Parser does this. 47.601 - * 47.602 - * @param varNode a var node 47.603 - */ 47.604 - public void addDeclaration(final VarNode varNode) { 47.605 - declarations.add(varNode); 47.606 - } 47.607 - 47.608 - /** 47.609 - * Return all variable declarations from this function scope 47.610 - * 47.611 - * @return all VarNodes in scope 47.612 - */ 47.613 - public List<VarNode> getDeclarations() { 47.614 - return Collections.unmodifiableList(declarations); 47.615 - } 47.616 - 47.617 - /** 47.618 * Get the compile unit used to compile this function 47.619 * @see Compiler 47.620 * @return the compile unit 47.621 @@ -1258,32 +1194,4 @@ 47.622 public void setMethodEmitter(final MethodEmitter method) { 47.623 this.method = method; 47.624 } 47.625 - 47.626 - /** 47.627 - * Each FunctionNode maintains a list of reference to its parent blocks. 47.628 - * Add a parent block to this function. 47.629 - * 47.630 - * @param parentBlock a block to remember as parent 47.631 - */ 47.632 - public void addReferencingParentBlock(final Block parentBlock) { 47.633 - assert parentBlock.getFunction() == function.findParentFunction(); // all parent blocks must be in the same function 47.634 - if (parentBlock != function.getParent()) { 47.635 - if (referencingParentBlocks == null) { 47.636 - referencingParentBlocks = new LinkedList<>(); 47.637 - } 47.638 - referencingParentBlocks.add(parentBlock); 47.639 - } 47.640 - } 47.641 - 47.642 - /** 47.643 - * Get the known parent blocks to this function 47.644 - * 47.645 - * @return list of parent blocks 47.646 - */ 47.647 - public List<Block> getReferencingParentBlocks() { 47.648 - if (referencingParentBlocks == null) { 47.649 - return Collections.emptyList(); 47.650 - } 47.651 - return Collections.unmodifiableList(referencingParentBlocks); 47.652 - } 47.653 }
48.1 --- a/src/jdk/nashorn/internal/ir/IdentNode.java Thu Mar 28 10:55:17 2013 -0700 48.2 +++ b/src/jdk/nashorn/internal/ir/IdentNode.java Mon Apr 01 21:42:31 2013 -0700 48.3 @@ -38,18 +38,18 @@ 48.4 /** 48.5 * IR representation for an identifier. 48.6 */ 48.7 -public class IdentNode extends Node implements PropertyKey, TypeOverride, FunctionCall { 48.8 +public class IdentNode extends Node implements PropertyKey, TypeOverride<IdentNode>, FunctionCall { 48.9 + private static final int PROPERTY_NAME = 1 << 0; 48.10 + private static final int INITIALIZED_HERE = 1 << 1; 48.11 + private static final int FUNCTION = 1 << 2; 48.12 + 48.13 /** Identifier. */ 48.14 private final String name; 48.15 48.16 /** Type for a callsite, e.g. X in a get()X or a set(X)V */ 48.17 private Type callSiteType; 48.18 48.19 - /** flag for an ident that is the property name of an AccessNode. */ 48.20 - private boolean isPropertyName; 48.21 - 48.22 - /** flag for an ident on the left hand side of <code>var lhs = rhs;</code>. */ 48.23 - private boolean isInitializedHere; 48.24 + private byte flags; 48.25 48.26 /** 48.27 * Constructor 48.28 @@ -71,9 +71,8 @@ 48.29 */ 48.30 public IdentNode(final IdentNode identNode) { 48.31 super(identNode); 48.32 - this.name = identNode.getName(); 48.33 - this.isPropertyName = identNode.isPropertyName; 48.34 - this.isInitializedHere = identNode.isInitializedHere; 48.35 + this.name = identNode.getName(); 48.36 + this.flags = identNode.flags; 48.37 } 48.38 48.39 @Override 48.40 @@ -92,12 +91,17 @@ 48.41 } 48.42 48.43 @Override 48.44 - public void setType(final Type type) { 48.45 + public IdentNode setType(final Type type) { 48.46 if (DEBUG_FIELDS && getSymbol() != null && !Type.areEquivalent(getSymbol().getSymbolType(), type)) { 48.47 ObjectClassGenerator.LOG.info(getClass().getName() + " " + this + " => " + type + " instead of " + getType()); 48.48 } 48.49 - this.callSiteType = type; 48.50 // do NOT, repeat NOT touch the symbol here. it might be a local variable or whatever. This is the override if it isn't 48.51 + if(this.callSiteType == type) { 48.52 + return this; 48.53 + } 48.54 + final IdentNode n = (IdentNode)clone(); 48.55 + n.callSiteType = type; 48.56 + return n; 48.57 } 48.58 48.59 @Override 48.60 @@ -131,8 +135,8 @@ 48.61 */ 48.62 @Override 48.63 public Node accept(final NodeVisitor visitor) { 48.64 - if (visitor.enter(this) != null) { 48.65 - return visitor.leave(this); 48.66 + if (visitor.enterIdentNode(this) != null) { 48.67 + return visitor.leaveIdentNode(this); 48.68 } 48.69 48.70 return this; 48.71 @@ -179,14 +183,18 @@ 48.72 * @return true if this is a property name 48.73 */ 48.74 public boolean isPropertyName() { 48.75 - return isPropertyName; 48.76 + return (flags & PROPERTY_NAME) != 0; 48.77 } 48.78 48.79 /** 48.80 * Flag this IdentNode as a property name 48.81 + * @return a node equivalent to this one except for the requested change. 48.82 */ 48.83 - public void setIsPropertyName() { 48.84 - isPropertyName = true; 48.85 + public IdentNode setIsPropertyName() { 48.86 + if(isPropertyName()) return this; 48.87 + final IdentNode n = (IdentNode)clone(); 48.88 + n.flags |= PROPERTY_NAME; 48.89 + return n; 48.90 } 48.91 48.92 /** 48.93 @@ -194,14 +202,18 @@ 48.94 * @return true if IdentNode is initialized on creation 48.95 */ 48.96 public boolean isInitializedHere() { 48.97 - return isInitializedHere; 48.98 + return (flags & INITIALIZED_HERE) != 0; 48.99 } 48.100 48.101 /** 48.102 * Flag IdentNode to be initialized on creation 48.103 + * @return a node equivalent to this one except for the requested change. 48.104 */ 48.105 - public void setIsInitializedHere() { 48.106 - isInitializedHere = true; 48.107 + public IdentNode setIsInitializedHere() { 48.108 + if(isInitializedHere()) return this; 48.109 + final IdentNode n = (IdentNode)clone(); 48.110 + n.flags |= INITIALIZED_HERE; 48.111 + return n; 48.112 } 48.113 48.114 /** 48.115 @@ -216,6 +228,17 @@ 48.116 48.117 @Override 48.118 public boolean isFunction() { 48.119 - return false; 48.120 + return (flags & FUNCTION) != 0; 48.121 + } 48.122 + 48.123 + /** 48.124 + * Mark this node as being the callee operand of a {@link CallNode}. 48.125 + * @return an ident node identical to this one in all aspects except with its function flag set. 48.126 + */ 48.127 + public IdentNode setIsFunction() { 48.128 + if(isFunction()) return this; 48.129 + final IdentNode n = (IdentNode)clone(); 48.130 + n.flags |= FUNCTION; 48.131 + return n; 48.132 } 48.133 }
49.1 --- a/src/jdk/nashorn/internal/ir/IfNode.java Thu Mar 28 10:55:17 2013 -0700 49.2 +++ b/src/jdk/nashorn/internal/ir/IfNode.java Mon Apr 01 21:42:31 2013 -0700 49.3 @@ -75,7 +75,7 @@ 49.4 49.5 @Override 49.6 public Node accept(final NodeVisitor visitor) { 49.7 - if (visitor.enter(this) != null) { 49.8 + if (visitor.enterIfNode(this) != null) { 49.9 test = test.accept(visitor); 49.10 49.11 pass = (Block)pass.accept(visitor); 49.12 @@ -84,7 +84,7 @@ 49.13 fail = (Block)fail.accept(visitor); 49.14 } 49.15 49.16 - return visitor.leave(this); 49.17 + return visitor.leaveIfNode(this); 49.18 } 49.19 49.20 return this;
50.1 --- a/src/jdk/nashorn/internal/ir/IndexNode.java Thu Mar 28 10:55:17 2013 -0700 50.2 +++ b/src/jdk/nashorn/internal/ir/IndexNode.java Mon Apr 01 21:42:31 2013 -0700 50.3 @@ -36,7 +36,7 @@ 50.4 * IR representation of an indexed access (brackets operator.) 50.5 * 50.6 */ 50.7 -public class IndexNode extends BaseNode implements TypeOverride { 50.8 +public class IndexNode extends BaseNode implements TypeOverride<IndexNode> { 50.9 /** Property ident. */ 50.10 private Node index; 50.11 50.12 @@ -92,10 +92,10 @@ 50.13 50.14 @Override 50.15 public Node accept(final NodeVisitor visitor) { 50.16 - if (visitor.enter(this) != null) { 50.17 + if (visitor.enterIndexNode(this) != null) { 50.18 base = base.accept(visitor); 50.19 index = index.accept(visitor); 50.20 - return visitor.leave(this); 50.21 + return visitor.leaveIndexNode(this); 50.22 } 50.23 50.24 return this; 50.25 @@ -144,12 +144,13 @@ 50.26 } 50.27 50.28 @Override 50.29 - public void setType(final Type type) { 50.30 + public IndexNode setType(final Type type) { 50.31 if (DEBUG_FIELDS && !Type.areEquivalent(getSymbol().getSymbolType(), type)) { 50.32 ObjectClassGenerator.LOG.info(getClass().getName() + " " + this + " => " + type + " instead of " + getType()); 50.33 } 50.34 hasCallSiteType = true; 50.35 getSymbol().setTypeOverride(type); 50.36 + return this; 50.37 } 50.38 50.39 @Override
51.1 --- a/src/jdk/nashorn/internal/ir/LabelNode.java Thu Mar 28 10:55:17 2013 -0700 51.2 +++ b/src/jdk/nashorn/internal/ir/LabelNode.java Mon Apr 01 21:42:31 2013 -0700 51.3 @@ -81,10 +81,10 @@ 51.4 51.5 @Override 51.6 public Node accept(final NodeVisitor visitor) { 51.7 - if (visitor.enter(this) != null) { 51.8 + if (visitor.enterLabelNode(this) != null) { 51.9 label = (IdentNode)label.accept(visitor); 51.10 body = (Block)body.accept(visitor); 51.11 - return visitor.leave(this); 51.12 + return visitor.leaveLabelNode(this); 51.13 } 51.14 51.15 return this;
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 52.2 +++ b/src/jdk/nashorn/internal/ir/LexicalContext.java Mon Apr 01 21:42:31 2013 -0700 52.3 @@ -0,0 +1,198 @@ 52.4 +package jdk.nashorn.internal.ir; 52.5 + 52.6 +import java.util.ArrayDeque; 52.7 +import java.util.Deque; 52.8 +import java.util.Iterator; 52.9 +import java.util.NoSuchElementException; 52.10 + 52.11 +/** 52.12 + * A class that tracks the current lexical context of node visitation as a stack of {@link Block} nodes. Has special 52.13 + * methods to retrieve useful subsets of the context. 52.14 + */ 52.15 +public class LexicalContext implements Cloneable { 52.16 + private final Deque<Block> lexicalContext; 52.17 + 52.18 + /** 52.19 + * Creates a new empty lexical context. 52.20 + */ 52.21 + public LexicalContext() { 52.22 + lexicalContext = new ArrayDeque<>(); 52.23 + } 52.24 + 52.25 + /** 52.26 + * Pushes a new block on top of the context, making it the innermost open block. 52.27 + * @param block the new block 52.28 + */ 52.29 + public void push(Block block) { 52.30 + //new Exception(block.toString()).printStackTrace(); 52.31 + lexicalContext.push(block); 52.32 + } 52.33 + 52.34 + /** 52.35 + * Pops the innermost block off the context. 52.36 + * @param the block expected to be popped, used to detect unbalanced pushes/pops 52.37 + */ 52.38 + public void pop(Block block) { 52.39 + final Block popped = lexicalContext.pop(); 52.40 + assert popped == block; 52.41 + } 52.42 + 52.43 + /** 52.44 + * Returns an iterator over all blocks in the context, with the top block (innermost lexical context) first. 52.45 + * @return an iterator over all blocks in the context. 52.46 + */ 52.47 + public Iterator<Block> getBlocks() { 52.48 + return lexicalContext.iterator(); 52.49 + } 52.50 + 52.51 + /** 52.52 + * Returns an iterator over all functions in the context, with the top (innermost open) function first. 52.53 + * @return an iterator over all functions in the context. 52.54 + */ 52.55 + public Iterator<FunctionNode> getFunctions() { 52.56 + return new FunctionIterator(getBlocks()); 52.57 + } 52.58 + 52.59 + private static final class FunctionIterator implements Iterator<FunctionNode> { 52.60 + private final Iterator<Block> it; 52.61 + private FunctionNode next; 52.62 + 52.63 + FunctionIterator(Iterator<Block> it) { 52.64 + this.it = it; 52.65 + next = findNext(); 52.66 + } 52.67 + 52.68 + @Override 52.69 + public boolean hasNext() { 52.70 + return next != null; 52.71 + } 52.72 + 52.73 + @Override 52.74 + public FunctionNode next() { 52.75 + if(next == null) { 52.76 + throw new NoSuchElementException(); 52.77 + } 52.78 + FunctionNode lnext = next; 52.79 + next = findNext(); 52.80 + return lnext; 52.81 + } 52.82 + 52.83 + private FunctionNode findNext() { 52.84 + while(it.hasNext()) { 52.85 + final Block block = it.next(); 52.86 + if(block instanceof FunctionNode) { 52.87 + return ((FunctionNode)block); 52.88 + } 52.89 + } 52.90 + return null; 52.91 + } 52.92 + 52.93 + @Override 52.94 + public void remove() { 52.95 + throw new UnsupportedOperationException(); 52.96 + } 52.97 + } 52.98 + 52.99 + /** 52.100 + * Returns an iterator over all ancestors block of the given block, with its parent block first. 52.101 + * @param block the block whose ancestors are returned 52.102 + * @return an iterator over all ancestors block of the given block. 52.103 + */ 52.104 + public Iterator<Block> getAncestorBlocks(Block block) { 52.105 + final Iterator<Block> it = getBlocks(); 52.106 + while(it.hasNext()) { 52.107 + final Block b = it.next(); 52.108 + if(block == b) { 52.109 + return it; 52.110 + } 52.111 + } 52.112 + throw new AssertionError("Block is not on the current lexical context stack"); 52.113 + } 52.114 + 52.115 + /** 52.116 + * Returns an iterator over a block and all its ancestors blocks, with the block first. 52.117 + * @param block the block that is the starting point of the iteration. 52.118 + * @return an iterator over a block and all its ancestors. 52.119 + */ 52.120 + public Iterator<Block> getBlocks(final Block block) { 52.121 + final Iterator<Block> it = getAncestorBlocks(block); 52.122 + return new Iterator<Block>() { 52.123 + boolean blockReturned = false; 52.124 + @Override 52.125 + public boolean hasNext() { 52.126 + return it.hasNext() || !blockReturned; 52.127 + } 52.128 + @Override 52.129 + public Block next() { 52.130 + if(blockReturned) { 52.131 + return it.next(); 52.132 + } 52.133 + blockReturned = true; 52.134 + return block; 52.135 + } 52.136 + @Override 52.137 + public void remove() { 52.138 + throw new UnsupportedOperationException(); 52.139 + } 52.140 + }; 52.141 + } 52.142 + 52.143 + /** 52.144 + * Returns the closest function node to the block. If the block is itself a function, it is returned. 52.145 + * @param block the block 52.146 + * @return the function closest to the block. 52.147 + * @see #getParentFunction(Block) 52.148 + */ 52.149 + public FunctionNode getFunction(Block block) { 52.150 + if(block instanceof FunctionNode) { 52.151 + return (FunctionNode)block; 52.152 + } 52.153 + return getParentFunction(block); 52.154 + } 52.155 + 52.156 + /** 52.157 + * Returns the closest function node to the block and all its ancestor functions. If the block is itself a function, 52.158 + * it is returned too. 52.159 + * @param block the block 52.160 + * @return the closest function node to the block and all its ancestor functions. 52.161 + */ 52.162 + public Iterator<FunctionNode> getFunctions(final Block block) { 52.163 + return new FunctionIterator(getBlocks(block)); 52.164 + } 52.165 + 52.166 + /** 52.167 + * Returns the containing function of the block. If the block is itself a function, its parent function is returned. 52.168 + * @param block the block 52.169 + * @return the containing function of the block. 52.170 + * @see #getFunction(Block) 52.171 + */ 52.172 + public FunctionNode getParentFunction(Block block) { 52.173 + return getFirstFunction(getAncestorBlocks(block)); 52.174 + } 52.175 + 52.176 + private static FunctionNode getFirstFunction(Iterator<Block> it) { 52.177 + while(it.hasNext()) { 52.178 + final Block ancestor = it.next(); 52.179 + if(ancestor instanceof FunctionNode) { 52.180 + return (FunctionNode)ancestor; 52.181 + } 52.182 + } 52.183 + return null; 52.184 + } 52.185 + 52.186 + /** 52.187 + * Returns the innermost block in the context. 52.188 + * @return the innermost block in the context. 52.189 + */ 52.190 + public Block getCurrentBlock() { 52.191 + return lexicalContext.element(); 52.192 + } 52.193 + 52.194 + /** 52.195 + * Returns the innermost function in the context. 52.196 + * @return the innermost function in the context. 52.197 + */ 52.198 + public FunctionNode getCurrentFunction() { 52.199 + return getFirstFunction(getBlocks()); 52.200 + } 52.201 +}
53.1 --- a/src/jdk/nashorn/internal/ir/LineNumberNode.java Thu Mar 28 10:55:17 2013 -0700 53.2 +++ b/src/jdk/nashorn/internal/ir/LineNumberNode.java Mon Apr 01 21:42:31 2013 -0700 53.3 @@ -63,8 +63,8 @@ 53.4 53.5 @Override 53.6 public Node accept(final NodeVisitor visitor) { 53.7 - if (visitor.enter(this) != null) { 53.8 - return visitor.leave(this); 53.9 + if (visitor.enterLineNumberNode(this) != null) { 53.10 + return visitor.leaveLineNumberNode(this); 53.11 } 53.12 53.13 return this;
54.1 --- a/src/jdk/nashorn/internal/ir/LiteralNode.java Thu Mar 28 10:55:17 2013 -0700 54.2 +++ b/src/jdk/nashorn/internal/ir/LiteralNode.java Mon Apr 01 21:42:31 2013 -0700 54.3 @@ -46,7 +46,7 @@ 54.4 */ 54.5 public abstract class LiteralNode<T> extends Node implements PropertyKey { 54.6 /** Literal value */ 54.7 - protected T value; 54.8 + protected final T value; 54.9 54.10 /** 54.11 * Constructor 54.12 @@ -67,8 +67,17 @@ 54.13 * @param literalNode source node 54.14 */ 54.15 protected LiteralNode(final LiteralNode<T> literalNode) { 54.16 + this(literalNode, literalNode.value); 54.17 + } 54.18 + 54.19 + /** 54.20 + * A copy constructor with value change. 54.21 + * @param literalNode the original literal node 54.22 + * @param newValue new value for this node 54.23 + */ 54.24 + protected LiteralNode(final LiteralNode<T> literalNode, final T newValue) { 54.25 super(literalNode); 54.26 - this.value = literalNode.value; 54.27 + this.value = newValue; 54.28 } 54.29 54.30 @Override 54.31 @@ -217,8 +226,8 @@ 54.32 */ 54.33 @Override 54.34 public Node accept(final NodeVisitor visitor) { 54.35 - if (visitor.enter(this) != null) { 54.36 - return visitor.leave(this); 54.37 + if (visitor.enterLiteralNode(this) != null) { 54.38 + return visitor.leaveLiteralNode(this); 54.39 } 54.40 54.41 return this; 54.42 @@ -544,6 +553,10 @@ 54.43 super(literalNode); 54.44 } 54.45 54.46 + private NodeLiteralNode(final LiteralNode<Node> literalNode, final Node value) { 54.47 + super(literalNode, value); 54.48 + } 54.49 + 54.50 @Override 54.51 protected Node copy(final CopyState cs) { 54.52 return new NodeLiteralNode(this); 54.53 @@ -551,11 +564,14 @@ 54.54 54.55 @Override 54.56 public Node accept(final NodeVisitor visitor) { 54.57 - if (visitor.enter(this) != null) { 54.58 + if (visitor.enterLiteralNode(this) != null) { 54.59 if (value != null) { 54.60 - value = value.accept(visitor); 54.61 + final Node newValue = value.accept(visitor); 54.62 + if(value != newValue) { 54.63 + return visitor.leaveLiteralNode(new NodeLiteralNode(this, newValue)); 54.64 + } 54.65 } 54.66 - return visitor.leave(this); 54.67 + return visitor.leaveLiteralNode(this); 54.68 } 54.69 54.70 return this; 54.71 @@ -878,14 +894,14 @@ 54.72 54.73 @Override 54.74 public Node accept(final NodeVisitor visitor) { 54.75 - if (visitor.enter(this) != null) { 54.76 + if (visitor.enterLiteralNode(this) != null) { 54.77 for (int i = 0; i < value.length; i++) { 54.78 final Node element = value[i]; 54.79 if (element != null) { 54.80 value[i] = element.accept(visitor); 54.81 } 54.82 } 54.83 - return visitor.leave(this); 54.84 + return visitor.leaveLiteralNode(this); 54.85 } 54.86 return this; 54.87 }
55.1 --- a/src/jdk/nashorn/internal/ir/Location.java Thu Mar 28 10:55:17 2013 -0700 55.2 +++ b/src/jdk/nashorn/internal/ir/Location.java Mon Apr 01 21:42:31 2013 -0700 55.3 @@ -65,7 +65,11 @@ 55.4 55.5 @Override 55.6 protected Object clone() { 55.7 - return new Location(this); 55.8 + try { 55.9 + return super.clone(); 55.10 + } catch(CloneNotSupportedException e) { 55.11 + throw new AssertionError(e); 55.12 + } 55.13 } 55.14 55.15 @Override
56.1 --- a/src/jdk/nashorn/internal/ir/Node.java Thu Mar 28 10:55:17 2013 -0700 56.2 +++ b/src/jdk/nashorn/internal/ir/Node.java Mon Apr 01 21:42:31 2013 -0700 56.3 @@ -165,12 +165,19 @@ 56.4 return true; 56.5 } 56.6 56.7 - setIsResolved(); 56.8 + setIsResolved(true); 56.9 56.10 return false; 56.11 } 56.12 56.13 /** 56.14 + * Reset the resolved flag. 56.15 + */ 56.16 + public void resetResolved() { 56.17 + setIsResolved(false); 56.18 + } 56.19 + 56.20 + /** 56.21 * Is this a debug info node like LineNumberNode etc? 56.22 * 56.23 * @return true if this is a debug node 56.24 @@ -234,8 +241,7 @@ 56.25 * 56.26 * @return Deep copy of the Node. 56.27 */ 56.28 - @Override 56.29 - public final Node clone() { 56.30 + public final Node copy() { 56.31 return copy(new CopyState()); 56.32 } 56.33 56.34 @@ -349,10 +355,10 @@ 56.35 } 56.36 56.37 /** 56.38 - * Flag this node as resolved, i.e. code has been generated for it 56.39 + * Flag this node as resolved or not, i.e. code has been generated for it 56.40 */ 56.41 - public void setIsResolved() { 56.42 - this.isResolved = true; 56.43 + private void setIsResolved(boolean isResolved) { 56.44 + this.isResolved = isResolved; 56.45 } 56.46 56.47 /**
57.1 --- a/src/jdk/nashorn/internal/ir/ObjectNode.java Thu Mar 28 10:55:17 2013 -0700 57.2 +++ b/src/jdk/nashorn/internal/ir/ObjectNode.java Mon Apr 01 21:42:31 2013 -0700 57.3 @@ -28,7 +28,6 @@ 57.4 import java.util.ArrayList; 57.5 import java.util.Collections; 57.6 import java.util.List; 57.7 -import jdk.nashorn.internal.ir.annotations.Ignore; 57.8 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 57.9 import jdk.nashorn.internal.runtime.Source; 57.10 57.11 @@ -36,9 +35,6 @@ 57.12 * IR representation of an object literal. 57.13 */ 57.14 public class ObjectNode extends Node { 57.15 - /** Literal context. */ 57.16 - @Ignore 57.17 - private Block context; 57.18 57.19 /** Literal elements. */ 57.20 private final List<Node> elements; 57.21 @@ -49,13 +45,11 @@ 57.22 * @param source the source 57.23 * @param token token 57.24 * @param finish finish 57.25 - * @param context the block for this ObjectNode 57.26 * @param elements the elements used to initialize this ObjectNode 57.27 */ 57.28 - public ObjectNode(final Source source, final long token, final int finish, final Block context, final List<Node> elements) { 57.29 + public ObjectNode(final Source source, final long token, final int finish, final List<Node> elements) { 57.30 super(source, token, finish); 57.31 57.32 - this.context = context; 57.33 this.elements = elements; 57.34 } 57.35 57.36 @@ -68,7 +62,6 @@ 57.37 newElements.add(cs.existingOrCopy(element)); 57.38 } 57.39 57.40 - this.context = (Block)cs.existingOrCopy(objectNode.context); 57.41 this.elements = newElements; 57.42 } 57.43 57.44 @@ -79,16 +72,12 @@ 57.45 57.46 @Override 57.47 public Node accept(final NodeVisitor visitor) { 57.48 - if (visitor.enter(this) != null) { 57.49 - if (context != null) { 57.50 - context = (Block)context.accept(visitor); 57.51 - } 57.52 - 57.53 + if (visitor.enterObjectNode(this) != null) { 57.54 for (int i = 0, count = elements.size(); i < count; i++) { 57.55 elements.set(i, elements.get(i).accept(visitor)); 57.56 } 57.57 57.58 - return visitor.leave(this); 57.59 + return visitor.leaveObjectNode(this); 57.60 } 57.61 57.62 return this; 57.63 @@ -117,14 +106,6 @@ 57.64 } 57.65 57.66 /** 57.67 - * Get the block that is this ObjectNode's literal context 57.68 - * @return the block 57.69 - */ 57.70 - public Block getContext() { 57.71 - return context; 57.72 - } 57.73 - 57.74 - /** 57.75 * Get the elements of this literal node 57.76 * @return a list of elements 57.77 */
58.1 --- a/src/jdk/nashorn/internal/ir/PropertyNode.java Thu Mar 28 10:55:17 2013 -0700 58.2 +++ b/src/jdk/nashorn/internal/ir/PropertyNode.java Mon Apr 01 21:42:31 2013 -0700 58.3 @@ -88,7 +88,7 @@ 58.4 58.5 @Override 58.6 public Node accept(final NodeVisitor visitor) { 58.7 - if (visitor.enter(this) != null) { 58.8 + if (visitor.enterPropertyNode(this) != null) { 58.9 key = (PropertyKey)((Node)key).accept(visitor); 58.10 58.11 if (value != null) { 58.12 @@ -103,7 +103,7 @@ 58.13 setter = setter.accept(visitor); 58.14 } 58.15 58.16 - return visitor.leave(this); 58.17 + return visitor.leavePropertyNode(this); 58.18 } 58.19 58.20 return this;
59.1 --- a/src/jdk/nashorn/internal/ir/ReferenceNode.java Thu Mar 28 10:55:17 2013 -0700 59.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 59.3 @@ -1,91 +0,0 @@ 59.4 -/* 59.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 59.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 59.7 - * 59.8 - * This code is free software; you can redistribute it and/or modify it 59.9 - * under the terms of the GNU General Public License version 2 only, as 59.10 - * published by the Free Software Foundation. Oracle designates this 59.11 - * particular file as subject to the "Classpath" exception as provided 59.12 - * by Oracle in the LICENSE file that accompanied this code. 59.13 - * 59.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 59.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 59.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 59.17 - * version 2 for more details (a copy is included in the LICENSE file that 59.18 - * accompanied this code). 59.19 - * 59.20 - * You should have received a copy of the GNU General Public License version 59.21 - * 2 along with this work; if not, write to the Free Software Foundation, 59.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 59.23 - * 59.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 59.25 - * or visit www.oracle.com if you need additional information or have any 59.26 - * questions. 59.27 - */ 59.28 - 59.29 -package jdk.nashorn.internal.ir; 59.30 - 59.31 -import jdk.nashorn.internal.ir.annotations.Reference; 59.32 -import jdk.nashorn.internal.ir.visitor.NodeVisitor; 59.33 -import jdk.nashorn.internal.runtime.Source; 59.34 - 59.35 -/** 59.36 - * IR representation of a reference to another entity (function.) 59.37 - */ 59.38 -public class ReferenceNode extends Node { 59.39 - /** Node referenced. */ 59.40 - @Reference 59.41 - private final FunctionNode reference; 59.42 - 59.43 - /** 59.44 - * Constructor 59.45 - * 59.46 - * @param source the source 59.47 - * @param token token 59.48 - * @param finish finish 59.49 - * @param reference the function node to reference 59.50 - */ 59.51 - public ReferenceNode(final Source source, final long token, final int finish, final FunctionNode reference) { 59.52 - super(source, token, finish); 59.53 - 59.54 - this.reference = reference; 59.55 - } 59.56 - 59.57 - private ReferenceNode(final ReferenceNode referenceNode) { 59.58 - super(referenceNode); 59.59 - 59.60 - this.reference = referenceNode.reference; 59.61 - } 59.62 - 59.63 - @Override 59.64 - protected Node copy(final CopyState cs) { 59.65 - return new ReferenceNode(this); 59.66 - } 59.67 - 59.68 - @Override 59.69 - public Node accept(final NodeVisitor visitor) { 59.70 - if (visitor.enter(this) != null) { 59.71 - return visitor.leave(this); 59.72 - } 59.73 - 59.74 - return this; 59.75 - } 59.76 - 59.77 - @Override 59.78 - public void toString(final StringBuilder sb) { 59.79 - if (reference == null) { 59.80 - sb.append("null"); 59.81 - } else { 59.82 - reference.toString(sb); 59.83 - } 59.84 - } 59.85 - 59.86 - /** 59.87 - * Get there function node reference that this node points tp 59.88 - * @return a function node reference 59.89 - */ 59.90 - public FunctionNode getReference() { 59.91 - return reference; 59.92 - } 59.93 - 59.94 -}
60.1 --- a/src/jdk/nashorn/internal/ir/ReturnNode.java Thu Mar 28 10:55:17 2013 -0700 60.2 +++ b/src/jdk/nashorn/internal/ir/ReturnNode.java Mon Apr 01 21:42:31 2013 -0700 60.3 @@ -100,12 +100,12 @@ 60.4 60.5 @Override 60.6 public Node accept(final NodeVisitor visitor) { 60.7 - if (visitor.enter(this) != null) { 60.8 + if (visitor.enterReturnNode(this) != null) { 60.9 if (expression != null) { 60.10 expression = expression.accept(visitor); 60.11 } 60.12 60.13 - return visitor.leave(this); 60.14 + return visitor.leaveReturnNode(this); 60.15 } 60.16 60.17 return this;
61.1 --- a/src/jdk/nashorn/internal/ir/RuntimeNode.java Thu Mar 28 10:55:17 2013 -0700 61.2 +++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java Mon Apr 01 21:42:31 2013 -0700 61.3 @@ -38,7 +38,7 @@ 61.4 * IR representation for a runtime call. 61.5 * 61.6 */ 61.7 -public class RuntimeNode extends Node implements TypeOverride { 61.8 +public class RuntimeNode extends Node implements TypeOverride<RuntimeNode> { 61.9 61.10 /** 61.11 * Request enum used for meta-information about the runtime request 61.12 @@ -393,8 +393,9 @@ 61.13 } 61.14 61.15 @Override 61.16 - public void setType(final Type type) { 61.17 + public RuntimeNode setType(final Type type) { 61.18 this.callSiteType = type; 61.19 + return this; 61.20 } 61.21 61.22 @Override 61.23 @@ -408,12 +409,12 @@ 61.24 61.25 @Override 61.26 public Node accept(final NodeVisitor visitor) { 61.27 - if (visitor.enter(this) != null) { 61.28 + if (visitor.enterRuntimeNode(this) != null) { 61.29 for (int i = 0, count = args.size(); i < count; i++) { 61.30 args.set(i, args.get(i).accept(visitor)); 61.31 } 61.32 61.33 - return visitor.leave(this); 61.34 + return visitor.leaveRuntimeNode(this); 61.35 } 61.36 61.37 return this;
62.1 --- a/src/jdk/nashorn/internal/ir/SplitNode.java Thu Mar 28 10:55:17 2013 -0700 62.2 +++ b/src/jdk/nashorn/internal/ir/SplitNode.java Mon Apr 01 21:42:31 2013 -0700 62.3 @@ -108,10 +108,10 @@ 62.4 visitor.setCurrentMethodEmitter(getMethodEmitter()); 62.5 62.6 try { 62.7 - if (visitor.enter(this) != null) { 62.8 + if (visitor.enterSplitNode(this) != null) { 62.9 body = body.accept(visitor); 62.10 62.11 - return visitor.leave(this); 62.12 + return visitor.leaveSplitNode(this); 62.13 } 62.14 } finally { 62.15 visitor.setCurrentCompileUnit(saveCompileUnit);
63.1 --- a/src/jdk/nashorn/internal/ir/SwitchNode.java Thu Mar 28 10:55:17 2013 -0700 63.2 +++ b/src/jdk/nashorn/internal/ir/SwitchNode.java Mon Apr 01 21:42:31 2013 -0700 63.3 @@ -85,7 +85,7 @@ 63.4 63.5 @Override 63.6 public Node accept(final NodeVisitor visitor) { 63.7 - if (visitor.enter(this) != null) { 63.8 + if (visitor.enterSwitchNode(this) != null) { 63.9 expression = expression.accept(visitor); 63.10 63.11 for (int i = 0, count = cases.size(); i < count; i++) { 63.12 @@ -94,7 +94,7 @@ 63.13 63.14 //the default case is in the cases list and should not be explicitly traversed! 63.15 63.16 - return visitor.leave(this); 63.17 + return visitor.leaveSwitchNode(this); 63.18 } 63.19 63.20 return this;
64.1 --- a/src/jdk/nashorn/internal/ir/Symbol.java Thu Mar 28 10:55:17 2013 -0700 64.2 +++ b/src/jdk/nashorn/internal/ir/Symbol.java Mon Apr 01 21:42:31 2013 -0700 64.3 @@ -38,31 +38,31 @@ 64.4 */ 64.5 64.6 public final class Symbol implements Comparable<Symbol> { 64.7 - /** Symbol flags. Kind ordered by precedence. */ 64.8 - public static final int IS_TEMP = 0b0000_0001; 64.9 + /** Symbol kinds. Kind ordered by precedence. */ 64.10 + public static final int IS_TEMP = 1; 64.11 /** Is this Global */ 64.12 - public static final int IS_GLOBAL = 0b0000_0010; 64.13 + public static final int IS_GLOBAL = 2; 64.14 /** Is this a variable */ 64.15 - public static final int IS_VAR = 0b0000_0011; 64.16 + public static final int IS_VAR = 3; 64.17 /** Is this a parameter */ 64.18 - public static final int IS_PARAM = 0b0000_0100; 64.19 + public static final int IS_PARAM = 4; 64.20 /** Is this a constant */ 64.21 - public static final int IS_CONSTANT = 0b0000_0101; 64.22 - 64.23 - static final int KINDMASK = 0b0000_1111; 64.24 + public static final int IS_CONSTANT = 5; 64.25 + /** Mask for kind flags */ 64.26 + public static final int KINDMASK = (1 << 3) - 1; // Kinds are represented by lower three bits 64.27 64.28 /** Is this scope */ 64.29 - public static final int IS_SCOPE = 0b0000_0001_0000; 64.30 + public static final int IS_SCOPE = 1 << 4; 64.31 /** Is this a this symbol */ 64.32 - public static final int IS_THIS = 0b0000_0010_0000; 64.33 + public static final int IS_THIS = 1 << 5; 64.34 /** Can this symbol ever be undefined */ 64.35 - public static final int CAN_BE_UNDEFINED = 0b0000_0100_0000; 64.36 + public static final int CAN_BE_UNDEFINED = 1 << 6; 64.37 /** Can this symbol ever have primitive types */ 64.38 - public static final int CAN_BE_PRIMITIVE = 0b0000_1000_0000; 64.39 + public static final int CAN_BE_PRIMITIVE = 1 << 7; 64.40 /** Is this a let */ 64.41 - public static final int IS_LET = 0b0001_0000_0000; 64.42 + public static final int IS_LET = 1 << 8; 64.43 /** Is this an internal symbol, never represented explicitly in source code */ 64.44 - public static final int IS_INTERNAL = 0b0010_0000_0000; 64.45 + public static final int IS_INTERNAL = 1 << 9; 64.46 64.47 /** Null or name identifying symbol. */ 64.48 private final String name; 64.49 @@ -269,15 +269,6 @@ 64.50 return type.isCategory2() ? 2 : 1; 64.51 } 64.52 64.53 - /** 64.54 - * Return the defining function (scope.) 64.55 - * 64.56 - * @return Defining function. 64.57 - */ 64.58 - public FunctionNode findFunction() { 64.59 - return block != null ? block.getFunction() : null; 64.60 - } 64.61 - 64.62 @Override 64.63 public boolean equals(final Object other) { 64.64 if (!(other instanceof Symbol)) { 64.65 @@ -487,27 +478,6 @@ 64.66 } 64.67 64.68 /** 64.69 - * Check if this symbol can be accessed directly with a putfield or getfield or dynamic load 64.70 - * 64.71 - * @param currentFunction function to check for fast scope 64.72 - * @return true if fast scope 64.73 - */ 64.74 - public boolean isFastScope(final FunctionNode currentFunction) { 64.75 - if (!isScope() || !block.needsScope()) { 64.76 - return false; 64.77 - } 64.78 - // Allow fast scope access if no parent function contains with or eval 64.79 - FunctionNode func = currentFunction; 64.80 - while (func != null) { 64.81 - if (func.hasWith() || func.hasEval()) { 64.82 - return false; 64.83 - } 64.84 - func = func.findParentFunction(); 64.85 - } 64.86 - return true; 64.87 - } 64.88 - 64.89 - /** 64.90 * Get the block in which the symbol is defined 64.91 * @return a block 64.92 */ 64.93 @@ -651,7 +621,7 @@ 64.94 * @return true if this this is a global scope symbol 64.95 */ 64.96 public boolean isTopLevel() { 64.97 - return block instanceof FunctionNode && ((FunctionNode) block).isScript(); 64.98 + return block instanceof FunctionNode && ((FunctionNode) block).isProgram(); 64.99 } 64.100 64.101
65.1 --- a/src/jdk/nashorn/internal/ir/TernaryNode.java Thu Mar 28 10:55:17 2013 -0700 65.2 +++ b/src/jdk/nashorn/internal/ir/TernaryNode.java Mon Apr 01 21:42:31 2013 -0700 65.3 @@ -77,11 +77,11 @@ 65.4 65.5 @Override 65.6 public Node accept(final NodeVisitor visitor) { 65.7 - if (visitor.enter(this) != null) { 65.8 - lhs = lhs.accept(visitor); 65.9 - rhs = rhs.accept(visitor); 65.10 - third = third.accept(visitor); 65.11 - return visitor.leave(this); 65.12 + if (visitor.enterTernaryNode(this) != null) { 65.13 + final Node newLhs = lhs().accept(visitor); 65.14 + final Node newRhs = rhs().accept(visitor); 65.15 + final Node newThird = third.accept(visitor); 65.16 + return visitor.leaveTernaryNode((TernaryNode)setThird(newThird).setLHS(newLhs).setRHS(newRhs)); 65.17 } 65.18 65.19 return this; 65.20 @@ -133,8 +133,12 @@ 65.21 /** 65.22 * Reset the "third" node for this ternary expression, i.e. "z" in x ? y : z 65.23 * @param third a node 65.24 + * @return a node equivalent to this one except for the requested change. 65.25 */ 65.26 - public void setThird(final Node third) { 65.27 - this.third = third; 65.28 + public TernaryNode setThird(final Node third) { 65.29 + if(this.third == third) return this; 65.30 + final TernaryNode n = (TernaryNode)clone(); 65.31 + n.third = third; 65.32 + return n; 65.33 } 65.34 }
66.1 --- a/src/jdk/nashorn/internal/ir/ThrowNode.java Thu Mar 28 10:55:17 2013 -0700 66.2 +++ b/src/jdk/nashorn/internal/ir/ThrowNode.java Mon Apr 01 21:42:31 2013 -0700 66.3 @@ -75,9 +75,9 @@ 66.4 */ 66.5 @Override 66.6 public Node accept(final NodeVisitor visitor) { 66.7 - if (visitor.enter(this) != null) { 66.8 + if (visitor.enterThrowNode(this) != null) { 66.9 setExpression(expression.accept(visitor)); 66.10 - return visitor.leave(this); 66.11 + return visitor.leaveThrowNode(this); 66.12 } 66.13 66.14 return this;
67.1 --- a/src/jdk/nashorn/internal/ir/TryNode.java Thu Mar 28 10:55:17 2013 -0700 67.2 +++ b/src/jdk/nashorn/internal/ir/TryNode.java Mon Apr 01 21:42:31 2013 -0700 67.3 @@ -101,7 +101,7 @@ 67.4 */ 67.5 @Override 67.6 public Node accept(final NodeVisitor visitor) { 67.7 - if (visitor.enter(this) != null) { 67.8 + if (visitor.enterTryNode(this) != null) { 67.9 // Need to do first for termination analysis. 67.10 if (finallyBody != null) { 67.11 finallyBody = (Block)finallyBody.accept(visitor); 67.12 @@ -115,7 +115,7 @@ 67.13 } 67.14 this.catchBlocks = newCatchBlocks; 67.15 67.16 - return visitor.leave(this); 67.17 + return visitor.leaveTryNode(this); 67.18 } 67.19 67.20 return this; 67.21 @@ -155,6 +155,15 @@ 67.22 } 67.23 67.24 /** 67.25 + * Returns true if the specified block is the body of this try block, or any of its catch blocks. 67.26 + * @param block the block 67.27 + * @return true if the specified block is the body of this try block, or any of its catch blocks. 67.28 + */ 67.29 + public boolean isChildBlock(Block block) { 67.30 + return body == block || catchBlocks.contains(block); 67.31 + } 67.32 + 67.33 + /** 67.34 * Get the catch blocks for this try block 67.35 * @return a list of blocks 67.36 */
68.1 --- a/src/jdk/nashorn/internal/ir/TypeOverride.java Thu Mar 28 10:55:17 2013 -0700 68.2 +++ b/src/jdk/nashorn/internal/ir/TypeOverride.java Mon Apr 01 21:42:31 2013 -0700 68.3 @@ -36,15 +36,17 @@ 68.4 * by using JSType.toInt32. Especially in scenarios where the field is already stored 68.5 * as a primitive, this will be much faster than the "object is all I see" scope 68.6 * available in the method 68.7 + * @param <T> the type of the node implementing the interface 68.8 */ 68.9 68.10 -public interface TypeOverride { 68.11 +public interface TypeOverride<T extends Node> { 68.12 /** 68.13 * Set the override type 68.14 * 68.15 * @param type the type 68.16 + * @return a node equivalent to this one except for the requested change. 68.17 */ 68.18 - public void setType(final Type type); 68.19 + public T setType(final Type type); 68.20 68.21 /** 68.22 * Returns true if this node can have a callsite override, e.g. all scope ident nodes
69.1 --- a/src/jdk/nashorn/internal/ir/UnaryNode.java Thu Mar 28 10:55:17 2013 -0700 69.2 +++ b/src/jdk/nashorn/internal/ir/UnaryNode.java Mon Apr 01 21:42:31 2013 -0700 69.3 @@ -41,7 +41,7 @@ 69.4 */ 69.5 public class UnaryNode extends Node implements Assignment<Node> { 69.6 /** Right hand side argument. */ 69.7 - protected Node rhs; 69.8 + private Node rhs; 69.9 69.10 /** 69.11 * Constructor 69.12 @@ -104,6 +104,11 @@ 69.13 } 69.14 69.15 @Override 69.16 + public Node setAssignmentDest(Node n) { 69.17 + return setRHS(n); 69.18 + } 69.19 + 69.20 + @Override 69.21 public Node getAssignmentSource() { 69.22 return getAssignmentDest(); 69.23 } 69.24 @@ -132,9 +137,8 @@ 69.25 */ 69.26 @Override 69.27 public Node accept(final NodeVisitor visitor) { 69.28 - if (visitor.enter(this) != null) { 69.29 - rhs = rhs.accept(visitor); 69.30 - return visitor.leave(this); 69.31 + if (visitor.enterUnaryNode(this) != null) { 69.32 + return visitor.leaveUnaryNode(setRHS(rhs.accept(visitor))); 69.33 } 69.34 69.35 return this; 69.36 @@ -152,9 +156,9 @@ 69.37 69.38 if (isConvert) { 69.39 convertPos = sb.length(); 69.40 - sb.append("(("); 69.41 + sb.append("("); 69.42 sb.append(getType()); 69.43 - sb.append(")"); 69.44 + sb.append(")("); 69.45 } 69.46 69.47 if (!isPostfix && !isConvert) { 69.48 @@ -191,8 +195,6 @@ 69.49 sb.setCharAt(convertPos, ' '); 69.50 } 69.51 } 69.52 - 69.53 - //TODO - conversions still have too many parenthesis - makes --print-lower-parse hard to read 69.54 } 69.55 69.56 /** 69.57 @@ -214,10 +216,12 @@ 69.58 * @see BinaryNode 69.59 * 69.60 * @param rhs right hand side or expression node 69.61 + * @return a node equivalent to this one except for the requested change. 69.62 */ 69.63 - public void setRHS(final Node rhs) { 69.64 - this.rhs = rhs; 69.65 + public UnaryNode setRHS(final Node rhs) { 69.66 + if(this.rhs == rhs) return this; 69.67 + final UnaryNode n = (UnaryNode)clone(); 69.68 + n.rhs = rhs; 69.69 + return n; 69.70 } 69.71 - 69.72 - 69.73 }
70.1 --- a/src/jdk/nashorn/internal/ir/VarNode.java Thu Mar 28 10:55:17 2013 -0700 70.2 +++ b/src/jdk/nashorn/internal/ir/VarNode.java Mon Apr 01 21:42:31 2013 -0700 70.3 @@ -38,8 +38,8 @@ 70.4 /** Initialization expression. */ 70.5 private Node init; 70.6 70.7 - /** Is this a function var node */ 70.8 - private boolean isFunctionVarNode; 70.9 + /** Is this a var statement (as opposed to a "var" in a for loop statement) */ 70.10 + private final boolean isStatement; 70.11 70.12 /** 70.13 * Constructor 70.14 @@ -51,20 +51,34 @@ 70.15 * @param init init node or null if just a declaration 70.16 */ 70.17 public VarNode(final Source source, final long token, final int finish, final IdentNode name, final Node init) { 70.18 + this(source, token, finish, name, init, true); 70.19 + } 70.20 + 70.21 + /** 70.22 + * Constructor 70.23 + * 70.24 + * @param source the source 70.25 + * @param token token 70.26 + * @param finish finish 70.27 + * @param name name of variable 70.28 + * @param init init node or null if just a declaration 70.29 + * @param isStatement if this is a var statement (true), or a for-loop initializer (false) 70.30 + */ 70.31 + public VarNode(final Source source, final long token, final int finish, final IdentNode name, final Node init, boolean isStatement) { 70.32 super(source, token, finish); 70.33 70.34 - this.name = name; 70.35 + this.name = init == null ? name : name.setIsInitializedHere(); 70.36 this.init = init; 70.37 - if (init != null) { 70.38 - this.name.setIsInitializedHere(); 70.39 - } 70.40 + this.isStatement = isStatement; 70.41 } 70.42 70.43 + 70.44 private VarNode(final VarNode varNode, final CopyState cs) { 70.45 super(varNode); 70.46 70.47 this.name = (IdentNode)cs.existingOrCopy(varNode.name); 70.48 this.init = cs.existingOrCopy(varNode.init); 70.49 + this.isStatement = varNode.isStatement; 70.50 } 70.51 70.52 @Override 70.53 @@ -83,6 +97,11 @@ 70.54 } 70.55 70.56 @Override 70.57 + public Node setAssignmentDest(IdentNode n) { 70.58 + return setName(n); 70.59 + } 70.60 + 70.61 + @Override 70.62 public Node getAssignmentSource() { 70.63 return isAssignment() ? getInit() : null; 70.64 } 70.65 @@ -127,16 +146,19 @@ 70.66 */ 70.67 @Override 70.68 public Node accept(final NodeVisitor visitor) { 70.69 - if (visitor.enter(this) != null) { 70.70 - name = (IdentNode)name.accept(visitor); 70.71 - 70.72 - if (init != null) { 70.73 - init = init.accept(visitor); 70.74 + if (visitor.enterVarNode(this) != null) { 70.75 + final IdentNode newName = (IdentNode)name.accept(visitor); 70.76 + final Node newInit = init == null ? null : init.accept(visitor); 70.77 + final VarNode newThis; 70.78 + if(name != newName || init != newInit) { 70.79 + newThis = (VarNode)clone(); 70.80 + newThis.init = newInit; 70.81 + newThis.name = newInit == null ? newName : newName.setIsInitializedHere(); 70.82 + } else { 70.83 + newThis = this; 70.84 } 70.85 - 70.86 - return visitor.leave(this); 70.87 + return visitor.leaveVarNode(newThis); 70.88 } 70.89 - 70.90 return this; 70.91 } 70.92 70.93 @@ -162,9 +184,13 @@ 70.94 /** 70.95 * Reset the initialization expression 70.96 * @param init new initialization expression 70.97 + * @return a node equivalent to this one except for the requested change. 70.98 */ 70.99 - public void setInit(final Node init) { 70.100 - this.init = init; 70.101 + public VarNode setInit(final Node init) { 70.102 + if(this.init == init) return this; 70.103 + final VarNode n = (VarNode)clone(); 70.104 + n.init = init; 70.105 + return n; 70.106 } 70.107 70.108 /** 70.109 @@ -179,30 +205,26 @@ 70.110 * Reset the identifier for this VarNode 70.111 * @param name new IdentNode representing the variable being set or declared 70.112 */ 70.113 - public void setName(final IdentNode name) { 70.114 - this.name = name; 70.115 + private VarNode setName(final IdentNode name) { 70.116 + if(this.name == name) return this; 70.117 + final VarNode n = (VarNode)clone(); 70.118 + n.name = name; 70.119 + return n; 70.120 } 70.121 70.122 /** 70.123 - * Check if this is a virtual assignment of a function node. Function nodes declared 70.124 - * with a name are hoisted to the top of the scope and appear as symbols too. This is 70.125 - * implemented by representing them as virtual VarNode assignments added to the code 70.126 - * during lowering 70.127 - * 70.128 - * @see FunctionNode 70.129 - * 70.130 - * @return true if this is a virtual function declaration 70.131 + * Returns true if this is a var statement (as opposed to a var initializer in a for loop). 70.132 + * @return true if this is a var statement (as opposed to a var initializer in a for loop). 70.133 */ 70.134 - public boolean isFunctionVarNode() { 70.135 - return isFunctionVarNode; 70.136 + public boolean isStatement() { 70.137 + return isStatement; 70.138 } 70.139 70.140 /** 70.141 - * Flag this var node as a virtual function var node assignment as described in 70.142 - * {@link VarNode#isFunctionVarNode()} 70.143 + * Returns true if this is a function declaration. 70.144 + * @return true if this is a function declaration. 70.145 */ 70.146 - public void setIsFunctionVarNode() { 70.147 - this.isFunctionVarNode = true; 70.148 + public boolean isFunctionDeclaration() { 70.149 + return init instanceof FunctionNode && ((FunctionNode)init).isDeclared(); 70.150 } 70.151 - 70.152 }
71.1 --- a/src/jdk/nashorn/internal/ir/WhileNode.java Thu Mar 28 10:55:17 2013 -0700 71.2 +++ b/src/jdk/nashorn/internal/ir/WhileNode.java Mon Apr 01 21:42:31 2013 -0700 71.3 @@ -88,11 +88,11 @@ 71.4 */ 71.5 @Override 71.6 public Node accept(final NodeVisitor visitor) { 71.7 - if (visitor.enter(this) != null) { 71.8 + if (visitor.enterWhileNode(this) != null) { 71.9 test = test.accept(visitor); 71.10 body = (Block)body.accept(visitor); 71.11 71.12 - return visitor.leave(this); 71.13 + return visitor.leaveWhileNode(this); 71.14 } 71.15 return this; 71.16 }
72.1 --- a/src/jdk/nashorn/internal/ir/WithNode.java Thu Mar 28 10:55:17 2013 -0700 72.2 +++ b/src/jdk/nashorn/internal/ir/WithNode.java Mon Apr 01 21:42:31 2013 -0700 72.3 @@ -73,10 +73,10 @@ 72.4 */ 72.5 @Override 72.6 public Node accept(final NodeVisitor visitor) { 72.7 - if (visitor.enter(this) != null) { 72.8 + if (visitor.enterWithNode(this) != null) { 72.9 expression = expression.accept(visitor); 72.10 body = (Block)body.accept(visitor); 72.11 - return visitor.leave(this); 72.12 + return visitor.leaveWithNode(this); 72.13 } 72.14 72.15 return this;
73.1 --- a/src/jdk/nashorn/internal/ir/annotations/ChildNode.java Thu Mar 28 10:55:17 2013 -0700 73.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 73.3 @@ -1,42 +0,0 @@ 73.4 -/* 73.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 73.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 73.7 - * 73.8 - * This code is free software; you can redistribute it and/or modify it 73.9 - * under the terms of the GNU General Public License version 2 only, as 73.10 - * published by the Free Software Foundation. Oracle designates this 73.11 - * particular file as subject to the "Classpath" exception as provided 73.12 - * by Oracle in the LICENSE file that accompanied this code. 73.13 - * 73.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 73.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 73.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 73.17 - * version 2 for more details (a copy is included in the LICENSE file that 73.18 - * accompanied this code). 73.19 - * 73.20 - * You should have received a copy of the GNU General Public License version 73.21 - * 2 along with this work; if not, write to the Free Software Foundation, 73.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 73.23 - * 73.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 73.25 - * or visit www.oracle.com if you need additional information or have any 73.26 - * questions. 73.27 - */ 73.28 - 73.29 -package jdk.nashorn.internal.ir.annotations; 73.30 - 73.31 -import java.lang.annotation.Retention; 73.32 -import java.lang.annotation.RetentionPolicy; 73.33 - 73.34 -/** 73.35 - * This is a child node, a real node, not a reference, to an IR node that should 73.36 - * be traversed. 73.37 - * <p> 73.38 - * TODO Currently not in use. Would make e.g. accept methods simple and unified 73.39 - * @see jdk.nashorn.internal.ir.Node 73.40 - */ 73.41 -@Retention(value=RetentionPolicy.RUNTIME) 73.42 -public @interface ChildNode { 73.43 - /** order of traversal compared to other children */ 73.44 - public int order() default -1; 73.45 -}
74.1 --- a/src/jdk/nashorn/internal/ir/annotations/ParentNode.java Thu Mar 28 10:55:17 2013 -0700 74.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 74.3 @@ -1,44 +0,0 @@ 74.4 -/* 74.5 - * Copyright (c) 2010, 2013, 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.annotations; 74.30 - 74.31 -import java.lang.annotation.Retention; 74.32 -import java.lang.annotation.RetentionPolicy; 74.33 - 74.34 -/** 74.35 - * Signifies a parent of a node, i.e. node that should not be traversed if we 74.36 - * go down the AST. In automatic parsing this can be handled by @Reference 74.37 - * annotations instead, as all parents are references. 74.38 - * <p> 74.39 - * TODO The use case is automating and creating one implementation of something like 74.40 - * Node.getParent() 74.41 - * 74.42 - * @see jdk.nashorn.internal.ir.Node 74.43 - */ 74.44 -@Retention(value=RetentionPolicy.RUNTIME) 74.45 -public @interface ParentNode { 74.46 - // EMPTY 74.47 -}
75.1 --- a/src/jdk/nashorn/internal/ir/annotations/Reference.java Thu Mar 28 10:55:17 2013 -0700 75.2 +++ b/src/jdk/nashorn/internal/ir/annotations/Reference.java Mon Apr 01 21:42:31 2013 -0700 75.3 @@ -33,7 +33,6 @@ 75.4 * AST traversal and cloning. Cloning currently as a rule uses 75.5 * existingOrSame for references and otherwise existingOrCopy 75.6 * <p> 75.7 - * TODO this could probably be automated using the @Reference annotation. 75.8 */ 75.9 75.10 @Retention(value=RetentionPolicy.RUNTIME)
76.1 --- a/src/jdk/nashorn/internal/ir/debug/ASTWriter.java Thu Mar 28 10:55:17 2013 -0700 76.2 +++ b/src/jdk/nashorn/internal/ir/debug/ASTWriter.java Mon Apr 01 21:42:31 2013 -0700 76.3 @@ -27,6 +27,7 @@ 76.4 76.5 import java.lang.reflect.Field; 76.6 import java.util.ArrayDeque; 76.7 +import java.util.ArrayList; 76.8 import java.util.Collection; 76.9 import java.util.Deque; 76.10 import java.util.Iterator; 76.11 @@ -36,10 +37,10 @@ 76.12 import jdk.nashorn.internal.ir.Node; 76.13 import jdk.nashorn.internal.ir.TernaryNode; 76.14 import jdk.nashorn.internal.ir.annotations.Ignore; 76.15 -import jdk.nashorn.internal.ir.annotations.ParentNode; 76.16 import jdk.nashorn.internal.ir.annotations.Reference; 76.17 import jdk.nashorn.internal.parser.Token; 76.18 import jdk.nashorn.internal.runtime.Context; 76.19 +import jdk.nashorn.internal.runtime.Debug; 76.20 76.21 /** 76.22 * AST-as-text visualizer. Sometimes you want tree form and not source 76.23 @@ -47,7 +48,6 @@ 76.24 * 76.25 * see the flags --print-ast and --print-ast-lower 76.26 */ 76.27 - 76.28 public final class ASTWriter { 76.29 /** Root node from which to start the traversal */ 76.30 private final Node root; 76.31 @@ -71,12 +71,22 @@ 76.32 @Override 76.33 public String toString() { 76.34 final StringBuilder sb = new StringBuilder(); 76.35 - printAST(sb, null, "root", root, 0); 76.36 + printAST(sb, null, null, "root", root, 0); 76.37 return sb.toString(); 76.38 } 76.39 76.40 + /** 76.41 + * Return the visited nodes in an ordered list 76.42 + * @return the list of nodes in order 76.43 + */ 76.44 + public Node[] toArray() { 76.45 + final List<Node> preorder = new ArrayList<>(); 76.46 + printAST(new StringBuilder(), preorder, null, "root", root, 0); 76.47 + return preorder.toArray(new Node[preorder.size()]); 76.48 + } 76.49 + 76.50 @SuppressWarnings("unchecked") 76.51 - private void printAST(final StringBuilder sb, final Field field, final String name, final Node node, final int indent) { 76.52 + private void printAST(final StringBuilder sb, final List<Node> preorder, final Field field, final String name, final Node node, final int indent) { 76.53 ASTWriter.indent(sb, indent); 76.54 if (node == null) { 76.55 sb.append("[Object "); 76.56 @@ -85,13 +95,23 @@ 76.57 return; 76.58 } 76.59 76.60 + if (preorder != null) { 76.61 + preorder.add(node); 76.62 + } 76.63 + 76.64 final boolean isReference = field != null && field.getAnnotation(Reference.class) != null; 76.65 76.66 Class<?> clazz = node.getClass(); 76.67 String type = clazz.getName(); 76.68 76.69 type = type.substring(type.lastIndexOf('.') + 1, type.length()); 76.70 -// type += "@" + Debug.id(node) + "#" + node.getSymbol(); 76.71 + if (isReference) { 76.72 + type = "ref: " + type; 76.73 + } 76.74 + type += "@" + Debug.id(node); 76.75 + if (node.getSymbol() != null) { 76.76 + type += "#" + node.getSymbol(); 76.77 + } 76.78 76.79 final List<Field> children = new LinkedList<>(); 76.80 76.81 @@ -153,9 +173,7 @@ 76.82 append('\n'); 76.83 76.84 for (final Field child : children) { 76.85 - if (child.getAnnotation(ParentNode.class) != null) { 76.86 - continue; 76.87 - } else if (child.getAnnotation(Ignore.class) != null) { 76.88 + if (child.getAnnotation(Ignore.class) != null) { 76.89 continue; 76.90 } 76.91 76.92 @@ -168,7 +186,7 @@ 76.93 } 76.94 76.95 if (value instanceof Node) { 76.96 - printAST(sb, child, child.getName(), (Node)value, indent + 1); 76.97 + printAST(sb, preorder, child, child.getName(), (Node)value, indent + 1); 76.98 } else if (value instanceof Collection) { 76.99 int pos = 0; 76.100 ASTWriter.indent(sb, indent + 1); 76.101 @@ -180,7 +198,7 @@ 76.102 append('\n'); 76.103 76.104 for (final Node member : (Collection<Node>)value) { 76.105 - printAST(sb, child, child.getName() + "[" + pos++ + "]", member, indent + 2); 76.106 + printAST(sb, preorder, child, child.getName() + "[" + pos++ + "]", member, indent + 2); 76.107 } 76.108 } 76.109 }
77.1 --- a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java Thu Mar 28 10:55:17 2013 -0700 77.2 +++ b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java Mon Apr 01 21:42:31 2013 -0700 77.3 @@ -112,7 +112,7 @@ 77.4 } 77.5 77.6 @Override 77.7 - public Node enter(final AccessNode accessNode) { 77.8 + public Node enterAccessNode(final AccessNode accessNode) { 77.9 enterDefault(accessNode); 77.10 77.11 type("MemberExpression"); 77.12 @@ -132,7 +132,7 @@ 77.13 } 77.14 77.15 @Override 77.16 - public Node enter(final Block block) { 77.17 + public Node enterBlock(final Block block) { 77.18 enterDefault(block); 77.19 77.20 type("BlockStatement"); 77.21 @@ -154,7 +154,7 @@ 77.22 } 77.23 77.24 @Override 77.25 - public Node enter(final BinaryNode binaryNode) { 77.26 + public Node enterBinaryNode(final BinaryNode binaryNode) { 77.27 enterDefault(binaryNode); 77.28 77.29 final String name; 77.30 @@ -183,7 +183,7 @@ 77.31 } 77.32 77.33 @Override 77.34 - public Node enter(final BreakNode breakNode) { 77.35 + public Node enterBreakNode(final BreakNode breakNode) { 77.36 enterDefault(breakNode); 77.37 77.38 type("BreakStatement"); 77.39 @@ -201,7 +201,7 @@ 77.40 } 77.41 77.42 @Override 77.43 - public Node enter(final CallNode callNode) { 77.44 + public Node enterCallNode(final CallNode callNode) { 77.45 enterDefault(callNode); 77.46 77.47 type("CallExpression"); 77.48 @@ -217,7 +217,7 @@ 77.49 } 77.50 77.51 @Override 77.52 - public Node enter(final CaseNode caseNode) { 77.53 + public Node enterCaseNode(final CaseNode caseNode) { 77.54 enterDefault(caseNode); 77.55 77.56 type("SwitchCase"); 77.57 @@ -238,7 +238,7 @@ 77.58 } 77.59 77.60 @Override 77.61 - public Node enter(final CatchNode catchNode) { 77.62 + public Node enterCatchNode(final CatchNode catchNode) { 77.63 enterDefault(catchNode); 77.64 77.65 type("CatchClause"); 77.66 @@ -264,7 +264,7 @@ 77.67 } 77.68 77.69 @Override 77.70 - public Node enter(final ContinueNode continueNode) { 77.71 + public Node enterContinueNode(final ContinueNode continueNode) { 77.72 enterDefault(continueNode); 77.73 77.74 type("ContinueStatement"); 77.75 @@ -282,7 +282,7 @@ 77.76 } 77.77 77.78 @Override 77.79 - public Node enter(final DoWhileNode doWhileNode) { 77.80 + public Node enterDoWhileNode(final DoWhileNode doWhileNode) { 77.81 enterDefault(doWhileNode); 77.82 77.83 type("DoWhileStatement"); 77.84 @@ -299,7 +299,7 @@ 77.85 } 77.86 77.87 @Override 77.88 - public Node enter(final EmptyNode emptyNode) { 77.89 + public Node enterEmptyNode(final EmptyNode emptyNode) { 77.90 enterDefault(emptyNode); 77.91 77.92 type("EmptyStatement"); 77.93 @@ -308,7 +308,7 @@ 77.94 } 77.95 77.96 @Override 77.97 - public Node enter(final ExecuteNode executeNode) { 77.98 + public Node enterExecuteNode(final ExecuteNode executeNode) { 77.99 enterDefault(executeNode); 77.100 77.101 type("ExpressionStatement"); 77.102 @@ -321,7 +321,7 @@ 77.103 } 77.104 77.105 @Override 77.106 - public Node enter(final ForNode forNode) { 77.107 + public Node enterForNode(final ForNode forNode) { 77.108 enterDefault(forNode); 77.109 77.110 if (forNode.isForIn() || (forNode.isForEach() && forNode.getInit() != null)) { 77.111 @@ -384,14 +384,14 @@ 77.112 } 77.113 77.114 @Override 77.115 - public Node enter(final FunctionNode functionNode) { 77.116 + public Node enterFunctionNode(final FunctionNode functionNode) { 77.117 enterDefault(functionNode); 77.118 77.119 - final boolean program = functionNode.isScript(); 77.120 + final boolean program = functionNode.isProgram(); 77.121 final String name; 77.122 if (program) { 77.123 name = "Program"; 77.124 - } else if (functionNode.isStatement()) { 77.125 + } else if (functionNode.isDeclared()) { 77.126 name = "FunctionDeclaration"; 77.127 } else { 77.128 name = "FunctionExpression"; 77.129 @@ -419,20 +419,11 @@ 77.130 } 77.131 77.132 // body consists of nested functions and statements 77.133 - final List<FunctionNode> funcs = functionNode.getFunctions(); 77.134 final List<Node> stats = functionNode.getStatements(); 77.135 - final int size = stats.size() + funcs.size(); 77.136 + final int size = stats.size(); 77.137 int idx = 0; 77.138 arrayStart("body"); 77.139 77.140 - for (final Node func : funcs) { 77.141 - func.accept(this); 77.142 - if (idx != (size - 1)) { 77.143 - comma(); 77.144 - } 77.145 - idx++; 77.146 - } 77.147 - 77.148 for (final Node stat : stats) { 77.149 if (! stat.isDebug()) { 77.150 stat.accept(this); 77.151 @@ -448,7 +439,7 @@ 77.152 } 77.153 77.154 @Override 77.155 - public Node enter(final IdentNode identNode) { 77.156 + public Node enterIdentNode(final IdentNode identNode) { 77.157 enterDefault(identNode); 77.158 77.159 final String name = identNode.getName(); 77.160 @@ -464,7 +455,7 @@ 77.161 } 77.162 77.163 @Override 77.164 - public Node enter(final IfNode ifNode) { 77.165 + public Node enterIfNode(final IfNode ifNode) { 77.166 enterDefault(ifNode); 77.167 77.168 type("IfStatement"); 77.169 @@ -490,7 +481,7 @@ 77.170 } 77.171 77.172 @Override 77.173 - public Node enter(final IndexNode indexNode) { 77.174 + public Node enterIndexNode(final IndexNode indexNode) { 77.175 enterDefault(indexNode); 77.176 77.177 type("MemberExpression"); 77.178 @@ -510,7 +501,7 @@ 77.179 } 77.180 77.181 @Override 77.182 - public Node enter(final LabelNode labelNode) { 77.183 + public Node enterLabelNode(final LabelNode labelNode) { 77.184 enterDefault(labelNode); 77.185 77.186 type("LabeledStatement"); 77.187 @@ -527,13 +518,13 @@ 77.188 } 77.189 77.190 @Override 77.191 - public Node enter(final LineNumberNode lineNumberNode) { 77.192 + public Node enterLineNumberNode(final LineNumberNode lineNumberNode) { 77.193 return null; 77.194 } 77.195 77.196 @SuppressWarnings("rawtypes") 77.197 @Override 77.198 - public Node enter(final LiteralNode literalNode) { 77.199 + public Node enterLiteralNode(final LiteralNode literalNode) { 77.200 enterDefault(literalNode); 77.201 77.202 if (literalNode instanceof LiteralNode.ArrayLiteralNode) { 77.203 @@ -569,7 +560,7 @@ 77.204 } 77.205 77.206 @Override 77.207 - public Node enter(final ObjectNode objectNode) { 77.208 + public Node enterObjectNode(final ObjectNode objectNode) { 77.209 enterDefault(objectNode); 77.210 77.211 type("ObjectExpression"); 77.212 @@ -581,7 +572,7 @@ 77.213 } 77.214 77.215 @Override 77.216 - public Node enter(final PropertyNode propertyNode) { 77.217 + public Node enterPropertyNode(final PropertyNode propertyNode) { 77.218 final Node key = propertyNode.getKey(); 77.219 77.220 final Node value = propertyNode.getValue(); 77.221 @@ -647,7 +638,7 @@ 77.222 } 77.223 77.224 @Override 77.225 - public Node enter(final ReturnNode returnNode) { 77.226 + public Node enterReturnNode(final ReturnNode returnNode) { 77.227 enterDefault(returnNode); 77.228 77.229 type("ReturnStatement"); 77.230 @@ -665,7 +656,7 @@ 77.231 } 77.232 77.233 @Override 77.234 - public Node enter(final RuntimeNode runtimeNode) { 77.235 + public Node enterRuntimeNode(final RuntimeNode runtimeNode) { 77.236 final RuntimeNode.Request req = runtimeNode.getRequest(); 77.237 77.238 if (req == RuntimeNode.Request.DEBUGGER) { 77.239 @@ -680,12 +671,12 @@ 77.240 } 77.241 77.242 @Override 77.243 - public Node enter(final SplitNode splitNode) { 77.244 + public Node enterSplitNode(final SplitNode splitNode) { 77.245 return null; 77.246 } 77.247 77.248 @Override 77.249 - public Node enter(final SwitchNode switchNode) { 77.250 + public Node enterSwitchNode(final SwitchNode switchNode) { 77.251 enterDefault(switchNode); 77.252 77.253 type("SwitchStatement"); 77.254 @@ -701,7 +692,7 @@ 77.255 } 77.256 77.257 @Override 77.258 - public Node enter(final TernaryNode ternaryNode) { 77.259 + public Node enterTernaryNode(final TernaryNode ternaryNode) { 77.260 enterDefault(ternaryNode); 77.261 77.262 type("ConditionalExpression"); 77.263 @@ -722,7 +713,7 @@ 77.264 } 77.265 77.266 @Override 77.267 - public Node enter(final ThrowNode throwNode) { 77.268 + public Node enterThrowNode(final ThrowNode throwNode) { 77.269 enterDefault(throwNode); 77.270 77.271 type("ThrowStatement"); 77.272 @@ -735,7 +726,7 @@ 77.273 } 77.274 77.275 @Override 77.276 - public Node enter(final TryNode tryNode) { 77.277 + public Node enterTryNode(final TryNode tryNode) { 77.278 enterDefault(tryNode); 77.279 77.280 type("TryStatement"); 77.281 @@ -760,7 +751,7 @@ 77.282 } 77.283 77.284 @Override 77.285 - public Node enter(final UnaryNode unaryNode) { 77.286 + public Node enterUnaryNode(final UnaryNode unaryNode) { 77.287 enterDefault(unaryNode); 77.288 77.289 final TokenType tokenType = unaryNode.tokenType(); 77.290 @@ -816,7 +807,7 @@ 77.291 } 77.292 77.293 @Override 77.294 - public Node enter(final VarNode varNode) { 77.295 + public Node enterVarNode(final VarNode varNode) { 77.296 enterDefault(varNode); 77.297 77.298 type("VariableDeclaration"); 77.299 @@ -852,7 +843,7 @@ 77.300 } 77.301 77.302 @Override 77.303 - public Node enter(final WhileNode whileNode) { 77.304 + public Node enterWhileNode(final WhileNode whileNode) { 77.305 enterDefault(whileNode); 77.306 77.307 type("WhileStatement"); 77.308 @@ -869,7 +860,7 @@ 77.309 } 77.310 77.311 @Override 77.312 - public Node enter(final WithNode withNode) { 77.313 + public Node enterWithNode(final WithNode withNode) { 77.314 enterDefault(withNode); 77.315 77.316 type("WithStatement");
78.1 --- a/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java Thu Mar 28 10:55:17 2013 -0700 78.2 +++ b/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java Mon Apr 01 21:42:31 2013 -0700 78.3 @@ -42,7 +42,6 @@ 78.4 import jdk.nashorn.internal.ir.LabelNode; 78.5 import jdk.nashorn.internal.ir.LineNumberNode; 78.6 import jdk.nashorn.internal.ir.Node; 78.7 -import jdk.nashorn.internal.ir.ReferenceNode; 78.8 import jdk.nashorn.internal.ir.ReturnNode; 78.9 import jdk.nashorn.internal.ir.RuntimeNode; 78.10 import jdk.nashorn.internal.ir.SplitNode; 78.11 @@ -138,13 +137,13 @@ 78.12 * Visits. 78.13 */ 78.14 @Override 78.15 - public Node enter(final AccessNode accessNode) { 78.16 + public Node enterAccessNode(final AccessNode accessNode) { 78.17 accessNode.toString(sb); 78.18 return null; 78.19 } 78.20 78.21 @Override 78.22 - public Node enter(final Block block) { 78.23 + public Node enterBlock(final Block block) { 78.24 sb.append(' '); 78.25 sb.append('{'); 78.26 78.27 @@ -152,21 +151,6 @@ 78.28 78.29 final boolean isFunction = block instanceof FunctionNode; 78.30 78.31 - if (isFunction) { 78.32 - final FunctionNode function = (FunctionNode)block; 78.33 - final List<FunctionNode> functions = function.getFunctions(); 78.34 - 78.35 - for (final FunctionNode f : functions) { 78.36 - sb.append(EOLN); 78.37 - indent(); 78.38 - f.accept(this); 78.39 - } 78.40 - 78.41 - if (!functions.isEmpty()) { 78.42 - sb.append(EOLN); 78.43 - } 78.44 - } 78.45 - 78.46 final List<Node> statements = block.getStatements(); 78.47 78.48 boolean lastLineNumber = false; 78.49 @@ -224,25 +208,25 @@ 78.50 } 78.51 78.52 @Override 78.53 - public Node enter(final BreakNode breakNode) { 78.54 + public Node enterBreakNode(final BreakNode breakNode) { 78.55 breakNode.toString(sb); 78.56 return null; 78.57 } 78.58 78.59 @Override 78.60 - public Node enter(final CallNode callNode) { 78.61 + public Node enterCallNode(final CallNode callNode) { 78.62 callNode.toString(sb); 78.63 return null; 78.64 } 78.65 78.66 @Override 78.67 - public Node enter(final ContinueNode continueNode) { 78.68 + public Node enterContinueNode(final ContinueNode continueNode) { 78.69 continueNode.toString(sb); 78.70 return null; 78.71 } 78.72 78.73 @Override 78.74 - public Node enter(final DoWhileNode doWhileNode) { 78.75 + public Node enterDoWhileNode(final DoWhileNode doWhileNode) { 78.76 sb.append("do"); 78.77 doWhileNode.getBody().accept(this); 78.78 sb.append(' '); 78.79 @@ -252,7 +236,7 @@ 78.80 } 78.81 78.82 @Override 78.83 - public Node enter(final ExecuteNode executeNode) { 78.84 + public Node enterExecuteNode(final ExecuteNode executeNode) { 78.85 final Node expression = executeNode.getExpression(); 78.86 78.87 if (expression instanceof UnaryNode) { 78.88 @@ -265,7 +249,7 @@ 78.89 } 78.90 78.91 @Override 78.92 - public Node enter(final ForNode forNode) { 78.93 + public Node enterForNode(final ForNode forNode) { 78.94 forNode.toString(sb); 78.95 forNode.getBody().accept(this); 78.96 78.97 @@ -273,15 +257,15 @@ 78.98 } 78.99 78.100 @Override 78.101 - public Node enter(final FunctionNode functionNode) { 78.102 + public Node enterFunctionNode(final FunctionNode functionNode) { 78.103 functionNode.toString(sb); 78.104 - enter((Block)functionNode); 78.105 + enterBlock(functionNode); 78.106 78.107 return null; 78.108 } 78.109 78.110 @Override 78.111 - public Node enter(final IfNode ifNode) { 78.112 + public Node enterIfNode(final IfNode ifNode) { 78.113 ifNode.toString(sb); 78.114 ifNode.getPass().accept(this); 78.115 78.116 @@ -296,13 +280,13 @@ 78.117 } 78.118 78.119 @Override 78.120 - public Node enter(final IndexNode indexNode) { 78.121 + public Node enterIndexNode(final IndexNode indexNode) { 78.122 indexNode.toString(sb); 78.123 return null; 78.124 } 78.125 78.126 @Override 78.127 - public Node enter(final LabelNode labeledNode) { 78.128 + public Node enterLabelNode(final LabelNode labeledNode) { 78.129 indent -= TABWIDTH; 78.130 indent(); 78.131 indent += TABWIDTH; 78.132 @@ -313,7 +297,7 @@ 78.133 } 78.134 78.135 @Override 78.136 - public Node enter(final LineNumberNode lineNumberNode) { 78.137 + public Node enterLineNumberNode(final LineNumberNode lineNumberNode) { 78.138 if (printLineNumbers) { 78.139 lineNumberNode.toString(sb); 78.140 } 78.141 @@ -323,25 +307,19 @@ 78.142 78.143 78.144 @Override 78.145 - public Node enter(final ReferenceNode referenceNode) { 78.146 - referenceNode.toString(sb); 78.147 - return null; 78.148 - } 78.149 - 78.150 - @Override 78.151 - public Node enter(final ReturnNode returnNode) { 78.152 + public Node enterReturnNode(final ReturnNode returnNode) { 78.153 returnNode.toString(sb); 78.154 return null; 78.155 } 78.156 78.157 @Override 78.158 - public Node enter(final RuntimeNode runtimeNode) { 78.159 + public Node enterRuntimeNode(final RuntimeNode runtimeNode) { 78.160 runtimeNode.toString(sb); 78.161 return null; 78.162 } 78.163 78.164 @Override 78.165 - public Node enter(final SplitNode splitNode) { 78.166 + public Node enterSplitNode(final SplitNode splitNode) { 78.167 splitNode.toString(sb); 78.168 sb.append(EOLN); 78.169 indent += TABWIDTH; 78.170 @@ -350,7 +328,7 @@ 78.171 } 78.172 78.173 @Override 78.174 - public Node leave(final SplitNode splitNode) { 78.175 + public Node leaveSplitNode(final SplitNode splitNode) { 78.176 sb.append("</split>"); 78.177 sb.append(EOLN); 78.178 indent -= TABWIDTH; 78.179 @@ -359,7 +337,7 @@ 78.180 } 78.181 78.182 @Override 78.183 - public Node enter(final SwitchNode switchNode) { 78.184 + public Node enterSwitchNode(final SwitchNode switchNode) { 78.185 switchNode.toString(sb); 78.186 sb.append(" {"); 78.187 78.188 @@ -383,13 +361,13 @@ 78.189 } 78.190 78.191 @Override 78.192 - public Node enter(final ThrowNode throwNode) { 78.193 + public Node enterThrowNode(final ThrowNode throwNode) { 78.194 throwNode.toString(sb); 78.195 return null; 78.196 } 78.197 78.198 @Override 78.199 - public Node enter(final TryNode tryNode) { 78.200 + public Node enterTryNode(final TryNode tryNode) { 78.201 tryNode.toString(sb); 78.202 tryNode.getBody().accept(this); 78.203 78.204 @@ -412,13 +390,19 @@ 78.205 } 78.206 78.207 @Override 78.208 - public Node enter(final VarNode varNode) { 78.209 - varNode.toString(sb); 78.210 + public Node enterVarNode(final VarNode varNode) { 78.211 + sb.append("var "); 78.212 + varNode.getName().toString(sb); 78.213 + final Node init = varNode.getInit(); 78.214 + if(init != null) { 78.215 + sb.append(" = "); 78.216 + init.accept(this); 78.217 + } 78.218 return null; 78.219 } 78.220 78.221 @Override 78.222 - public Node enter(final WhileNode whileNode) { 78.223 + public Node enterWhileNode(final WhileNode whileNode) { 78.224 whileNode.toString(sb); 78.225 whileNode.getBody().accept(this); 78.226 78.227 @@ -426,7 +410,7 @@ 78.228 } 78.229 78.230 @Override 78.231 - public Node enter(final WithNode withNode) { 78.232 + public Node enterWithNode(final WithNode withNode) { 78.233 withNode.toString(sb); 78.234 withNode.getBody().accept(this); 78.235
79.1 --- a/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java Thu Mar 28 10:55:17 2013 -0700 79.2 +++ b/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java Mon Apr 01 21:42:31 2013 -0700 79.3 @@ -53,7 +53,7 @@ 79.4 } 79.5 79.6 @Override 79.7 - public final Node enter(final UnaryNode unaryNode) { 79.8 + public final Node enterUnaryNode(final UnaryNode unaryNode) { 79.9 switch (unaryNode.tokenType()) { 79.10 case ADD: 79.11 return enterADD(unaryNode); 79.12 @@ -81,12 +81,12 @@ 79.13 case INCPOSTFIX: 79.14 return enterDECINC(unaryNode); 79.15 default: 79.16 - return super.enter(unaryNode); 79.17 + return super.enterUnaryNode(unaryNode); 79.18 } 79.19 } 79.20 79.21 @Override 79.22 - public final Node leave(final UnaryNode unaryNode) { 79.23 + public final Node leaveUnaryNode(final UnaryNode unaryNode) { 79.24 switch (unaryNode.tokenType()) { 79.25 case ADD: 79.26 return leaveADD(unaryNode); 79.27 @@ -114,12 +114,12 @@ 79.28 case INCPOSTFIX: 79.29 return leaveDECINC(unaryNode); 79.30 default: 79.31 - return super.leave(unaryNode); 79.32 + return super.leaveUnaryNode(unaryNode); 79.33 } 79.34 } 79.35 79.36 @Override 79.37 - public final Node enter(final BinaryNode binaryNode) { 79.38 + public final Node enterBinaryNode(final BinaryNode binaryNode) { 79.39 switch (binaryNode.tokenType()) { 79.40 case ADD: 79.41 return enterADD(binaryNode); 79.42 @@ -198,12 +198,12 @@ 79.43 case SUB: 79.44 return enterSUB(binaryNode); 79.45 default: 79.46 - return super.enter(binaryNode); 79.47 + return super.enterBinaryNode(binaryNode); 79.48 } 79.49 } 79.50 79.51 @Override 79.52 - public final Node leave(final BinaryNode binaryNode) { 79.53 + public final Node leaveBinaryNode(final BinaryNode binaryNode) { 79.54 switch (binaryNode.tokenType()) { 79.55 case ADD: 79.56 return leaveADD(binaryNode); 79.57 @@ -282,7 +282,7 @@ 79.58 case SUB: 79.59 return leaveSUB(binaryNode); 79.60 default: 79.61 - return super.leave(binaryNode); 79.62 + return super.leaveBinaryNode(binaryNode); 79.63 } 79.64 } 79.65
80.1 --- a/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java Thu Mar 28 10:55:17 2013 -0700 80.2 +++ b/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java Mon Apr 01 21:42:31 2013 -0700 80.3 @@ -49,7 +49,6 @@ 80.4 import jdk.nashorn.internal.ir.Node; 80.5 import jdk.nashorn.internal.ir.ObjectNode; 80.6 import jdk.nashorn.internal.ir.PropertyNode; 80.7 -import jdk.nashorn.internal.ir.ReferenceNode; 80.8 import jdk.nashorn.internal.ir.ReturnNode; 80.9 import jdk.nashorn.internal.ir.RuntimeNode; 80.10 import jdk.nashorn.internal.ir.SplitNode; 80.11 @@ -153,7 +152,7 @@ 80.12 * @param accessNode the node 80.13 * @return processed node, null if traversal should end, null if traversal should end 80.14 */ 80.15 - public Node enter(final AccessNode accessNode) { 80.16 + public Node enterAccessNode(final AccessNode accessNode) { 80.17 return enterDefault(accessNode); 80.18 } 80.19 80.20 @@ -163,7 +162,7 @@ 80.21 * @param accessNode the node 80.22 * @return processed node, null if traversal should end 80.23 */ 80.24 - public Node leave(final AccessNode accessNode) { 80.25 + public Node leaveAccessNode(final AccessNode accessNode) { 80.26 return leaveDefault(accessNode); 80.27 } 80.28 80.29 @@ -173,7 +172,7 @@ 80.30 * @param block the node 80.31 * @return processed node, null if traversal should end 80.32 */ 80.33 - public Node enter(final Block block) { 80.34 + public Node enterBlock(final Block block) { 80.35 return enterDefault(block); 80.36 } 80.37 80.38 @@ -183,7 +182,7 @@ 80.39 * @param block the node 80.40 * @return processed node, which will replace the original one, or the original node 80.41 */ 80.42 - public Node leave(final Block block) { 80.43 + public Node leaveBlock(final Block block) { 80.44 return leaveDefault(block); 80.45 } 80.46 80.47 @@ -193,7 +192,7 @@ 80.48 * @param binaryNode the node 80.49 * @return processed node 80.50 */ 80.51 - public Node enter(final BinaryNode binaryNode) { 80.52 + public Node enterBinaryNode(final BinaryNode binaryNode) { 80.53 return enterDefault(binaryNode); 80.54 } 80.55 80.56 @@ -203,7 +202,7 @@ 80.57 * @param binaryNode the node 80.58 * @return processed node, which will replace the original one, or the original node 80.59 */ 80.60 - public Node leave(final BinaryNode binaryNode) { 80.61 + public Node leaveBinaryNode(final BinaryNode binaryNode) { 80.62 return leaveDefault(binaryNode); 80.63 } 80.64 80.65 @@ -213,7 +212,7 @@ 80.66 * @param breakNode the node 80.67 * @return processed node, null if traversal should end 80.68 */ 80.69 - public Node enter(final BreakNode breakNode) { 80.70 + public Node enterBreakNode(final BreakNode breakNode) { 80.71 return enterDefault(breakNode); 80.72 } 80.73 80.74 @@ -223,7 +222,7 @@ 80.75 * @param breakNode the node 80.76 * @return processed node, which will replace the original one, or the original node 80.77 */ 80.78 - public Node leave(final BreakNode breakNode) { 80.79 + public Node leaveBreakNode(final BreakNode breakNode) { 80.80 return leaveDefault(breakNode); 80.81 } 80.82 80.83 @@ -233,7 +232,7 @@ 80.84 * @param callNode the node 80.85 * @return processed node, null if traversal should end 80.86 */ 80.87 - public Node enter(final CallNode callNode) { 80.88 + public Node enterCallNode(final CallNode callNode) { 80.89 return enterDefault(callNode); 80.90 } 80.91 80.92 @@ -243,7 +242,7 @@ 80.93 * @param callNode the node 80.94 * @return processed node, which will replace the original one, or the original node 80.95 */ 80.96 - public Node leave(final CallNode callNode) { 80.97 + public Node leaveCallNode(final CallNode callNode) { 80.98 return leaveDefault(callNode); 80.99 } 80.100 80.101 @@ -253,7 +252,7 @@ 80.102 * @param caseNode the node 80.103 * @return processed node, null if traversal should end 80.104 */ 80.105 - public Node enter(final CaseNode caseNode) { 80.106 + public Node enterCaseNode(final CaseNode caseNode) { 80.107 return enterDefault(caseNode); 80.108 } 80.109 80.110 @@ -263,7 +262,7 @@ 80.111 * @param caseNode the node 80.112 * @return processed node, which will replace the original one, or the original node 80.113 */ 80.114 - public Node leave(final CaseNode caseNode) { 80.115 + public Node leaveCaseNode(final CaseNode caseNode) { 80.116 return leaveDefault(caseNode); 80.117 } 80.118 80.119 @@ -273,7 +272,7 @@ 80.120 * @param catchNode the node 80.121 * @return processed node, null if traversal should end 80.122 */ 80.123 - public Node enter(final CatchNode catchNode) { 80.124 + public Node enterCatchNode(final CatchNode catchNode) { 80.125 return enterDefault(catchNode); 80.126 } 80.127 80.128 @@ -283,7 +282,7 @@ 80.129 * @param catchNode the node 80.130 * @return processed node, which will replace the original one, or the original node 80.131 */ 80.132 - public Node leave(final CatchNode catchNode) { 80.133 + public Node leaveCatchNode(final CatchNode catchNode) { 80.134 return leaveDefault(catchNode); 80.135 } 80.136 80.137 @@ -293,7 +292,7 @@ 80.138 * @param continueNode the node 80.139 * @return processed node, null if traversal should end 80.140 */ 80.141 - public Node enter(final ContinueNode continueNode) { 80.142 + public Node enterContinueNode(final ContinueNode continueNode) { 80.143 return enterDefault(continueNode); 80.144 } 80.145 80.146 @@ -303,7 +302,7 @@ 80.147 * @param continueNode the node 80.148 * @return processed node, which will replace the original one, or the original node 80.149 */ 80.150 - public Node leave(final ContinueNode continueNode) { 80.151 + public Node leaveContinueNode(final ContinueNode continueNode) { 80.152 return leaveDefault(continueNode); 80.153 } 80.154 80.155 @@ -313,7 +312,7 @@ 80.156 * @param doWhileNode the node 80.157 * @return processed node 80.158 */ 80.159 - public Node enter(final DoWhileNode doWhileNode) { 80.160 + public Node enterDoWhileNode(final DoWhileNode doWhileNode) { 80.161 return enterDefault(doWhileNode); 80.162 } 80.163 80.164 @@ -323,7 +322,7 @@ 80.165 * @param doWhileNode the node 80.166 * @return processed node, which will replace the original one, or the original node 80.167 */ 80.168 - public Node leave(final DoWhileNode doWhileNode) { 80.169 + public Node leaveDoWhileNode(final DoWhileNode doWhileNode) { 80.170 return leaveDefault(doWhileNode); 80.171 } 80.172 80.173 @@ -333,7 +332,7 @@ 80.174 * @param emptyNode the node 80.175 * @return processed node 80.176 */ 80.177 - public Node enter(final EmptyNode emptyNode) { 80.178 + public Node enterEmptyNode(final EmptyNode emptyNode) { 80.179 return enterDefault(emptyNode); 80.180 } 80.181 80.182 @@ -343,7 +342,7 @@ 80.183 * @param emptyNode the node 80.184 * @return processed node, which will replace the original one, or the original node 80.185 */ 80.186 - public Node leave(final EmptyNode emptyNode) { 80.187 + public Node leaveEmptyNode(final EmptyNode emptyNode) { 80.188 return leaveDefault(emptyNode); 80.189 } 80.190 80.191 @@ -353,7 +352,7 @@ 80.192 * @param executeNode the node 80.193 * @return processed node, null if traversal should end 80.194 */ 80.195 - public Node enter(final ExecuteNode executeNode) { 80.196 + public Node enterExecuteNode(final ExecuteNode executeNode) { 80.197 return enterDefault(executeNode); 80.198 } 80.199 80.200 @@ -363,7 +362,7 @@ 80.201 * @param executeNode the node 80.202 * @return processed node, which will replace the original one, or the original node 80.203 */ 80.204 - public Node leave(final ExecuteNode executeNode) { 80.205 + public Node leaveExecuteNode(final ExecuteNode executeNode) { 80.206 return leaveDefault(executeNode); 80.207 } 80.208 80.209 @@ -373,7 +372,7 @@ 80.210 * @param forNode the node 80.211 * @return processed node, null if traversal should end 80.212 */ 80.213 - public Node enter(final ForNode forNode) { 80.214 + public Node enterForNode(final ForNode forNode) { 80.215 return enterDefault(forNode); 80.216 } 80.217 80.218 @@ -383,7 +382,7 @@ 80.219 * @param forNode the node 80.220 * @return processed node, which will replace the original one, or the original node 80.221 */ 80.222 - public Node leave(final ForNode forNode) { 80.223 + public Node leaveForNode(final ForNode forNode) { 80.224 return leaveDefault(forNode); 80.225 } 80.226 80.227 @@ -393,7 +392,7 @@ 80.228 * @param functionNode the node 80.229 * @return processed node 80.230 */ 80.231 - public Node enter(final FunctionNode functionNode) { 80.232 + public Node enterFunctionNode(final FunctionNode functionNode) { 80.233 return enterDefault(functionNode); 80.234 } 80.235 80.236 @@ -403,7 +402,7 @@ 80.237 * @param functionNode the node 80.238 * @return processed node, which will replace the original one, or the original node 80.239 */ 80.240 - public Node leave(final FunctionNode functionNode) { 80.241 + public Node leaveFunctionNode(final FunctionNode functionNode) { 80.242 return leaveDefault(functionNode); 80.243 } 80.244 80.245 @@ -413,7 +412,7 @@ 80.246 * @param identNode the node 80.247 * @return processed node, null if traversal should end 80.248 */ 80.249 - public Node enter(final IdentNode identNode) { 80.250 + public Node enterIdentNode(final IdentNode identNode) { 80.251 return enterDefault(identNode); 80.252 } 80.253 80.254 @@ -423,7 +422,7 @@ 80.255 * @param identNode the node 80.256 * @return processed node, which will replace the original one, or the original node 80.257 */ 80.258 - public Node leave(final IdentNode identNode) { 80.259 + public Node leaveIdentNode(final IdentNode identNode) { 80.260 return leaveDefault(identNode); 80.261 } 80.262 80.263 @@ -433,7 +432,7 @@ 80.264 * @param ifNode the node 80.265 * @return processed node, null if traversal should end 80.266 */ 80.267 - public Node enter(final IfNode ifNode) { 80.268 + public Node enterIfNode(final IfNode ifNode) { 80.269 return enterDefault(ifNode); 80.270 } 80.271 80.272 @@ -443,7 +442,7 @@ 80.273 * @param ifNode the node 80.274 * @return processed node, which will replace the original one, or the original node 80.275 */ 80.276 - public Node leave(final IfNode ifNode) { 80.277 + public Node leaveIfNode(final IfNode ifNode) { 80.278 return leaveDefault(ifNode); 80.279 } 80.280 80.281 @@ -453,7 +452,7 @@ 80.282 * @param indexNode the node 80.283 * @return processed node, null if traversal should end 80.284 */ 80.285 - public Node enter(final IndexNode indexNode) { 80.286 + public Node enterIndexNode(final IndexNode indexNode) { 80.287 return enterDefault(indexNode); 80.288 } 80.289 80.290 @@ -463,7 +462,7 @@ 80.291 * @param indexNode the node 80.292 * @return processed node, which will replace the original one, or the original node 80.293 */ 80.294 - public Node leave(final IndexNode indexNode) { 80.295 + public Node leaveIndexNode(final IndexNode indexNode) { 80.296 return leaveDefault(indexNode); 80.297 } 80.298 80.299 @@ -473,7 +472,7 @@ 80.300 * @param labelNode the node 80.301 * @return processed node, null if traversal should end 80.302 */ 80.303 - public Node enter(final LabelNode labelNode) { 80.304 + public Node enterLabelNode(final LabelNode labelNode) { 80.305 return enterDefault(labelNode); 80.306 } 80.307 80.308 @@ -483,7 +482,7 @@ 80.309 * @param labelNode the node 80.310 * @return processed node, which will replace the original one, or the original node 80.311 */ 80.312 - public Node leave(final LabelNode labelNode) { 80.313 + public Node leaveLabelNode(final LabelNode labelNode) { 80.314 return leaveDefault(labelNode); 80.315 } 80.316 80.317 @@ -493,7 +492,7 @@ 80.318 * @param lineNumberNode the node 80.319 * @return processed node, null if traversal should end 80.320 */ 80.321 - public Node enter(final LineNumberNode lineNumberNode) { 80.322 + public Node enterLineNumberNode(final LineNumberNode lineNumberNode) { 80.323 return enterDefault(lineNumberNode); 80.324 } 80.325 80.326 @@ -503,7 +502,7 @@ 80.327 * @param lineNumberNode the node 80.328 * @return processed node, which will replace the original one, or the original node 80.329 */ 80.330 - public Node leave(final LineNumberNode lineNumberNode) { 80.331 + public Node leaveLineNumberNode(final LineNumberNode lineNumberNode) { 80.332 return leaveDefault(lineNumberNode); 80.333 } 80.334 80.335 @@ -513,8 +512,7 @@ 80.336 * @param literalNode the node 80.337 * @return processed node 80.338 */ 80.339 - @SuppressWarnings("rawtypes") 80.340 - public Node enter(final LiteralNode literalNode) { 80.341 + public Node enterLiteralNode(final LiteralNode<?> literalNode) { 80.342 return enterDefault(literalNode); 80.343 } 80.344 80.345 @@ -524,8 +522,7 @@ 80.346 * @param literalNode the node 80.347 * @return processed node, which will replace the original one, or the original node 80.348 */ 80.349 - @SuppressWarnings("rawtypes") 80.350 - public Node leave(final LiteralNode literalNode) { 80.351 + public Node leaveLiteralNode(final LiteralNode<?> literalNode) { 80.352 return leaveDefault(literalNode); 80.353 } 80.354 80.355 @@ -535,7 +532,7 @@ 80.356 * @param objectNode the node 80.357 * @return processed node 80.358 */ 80.359 - public Node enter(final ObjectNode objectNode) { 80.360 + public Node enterObjectNode(final ObjectNode objectNode) { 80.361 return enterDefault(objectNode); 80.362 } 80.363 80.364 @@ -545,7 +542,7 @@ 80.365 * @param objectNode the node 80.366 * @return processed node, which will replace the original one, or the original node 80.367 */ 80.368 - public Node leave(final ObjectNode objectNode) { 80.369 + public Node leaveObjectNode(final ObjectNode objectNode) { 80.370 return leaveDefault(objectNode); 80.371 } 80.372 80.373 @@ -555,7 +552,7 @@ 80.374 * @param propertyNode the node 80.375 * @return processed node, null if traversal should end 80.376 */ 80.377 - public Node enter(final PropertyNode propertyNode) { 80.378 + public Node enterPropertyNode(final PropertyNode propertyNode) { 80.379 return enterDefault(propertyNode); 80.380 } 80.381 80.382 @@ -565,37 +562,17 @@ 80.383 * @param propertyNode the node 80.384 * @return processed node, which will replace the original one, or the original node 80.385 */ 80.386 - public Node leave(final PropertyNode propertyNode) { 80.387 + public Node leavePropertyNode(final PropertyNode propertyNode) { 80.388 return leaveDefault(propertyNode); 80.389 } 80.390 80.391 /** 80.392 - * Callback for entering a ReferenceNode 80.393 - * 80.394 - * @param referenceNode the node 80.395 - * @return processed node, null if traversal should end 80.396 - */ 80.397 - public Node enter(final ReferenceNode referenceNode) { 80.398 - return enterDefault(referenceNode); 80.399 - } 80.400 - 80.401 - /** 80.402 - * Callback for leaving a ReferenceNode 80.403 - * 80.404 - * @param referenceNode the node 80.405 - * @return processed node, which will replace the original one, or the original node 80.406 - */ 80.407 - public Node leave(final ReferenceNode referenceNode) { 80.408 - return leaveDefault(referenceNode); 80.409 - } 80.410 - 80.411 - /** 80.412 * Callback for entering a ReturnNode 80.413 * 80.414 * @param returnNode the node 80.415 * @return processed node, null if traversal should end 80.416 */ 80.417 - public Node enter(final ReturnNode returnNode) { 80.418 + public Node enterReturnNode(final ReturnNode returnNode) { 80.419 return enterDefault(returnNode); 80.420 } 80.421 80.422 @@ -605,7 +582,7 @@ 80.423 * @param returnNode the node 80.424 * @return processed node, which will replace the original one, or the original node 80.425 */ 80.426 - public Node leave(final ReturnNode returnNode) { 80.427 + public Node leaveReturnNode(final ReturnNode returnNode) { 80.428 return leaveDefault(returnNode); 80.429 } 80.430 80.431 @@ -615,7 +592,7 @@ 80.432 * @param runtimeNode the node 80.433 * @return processed node, null if traversal should end 80.434 */ 80.435 - public Node enter(final RuntimeNode runtimeNode) { 80.436 + public Node enterRuntimeNode(final RuntimeNode runtimeNode) { 80.437 return enterDefault(runtimeNode); 80.438 } 80.439 80.440 @@ -625,7 +602,7 @@ 80.441 * @param runtimeNode the node 80.442 * @return processed node, which will replace the original one, or the original node 80.443 */ 80.444 - public Node leave(final RuntimeNode runtimeNode) { 80.445 + public Node leaveRuntimeNode(final RuntimeNode runtimeNode) { 80.446 return leaveDefault(runtimeNode); 80.447 } 80.448 80.449 @@ -635,7 +612,7 @@ 80.450 * @param splitNode the node 80.451 * @return processed node, null if traversal should end 80.452 */ 80.453 - public Node enter(final SplitNode splitNode) { 80.454 + public Node enterSplitNode(final SplitNode splitNode) { 80.455 return enterDefault(splitNode); 80.456 } 80.457 80.458 @@ -645,7 +622,7 @@ 80.459 * @param splitNode the node 80.460 * @return processed node, which will replace the original one, or the original node 80.461 */ 80.462 - public Node leave(final SplitNode splitNode) { 80.463 + public Node leaveSplitNode(final SplitNode splitNode) { 80.464 return leaveDefault(splitNode); 80.465 } 80.466 80.467 @@ -655,7 +632,7 @@ 80.468 * @param switchNode the node 80.469 * @return processed node, null if traversal should end 80.470 */ 80.471 - public Node enter(final SwitchNode switchNode) { 80.472 + public Node enterSwitchNode(final SwitchNode switchNode) { 80.473 return enterDefault(switchNode); 80.474 } 80.475 80.476 @@ -665,7 +642,7 @@ 80.477 * @param switchNode the node 80.478 * @return processed node, which will replace the original one, or the original node 80.479 */ 80.480 - public Node leave(final SwitchNode switchNode) { 80.481 + public Node leaveSwitchNode(final SwitchNode switchNode) { 80.482 return leaveDefault(switchNode); 80.483 } 80.484 80.485 @@ -675,7 +652,7 @@ 80.486 * @param ternaryNode the node 80.487 * @return processed node, null if traversal should end 80.488 */ 80.489 - public Node enter(final TernaryNode ternaryNode) { 80.490 + public Node enterTernaryNode(final TernaryNode ternaryNode) { 80.491 return enterDefault(ternaryNode); 80.492 } 80.493 80.494 @@ -685,7 +662,7 @@ 80.495 * @param ternaryNode the node 80.496 * @return processed node, which will replace the original one, or the original node 80.497 */ 80.498 - public Node leave(final TernaryNode ternaryNode) { 80.499 + public Node leaveTernaryNode(final TernaryNode ternaryNode) { 80.500 return leaveDefault(ternaryNode); 80.501 } 80.502 80.503 @@ -695,7 +672,7 @@ 80.504 * @param throwNode the node 80.505 * @return processed node, null if traversal should end 80.506 */ 80.507 - public Node enter(final ThrowNode throwNode) { 80.508 + public Node enterThrowNode(final ThrowNode throwNode) { 80.509 return enterDefault(throwNode); 80.510 } 80.511 80.512 @@ -705,7 +682,7 @@ 80.513 * @param throwNode the node 80.514 * @return processed node, which will replace the original one, or the original node 80.515 */ 80.516 - public Node leave(final ThrowNode throwNode) { 80.517 + public Node leaveThrowNode(final ThrowNode throwNode) { 80.518 return leaveDefault(throwNode); 80.519 } 80.520 80.521 @@ -715,7 +692,7 @@ 80.522 * @param tryNode the node 80.523 * @return processed node, null if traversal should end 80.524 */ 80.525 - public Node enter(final TryNode tryNode) { 80.526 + public Node enterTryNode(final TryNode tryNode) { 80.527 return enterDefault(tryNode); 80.528 } 80.529 80.530 @@ -725,7 +702,7 @@ 80.531 * @param tryNode the node 80.532 * @return processed node, which will replace the original one, or the original node 80.533 */ 80.534 - public Node leave(final TryNode tryNode) { 80.535 + public Node leaveTryNode(final TryNode tryNode) { 80.536 return leaveDefault(tryNode); 80.537 } 80.538 80.539 @@ -735,7 +712,7 @@ 80.540 * @param unaryNode the node 80.541 * @return processed node, null if traversal should end 80.542 */ 80.543 - public Node enter(final UnaryNode unaryNode) { 80.544 + public Node enterUnaryNode(final UnaryNode unaryNode) { 80.545 return enterDefault(unaryNode); 80.546 } 80.547 80.548 @@ -745,7 +722,7 @@ 80.549 * @param unaryNode the node 80.550 * @return processed node, which will replace the original one, or the original node 80.551 */ 80.552 - public Node leave(final UnaryNode unaryNode) { 80.553 + public Node leaveUnaryNode(final UnaryNode unaryNode) { 80.554 return leaveDefault(unaryNode); 80.555 } 80.556 80.557 @@ -755,7 +732,7 @@ 80.558 * @param varNode the node 80.559 * @return processed node, null if traversal should end 80.560 */ 80.561 - public Node enter(final VarNode varNode) { 80.562 + public Node enterVarNode(final VarNode varNode) { 80.563 return enterDefault(varNode); 80.564 } 80.565 80.566 @@ -765,7 +742,7 @@ 80.567 * @param varNode the node 80.568 * @return processed node, which will replace the original one, or the original node 80.569 */ 80.570 - public Node leave(final VarNode varNode) { 80.571 + public Node leaveVarNode(final VarNode varNode) { 80.572 return leaveDefault(varNode); 80.573 } 80.574 80.575 @@ -775,7 +752,7 @@ 80.576 * @param whileNode the node 80.577 * @return processed node, null if traversal should end 80.578 */ 80.579 - public Node enter(final WhileNode whileNode) { 80.580 + public Node enterWhileNode(final WhileNode whileNode) { 80.581 return enterDefault(whileNode); 80.582 } 80.583 80.584 @@ -785,7 +762,7 @@ 80.585 * @param whileNode the node 80.586 * @return processed node, which will replace the original one, or the original node 80.587 */ 80.588 - public Node leave(final WhileNode whileNode) { 80.589 + public Node leaveWhileNode(final WhileNode whileNode) { 80.590 return leaveDefault(whileNode); 80.591 } 80.592 80.593 @@ -795,7 +772,7 @@ 80.594 * @param withNode the node 80.595 * @return processed node, null if traversal should end 80.596 */ 80.597 - public Node enter(final WithNode withNode) { 80.598 + public Node enterWithNode(final WithNode withNode) { 80.599 return enterDefault(withNode); 80.600 } 80.601 80.602 @@ -805,7 +782,7 @@ 80.603 * @param withNode the node 80.604 * @return processed node, which will replace the original one, or the original node 80.605 */ 80.606 - public Node leave(final WithNode withNode) { 80.607 + public Node leaveWithNode(final WithNode withNode) { 80.608 return leaveDefault(withNode); 80.609 } 80.610
81.1 --- a/src/jdk/nashorn/internal/objects/Global.java Thu Mar 28 10:55:17 2013 -0700 81.2 +++ b/src/jdk/nashorn/internal/objects/Global.java Mon Apr 01 21:42:31 2013 -0700 81.3 @@ -34,6 +34,9 @@ 81.4 import java.lang.invoke.MethodHandle; 81.5 import java.lang.invoke.MethodHandles; 81.6 import java.lang.ref.SoftReference; 81.7 +import java.lang.reflect.Field; 81.8 +import java.security.AccessController; 81.9 +import java.security.PrivilegedAction; 81.10 import java.util.LinkedHashMap; 81.11 import java.util.List; 81.12 import java.util.Map; 81.13 @@ -256,13 +259,29 @@ 81.14 @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE) 81.15 public volatile Object packages; 81.16 81.17 + /** Nashorn extension: Java access - global.com */ 81.18 + @Property(attributes = Attribute.NOT_ENUMERABLE) 81.19 + public volatile Object com; 81.20 + 81.21 + /** Nashorn extension: Java access - global.edu */ 81.22 + @Property(attributes = Attribute.NOT_ENUMERABLE) 81.23 + public volatile Object edu; 81.24 + 81.25 /** Nashorn extension: Java access - global.java */ 81.26 @Property(attributes = Attribute.NOT_ENUMERABLE) 81.27 public volatile Object java; 81.28 81.29 + /** Nashorn extension: Java access - global.javafx */ 81.30 + @Property(attributes = Attribute.NOT_ENUMERABLE) 81.31 + public volatile Object javafx; 81.32 + 81.33 /** Nashorn extension: Java access - global.javax */ 81.34 @Property(attributes = Attribute.NOT_ENUMERABLE) 81.35 - public Object javax; 81.36 + public volatile Object javax; 81.37 + 81.38 + /** Nashorn extension: Java access - global.org */ 81.39 + @Property(attributes = Attribute.NOT_ENUMERABLE) 81.40 + public volatile Object org; 81.41 81.42 /** Nashorn extension: Java access - global.javaImporter */ 81.43 @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE) 81.44 @@ -317,8 +336,12 @@ 81.45 private ScriptFunction builtinTypeError; 81.46 private ScriptFunction builtinURIError; 81.47 private ScriptObject builtinPackages; 81.48 + private ScriptObject builtinCom; 81.49 + private ScriptObject builtinEdu; 81.50 private ScriptObject builtinJava; 81.51 + private ScriptObject builtinJavafx; 81.52 private ScriptObject builtinJavax; 81.53 + private ScriptObject builtinOrg; 81.54 private ScriptObject builtinJavaImporter; 81.55 private ScriptObject builtinJavaApi; 81.56 private ScriptObject builtinArrayBuffer; 81.57 @@ -1479,8 +1502,12 @@ 81.58 private void initJavaAccess() { 81.59 final ScriptObject objectProto = getObjectPrototype(); 81.60 this.builtinPackages = new NativeJavaPackage("", objectProto); 81.61 + this.builtinCom = new NativeJavaPackage("com", objectProto); 81.62 + this.builtinEdu = new NativeJavaPackage("edu", objectProto); 81.63 this.builtinJava = new NativeJavaPackage("java", objectProto); 81.64 + this.builtinJavafx = new NativeJavaPackage("javafx", objectProto); 81.65 this.builtinJavax = new NativeJavaPackage("javax", objectProto); 81.66 + this.builtinOrg = new NativeJavaPackage("org", objectProto); 81.67 this.builtinJavaImporter = initConstructor("JavaImporter"); 81.68 this.builtinJavaApi = initConstructor("Java"); 81.69 } 81.70 @@ -1503,8 +1530,10 @@ 81.71 addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value); 81.72 81.73 // Nashorn extension: global.$OPTIONS (scripting-mode-only) 81.74 - value = context.getEnv(); 81.75 - addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, value); 81.76 + final ScriptObject options = newEmptyInstance(); 81.77 + final ScriptEnvironment scriptEnv = context.getEnv(); 81.78 + copyOptions(options, scriptEnv); 81.79 + addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options); 81.80 81.81 // Nashorn extension: global.$ENV (scripting-mode-only) 81.82 if (System.getSecurityManager() == null) { 81.83 @@ -1523,6 +1552,22 @@ 81.84 addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 81.85 } 81.86 81.87 + private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) { 81.88 + AccessController.doPrivileged(new PrivilegedAction<Void>() { 81.89 + @Override 81.90 + public Void run() { 81.91 + for (Field f : scriptEnv.getClass().getFields()) { 81.92 + try { 81.93 + options.set(f.getName(), f.get(scriptEnv), false); 81.94 + } catch (final IllegalArgumentException | IllegalAccessException exp) { 81.95 + throw new RuntimeException(exp); 81.96 + } 81.97 + } 81.98 + return null; 81.99 + } 81.100 + }); 81.101 + } 81.102 + 81.103 private void initTypedArray() { 81.104 this.builtinArrayBuffer = initConstructor("ArrayBuffer"); 81.105 this.builtinInt8Array = initConstructor("Int8Array"); 81.106 @@ -1545,8 +1590,12 @@ 81.107 this.function = this.builtinFunction; 81.108 this.jsadapter = this.builtinJSAdapter; 81.109 this.json = this.builtinJSON; 81.110 + this.com = this.builtinCom; 81.111 + this.edu = this.builtinEdu; 81.112 this.java = this.builtinJava; 81.113 + this.javafx = this.builtinJavafx; 81.114 this.javax = this.builtinJavax; 81.115 + this.org = this.builtinOrg; 81.116 this.javaImporter = this.builtinJavaImporter; 81.117 this.javaApi = this.builtinJavaApi; 81.118 this.math = this.builtinMath;
82.1 --- a/src/jdk/nashorn/internal/objects/NativeArray.java Thu Mar 28 10:55:17 2013 -0700 82.2 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java Mon Apr 01 21:42:31 2013 -0700 82.3 @@ -605,7 +605,7 @@ 82.4 final boolean strict = sobj.isStrictContext(); 82.5 82.6 if (bulkable(sobj)) { 82.7 - return ((NativeArray)sobj).getArray().pop(); 82.8 + return sobj.getArray().pop(); 82.9 } 82.10 82.11 final long len = JSType.toUint32(sobj.getLength()); 82.12 @@ -725,7 +725,7 @@ 82.13 first = sobj.get(0); 82.14 82.15 if (bulkable(sobj)) { 82.16 - ((NativeArray) sobj).getArray().shiftLeft(1); 82.17 + sobj.getArray().shiftLeft(1); 82.18 } else { 82.19 for (long k = 1; k < len; k++) { 82.20 sobj.set(k - 1, sobj.get(k), strict);
83.1 --- a/src/jdk/nashorn/internal/objects/NativeDebug.java Thu Mar 28 10:55:17 2013 -0700 83.2 +++ b/src/jdk/nashorn/internal/objects/NativeDebug.java Mon Apr 01 21:42:31 2013 -0700 83.3 @@ -66,7 +66,7 @@ 83.4 public static Object getContext(final Object self) { 83.5 final SecurityManager sm = System.getSecurityManager(); 83.6 if (sm != null) { 83.7 - sm.checkPermission(new RuntimePermission("getNashornContext")); 83.8 + sm.checkPermission(new RuntimePermission("nashorn.getContext")); 83.9 } 83.10 return Global.getThisContext(); 83.11 } 83.12 @@ -162,21 +162,6 @@ 83.13 } 83.14 83.15 /** 83.16 - * Nashorn extension: get invocation handle from {@link ScriptFunction} 83.17 - * 83.18 - * @param self self reference 83.19 - * @param obj script function 83.20 - * @return the invocation handle for the given ScriptFunction 83.21 - */ 83.22 - @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 83.23 - public static Object methodHandle(final Object self, final Object obj) { 83.24 - if (obj instanceof ScriptFunction) { 83.25 - return ((ScriptFunction)obj).getInvokeHandle(); 83.26 - } 83.27 - return UNDEFINED; 83.28 - } 83.29 - 83.30 - /** 83.31 * Check object identity comparison regardless of type 83.32 * 83.33 * @param self self reference
84.1 --- a/src/jdk/nashorn/internal/objects/NativeError.java Thu Mar 28 10:55:17 2013 -0700 84.2 +++ b/src/jdk/nashorn/internal/objects/NativeError.java Mon Apr 01 21:42:31 2013 -0700 84.3 @@ -317,7 +317,7 @@ 84.4 return name; 84.5 } 84.6 // Step 10 : return name + ": " + msg 84.7 - return (String)name + ": " + (String)msg; 84.8 + return name + ": " + msg; 84.9 } 84.10 84.11 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
85.1 --- a/src/jdk/nashorn/internal/objects/NativeJava.java Thu Mar 28 10:55:17 2013 -0700 85.2 +++ b/src/jdk/nashorn/internal/objects/NativeJava.java Mon Apr 01 21:42:31 2013 -0700 85.3 @@ -223,6 +223,23 @@ 85.4 } 85.5 85.6 /** 85.7 + * Returns name of a java type {@link StaticClass}. 85.8 + * @param self not used 85.9 + * @param type the type whose name is returned 85.10 + * @return name of the given type 85.11 + */ 85.12 + @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 85.13 + public static Object typeName(final Object self, final Object type) { 85.14 + if (type instanceof StaticClass) { 85.15 + return ((StaticClass)type).getRepresentedClass().getName(); 85.16 + } else if (type instanceof Class) { 85.17 + return ((Class<?>)type).getName(); 85.18 + } else { 85.19 + return UNDEFINED; 85.20 + } 85.21 + } 85.22 + 85.23 + /** 85.24 * Given a JavaScript array and a Java type, returns a Java array with the same initial contents, and with the 85.25 * specified component type. Example: 85.26 * <pre>
86.1 --- a/src/jdk/nashorn/internal/objects/NativeString.java Thu Mar 28 10:55:17 2013 -0700 86.2 +++ b/src/jdk/nashorn/internal/objects/NativeString.java Mon Apr 01 21:42:31 2013 -0700 86.3 @@ -122,6 +122,19 @@ 86.4 return value.length(); 86.5 } 86.6 86.7 + // This is to support length as method call as well. 86.8 + @Override 86.9 + protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) { 86.10 + final String name = desc.getNameToken(2); 86.11 + 86.12 + // if str.length(), then let the bean linker handle it 86.13 + if ("length".equals(name) && "getMethod".equals(operator)) { 86.14 + return null; 86.15 + } 86.16 + 86.17 + return super.findGetMethod(desc, request, operator); 86.18 + } 86.19 + 86.20 // This is to provide array-like access to string characters without creating a NativeString wrapper. 86.21 @Override 86.22 protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
87.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Thu Mar 28 10:55:17 2013 -0700 87.2 +++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Mon Apr 01 21:42:31 2013 -0700 87.3 @@ -31,6 +31,7 @@ 87.4 import jdk.nashorn.internal.runtime.GlobalFunctions; 87.5 import jdk.nashorn.internal.runtime.Property; 87.6 import jdk.nashorn.internal.runtime.PropertyMap; 87.7 +import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; 87.8 import jdk.nashorn.internal.runtime.ScriptFunction; 87.9 import jdk.nashorn.internal.runtime.ScriptFunctionData; 87.10 import jdk.nashorn.internal.runtime.ScriptObject; 87.11 @@ -86,8 +87,8 @@ 87.12 * @param builtin is this a built-in function 87.13 * @param isConstructor can the function be used as a constructor (most can; some built-ins are restricted). 87.14 */ 87.15 - ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final boolean strict, final boolean builtin, final boolean isConstructor) { 87.16 - super(name, methodHandle, getMap(strict), scope, specs, strict, builtin, isConstructor); 87.17 + ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) { 87.18 + super(name, methodHandle, getMap(isStrict), scope, specs, isStrict, isBuiltin, isConstructor); 87.19 init(); 87.20 } 87.21 87.22 @@ -95,14 +96,10 @@ 87.23 * Constructor called by (compiler) generated code for {@link ScriptObject}s. 87.24 * 87.25 * @param data static function data 87.26 - * @param methodHandle handle for invocation 87.27 * @param scope scope object 87.28 - * @param allocator instance constructor for function 87.29 */ 87.30 - public ScriptFunctionImpl(final MethodHandle methodHandle, final ScriptFunctionData data, final ScriptObject scope, final MethodHandle allocator) { 87.31 + public ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope) { 87.32 super(data, getMap(data.isStrict()), scope); 87.33 - // Set method handles in script data 87.34 - data.setMethodHandles(methodHandle, allocator); 87.35 init(); 87.36 } 87.37
88.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionTrampolineImpl.java Thu Mar 28 10:55:17 2013 -0700 88.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 88.3 @@ -1,122 +0,0 @@ 88.4 -package jdk.nashorn.internal.objects; 88.5 - 88.6 -import static jdk.nashorn.internal.lookup.Lookup.MH; 88.7 - 88.8 -import java.lang.invoke.MethodHandle; 88.9 -import java.lang.invoke.MethodHandles; 88.10 -import java.lang.invoke.MethodType; 88.11 -import jdk.nashorn.internal.codegen.CompilationException; 88.12 -import jdk.nashorn.internal.codegen.Compiler; 88.13 -import jdk.nashorn.internal.codegen.FunctionSignature; 88.14 -import jdk.nashorn.internal.codegen.types.Type; 88.15 -import jdk.nashorn.internal.ir.FunctionNode; 88.16 -import jdk.nashorn.internal.runtime.CodeInstaller; 88.17 -import jdk.nashorn.internal.runtime.Context; 88.18 -import jdk.nashorn.internal.runtime.ScriptEnvironment; 88.19 -import jdk.nashorn.internal.runtime.ScriptFunction; 88.20 -import jdk.nashorn.internal.runtime.ScriptFunctionData; 88.21 -import jdk.nashorn.internal.runtime.ScriptObject; 88.22 - 88.23 -/** 88.24 - * A trampoline is a promise to compile a {@link ScriptFunction} later. It just looks like 88.25 - * the call to the script function, but when invoked it will compile the script function 88.26 - * (in a new compile unit) and invoke it 88.27 - */ 88.28 -public final class ScriptFunctionTrampolineImpl extends ScriptFunctionImpl { 88.29 - 88.30 - private CodeInstaller<ScriptEnvironment> installer; 88.31 - 88.32 - /** Function node to lazily recompile when trampoline is hit */ 88.33 - private FunctionNode functionNode; 88.34 - 88.35 - /** 88.36 - * Constructor 88.37 - * 88.38 - * @param installer opaque code installer from context 88.39 - * @param functionNode function node to lazily compile when trampoline is hit 88.40 - * @param data {@link ScriptFunctionData} for function 88.41 - * @param scope scope 88.42 - * @param allocator allocator 88.43 - */ 88.44 - public ScriptFunctionTrampolineImpl(final CodeInstaller<ScriptEnvironment> installer, final FunctionNode functionNode, final ScriptFunctionData data, final ScriptObject scope, final MethodHandle allocator) { 88.45 - super(null, data, scope, allocator); 88.46 - 88.47 - this.installer = installer; 88.48 - this.functionNode = functionNode; 88.49 - 88.50 - data.setMethodHandles(makeTrampoline(), allocator); 88.51 - } 88.52 - 88.53 - private final MethodHandle makeTrampoline() { 88.54 - final MethodType mt = 88.55 - new FunctionSignature( 88.56 - true, 88.57 - functionNode.needsCallee(), 88.58 - Type.OBJECT, 88.59 - functionNode.getParameters().size()). 88.60 - getMethodType(); 88.61 - 88.62 - return 88.63 - MH.bindTo( 88.64 - MH.asCollector( 88.65 - findOwnMH( 88.66 - "trampoline", 88.67 - Object.class, 88.68 - Object[].class), 88.69 - Object[].class, 88.70 - mt.parameterCount()), 88.71 - this); 88.72 - } 88.73 - 88.74 - private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { 88.75 - return MH.findVirtual(MethodHandles.lookup(), ScriptFunctionTrampolineImpl.class, name, MH.type(rtype, types)); 88.76 - } 88.77 - 88.78 - @Override 88.79 - protected ScriptFunction makeBoundFunction(final ScriptFunctionData data) { 88.80 - //prevent trampoline recompilation cycle if a function is bound before use 88.81 - compile(); 88.82 - return super.makeBoundFunction(data); 88.83 - } 88.84 - 88.85 - private MethodHandle compile() throws CompilationException { 88.86 - final Compiler compiler = new Compiler(installer, functionNode); 88.87 - 88.88 - compiler.compile(); 88.89 - 88.90 - final Class<?> clazz = compiler.install(); 88.91 - /* compute function signature for lazy method. this can be done first after compilation, as only then do we know 88.92 - * the final state about callees, scopes and specialized parameter types */ 88.93 - final FunctionSignature signature = new FunctionSignature(true, functionNode.needsCallee(), Type.OBJECT, functionNode.getParameters().size()); 88.94 - final MethodType mt = signature.getMethodType(); 88.95 - 88.96 - MethodHandle mh = MH.findStatic(MethodHandles.publicLookup(), clazz, functionNode.getName(), mt); 88.97 - if (functionNode.needsCallee()) { 88.98 - mh = MH.bindTo(mh, this); 88.99 - } 88.100 - 88.101 - // now the invoker method looks like the one our superclass is expecting 88.102 - resetInvoker(mh); 88.103 - 88.104 - return mh; 88.105 - } 88.106 - 88.107 - @SuppressWarnings("unused") 88.108 - private Object trampoline(final Object... args) throws CompilationException { 88.109 - Compiler.LOG.info(">>> TRAMPOLINE: Hitting trampoline for '" + functionNode.getName() + "'"); 88.110 - MethodHandle mh = compile(); 88.111 - 88.112 - Compiler.LOG.info("<<< COMPILED TO: " + mh); 88.113 - // spread the array to invididual args of the correct type 88.114 - mh = MH.asSpreader(mh, Object[].class, mh.type().parameterCount()); 88.115 - 88.116 - try { 88.117 - //invoke the real method the trampoline points to. this only happens once 88.118 - return mh.invoke(args); 88.119 - } catch (final RuntimeException | Error e) { 88.120 - throw e; 88.121 - } catch (final Throwable t) { 88.122 - throw new RuntimeException(t); 88.123 - } 88.124 - } 88.125 -}
89.1 --- a/src/jdk/nashorn/internal/parser/JSONParser.java Thu Mar 28 10:55:17 2013 -0700 89.2 +++ b/src/jdk/nashorn/internal/parser/JSONParser.java Mon Apr 01 21:42:31 2013 -0700 89.3 @@ -313,7 +313,7 @@ 89.4 } 89.5 89.6 // Construct new object literal. 89.7 - return new ObjectNode(source, objectToken, finish, null, elements); 89.8 + return new ObjectNode(source, objectToken, finish, elements); 89.9 } 89.10 89.11 /**
90.1 --- a/src/jdk/nashorn/internal/parser/Parser.java Thu Mar 28 10:55:17 2013 -0700 90.2 +++ b/src/jdk/nashorn/internal/parser/Parser.java Mon Apr 01 21:42:31 2013 -0700 90.3 @@ -56,6 +56,7 @@ 90.4 import java.util.ArrayList; 90.5 import java.util.HashMap; 90.6 import java.util.HashSet; 90.7 +import java.util.Iterator; 90.8 import java.util.List; 90.9 import java.util.Map; 90.10 import java.util.Stack; 90.11 @@ -75,17 +76,18 @@ 90.12 import jdk.nashorn.internal.ir.ExecuteNode; 90.13 import jdk.nashorn.internal.ir.ForNode; 90.14 import jdk.nashorn.internal.ir.FunctionNode; 90.15 +import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 90.16 import jdk.nashorn.internal.ir.IdentNode; 90.17 import jdk.nashorn.internal.ir.IfNode; 90.18 import jdk.nashorn.internal.ir.IndexNode; 90.19 import jdk.nashorn.internal.ir.LabelNode; 90.20 +import jdk.nashorn.internal.ir.LexicalContext; 90.21 import jdk.nashorn.internal.ir.LineNumberNode; 90.22 import jdk.nashorn.internal.ir.LiteralNode; 90.23 import jdk.nashorn.internal.ir.Node; 90.24 import jdk.nashorn.internal.ir.ObjectNode; 90.25 import jdk.nashorn.internal.ir.PropertyKey; 90.26 import jdk.nashorn.internal.ir.PropertyNode; 90.27 -import jdk.nashorn.internal.ir.ReferenceNode; 90.28 import jdk.nashorn.internal.ir.ReturnNode; 90.29 import jdk.nashorn.internal.ir.RuntimeNode; 90.30 import jdk.nashorn.internal.ir.SwitchNode; 90.31 @@ -96,7 +98,6 @@ 90.32 import jdk.nashorn.internal.ir.VarNode; 90.33 import jdk.nashorn.internal.ir.WhileNode; 90.34 import jdk.nashorn.internal.ir.WithNode; 90.35 -import jdk.nashorn.internal.runtime.Context; 90.36 import jdk.nashorn.internal.runtime.DebugLogger; 90.37 import jdk.nashorn.internal.runtime.ErrorManager; 90.38 import jdk.nashorn.internal.runtime.JSErrorType; 90.39 @@ -116,19 +117,13 @@ 90.40 /** Is scripting mode. */ 90.41 private final boolean scripting; 90.42 90.43 - /** Top level script being parsed. */ 90.44 - private FunctionNode script; 90.45 - 90.46 - /** Current function being parsed. */ 90.47 - private FunctionNode function; 90.48 - 90.49 - /** Current parsing block. */ 90.50 - private Block block; 90.51 + private final LexicalContext lexicalContext = new LexicalContext(); 90.52 + private List<Node> functionDeclarations; 90.53 90.54 /** Namespace for function names where not explicitly given */ 90.55 private final Namespace namespace; 90.56 90.57 - private static DebugLogger LOG = new DebugLogger("parser"); 90.58 + private static final DebugLogger LOG = new DebugLogger("parser"); 90.59 90.60 /** 90.61 * Constructor 90.62 @@ -279,7 +274,9 @@ 90.63 * @return New block. 90.64 */ 90.65 private Block newBlock() { 90.66 - return block = new Block(source, token, Token.descPosition(token), block, function); 90.67 + final Block block = new Block(source, token, Token.descPosition(token)); 90.68 + lexicalContext.push(block); 90.69 + return block; 90.70 } 90.71 90.72 /** 90.73 @@ -292,18 +289,23 @@ 90.74 // Build function name. 90.75 final StringBuilder sb = new StringBuilder(); 90.76 90.77 - if (block != null) { 90.78 - block.addParentName(sb); 90.79 + final FunctionNode parentFunction = getFunction(); 90.80 + if(parentFunction != null && !parentFunction.isProgram()) { 90.81 + sb.append(parentFunction.getName()).append('$'); 90.82 } 90.83 90.84 sb.append(ident != null ? ident.getName() : FUNCTION_PREFIX.tag()); 90.85 final String name = namespace.uniqueName(sb.toString()); 90.86 - assert function != null || name.equals(RUN_SCRIPT.tag()) : "name = " + name;// must not rename runScript(). 90.87 + assert parentFunction != null || name.equals(RUN_SCRIPT.tag()) : "name = " + name;// must not rename runScript(). 90.88 90.89 // Start new block. 90.90 - final FunctionNode functionBlock = new FunctionNode(source, token, Token.descPosition(token), namespace, block, ident, name); 90.91 - block = function = functionBlock; 90.92 - function.setStrictMode(isStrictMode); 90.93 + final FunctionNode functionBlock = new FunctionNode(source, token, Token.descPosition(token), namespace, ident, name); 90.94 + if(parentFunction == null) { 90.95 + functionBlock.setProgram(); 90.96 + } 90.97 + functionBlock.setStrictMode(isStrictMode); 90.98 + functionBlock.setState(errors.hasErrors() ? CompilationState.PARSE_ERROR : CompilationState.PARSED); 90.99 + lexicalContext.push(functionBlock); 90.100 90.101 return functionBlock; 90.102 } 90.103 @@ -311,9 +313,8 @@ 90.104 /** 90.105 * Restore the current block. 90.106 */ 90.107 - private void restoreBlock() { 90.108 - block = block.getParent(); 90.109 - function = block.getFunction(); 90.110 + private void restoreBlock(Block block) { 90.111 + lexicalContext.pop(block); 90.112 } 90.113 90.114 /** 90.115 @@ -323,22 +324,25 @@ 90.116 private Block getBlock(final boolean needsBraces) { 90.117 // Set up new block. Captures LBRACE. 90.118 final Block newBlock = newBlock(); 90.119 - pushControlNode(newBlock); 90.120 - 90.121 - // Block opening brace. 90.122 - if (needsBraces) { 90.123 - expect(LBRACE); 90.124 + try { 90.125 + pushControlNode(newBlock); 90.126 + 90.127 + // Block opening brace. 90.128 + if (needsBraces) { 90.129 + expect(LBRACE); 90.130 + } 90.131 + 90.132 + try { 90.133 + // Accumulate block statements. 90.134 + statementList(); 90.135 + } finally { 90.136 + popControlNode(); 90.137 + } 90.138 + } finally { 90.139 + restoreBlock(newBlock); 90.140 } 90.141 90.142 - try { 90.143 - // Accumulate block statements. 90.144 - statementList(); 90.145 - } finally { 90.146 - restoreBlock(); 90.147 - popControlNode(); 90.148 - } 90.149 - 90.150 - final int possibleEnd = Token.descPosition(token) + Token.descLength(token); 90.151 + final int possibleEnd = Token.descPosition(token) + Token.descLength(token); 90.152 90.153 // Block closing brace. 90.154 if (needsBraces) { 90.155 @@ -365,7 +369,7 @@ 90.156 // Accumulate statements. 90.157 statement(); 90.158 } finally { 90.159 - restoreBlock(); 90.160 + restoreBlock(newBlock); 90.161 } 90.162 90.163 return newBlock; 90.164 @@ -379,7 +383,10 @@ 90.165 final String name = ident.getName(); 90.166 90.167 if (EVAL.tag().equals(name)) { 90.168 - function.setHasEval(); 90.169 + final Iterator<FunctionNode> it = lexicalContext.getFunctions(); 90.170 + if(it.hasNext()) { 90.171 + it.next().setHasEval(it); 90.172 + } 90.173 } 90.174 } 90.175 90.176 @@ -391,7 +398,7 @@ 90.177 final String name = ident.getName(); 90.178 90.179 if (ARGUMENTS.tag().equals(name)) { 90.180 - function.setUsesArguments(); 90.181 + getFunction().setUsesArguments(); 90.182 } 90.183 } 90.184 90.185 @@ -438,7 +445,7 @@ 90.186 } 90.187 90.188 if (lhs instanceof IdentNode) { 90.189 - if (! checkIdentLValue((IdentNode)lhs)) { 90.190 + if (!checkIdentLValue((IdentNode)lhs)) { 90.191 return referenceError(lhs, rhs); 90.192 } 90.193 verifyStrictIdent((IdentNode)lhs, "assignment"); 90.194 @@ -482,7 +489,7 @@ 90.195 * @return null or the found label node. 90.196 */ 90.197 private LabelNode findLabel(final IdentNode ident) { 90.198 - for (final LabelNode labelNode : function.getLabelStack()) { 90.199 + for (final LabelNode labelNode : getFunction().getLabelStack()) { 90.200 if (labelNode.getLabel().equals(ident)) { 90.201 return labelNode; 90.202 } 90.203 @@ -496,14 +503,14 @@ 90.204 * @param labelNode Label to add. 90.205 */ 90.206 private void pushLabel(final LabelNode labelNode) { 90.207 - function.getLabelStack().push(labelNode); 90.208 + getFunction().getLabelStack().push(labelNode); 90.209 } 90.210 90.211 /** 90.212 * Remove a label from the label stack. 90.213 */ 90.214 private void popLabel() { 90.215 - function.getLabelStack().pop(); 90.216 + getFunction().getLabelStack().pop(); 90.217 } 90.218 90.219 /** 90.220 @@ -513,6 +520,7 @@ 90.221 private void pushControlNode(final Node node) { 90.222 final boolean isLoop = node instanceof WhileNode; 90.223 final boolean isBreakable = node instanceof BreakableNode || node instanceof Block; 90.224 + final FunctionNode function = getFunction(); 90.225 function.getControlStack().push(node); 90.226 90.227 for (final LabelNode labelNode : function.getLabelStack()) { 90.228 @@ -531,7 +539,7 @@ 90.229 */ 90.230 private void popControlNode() { 90.231 // Get control stack. 90.232 - final Stack<Node> controlStack = function.getControlStack(); 90.233 + final Stack<Node> controlStack = getFunction().getControlStack(); 90.234 90.235 // Can be empty if missing brace. 90.236 if (!controlStack.isEmpty()) { 90.237 @@ -541,7 +549,7 @@ 90.238 90.239 private void popControlNode(final Node node) { 90.240 // Get control stack. 90.241 - final Stack<Node> controlStack = function.getControlStack(); 90.242 + final Stack<Node> controlStack = getFunction().getControlStack(); 90.243 90.244 // Can be empty if missing brace. 90.245 if (!controlStack.isEmpty() && controlStack.peek() == node) { 90.246 @@ -550,7 +558,7 @@ 90.247 } 90.248 90.249 private boolean isInWithBlock() { 90.250 - final Stack<Node> controlStack = function.getControlStack(); 90.251 + final Stack<Node> controlStack = getFunction().getControlStack(); 90.252 for (int i = controlStack.size() - 1; i >= 0; i--) { 90.253 final Node node = controlStack.get(i); 90.254 90.255 @@ -563,7 +571,7 @@ 90.256 } 90.257 90.258 private <T extends Node> T findControl(final Class<T> ctype) { 90.259 - final Stack<Node> controlStack = function.getControlStack(); 90.260 + final Stack<Node> controlStack = getFunction().getControlStack(); 90.261 for (int i = controlStack.size() - 1; i >= 0; i--) { 90.262 final Node node = controlStack.get(i); 90.263 90.264 @@ -577,7 +585,7 @@ 90.265 90.266 private <T extends Node> List<T> findControls(final Class<T> ctype, final Node to) { 90.267 final List<T> nodes = new ArrayList<>(); 90.268 - final Stack<Node> controlStack = function.getControlStack(); 90.269 + final Stack<Node> controlStack = getFunction().getControlStack(); 90.270 for (int i = controlStack.size() - 1; i >= 0; i--) { 90.271 final Node node = controlStack.get(i); 90.272 90.273 @@ -621,15 +629,16 @@ 90.274 // Make a fake token for the script. 90.275 final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength()); 90.276 // Set up the script to append elements. 90.277 - script = newFunctionBlock(new IdentNode(source, functionToken, Token.descPosition(functionToken), scriptName)); 90.278 - // set kind to be SCRIPT 90.279 + 90.280 + final FunctionNode script = newFunctionBlock(new IdentNode(source, functionToken, Token.descPosition(functionToken), scriptName)); 90.281 + 90.282 script.setKind(FunctionNode.Kind.SCRIPT); 90.283 - // Set the first token of the script. 90.284 script.setFirstToken(functionToken); 90.285 - // Gather source elements. 90.286 + functionDeclarations = new ArrayList<>(); 90.287 sourceElements(); 90.288 + script.prependStatements(functionDeclarations); 90.289 + functionDeclarations = null; 90.290 expect(EOF); 90.291 - // Set the last token of the script. 90.292 script.setLastToken(token); 90.293 script.setFinish(source.getLength() - 1); 90.294 90.295 @@ -707,7 +716,7 @@ 90.296 // check for directive prologues 90.297 if (checkDirective) { 90.298 // skip any debug statement like line number to get actual first line 90.299 - final Node lastStatement = lastStatement(block.getStatements()); 90.300 + final Node lastStatement = lastStatement(getBlock().getStatements()); 90.301 90.302 // get directive prologue, if any 90.303 final String directive = getDirective(lastStatement); 90.304 @@ -727,6 +736,7 @@ 90.305 // handle use strict directive 90.306 if ("use strict".equals(directive)) { 90.307 isStrictMode = true; 90.308 + final FunctionNode function = getFunction(); 90.309 function.setStrictMode(true); 90.310 90.311 // We don't need to check these, if lexical environment is already strict 90.312 @@ -799,11 +809,11 @@ 90.313 if (isStrictMode && !topLevel) { 90.314 error(AbstractParser.message("strict.no.func.here"), token); 90.315 } 90.316 - functionExpression(true); 90.317 + functionExpression(true, topLevel); 90.318 return; 90.319 } 90.320 90.321 - block.addStatement(lineNumberNode); 90.322 + getBlock().addStatement(lineNumberNode); 90.323 90.324 switch (type) { 90.325 case LBRACE: 90.326 @@ -889,7 +899,7 @@ 90.327 // Force block execution. 90.328 final ExecuteNode executeNode = new ExecuteNode(source, newBlock.getToken(), finish, newBlock); 90.329 90.330 - block.addStatement(executeNode); 90.331 + getBlock().addStatement(executeNode); 90.332 } 90.333 90.334 /** 90.335 @@ -984,13 +994,9 @@ 90.336 90.337 // Allocate var node. 90.338 final VarNode var = new VarNode(source, varToken, finish, name, init); 90.339 - if (isStatement) { 90.340 - function.addDeclaration(var); 90.341 - } 90.342 - 90.343 vars.add(var); 90.344 // Add to current block. 90.345 - block.addStatement(var); 90.346 + getBlock().addStatement(var); 90.347 90.348 if (type != COMMARIGHT) { 90.349 break; 90.350 @@ -1003,7 +1009,7 @@ 90.351 boolean semicolon = type == SEMICOLON; 90.352 endOfLine(); 90.353 if (semicolon) { 90.354 - block.setFinish(finish); 90.355 + getBlock().setFinish(finish); 90.356 } 90.357 } 90.358 90.359 @@ -1020,7 +1026,7 @@ 90.360 */ 90.361 private void emptyStatement() { 90.362 if (env._empty_statements) { 90.363 - block.addStatement(new EmptyNode(source, token, 90.364 + getBlock().addStatement(new EmptyNode(source, token, 90.365 Token.descPosition(token) + Token.descLength(token))); 90.366 } 90.367 90.368 @@ -1046,7 +1052,7 @@ 90.369 ExecuteNode executeNode = null; 90.370 if (expression != null) { 90.371 executeNode = new ExecuteNode(source, expressionToken, finish, expression); 90.372 - block.addStatement(executeNode); 90.373 + getBlock().addStatement(executeNode); 90.374 } else { 90.375 expect(null); 90.376 } 90.377 @@ -1055,7 +1061,7 @@ 90.378 90.379 if (executeNode != null) { 90.380 executeNode.setFinish(finish); 90.381 - block.setFinish(finish); 90.382 + getBlock().setFinish(finish); 90.383 } 90.384 } 90.385 90.386 @@ -1097,7 +1103,7 @@ 90.387 // Construct and add new if node. 90.388 final IfNode ifNode = new IfNode(source, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail); 90.389 90.390 - block.addStatement(ifNode); 90.391 + getBlock().addStatement(ifNode); 90.392 } 90.393 90.394 /** 90.395 @@ -1146,13 +1152,13 @@ 90.396 outer.setFinish(body.getFinish()); 90.397 90.398 // Add for to current block. 90.399 - block.addStatement(forNode); 90.400 + getBlock().addStatement(forNode); 90.401 } finally { 90.402 - restoreBlock(); 90.403 + restoreBlock(outer); 90.404 popControlNode(); 90.405 } 90.406 90.407 - block.addStatement(new ExecuteNode(source, outer.getToken(), outer.getFinish(), outer)); 90.408 + getBlock().addStatement(new ExecuteNode(source, outer.getToken(), outer.getFinish(), outer)); 90.409 } 90.410 90.411 /** 90.412 @@ -1231,7 +1237,7 @@ 90.413 } 90.414 90.415 if (init instanceof IdentNode) { 90.416 - if (! checkIdentLValue((IdentNode)init)) { 90.417 + if (!checkIdentLValue((IdentNode)init)) { 90.418 error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken()); 90.419 } 90.420 verifyStrictIdent((IdentNode)init, "for-in iterator"); 90.421 @@ -1286,7 +1292,7 @@ 90.422 whileNode.setFinish(statements.getFinish()); 90.423 90.424 // Add WHILE node. 90.425 - block.addStatement(whileNode); 90.426 + getBlock().addStatement(whileNode); 90.427 } finally { 90.428 popControlNode(); 90.429 } 90.430 @@ -1333,7 +1339,7 @@ 90.431 doWhileNode.setFinish(finish); 90.432 90.433 // Add DO node. 90.434 - block.addStatement(doWhileNode); 90.435 + getBlock().addStatement(doWhileNode); 90.436 } finally { 90.437 popControlNode(); 90.438 } 90.439 @@ -1385,7 +1391,7 @@ 90.440 final ContinueNode continueNode = new ContinueNode(source, continueToken, finish, labelNode, targetNode, findControl(TryNode.class)); 90.441 continueNode.setScopeNestingLevel(countControls(WithNode.class, targetNode)); 90.442 90.443 - block.addStatement(continueNode); 90.444 + getBlock().addStatement(continueNode); 90.445 } 90.446 90.447 /** 90.448 @@ -1433,7 +1439,7 @@ 90.449 final BreakNode breakNode = new BreakNode(source, breakToken, finish, labelNode, targetNode, findControl(TryNode.class)); 90.450 breakNode.setScopeNestingLevel(countControls(WithNode.class, targetNode)); 90.451 90.452 - block.addStatement(breakNode); 90.453 + getBlock().addStatement(breakNode); 90.454 } 90.455 90.456 /** 90.457 @@ -1446,7 +1452,7 @@ 90.458 */ 90.459 private void returnStatement() { 90.460 // check for return outside function 90.461 - if (function.getKind() == FunctionNode.Kind.SCRIPT) { 90.462 + if (getFunction().getKind() == FunctionNode.Kind.SCRIPT) { 90.463 error(AbstractParser.message("invalid.return")); 90.464 } 90.465 90.466 @@ -1473,7 +1479,7 @@ 90.467 90.468 // Construct and add RETURN node. 90.469 final ReturnNode returnNode = new ReturnNode(source, returnToken, finish, expression, findControl(TryNode.class)); 90.470 - block.addStatement(returnNode); 90.471 + getBlock().addStatement(returnNode); 90.472 } 90.473 90.474 /** 90.475 @@ -1508,7 +1514,7 @@ 90.476 90.477 // Construct and add YIELD node. 90.478 final ReturnNode yieldNode = new ReturnNode(source, yieldToken, finish, expression, findControl(TryNode.class)); 90.479 - block.addStatement(yieldNode); 90.480 + getBlock().addStatement(yieldNode); 90.481 } 90.482 90.483 /** 90.484 @@ -1532,7 +1538,10 @@ 90.485 90.486 // Get WITH expression. 90.487 final WithNode withNode = new WithNode(source, withToken, finish, null, null); 90.488 - function.setHasWith(); 90.489 + final Iterator<FunctionNode> it = lexicalContext.getFunctions(); 90.490 + if(it.hasNext()) { 90.491 + it.next().setHasWith(it); 90.492 + } 90.493 90.494 try { 90.495 pushControlNode(withNode); 90.496 @@ -1552,7 +1561,7 @@ 90.497 popControlNode(withNode); 90.498 } 90.499 90.500 - block.addStatement(withNode); 90.501 + getBlock().addStatement(withNode); 90.502 } 90.503 90.504 /** 90.505 @@ -1652,7 +1661,7 @@ 90.506 90.507 switchNode.setFinish(finish); 90.508 90.509 - block.addStatement(switchNode); 90.510 + getBlock().addStatement(switchNode); 90.511 } finally { 90.512 popControlNode(); 90.513 } 90.514 @@ -1687,7 +1696,7 @@ 90.515 labelNode.setBody(statements); 90.516 labelNode.setFinish(finish); 90.517 90.518 - block.addStatement(labelNode); 90.519 + getBlock().addStatement(labelNode); 90.520 } finally { 90.521 // Remove label. 90.522 popLabel(); 90.523 @@ -1730,7 +1739,7 @@ 90.524 90.525 // Construct and add THROW node. 90.526 final ThrowNode throwNode = new ThrowNode(source, throwToken, finish, expression, findControl(TryNode.class)); 90.527 - block.addStatement(throwNode); 90.528 + getBlock().addStatement(throwNode); 90.529 } 90.530 90.531 /** 90.532 @@ -1796,18 +1805,18 @@ 90.533 90.534 expect(RPAREN); 90.535 90.536 + final Block catchBlock = newBlock(); 90.537 try { 90.538 - final Block catchBlock = newBlock(); 90.539 90.540 // Get CATCH body. 90.541 final Block catchBody = getBlock(true); 90.542 90.543 // Create and add catch. 90.544 final CatchNode catchNode = new CatchNode(source, catchToken, finish, exception, ifExpression, catchBody); 90.545 - block.addStatement(catchNode); 90.546 + getBlock().addStatement(catchNode); 90.547 catchBlocks.add(catchBlock); 90.548 } finally { 90.549 - restoreBlock(); 90.550 + restoreBlock(catchBlock); 90.551 } 90.552 90.553 // If unconditional catch then should to be the end. 90.554 @@ -1843,11 +1852,11 @@ 90.555 outer.addStatement(tryNode); 90.556 } finally { 90.557 popControlNode(tryNode); 90.558 - restoreBlock(); 90.559 + restoreBlock(outer); 90.560 popControlNode(outer); 90.561 } 90.562 90.563 - block.addStatement(new ExecuteNode(source, outer.getToken(), outer.getFinish(), outer)); 90.564 + getBlock().addStatement(new ExecuteNode(source, outer.getToken(), outer.getFinish(), outer)); 90.565 } 90.566 90.567 /** 90.568 @@ -1867,7 +1876,7 @@ 90.569 endOfLine(); 90.570 90.571 final RuntimeNode runtimeNode = new RuntimeNode(source, debuggerToken, finish, RuntimeNode.Request.DEBUGGER, new ArrayList<Node>()); 90.572 - block.addStatement(runtimeNode); 90.573 + getBlock().addStatement(runtimeNode); 90.574 } 90.575 90.576 /** 90.577 @@ -2026,7 +2035,7 @@ 90.578 break; 90.579 90.580 default: 90.581 - if (! elision) { 90.582 + if (!elision) { 90.583 error(AbstractParser.message("expected.comma", type.getNameOrType())); 90.584 } 90.585 // Add expression element. 90.586 @@ -2067,15 +2076,11 @@ 90.587 next(); 90.588 90.589 // Object context. 90.590 - Block objectContext = null; 90.591 // Prepare to accumulate elements. 90.592 final List<Node> elements = new ArrayList<>(); 90.593 final Map<Object, PropertyNode> map = new HashMap<>(); 90.594 90.595 - try { 90.596 - // Create a block for the object literal. 90.597 - objectContext = newBlock(); 90.598 - 90.599 + // Create a block for the object literal. 90.600 boolean commaSeen = true; 90.601 loop: 90.602 while (true) { 90.603 @@ -2090,97 +2095,90 @@ 90.604 break; 90.605 90.606 default: 90.607 - if (! commaSeen) { 90.608 + if (!commaSeen) { 90.609 error(AbstractParser.message("expected.comma", type.getNameOrType())); 90.610 - } 90.611 - 90.612 - commaSeen = false; 90.613 - // Get and add the next property. 90.614 - final PropertyNode property = propertyAssignment(); 90.615 - final Object key = property.getKeyName(); 90.616 - final PropertyNode existingProperty = map.get(key); 90.617 - 90.618 - if (existingProperty != null) { 90.619 - // ECMA section 11.1.5 Object Initialiser 90.620 - // point # 4 on property assignment production 90.621 - final Node value = property.getValue(); 90.622 - final Node getter = property.getGetter(); 90.623 - final Node setter = property.getSetter(); 90.624 - 90.625 - final Node prevValue = existingProperty.getValue(); 90.626 - final Node prevGetter = existingProperty.getGetter(); 90.627 - final Node prevSetter = existingProperty.getSetter(); 90.628 - 90.629 - boolean redefinitionOk = true; 90.630 - // ECMA 11.1.5 strict mode restrictions 90.631 - if (isStrictMode) { 90.632 - if (value != null && prevValue != null) { 90.633 - redefinitionOk = false; 90.634 - } 90.635 - } 90.636 - 90.637 - final boolean isPrevAccessor = prevGetter != null || prevSetter != null; 90.638 - final boolean isAccessor = getter != null || setter != null; 90.639 - 90.640 - // data property redefined as accessor property 90.641 - if (prevValue != null && isAccessor) { 90.642 + } 90.643 + 90.644 + commaSeen = false; 90.645 + // Get and add the next property. 90.646 + final PropertyNode property = propertyAssignment(); 90.647 + final Object key = property.getKeyName(); 90.648 + final PropertyNode existingProperty = map.get(key); 90.649 + 90.650 + if (existingProperty != null) { 90.651 + // ECMA section 11.1.5 Object Initialiser 90.652 + // point # 4 on property assignment production 90.653 + final Node value = property.getValue(); 90.654 + final Node getter = property.getGetter(); 90.655 + final Node setter = property.getSetter(); 90.656 + 90.657 + final Node prevValue = existingProperty.getValue(); 90.658 + final Node prevGetter = existingProperty.getGetter(); 90.659 + final Node prevSetter = existingProperty.getSetter(); 90.660 + 90.661 + boolean redefinitionOk = true; 90.662 + // ECMA 11.1.5 strict mode restrictions 90.663 + if (isStrictMode) { 90.664 + if (value != null && prevValue != null) { 90.665 redefinitionOk = false; 90.666 } 90.667 - 90.668 - // accessor property redefined as data 90.669 - if (isPrevAccessor && value != null) { 90.670 + } 90.671 + 90.672 + final boolean isPrevAccessor = prevGetter != null || prevSetter != null; 90.673 + final boolean isAccessor = getter != null || setter != null; 90.674 + 90.675 + // data property redefined as accessor property 90.676 + if (prevValue != null && isAccessor) { 90.677 + redefinitionOk = false; 90.678 + } 90.679 + 90.680 + // accessor property redefined as data 90.681 + if (isPrevAccessor && value != null) { 90.682 + redefinitionOk = false; 90.683 + } 90.684 + 90.685 + if (isAccessor && isPrevAccessor) { 90.686 + if (getter != null && prevGetter != null || 90.687 + setter != null && prevSetter != null) { 90.688 redefinitionOk = false; 90.689 } 90.690 - 90.691 - if (isAccessor && isPrevAccessor) { 90.692 - if (getter != null && prevGetter != null || 90.693 - setter != null && prevSetter != null) { 90.694 - redefinitionOk = false; 90.695 - } 90.696 + } 90.697 + 90.698 + if (!redefinitionOk) { 90.699 + error(AbstractParser.message("property.redefinition", key.toString()), property.getToken()); 90.700 + } 90.701 + 90.702 + if (value != null) { 90.703 + final Node existingValue = existingProperty.getValue(); 90.704 + 90.705 + if (existingValue == null) { 90.706 + existingProperty.setValue(value); 90.707 + } else { 90.708 + final long propertyToken = Token.recast(existingProperty.getToken(), COMMARIGHT); 90.709 + existingProperty.setValue(new BinaryNode(source, propertyToken, existingValue, value)); 90.710 } 90.711 90.712 - if (! redefinitionOk) { 90.713 - error(AbstractParser.message("property.redefinition", key.toString()), property.getToken()); 90.714 - } 90.715 - 90.716 - if (value != null) { 90.717 - final Node existingValue = existingProperty.getValue(); 90.718 - 90.719 - if (existingValue == null) { 90.720 - existingProperty.setValue(value); 90.721 - } else { 90.722 - final long propertyToken = Token.recast(existingProperty.getToken(), COMMARIGHT); 90.723 - existingProperty.setValue(new BinaryNode(source, propertyToken, existingValue, value)); 90.724 - } 90.725 - 90.726 - existingProperty.setGetter(null); 90.727 - existingProperty.setSetter(null); 90.728 - } 90.729 - 90.730 - if (getter != null) { 90.731 - existingProperty.setGetter(getter); 90.732 - } 90.733 - 90.734 - if (setter != null) { 90.735 - existingProperty.setSetter(setter); 90.736 - } 90.737 - } else { 90.738 - map.put(key, property); 90.739 - elements.add(property); 90.740 + existingProperty.setGetter(null); 90.741 + existingProperty.setSetter(null); 90.742 } 90.743 90.744 - break; 90.745 + if (getter != null) { 90.746 + existingProperty.setGetter(getter); 90.747 + } 90.748 + 90.749 + if (setter != null) { 90.750 + existingProperty.setSetter(setter); 90.751 + } 90.752 + } else { 90.753 + map.put(key, property); 90.754 + elements.add(property); 90.755 } 90.756 + 90.757 + break; 90.758 } 90.759 - } finally { 90.760 - restoreBlock(); 90.761 } 90.762 90.763 - // Construct new object literal. 90.764 - objectContext.setFinish(finish); 90.765 - objectContext.setStart(Token.descPosition(objectToken)); 90.766 - 90.767 - return new ObjectNode(source, objectToken, finish, objectContext, elements); 90.768 + return new ObjectNode(source, objectToken, finish, elements); 90.769 } 90.770 90.771 /** 90.772 @@ -2258,7 +2256,7 @@ 90.773 parameters = new ArrayList<>(); 90.774 functionNode = functionBody(getSetToken, getNameNode, parameters, FunctionNode.Kind.GETTER); 90.775 propertyNode = new PropertyNode(source, propertyToken, finish, getIdent, null); 90.776 - propertyNode.setGetter(new ReferenceNode(source, propertyToken, finish, functionNode)); 90.777 + propertyNode.setGetter(functionNode); 90.778 return propertyNode; 90.779 90.780 case "set": 90.781 @@ -2273,7 +2271,7 @@ 90.782 parameters.add(argIdent); 90.783 functionNode = functionBody(getSetToken, setNameNode, parameters, FunctionNode.Kind.SETTER); 90.784 propertyNode = new PropertyNode(source, propertyToken, finish, setIdent, null); 90.785 - propertyNode.setSetter(new ReferenceNode(source, propertyToken, finish, functionNode)); 90.786 + propertyNode.setSetter(functionNode); 90.787 return propertyNode; 90.788 90.789 default: 90.790 @@ -2454,7 +2452,7 @@ 90.791 90.792 case FUNCTION: 90.793 // Get function expression. 90.794 - lhs = functionExpression(false); 90.795 + lhs = functionExpression(false, false); 90.796 break; 90.797 90.798 default: 90.799 @@ -2559,7 +2557,7 @@ 90.800 * 90.801 * @return Expression node. 90.802 */ 90.803 - private Node functionExpression(final boolean isStatement) { 90.804 + private Node functionExpression(final boolean isStatement, final boolean topLevel) { 90.805 final LineNumberNode lineNumber = lineNumber(); 90.806 90.807 final long functionToken = token; 90.808 @@ -2594,10 +2592,12 @@ 90.809 90.810 final FunctionNode functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL); 90.811 90.812 - if (isStatement && !isInWithBlock()) { 90.813 - functionNode.setIsStatement(); 90.814 + if (isStatement) { 90.815 + if(topLevel) { 90.816 + functionNode.setIsDeclared(); 90.817 + } 90.818 if(ARGUMENTS.tag().equals(name.getName())) { 90.819 - functionNode.findParentFunction().setDefinesArguments(); 90.820 + getFunction().setDefinesArguments(); 90.821 } 90.822 } 90.823 90.824 @@ -2605,8 +2605,6 @@ 90.825 functionNode.setIsAnonymous(); 90.826 } 90.827 90.828 - final ReferenceNode referenceNode = new ReferenceNode(source, functionToken, finish, functionNode); 90.829 - 90.830 final int arity = parameters.size(); 90.831 90.832 final boolean strict = functionNode.isStrictMode(); 90.833 @@ -2642,17 +2640,18 @@ 90.834 } 90.835 90.836 if (isStatement) { 90.837 - final VarNode var = new VarNode(source, functionToken, finish, name, referenceNode); 90.838 - if (isInWithBlock()) { 90.839 - function.addDeclaration(var); 90.840 - // Add to current block. 90.841 - block.addStatement(var); 90.842 + final VarNode varNode = new VarNode(source, functionToken, finish, name, functionNode, true); 90.843 + if(topLevel) { 90.844 + functionDeclarations.add(lineNumber); 90.845 + functionDeclarations.add(varNode); 90.846 } else { 90.847 - functionNode.setFunctionVarNode(var, lineNumber); 90.848 + final Block block = getBlock(); 90.849 + block.addStatement(lineNumber); 90.850 + block.addStatement(varNode); 90.851 } 90.852 } 90.853 90.854 - return referenceNode; 90.855 + return functionNode; 90.856 } 90.857 90.858 /** 90.859 @@ -2735,7 +2734,14 @@ 90.860 expect(LBRACE); 90.861 90.862 // Gather the function elements. 90.863 - sourceElements(); 90.864 + final List<Node> prevFunctionDecls = functionDeclarations; 90.865 + functionDeclarations = new ArrayList<>(); 90.866 + try { 90.867 + sourceElements(); 90.868 + functionNode.prependStatements(functionDeclarations); 90.869 + } finally { 90.870 + functionDeclarations = prevFunctionDecls; 90.871 + } 90.872 90.873 functionNode.setLastToken(token); 90.874 expect(RBRACE); 90.875 @@ -2743,12 +2749,9 @@ 90.876 90.877 } 90.878 } finally { 90.879 - restoreBlock(); 90.880 + restoreBlock(functionNode); 90.881 } 90.882 90.883 - // Add the body of the function to the current block. 90.884 - block.addFunction(functionNode); 90.885 - 90.886 return functionNode; 90.887 } 90.888 90.889 @@ -2845,7 +2848,7 @@ 90.890 } 90.891 90.892 if (lhs instanceof IdentNode) { 90.893 - if (! checkIdentLValue((IdentNode)lhs)) { 90.894 + if (!checkIdentLValue((IdentNode)lhs)) { 90.895 return referenceError(lhs, null); 90.896 } 90.897 verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator"); 90.898 @@ -2872,7 +2875,7 @@ 90.899 return referenceError(lhs, null); 90.900 } 90.901 if (lhs instanceof IdentNode) { 90.902 - if (! checkIdentLValue((IdentNode)lhs)) { 90.903 + if (!checkIdentLValue((IdentNode)lhs)) { 90.904 next(); 90.905 return referenceError(lhs, null); 90.906 } 90.907 @@ -3083,4 +3086,12 @@ 90.908 public String toString() { 90.909 return "[JavaScript Parsing]"; 90.910 } 90.911 + 90.912 + private Block getBlock() { 90.913 + return lexicalContext.getCurrentBlock(); 90.914 + } 90.915 + 90.916 + private FunctionNode getFunction() { 90.917 + return lexicalContext.getCurrentFunction(); 90.918 + } 90.919 }
91.1 --- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java Thu Mar 28 10:55:17 2013 -0700 91.2 +++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java Mon Apr 01 21:42:31 2013 -0700 91.3 @@ -164,7 +164,6 @@ 91.4 super(key, flags, slot); 91.5 91.6 /* 91.7 - * 91.8 * primitiveGetter and primitiveSetter are only used in dual fields mode. Setting them to null also 91.9 * works in dual field mode, it only means that the property never has a primitive 91.10 * representation. 91.11 @@ -348,11 +347,10 @@ 91.12 91.13 private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) { 91.14 if (DEBUG_FIELDS) { 91.15 - final MethodHandle mhd = MethodHandleFactory.addDebugPrintout( 91.16 + return MethodHandleFactory.addDebugPrintout( 91.17 LOG, 91.18 mh, 91.19 tag + " '" + getKey() + "' (property="+ Debug.id(this) + ", forType=" + stripName(forType) + ", type=" + stripName(type) + ')'); 91.20 - return mhd; 91.21 } 91.22 return mh; 91.23 }
92.1 --- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java Thu Mar 28 10:55:17 2013 -0700 92.2 +++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java Mon Apr 01 21:42:31 2013 -0700 92.3 @@ -25,6 +25,8 @@ 92.4 92.5 package jdk.nashorn.internal.runtime; 92.6 92.7 +import jdk.nashorn.internal.codegen.ClassEmitter; 92.8 + 92.9 /** 92.10 * Interface for installing classes passed to the compiler. 92.11 * As only the code generating package (i.e. Context) knows about 92.12 @@ -52,12 +54,12 @@ 92.13 */ 92.14 public Class<?> install(final String className, final byte[] bytecode); 92.15 92.16 - /* 92.17 + /** 92.18 * Verify generated bytecode before emission. This is called back from the 92.19 * {@link ClassEmitter} or the {@link Compiler}. If the "--verify-code" parameter 92.20 * hasn't been given, this is a nop 92.21 * 92.22 - * @param bytecode bytecode to verify 92.23 + * @param code bytecode to verify 92.24 */ 92.25 public void verify(final byte[] code); 92.26 }
93.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 93.2 +++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java Mon Apr 01 21:42:31 2013 -0700 93.3 @@ -0,0 +1,162 @@ 93.4 +/* 93.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 93.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 93.7 + * 93.8 + * This code is free software; you can redistribute it and/or modify it 93.9 + * under the terms of the GNU General Public License version 2 only, as 93.10 + * published by the Free Software Foundation. Oracle designates this 93.11 + * particular file as subject to the "Classpath" exception as provided 93.12 + * by Oracle in the LICENSE file that accompanied this code. 93.13 + * 93.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 93.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 93.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 93.17 + * version 2 for more details (a copy is included in the LICENSE file that 93.18 + * accompanied this code). 93.19 + * 93.20 + * You should have received a copy of the GNU General Public License version 93.21 + * 2 along with this work; if not, write to the Free Software Foundation, 93.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 93.23 + * 93.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 93.25 + * or visit www.oracle.com if you need additional information or have any 93.26 + * questions. 93.27 + */ 93.28 +package jdk.nashorn.internal.runtime; 93.29 + 93.30 +import java.lang.invoke.MethodHandle; 93.31 +import java.lang.invoke.MethodType; 93.32 + 93.33 +import jdk.nashorn.internal.codegen.types.Type; 93.34 + 93.35 +/** 93.36 + * An version of a JavaScript function, native or JavaScript. 93.37 + * Supports lazily generating a constructor version of the invocation. 93.38 + */ 93.39 +final class CompiledFunction implements Comparable<CompiledFunction> { 93.40 + 93.41 + private final MethodHandle invoker; 93.42 + private MethodHandle constructor; 93.43 + 93.44 + CompiledFunction(final MethodHandle invoker) { 93.45 + this(invoker, null); 93.46 + } 93.47 + 93.48 + CompiledFunction(final MethodHandle invoker, final MethodHandle constructor) { 93.49 + this.invoker = invoker; 93.50 + this.constructor = constructor; //isConstructor 93.51 + } 93.52 + 93.53 + @Override 93.54 + public String toString() { 93.55 + return "<invoker=" + invoker + " ctor=" + constructor + ">"; 93.56 + } 93.57 + 93.58 + MethodHandle getInvoker() { 93.59 + return invoker; 93.60 + } 93.61 + 93.62 + MethodHandle getConstructor() { 93.63 + return constructor; 93.64 + } 93.65 + 93.66 + void setConstructor(final MethodHandle constructor) { 93.67 + this.constructor = constructor; 93.68 + } 93.69 + 93.70 + boolean hasConstructor() { 93.71 + return constructor != null; 93.72 + } 93.73 + 93.74 + MethodType type() { 93.75 + return invoker.type(); 93.76 + } 93.77 + 93.78 + @Override 93.79 + public int compareTo(final CompiledFunction o) { 93.80 + return weight() - o.weight(); 93.81 + } 93.82 + 93.83 + private int weight() { 93.84 + return weight(type()); 93.85 + } 93.86 + 93.87 + private static int weight(final MethodType type) { 93.88 + if (isVarArgsType(type)) { 93.89 + return Integer.MAX_VALUE; //if there is a varargs it should be the heavist and last fallback 93.90 + } 93.91 + 93.92 + int weight = Type.typeFor(type.returnType()).getWeight(); 93.93 + for (final Class<?> paramType : type.parameterArray()) { 93.94 + final int pweight = Type.typeFor(paramType).getWeight(); 93.95 + weight += pweight; 93.96 + } 93.97 + return weight; 93.98 + } 93.99 + 93.100 + private static boolean isVarArgsType(final MethodType type) { 93.101 + assert type.parameterCount() >= 1 : type; 93.102 + return type.parameterType(type.parameterCount() - 1) == Object[].class; 93.103 + } 93.104 + 93.105 + boolean moreGenericThan(final CompiledFunction o) { 93.106 + return weight() > o.weight(); 93.107 + } 93.108 + 93.109 + boolean moreGenericThan(final MethodType type) { 93.110 + return weight() > weight(type); 93.111 + } 93.112 + 93.113 + /** 93.114 + * Check whether a given method descriptor is compatible with this invocation. 93.115 + * It is compatible if the types are narrower than the invocation type so that 93.116 + * a semantically equivalent linkage can be performed. 93.117 + * 93.118 + * @param typesc 93.119 + * @return 93.120 + */ 93.121 + boolean typeCompatible(final MethodType type) { 93.122 + final Class<?>[] wantedParams = type.parameterArray(); 93.123 + final Class<?>[] existingParams = type().parameterArray(); 93.124 + 93.125 + //if we are not examining a varargs type, the number of parameters must be the same 93.126 + if (wantedParams.length != existingParams.length && !isVarArgsType(type)) { 93.127 + return false; 93.128 + } 93.129 + 93.130 + //we only go as far as the shortest array. the only chance to make this work if 93.131 + //parameters lengths do not match is if our type ends with a varargs argument. 93.132 + //then every trailing parameter in the given callsite can be folded into it, making 93.133 + //us compatible (albeit slower than a direct specialization) 93.134 + final int lastParamIndex = Math.min(wantedParams.length, existingParams.length); 93.135 + for (int i = 0; i < lastParamIndex; i++) { 93.136 + final Type w = Type.typeFor(wantedParams[i]); 93.137 + final Type e = Type.typeFor(existingParams[i]); 93.138 + 93.139 + //don't specialize on booleans, we have the "true" vs int 1 ambiguity in resolution 93.140 + //we also currently don't support boolean as a javascript function callsite type. 93.141 + //it will always box. 93.142 + if (w.isBoolean()) { 93.143 + return false; 93.144 + } 93.145 + 93.146 + //This callsite type has a vararg here. it will swallow all remaining args. 93.147 + //for consistency, check that it's the last argument 93.148 + if (e.isArray()) { 93.149 + return true; 93.150 + } 93.151 + 93.152 + //Our arguments must be at least as wide as the wanted one, if not wider 93.153 + if (Type.widest(w, e) != e) { 93.154 + //e.g. this invocation takes double and callsite says "object". reject. won't fit 93.155 + //but if invocation takes a double and callsite says "int" or "long" or "double", that's fine 93.156 + return false; 93.157 + } 93.158 + } 93.159 + 93.160 + return true; // anything goes for return type, take the convenient one and it will be upcasted thru dynalink magic. 93.161 + } 93.162 + 93.163 + 93.164 + 93.165 +}
94.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 94.2 +++ b/src/jdk/nashorn/internal/runtime/CompiledFunctions.java Mon Apr 01 21:42:31 2013 -0700 94.3 @@ -0,0 +1,73 @@ 94.4 +/* 94.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 94.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 94.7 + * 94.8 + * This code is free software; you can redistribute it and/or modify it 94.9 + * under the terms of the GNU General Public License version 2 only, as 94.10 + * published by the Free Software Foundation. Oracle designates this 94.11 + * particular file as subject to the "Classpath" exception as provided 94.12 + * by Oracle in the LICENSE file that accompanied this code. 94.13 + * 94.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 94.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 94.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 94.17 + * version 2 for more details (a copy is included in the LICENSE file that 94.18 + * accompanied this code). 94.19 + * 94.20 + * You should have received a copy of the GNU General Public License version 94.21 + * 2 along with this work; if not, write to the Free Software Foundation, 94.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 94.23 + * 94.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 94.25 + * or visit www.oracle.com if you need additional information or have any 94.26 + * questions. 94.27 + */ 94.28 +package jdk.nashorn.internal.runtime; 94.29 + 94.30 +import java.lang.invoke.MethodType; 94.31 +import java.util.Iterator; 94.32 +import java.util.TreeSet; 94.33 + 94.34 +/** 94.35 + * This is a list of code versions of a function. 94.36 + * The list is sorted in ascending order of generic descriptors 94.37 + */ 94.38 +@SuppressWarnings("serial") 94.39 +final class CompiledFunctions extends TreeSet<CompiledFunction> { 94.40 + 94.41 + CompiledFunction best(final MethodType type) { 94.42 + final Iterator<CompiledFunction> iter = iterator(); 94.43 + while (iter.hasNext()) { 94.44 + final CompiledFunction next = iter.next(); 94.45 + if (next.typeCompatible(type)) { 94.46 + return next; 94.47 + } 94.48 + } 94.49 + return mostGeneric(); 94.50 + } 94.51 + 94.52 + boolean needsCallee() { 94.53 + for (final CompiledFunction inv : this) { 94.54 + assert ScriptFunctionData.needsCallee(inv.getInvoker()) == ScriptFunctionData.needsCallee(mostGeneric().getInvoker()); 94.55 + } 94.56 + return ScriptFunctionData.needsCallee(mostGeneric().getInvoker()); 94.57 + } 94.58 + 94.59 + CompiledFunction mostGeneric() { 94.60 + return last(); 94.61 + } 94.62 + 94.63 + /** 94.64 + * Is the given type even more specific than this entire list? That means 94.65 + * we have an opportunity for more specific versions of the method 94.66 + * through lazy code generation 94.67 + * 94.68 + * @param type type to check against 94.69 + * @return true if the given type is more specific than all invocations available 94.70 + */ 94.71 + boolean isLessSpecificThan(final MethodType type) { 94.72 + return best(type).moreGenericThan(type); 94.73 + } 94.74 + 94.75 + 94.76 +}
95.1 --- a/src/jdk/nashorn/internal/runtime/Context.java Thu Mar 28 10:55:17 2013 -0700 95.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java Mon Apr 01 21:42:31 2013 -0700 95.3 @@ -27,9 +27,9 @@ 95.4 95.5 import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT; 95.6 import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE; 95.7 +import static jdk.nashorn.internal.lookup.Lookup.MH; 95.8 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 95.9 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 95.10 -import static jdk.nashorn.internal.lookup.Lookup.MH; 95.11 95.12 import java.io.File; 95.13 import java.io.IOException; 95.14 @@ -39,10 +39,13 @@ 95.15 import java.lang.reflect.Constructor; 95.16 import java.net.MalformedURLException; 95.17 import java.net.URL; 95.18 +import java.security.AccessControlContext; 95.19 import java.security.AccessController; 95.20 import java.security.CodeSigner; 95.21 import java.security.CodeSource; 95.22 +import java.security.Permissions; 95.23 import java.security.PrivilegedAction; 95.24 +import java.security.ProtectionDomain; 95.25 import jdk.internal.org.objectweb.asm.ClassReader; 95.26 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter; 95.27 import jdk.nashorn.internal.codegen.Compiler; 95.28 @@ -77,7 +80,7 @@ 95.29 95.30 /** 95.31 * Return the context for this installer 95.32 - * @return context 95.33 + * @return ScriptEnvironment 95.34 */ 95.35 @Override 95.36 public ScriptEnvironment getOwner() { 95.37 @@ -123,7 +126,7 @@ 95.38 if (callerLoader != myLoader && 95.39 !(callerLoader instanceof StructureLoader) && 95.40 !(JavaAdapterFactory.isAdapterClass(caller))) { 95.41 - sm.checkPermission(new RuntimePermission("getNashornGlobal")); 95.42 + sm.checkPermission(new RuntimePermission("nashorn.getGlobal")); 95.43 } 95.44 } 95.45 95.46 @@ -137,7 +140,7 @@ 95.47 public static void setGlobal(final ScriptObject global) { 95.48 final SecurityManager sm = System.getSecurityManager(); 95.49 if (sm != null) { 95.50 - sm.checkPermission(new RuntimePermission("setNashornGlobal")); 95.51 + sm.checkPermission(new RuntimePermission("nashorn.setGlobal")); 95.52 } 95.53 95.54 if (global != null && !(global instanceof GlobalObject)) { 95.55 @@ -154,7 +157,7 @@ 95.56 public static Context getContext() { 95.57 final SecurityManager sm = System.getSecurityManager(); 95.58 if (sm != null) { 95.59 - sm.checkPermission(new RuntimePermission("getNashornContext")); 95.60 + sm.checkPermission(new RuntimePermission("nashorn.getContext")); 95.61 } 95.62 return getContextTrusted(); 95.63 } 95.64 @@ -267,7 +270,7 @@ 95.65 public Context(final Options options, final ErrorManager errors, final PrintWriter out, final PrintWriter err, final ClassLoader appLoader) { 95.66 final SecurityManager sm = System.getSecurityManager(); 95.67 if (sm != null) { 95.68 - sm.checkPermission(new RuntimePermission("createNashornContext")); 95.69 + sm.checkPermission(new RuntimePermission("nashorn.createContext")); 95.70 } 95.71 95.72 this.env = new ScriptEnvironment(options, out, err); 95.73 @@ -533,7 +536,13 @@ 95.74 if (index != -1) { 95.75 final SecurityManager sm = System.getSecurityManager(); 95.76 if (sm != null) { 95.77 - sm.checkPackageAccess(fullName.substring(0, index)); 95.78 + AccessController.doPrivileged(new PrivilegedAction<Void>() { 95.79 + @Override 95.80 + public Void run() { 95.81 + sm.checkPackageAccess(fullName.substring(0, index)); 95.82 + return null; 95.83 + } 95.84 + }, createNoPermissionsContext()); 95.85 } 95.86 } 95.87 95.88 @@ -599,7 +608,7 @@ 95.89 public ScriptObject newGlobal() { 95.90 final SecurityManager sm = System.getSecurityManager(); 95.91 if (sm != null) { 95.92 - sm.checkPermission(new RuntimePermission("createNashornGlobal")); 95.93 + sm.checkPermission(new RuntimePermission("nashorn.newGlobal")); 95.94 } 95.95 95.96 return newGlobalTrusted(); 95.97 @@ -676,6 +685,10 @@ 95.98 return (context != null) ? context : Context.getContextTrusted(); 95.99 } 95.100 95.101 + private static AccessControlContext createNoPermissionsContext() { 95.102 + return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, new Permissions()) }); 95.103 + } 95.104 + 95.105 private Object evaluateSource(final Source source, final ScriptObject scope, final ScriptObject thiz) { 95.106 ScriptFunction script = null; 95.107 95.108 @@ -731,6 +744,7 @@ 95.109 global = (GlobalObject)Context.getGlobalTrusted(); 95.110 script = global.findCachedClass(source); 95.111 if (script != null) { 95.112 + Compiler.LOG.fine("Code cache hit for " + source + " avoiding recompile."); 95.113 return script; 95.114 } 95.115 }
96.1 --- a/src/jdk/nashorn/internal/runtime/ECMAException.java Thu Mar 28 10:55:17 2013 -0700 96.2 +++ b/src/jdk/nashorn/internal/runtime/ECMAException.java Mon Apr 01 21:42:31 2013 -0700 96.3 @@ -237,7 +237,7 @@ 96.4 return (String)name; 96.5 } 96.6 96.7 - return (String)name + ": " + (String)msg; 96.8 + return name + ": " + msg; 96.9 } 96.10 96.11 private static Throwable asThrowable(final Object obj) {
97.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 97.2 +++ b/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Mon Apr 01 21:42:31 2013 -0700 97.3 @@ -0,0 +1,100 @@ 97.4 +/* 97.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 97.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 97.7 + * 97.8 + * This code is free software; you can redistribute it and/or modify it 97.9 + * under the terms of the GNU General Public License version 2 only, as 97.10 + * published by the Free Software Foundation. Oracle designates this 97.11 + * particular file as subject to the "Classpath" exception as provided 97.12 + * by Oracle in the LICENSE file that accompanied this code. 97.13 + * 97.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 97.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 97.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 97.17 + * version 2 for more details (a copy is included in the LICENSE file that 97.18 + * accompanied this code). 97.19 + * 97.20 + * You should have received a copy of the GNU General Public License version 97.21 + * 2 along with this work; if not, write to the Free Software Foundation, 97.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 97.23 + * 97.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 97.25 + * or visit www.oracle.com if you need additional information or have any 97.26 + * questions. 97.27 + */ 97.28 + 97.29 +package jdk.nashorn.internal.runtime; 97.30 + 97.31 +import static jdk.nashorn.internal.lookup.Lookup.MH; 97.32 + 97.33 +import java.lang.invoke.MethodHandle; 97.34 + 97.35 +/** 97.36 + * This is a subclass that represents a script function that may not be regenerated. 97.37 + * This is used for example for bound functions and builtins. 97.38 + */ 97.39 +public final class FinalScriptFunctionData extends ScriptFunctionData { 97.40 + 97.41 + /** 97.42 + * Constructor - used for bind 97.43 + * 97.44 + * @param name name 97.45 + * @param arity arity 97.46 + * @param list precompiled code 97.47 + * @param isStrict strict 97.48 + * @param isBuiltin builtin 97.49 + * @param isConstructor constructor 97.50 + */ 97.51 + FinalScriptFunctionData(final String name, int arity, CompiledFunctions functions, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) { 97.52 + super(name, arity, isStrict, isBuiltin, isConstructor); 97.53 + code.addAll(functions); 97.54 + } 97.55 + 97.56 + /** 97.57 + * Constructor - used from ScriptFunction. This assumes that we have code alraedy for the 97.58 + * method (typically a native method) and possibly specializations. 97.59 + * 97.60 + * @param name name 97.61 + * @param mh method handle for generic version of method 97.62 + * @param specs specializations 97.63 + * @param isStrict strict 97.64 + * @param isBuiltin builtin 97.65 + * @param isConstructor constructor 97.66 + */ 97.67 + FinalScriptFunctionData(final String name, final MethodHandle mh, final MethodHandle[] specs, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) { 97.68 + super(name, arity(mh), isStrict, isBuiltin, isConstructor); 97.69 + 97.70 + addInvoker(mh); 97.71 + if (specs != null) { 97.72 + for (final MethodHandle spec : specs) { 97.73 + addInvoker(spec); 97.74 + } 97.75 + } 97.76 + } 97.77 + 97.78 + private void addInvoker(final MethodHandle mh) { 97.79 + boolean needsCallee = needsCallee(mh); 97.80 + if (isConstructor(mh)) { 97.81 + //only nasgen constructors: (boolean, self, args) are subject to binding a boolean newObj. isConstructor 97.82 + //is too conservative a check. However, isConstructor(mh) always implies isConstructor param 97.83 + assert isConstructor(); 97.84 + code.add(new CompiledFunction(MH.insertArguments(mh, 0, false), composeConstructor(MH.insertArguments(mh, 0, true), needsCallee))); //make sure callee state can be determined when we reach constructor 97.85 + } else { 97.86 + code.add(new CompiledFunction(mh)); 97.87 + } 97.88 + } 97.89 + 97.90 + private static int arity(final MethodHandle mh) { 97.91 + if (isVarArg(mh)) { 97.92 + return -1; 97.93 + } 97.94 + 97.95 + //drop self, callee and boolean constructor flag to get real arity 97.96 + return mh.type().parameterCount() - 1 - (needsCallee(mh) ? 1 : 0) - (isConstructor(mh) ? 1 : 0); 97.97 + } 97.98 + 97.99 + private static boolean isConstructor(final MethodHandle mh) { 97.100 + return mh.type().parameterCount() >= 1 && mh.type().parameterType(0) == boolean.class; 97.101 + } 97.102 + 97.103 +}
98.1 --- a/src/jdk/nashorn/internal/runtime/NashornLoader.java Thu Mar 28 10:55:17 2013 -0700 98.2 +++ b/src/jdk/nashorn/internal/runtime/NashornLoader.java Mon Apr 01 21:42:31 2013 -0700 98.3 @@ -30,6 +30,10 @@ 98.4 import java.net.MalformedURLException; 98.5 import java.net.URL; 98.6 import java.net.URLClassLoader; 98.7 +import java.security.CodeSource; 98.8 +import java.security.Permission; 98.9 +import java.security.PermissionCollection; 98.10 +import java.security.Permissions; 98.11 import java.security.SecureClassLoader; 98.12 import jdk.nashorn.tools.Shell; 98.13 98.14 @@ -40,6 +44,28 @@ 98.15 * 98.16 */ 98.17 abstract class NashornLoader extends SecureClassLoader { 98.18 + private static final String OBJECTS_PKG = "jdk.nashorn.internal.objects"; 98.19 + private static final String RUNTIME_PKG = "jdk.nashorn.internal.runtime"; 98.20 + private static final String RUNTIME_LINKER_PKG = "jdk.nashorn.internal.runtime.linker"; 98.21 + private static final String SCRIPTS_PKG = "jdk.nashorn.internal.scripts"; 98.22 + 98.23 + private static final Permission[] SCRIPT_PERMISSIONS; 98.24 + static { 98.25 + SCRIPT_PERMISSIONS = new Permission[4]; 98.26 + 98.27 + /* 98.28 + * Generated classes get access to runtime, runtime.linker, objects, scripts packages. 98.29 + * Note that the actual scripts can not access these because Java.type, Packages 98.30 + * prevent these restricted packages. And Java reflection and JSR292 access is prevented 98.31 + * for scripts. In other words, nashorn generated portions of script classes can access 98.32 + * clases in these implementation packages. 98.33 + */ 98.34 + SCRIPT_PERMISSIONS[0] = new RuntimePermission("accessClassInPackage." + RUNTIME_PKG); 98.35 + SCRIPT_PERMISSIONS[1] = new RuntimePermission("accessClassInPackage." + RUNTIME_LINKER_PKG); 98.36 + SCRIPT_PERMISSIONS[2] = new RuntimePermission("accessClassInPackage." + OBJECTS_PKG); 98.37 + SCRIPT_PERMISSIONS[3] = new RuntimePermission("accessClassInPackage." + SCRIPTS_PKG); 98.38 + } 98.39 + 98.40 private final Context context; 98.41 98.42 final Context getContext() { 98.43 @@ -68,11 +94,30 @@ 98.44 if (i != -1) { 98.45 final SecurityManager sm = System.getSecurityManager(); 98.46 if (sm != null) { 98.47 - sm.checkPackageAccess(name.substring(0, i)); 98.48 + final String pkgName = name.substring(0, i); 98.49 + switch (pkgName) { 98.50 + case RUNTIME_PKG: 98.51 + case RUNTIME_LINKER_PKG: 98.52 + case OBJECTS_PKG: 98.53 + case SCRIPTS_PKG: 98.54 + // allow it. 98.55 + break; 98.56 + default: 98.57 + sm.checkPackageAccess(pkgName); 98.58 + } 98.59 } 98.60 } 98.61 } 98.62 98.63 + @Override 98.64 + protected PermissionCollection getPermissions(CodeSource codesource) { 98.65 + final Permissions permCollection = new Permissions(); 98.66 + for (final Permission perm : SCRIPT_PERMISSIONS) { 98.67 + permCollection.add(perm); 98.68 + } 98.69 + return permCollection; 98.70 + } 98.71 + 98.72 /** 98.73 * Create a secure URL class loader for the given classpath 98.74 * @param classPath classpath for the loader to search from
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 99.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Mon Apr 01 21:42:31 2013 -0700 99.3 @@ -0,0 +1,185 @@ 99.4 +/* 99.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 99.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 99.7 + * 99.8 + * This code is free software; you can redistribute it and/or modify it 99.9 + * under the terms of the GNU General Public License version 2 only, as 99.10 + * published by the Free Software Foundation. Oracle designates this 99.11 + * particular file as subject to the "Classpath" exception as provided 99.12 + * by Oracle in the LICENSE file that accompanied this code. 99.13 + * 99.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 99.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 99.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 99.17 + * version 2 for more details (a copy is included in the LICENSE file that 99.18 + * accompanied this code). 99.19 + * 99.20 + * You should have received a copy of the GNU General Public License version 99.21 + * 2 along with this work; if not, write to the Free Software Foundation, 99.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 99.23 + * 99.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 99.25 + * or visit www.oracle.com if you need additional information or have any 99.26 + * questions. 99.27 + */ 99.28 + 99.29 +package jdk.nashorn.internal.runtime; 99.30 + 99.31 +import java.lang.invoke.MethodHandle; 99.32 +import java.lang.invoke.MethodHandles; 99.33 +import java.lang.invoke.MethodType; 99.34 + 99.35 +import jdk.nashorn.internal.codegen.Compiler; 99.36 +import jdk.nashorn.internal.codegen.CompilerConstants; 99.37 +import jdk.nashorn.internal.codegen.FunctionSignature; 99.38 +import jdk.nashorn.internal.ir.FunctionNode; 99.39 +import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 99.40 +import jdk.nashorn.internal.parser.Token; 99.41 +import jdk.nashorn.internal.parser.TokenType; 99.42 + 99.43 +import static jdk.nashorn.internal.lookup.Lookup.MH; 99.44 + 99.45 +/** 99.46 + * This is a subclass that represents a script function that may be regenerated, 99.47 + * for example with specialization based on call site types, or lazily generated. 99.48 + * The common denominator is that it can get new invokers during its lifespan, 99.49 + * unlike {@link FinalScriptFunctionData} 99.50 + */ 99.51 +public final class RecompilableScriptFunctionData extends ScriptFunctionData { 99.52 + 99.53 + private final FunctionNode functionNode; 99.54 + private final PropertyMap allocatorMap; 99.55 + private final CodeInstaller<ScriptEnvironment> installer; 99.56 + private final String allocatorClassName; 99.57 + 99.58 + /** lazily generated allocator */ 99.59 + private MethodHandle allocator; 99.60 + 99.61 + private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); 99.62 + 99.63 + /** 99.64 + * Constructor - public as scripts use it 99.65 + * 99.66 + * @param functionNode functionNode that represents this function code 99.67 + * @param installer installer for code regeneration versions of this function 99.68 + * @param allocatorClassName name of our allocator class, will be looked up dynamically if used as a constructor 99.69 + * @param allocatorMap allocator map to seed instances with, when constructing 99.70 + */ 99.71 + public RecompilableScriptFunctionData(final FunctionNode functionNode, final CodeInstaller<ScriptEnvironment> installer, final String allocatorClassName, final PropertyMap allocatorMap) { 99.72 + super(functionNode.isAnonymous() ? 99.73 + "" : 99.74 + functionNode.getIdent().getName(), 99.75 + functionNode.getParameters().size(), 99.76 + functionNode.isStrictMode(), 99.77 + false, 99.78 + true); 99.79 + 99.80 + this.functionNode = functionNode; 99.81 + this.installer = installer; 99.82 + this.allocatorClassName = allocatorClassName; 99.83 + this.allocatorMap = allocatorMap; 99.84 + } 99.85 + 99.86 + @Override 99.87 + String toSource() { 99.88 + final Source source = functionNode.getSource(); 99.89 + final long token = tokenFor(functionNode); 99.90 + 99.91 + if (source != null && token != 0) { 99.92 + return source.getString(Token.descPosition(token), Token.descLength(token)); 99.93 + } 99.94 + 99.95 + return "function " + (name == null ? "" : name) + "() { [native code] }"; 99.96 + } 99.97 + 99.98 + @Override 99.99 + public String toString() { 99.100 + final StringBuilder sb = new StringBuilder(); 99.101 + final Source source = functionNode.getSource(); 99.102 + final long token = tokenFor(functionNode); 99.103 + 99.104 + if (source != null) { 99.105 + sb.append(source.getName()) 99.106 + .append(':') 99.107 + .append(source.getLine(Token.descPosition(token))) 99.108 + .append(' '); 99.109 + } 99.110 + 99.111 + return sb.toString() + super.toString(); 99.112 + } 99.113 + 99.114 + private static long tokenFor(final FunctionNode fn) { 99.115 + final int position = Token.descPosition(fn.getFirstToken()); 99.116 + final int length = Token.descPosition(fn.getLastToken()) - position + Token.descLength(fn.getLastToken()); 99.117 + 99.118 + return Token.toDesc(TokenType.FUNCTION, position, length); 99.119 + } 99.120 + 99.121 + @Override 99.122 + ScriptObject allocate() { 99.123 + try { 99.124 + ensureHasAllocator(); //if allocatorClass name is set to null (e.g. for bound functions) we don't even try 99.125 + return allocator == null ? null : (ScriptObject)allocator.invokeExact(allocatorMap); 99.126 + } catch (final RuntimeException | Error e) { 99.127 + throw e; 99.128 + } catch (final Throwable t) { 99.129 + throw new RuntimeException(t); 99.130 + } 99.131 + } 99.132 + 99.133 + private void ensureHasAllocator() throws ClassNotFoundException { 99.134 + if (allocator == null && allocatorClassName != null) { 99.135 + this.allocator = MH.findStatic(LOOKUP, Context.forStructureClass(allocatorClassName), CompilerConstants.ALLOCATE.tag(), MH.type(ScriptObject.class, PropertyMap.class)); 99.136 + } 99.137 + } 99.138 + 99.139 + @Override 99.140 + protected void ensureCodeGenerated() { 99.141 + if (!code.isEmpty()) { 99.142 + return; // nothing to do, we have code, at least some. 99.143 + } 99.144 + 99.145 + // check if function node is lazy, need to compile it. 99.146 + // note that currently function cloning is not working completely, which 99.147 + // means that the compiler will mutate the function node it has been given 99.148 + // once it has been compiled, it cannot be recompiled. This means that 99.149 + // lazy compilation works (not compiled yet) but e.g. specializations won't 99.150 + // until the copy-on-write changes for IR are in, making cloning meaningless. 99.151 + // therefore, currently method specialization is disabled. TODO 99.152 + 99.153 + if (functionNode.isLazy()) { 99.154 + Compiler.LOG.info("Trampoline hit: need to do lazy compilation of '" + functionNode.getName() + "'"); 99.155 + new Compiler(installer, functionNode).compile().install(); 99.156 + 99.157 + // we don't need to update any flags - varArgs and needsCallee are instrincic 99.158 + // in the function world we need to get a destination node from the compile instead 99.159 + // and replace it with our function node. TODO 99.160 + } 99.161 + 99.162 + // we can't get here unless we have bytecode, either from eager compilation or from 99.163 + // running a lazy compile on the lines above 99.164 + 99.165 + assert functionNode.hasState(CompilationState.INSTALLED); 99.166 + 99.167 + // code exists - look it up and add it into the automatically sorted invoker list 99.168 + code.add( 99.169 + new CompiledFunction( 99.170 + MH.findStatic( 99.171 + LOOKUP, 99.172 + functionNode.getCompileUnit().getCode(), 99.173 + functionNode.getName(), 99.174 + new FunctionSignature(functionNode). 99.175 + getMethodType()))); 99.176 + } 99.177 + 99.178 + @Override 99.179 + MethodHandle getBestInvoker(final MethodType callSiteType, final Object[] args) { 99.180 + final MethodHandle mh = super.getBestInvoker(callSiteType, args); 99.181 + if (code.isLessSpecificThan(callSiteType)) { 99.182 + // opportunity for code specialization - we can regenerate a better version of this method 99.183 + } 99.184 + return mh; 99.185 + } 99.186 + 99.187 +} 99.188 +
100.1 --- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Thu Mar 28 10:55:17 2013 -0700 100.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Mon Apr 01 21:42:31 2013 -0700 100.3 @@ -82,6 +82,9 @@ 100.4 /** Show full Nashorn version */ 100.5 public final boolean _fullversion; 100.6 100.7 + /** Should lazy compilation take place */ 100.8 + public final boolean _lazy_compilation; 100.9 + 100.10 /** Create a new class loaded for each compilation */ 100.11 public final boolean _loader_per_compile; 100.12 100.13 @@ -155,6 +158,7 @@ 100.14 _early_lvalue_error = options.getBoolean("early.lvalue.error"); 100.15 _empty_statements = options.getBoolean("empty.statements"); 100.16 _fullversion = options.getBoolean("fullversion"); 100.17 + _lazy_compilation = options.getBoolean("lazy.compilation"); 100.18 _loader_per_compile = options.getBoolean("loader.per.compile"); 100.19 _no_syntax_extensions = options.getBoolean("no.syntax.extensions"); 100.20 _package = options.getString("package");
101.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Mar 28 10:55:17 2013 -0700 101.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java Mon Apr 01 21:42:31 2013 -0700 101.3 @@ -33,11 +33,11 @@ 101.4 import java.lang.invoke.MethodHandle; 101.5 import java.lang.invoke.MethodHandles; 101.6 import java.lang.invoke.MethodType; 101.7 + 101.8 import jdk.internal.dynalink.CallSiteDescriptor; 101.9 import jdk.internal.dynalink.linker.GuardedInvocation; 101.10 import jdk.internal.dynalink.linker.LinkRequest; 101.11 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 101.12 -import jdk.nashorn.internal.objects.annotations.SpecializedFunction; 101.13 import jdk.nashorn.internal.lookup.MethodHandleFactory; 101.14 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; 101.15 import jdk.nashorn.internal.runtime.linker.NashornGuards; 101.16 @@ -48,16 +48,16 @@ 101.17 public abstract class ScriptFunction extends ScriptObject { 101.18 101.19 /** Method handle for prototype getter for this ScriptFunction */ 101.20 - public static final MethodHandle G$PROTOTYPE = findOwnMH("G$prototype", Object.class, Object.class); 101.21 + public static final MethodHandle G$PROTOTYPE = findOwnMH("G$prototype", Object.class, Object.class); 101.22 101.23 /** Method handle for prototype setter for this ScriptFunction */ 101.24 - public static final MethodHandle S$PROTOTYPE = findOwnMH("S$prototype", void.class, Object.class, Object.class); 101.25 + public static final MethodHandle S$PROTOTYPE = findOwnMH("S$prototype", void.class, Object.class, Object.class); 101.26 101.27 /** Method handle for length getter for this ScriptFunction */ 101.28 - public static final MethodHandle G$LENGTH = findOwnMH("G$length", int.class, Object.class); 101.29 + public static final MethodHandle G$LENGTH = findOwnMH("G$length", int.class, Object.class); 101.30 101.31 /** Method handle for name getter for this ScriptFunction */ 101.32 - public static final MethodHandle G$NAME = findOwnMH("G$name", Object.class, Object.class); 101.33 + public static final MethodHandle G$NAME = findOwnMH("G$name", Object.class, Object.class); 101.34 101.35 /** Method handle for allocate function for this ScriptFunction */ 101.36 static final MethodHandle ALLOCATE = findOwnMH("allocate", Object.class); 101.37 @@ -67,7 +67,9 @@ 101.38 /** method handle to scope getter for this ScriptFunction */ 101.39 public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class); 101.40 101.41 - private final ScriptFunctionData data; 101.42 + private static final MethodHandle IS_FUNCTION_MH = findOwnMH("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class); 101.43 + 101.44 + private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class); 101.45 101.46 /** Reference to constructor prototype. */ 101.47 protected Object prototype; 101.48 @@ -75,6 +77,8 @@ 101.49 /** The parent scope. */ 101.50 private final ScriptObject scope; 101.51 101.52 + private final ScriptFunctionData data; 101.53 + 101.54 /** 101.55 * Constructor 101.56 * 101.57 @@ -97,7 +101,7 @@ 101.58 final boolean builtin, 101.59 final boolean isConstructor) { 101.60 101.61 - this (new ScriptFunctionData(name, methodHandle, specs, strict, builtin, isConstructor), map, scope); 101.62 + this(new FinalScriptFunctionData(name, methodHandle, specs, strict, builtin, isConstructor), map, scope); 101.63 } 101.64 101.65 /** 101.66 @@ -118,8 +122,8 @@ 101.67 constructorCount++; 101.68 } 101.69 101.70 - this.data = data; 101.71 - this.scope = scope; 101.72 + this.data = data; 101.73 + this.scope = scope; 101.74 } 101.75 101.76 @Override 101.77 @@ -295,20 +299,20 @@ 101.78 /** 101.79 * Return the most appropriate invoke handle if there are specializations 101.80 * @param type most specific method type to look for invocation with 101.81 + * @param callsite args for trampoline invocation 101.82 * @return invoke method handle 101.83 */ 101.84 - private final MethodHandle getBestInvoker(final MethodType type) { 101.85 - return data.getBestInvoker(type); 101.86 + private MethodHandle getBestInvoker(final MethodType type, final Object[] args) { 101.87 + return data.getBestInvoker(type, args); 101.88 } 101.89 101.90 /** 101.91 - * Get the invoke handle - the most generic (and if no specializations are in place, only) invocation 101.92 - * method handle for this ScriptFunction 101.93 - * @see SpecializedFunction 101.94 - * @return invokeHandle 101.95 + * Return the most appropriate invoke handle if there are specializations 101.96 + * @param type most specific method type to look for invocation with 101.97 + * @return invoke method handle 101.98 */ 101.99 - public final MethodHandle getInvokeHandle() { 101.100 - return data.getInvoker(); 101.101 + public MethodHandle getBestInvoker(final MethodType type) { 101.102 + return getBestInvoker(type, null); 101.103 } 101.104 101.105 /** 101.106 @@ -319,7 +323,7 @@ 101.107 * @return bound invoke handle 101.108 */ 101.109 public final MethodHandle getBoundInvokeHandle(final ScriptObject self) { 101.110 - return MH.bindTo(bindToCalleeIfNeeded(getInvokeHandle()), self); 101.111 + return MH.bindTo(bindToCalleeIfNeeded(data.getGenericInvoker()), self); 101.112 } 101.113 101.114 /** 101.115 @@ -329,7 +333,8 @@ 101.116 * @return the potentially bound method handle 101.117 */ 101.118 private MethodHandle bindToCalleeIfNeeded(final MethodHandle methodHandle) { 101.119 - return data.needsCallee() ? MH.bindTo(methodHandle, this) : methodHandle; 101.120 + return ScriptFunctionData.needsCallee(methodHandle) ? MH.bindTo(methodHandle, this) : methodHandle; 101.121 + 101.122 } 101.123 101.124 /** 101.125 @@ -340,15 +345,6 @@ 101.126 return data.getName(); 101.127 } 101.128 101.129 - /** 101.130 - * Does this script function need to be compiled. This determined by 101.131 - * null checking invokeHandle 101.132 - * 101.133 - * @return true if this needs compilation 101.134 - */ 101.135 - public final boolean needsCompilation() { 101.136 - return data.getInvoker() == null; 101.137 - } 101.138 101.139 /** 101.140 * Get the scope for this function 101.141 @@ -359,15 +355,6 @@ 101.142 } 101.143 101.144 /** 101.145 - * Reset the invoker handle. This is used by trampolines for 101.146 - * lazy code generation 101.147 - * @param invoker new invoker 101.148 - */ 101.149 - protected void resetInvoker(final MethodHandle invoker) { 101.150 - data.resetInvoker(invoker); 101.151 - } 101.152 - 101.153 - /** 101.154 * Prototype getter for this ScriptFunction - follows the naming convention 101.155 * used by Nasgen and the code generator 101.156 * 101.157 @@ -464,7 +451,7 @@ 101.158 @Override 101.159 protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc) { 101.160 final MethodType type = desc.getMethodType(); 101.161 - return new GuardedInvocation(pairArguments(data.getBestConstructor(type), type), null, NashornGuards.getFunctionGuard(this)); 101.162 + return new GuardedInvocation(pairArguments(data.getBestConstructor(type.changeParameterType(0, ScriptFunction.class), null), type), null, getFunctionGuard(this)); 101.163 } 101.164 101.165 @SuppressWarnings("unused") 101.166 @@ -472,7 +459,7 @@ 101.167 if (obj instanceof ScriptObject || !ScriptFunctionData.isPrimitiveThis(obj)) { 101.168 return obj; 101.169 } 101.170 - return ((GlobalObject) Context.getGlobalTrusted()).wrapAsObject(obj); 101.171 + return ((GlobalObject)Context.getGlobalTrusted()).wrapAsObject(obj); 101.172 } 101.173 101.174 /** 101.175 @@ -506,8 +493,7 @@ 101.176 MethodHandle guard = null; 101.177 101.178 if (data.needsCallee()) { 101.179 - final MethodHandle callHandle = getBestInvoker(type); 101.180 - 101.181 + final MethodHandle callHandle = getBestInvoker(type, request.getArguments()); 101.182 if (NashornCallSiteDescriptor.isScope(desc)) { 101.183 // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined 101.184 // (callee, this, args...) => (callee, args...) 101.185 @@ -525,13 +511,12 @@ 101.186 if (ScriptFunctionData.isPrimitiveThis(request.getArguments()[1])) { 101.187 boundHandle = MH.filterArguments(boundHandle, 1, WRAPFILTER); 101.188 } else { 101.189 - guard = NashornGuards.getNonStrictFunctionGuard(this); 101.190 + guard = getNonStrictFunctionGuard(this); 101.191 } 101.192 } 101.193 } 101.194 } else { 101.195 - final MethodHandle callHandle = getBestInvoker(type.dropParameterTypes(0, 1)); 101.196 - 101.197 + final MethodHandle callHandle = getBestInvoker(type.dropParameterTypes(0, 1), request.getArguments()); 101.198 if (NashornCallSiteDescriptor.isScope(desc)) { 101.199 // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined 101.200 // (this, args...) => (args...) 101.201 @@ -545,7 +530,8 @@ 101.202 } 101.203 101.204 boundHandle = pairArguments(boundHandle, type); 101.205 - return new GuardedInvocation(boundHandle, guard == null ? NashornGuards.getFunctionGuard(this) : guard); 101.206 + 101.207 + return new GuardedInvocation(boundHandle, guard == null ? getFunctionGuard(this) : guard); 101.208 } 101.209 101.210 /** 101.211 @@ -554,13 +540,50 @@ 101.212 * These don't want a callee parameter, so bind that. Name binding is optional. 101.213 */ 101.214 MethodHandle getCallMethodHandle(final MethodType type, final String bindName) { 101.215 - return pairArguments(bindToNameIfNeeded(bindToCalleeIfNeeded(getBestInvoker(type)), bindName), type); 101.216 + return pairArguments(bindToNameIfNeeded(bindToCalleeIfNeeded(getBestInvoker(type, null)), bindName), type); 101.217 } 101.218 101.219 private static MethodHandle bindToNameIfNeeded(final MethodHandle methodHandle, final String bindName) { 101.220 return bindName == null ? methodHandle : MH.insertArguments(methodHandle, 1, bindName); 101.221 } 101.222 101.223 + /** 101.224 + * Get the guard that checks if a {@link ScriptFunction} is equal to 101.225 + * a known ScriptFunction, using reference comparison 101.226 + * 101.227 + * @param function The ScriptFunction to check against. This will be bound to the guard method handle 101.228 + * 101.229 + * @return method handle for guard 101.230 + */ 101.231 + private static MethodHandle getFunctionGuard(final ScriptFunction function) { 101.232 + assert function.data != null; 101.233 + return MH.insertArguments(IS_FUNCTION_MH, 1, function.data); 101.234 + } 101.235 + 101.236 + /** 101.237 + * Get a guard that checks if a {@link ScriptFunction} is equal to 101.238 + * a known ScriptFunction using reference comparison, and whether the type of 101.239 + * the second argument (this-object) is not a JavaScript primitive type. 101.240 + * 101.241 + * @param function The ScriptFunction to check against. This will be bound to the guard method handle 101.242 + * 101.243 + * @return method handle for guard 101.244 + */ 101.245 + private static MethodHandle getNonStrictFunctionGuard(final ScriptFunction function) { 101.246 + assert function.data != null; 101.247 + return MH.insertArguments(IS_NONSTRICT_FUNCTION, 2, function.data); 101.248 + } 101.249 + 101.250 + @SuppressWarnings("unused") 101.251 + private static boolean isFunctionMH(final Object self, final ScriptFunctionData data) { 101.252 + return self instanceof ScriptFunction && ((ScriptFunction)self).data == data; 101.253 + } 101.254 + 101.255 + @SuppressWarnings("unused") 101.256 + private static boolean isNonStrictFunction(final Object self, final Object arg, final ScriptFunctionData data) { 101.257 + return self instanceof ScriptFunction && ((ScriptFunction)self).data == data && arg instanceof ScriptObject; 101.258 + } 101.259 + 101.260 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { 101.261 final Class<?> own = ScriptFunction.class; 101.262 final MethodType mt = MH.type(rtype, types);
102.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Thu Mar 28 10:55:17 2013 -0700 102.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Mon Apr 01 21:42:31 2013 -0700 102.3 @@ -32,227 +32,94 @@ 102.4 import java.lang.invoke.MethodHandle; 102.5 import java.lang.invoke.MethodHandles; 102.6 import java.lang.invoke.MethodType; 102.7 -import jdk.nashorn.internal.ir.FunctionNode; 102.8 -import jdk.nashorn.internal.parser.Token; 102.9 -import jdk.nashorn.internal.parser.TokenType; 102.10 + 102.11 +import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory; 102.12 102.13 /** 102.14 * A container for data needed to instantiate a specific {@link ScriptFunction} at runtime. 102.15 * Instances of this class are created during codegen and stored in script classes' 102.16 * constants array to reduce function instantiation overhead during runtime. 102.17 */ 102.18 -public final class ScriptFunctionData { 102.19 +public abstract class ScriptFunctionData { 102.20 + 102.21 + /** Name of the function or "" for anonynous functions */ 102.22 + protected final String name; 102.23 + 102.24 + /** All versions of this function that have been generated to code */ 102.25 + protected final CompiledFunctions code; 102.26 + 102.27 + private int arity; 102.28 + 102.29 + private final boolean isStrict; 102.30 + 102.31 + private final boolean isBuiltin; 102.32 + 102.33 + private final boolean isConstructor; 102.34 + 102.35 + private static final MethodHandle NEWFILTER = findOwnMH("newFilter", Object.class, Object.class, Object.class); 102.36 private static final MethodHandle BIND_VAR_ARGS = findOwnMH("bindVarArgs", Object[].class, Object[].class, Object[].class); 102.37 - private static final MethodHandle NEWFILTER = findOwnMH("newFilter", Object.class, Object.class, Object.class); 102.38 - 102.39 - // per-function object flags 102.40 - private static final int IS_STRICT = 0b0000_0001; 102.41 - private static final int IS_BUILTIN = 0b0000_0010; 102.42 - private static final int HAS_CALLEE = 0b0000_0100; 102.43 - private static final int IS_VARARGS = 0b0000_1000; 102.44 - private static final int IS_CONSTRUCTOR = 0b0001_0000; 102.45 - 102.46 - /** Name of the function or "" */ 102.47 - private final String name; 102.48 - /** Source of this function, or null */ 102.49 - private final Source source; 102.50 - /** Map for new instance constructor */ 102.51 - private PropertyMap allocatorMap; 102.52 - /** Start position and length in source */ 102.53 - private final long token; 102.54 - /** Number of expected arguments, either taken from FunctionNode or calculated from method handle signature*/ 102.55 - private int arity; 102.56 - private final int flags; 102.57 - 102.58 - /** Reference to code for this method. */ 102.59 - private MethodHandle invoker; 102.60 - /** Reference to code for this method when called to create "new" object. This must always be populated with a 102.61 - * result of calling {@link #composeConstructor(MethodHandle)} on the value of the {@link #invoker} field. */ 102.62 - private MethodHandle constructor; 102.63 - /** Constructor to create a new instance. */ 102.64 - private MethodHandle allocator; 102.65 - /** Generic invoker to used in {@link ScriptFunction#invoke(Object, Object...)}. */ 102.66 - private MethodHandle genericInvoker; 102.67 - /** Specializations - see @SpecializedFunction */ 102.68 - private MethodHandle[] invokeSpecializations; 102.69 - /** Specializations - see @SpecializedFunction. Same restrictions as for {@link #constructor} apply; only populate 102.70 - * with method handles returned from {@link #composeConstructor(MethodHandle)}. */ 102.71 - private MethodHandle[] constructSpecializations; 102.72 - 102.73 - /** 102.74 - * Constructor 102.75 - * @param fn the function node 102.76 - * @param allocatorMap the allocator property map 102.77 - */ 102.78 - public ScriptFunctionData(final FunctionNode fn, final PropertyMap allocatorMap) { 102.79 - 102.80 - final long firstToken = fn.getFirstToken(); 102.81 - final long lastToken = fn.getLastToken(); 102.82 - final int position = Token.descPosition(firstToken); 102.83 - final int length = Token.descPosition(lastToken) - position + Token.descLength(lastToken); 102.84 - 102.85 - this.name = fn.isAnonymous() ? "" : fn.getIdent().getName(); 102.86 - this.source = fn.getSource(); 102.87 - this.allocatorMap = allocatorMap; 102.88 - this.token = Token.toDesc(TokenType.FUNCTION, position, length); 102.89 - this.arity = fn.getParameters().size(); 102.90 - this.flags = makeFlags(fn.needsCallee(), fn.isVarArg(), fn.isStrictMode(), false, true); 102.91 - } 102.92 102.93 /** 102.94 * Constructor 102.95 * 102.96 - * @param name the function name 102.97 - * @param methodHandle the method handle 102.98 - * @param specs array of specialized method handles 102.99 - * @param strict strict flag 102.100 - * @param builtin builtin flag 102.101 - * @param isConstructor constructor flags 102.102 + * @param name script function name 102.103 + * @param arity arity 102.104 + * @param isStrict is the function strict 102.105 + * @param isBuiltin is the function built in 102.106 + * @param isConstructor is the function a constructor 102.107 */ 102.108 - public ScriptFunctionData(final String name, final MethodHandle methodHandle, final MethodHandle[] specs, final boolean strict, final boolean builtin, final boolean isConstructor) { 102.109 - this(name, null, 0L, methodHandle, specs, strict, builtin, isConstructor); 102.110 + protected ScriptFunctionData(final String name, final int arity, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) { 102.111 + this.name = name; 102.112 + this.arity = arity; 102.113 + this.code = new CompiledFunctions(); 102.114 + this.isStrict = isStrict; 102.115 + this.isBuiltin = isBuiltin; 102.116 + this.isConstructor = isConstructor; 102.117 } 102.118 102.119 - private ScriptFunctionData(final String name, final Source source, final long token, final MethodHandle methodHandle, final MethodHandle[] specs, final boolean strict, final boolean builtin, final boolean isConstructor) { 102.120 - this.name = name; 102.121 - this.source = source; 102.122 - this.token = token; 102.123 - 102.124 - final boolean isVarArg = isVarArg(methodHandle); 102.125 - final boolean needsCallee = needsCallee(methodHandle); 102.126 - 102.127 - this.flags = makeFlags(needsCallee, isVarArg, strict, builtin, isConstructor); 102.128 - int lArity = isVarArg ? -1 : methodHandle.type().parameterCount() - 1; //drop the self param for arity 102.129 - 102.130 - if (needsCallee && !isVarArg) { 102.131 - lArity--; 102.132 - } 102.133 - 102.134 - if (isConstructor(methodHandle)) { 102.135 - assert isConstructor; 102.136 - if (!isVarArg) { 102.137 - lArity--; // drop the boolean flag for arity 102.138 - } 102.139 - /* 102.140 - * We insert a boolean argument to tell if the method was invoked as constructor or not if the method 102.141 - * handle's first argument is boolean. 102.142 - */ 102.143 - this.invoker = MH.insertArguments(methodHandle, 0, false); 102.144 - this.constructor = composeConstructor(MH.insertArguments(methodHandle, 0, true)); 102.145 - 102.146 - if (specs != null) { 102.147 - this.invokeSpecializations = new MethodHandle[specs.length]; 102.148 - this.constructSpecializations = new MethodHandle[specs.length]; 102.149 - for (int i = 0; i < specs.length; i++) { 102.150 - this.invokeSpecializations[i] = MH.insertArguments(specs[i], 0, false); 102.151 - this.constructSpecializations[i] = composeConstructor(MH.insertArguments(specs[i], 0, true)); 102.152 - } 102.153 - } 102.154 - } else { 102.155 - this.invoker = methodHandle; 102.156 - this.constructor = null; // delay composition of the constructor 102.157 - this.invokeSpecializations = specs; 102.158 - this.constructSpecializations = null; // delay composition of the constructors 102.159 - } 102.160 - this.arity = lArity; 102.161 - } 102.162 - 102.163 - /** 102.164 - * Get the arity of the function. 102.165 - * @return the arity 102.166 - */ 102.167 - int getArity() { 102.168 + final int getArity() { 102.169 return arity; 102.170 } 102.171 102.172 /** 102.173 - * Set the arity of the function. 102.174 - * @param arity the arity 102.175 + * Used from e.g. Native*$Constructors as an explicit call. TODO - make arity immutable and final 102.176 + * @param arity new arity 102.177 */ 102.178 - void setArity(int arity) { 102.179 + void setArity(final int arity) { 102.180 this.arity = arity; 102.181 } 102.182 102.183 - /** 102.184 - * Get the function name. 102.185 - * @return function name 102.186 - */ 102.187 - String getName() { 102.188 - return name; 102.189 + CompiledFunction bind(final CompiledFunction originalInv, final ScriptFunction fn, final Object self, final Object[] args) { 102.190 + final MethodHandle boundInvoker = bindInvokeHandle(originalInv.getInvoker(), fn, self, args); 102.191 + 102.192 + if (isConstructor()) { 102.193 + ensureConstructor(originalInv); 102.194 + return new CompiledFunction(boundInvoker, bindConstructHandle(originalInv.getConstructor(), fn, args)); 102.195 + } 102.196 + 102.197 + return new CompiledFunction(boundInvoker); 102.198 } 102.199 102.200 /** 102.201 - * Get this function as a String containing its source code. If no source code 102.202 - * exists in this ScriptFunction, its contents will be displayed as {@code [native code]} 102.203 - * @return string representation of this function's source 102.204 + * Is this a ScriptFunction generated with strict semantics? 102.205 + * @return true if strict, false otherwise 102.206 */ 102.207 - String toSource() { 102.208 - if (source != null && token != 0) { 102.209 - return source.getString(Token.descPosition(token), Token.descLength(token)); 102.210 - } 102.211 - 102.212 - return "function " + (name == null ? "" : name) + "() { [native code] }"; 102.213 + public boolean isStrict() { 102.214 + return isStrict; 102.215 } 102.216 102.217 - @Override 102.218 - public String toString() { 102.219 - final StringBuilder sb = new StringBuilder(); 102.220 - 102.221 - sb.append(super.toString()) 102.222 - .append(" [ ") 102.223 - .append(invoker) 102.224 - .append(", ") 102.225 - .append((name == null || name.isEmpty()) ? "<anonymous>" : name); 102.226 - 102.227 - if (source != null) { 102.228 - sb.append(" @ ") 102.229 - .append(source.getName()) 102.230 - .append(':') 102.231 - .append(source.getLine(Token.descPosition(token))); 102.232 - } 102.233 - sb.append(" ]"); 102.234 - 102.235 - return sb.toString(); 102.236 + boolean isBuiltin() { 102.237 + return isBuiltin; 102.238 } 102.239 102.240 - /** 102.241 - * Returns true if the function needs a callee argument. 102.242 - * @return the needsCallee flag 102.243 - */ 102.244 - boolean needsCallee() { 102.245 - return (flags & HAS_CALLEE) != 0; 102.246 + boolean isConstructor() { 102.247 + return isConstructor; 102.248 } 102.249 102.250 - /** 102.251 - * Returns true if this is a strict-mode function. 102.252 - * @return the strict flag 102.253 - */ 102.254 - public boolean isStrict() { 102.255 - return (flags & IS_STRICT) != 0; 102.256 - } 102.257 - 102.258 - /** 102.259 - * Returns true if this is a built-in function. 102.260 - * @return the built-in flag 102.261 - */ 102.262 - private boolean isBuiltin() { 102.263 - return (flags & IS_BUILTIN) != 0; 102.264 - } 102.265 - 102.266 - /** 102.267 - * Returns true if this function can be used as a constructor. 102.268 - * @return the constructor flag 102.269 - */ 102.270 - private boolean isConstructor() { 102.271 - return (flags & IS_CONSTRUCTOR) != 0; 102.272 - } 102.273 - 102.274 - /** 102.275 - * Returns true if this is a var-arg function. 102.276 - * @return the var-arg flag 102.277 - */ 102.278 - private boolean isVarArg() { 102.279 - return (flags & IS_VARARGS) != 0; 102.280 + boolean needsCallee() { 102.281 + // we don't know if we need a callee or not unless we are generated 102.282 + ensureCodeGenerated(); 102.283 + return code.needsCallee(); 102.284 } 102.285 102.286 /** 102.287 @@ -261,127 +128,408 @@ 102.288 * @return true if this argument must be an object 102.289 */ 102.290 boolean needsWrappedThis() { 102.291 - return (flags & (IS_STRICT | IS_BUILTIN)) == 0; 102.292 + return !isStrict && !isBuiltin; 102.293 + } 102.294 + 102.295 + String toSource() { 102.296 + return "function " + (name == null ? "" : name) + "() { [native code] }"; 102.297 + } 102.298 + 102.299 + String getName() { 102.300 + return name; 102.301 } 102.302 102.303 /** 102.304 - * Get the method handle used to invoke this function. 102.305 - * @return the invoke handle 102.306 + * Get this function as a String containing its source code. If no source code 102.307 + * exists in this ScriptFunction, its contents will be displayed as {@code [native code]} 102.308 + * 102.309 + * @return string representation of this function 102.310 */ 102.311 - MethodHandle getInvoker() { 102.312 - return invoker; 102.313 - } 102.314 + @Override 102.315 + public String toString() { 102.316 + final StringBuilder sb = new StringBuilder(); 102.317 102.318 - MethodHandle getBestInvoker(final MethodType type) { 102.319 - return SpecializedMethodChooser.candidateWithLowestWeight(type, invoker, invokeSpecializations); 102.320 + sb.append("name='"). 102.321 + append(name.isEmpty() ? "<anonymous>" : name). 102.322 + append("' "). 102.323 + append(code.size()). 102.324 + append(" invokers="). 102.325 + append(code); 102.326 + 102.327 + return sb.toString(); 102.328 } 102.329 102.330 /** 102.331 - * Get the method handle used to invoke this function as a constructor. 102.332 - * @return the constructor handle 102.333 + * Pick the best invoker, i.e. the one version of this method with as narrow and specific 102.334 + * types as possible. If the call site arguments are objects, but boxed primitives we can 102.335 + * also try to get a primitive version of the method and do an unboxing filter, but then 102.336 + * we need to insert a guard that checks the argument is really always a boxed primitive 102.337 + * and not suddenly a "real" object 102.338 + * 102.339 + * @param callSiteType callsite type 102.340 + * @param args arguments at callsite on first trampoline invocation 102.341 + * @return method handle to best invoker 102.342 */ 102.343 - private MethodHandle getConstructor() { 102.344 - if (constructor == null) { 102.345 - constructor = composeConstructor(invoker); 102.346 - } 102.347 - 102.348 - return constructor; 102.349 + MethodHandle getBestInvoker(final MethodType callSiteType, final Object[] args) { 102.350 + return getBest(callSiteType).getInvoker(); 102.351 } 102.352 102.353 - MethodHandle getBestConstructor(MethodType descType) { 102.354 + MethodHandle getBestInvoker(final MethodType callSiteType) { 102.355 + return getBestInvoker(callSiteType, null); 102.356 + } 102.357 + 102.358 + MethodHandle getBestConstructor(final MethodType callSiteType, final Object[] args) { 102.359 if (!isConstructor()) { 102.360 throw typeError("not.a.constructor", toSource()); 102.361 } 102.362 - return SpecializedMethodChooser.candidateWithLowestWeight(descType, getConstructor(), getConstructSpecializations()); 102.363 + ensureCodeGenerated(); 102.364 + 102.365 + final CompiledFunction best = getBest(callSiteType); 102.366 + ensureConstructor(best); 102.367 + return best.getConstructor(); 102.368 } 102.369 102.370 - private MethodHandle composeConstructor(MethodHandle ctor) { 102.371 + MethodHandle getBestConstructor(final MethodType callSiteType) { 102.372 + return getBestConstructor(callSiteType, null); 102.373 + } 102.374 + 102.375 + /** 102.376 + * Subclass responsibility. If we can have lazy code generation, this is a hook to ensure that 102.377 + * code exists before performing an operation. 102.378 + */ 102.379 + protected void ensureCodeGenerated() { 102.380 + //empty 102.381 + } 102.382 + 102.383 + /** 102.384 + * Return a generic Object/Object invoker for this method. It will ensure code 102.385 + * is generated, get the most generic of all versions of this function and adapt it 102.386 + * to Objects. 102.387 + * 102.388 + * TODO this is only public because {@link JavaAdapterFactory} can't supply us with 102.389 + * a MethodType that we can use for lookup due to boostrapping problems. Can be fixed 102.390 + * 102.391 + * @return generic invoker of this script function 102.392 + */ 102.393 + public final MethodHandle getGenericInvoker() { 102.394 + ensureCodeGenerated(); 102.395 + return composeGenericMethod(code.mostGeneric().getInvoker()); 102.396 + } 102.397 + 102.398 + private CompiledFunction getBest(final MethodType callSiteType) { 102.399 + ensureCodeGenerated(); 102.400 + return code.best(callSiteType); 102.401 + } 102.402 + 102.403 + /** 102.404 + * Allocates an object using this function's allocator. 102.405 + * @return the object allocated using this function's allocator, or null if the function doesn't have an allocator. 102.406 + */ 102.407 + ScriptObject allocate() { 102.408 + return null; 102.409 + } 102.410 + 102.411 + /** 102.412 + * This method is used to create the immutable portion of a bound function. 102.413 + * See {@link ScriptFunction#makeBoundFunction(Object, Object[])} 102.414 + * 102.415 + * @param fn the original function being bound 102.416 + * @param self this reference to bind. Can be null. 102.417 + * @param args additional arguments to bind. Can be null. 102.418 + */ 102.419 + ScriptFunctionData makeBoundFunctionData(final ScriptFunction fn, final Object self, final Object[] args) { 102.420 + ensureCodeGenerated(); 102.421 + 102.422 + final Object[] allArgs = args == null ? ScriptRuntime.EMPTY_ARRAY : args; 102.423 + final int length = args == null ? 0 : args.length; 102.424 + 102.425 + CompiledFunctions boundList = new CompiledFunctions(); 102.426 + for (final CompiledFunction inv : code) { 102.427 + boundList.add(bind(inv, fn, self, allArgs)); 102.428 + } 102.429 + ScriptFunctionData boundData = new FinalScriptFunctionData(name, arity == -1 ? -1 : Math.max(0, arity - length), boundList, isStrict(), isBuiltin(), isConstructor()); 102.430 + return boundData; 102.431 + } 102.432 + 102.433 + /** 102.434 + * Compose a constructor given a primordial constructor handle 102.435 + * 102.436 + * @param ctor primordial constructor handle 102.437 + * @param needsCallee do we need to pass a callee 102.438 + * 102.439 + * @return the composed constructor 102.440 + */ 102.441 + protected MethodHandle composeConstructor(final MethodHandle ctor, final boolean needsCallee) { 102.442 // If it was (callee, this, args...), permute it to (this, callee, args...). We're doing this because having 102.443 // "this" in the first argument position is what allows the elegant folded composition of 102.444 // (newFilter x constructor x allocator) further down below in the code. Also, ensure the composite constructor 102.445 // always returns Object. 102.446 - MethodHandle composedCtor = changeReturnTypeToObject(swapCalleeAndThis(ctor)); 102.447 + MethodHandle composedCtor = needsCallee ? swapCalleeAndThis(ctor) : ctor; 102.448 + 102.449 + composedCtor = changeReturnTypeToObject(composedCtor); 102.450 102.451 final MethodType ctorType = composedCtor.type(); 102.452 + 102.453 // Construct a dropping type list for NEWFILTER, but don't include constructor "this" into it, so it's actually 102.454 // captured as "allocation" parameter of NEWFILTER after we fold the constructor into it. 102.455 // (this, [callee, ]args...) => ([callee, ]args...) 102.456 final Class<?>[] ctorArgs = ctorType.dropParameterTypes(0, 1).parameterArray(); 102.457 + 102.458 // Fold constructor into newFilter that replaces the return value from the constructor with the originally 102.459 // allocated value when the originally allocated value is a primitive. 102.460 // (result, this, [callee, ]args...) x (this, [callee, ]args...) => (this, [callee, ]args...) 102.461 composedCtor = MH.foldArguments(MH.dropArguments(NEWFILTER, 2, ctorArgs), composedCtor); 102.462 102.463 // allocate() takes a ScriptFunction and returns a newly allocated ScriptObject... 102.464 - if (needsCallee()) { 102.465 + if (needsCallee) { 102.466 // ...we either fold it into the previous composition, if we need both the ScriptFunction callee object and 102.467 // the newly allocated object in the arguments, so (this, callee, args...) x (callee) => (callee, args...), 102.468 // or... 102.469 return MH.foldArguments(composedCtor, ScriptFunction.ALLOCATE); 102.470 } 102.471 + 102.472 // ...replace the ScriptFunction argument with the newly allocated object, if it doesn't need the callee 102.473 // (this, args...) filter (callee) => (callee, args...) 102.474 return MH.filterArguments(composedCtor, 0, ScriptFunction.ALLOCATE); 102.475 } 102.476 102.477 /** 102.478 - * Get an adapted version of the invoker handle that only uses {@code Object} as parameter and return types. 102.479 - * @return the generic invoke handle 102.480 + * If this function's method handles need a callee parameter, swap the order of first two arguments for the passed 102.481 + * method handle. If this function's method handles don't need a callee parameter, returns the original method 102.482 + * handle unchanged. 102.483 + * 102.484 + * @param mh a method handle with order of arguments {@code (callee, this, args...)} 102.485 + * 102.486 + * @return a method handle with order of arguments {@code (this, callee, args...)} 102.487 */ 102.488 - private MethodHandle getGenericInvoker() { 102.489 - if (genericInvoker == null) { 102.490 - assert invoker != null : "invoker is null"; 102.491 - genericInvoker = makeGenericMethod(invoker); 102.492 + private static MethodHandle swapCalleeAndThis(final MethodHandle mh) { 102.493 + final MethodType type = mh.type(); 102.494 + assert type.parameterType(0) == ScriptFunction.class : type; 102.495 + assert type.parameterType(1) == Object.class : type; 102.496 + final MethodType newType = type.changeParameterType(0, Object.class).changeParameterType(1, ScriptFunction.class); 102.497 + final int[] reorder = new int[type.parameterCount()]; 102.498 + reorder[0] = 1; 102.499 + assert reorder[1] == 0; 102.500 + for (int i = 2; i < reorder.length; ++i) { 102.501 + reorder[i] = i; 102.502 } 102.503 - return genericInvoker; 102.504 + return MethodHandles.permuteArguments(mh, newType, reorder); 102.505 + } 102.506 + 102.507 + /** 102.508 + * Convert this argument for non-strict functions according to ES 10.4.3 102.509 + * 102.510 + * @param thiz the this argument 102.511 + * 102.512 + * @return the converted this object 102.513 + */ 102.514 + private Object convertThisObject(final Object thiz) { 102.515 + if (!(thiz instanceof ScriptObject) && needsWrappedThis()) { 102.516 + if (JSType.nullOrUndefined(thiz)) { 102.517 + return Context.getGlobalTrusted(); 102.518 + } 102.519 + 102.520 + if (isPrimitiveThis(thiz)) { 102.521 + return ((GlobalObject)Context.getGlobalTrusted()).wrapAsObject(thiz); 102.522 + } 102.523 + } 102.524 + 102.525 + return thiz; 102.526 + } 102.527 + 102.528 + static boolean isPrimitiveThis(final Object obj) { 102.529 + return obj instanceof String || obj instanceof ConsString || 102.530 + obj instanceof Number || obj instanceof Boolean; 102.531 + } 102.532 + 102.533 + /** 102.534 + * Creates an invoker method handle for a bound function. 102.535 + * 102.536 + * @param targetFn the function being bound 102.537 + * @param originalInvoker an original invoker method handle for the function. This can be its generic invoker or 102.538 + * any of its specializations. 102.539 + * @param self the "this" value being bound 102.540 + * @param args additional arguments being bound 102.541 + * 102.542 + * @return a bound invoker method handle that will bind the self value and the specified arguments. The resulting 102.543 + * invoker never needs a callee; if the original invoker needed it, it will be bound to {@code fn}. The resulting 102.544 + * invoker still takes an initial {@code this} parameter, but it is always dropped and the bound {@code self} passed 102.545 + * to the original invoker on invocation. 102.546 + */ 102.547 + private MethodHandle bindInvokeHandle(final MethodHandle originalInvoker, final ScriptFunction targetFn, final Object self, final Object[] args) { 102.548 + // Is the target already bound? If it is, we won't bother binding either callee or self as they're already bound 102.549 + // in the target and will be ignored anyway. 102.550 + final boolean isTargetBound = targetFn.isBoundFunction(); 102.551 + 102.552 + final boolean needsCallee = needsCallee(originalInvoker); 102.553 + assert needsCallee == needsCallee() : "callee contract violation 2"; 102.554 + assert !(isTargetBound && needsCallee); // already bound functions don't need a callee 102.555 + 102.556 + final Object boundSelf = isTargetBound ? null : convertThisObject(self); 102.557 + final MethodHandle boundInvoker; 102.558 + 102.559 + if (isVarArg(originalInvoker)) { 102.560 + // First, bind callee and this without arguments 102.561 + final MethodHandle noArgBoundInvoker; 102.562 + 102.563 + if (isTargetBound) { 102.564 + // Don't bind either callee or this 102.565 + noArgBoundInvoker = originalInvoker; 102.566 + } else if (needsCallee) { 102.567 + // Bind callee and this 102.568 + noArgBoundInvoker = MH.insertArguments(originalInvoker, 0, targetFn, boundSelf); 102.569 + } else { 102.570 + // Only bind this 102.571 + noArgBoundInvoker = MH.bindTo(originalInvoker, boundSelf); 102.572 + } 102.573 + // Now bind arguments 102.574 + if (args.length > 0) { 102.575 + boundInvoker = varArgBinder(noArgBoundInvoker, args); 102.576 + } else { 102.577 + boundInvoker = noArgBoundInvoker; 102.578 + } 102.579 + } else { 102.580 + final Object[] boundArgs = new Object[Math.min(originalInvoker.type().parameterCount(), args.length + (isTargetBound ? 0 : (needsCallee ? 2 : 1)))]; 102.581 + int next = 0; 102.582 + if (!isTargetBound) { 102.583 + if (needsCallee) { 102.584 + boundArgs[next++] = targetFn; 102.585 + } 102.586 + boundArgs[next++] = boundSelf; 102.587 + } 102.588 + // If more bound args were specified than the function can take, we'll just drop those. 102.589 + System.arraycopy(args, 0, boundArgs, next, boundArgs.length - next); 102.590 + // If target is already bound, insert additional bound arguments after "this" argument, at position 1; 102.591 + // "this" will get dropped anyway by the target invoker. We previously asserted that already bound functions 102.592 + // don't take a callee parameter, so we can know that the signature is (this[, args...]) therefore args 102.593 + // start at position 1. If the function is not bound, we start inserting arguments at position 0. 102.594 + boundInvoker = MH.insertArguments(originalInvoker, isTargetBound ? 1 : 0, boundArgs); 102.595 + } 102.596 + 102.597 + if (isTargetBound) { 102.598 + return boundInvoker; 102.599 + } 102.600 + 102.601 + // If the target is not already bound, add a dropArguments that'll throw away the passed this 102.602 + return MH.dropArguments(boundInvoker, 0, Object.class); 102.603 + } 102.604 + 102.605 + /** 102.606 + * Creates a constructor method handle for a bound function using the passed constructor handle. 102.607 + * 102.608 + * @param originalConstructor the constructor handle to bind. It must be a composed constructor. 102.609 + * @param fn the function being bound 102.610 + * @param args arguments being bound 102.611 + * 102.612 + * @return a bound constructor method handle that will bind the specified arguments. The resulting constructor never 102.613 + * needs a callee; if the original constructor needed it, it will be bound to {@code fn}. The resulting constructor 102.614 + * still takes an initial {@code this} parameter and passes it to the underlying original constructor. Finally, if 102.615 + * this script function data object has no constructor handle, null is returned. 102.616 + */ 102.617 + private static MethodHandle bindConstructHandle(final MethodHandle originalConstructor, final ScriptFunction fn, final Object[] args) { 102.618 + assert originalConstructor != null; 102.619 + 102.620 + // If target function is already bound, don't bother binding the callee. 102.621 + final MethodHandle calleeBoundConstructor = fn.isBoundFunction() ? originalConstructor : 102.622 + MH.dropArguments(MH.bindTo(originalConstructor, fn), 0, ScriptFunction.class); 102.623 + 102.624 + if (args.length == 0) { 102.625 + return calleeBoundConstructor; 102.626 + } 102.627 + 102.628 + if (isVarArg(calleeBoundConstructor)) { 102.629 + return varArgBinder(calleeBoundConstructor, args); 102.630 + } 102.631 + 102.632 + final Object[] boundArgs; 102.633 + 102.634 + final int maxArgCount = calleeBoundConstructor.type().parameterCount() - 1; 102.635 + if (args.length <= maxArgCount) { 102.636 + boundArgs = args; 102.637 + } else { 102.638 + boundArgs = new Object[maxArgCount]; 102.639 + System.arraycopy(args, 0, boundArgs, 0, maxArgCount); 102.640 + } 102.641 + 102.642 + return MH.insertArguments(calleeBoundConstructor, 1, boundArgs); 102.643 + } 102.644 + 102.645 + /** 102.646 + * Takes a method handle, and returns a potentially different method handle that can be used in 102.647 + * {@code ScriptFunction#invoke(Object, Object...)} or {code ScriptFunction#construct(Object, Object...)}. 102.648 + * The returned method handle will be sure to return {@code Object}, and will have all its parameters turned into 102.649 + * {@code Object} as well, except for the following ones: 102.650 + * <ul> 102.651 + * <li>a last parameter of type {@code Object[]} which is used for vararg functions,</li> 102.652 + * <li>the first argument, which is forced to be {@link ScriptFunction}, in case the function receives itself 102.653 + * (callee) as an argument.</li> 102.654 + * </ul> 102.655 + * 102.656 + * @param mh the original method handle 102.657 + * 102.658 + * @return the new handle, conforming to the rules above. 102.659 + */ 102.660 + protected MethodHandle composeGenericMethod(final MethodHandle mh) { 102.661 + final MethodType type = mh.type(); 102.662 + MethodType newType = type.generic(); 102.663 + if (isVarArg(mh)) { 102.664 + newType = newType.changeParameterType(type.parameterCount() - 1, Object[].class); 102.665 + } 102.666 + if (needsCallee(mh)) { 102.667 + newType = newType.changeParameterType(0, ScriptFunction.class); 102.668 + } 102.669 + return type.equals(newType) ? mh : mh.asType(newType); 102.670 } 102.671 102.672 /** 102.673 * Execute this script function. 102.674 + * 102.675 * @param self Target object. 102.676 * @param arguments Call arguments. 102.677 * @return ScriptFunction result. 102.678 + * 102.679 * @throws Throwable if there is an exception/error with the invocation or thrown from it 102.680 */ 102.681 Object invoke(final ScriptFunction fn, final Object self, final Object... arguments) throws Throwable { 102.682 - final MethodHandle genInvoker = getGenericInvoker(); 102.683 - final Object selfObj = convertThisObject(self); 102.684 - final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments; 102.685 + final MethodHandle mh = getGenericInvoker(); 102.686 102.687 - if (isVarArg()) { 102.688 - if (needsCallee()) { 102.689 - return genInvoker.invokeExact(fn, selfObj, args); 102.690 + final Object selfObj = convertThisObject(self); 102.691 + final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments; 102.692 + 102.693 + if (isVarArg(mh)) { 102.694 + if (needsCallee(mh)) { 102.695 + return mh.invokeExact(fn, selfObj, args); 102.696 } 102.697 - return genInvoker.invokeExact(selfObj, args); 102.698 + return mh.invokeExact(selfObj, args); 102.699 } 102.700 102.701 - final int paramCount = genInvoker.type().parameterCount(); 102.702 - if (needsCallee()) { 102.703 + final int paramCount = mh.type().parameterCount(); 102.704 + if (needsCallee(mh)) { 102.705 switch (paramCount) { 102.706 case 2: 102.707 - return genInvoker.invokeExact(fn, selfObj); 102.708 + return mh.invokeExact(fn, selfObj); 102.709 case 3: 102.710 - return genInvoker.invokeExact(fn, selfObj, getArg(args, 0)); 102.711 + return mh.invokeExact(fn, selfObj, getArg(args, 0)); 102.712 case 4: 102.713 - return genInvoker.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1)); 102.714 + return mh.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1)); 102.715 case 5: 102.716 - return genInvoker.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2)); 102.717 + return mh.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2)); 102.718 default: 102.719 - return genInvoker.invokeWithArguments(withArguments(fn, selfObj, paramCount, args)); 102.720 + return mh.invokeWithArguments(withArguments(fn, selfObj, paramCount, args)); 102.721 } 102.722 } 102.723 102.724 switch (paramCount) { 102.725 case 1: 102.726 - return genInvoker.invokeExact(selfObj); 102.727 + return mh.invokeExact(selfObj); 102.728 case 2: 102.729 - return genInvoker.invokeExact(selfObj, getArg(args, 0)); 102.730 + return mh.invokeExact(selfObj, getArg(args, 0)); 102.731 case 3: 102.732 - return genInvoker.invokeExact(selfObj, getArg(args, 0), getArg(args, 1)); 102.733 + return mh.invokeExact(selfObj, getArg(args, 0), getArg(args, 1)); 102.734 case 4: 102.735 - return genInvoker.invokeExact(selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2)); 102.736 + return mh.invokeExact(selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2)); 102.737 default: 102.738 - return genInvoker.invokeWithArguments(withArguments(null, selfObj, paramCount, args)); 102.739 + return mh.invokeWithArguments(withArguments(null, selfObj, paramCount, args)); 102.740 } 102.741 } 102.742 102.743 @@ -389,15 +537,13 @@ 102.744 return i < args.length ? args[i] : UNDEFINED; 102.745 } 102.746 102.747 - private Object[] withArguments(final ScriptFunction fn, final Object self, final int argCount, final Object[] args) { 102.748 + private static Object[] withArguments(final ScriptFunction fn, final Object self, final int argCount, final Object[] args) { 102.749 final Object[] finalArgs = new Object[argCount]; 102.750 102.751 int nextArg = 0; 102.752 - if (needsCallee()) { 102.753 - assert fn != null; 102.754 + if (fn != null) { 102.755 + //needs callee 102.756 finalArgs[nextArg++] = fn; 102.757 - } else { 102.758 - assert fn == null; 102.759 } 102.760 finalArgs[nextArg++] = self; 102.761 102.762 @@ -413,255 +559,14 @@ 102.763 102.764 return finalArgs; 102.765 } 102.766 - 102.767 - /** 102.768 - * Get the specialized construct handles for this function. 102.769 - * @return array of specialized construct handles 102.770 - */ 102.771 - private MethodHandle[] getConstructSpecializations() { 102.772 - if(constructSpecializations == null && invokeSpecializations != null) { 102.773 - final MethodHandle[] ctors = new MethodHandle[invokeSpecializations.length]; 102.774 - for(int i = 0; i < ctors.length; ++i) { 102.775 - ctors[i] = composeConstructor(invokeSpecializations[i]); 102.776 - } 102.777 - constructSpecializations = ctors; 102.778 - } 102.779 - return constructSpecializations; 102.780 - } 102.781 - 102.782 - /** 102.783 - * Set the method handles for this function. 102.784 - * @param invoker the invoker handle 102.785 - * @param allocator the allocator handle 102.786 - */ 102.787 - public void setMethodHandles(final MethodHandle invoker, final MethodHandle allocator) { 102.788 - // We can't make method handle fields final because they're not available during codegen 102.789 - // and they're set when first called, so we enforce set-once here. 102.790 - if (this.invoker == null) { 102.791 - this.invoker = invoker; 102.792 - this.constructor = null; // delay constructor composition 102.793 - this.allocator = allocator; 102.794 - } 102.795 - } 102.796 - 102.797 - /** 102.798 - * Used by the trampoline. Must not be any wider than package 102.799 - * private 102.800 - * @param invoker new invoker 102.801 - */ 102.802 - void resetInvoker(final MethodHandle invoker) { 102.803 - this.invoker = invoker; 102.804 - this.constructor = null; //delay constructor composition 102.805 - } 102.806 - 102.807 - /** 102.808 - * Allocates an object using this function's allocator. 102.809 - * @return the object allocated using this function's allocator, or null if the function doesn't have an allocator. 102.810 - */ 102.811 - ScriptObject allocate() { 102.812 - if (allocator == null) { 102.813 - return null; 102.814 - } 102.815 - 102.816 - try { 102.817 - return (ScriptObject)allocator.invokeExact(allocatorMap); 102.818 - } catch (final RuntimeException | Error e) { 102.819 - throw e; 102.820 - } catch (final Throwable t) { 102.821 - throw new RuntimeException(t); 102.822 - } 102.823 - } 102.824 - 102.825 - /** 102.826 - * This method is used to create the immutable portion of a bound function. 102.827 - * See {@link ScriptFunction#makeBoundFunction(Object, Object[])} 102.828 - * 102.829 - * @param fn the original function being bound 102.830 - * @param self this reference to bind. Can be null. 102.831 - * @param args additional arguments to bind. Can be null. 102.832 - */ 102.833 - ScriptFunctionData makeBoundFunctionData(final ScriptFunction fn, final Object self, final Object[] args) { 102.834 - final Object[] allArgs = args == null ? ScriptRuntime.EMPTY_ARRAY : args; 102.835 - 102.836 - final boolean isConstructor = isConstructor(); 102.837 - // Note that the new ScriptFunctionData's method handle will not need a callee regardless of whether the 102.838 - // original did. 102.839 - final ScriptFunctionData boundData = new ScriptFunctionData(name, source, token, 102.840 - bindInvokeHandle(invoker, fn, self, allArgs), bindInvokeSpecializations(fn, self, allArgs), isStrict(), isBuiltin(), isConstructor); 102.841 - if(isConstructor) { 102.842 - // Can't just rely on bound invoke as a basis for constructor, as it ignores the passed "this" in favor of the 102.843 - // bound "this"; constructor on the other hand must see the actual "this" received from the allocator. 102.844 - 102.845 - // Binding a function will force constructor composition in getConstructor(); not really any way around that 102.846 - // as it's the composed constructor that has to be bound to the function. 102.847 - boundData.constructor = bindConstructHandle(getConstructor(), fn, allArgs); 102.848 - boundData.constructSpecializations = bindConstructorSpecializations(fn, allArgs); 102.849 - } 102.850 - assert boundData.allocator == null; 102.851 - final int thisArity = getArity(); 102.852 - if(thisArity != -1) { 102.853 - boundData.setArity(Math.max(0, thisArity - args.length)); 102.854 - } else { 102.855 - assert boundData.getArity() == -1; 102.856 - } 102.857 - return boundData; 102.858 - } 102.859 - 102.860 - /** 102.861 - * Convert this argument for non-strict functions according to ES 10.4.3 102.862 - * 102.863 - * @param thiz the this argument 102.864 - * 102.865 - * @return the converted this object 102.866 - */ 102.867 - Object convertThisObject(final Object thiz) { 102.868 - if (!(thiz instanceof ScriptObject) && needsWrappedThis()) { 102.869 - if (JSType.nullOrUndefined(thiz)) { 102.870 - return Context.getGlobalTrusted(); 102.871 - } 102.872 - 102.873 - if (isPrimitiveThis(thiz)) { 102.874 - return ((GlobalObject)Context.getGlobalTrusted()).wrapAsObject(thiz); 102.875 - } 102.876 - } 102.877 - 102.878 - return thiz; 102.879 - } 102.880 - 102.881 - static boolean isPrimitiveThis(Object obj) { 102.882 - return obj instanceof String || obj instanceof ConsString || 102.883 - obj instanceof Number || obj instanceof Boolean; 102.884 - } 102.885 - 102.886 - /** 102.887 - * Creates an invoker method handle for a bound function. 102.888 - * @param targetFn the function being bound 102.889 - * @param originalInvoker an original invoker method handle for the function. This can be its generic invoker or 102.890 - * any of its specializations. 102.891 - * @param self the "this" value being bound 102.892 - * @param args additional arguments being bound 102.893 - * @return a bound invoker method handle that will bind the self value and the specified arguments. The resulting 102.894 - * invoker never needs a callee; if the original invoker needed it, it will be bound to {@code fn}. The resulting 102.895 - * invoker still takes an initial {@code this} parameter, but it is always dropped and the bound {@code self} passed 102.896 - * to the original invoker on invocation. 102.897 - */ 102.898 - private MethodHandle bindInvokeHandle(final MethodHandle originalInvoker, final ScriptFunction targetFn, final Object self, final Object[] args) { 102.899 - // Is the target already bound? If it is, we won't bother binding either callee or self as they're already bound 102.900 - // in the target and will be ignored anyway. 102.901 - final boolean isTargetBound = targetFn.isBoundFunction(); 102.902 - assert !(isTargetBound && needsCallee()); // already bound functions don't need a callee 102.903 - final Object boundSelf = isTargetBound ? null : convertThisObject(self); 102.904 - final MethodHandle boundInvoker; 102.905 - if(isVarArg(originalInvoker)) { 102.906 - // First, bind callee and this without arguments 102.907 - final MethodHandle noArgBoundInvoker; 102.908 - if(isTargetBound) { 102.909 - // Don't bind either callee or this 102.910 - noArgBoundInvoker = originalInvoker; 102.911 - } else if(needsCallee()) { 102.912 - // Bind callee and this 102.913 - noArgBoundInvoker = MH.insertArguments(originalInvoker, 0, targetFn, boundSelf); 102.914 - } else { 102.915 - // Only bind this 102.916 - noArgBoundInvoker = MH.bindTo(originalInvoker, boundSelf); 102.917 - } 102.918 - // Now bind arguments 102.919 - if(args.length > 0) { 102.920 - boundInvoker = varArgBinder(noArgBoundInvoker, args); 102.921 - } else { 102.922 - boundInvoker = noArgBoundInvoker; 102.923 - } 102.924 - } else { 102.925 - final Object[] boundArgs = new Object[Math.min(originalInvoker.type().parameterCount(), 102.926 - args.length + (isTargetBound ? 0 : (needsCallee() ? 2 : 1)))]; 102.927 - int next = 0; 102.928 - if(!isTargetBound) { 102.929 - if(needsCallee()) { 102.930 - boundArgs[next++] = targetFn; 102.931 - } 102.932 - boundArgs[next++] = boundSelf; 102.933 - } 102.934 - // If more bound args were specified than the function can take, we'll just drop those. 102.935 - System.arraycopy(args, 0, boundArgs, next, boundArgs.length - next); 102.936 - // If target is already bound, insert additional bound arguments after "this" argument, at position 1; 102.937 - // "this" will get dropped anyway by the target invoker. We previously asserted that already bound functions 102.938 - // don't take a callee parameter, so we can know that the signature is (this[, args...]) therefore args 102.939 - // start at position 1. If the function is not bound, we start inserting arguments at position 0. 102.940 - boundInvoker = MH.insertArguments(originalInvoker, isTargetBound ? 1 : 0, boundArgs); 102.941 - } 102.942 - if(isTargetBound) { 102.943 - return boundInvoker; 102.944 - } 102.945 - // If the target is not already bound, add a dropArguments that'll throw away the passed this 102.946 - return MH.dropArguments(boundInvoker, 0, Object.class); 102.947 - } 102.948 - 102.949 - private MethodHandle[] bindInvokeSpecializations(final ScriptFunction fn, final Object self, final Object[] args) { 102.950 - if(invokeSpecializations == null) { 102.951 - return null; 102.952 - } 102.953 - final MethodHandle[] boundSpecializations = new MethodHandle[invokeSpecializations.length]; 102.954 - for(int i = 0; i < invokeSpecializations.length; ++i) { 102.955 - boundSpecializations[i] = bindInvokeHandle(invokeSpecializations[i], fn, self, args); 102.956 - } 102.957 - return boundSpecializations; 102.958 - } 102.959 - 102.960 - /** 102.961 - * Creates a constructor method handle for a bound function using the passed constructor handle. 102.962 - * @param originalConstructor the constructor handle to bind. It must be a composed constructor. 102.963 - * @param fn the function being bound 102.964 - * @param args arguments being bound 102.965 - * @return a bound constructor method handle that will bind the specified arguments. The resulting constructor never 102.966 - * needs a callee; if the original constructor needed it, it will be bound to {@code fn}. The resulting constructor 102.967 - * still takes an initial {@code this} parameter and passes it to the underlying original constructor. Finally, if 102.968 - * this script function data object has no constructor handle, null is returned. 102.969 - */ 102.970 - private static MethodHandle bindConstructHandle(final MethodHandle originalConstructor, final ScriptFunction fn, final Object[] args) { 102.971 - if(originalConstructor == null) { 102.972 - return null; 102.973 - } 102.974 - 102.975 - // If target function is already bound, don't bother binding the callee. 102.976 - final MethodHandle calleeBoundConstructor = fn.isBoundFunction() ? originalConstructor : 102.977 - MH.dropArguments(MH.bindTo(originalConstructor, fn), 0, ScriptFunction.class); 102.978 - if(args.length == 0) { 102.979 - return calleeBoundConstructor; 102.980 - } 102.981 - 102.982 - if(isVarArg(calleeBoundConstructor)) { 102.983 - return varArgBinder(calleeBoundConstructor, args); 102.984 - } 102.985 - 102.986 - final Object[] boundArgs; 102.987 - final int maxArgCount = calleeBoundConstructor.type().parameterCount() - 1; 102.988 - if (args.length <= maxArgCount) { 102.989 - boundArgs = args; 102.990 - } else { 102.991 - boundArgs = new Object[maxArgCount]; 102.992 - System.arraycopy(args, 0, boundArgs, 0, maxArgCount); 102.993 - } 102.994 - return MH.insertArguments(calleeBoundConstructor, 1, boundArgs); 102.995 - } 102.996 - 102.997 - private MethodHandle[] bindConstructorSpecializations(final ScriptFunction fn, final Object[] args) { 102.998 - final MethodHandle[] ctorSpecs = getConstructSpecializations(); 102.999 - if(ctorSpecs == null) { 102.1000 - return null; 102.1001 - } 102.1002 - final MethodHandle[] boundSpecializations = new MethodHandle[ctorSpecs.length]; 102.1003 - for(int i = 0; i < ctorSpecs.length; ++i) { 102.1004 - boundSpecializations[i] = bindConstructHandle(ctorSpecs[i], fn, args); 102.1005 - } 102.1006 - return boundSpecializations; 102.1007 - } 102.1008 - 102.1009 /** 102.1010 * Takes a variable-arity method and binds a variable number of arguments in it. The returned method will filter the 102.1011 * vararg array and pass a different array that prepends the bound arguments in front of the arguments passed on 102.1012 * invocation 102.1013 + * 102.1014 * @param mh the handle 102.1015 * @param args the bound arguments 102.1016 + * 102.1017 * @return the bound method handle 102.1018 */ 102.1019 private static MethodHandle varArgBinder(final MethodHandle mh, final Object[] args) { 102.1020 @@ -671,41 +576,20 @@ 102.1021 } 102.1022 102.1023 /** 102.1024 - * Convert boolean flags to int. 102.1025 - * @param needsCallee needs-callee flag 102.1026 - * @param isVarArg var-arg flag 102.1027 - * @param isStrict strict flag 102.1028 - * @param isBuiltin builtin flag 102.1029 - * @return int flags 102.1030 + * Adapts the method handle so its return type is {@code Object}. If the handle's return type is already 102.1031 + * {@code Object}, the handle is returned unchanged. 102.1032 + * 102.1033 + * @param mh the handle to adapt 102.1034 + * @return the adapted handle 102.1035 */ 102.1036 - private static int makeFlags(final boolean needsCallee, final boolean isVarArg, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) { 102.1037 - int flags = 0; 102.1038 - if (needsCallee) { 102.1039 - flags |= HAS_CALLEE; 102.1040 - } 102.1041 - if (isVarArg) { 102.1042 - flags |= IS_VARARGS; 102.1043 - } 102.1044 - if (isStrict) { 102.1045 - flags |= IS_STRICT; 102.1046 - } 102.1047 - if (isBuiltin) { 102.1048 - flags |= IS_BUILTIN; 102.1049 - } 102.1050 - if (isConstructor) { 102.1051 - flags |= IS_CONSTRUCTOR; 102.1052 - } 102.1053 - 102.1054 - return flags; 102.1055 + private static MethodHandle changeReturnTypeToObject(final MethodHandle mh) { 102.1056 + return MH.asType(mh, mh.type().changeReturnType(Object.class)); 102.1057 } 102.1058 102.1059 - /** 102.1060 - * Test if a methodHandle refers to a constructor. 102.1061 - * @param methodHandle MethodHandle to test. 102.1062 - * @return True if method is a constructor. 102.1063 - */ 102.1064 - private static boolean isConstructor(final MethodHandle methodHandle) { 102.1065 - return methodHandle.type().parameterCount() >= 1 && methodHandle.type().parameterType(0) == boolean.class; 102.1066 + private void ensureConstructor(final CompiledFunction inv) { 102.1067 + if (!inv.hasConstructor()) { 102.1068 + inv.setConstructor(composeConstructor(inv.getInvoker(), needsCallee(inv.getInvoker()))); 102.1069 + } 102.1070 } 102.1071 102.1072 /** 102.1073 @@ -713,102 +597,56 @@ 102.1074 * {@code (boolean, Object, ScriptFunction, ...)} or {@code (Object, ScriptFunction, ...)}, then we'll assume it has 102.1075 * a callee argument. We need this as the constructor above is not passed this information, and can't just blindly 102.1076 * assume it's false (notably, it's being invoked for creation of new scripts, and scripts have scopes, therefore 102.1077 - * they also always receive a callee. 102.1078 - * @param methodHandle the examined method handle 102.1079 + * they also always receive a callee). 102.1080 + * 102.1081 + * @param mh the examined method handle 102.1082 + * 102.1083 * @return true if the method handle expects a callee, false otherwise 102.1084 */ 102.1085 - private static boolean needsCallee(MethodHandle methodHandle) { 102.1086 - final MethodType type = methodHandle.type(); 102.1087 - final int len = type.parameterCount(); 102.1088 - if(len == 0) { 102.1089 + protected static boolean needsCallee(final MethodHandle mh) { 102.1090 + final MethodType type = mh.type(); 102.1091 + final int length = type.parameterCount(); 102.1092 + 102.1093 + if (length == 0) { 102.1094 return false; 102.1095 } 102.1096 - if(type.parameterType(0) == boolean.class) { 102.1097 - return len > 1 && type.parameterType(1) == ScriptFunction.class; 102.1098 + 102.1099 + if (type.parameterType(0) == boolean.class) { 102.1100 + return length > 1 && type.parameterType(1) == ScriptFunction.class; 102.1101 } 102.1102 + 102.1103 return type.parameterType(0) == ScriptFunction.class; 102.1104 } 102.1105 102.1106 - private static boolean isVarArg(MethodHandle methodHandle) { 102.1107 - final MethodType type = methodHandle.type(); 102.1108 + /** 102.1109 + * Check if a javascript function methodhandle is a vararg handle 102.1110 + * 102.1111 + * @param mh method handle to check 102.1112 + * 102.1113 + * @return true if vararg 102.1114 + */ 102.1115 + protected static boolean isVarArg(final MethodHandle mh) { 102.1116 + final MethodType type = mh.type(); 102.1117 return type.parameterType(type.parameterCount() - 1).isArray(); 102.1118 } 102.1119 102.1120 - /** 102.1121 - * Takes a method handle, and returns a potentially different method handle that can be used in 102.1122 - * {@link ScriptFunction#invoke(Object, Object...)} or {@link ScriptFunction#construct(Object, Object...)}. 102.1123 - * The returned method handle will be sure to return {@code Object}, and will have all its parameters turned into 102.1124 - * {@code Object} as well, except for the following ones: 102.1125 - * <ul> 102.1126 - * <li>a last parameter of type {@code Object[]} which is used for vararg functions,</li> 102.1127 - * <li>the first argument, which is forced to be {@link ScriptFunction}, in case the function receives itself 102.1128 - * (callee) as an argument.</li> 102.1129 - * </ul> 102.1130 - * 102.1131 - * @param handle the original method handle 102.1132 - * @return the new handle, conforming to the rules above. 102.1133 - */ 102.1134 - private MethodHandle makeGenericMethod(final MethodHandle handle) { 102.1135 - final MethodType type = handle.type(); 102.1136 - MethodType newType = type.generic(); 102.1137 - if (isVarArg()) { 102.1138 - newType = newType.changeParameterType(type.parameterCount() - 1, Object[].class); 102.1139 - } 102.1140 - if (needsCallee()) { 102.1141 - newType = newType.changeParameterType(0, ScriptFunction.class); 102.1142 - } 102.1143 - return type.equals(newType) ? handle : handle.asType(newType); 102.1144 - } 102.1145 - 102.1146 - /** 102.1147 - * Adapts the method handle so its return type is {@code Object}. If the handle's return type is already 102.1148 - * {@code Object}, the handle is returned unchanged. 102.1149 - * @param mh the handle to adapt 102.1150 - * @return the adapted handle 102.1151 - */ 102.1152 - private static MethodHandle changeReturnTypeToObject(final MethodHandle mh) { 102.1153 - return MH.asType(mh, mh.type().changeReturnType(Object.class)); 102.1154 - } 102.1155 - 102.1156 - 102.1157 - /** 102.1158 - * If this function's method handles need a callee parameter, swap the order of first two arguments for the passed 102.1159 - * method handle. If this function's method handles don't need a callee parameter, returns the original method 102.1160 - * handle unchanged. 102.1161 - * @param mh a method handle with order of arguments {@code (callee, this, args...)} 102.1162 - * @return a method handle with order of arguments {@code (this, callee, args...)} 102.1163 - */ 102.1164 - private MethodHandle swapCalleeAndThis(final MethodHandle mh) { 102.1165 - if (!needsCallee()) { 102.1166 - return mh; 102.1167 - } 102.1168 - final MethodType type = mh.type(); 102.1169 - assert type.parameterType(0) == ScriptFunction.class; 102.1170 - assert type.parameterType(1) == Object.class; 102.1171 - final MethodType newType = type.changeParameterType(0, Object.class).changeParameterType(1, ScriptFunction.class); 102.1172 - final int[] reorder = new int[type.parameterCount()]; 102.1173 - reorder[0] = 1; 102.1174 - assert reorder[1] == 0; 102.1175 - for (int i = 2; i < reorder.length; ++i) { 102.1176 - reorder[i] = i; 102.1177 - } 102.1178 - return MethodHandles.permuteArguments(mh, newType, reorder); 102.1179 - } 102.1180 - 102.1181 @SuppressWarnings("unused") 102.1182 private static Object[] bindVarArgs(final Object[] array1, final Object[] array2) { 102.1183 - if(array2 == null) { 102.1184 + if (array2 == null) { 102.1185 // Must clone it, as we can't allow the receiving method to alter the array 102.1186 return array1.clone(); 102.1187 } 102.1188 + 102.1189 final int l2 = array2.length; 102.1190 - if(l2 == 0) { 102.1191 + if (l2 == 0) { 102.1192 return array1.clone(); 102.1193 } 102.1194 + 102.1195 final int l1 = array1.length; 102.1196 final Object[] concat = new Object[l1 + l2]; 102.1197 System.arraycopy(array1, 0, concat, 0, l1); 102.1198 System.arraycopy(array2, 0, concat, l1, l2); 102.1199 + 102.1200 return concat; 102.1201 } 102.1202 102.1203 @@ -820,5 +658,4 @@ 102.1204 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { 102.1205 return MH.findStatic(MethodHandles.lookup(), ScriptFunctionData.class, name, MH.type(rtype, types)); 102.1206 } 102.1207 - 102.1208 }
103.1 --- a/src/jdk/nashorn/internal/runtime/ScriptLoader.java Thu Mar 28 10:55:17 2013 -0700 103.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptLoader.java Mon Apr 01 21:42:31 2013 -0700 103.3 @@ -26,6 +26,7 @@ 103.4 package jdk.nashorn.internal.runtime; 103.5 103.6 import java.security.CodeSource; 103.7 +import java.security.ProtectionDomain; 103.8 103.9 /** 103.10 * Responsible for loading script generated classes. 103.11 @@ -57,6 +58,9 @@ 103.12 * @return Installed class. 103.13 */ 103.14 synchronized Class<?> installClass(final String name, final byte[] data, final CodeSource cs) { 103.15 + if (cs == null) { 103.16 + return defineClass(name, data, 0, data.length, new ProtectionDomain(null, getPermissions(null))); 103.17 + } 103.18 return defineClass(name, data, 0, data.length, cs); 103.19 } 103.20 }
104.1 --- a/src/jdk/nashorn/internal/runtime/SpecializedMethodChooser.java Thu Mar 28 10:55:17 2013 -0700 104.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 104.3 @@ -1,99 +0,0 @@ 104.4 -/* 104.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 104.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 104.7 - * 104.8 - * This code is free software; you can redistribute it and/or modify it 104.9 - * under the terms of the GNU General Public License version 2 only, as 104.10 - * published by the Free Software Foundation. Oracle designates this 104.11 - * particular file as subject to the "Classpath" exception as provided 104.12 - * by Oracle in the LICENSE file that accompanied this code. 104.13 - * 104.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 104.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 104.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 104.17 - * version 2 for more details (a copy is included in the LICENSE file that 104.18 - * accompanied this code). 104.19 - * 104.20 - * You should have received a copy of the GNU General Public License version 104.21 - * 2 along with this work; if not, write to the Free Software Foundation, 104.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 104.23 - * 104.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 104.25 - * or visit www.oracle.com if you need additional information or have any 104.26 - * questions. 104.27 - */ 104.28 - 104.29 -package jdk.nashorn.internal.runtime; 104.30 - 104.31 -import java.lang.invoke.MethodHandle; 104.32 -import java.lang.invoke.MethodType; 104.33 -import jdk.nashorn.internal.codegen.types.Type; 104.34 -import jdk.nashorn.internal.runtime.options.Options; 104.35 - 104.36 -class SpecializedMethodChooser { 104.37 - /** Should specialized function and specialized constructors for the builtin be used if available? */ 104.38 - private static final boolean DISABLE_SPECIALIZATION = Options.getBooleanProperty("nashorn.scriptfunction.specialization.disable"); 104.39 - 104.40 - static MethodHandle candidateWithLowestWeight(final MethodType descType, final MethodHandle initialCandidate, final MethodHandle[] specs) { 104.41 - if (DISABLE_SPECIALIZATION || specs == null) { 104.42 - return initialCandidate; 104.43 - } 104.44 - 104.45 - int minimumWeight = Integer.MAX_VALUE; 104.46 - MethodHandle candidate = initialCandidate; 104.47 - 104.48 - for (final MethodHandle spec : specs) { 104.49 - final MethodType specType = spec.type(); 104.50 - 104.51 - if (!typeCompatible(descType, specType)) { 104.52 - continue; 104.53 - } 104.54 - 104.55 - //return type is ok. we want a wider or equal one for our callsite. 104.56 - final int specWeight = weigh(specType); 104.57 - if (specWeight < minimumWeight) { 104.58 - candidate = spec; 104.59 - minimumWeight = specWeight; 104.60 - } 104.61 - } 104.62 - 104.63 - return candidate; 104.64 - } 104.65 - 104.66 - private static boolean typeCompatible(final MethodType desc, final MethodType spec) { 104.67 - //spec must fit in desc 104.68 - final Class<?>[] dparray = desc.parameterArray(); 104.69 - final Class<?>[] sparray = spec.parameterArray(); 104.70 - 104.71 - if (dparray.length != sparray.length) { 104.72 - return false; 104.73 - } 104.74 - 104.75 - for (int i = 0; i < dparray.length; i++) { 104.76 - final Type dp = Type.typeFor(dparray[i]); 104.77 - final Type sp = Type.typeFor(sparray[i]); 104.78 - 104.79 - if (dp.isBoolean()) { 104.80 - return false; //don't specialize on booleans, we have the "true" vs int 1 ambiguity in resolution 104.81 - } 104.82 - 104.83 - //specialization arguments must be at least as wide as dp, if not wider 104.84 - if (Type.widest(dp, sp) != sp) { 104.85 - //e.g. specialization takes double and callsite says "object". reject. 104.86 - //but if specialization says double and callsite says "int" or "long" or "double", that's fine 104.87 - return false; 104.88 - } 104.89 - } 104.90 - 104.91 - return true; // anything goes for return type, take the convenient one and it will be upcasted thru dynalink magic. 104.92 - } 104.93 - 104.94 - private static int weigh(final MethodType t) { 104.95 - int weight = Type.typeFor(t.returnType()).getWeight(); 104.96 - for (final Class<?> paramType : t.parameterArray()) { 104.97 - final int pweight = Type.typeFor(paramType).getWeight(); 104.98 - weight += pweight; 104.99 - } 104.100 - return weight; 104.101 - } 104.102 -}
105.1 --- a/src/jdk/nashorn/internal/runtime/StructureLoader.java Thu Mar 28 10:55:17 2013 -0700 105.2 +++ b/src/jdk/nashorn/internal/runtime/StructureLoader.java Mon Apr 01 21:42:31 2013 -0700 105.3 @@ -38,6 +38,7 @@ 105.4 import java.security.CodeSource; 105.5 import java.security.PrivilegedActionException; 105.6 import java.security.PrivilegedExceptionAction; 105.7 +import java.security.ProtectionDomain; 105.8 import jdk.nashorn.internal.codegen.ObjectClassGenerator; 105.9 105.10 /** 105.11 @@ -129,6 +130,6 @@ 105.12 } 105.13 105.14 final byte[] code = new ObjectClassGenerator(context).generate(descriptor); 105.15 - return defineClass(name, code, 0, code.length); 105.16 + return defineClass(name, code, 0, code.length, new ProtectionDomain(null, getPermissions(null))); 105.17 } 105.18 }
106.1 --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Thu Mar 28 10:55:17 2013 -0700 106.2 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Mon Apr 01 21:42:31 2013 -0700 106.3 @@ -57,7 +57,7 @@ 106.4 static { 106.5 final DynamicLinkerFactory factory = new DynamicLinkerFactory(); 106.6 factory.setPrioritizedLinkers(new NashornLinker(), new NashornPrimitiveLinker(), new NashornStaticClassLinker(), 106.7 - new JSObjectLinker()); 106.8 + new JSObjectLinker(), new ReflectionCheckLinker()); 106.9 factory.setFallbackLinkers(new BeansLinker(), new NashornBottomLinker()); 106.10 factory.setSyncOnRelink(true); 106.11 final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", -1);
107.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Thu Mar 28 10:55:17 2013 -0700 107.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Mon Apr 01 21:42:31 2013 -0700 107.3 @@ -54,6 +54,7 @@ 107.4 import java.security.CodeSource; 107.5 import java.security.Permissions; 107.6 import java.security.PrivilegedAction; 107.7 +import java.security.PrivilegedExceptionAction; 107.8 import java.security.ProtectionDomain; 107.9 import java.security.SecureClassLoader; 107.10 import java.security.SecureRandom; 107.11 @@ -410,9 +411,14 @@ 107.12 */ 107.13 public static MethodHandle getConstructor(final Class<?> sourceType, final Class<?> targetType) throws Exception { 107.14 final StaticClass adapterClass = getAdapterClassFor(new Class<?>[] { targetType }); 107.15 - return MH.bindTo(Bootstrap.getLinkerServices().getGuardedInvocation(new LinkRequestImpl(NashornCallSiteDescriptor.get( 107.16 - "dyn:new", MethodType.methodType(targetType, StaticClass.class, sourceType), 0), false, 107.17 - adapterClass, null)).getInvocation(), adapterClass); 107.18 + return AccessController.doPrivileged(new PrivilegedExceptionAction<MethodHandle>() { 107.19 + @Override 107.20 + public MethodHandle run() throws Exception { 107.21 + return MH.bindTo(Bootstrap.getLinkerServices().getGuardedInvocation(new LinkRequestImpl(NashornCallSiteDescriptor.get( 107.22 + "dyn:new", MethodType.methodType(targetType, StaticClass.class, sourceType), 0), false, 107.23 + adapterClass, null)).getInvocation(), adapterClass); 107.24 + } 107.25 + }); 107.26 } 107.27 107.28 /** 107.29 @@ -456,9 +462,26 @@ 107.30 private static ClassLoader createClassLoader(final ClassLoader parentLoader, final String className, 107.31 final byte[] classBytes, final String privilegedActionClassName) { 107.32 return new AdapterLoader(parentLoader) { 107.33 + private final ClassLoader myLoader = getClass().getClassLoader(); 107.34 private final ProtectionDomain myProtectionDomain = getClass().getProtectionDomain(); 107.35 107.36 @Override 107.37 + public Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException { 107.38 + try { 107.39 + return super.loadClass(name, resolve); 107.40 + } catch (final SecurityException se) { 107.41 + // we may be implementing an interface or extending a class that was 107.42 + // loaded by a loader that prevents package.access. If so, it'd throw 107.43 + // SecurityException for nashorn's classes!. For adapter's to work, we 107.44 + // should be able to refer to nashorn classes. 107.45 + if (name.startsWith("jdk.nashorn.internal.")) { 107.46 + return myLoader.loadClass(name); 107.47 + } 107.48 + throw se; 107.49 + } 107.50 + } 107.51 + 107.52 + @Override 107.53 protected Class<?> findClass(final String name) throws ClassNotFoundException { 107.54 if(name.equals(className)) { 107.55 final byte[] bytes = classBytes;
108.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Thu Mar 28 10:55:17 2013 -0700 108.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Mon Apr 01 21:42:31 2013 -0700 108.3 @@ -39,7 +39,7 @@ 108.4 import jdk.nashorn.internal.runtime.ScriptObject; 108.5 108.6 /** 108.7 - * Utility class shared by {@link NashornLinker} and {@code NashornPrimitiveLinker} for converting JS values to Java 108.8 + * Utility class shared by {@code NashornLinker} and {@code NashornPrimitiveLinker} for converting JS values to Java 108.9 * types. 108.10 */ 108.11 public class JavaArgumentConverters {
109.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java Thu Mar 28 10:55:17 2013 -0700 109.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java Mon Apr 01 21:42:31 2013 -0700 109.3 @@ -40,8 +40,6 @@ 109.4 private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class); 109.5 private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class); 109.6 private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class); 109.7 - private static final MethodHandle IS_FUNCTION_MH = findOwnMH("isFunctionMH", boolean.class, Object.class, MethodHandle.class); 109.8 - private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH("isNonStrictFunction", boolean.class, Object.class, Object.class, MethodHandle.class); 109.9 private static final MethodHandle IS_INSTANCEOF_2 = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class); 109.10 109.11 // don't create me! 109.12 @@ -87,33 +85,6 @@ 109.13 return MH.insertArguments(IS_INSTANCEOF_2, 1, class1, class2); 109.14 } 109.15 109.16 - /** 109.17 - * Get the guard that checks if a {@link ScriptFunction} is equal to 109.18 - * a known ScriptFunction, using reference comparison 109.19 - * 109.20 - * @param function The ScriptFunction to check against. This will be bound to the guard method handle 109.21 - * 109.22 - * @return method handle for guard 109.23 - */ 109.24 - public static MethodHandle getFunctionGuard(final ScriptFunction function) { 109.25 - assert function.getInvokeHandle() != null; 109.26 - return MH.insertArguments(IS_FUNCTION_MH, 1, function.getInvokeHandle()); 109.27 - } 109.28 - 109.29 - /** 109.30 - * Get a guard that checks if a {@link ScriptFunction} is equal to 109.31 - * a known ScriptFunction using reference comparison, and whether the type of 109.32 - * the second argument (this-object) is not a JavaScript primitive type. 109.33 - * 109.34 - * @param function The ScriptFunction to check against. This will be bound to the guard method handle 109.35 - * 109.36 - * @return method handle for guard 109.37 - */ 109.38 - public static MethodHandle getNonStrictFunctionGuard(final ScriptFunction function) { 109.39 - assert function.getInvokeHandle() != null; 109.40 - return MH.insertArguments(IS_NONSTRICT_FUNCTION, 2, function.getInvokeHandle()); 109.41 - } 109.42 - 109.43 @SuppressWarnings("unused") 109.44 private static boolean isScriptObject(final Object self) { 109.45 return self instanceof ScriptObject; 109.46 @@ -130,16 +101,6 @@ 109.47 } 109.48 109.49 @SuppressWarnings("unused") 109.50 - private static boolean isFunctionMH(final Object self, final MethodHandle mh) { 109.51 - return self instanceof ScriptFunction && ((ScriptFunction)self).getInvokeHandle() == mh; 109.52 - } 109.53 - 109.54 - @SuppressWarnings("unused") 109.55 - private static boolean isNonStrictFunction(final Object self, final Object arg, final MethodHandle mh) { 109.56 - return self instanceof ScriptFunction && ((ScriptFunction)self).getInvokeHandle() == mh && arg instanceof ScriptObject; 109.57 - } 109.58 - 109.59 - @SuppressWarnings("unused") 109.60 private static boolean isInstanceOf2(final Object self, final Class<?> class1, final Class<?> class2) { 109.61 return class1.isInstance(self) || class2.isInstance(self); 109.62 }
110.1 --- a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Thu Mar 28 10:55:17 2013 -0700 110.2 +++ b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Mon Apr 01 21:42:31 2013 -0700 110.3 @@ -109,7 +109,6 @@ 110.4 } 110.5 return new GuardedInvocation(method, guard, link.getSwitchPoint()); 110.6 } 110.7 - assert desc.getNameTokenCount() <= 2; // Named operations would hit the return null after findProperty 110.8 return null; 110.9 } 110.10 }
111.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 111.2 +++ b/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java Mon Apr 01 21:42:31 2013 -0700 111.3 @@ -0,0 +1,60 @@ 111.4 +/* 111.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 111.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 111.7 + * 111.8 + * This code is free software; you can redistribute it and/or modify it 111.9 + * under the terms of the GNU General Public License version 2 only, as 111.10 + * published by the Free Software Foundation. Oracle designates this 111.11 + * particular file as subject to the "Classpath" exception as provided 111.12 + * by Oracle in the LICENSE file that accompanied this code. 111.13 + * 111.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 111.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 111.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 111.17 + * version 2 for more details (a copy is included in the LICENSE file that 111.18 + * accompanied this code). 111.19 + * 111.20 + * You should have received a copy of the GNU General Public License version 111.21 + * 2 along with this work; if not, write to the Free Software Foundation, 111.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 111.23 + * 111.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 111.25 + * or visit www.oracle.com if you need additional information or have any 111.26 + * questions. 111.27 + */ 111.28 + 111.29 +package jdk.nashorn.internal.runtime.linker; 111.30 + 111.31 +import jdk.internal.dynalink.linker.GuardedInvocation; 111.32 +import jdk.internal.dynalink.linker.LinkRequest; 111.33 +import jdk.internal.dynalink.linker.LinkerServices; 111.34 +import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; 111.35 + 111.36 +/** 111.37 + * Check java reflection permission for java reflective and java.lang.invoke access from scripts 111.38 + */ 111.39 +final class ReflectionCheckLinker implements TypeBasedGuardingDynamicLinker{ 111.40 + @Override 111.41 + public boolean canLinkType(final Class<?> type) { 111.42 + return canLinkTypeStatic(type); 111.43 + } 111.44 + 111.45 + private static boolean canLinkTypeStatic(final Class<?> type) { 111.46 + if (type == Class.class || ClassLoader.class.isAssignableFrom(type)) { 111.47 + return true; 111.48 + } 111.49 + final String name = type.getName(); 111.50 + return name.startsWith("java.lang.reflect.") || name.startsWith("java.lang.invoke."); 111.51 + } 111.52 + 111.53 + @Override 111.54 + public GuardedInvocation getGuardedInvocation(final LinkRequest origRequest, final LinkerServices linkerServices) 111.55 + throws Exception { 111.56 + final SecurityManager sm = System.getSecurityManager(); 111.57 + if (sm != null) { 111.58 + sm.checkPermission(new RuntimePermission("nashorn.JavaReflection")); 111.59 + } 111.60 + // let the next linker deal with actual linking 111.61 + return null; 111.62 + } 111.63 +}
112.1 --- a/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java Thu Mar 28 10:55:17 2013 -0700 112.2 +++ b/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java Mon Apr 01 21:42:31 2013 -0700 112.3 @@ -278,7 +278,7 @@ 112.4 this.valueNextArg = Boolean.parseBoolean(arg); 112.5 break; 112.6 default: 112.7 - throw new IllegalArgumentException(); 112.8 + throw new IllegalArgumentException(keyToken); 112.9 } 112.10 } 112.11
113.1 --- a/src/jdk/nashorn/internal/runtime/options/Options.java Thu Mar 28 10:55:17 2013 -0700 113.2 +++ b/src/jdk/nashorn/internal/runtime/options/Options.java Mon Apr 01 21:42:31 2013 -0700 113.3 @@ -66,6 +66,9 @@ 113.4 /** The options map of enabled options */ 113.5 private final TreeMap<String, Option<?>> options; 113.6 113.7 + /** System property that can be used for command line option propagation */ 113.8 + private static final String NASHORN_ARGS_PROPERTY = "nashorn.args"; 113.9 + 113.10 /** 113.11 * Constructor 113.12 * 113.13 @@ -386,6 +389,14 @@ 113.14 final LinkedList<String> argList = new LinkedList<>(); 113.15 Collections.addAll(argList, args); 113.16 113.17 + final String extra = getStringProperty(NASHORN_ARGS_PROPERTY, null); 113.18 + if (extra != null) { 113.19 + final StringTokenizer st = new StringTokenizer(extra); 113.20 + while (st.hasMoreTokens()) { 113.21 + argList.add(st.nextToken()); 113.22 + } 113.23 + } 113.24 + 113.25 while (!argList.isEmpty()) { 113.26 final String arg = argList.remove(0); 113.27
114.1 --- a/src/jdk/nashorn/internal/runtime/regexp/DefaultRegExp.java Thu Mar 28 10:55:17 2013 -0700 114.2 +++ b/src/jdk/nashorn/internal/runtime/regexp/DefaultRegExp.java Mon Apr 01 21:42:31 2013 -0700 114.3 @@ -95,14 +95,14 @@ 114.4 return null; // never matches or similar, e.g. a[] 114.5 } 114.6 114.7 - RegExpMatcher matcher = this.matcher; 114.8 + RegExpMatcher currentMatcher = this.matcher; 114.9 114.10 - if (matcher == null || matcher.getInput() != str) { 114.11 - matcher = new DefaultMatcher(str); 114.12 - this.matcher = matcher; 114.13 + if (currentMatcher == null || matcher.getInput() != str) { 114.14 + currentMatcher = new DefaultMatcher(str); 114.15 + this.matcher = currentMatcher; 114.16 } 114.17 114.18 - return matcher; 114.19 + return currentMatcher; 114.20 } 114.21 114.22 class DefaultMatcher implements RegExpMatcher {
115.1 --- a/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java Thu Mar 28 10:55:17 2013 -0700 115.2 +++ b/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java Mon Apr 01 21:42:31 2013 -0700 115.3 @@ -97,14 +97,14 @@ 115.4 return null; 115.5 } 115.6 115.7 - RegExpMatcher matcher = this.matcher; 115.8 + RegExpMatcher currentMatcher = this.matcher; 115.9 115.10 - if (matcher == null || input != matcher.getInput()) { 115.11 - matcher = new JoniMatcher(input); 115.12 - this.matcher = matcher; 115.13 + if (currentMatcher == null || input != currentMatcher.getInput()) { 115.14 + currentMatcher = new JoniMatcher(input); 115.15 + this.matcher = currentMatcher; 115.16 } 115.17 115.18 - return matcher; 115.19 + return currentMatcher; 115.20 } 115.21 115.22 /**
116.1 --- a/src/jdk/nashorn/internal/runtime/regexp/RegExp.java Thu Mar 28 10:55:17 2013 -0700 116.2 +++ b/src/jdk/nashorn/internal/runtime/regexp/RegExp.java Mon Apr 01 21:42:31 2013 -0700 116.3 @@ -156,7 +156,7 @@ 116.4 * 116.5 * @param key the message key 116.6 * @param str string argument 116.7 - * @throws jdk.nashorn.internal.runtime.ParserException 116.8 + * @throws jdk.nashorn.internal.runtime.ParserException unconditionally 116.9 */ 116.10 protected static void throwParserException(final String key, final String str) throws ParserException { 116.11 throw new ParserException(ECMAErrors.getMessage("parser.error.regex." + key, str));
117.1 --- a/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java Thu Mar 28 10:55:17 2013 -0700 117.2 +++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java Mon Apr 01 21:42:31 2013 -0700 117.3 @@ -25,7 +25,6 @@ 117.4 117.5 package jdk.nashorn.internal.runtime.regexp; 117.6 117.7 -import jdk.nashorn.internal.parser.Lexer; 117.8 import jdk.nashorn.internal.runtime.ParserException; 117.9 import jdk.nashorn.internal.runtime.options.Options; 117.10 117.11 @@ -35,7 +34,6 @@ 117.12 */ 117.13 public class RegExpFactory { 117.14 117.15 - 117.16 private final static RegExpFactory instance; 117.17 117.18 private final static String JDK = "jdk"; 117.19 @@ -60,7 +58,8 @@ 117.20 * Creates a Regular expression from the given {@code pattern} and {@code flags} strings. 117.21 * 117.22 * @param pattern RegExp pattern string 117.23 - * @param flags RegExp flags string 117.24 + * @param flags RegExp flags string 117.25 + * @return new RegExp 117.26 * @throws ParserException if flags is invalid or pattern string has syntax error. 117.27 */ 117.28 protected RegExp compile(final String pattern, final String flags) throws ParserException { 117.29 @@ -71,8 +70,8 @@ 117.30 * Compile a regexp with the given {@code source} and {@code flags}. 117.31 * 117.32 * @param pattern RegExp pattern string 117.33 - * @param flags flag string 117.34 - * 117.35 + * @param flags flag string 117.36 + * @return new RegExp 117.37 * @throws ParserException if invalid source or flags 117.38 */ 117.39 public static RegExp create(final String pattern, final String flags) {
118.1 --- a/src/jdk/nashorn/internal/runtime/regexp/RegExpResult.java Thu Mar 28 10:55:17 2013 -0700 118.2 +++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpResult.java Mon Apr 01 21:42:31 2013 -0700 118.3 @@ -80,11 +80,11 @@ 118.4 118.5 /** 118.6 * Get the group with the given index or the empty string if group index is not valid. 118.7 - * @param index the group index 118.8 + * @param groupIndex the group index 118.9 * @return the group or "" 118.10 */ 118.11 - public Object getGroup(int index) { 118.12 - return index >= 0 && index < groups.length ? groups[index] : ""; 118.13 + public Object getGroup(final int groupIndex) { 118.14 + return groupIndex >= 0 && groupIndex < groups.length ? groups[groupIndex] : ""; 118.15 } 118.16 118.17 /**
119.1 --- a/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java Thu Mar 28 10:55:17 2013 -0700 119.2 +++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java Mon Apr 01 21:42:31 2013 -0700 119.3 @@ -182,8 +182,6 @@ 119.4 * @return Committed token 119.5 */ 119.6 private boolean commit(final int n) { 119.7 - final int startIn = position; 119.8 - 119.9 switch (n) { 119.10 case 1: 119.11 sb.append(ch0);
120.1 --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java Thu Mar 28 10:55:17 2013 -0700 120.2 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java Mon Apr 01 21:42:31 2013 -0700 120.3 @@ -1459,4 +1459,4 @@ 120.4 private int finish() { 120.5 return bestLen; 120.6 } 120.7 -} 120.8 \ No newline at end of file 120.9 +}
121.1 --- a/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/AsciiTables.java Thu Mar 28 10:55:17 2013 -0700 121.2 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/AsciiTables.java Mon Apr 01 21:42:31 2013 -0700 121.3 @@ -154,4 +154,4 @@ 121.4 {0x59, 0x79}, 121.5 {0x5a, 0x7a} 121.6 }; 121.7 -} 121.8 \ No newline at end of file 121.9 +}
122.1 --- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties Thu Mar 28 10:55:17 2013 -0700 122.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties Mon Apr 01 21:42:31 2013 -0700 122.3 @@ -42,6 +42,8 @@ 122.4 parser.error.expected.comma=Expected comma but found {0} 122.5 parser.error.expected=Expected {0} but found {1} 122.6 parser.error.invalid.return=Invalid return statement 122.7 +parser.error.no.func.decl.here=Function declarations can only occur at program or function body level. You should use a function expression here instead. 122.8 +parser.error.no.func.decl.here.warn=Function declarations should only occur at program or function body level. Function declaration in nested block was converted to a function expression. 122.9 parser.error.property.redefinition=Property "{0}" already defined 122.10 parser.error.unexpected.token=Unexpected token: {0} 122.11 parser.error.many.vars.in.for.in.loop=Only one variable allowed in for..in loop 122.12 @@ -57,7 +59,7 @@ 122.13 parser.error.strict.cant.delete.ident=cannot delete identifier "{0}" in strict mode 122.14 parser.error.strict.param.redefinition=strict mode function cannot have duplicate parameter name "{0}" 122.15 parser.error.strict.no.octal=cannot use octal value in strict mode 122.16 -parser.error.strict.no.func.here=In strict mode, functions can only be declared at top-level or immediately within a function 122.17 +parser.error.strict.no.func.decl.here=In strict mode, function declarations can only occur at program or function body level. You should use a function expression here instead. 122.18 type.error.strict.getter.setter.poison=In strict mode, "caller", "callee", and "arguments" properties can not be accessed on functions or the arguments object 122.19 122.20 # not the expected type in a given context
123.1 --- a/src/jdk/nashorn/internal/runtime/resources/Options.properties Thu Mar 28 10:55:17 2013 -0700 123.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Options.properties Mon Apr 01 21:42:31 2013 -0700 123.3 @@ -165,6 +165,12 @@ 123.4 desc="Generate local variable table in .class files." \ 123.5 } 123.6 123.7 +nashorn.option.lazy.compilation = { \ 123.8 + name="--lazy-compilation", \ 123.9 + is_undocumented=true, \ 123.10 + desc="EXPERIMENTAL: Use lazy code generation strategies - do not compile the entire script at once." \ 123.11 +} 123.12 + 123.13 nashorn.option.loader.per.compile = { \ 123.14 name="--loader-per-compile", \ 123.15 is_undocumented=true, \
124.1 --- a/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js Thu Mar 28 10:55:17 2013 -0700 124.2 +++ b/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js Mon Apr 01 21:42:31 2013 -0700 124.3 @@ -1,21 +1,21 @@ 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 + * 124.9 * This code is free software; you can redistribute it and/or modify it 124.10 * under the terms of the GNU General Public License version 2 only, as 124.11 * published by the Free Software Foundation. 124.12 - * 124.13 + * 124.14 * This code is distributed in the hope that it will be useful, but WITHOUT 124.15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 124.16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 124.17 * version 2 for more details (a copy is included in the LICENSE file that 124.18 * accompanied this code). 124.19 - * 124.20 + * 124.21 * You should have received a copy of the GNU General Public License version 124.22 * 2 along with this work; if not, write to the Free Software Foundation, 124.23 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 124.24 - * 124.25 + * 124.26 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 124.27 * or visit www.oracle.com if you need additional information or have any 124.28 * questions. 124.29 @@ -34,7 +34,7 @@ 124.30 if (arguments.length < 2) { 124.31 throw new TypeError("JavaAdapter requires atleast two arguments"); 124.32 } 124.33 - 124.34 + 124.35 var types = Array.prototype.slice.call(arguments, 0, arguments.length - 1); 124.36 var NewType = Java.extend.apply(Java, types); 124.37 return new NewType(arguments[arguments.length - 1]); 124.38 @@ -56,10 +56,10 @@ 124.39 return type; 124.40 } catch (e) {} 124.41 } 124.42 - 124.43 + 124.44 return oldNoSuchProperty? oldNoSuchProperty(name) : undefined; 124.45 } 124.46 - 124.47 + 124.48 var prefix = "[JavaPackage "; 124.49 return function() { 124.50 for (var i in arguments) { 124.51 @@ -343,7 +343,9 @@ 124.52 configurable: true, enumerable: false, writable: true, 124.53 value: function(clazz) { 124.54 if (Java.isType(clazz)) { 124.55 - this[clazz.class.getSimpleName()] = clazz; 124.56 + var className = Java.typeName(clazz); 124.57 + var simpleName = className.substring(className.lastIndexOf('.') + 1); 124.58 + this[simpleName] = clazz; 124.59 } else { 124.60 throw new TypeError(clazz + " is not a Java class"); 124.61 }
125.1 --- a/src/jdk/nashorn/internal/runtime/resources/parser.js Thu Mar 28 10:55:17 2013 -0700 125.2 +++ b/src/jdk/nashorn/internal/runtime/resources/parser.js Mon Apr 01 21:42:31 2013 -0700 125.3 @@ -1,21 +1,21 @@ 125.4 /* 125.5 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 125.6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 125.7 - * 125.8 + * 125.9 * This code is free software; you can redistribute it and/or modify it 125.10 * under the terms of the GNU General Public License version 2 only, as 125.11 * published by the Free Software Foundation. 125.12 - * 125.13 + * 125.14 * This code is distributed in the hope that it will be useful, but WITHOUT 125.15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 125.16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 125.17 * version 2 for more details (a copy is included in the LICENSE file that 125.18 * accompanied this code). 125.19 - * 125.20 + * 125.21 * You should have received a copy of the GNU General Public License version 125.22 * 2 along with this work; if not, write to the Free Software Foundation, 125.23 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 125.24 - * 125.25 + * 125.26 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 125.27 * or visit www.oracle.com if you need additional information or have any 125.28 * questions. 125.29 @@ -47,7 +47,7 @@ 125.30 code = arguments[0]; 125.31 } 125.32 125.33 - var jsonStr = Packages.jdk.nashorn.internal.runtime.ScriptRuntime.parse(code, name, location); 125.34 + var jsonStr = Packages.jdk.nashorn.api.scripting.ScriptUtils.parse(code, name, location); 125.35 return JSON.parse(jsonStr, 125.36 function (prop, value) { 125.37 if (typeof(value) == 'string' && prop == "value") {
126.1 --- a/test/script/basic/JDK-8006755.js Thu Mar 28 10:55:17 2013 -0700 126.2 +++ b/test/script/basic/JDK-8006755.js Mon Apr 01 21:42:31 2013 -0700 126.3 @@ -31,7 +31,7 @@ 126.4 var scope = { x: "hello" }; 126.5 126.6 with (scope) { 126.7 - function main() { 126.8 + var main = function() { 126.9 if (x != "hello") { 126.10 fail("x != 'hello'"); 126.11 }
127.1 --- a/test/script/basic/JDK-8008448.js Thu Mar 28 10:55:17 2013 -0700 127.2 +++ b/test/script/basic/JDK-8008448.js Mon Apr 01 21:42:31 2013 -0700 127.3 @@ -32,7 +32,7 @@ 127.4 127.5 var File = Java.type("java.io.File"); 127.6 var FilenameFilter = Java.type("java.io.FilenameFilter"); 127.7 -var Source = Java.type("jdk.nashorn.internal.runtime.Source") 127.8 +var SourceHelper = Java.type("jdk.nashorn.test.models.SourceHelper") 127.9 127.10 // Filter out non .js files 127.11 var files = new File(__DIR__).listFiles(new FilenameFilter() { 127.12 @@ -44,5 +44,5 @@ 127.13 127.14 // parse each file to make sure it does not result in exception 127.15 for each (var f in files) { 127.16 - parse(new Source(f.toString(), f).getString()); 127.17 + parse(SourceHelper.readFully(f)); 127.18 }
128.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 128.2 +++ b/test/script/basic/JDK-8009868.js Mon Apr 01 21:42:31 2013 -0700 128.3 @@ -0,0 +1,35 @@ 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. 128.11 + * 128.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 128.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 128.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 128.15 + * version 2 for more details (a copy is included in the LICENSE file that 128.16 + * accompanied this code). 128.17 + * 128.18 + * You should have received a copy of the GNU General Public License version 128.19 + * 2 along with this work; if not, write to the Free Software Foundation, 128.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 128.21 + * 128.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 128.23 + * or visit www.oracle.com if you need additional information or have any 128.24 + * questions. 128.25 + */ 128.26 + 128.27 + 128.28 +/** 128.29 + * JDK-8009868: For loop with "true" as condition results in AssertionError in codegen 128.30 + * 128.31 + * @test 128.32 + * @run 128.33 + */ 128.34 + 128.35 +// This used to crash with AssertionError in codegen 128.36 +for(; true;) { 128.37 + break; 128.38 +}
129.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 129.2 +++ b/test/script/basic/JDK-8010199.js Mon Apr 01 21:42:31 2013 -0700 129.3 @@ -0,0 +1,51 @@ 129.4 +/* 129.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 129.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 129.7 + * 129.8 + * This code is free software; you can redistribute it and/or modify it 129.9 + * under the terms of the GNU General Public License version 2 only, as 129.10 + * published by the Free Software Foundation. 129.11 + * 129.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 129.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 129.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 129.15 + * version 2 for more details (a copy is included in the LICENSE file that 129.16 + * accompanied this code). 129.17 + * 129.18 + * You should have received a copy of the GNU General Public License version 129.19 + * 2 along with this work; if not, write to the Free Software Foundation, 129.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 129.21 + * 129.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 129.23 + * or visit www.oracle.com if you need additional information or have any 129.24 + * questions. 129.25 + */ 129.26 + 129.27 +/** 129.28 + * JDK-8010199: javax.script.Invocable implementation for nashorn does not return null when matching functions are missing 129.29 + * 129.30 + * @test 129.31 + * @run 129.32 + */ 129.33 + 129.34 +var m = new javax.script.ScriptEngineManager(); 129.35 +var e = m.getEngineByName("nashorn"); 129.36 + 129.37 +var iface = e.getInterface(java.lang.Runnable.class); 129.38 + 129.39 +if (iface != null) { 129.40 + fail("Expected interface object to be null"); 129.41 +} 129.42 + 129.43 +e.eval("var runcalled = false; function run() { runcalled = true }"); 129.44 + 129.45 +iface = e.getInterface(java.lang.Runnable.class); 129.46 +if (iface == null) { 129.47 + fail("Expected interface object to be non-null"); 129.48 +} 129.49 + 129.50 +iface.run(); 129.51 + 129.52 +if (e.get("runcalled") != true) { 129.53 + fail("runcalled is not true"); 129.54 +}
130.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 130.2 +++ b/test/script/basic/JDK-8010709.js Mon Apr 01 21:42:31 2013 -0700 130.3 @@ -0,0 +1,46 @@ 130.4 +/* 130.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 130.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 130.7 + * 130.8 + * This code is free software; you can redistribute it and/or modify it 130.9 + * under the terms of the GNU General Public License version 2 only, as 130.10 + * published by the Free Software Foundation. 130.11 + * 130.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 130.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 130.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 130.15 + * version 2 for more details (a copy is included in the LICENSE file that 130.16 + * accompanied this code). 130.17 + * 130.18 + * You should have received a copy of the GNU General Public License version 130.19 + * 2 along with this work; if not, write to the Free Software Foundation, 130.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 130.21 + * 130.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 130.23 + * or visit www.oracle.com if you need additional information or have any 130.24 + * questions. 130.25 + */ 130.26 + 130.27 +/** 130.28 + * JDK-8010709 org on the top level doesn't resolve 130.29 + * 130.30 + * @test 130.31 + * @run 130.32 + */ 130.33 + 130.34 +function check(pkgName) { 130.35 + if (typeof this[pkgName] != 'object') { 130.36 + fail(pkgName + " not defined"); 130.37 + } 130.38 + 130.39 + if (String(this[pkgName]) != '[JavaPackage ' + pkgName + ']') { 130.40 + fail(pkgName + " is not a JavaPackage"); 130.41 + } 130.42 +} 130.43 + 130.44 +check("com"); 130.45 +check("edu"); 130.46 +check("java"); 130.47 +check("javafx"); 130.48 +check("javax"); 130.49 +check("org");
131.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 131.2 +++ b/test/script/basic/JDK-8010720.js Mon Apr 01 21:42:31 2013 -0700 131.3 @@ -0,0 +1,49 @@ 131.4 +/* 131.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 131.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 131.7 + * 131.8 + * This code is free software; you can redistribute it and/or modify it 131.9 + * under the terms of the GNU General Public License version 2 only, as 131.10 + * published by the Free Software Foundation. 131.11 + * 131.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 131.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 131.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 131.15 + * version 2 for more details (a copy is included in the LICENSE file that 131.16 + * accompanied this code). 131.17 + * 131.18 + * You should have received a copy of the GNU General Public License version 131.19 + * 2 along with this work; if not, write to the Free Software Foundation, 131.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 131.21 + * 131.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 131.23 + * or visit www.oracle.com if you need additional information or have any 131.24 + * questions. 131.25 + */ 131.26 + 131.27 +/** 131.28 + * JDK-8010720: Linkage problem with java.lang.String.length() 131.29 + * 131.30 + * @test 131.31 + * @run 131.32 + */ 131.33 + 131.34 +var s = new java.lang.String("nashorn"); 131.35 + 131.36 +if (s.length() != 7) { 131.37 + fail("s.length() does not return expected value"); 131.38 +} 131.39 + 131.40 +if (s.length != 7) { 131.41 + fail("s.length does not return expected value"); 131.42 +} 131.43 + 131.44 + 131.45 +if ('hello'.length() != 5) { 131.46 + fail("'hello'.length() does not return expected value"); 131.47 +} 131.48 + 131.49 +if ('hello'.length != 5) { 131.50 + fail("'hello'.length does not return expected value"); 131.51 +} 131.52 +
132.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 132.2 +++ b/test/script/basic/JDK-8017010.js Mon Apr 01 21:42:31 2013 -0700 132.3 @@ -0,0 +1,68 @@ 132.4 +/* 132.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 132.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 132.7 + * 132.8 + * This code is free software; you can redistribute it and/or modify it 132.9 + * under the terms of the GNU General Public License version 2 only, as 132.10 + * published by the Free Software Foundation. 132.11 + * 132.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 132.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 132.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 132.15 + * version 2 for more details (a copy is included in the LICENSE file that 132.16 + * accompanied this code). 132.17 + * 132.18 + * You should have received a copy of the GNU General Public License version 132.19 + * 2 along with this work; if not, write to the Free Software Foundation, 132.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 132.21 + * 132.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 132.23 + * or visit www.oracle.com if you need additional information or have any 132.24 + * questions. 132.25 + */ 132.26 + 132.27 +/** 132.28 + * JDK-8010710 - slot/scope problem with temporary expressions 132.29 + * as array index in self modifying assigns 132.30 + * 132.31 + * @test 132.32 + * @run 132.33 + */ 132.34 +function zero() { 132.35 + return 0; 132.36 +} 132.37 + 132.38 +//try complex self modifying assignment and force slots to temporary value index operators 132.39 +var a = [1, 2, 3, 4, 5]; 132.40 +var b = [a, a]; 132.41 +print(b[zero() + 1][2 + a[0]] += 10); 132.42 + 132.43 +//repro for NASHORN-258 that never made it 132.44 +function AddRoundKey() { 132.45 + var r=0; 132.46 + state[r][1] &= 17; 132.47 +} 132.48 + 132.49 +var srcFiles = []; 132.50 +for(i=0;i<100;i++) { 132.51 + srcFiles.push('dummy'); 132.52 +} 132.53 +var added = ''; 132.54 + 132.55 +//this broke the javafx build system. verify it works 132.56 +function bouncingBall() { 132.57 + for (j=0; j<100; j++) { 132.58 + added += srcFiles[j]; 132.59 + } 132.60 +} 132.61 +bouncingBall(); 132.62 +print(added); 132.63 + 132.64 +//this is how they should have done it for speed, that works always, verify this too 132.65 +function bouncingBall2() { 132.66 + for (var k=0; k<100; k++) { 132.67 + added += srcFiles[k]; 132.68 + } 132.69 +} 132.70 +bouncingBall2(); 132.71 +print(added);
133.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 133.2 +++ b/test/script/basic/JDK-8017010.js.EXPECTED Mon Apr 01 21:42:31 2013 -0700 133.3 @@ -0,0 +1,3 @@ 133.4 +14 133.5 +dummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummy 133.6 +dummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummydummy
134.1 --- a/test/script/basic/NASHORN-258.js Thu Mar 28 10:55:17 2013 -0700 134.2 +++ b/test/script/basic/NASHORN-258.js Mon Apr 01 21:42:31 2013 -0700 134.3 @@ -29,6 +29,16 @@ 134.4 */ 134.5 134.6 function test3(a) { 134.7 + for (i = 0; i < a.length ; i++) { 134.8 + for (j = 0; j < a[i].length ; j++) { 134.9 + for (k = 0; k < a[i][j].length ; k++) { 134.10 + a[i][j][k] *= 8; 134.11 + } 134.12 + } 134.13 + } 134.14 +} 134.15 + 134.16 +function test3local(a) { 134.17 for (var i = 0; i < a.length ; i++) { 134.18 for (var j = 0; j < a[i].length ; j++) { 134.19 for (var k = 0; k < a[i][j].length ; k++) { 134.20 @@ -45,6 +55,8 @@ 134.21 test3(array); 134.22 print(array); 134.23 134.24 +test3local(array); 134.25 +print(array); 134.26 134.27 function outer() { 134.28
135.1 --- a/test/script/basic/NASHORN-258.js.EXPECTED Thu Mar 28 10:55:17 2013 -0700 135.2 +++ b/test/script/basic/NASHORN-258.js.EXPECTED Mon Apr 01 21:42:31 2013 -0700 135.3 @@ -1,2 +1,3 @@ 135.4 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 135.5 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64 135.6 1,1,8,1,1,8,1,1,8,1,1,8,1,1,8,1,1,8,1,1,8,1,1,8,1,1,8
136.1 --- a/test/script/basic/NASHORN-401.js Thu Mar 28 10:55:17 2013 -0700 136.2 +++ b/test/script/basic/NASHORN-401.js Mon Apr 01 21:42:31 2013 -0700 136.3 @@ -28,7 +28,7 @@ 136.4 * @run 136.5 */ 136.6 136.7 -var t = new Packages.jdk.nashorn.internal.runtime.Nashorn401TestSubject(); 136.8 +var t = new Packages.jdk.nashorn.test.models.Nashorn401TestSubject(); 136.9 136.10 print(t.method2(10)); 136.11 print(t.method2(10.2));
137.1 --- a/test/script/basic/NASHORN-837.js Thu Mar 28 10:55:17 2013 -0700 137.2 +++ b/test/script/basic/NASHORN-837.js Mon Apr 01 21:42:31 2013 -0700 137.3 @@ -28,23 +28,13 @@ 137.4 * @run 137.5 */ 137.6 137.7 -var failed = false; 137.8 - 137.9 try { 137.10 - try { 137.11 - throw new TypeError('error'); 137.12 - } catch (iox) { 137.13 - function f() { 137.14 - print(iox.message); 137.15 - } 137.16 + throw new TypeError('error'); 137.17 +} catch (iox) { 137.18 + var f = function() { 137.19 + if(iox.message != 'error') { 137.20 + print("Failure! iox did not throw correct exception"); 137.21 + } 137.22 } 137.23 - f(); 137.24 -} catch (e) { 137.25 - failed = (e instanceof ReferenceError); 137.26 - //iox not defined should be thrown 137.27 } 137.28 - 137.29 -if (!failed) { 137.30 - print("Failure! iox did not throw correct exception"); 137.31 -} 137.32 - 137.33 +f();
138.1 --- a/test/script/basic/compile-octane.js.EXPECTED Thu Mar 28 10:55:17 2013 -0700 138.2 +++ b/test/script/basic/compile-octane.js.EXPECTED Mon Apr 01 21:42:31 2013 -0700 138.3 @@ -16,6 +16,9 @@ 138.4 Compiling... gbemu.js 138.5 Compiled OK: gbemu.js 138.6 138.7 +Compiling... mandreel.js 138.8 +Compiled OK: mandreel.js 138.9 + 138.10 Compiling... navier-stokes.js 138.11 Compiled OK: navier-stokes.js 138.12
139.1 --- a/test/script/basic/consstring.js Thu Mar 28 10:55:17 2013 -0700 139.2 +++ b/test/script/basic/consstring.js Mon Apr 01 21:42:31 2013 -0700 139.3 @@ -37,4 +37,4 @@ 139.4 list.add((str + "3").toString()); // toString() called on primitive string 139.5 list.add(new String(str + "4").toString()); // toString() called on String object 139.6 139.7 -Packages.jdk.nashorn.internal.test.models.StringArgs.checkString(list); 139.8 +Packages.jdk.nashorn.test.models.StringArgs.checkString(list);
140.1 --- a/test/script/basic/fileline.js Thu Mar 28 10:55:17 2013 -0700 140.2 +++ b/test/script/basic/fileline.js Mon Apr 01 21:42:31 2013 -0700 140.3 @@ -41,8 +41,8 @@ 140.4 load(__DIR__ + "loadedfile.js"); 140.5 140.6 // Add check for base part of a URL. We can't test __DIR__ inside 140.7 -// a script that is downloaded from a URL. check for Source.baseURL 140.8 +// a script that is downloaded from a URL. check for SourceHelper.baseURL 140.9 // which is exposed as __DIR__ for URL case. 140.10 140.11 var url = new java.net.URL("http://www.acme.com:8080/foo/bar.js"); 140.12 -print(Packages.jdk.nashorn.internal.runtime.Source.baseURL(url)); 140.13 +print(Packages.jdk.nashorn.test.models.SourceHelper.baseURL(url));
141.1 --- a/test/script/basic/javainnerclasses.js Thu Mar 28 10:55:17 2013 -0700 141.2 +++ b/test/script/basic/javainnerclasses.js Mon Apr 01 21:42:31 2013 -0700 141.3 @@ -29,25 +29,25 @@ 141.4 */ 141.5 141.6 // Do it with Java.type() 141.7 -var outer = new (Java.type("jdk.nashorn.internal.test.models.OuterClass"))("apple") 141.8 +var outer = new (Java.type("jdk.nashorn.test.models.OuterClass"))("apple") 141.9 print(outer) 141.10 -var innerStatic = new (Java.type("jdk.nashorn.internal.test.models.OuterClass$InnerStaticClass"))("orange") 141.11 +var innerStatic = new (Java.type("jdk.nashorn.test.models.OuterClass$InnerStaticClass"))("orange") 141.12 print(innerStatic) 141.13 -var innerNonStatic = new (Java.type("jdk.nashorn.internal.test.models.OuterClass$InnerNonStaticClass"))(outer, "pear") 141.14 +var innerNonStatic = new (Java.type("jdk.nashorn.test.models.OuterClass$InnerNonStaticClass"))(outer, "pear") 141.15 print(innerNonStatic) 141.16 141.17 // Now do it with Packages and explicit $ names 141.18 -var outer = new Packages.jdk.nashorn.internal.test.models.OuterClass("red") 141.19 +var outer = new Packages.jdk.nashorn.test.models.OuterClass("red") 141.20 print(outer) 141.21 -var innerStatic = new Packages.jdk.nashorn.internal.test.models.OuterClass$InnerStaticClass("green") 141.22 +var innerStatic = new Packages.jdk.nashorn.test.models.OuterClass$InnerStaticClass("green") 141.23 print(innerStatic) 141.24 -var innerNonStatic = new Packages.jdk.nashorn.internal.test.models.OuterClass$InnerNonStaticClass(outer, "blue") 141.25 +var innerNonStatic = new Packages.jdk.nashorn.test.models.OuterClass$InnerNonStaticClass(outer, "blue") 141.26 print(innerNonStatic) 141.27 141.28 // Now do it with Packages and nested properties 141.29 -var outer = new Packages.jdk.nashorn.internal.test.models.OuterClass("sweet") 141.30 +var outer = new Packages.jdk.nashorn.test.models.OuterClass("sweet") 141.31 print(outer) 141.32 -var innerStatic = new Packages.jdk.nashorn.internal.test.models.OuterClass.InnerStaticClass("sour") 141.33 +var innerStatic = new Packages.jdk.nashorn.test.models.OuterClass.InnerStaticClass("sour") 141.34 print(innerStatic) 141.35 -var innerNonStatic = new Packages.jdk.nashorn.internal.test.models.OuterClass.InnerNonStaticClass(outer, "bitter") 141.36 +var innerNonStatic = new Packages.jdk.nashorn.test.models.OuterClass.InnerNonStaticClass(outer, "bitter") 141.37 print(innerNonStatic)
142.1 --- a/test/script/basic/list.js Thu Mar 28 10:55:17 2013 -0700 142.2 +++ b/test/script/basic/list.js Mon Apr 01 21:42:31 2013 -0700 142.3 @@ -28,7 +28,7 @@ 142.4 * @run 142.5 */ 142.6 var l = new java.util.ArrayList(); 142.7 -print("l.class.name=" + l.class.name) // Has "class" property like any POJO 142.8 +print("l.class.name=" + Java.typeName(l.class)) // Has "class" property like any POJO 142.9 142.10 l.add("foo") 142.11 l.add("bar")
143.1 --- a/test/script/basic/map.js Thu Mar 28 10:55:17 2013 -0700 143.2 +++ b/test/script/basic/map.js Mon Apr 01 21:42:31 2013 -0700 143.3 @@ -28,7 +28,7 @@ 143.4 * @run 143.5 */ 143.6 var m = new (Java.type("java.util.LinkedHashMap")); 143.7 -print("m.class.name=" + m.class.name) // Has "class" property like any POJO 143.8 +print("m.class.name=" + Java.typeName(m.class)) // Has "class" property like any POJO 143.9 143.10 var empty_key = "empty" 143.11
144.1 --- a/test/script/basic/run-octane.js Thu Mar 28 10:55:17 2013 -0700 144.2 +++ b/test/script/basic/run-octane.js Mon Apr 01 21:42:31 2013 -0700 144.3 @@ -31,7 +31,8 @@ 144.4 "crypto.js", 144.5 "deltablue.js", 144.6 "earley-boyer.js", 144.7 - "gbemu.js", 144.8 + "gbemu.js", 144.9 + "mandreel.js", 144.10 "navier-stokes.js", 144.11 "pdfjs.js", 144.12 "raytrace.js", 144.13 @@ -49,6 +50,12 @@ 144.14 { name: "gbemu.js" }, 144.15 ]; 144.16 144.17 + 144.18 +//TODO mandreel can be compiled as a test, but not run multiple times unless modified to not have global state 144.19 +var compileOnly = { 144.20 + "mandreel.js" : true 144.21 +}; 144.22 + 144.23 var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__; 144.24 144.25 // TODO: why is this path hard coded when it's defined in project properties? 144.26 @@ -63,6 +70,10 @@ 144.27 return str.indexOf(suffix, str.length - suffix.length) !== -1; 144.28 } 144.29 144.30 +function should_compile_only(name) { 144.31 + return (typeof compile_only !== 'undefined') || compileOnly[name] === true; 144.32 +} 144.33 + 144.34 function run_one_benchmark(arg, iters) { 144.35 144.36 var file_name; 144.37 @@ -77,14 +88,18 @@ 144.38 } 144.39 file_name = file[file.length - 1]; 144.40 144.41 - if (typeof compile_only !== 'undefined') { 144.42 + var compile_and_return = should_compile_only(file_name); 144.43 + if (compile_and_return) { 144.44 + if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them 144.45 + return; 144.46 + } 144.47 print("Compiling... " + file_name); 144.48 } 144.49 144.50 load(path + 'base.js'); 144.51 load(arg); 144.52 144.53 - if (typeof compile_only !== 'undefined') { 144.54 + if (compile_and_return) { 144.55 print("Compiled OK: " + file_name); 144.56 print(""); 144.57 return; 144.58 @@ -164,7 +179,7 @@ 144.59 144.60 function run_suite(tests, iters) { 144.61 for (var idx = 0; idx < tests.length; idx++) { 144.62 - run_one_benchmark(tests[idx], iters, false); 144.63 + run_one_benchmark(tests[idx], iters); 144.64 } 144.65 } 144.66
145.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 145.2 +++ b/test/script/basic/runsunspider-eager.js Mon Apr 01 21:42:31 2013 -0700 145.3 @@ -0,0 +1,33 @@ 145.4 +/* 145.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 145.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 145.7 + * 145.8 + * This code is free software; you can redistribute it and/or modify it 145.9 + * under the terms of the GNU General Public License version 2 only, as 145.10 + * published by the Free Software Foundation. 145.11 + * 145.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 145.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 145.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 145.15 + * version 2 for more details (a copy is included in the LICENSE file that 145.16 + * accompanied this code). 145.17 + * 145.18 + * You should have received a copy of the GNU General Public License version 145.19 + * 2 along with this work; if not, write to the Free Software Foundation, 145.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 145.21 + * 145.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 145.23 + * or visit www.oracle.com if you need additional information or have any 145.24 + * questions. 145.25 + */ 145.26 + 145.27 +/** 145.28 + * runsunspider : runs the sunspider tests and checks for compliance 145.29 + * 145.30 + * @test 145.31 + * @option -timezone=PST 145.32 + * @runif external.sunspider 145.33 + */ 145.34 + 145.35 +load(__DIR__ + "runsunspider.js"); 145.36 +
146.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 146.2 +++ b/test/script/basic/runsunspider-eager.js.EXPECTED Mon Apr 01 21:42:31 2013 -0700 146.3 @@ -0,0 +1,1 @@ 146.4 +Sunspider finished!
147.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 147.2 +++ b/test/script/basic/runsunspider-lazy.js Mon Apr 01 21:42:31 2013 -0700 147.3 @@ -0,0 +1,34 @@ 147.4 +/* 147.5 + * Copyright (c) 2010, 2013, 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 + * runsunspider : runs the sunspider tests and checks for compliance 147.29 + * 147.30 + * @test 147.31 + * @option -timezone=PST 147.32 + * @option --lazy-compilation 147.33 + * @runif external.sunspider 147.34 + */ 147.35 + 147.36 +load(__DIR__ + "runsunspider.js"); 147.37 +
148.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 148.2 +++ b/test/script/basic/runsunspider-lazy.js.EXPECTED Mon Apr 01 21:42:31 2013 -0700 148.3 @@ -0,0 +1,1 @@ 148.4 +Sunspider finished!
149.1 --- a/test/script/basic/runsunspider.js Thu Mar 28 10:55:17 2013 -0700 149.2 +++ b/test/script/basic/runsunspider.js Mon Apr 01 21:42:31 2013 -0700 149.3 @@ -24,39 +24,11 @@ 149.4 /** 149.5 * runsunspider : runs the sunspider tests and checks for compliance 149.6 * 149.7 - * @test 149.8 - * @option -timezone=PST 149.9 - * @runif external.sunspider 149.10 - */ 149.11 - 149.12 -/* 149.13 - * Copyright (c) 2010-2011, Oracle and/or its affiliates. All rights reserved. 149.14 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 149.15 - * 149.16 - * This code is free software; you can redistribute it and/or modify it 149.17 - * under the terms of the GNU General Public License version 2 only, as 149.18 - * published by the Free Software Foundation. Oracle designates this 149.19 - * particular file as subject to the "Classpath" exception as provided 149.20 - * by Oracle in the LICENSE file that accompanied this code. 149.21 - * 149.22 - * This code is distributed in the hope that it will be useful, but WITHOUT 149.23 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 149.24 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 149.25 - * version 2 for more details (a copy is included in the LICENSE file that 149.26 - * accompanied this code). 149.27 - * 149.28 - * You should have received a copy of the GNU General Public License version 149.29 - * 2 along with this work; if not, write to the Free Software Foundation, 149.30 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 149.31 - * 149.32 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 149.33 - * or visit www.oracle.com if you need additional information or have any 149.34 - * questions. 149.35 + * @subtest 149.36 */ 149.37 149.38 /** 149.39 * This is not a test, but a test "framework" for running sunspider tests. 149.40 - * 149.41 */ 149.42 149.43 function assertEq(a, b) {
150.1 --- a/test/script/basic/runsunspider.js.EXPECTED Thu Mar 28 10:55:17 2013 -0700 150.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 150.3 @@ -1,1 +0,0 @@ 150.4 -Sunspider finished!
151.1 --- a/test/script/basic/stdin.js Thu Mar 28 10:55:17 2013 -0700 151.2 +++ b/test/script/basic/stdin.js Mon Apr 01 21:42:31 2013 -0700 151.3 @@ -28,8 +28,8 @@ 151.4 * @run 151.5 */ 151.6 151.7 -print(java.lang.System.in.class.name); 151.8 +print(Java.typeName(java.lang.System.in.class)); 151.9 var prop = "in"; 151.10 -print(java.lang.System[prop].class.name); 151.11 -print(java.lang.System["in"].class.name); 151.12 +print(Java.typeName(java.lang.System[prop].class)); 151.13 +print(Java.typeName(java.lang.System["in"].class)); 151.14
152.1 --- a/test/script/currently-failing/JDK-8006529.js Thu Mar 28 10:55:17 2013 -0700 152.2 +++ b/test/script/currently-failing/JDK-8006529.js Mon Apr 01 21:42:31 2013 -0700 152.3 @@ -39,12 +39,13 @@ 152.4 * and FunctionNode because of package-access check and so reflective calls. 152.5 */ 152.6 152.7 -var Parser = Java.type("jdk.nashorn.internal.parser.Parser") 152.8 -var Compiler = Java.type("jdk.nashorn.internal.codegen.Compiler") 152.9 -var Context = Java.type("jdk.nashorn.internal.runtime.Context") 152.10 +var Parser = Java.type("jdk.nashorn.internal.parser.Parser") 152.11 +var Compiler = Java.type("jdk.nashorn.internal.codegen.Compiler") 152.12 +var Context = Java.type("jdk.nashorn.internal.runtime.Context") 152.13 var ScriptEnvironment = Java.type("jdk.nashorn.internal.runtime.ScriptEnvironment") 152.14 -var Source = Java.type("jdk.nashorn.internal.runtime.Source") 152.15 -var FunctionNode = Java.type("jdk.nashorn.internal.ir.FunctionNode") 152.16 +var Source = Java.type("jdk.nashorn.internal.runtime.Source") 152.17 +var FunctionNode = Java.type("jdk.nashorn.internal.ir.FunctionNode") 152.18 +var ThrowErrorManager = Java.type("jdk.nashorn.internal.runtime.Context$ThrowErrorManager"); 152.19 152.20 // Compiler class methods and fields 152.21 var parseMethod = Parser.class.getMethod("parse"); 152.22 @@ -90,7 +91,7 @@ 152.23 // representing it. 152.24 function compile(source) { 152.25 var source = new Source("<no name>", source); 152.26 - var parser = new Parser(Context.getContext().getEnv(), source, null); 152.27 + var parser = new Parser(Context.getContext().getEnv(), source, new ThrowErrorManager()); 152.28 var func = parseMethod.invoke(parser); 152.29 var compiler = new Compiler(Context.getContext().getEnv(), func); 152.30
153.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 153.2 +++ b/test/script/currently-failing/clone_ir.js Mon Apr 01 21:42:31 2013 -0700 153.3 @@ -0,0 +1,100 @@ 153.4 +/* 153.5 + * Copyright (c) 2010, 2013, 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 + * clone_ir : Check that functionNode.clone copies all nodes and that they 153.29 + * are not the same references 153.30 + * 153.31 + * @test 153.32 + * @run 153.33 + */ 153.34 + 153.35 +var js1 = "var tuple = { func : function f(x) { if (x) { print('true'); { print('block_under-true'); } } else { print('false'); } } }"; 153.36 + 153.37 +var Parser = Java.type("jdk.nashorn.internal.parser.Parser"); 153.38 +var ASTWriter = Java.type("jdk.nashorn.internal.ir.debug.ASTWriter"); 153.39 +var Context = Java.type("jdk.nashorn.internal.runtime.Context"); 153.40 +var ScriptEnvironment = Java.type("jdk.nashorn.internal.runtime.ScriptEnvironment"); 153.41 +var Source = Java.type("jdk.nashorn.internal.runtime.Source"); 153.42 +var FunctionNode = Java.type("jdk.nashorn.internal.ir.FunctionNode"); 153.43 +var ThrowErrorManager = Java.type("jdk.nashorn.internal.runtime.Context$ThrowErrorManager"); 153.44 +var System = Java.type("java.lang.System"); 153.45 + 153.46 +var toArrayMethod = ASTWriter.class.getMethod("toArray"); 153.47 +var parseMethod = Parser.class.getMethod("parse"); 153.48 + 153.49 +function toString(obj) { 153.50 + var output = "{ "; 153.51 + for (property in obj) { 153.52 + output += property + ': ' + obj[property]+'; '; 153.53 + } 153.54 + return output + '}' 153.55 +} 153.56 + 153.57 +function flatten(func) { 153.58 + var writer = new ASTWriter(func); 153.59 + var funcList = toArrayMethod.invoke(writer); 153.60 + 153.61 + var res = []; 153.62 + for each (x in funcList) { 153.63 + res.push({ name: x.getClass().getName(), id: System.identityHashCode(x) }); 153.64 + } 153.65 + return res; 153.66 +} 153.67 + 153.68 +function check(contents) { 153.69 + return check_src(new Source("<no name>", contents)); 153.70 +} 153.71 + 153.72 +function check_src(src) { 153.73 + var parser = new Parser(Context.getContext().getEnv(), src, new ThrowErrorManager()); 153.74 + 153.75 + var func = parseMethod.invoke(parser); 153.76 + print(func); 153.77 + var func2 = func.clone(); 153.78 + 153.79 + var f1 = flatten(func); 153.80 + var f2 = flatten(func2); 153.81 + 153.82 + print(f1.map(toString)); 153.83 + print(f2.map(toString)); 153.84 + 153.85 + if (f1.length != f2.length) { 153.86 + print("length difference between original and clone " + f1.length + " != " + f2.length); 153.87 + return false; 153.88 + } 153.89 + 153.90 + for (var i = 0; i < f1.length; i++) { 153.91 + if (f1[i].name !== f2[i].name) { 153.92 + print("name conflict at " + i + " " + f1[i].name + " != " + f2[i].name); 153.93 + return false; 153.94 + } else if (f1[i].id === f2[i].id) { 153.95 + print("id problem at " + i + " " + toString(f1[i]) + " was not deep copied to " + toString(f2[i]) + " became " + f1[i].id + " != " + f2[i].id); 153.96 + return false; 153.97 + } 153.98 + } 153.99 + 153.100 + return true; 153.101 +} 153.102 + 153.103 +print(check(js1));
154.1 --- a/test/script/sandbox/javaextend.js Thu Mar 28 10:55:17 2013 -0700 154.2 +++ b/test/script/sandbox/javaextend.js Mon Apr 01 21:42:31 2013 -0700 154.3 @@ -27,7 +27,7 @@ 154.4 */ 154.5 154.6 function model(n) { 154.7 - return Java.type("jdk.nashorn.internal.test.models." + n) 154.8 + return Java.type("jdk.nashorn.test.models." + n) 154.9 } 154.10 154.11 // Can't extend a final class
155.1 --- a/test/script/sandbox/javaextend.js.EXPECTED Thu Mar 28 10:55:17 2013 -0700 155.2 +++ b/test/script/sandbox/javaextend.js.EXPECTED Mon Apr 01 21:42:31 2013 -0700 155.3 @@ -1,6 +1,6 @@ 155.4 -TypeError: Can not extend final class jdk.nashorn.internal.test.models.FinalClass. 155.5 -TypeError: Can not extend class jdk.nashorn.internal.test.models.NoAccessibleConstructorClass as it has no public or protected constructors. 155.6 -TypeError: Can not extend/implement non-public class/interface jdk.nashorn.internal.test.models.NonPublicClass. 155.7 +TypeError: Can not extend final class jdk.nashorn.test.models.FinalClass. 155.8 +TypeError: Can not extend class jdk.nashorn.test.models.NoAccessibleConstructorClass as it has no public or protected constructors. 155.9 +TypeError: Can not extend/implement non-public class/interface jdk.nashorn.test.models.NonPublicClass. 155.10 TypeError: Can not extend multiple classes java.lang.Number and java.lang.Thread. At most one of the specified types can be a class, the rest must all be interfaces. 155.11 abcdabcd 155.12 run-object
156.1 --- a/test/script/sandbox/reflection.js Thu Mar 28 10:55:17 2013 -0700 156.2 +++ b/test/script/sandbox/reflection.js Mon Apr 01 21:42:31 2013 -0700 156.3 @@ -30,9 +30,7 @@ 156.4 */ 156.5 156.6 function check(e) { 156.7 - if (e instanceof java.lang.SecurityException) { 156.8 - print(e); 156.9 - } else { 156.10 + if (! (e instanceof java.lang.SecurityException)) { 156.11 fail("expected SecurityException, got " + e); 156.12 } 156.13 }
157.1 --- a/test/script/sandbox/reflection.js.EXPECTED Thu Mar 28 10:55:17 2013 -0700 157.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 157.3 @@ -1,1 +0,0 @@ 157.4 -java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")
158.1 --- a/test/script/sandbox/unsafe.js Thu Mar 28 10:55:17 2013 -0700 158.2 +++ b/test/script/sandbox/unsafe.js Mon Apr 01 21:42:31 2013 -0700 158.3 @@ -30,9 +30,7 @@ 158.4 */ 158.5 158.6 function check(e) { 158.7 - if (e instanceof java.lang.SecurityException) { 158.8 - print(e); 158.9 - } else { 158.10 + if (! (e instanceof java.lang.SecurityException)) { 158.11 fail("expected SecurityException, got " + e); 158.12 } 158.13 }
159.1 --- a/test/script/sandbox/unsafe.js.EXPECTED Thu Mar 28 10:55:17 2013 -0700 159.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 159.3 @@ -1,4 +0,0 @@ 159.4 -java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.sun.misc") 159.5 -java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.sun.misc") 159.6 -java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.sun") 159.7 -java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "getClassLoader")
160.1 --- a/test/script/trusted/urlreader.js Thu Mar 28 10:55:17 2013 -0700 160.2 +++ b/test/script/trusted/urlreader.js Mon Apr 01 21:42:31 2013 -0700 160.3 @@ -9,7 +9,7 @@ 160.4 var URL = Java.type("java.net.URL"); 160.5 var File = Java.type("java.io.File"); 160.6 var JString = Java.type("java.lang.String"); 160.7 -var Source = Java.type("jdk.nashorn.internal.runtime.Source"); 160.8 +var SourceHelper = Java.type("jdk.nashorn.test.models.SourceHelper"); 160.9 160.10 var url = new File(__FILE__).toURI().toURL(); 160.11 var reader = new URLReader(url); 160.12 @@ -19,9 +19,9 @@ 160.13 160.14 // check URL read 160.15 // read URL content by directly reading from URL 160.16 -var str = new Source(url.toString(), url).getString(); 160.17 +var str = SourceHelper.readFully(url); 160.18 // read URL content via URLReader 160.19 -var content = new JString(Source.readFully(reader)); 160.20 +var content = new JString(SourceHelper.readFully(reader)); 160.21 160.22 // assert that the content is same 160.23 Assert.assertEquals(str, content);
161.1 --- a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Thu Mar 28 10:55:17 2013 -0700 161.2 +++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Mon Apr 01 21:42:31 2013 -0700 161.3 @@ -47,7 +47,6 @@ 161.4 import javax.script.ScriptEngineManager; 161.5 import javax.script.ScriptException; 161.6 import javax.script.SimpleScriptContext; 161.7 -import jdk.nashorn.internal.runtime.Version; 161.8 import netscape.javascript.JSObject; 161.9 import org.testng.Assert; 161.10 import org.testng.annotations.Test; 161.11 @@ -129,7 +128,6 @@ 161.12 assertEquals(fac.getParameter(ScriptEngine.NAME), "javascript"); 161.13 assertEquals(fac.getLanguageVersion(), "ECMA - 262 Edition 5.1"); 161.14 assertEquals(fac.getEngineName(), "Oracle Nashorn"); 161.15 - assertEquals(fac.getEngineVersion(), Version.version()); 161.16 assertEquals(fac.getOutputStatement("context"), "print(context)"); 161.17 assertEquals(fac.getProgram("print('hello')", "print('world')"), "print('hello');print('world');"); 161.18 assertEquals(fac.getParameter(ScriptEngine.NAME), "javascript"); 161.19 @@ -285,6 +283,68 @@ 161.20 } 161.21 } 161.22 161.23 + public interface Foo { 161.24 + public void bar(); 161.25 + } 161.26 + 161.27 + public interface Foo2 extends Foo { 161.28 + public void bar2(); 161.29 + } 161.30 + 161.31 + @Test 161.32 + public void getInterfaceMissingTest() { 161.33 + final ScriptEngineManager manager = new ScriptEngineManager(); 161.34 + final ScriptEngine engine = manager.getEngineByName("nashorn"); 161.35 + 161.36 + // don't define any function. 161.37 + try { 161.38 + engine.eval(""); 161.39 + } catch (final Exception exp) { 161.40 + exp.printStackTrace(); 161.41 + fail(exp.getMessage()); 161.42 + } 161.43 + 161.44 + Runnable runnable = ((Invocable)engine).getInterface(Runnable.class); 161.45 + if (runnable != null) { 161.46 + fail("runnable is not null!"); 161.47 + } 161.48 + 161.49 + // now define "run" 161.50 + try { 161.51 + engine.eval("function run() { print('this is run function'); }"); 161.52 + } catch (final Exception exp) { 161.53 + exp.printStackTrace(); 161.54 + fail(exp.getMessage()); 161.55 + } 161.56 + runnable = ((Invocable)engine).getInterface(Runnable.class); 161.57 + // should not return null now! 161.58 + runnable.run(); 161.59 + 161.60 + // define only one method of "Foo2" 161.61 + try { 161.62 + engine.eval("function bar() { print('bar function'); }"); 161.63 + } catch (final Exception exp) { 161.64 + exp.printStackTrace(); 161.65 + fail(exp.getMessage()); 161.66 + } 161.67 + 161.68 + Foo2 foo2 = ((Invocable)engine).getInterface(Foo2.class); 161.69 + if (foo2 != null) { 161.70 + throw new RuntimeException("foo2 is not null!"); 161.71 + } 161.72 + 161.73 + // now define other method of "Foo2" 161.74 + try { 161.75 + engine.eval("function bar2() { print('bar2 function'); }"); 161.76 + } catch (final Exception exp) { 161.77 + exp.printStackTrace(); 161.78 + fail(exp.getMessage()); 161.79 + } 161.80 + foo2 = ((Invocable)engine).getInterface(Foo2.class); 161.81 + foo2.bar(); 161.82 + foo2.bar2(); 161.83 + } 161.84 + 161.85 @Test 161.86 public void accessGlobalTest() { 161.87 final ScriptEngineManager m = new ScriptEngineManager(); 161.88 @@ -313,27 +373,6 @@ 161.89 } 161.90 } 161.91 161.92 - public static void alert(final Object msg) { 161.93 - System.out.println(msg); 161.94 - } 161.95 - 161.96 - @Test 161.97 - public void exposeMethodTest() { 161.98 - final ScriptEngineManager m = new ScriptEngineManager(); 161.99 - final ScriptEngine e = m.getEngineByName("nashorn"); 161.100 - 161.101 - try { 161.102 - final Method alert = ScriptEngineTest.class.getMethod("alert", Object.class); 161.103 - // expose a Method object as global var. 161.104 - e.put("alert", alert); 161.105 - // call the global var. 161.106 - e.eval("alert.invoke(null, 'alert! alert!!')"); 161.107 - } catch (final NoSuchMethodException | SecurityException | ScriptException exp) { 161.108 - exp.printStackTrace(); 161.109 - fail(exp.getMessage()); 161.110 - } 161.111 - } 161.112 - 161.113 @Test 161.114 public void putGlobalFunctionTest() { 161.115 final ScriptEngineManager m = new ScriptEngineManager(); 161.116 @@ -593,13 +632,6 @@ 161.117 } 161.118 161.119 @Test 161.120 - public void versionTest() { 161.121 - final ScriptEngineManager m = new ScriptEngineManager(); 161.122 - final ScriptEngine e = m.getEngineByName("nashorn"); 161.123 - assertEquals(e.getFactory().getEngineVersion(), Version.version()); 161.124 - } 161.125 - 161.126 - @Test 161.127 public void noEnumerablePropertiesTest() { 161.128 final ScriptEngineManager m = new ScriptEngineManager(); 161.129 final ScriptEngine e = m.getEngineByName("nashorn"); 161.130 @@ -874,26 +906,4 @@ 161.131 fail(se.getMessage()); 161.132 } 161.133 } 161.134 - 161.135 - @Test 161.136 - public void factoryOptionsTest() { 161.137 - final ScriptEngineManager sm = new ScriptEngineManager(); 161.138 - for (ScriptEngineFactory fac : sm.getEngineFactories()) { 161.139 - if (fac instanceof NashornScriptEngineFactory) { 161.140 - final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac; 161.141 - // specify --no-syntax-extensions flag 161.142 - final String[] options = new String[] { "--no-syntax-extensions" }; 161.143 - final ScriptEngine e = nfac.getScriptEngine(options); 161.144 - try { 161.145 - // try nashorn specific extension 161.146 - e.eval("var f = funtion(x) 2*x;"); 161.147 - fail("should have thrown exception!"); 161.148 - } catch (final ScriptException se) { 161.149 - } 161.150 - return; 161.151 - } 161.152 - } 161.153 - 161.154 - fail("Cannot find nashorn factory!"); 161.155 - } 161.156 }
162.1 --- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Thu Mar 28 10:55:17 2013 -0700 162.2 +++ b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Mon Apr 01 21:42:31 2013 -0700 162.3 @@ -44,6 +44,7 @@ 162.4 private static final boolean VERBOSE = Boolean.valueOf(System.getProperty("compilertest.verbose")); 162.5 private static final boolean TEST262 = Boolean.valueOf(System.getProperty("compilertest.test262")); 162.6 private static final String TEST_BASIC_DIR = System.getProperty("test.basic.dir"); 162.7 + private static final String TEST_NODE_DIR = System.getProperty("test.node.dir"); 162.8 private static final String TEST262_SUITE_DIR = System.getProperty("test262.suite.dir"); 162.9 162.10 interface TestFilter { 162.11 @@ -81,21 +82,22 @@ 162.12 @Test 162.13 public void compileAllTests() { 162.14 if (TEST262) { 162.15 - compileTestSet(TEST262_SUITE_DIR, new TestFilter() { 162.16 + compileTestSet(new File(TEST262_SUITE_DIR), new TestFilter() { 162.17 @Override 162.18 public boolean exclude(final File file, final String content) { 162.19 return content.indexOf("@negative") != -1; 162.20 } 162.21 }); 162.22 } 162.23 - compileTestSet(TEST_BASIC_DIR, null); 162.24 + compileTestSet(new File(TEST_BASIC_DIR), null); 162.25 + compileTestSet(new File(TEST_NODE_DIR, "node"), null); 162.26 + compileTestSet(new File(TEST_NODE_DIR, "src"), null); 162.27 } 162.28 162.29 - private void compileTestSet(final String testSet, final TestFilter filter) { 162.30 + private void compileTestSet(final File testSetDir, final TestFilter filter) { 162.31 passed = 0; 162.32 failed = 0; 162.33 skipped = 0; 162.34 - final File testSetDir = new File(testSet); 162.35 if (! testSetDir.isDirectory()) { 162.36 log("WARNING: " + testSetDir + " not found or not a directory"); 162.37 return; 162.38 @@ -103,7 +105,7 @@ 162.39 log(testSetDir.getAbsolutePath()); 162.40 compileJSDirectory(testSetDir, filter); 162.41 162.42 - log(testSet + " compile done!"); 162.43 + log(testSetDir + " compile done!"); 162.44 log("compile ok: " + passed); 162.45 log("compile failed: " + failed); 162.46 log("compile skipped: " + skipped);
163.1 --- a/test/src/jdk/nashorn/internal/runtime/Nashorn401TestSubject.java Thu Mar 28 10:55:17 2013 -0700 163.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 163.3 @@ -1,57 +0,0 @@ 163.4 -/* 163.5 - * Copyright (c) 2010, 2013, 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. Oracle designates this 163.11 - * particular file as subject to the "Classpath" exception as provided 163.12 - * by Oracle in the LICENSE file that accompanied this code. 163.13 - * 163.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 163.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 163.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 163.17 - * version 2 for more details (a copy is included in the LICENSE file that 163.18 - * accompanied this code). 163.19 - * 163.20 - * You should have received a copy of the GNU General Public License version 163.21 - * 2 along with this work; if not, write to the Free Software Foundation, 163.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 163.23 - * 163.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 163.25 - * or visit www.oracle.com if you need additional information or have any 163.26 - * questions. 163.27 - */ 163.28 - 163.29 -package jdk.nashorn.internal.runtime; 163.30 - 163.31 -public class Nashorn401TestSubject { 163.32 - public String method2(int arg) { 163.33 - return "int method 2"; 163.34 - } 163.35 - 163.36 - public String method2(double arg) { 163.37 - return "double method 2"; 163.38 - } 163.39 - 163.40 - public String method2(String arg) { 163.41 - return "string method 2"; 163.42 - } 163.43 - 163.44 - public String method3(double arg) { 163.45 - return "double method 3: " + arg; 163.46 - } 163.47 - 163.48 - public String method3(int arg) { 163.49 - return "int method 3: " + arg; 163.50 - } 163.51 - 163.52 - public String method4(Double arg) { 163.53 - return "double method 4: " + arg; 163.54 - } 163.55 - 163.56 - public String method4(int arg) { 163.57 - return "int method 4: " + arg; 163.58 - } 163.59 - 163.60 -}
164.1 --- a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java Thu Mar 28 10:55:17 2013 -0700 164.2 +++ b/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java Mon Apr 01 21:42:31 2013 -0700 164.3 @@ -25,7 +25,7 @@ 164.4 164.5 package jdk.nashorn.internal.runtime; 164.6 164.7 - 164.8 +import static org.testng.Assert.assertEquals; 164.9 import static org.testng.Assert.assertTrue; 164.10 import static org.testng.Assert.fail; 164.11 164.12 @@ -40,6 +40,13 @@ 164.13 * Tests for trusted client usage of nashorn script engine factory extension API 164.14 */ 164.15 public class TrustedScriptEngineTest { 164.16 + @Test 164.17 + public void versionTest() { 164.18 + final ScriptEngineManager m = new ScriptEngineManager(); 164.19 + final ScriptEngine e = m.getEngineByName("nashorn"); 164.20 + assertEquals(e.getFactory().getEngineVersion(), Version.version()); 164.21 + } 164.22 + 164.23 private static class MyClassLoader extends ClassLoader { 164.24 // to check if script engine uses the specified class loader 164.25 private final boolean[] reached = new boolean[1]; 164.26 @@ -116,4 +123,26 @@ 164.27 164.28 fail("Cannot find nashorn factory!"); 164.29 } 164.30 + 164.31 + @Test 164.32 + public void factoryOptionsTest() { 164.33 + final ScriptEngineManager sm = new ScriptEngineManager(); 164.34 + for (ScriptEngineFactory fac : sm.getEngineFactories()) { 164.35 + if (fac instanceof NashornScriptEngineFactory) { 164.36 + final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac; 164.37 + // specify --no-syntax-extensions flag 164.38 + final String[] options = new String[] { "--no-syntax-extensions" }; 164.39 + final ScriptEngine e = nfac.getScriptEngine(options); 164.40 + try { 164.41 + // try nashorn specific extension 164.42 + e.eval("var f = funtion(x) 2*x;"); 164.43 + fail("should have thrown exception!"); 164.44 + } catch (final ScriptException se) { 164.45 + } 164.46 + return; 164.47 + } 164.48 + } 164.49 + 164.50 + fail("Cannot find nashorn factory!"); 164.51 + } 164.52 }
165.1 --- a/test/src/jdk/nashorn/internal/test/models/ConstructorWithArgument.java Thu Mar 28 10:55:17 2013 -0700 165.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 165.3 @@ -1,40 +0,0 @@ 165.4 -/* 165.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 165.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 165.7 - * 165.8 - * This code is free software; you can redistribute it and/or modify it 165.9 - * under the terms of the GNU General Public License version 2 only, as 165.10 - * published by the Free Software Foundation. Oracle designates this 165.11 - * particular file as subject to the "Classpath" exception as provided 165.12 - * by Oracle in the LICENSE file that accompanied this code. 165.13 - * 165.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 165.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 165.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 165.17 - * version 2 for more details (a copy is included in the LICENSE file that 165.18 - * accompanied this code). 165.19 - * 165.20 - * You should have received a copy of the GNU General Public License version 165.21 - * 2 along with this work; if not, write to the Free Software Foundation, 165.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 165.23 - * 165.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 165.25 - * or visit www.oracle.com if you need additional information or have any 165.26 - * questions. 165.27 - */ 165.28 - 165.29 -package jdk.nashorn.internal.test.models; 165.30 - 165.31 -public abstract class ConstructorWithArgument { 165.32 - private final String token; 165.33 - 165.34 - protected ConstructorWithArgument(String token) { 165.35 - this.token = token; 165.36 - } 165.37 - 165.38 - public String getToken() { 165.39 - return token; 165.40 - } 165.41 - 165.42 - protected abstract void doSomething(); 165.43 -}
166.1 --- a/test/src/jdk/nashorn/internal/test/models/DessertTopping.java Thu Mar 28 10:55:17 2013 -0700 166.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 166.3 @@ -1,30 +0,0 @@ 166.4 -/* 166.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 166.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 166.7 - * 166.8 - * This code is free software; you can redistribute it and/or modify it 166.9 - * under the terms of the GNU General Public License version 2 only, as 166.10 - * published by the Free Software Foundation. Oracle designates this 166.11 - * particular file as subject to the "Classpath" exception as provided 166.12 - * by Oracle in the LICENSE file that accompanied this code. 166.13 - * 166.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 166.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 166.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 166.17 - * version 2 for more details (a copy is included in the LICENSE file that 166.18 - * accompanied this code). 166.19 - * 166.20 - * You should have received a copy of the GNU General Public License version 166.21 - * 2 along with this work; if not, write to the Free Software Foundation, 166.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 166.23 - * 166.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 166.25 - * or visit www.oracle.com if you need additional information or have any 166.26 - * questions. 166.27 - */ 166.28 - 166.29 -package jdk.nashorn.internal.test.models; 166.30 - 166.31 -public interface DessertTopping { 166.32 - public String pourOnDessert(); 166.33 -}
167.1 --- a/test/src/jdk/nashorn/internal/test/models/DessertToppingFloorWaxDriver.java Thu Mar 28 10:55:17 2013 -0700 167.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 167.3 @@ -1,36 +0,0 @@ 167.4 -/* 167.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 167.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 167.7 - * 167.8 - * This code is free software; you can redistribute it and/or modify it 167.9 - * under the terms of the GNU General Public License version 2 only, as 167.10 - * published by the Free Software Foundation. Oracle designates this 167.11 - * particular file as subject to the "Classpath" exception as provided 167.12 - * by Oracle in the LICENSE file that accompanied this code. 167.13 - * 167.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 167.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 167.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 167.17 - * version 2 for more details (a copy is included in the LICENSE file that 167.18 - * accompanied this code). 167.19 - * 167.20 - * You should have received a copy of the GNU General Public License version 167.21 - * 2 along with this work; if not, write to the Free Software Foundation, 167.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 167.23 - * 167.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 167.25 - * or visit www.oracle.com if you need additional information or have any 167.26 - * questions. 167.27 - */ 167.28 - 167.29 -package jdk.nashorn.internal.test.models; 167.30 - 167.31 -public class DessertToppingFloorWaxDriver { 167.32 - public void decorateDessert(DessertTopping dt) { 167.33 - dt.pourOnDessert(); 167.34 - } 167.35 - 167.36 - public void waxFloor(FloorWax fw) { 167.37 - fw.shineUpTheFloor(); 167.38 - } 167.39 -}
168.1 --- a/test/src/jdk/nashorn/internal/test/models/FinalClass.java Thu Mar 28 10:55:17 2013 -0700 168.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 168.3 @@ -1,30 +0,0 @@ 168.4 -/* 168.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 168.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 168.7 - * 168.8 - * This code is free software; you can redistribute it and/or modify it 168.9 - * under the terms of the GNU General Public License version 2 only, as 168.10 - * published by the Free Software Foundation. Oracle designates this 168.11 - * particular file as subject to the "Classpath" exception as provided 168.12 - * by Oracle in the LICENSE file that accompanied this code. 168.13 - * 168.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 168.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 168.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 168.17 - * version 2 for more details (a copy is included in the LICENSE file that 168.18 - * accompanied this code). 168.19 - * 168.20 - * You should have received a copy of the GNU General Public License version 168.21 - * 2 along with this work; if not, write to the Free Software Foundation, 168.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 168.23 - * 168.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 168.25 - * or visit www.oracle.com if you need additional information or have any 168.26 - * questions. 168.27 - */ 168.28 - 168.29 -package jdk.nashorn.internal.test.models; 168.30 - 168.31 -public final class FinalClass { 168.32 - //empty 168.33 -}
169.1 --- a/test/src/jdk/nashorn/internal/test/models/FloorWax.java Thu Mar 28 10:55:17 2013 -0700 169.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 169.3 @@ -1,30 +0,0 @@ 169.4 -/* 169.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 169.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 169.7 - * 169.8 - * This code is free software; you can redistribute it and/or modify it 169.9 - * under the terms of the GNU General Public License version 2 only, as 169.10 - * published by the Free Software Foundation. Oracle designates this 169.11 - * particular file as subject to the "Classpath" exception as provided 169.12 - * by Oracle in the LICENSE file that accompanied this code. 169.13 - * 169.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 169.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 169.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 169.17 - * version 2 for more details (a copy is included in the LICENSE file that 169.18 - * accompanied this code). 169.19 - * 169.20 - * You should have received a copy of the GNU General Public License version 169.21 - * 2 along with this work; if not, write to the Free Software Foundation, 169.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 169.23 - * 169.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 169.25 - * or visit www.oracle.com if you need additional information or have any 169.26 - * questions. 169.27 - */ 169.28 - 169.29 -package jdk.nashorn.internal.test.models; 169.30 - 169.31 -public interface FloorWax { 169.32 - public String shineUpTheFloor(); 169.33 -}
170.1 --- a/test/src/jdk/nashorn/internal/test/models/NoAccessibleConstructorClass.java Thu Mar 28 10:55:17 2013 -0700 170.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 170.3 @@ -1,30 +0,0 @@ 170.4 -/* 170.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 170.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 170.7 - * 170.8 - * This code is free software; you can redistribute it and/or modify it 170.9 - * under the terms of the GNU General Public License version 2 only, as 170.10 - * published by the Free Software Foundation. Oracle designates this 170.11 - * particular file as subject to the "Classpath" exception as provided 170.12 - * by Oracle in the LICENSE file that accompanied this code. 170.13 - * 170.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 170.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 170.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 170.17 - * version 2 for more details (a copy is included in the LICENSE file that 170.18 - * accompanied this code). 170.19 - * 170.20 - * You should have received a copy of the GNU General Public License version 170.21 - * 2 along with this work; if not, write to the Free Software Foundation, 170.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 170.23 - * 170.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 170.25 - * or visit www.oracle.com if you need additional information or have any 170.26 - * questions. 170.27 - */ 170.28 - 170.29 -package jdk.nashorn.internal.test.models; 170.30 - 170.31 -public class NoAccessibleConstructorClass { 170.32 - NoAccessibleConstructorClass() { } 170.33 -}
171.1 --- a/test/src/jdk/nashorn/internal/test/models/NonPublicClass.java Thu Mar 28 10:55:17 2013 -0700 171.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 171.3 @@ -1,30 +0,0 @@ 171.4 -/* 171.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 171.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 171.7 - * 171.8 - * This code is free software; you can redistribute it and/or modify it 171.9 - * under the terms of the GNU General Public License version 2 only, as 171.10 - * published by the Free Software Foundation. Oracle designates this 171.11 - * particular file as subject to the "Classpath" exception as provided 171.12 - * by Oracle in the LICENSE file that accompanied this code. 171.13 - * 171.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 171.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 171.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 171.17 - * version 2 for more details (a copy is included in the LICENSE file that 171.18 - * accompanied this code). 171.19 - * 171.20 - * You should have received a copy of the GNU General Public License version 171.21 - * 2 along with this work; if not, write to the Free Software Foundation, 171.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 171.23 - * 171.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 171.25 - * or visit www.oracle.com if you need additional information or have any 171.26 - * questions. 171.27 - */ 171.28 - 171.29 -package jdk.nashorn.internal.test.models; 171.30 - 171.31 -class NonPublicClass { 171.32 - public NonPublicClass() { } 171.33 -}
172.1 --- a/test/src/jdk/nashorn/internal/test/models/OuterClass.java Thu Mar 28 10:55:17 2013 -0700 172.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 172.3 @@ -1,65 +0,0 @@ 172.4 -/* 172.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 172.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 172.7 - * 172.8 - * This code is free software; you can redistribute it and/or modify it 172.9 - * under the terms of the GNU General Public License version 2 only, as 172.10 - * published by the Free Software Foundation. Oracle designates this 172.11 - * particular file as subject to the "Classpath" exception as provided 172.12 - * by Oracle in the LICENSE file that accompanied this code. 172.13 - * 172.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 172.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 172.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 172.17 - * version 2 for more details (a copy is included in the LICENSE file that 172.18 - * accompanied this code). 172.19 - * 172.20 - * You should have received a copy of the GNU General Public License version 172.21 - * 2 along with this work; if not, write to the Free Software Foundation, 172.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 172.23 - * 172.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 172.25 - * or visit www.oracle.com if you need additional information or have any 172.26 - * questions. 172.27 - */ 172.28 - 172.29 -package jdk.nashorn.internal.test.models; 172.30 - 172.31 -public class OuterClass { 172.32 - private final String value; 172.33 - 172.34 - public OuterClass(String value) { 172.35 - this.value = value; 172.36 - } 172.37 - 172.38 - public static class InnerStaticClass { 172.39 - private final String value; 172.40 - 172.41 - public InnerStaticClass(String value) { 172.42 - this.value = value; 172.43 - } 172.44 - 172.45 - @Override 172.46 - public String toString() { 172.47 - return "InnerStaticClass[value=" + value + "]"; 172.48 - } 172.49 - } 172.50 - 172.51 - public class InnerNonStaticClass { 172.52 - private final String value; 172.53 - 172.54 - public InnerNonStaticClass(String value) { 172.55 - this.value = value; 172.56 - } 172.57 - 172.58 - @Override 172.59 - public String toString() { 172.60 - return "InnerNonStaticClass[value=" + value + ", outer=" + OuterClass.this + "]"; 172.61 - } 172.62 - } 172.63 - 172.64 - @Override 172.65 - public String toString() { 172.66 - return "OuterClass[value=" + value + "]"; 172.67 - } 172.68 -}
173.1 --- a/test/src/jdk/nashorn/internal/test/models/OverloadedSam.java Thu Mar 28 10:55:17 2013 -0700 173.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 173.3 @@ -1,31 +0,0 @@ 173.4 -/* 173.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 173.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 173.7 - * 173.8 - * This code is free software; you can redistribute it and/or modify it 173.9 - * under the terms of the GNU General Public License version 2 only, as 173.10 - * published by the Free Software Foundation. Oracle designates this 173.11 - * particular file as subject to the "Classpath" exception as provided 173.12 - * by Oracle in the LICENSE file that accompanied this code. 173.13 - * 173.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 173.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 173.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 173.17 - * version 2 for more details (a copy is included in the LICENSE file that 173.18 - * accompanied this code). 173.19 - * 173.20 - * You should have received a copy of the GNU General Public License version 173.21 - * 2 along with this work; if not, write to the Free Software Foundation, 173.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 173.23 - * 173.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 173.25 - * or visit www.oracle.com if you need additional information or have any 173.26 - * questions. 173.27 - */ 173.28 - 173.29 -package jdk.nashorn.internal.test.models; 173.30 - 173.31 -public interface OverloadedSam { 173.32 - public void sam(String s); 173.33 - public void sam(String s1, String s2); 173.34 -}
174.1 --- a/test/src/jdk/nashorn/internal/test/models/OverrideObject.java Thu Mar 28 10:55:17 2013 -0700 174.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 174.3 @@ -1,44 +0,0 @@ 174.4 -/* 174.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 174.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 174.7 - * 174.8 - * This code is free software; you can redistribute it and/or modify it 174.9 - * under the terms of the GNU General Public License version 2 only, as 174.10 - * published by the Free Software Foundation. Oracle designates this 174.11 - * particular file as subject to the "Classpath" exception as provided 174.12 - * by Oracle in the LICENSE file that accompanied this code. 174.13 - * 174.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 174.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 174.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 174.17 - * version 2 for more details (a copy is included in the LICENSE file that 174.18 - * accompanied this code). 174.19 - * 174.20 - * You should have received a copy of the GNU General Public License version 174.21 - * 2 along with this work; if not, write to the Free Software Foundation, 174.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 174.23 - * 174.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 174.25 - * or visit www.oracle.com if you need additional information or have any 174.26 - * questions. 174.27 - */ 174.28 - 174.29 -package jdk.nashorn.internal.test.models; 174.30 - 174.31 -public class OverrideObject { 174.32 - @Override 174.33 - public int hashCode() { 174.34 - return 5; 174.35 - } 174.36 - 174.37 - @Override 174.38 - public String toString() { 174.39 - return "override-object"; 174.40 - } 174.41 - 174.42 - @Override 174.43 - public boolean equals(Object o) { 174.44 - // TODO: add a FindBugs annotation to ignore EQ_ALWAYS_FALSE here. This is just a test. 174.45 - return false; 174.46 - } 174.47 -}
175.1 --- a/test/src/jdk/nashorn/internal/test/models/StringArgs.java Thu Mar 28 10:55:17 2013 -0700 175.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 175.3 @@ -1,39 +0,0 @@ 175.4 -/* 175.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 175.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 175.7 - * 175.8 - * This code is free software; you can redistribute it and/or modify it 175.9 - * under the terms of the GNU General Public License version 2 only, as 175.10 - * published by the Free Software Foundation. Oracle designates this 175.11 - * particular file as subject to the "Classpath" exception as provided 175.12 - * by Oracle in the LICENSE file that accompanied this code. 175.13 - * 175.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 175.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 175.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 175.17 - * version 2 for more details (a copy is included in the LICENSE file that 175.18 - * accompanied this code). 175.19 - * 175.20 - * You should have received a copy of the GNU General Public License version 175.21 - * 2 along with this work; if not, write to the Free Software Foundation, 175.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 175.23 - * 175.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 175.25 - * or visit www.oracle.com if you need additional information or have any 175.26 - * questions. 175.27 - */ 175.28 - 175.29 -package jdk.nashorn.internal.test.models; 175.30 - 175.31 -import java.util.List; 175.32 - 175.33 -public class StringArgs { 175.34 - 175.35 - public static void checkString(List<?> list) { 175.36 - for (Object s : list) { 175.37 - if (!(s instanceof String)) { 175.38 - throw new AssertionError("Not a String: " + s); 175.39 - } 175.40 - } 175.41 - } 175.42 -}
176.1 --- a/test/src/jdk/nashorn/internal/test/models/Toothpaste.java Thu Mar 28 10:55:17 2013 -0700 176.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 176.3 @@ -1,34 +0,0 @@ 176.4 -/* 176.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 176.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 176.7 - * 176.8 - * This code is free software; you can redistribute it and/or modify it 176.9 - * under the terms of the GNU General Public License version 2 only, as 176.10 - * published by the Free Software Foundation. Oracle designates this 176.11 - * particular file as subject to the "Classpath" exception as provided 176.12 - * by Oracle in the LICENSE file that accompanied this code. 176.13 - * 176.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 176.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 176.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 176.17 - * version 2 for more details (a copy is included in the LICENSE file that 176.18 - * accompanied this code). 176.19 - * 176.20 - * You should have received a copy of the GNU General Public License version 176.21 - * 2 along with this work; if not, write to the Free Software Foundation, 176.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 176.23 - * 176.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 176.25 - * or visit www.oracle.com if you need additional information or have any 176.26 - * questions. 176.27 - */ 176.28 - 176.29 -package jdk.nashorn.internal.test.models; 176.30 - 176.31 -public abstract class Toothpaste { 176.32 - public void applyToBrush() { 176.33 - applyToBrushImpl(); 176.34 - } 176.35 - 176.36 - protected abstract void applyToBrushImpl(); 176.37 -}
177.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 177.2 +++ b/test/src/jdk/nashorn/test/models/ConstructorWithArgument.java Mon Apr 01 21:42:31 2013 -0700 177.3 @@ -0,0 +1,40 @@ 177.4 +/* 177.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 177.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 177.7 + * 177.8 + * This code is free software; you can redistribute it and/or modify it 177.9 + * under the terms of the GNU General Public License version 2 only, as 177.10 + * published by the Free Software Foundation. Oracle designates this 177.11 + * particular file as subject to the "Classpath" exception as provided 177.12 + * by Oracle in the LICENSE file that accompanied this code. 177.13 + * 177.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 177.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 177.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 177.17 + * version 2 for more details (a copy is included in the LICENSE file that 177.18 + * accompanied this code). 177.19 + * 177.20 + * You should have received a copy of the GNU General Public License version 177.21 + * 2 along with this work; if not, write to the Free Software Foundation, 177.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 177.23 + * 177.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 177.25 + * or visit www.oracle.com if you need additional information or have any 177.26 + * questions. 177.27 + */ 177.28 + 177.29 +package jdk.nashorn.test.models; 177.30 + 177.31 +public abstract class ConstructorWithArgument { 177.32 + private final String token; 177.33 + 177.34 + protected ConstructorWithArgument(String token) { 177.35 + this.token = token; 177.36 + } 177.37 + 177.38 + public String getToken() { 177.39 + return token; 177.40 + } 177.41 + 177.42 + protected abstract void doSomething(); 177.43 +}
178.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 178.2 +++ b/test/src/jdk/nashorn/test/models/DessertTopping.java Mon Apr 01 21:42:31 2013 -0700 178.3 @@ -0,0 +1,30 @@ 178.4 +/* 178.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 178.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 178.7 + * 178.8 + * This code is free software; you can redistribute it and/or modify it 178.9 + * under the terms of the GNU General Public License version 2 only, as 178.10 + * published by the Free Software Foundation. Oracle designates this 178.11 + * particular file as subject to the "Classpath" exception as provided 178.12 + * by Oracle in the LICENSE file that accompanied this code. 178.13 + * 178.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 178.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 178.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 178.17 + * version 2 for more details (a copy is included in the LICENSE file that 178.18 + * accompanied this code). 178.19 + * 178.20 + * You should have received a copy of the GNU General Public License version 178.21 + * 2 along with this work; if not, write to the Free Software Foundation, 178.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 178.23 + * 178.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 178.25 + * or visit www.oracle.com if you need additional information or have any 178.26 + * questions. 178.27 + */ 178.28 + 178.29 +package jdk.nashorn.test.models; 178.30 + 178.31 +public interface DessertTopping { 178.32 + public String pourOnDessert(); 178.33 +}
179.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 179.2 +++ b/test/src/jdk/nashorn/test/models/DessertToppingFloorWaxDriver.java Mon Apr 01 21:42:31 2013 -0700 179.3 @@ -0,0 +1,36 @@ 179.4 +/* 179.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 179.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 179.7 + * 179.8 + * This code is free software; you can redistribute it and/or modify it 179.9 + * under the terms of the GNU General Public License version 2 only, as 179.10 + * published by the Free Software Foundation. Oracle designates this 179.11 + * particular file as subject to the "Classpath" exception as provided 179.12 + * by Oracle in the LICENSE file that accompanied this code. 179.13 + * 179.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 179.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 179.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 179.17 + * version 2 for more details (a copy is included in the LICENSE file that 179.18 + * accompanied this code). 179.19 + * 179.20 + * You should have received a copy of the GNU General Public License version 179.21 + * 2 along with this work; if not, write to the Free Software Foundation, 179.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 179.23 + * 179.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 179.25 + * or visit www.oracle.com if you need additional information or have any 179.26 + * questions. 179.27 + */ 179.28 + 179.29 +package jdk.nashorn.test.models; 179.30 + 179.31 +public class DessertToppingFloorWaxDriver { 179.32 + public void decorateDessert(DessertTopping dt) { 179.33 + dt.pourOnDessert(); 179.34 + } 179.35 + 179.36 + public void waxFloor(FloorWax fw) { 179.37 + fw.shineUpTheFloor(); 179.38 + } 179.39 +}
180.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 180.2 +++ b/test/src/jdk/nashorn/test/models/FinalClass.java Mon Apr 01 21:42:31 2013 -0700 180.3 @@ -0,0 +1,30 @@ 180.4 +/* 180.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 180.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 180.7 + * 180.8 + * This code is free software; you can redistribute it and/or modify it 180.9 + * under the terms of the GNU General Public License version 2 only, as 180.10 + * published by the Free Software Foundation. Oracle designates this 180.11 + * particular file as subject to the "Classpath" exception as provided 180.12 + * by Oracle in the LICENSE file that accompanied this code. 180.13 + * 180.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 180.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 180.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 180.17 + * version 2 for more details (a copy is included in the LICENSE file that 180.18 + * accompanied this code). 180.19 + * 180.20 + * You should have received a copy of the GNU General Public License version 180.21 + * 2 along with this work; if not, write to the Free Software Foundation, 180.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 180.23 + * 180.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 180.25 + * or visit www.oracle.com if you need additional information or have any 180.26 + * questions. 180.27 + */ 180.28 + 180.29 +package jdk.nashorn.test.models; 180.30 + 180.31 +public final class FinalClass { 180.32 + //empty 180.33 +}
181.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 181.2 +++ b/test/src/jdk/nashorn/test/models/FloorWax.java Mon Apr 01 21:42:31 2013 -0700 181.3 @@ -0,0 +1,30 @@ 181.4 +/* 181.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 181.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 181.7 + * 181.8 + * This code is free software; you can redistribute it and/or modify it 181.9 + * under the terms of the GNU General Public License version 2 only, as 181.10 + * published by the Free Software Foundation. Oracle designates this 181.11 + * particular file as subject to the "Classpath" exception as provided 181.12 + * by Oracle in the LICENSE file that accompanied this code. 181.13 + * 181.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 181.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 181.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 181.17 + * version 2 for more details (a copy is included in the LICENSE file that 181.18 + * accompanied this code). 181.19 + * 181.20 + * You should have received a copy of the GNU General Public License version 181.21 + * 2 along with this work; if not, write to the Free Software Foundation, 181.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 181.23 + * 181.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 181.25 + * or visit www.oracle.com if you need additional information or have any 181.26 + * questions. 181.27 + */ 181.28 + 181.29 +package jdk.nashorn.test.models; 181.30 + 181.31 +public interface FloorWax { 181.32 + public String shineUpTheFloor(); 181.33 +}
182.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 182.2 +++ b/test/src/jdk/nashorn/test/models/Nashorn401TestSubject.java Mon Apr 01 21:42:31 2013 -0700 182.3 @@ -0,0 +1,57 @@ 182.4 +/* 182.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 182.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 182.7 + * 182.8 + * This code is free software; you can redistribute it and/or modify it 182.9 + * under the terms of the GNU General Public License version 2 only, as 182.10 + * published by the Free Software Foundation. Oracle designates this 182.11 + * particular file as subject to the "Classpath" exception as provided 182.12 + * by Oracle in the LICENSE file that accompanied this code. 182.13 + * 182.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 182.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 182.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 182.17 + * version 2 for more details (a copy is included in the LICENSE file that 182.18 + * accompanied this code). 182.19 + * 182.20 + * You should have received a copy of the GNU General Public License version 182.21 + * 2 along with this work; if not, write to the Free Software Foundation, 182.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 182.23 + * 182.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 182.25 + * or visit www.oracle.com if you need additional information or have any 182.26 + * questions. 182.27 + */ 182.28 + 182.29 +package jdk.nashorn.test.models; 182.30 + 182.31 +public class Nashorn401TestSubject { 182.32 + public String method2(int arg) { 182.33 + return "int method 2"; 182.34 + } 182.35 + 182.36 + public String method2(double arg) { 182.37 + return "double method 2"; 182.38 + } 182.39 + 182.40 + public String method2(String arg) { 182.41 + return "string method 2"; 182.42 + } 182.43 + 182.44 + public String method3(double arg) { 182.45 + return "double method 3: " + arg; 182.46 + } 182.47 + 182.48 + public String method3(int arg) { 182.49 + return "int method 3: " + arg; 182.50 + } 182.51 + 182.52 + public String method4(Double arg) { 182.53 + return "double method 4: " + arg; 182.54 + } 182.55 + 182.56 + public String method4(int arg) { 182.57 + return "int method 4: " + arg; 182.58 + } 182.59 + 182.60 +}
183.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 183.2 +++ b/test/src/jdk/nashorn/test/models/NoAccessibleConstructorClass.java Mon Apr 01 21:42:31 2013 -0700 183.3 @@ -0,0 +1,30 @@ 183.4 +/* 183.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 183.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 183.7 + * 183.8 + * This code is free software; you can redistribute it and/or modify it 183.9 + * under the terms of the GNU General Public License version 2 only, as 183.10 + * published by the Free Software Foundation. Oracle designates this 183.11 + * particular file as subject to the "Classpath" exception as provided 183.12 + * by Oracle in the LICENSE file that accompanied this code. 183.13 + * 183.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 183.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 183.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 183.17 + * version 2 for more details (a copy is included in the LICENSE file that 183.18 + * accompanied this code). 183.19 + * 183.20 + * You should have received a copy of the GNU General Public License version 183.21 + * 2 along with this work; if not, write to the Free Software Foundation, 183.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 183.23 + * 183.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 183.25 + * or visit www.oracle.com if you need additional information or have any 183.26 + * questions. 183.27 + */ 183.28 + 183.29 +package jdk.nashorn.test.models; 183.30 + 183.31 +public class NoAccessibleConstructorClass { 183.32 + NoAccessibleConstructorClass() { } 183.33 +}
184.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 184.2 +++ b/test/src/jdk/nashorn/test/models/NonPublicClass.java Mon Apr 01 21:42:31 2013 -0700 184.3 @@ -0,0 +1,30 @@ 184.4 +/* 184.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 184.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 184.7 + * 184.8 + * This code is free software; you can redistribute it and/or modify it 184.9 + * under the terms of the GNU General Public License version 2 only, as 184.10 + * published by the Free Software Foundation. Oracle designates this 184.11 + * particular file as subject to the "Classpath" exception as provided 184.12 + * by Oracle in the LICENSE file that accompanied this code. 184.13 + * 184.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 184.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 184.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 184.17 + * version 2 for more details (a copy is included in the LICENSE file that 184.18 + * accompanied this code). 184.19 + * 184.20 + * You should have received a copy of the GNU General Public License version 184.21 + * 2 along with this work; if not, write to the Free Software Foundation, 184.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 184.23 + * 184.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 184.25 + * or visit www.oracle.com if you need additional information or have any 184.26 + * questions. 184.27 + */ 184.28 + 184.29 +package jdk.nashorn.test.models; 184.30 + 184.31 +class NonPublicClass { 184.32 + public NonPublicClass() { } 184.33 +}
185.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 185.2 +++ b/test/src/jdk/nashorn/test/models/OuterClass.java Mon Apr 01 21:42:31 2013 -0700 185.3 @@ -0,0 +1,65 @@ 185.4 +/* 185.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 185.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 185.7 + * 185.8 + * This code is free software; you can redistribute it and/or modify it 185.9 + * under the terms of the GNU General Public License version 2 only, as 185.10 + * published by the Free Software Foundation. Oracle designates this 185.11 + * particular file as subject to the "Classpath" exception as provided 185.12 + * by Oracle in the LICENSE file that accompanied this code. 185.13 + * 185.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 185.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 185.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 185.17 + * version 2 for more details (a copy is included in the LICENSE file that 185.18 + * accompanied this code). 185.19 + * 185.20 + * You should have received a copy of the GNU General Public License version 185.21 + * 2 along with this work; if not, write to the Free Software Foundation, 185.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 185.23 + * 185.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 185.25 + * or visit www.oracle.com if you need additional information or have any 185.26 + * questions. 185.27 + */ 185.28 + 185.29 +package jdk.nashorn.test.models; 185.30 + 185.31 +public class OuterClass { 185.32 + private final String value; 185.33 + 185.34 + public OuterClass(String value) { 185.35 + this.value = value; 185.36 + } 185.37 + 185.38 + public static class InnerStaticClass { 185.39 + private final String value; 185.40 + 185.41 + public InnerStaticClass(String value) { 185.42 + this.value = value; 185.43 + } 185.44 + 185.45 + @Override 185.46 + public String toString() { 185.47 + return "InnerStaticClass[value=" + value + "]"; 185.48 + } 185.49 + } 185.50 + 185.51 + public class InnerNonStaticClass { 185.52 + private final String value; 185.53 + 185.54 + public InnerNonStaticClass(String value) { 185.55 + this.value = value; 185.56 + } 185.57 + 185.58 + @Override 185.59 + public String toString() { 185.60 + return "InnerNonStaticClass[value=" + value + ", outer=" + OuterClass.this + "]"; 185.61 + } 185.62 + } 185.63 + 185.64 + @Override 185.65 + public String toString() { 185.66 + return "OuterClass[value=" + value + "]"; 185.67 + } 185.68 +}
186.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 186.2 +++ b/test/src/jdk/nashorn/test/models/OverloadedSam.java Mon Apr 01 21:42:31 2013 -0700 186.3 @@ -0,0 +1,31 @@ 186.4 +/* 186.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 186.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 186.7 + * 186.8 + * This code is free software; you can redistribute it and/or modify it 186.9 + * under the terms of the GNU General Public License version 2 only, as 186.10 + * published by the Free Software Foundation. Oracle designates this 186.11 + * particular file as subject to the "Classpath" exception as provided 186.12 + * by Oracle in the LICENSE file that accompanied this code. 186.13 + * 186.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 186.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 186.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 186.17 + * version 2 for more details (a copy is included in the LICENSE file that 186.18 + * accompanied this code). 186.19 + * 186.20 + * You should have received a copy of the GNU General Public License version 186.21 + * 2 along with this work; if not, write to the Free Software Foundation, 186.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 186.23 + * 186.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 186.25 + * or visit www.oracle.com if you need additional information or have any 186.26 + * questions. 186.27 + */ 186.28 + 186.29 +package jdk.nashorn.test.models; 186.30 + 186.31 +public interface OverloadedSam { 186.32 + public void sam(String s); 186.33 + public void sam(String s1, String s2); 186.34 +}
187.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 187.2 +++ b/test/src/jdk/nashorn/test/models/OverrideObject.java Mon Apr 01 21:42:31 2013 -0700 187.3 @@ -0,0 +1,44 @@ 187.4 +/* 187.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 187.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 187.7 + * 187.8 + * This code is free software; you can redistribute it and/or modify it 187.9 + * under the terms of the GNU General Public License version 2 only, as 187.10 + * published by the Free Software Foundation. Oracle designates this 187.11 + * particular file as subject to the "Classpath" exception as provided 187.12 + * by Oracle in the LICENSE file that accompanied this code. 187.13 + * 187.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 187.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 187.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 187.17 + * version 2 for more details (a copy is included in the LICENSE file that 187.18 + * accompanied this code). 187.19 + * 187.20 + * You should have received a copy of the GNU General Public License version 187.21 + * 2 along with this work; if not, write to the Free Software Foundation, 187.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 187.23 + * 187.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 187.25 + * or visit www.oracle.com if you need additional information or have any 187.26 + * questions. 187.27 + */ 187.28 + 187.29 +package jdk.nashorn.test.models; 187.30 + 187.31 +public class OverrideObject { 187.32 + @Override 187.33 + public int hashCode() { 187.34 + return 5; 187.35 + } 187.36 + 187.37 + @Override 187.38 + public String toString() { 187.39 + return "override-object"; 187.40 + } 187.41 + 187.42 + @Override 187.43 + public boolean equals(Object o) { 187.44 + // TODO: add a FindBugs annotation to ignore EQ_ALWAYS_FALSE here. This is just a test. 187.45 + return false; 187.46 + } 187.47 +}
188.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 188.2 +++ b/test/src/jdk/nashorn/test/models/SourceHelper.java Mon Apr 01 21:42:31 2013 -0700 188.3 @@ -0,0 +1,55 @@ 188.4 +/* 188.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 188.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 188.7 + * 188.8 + * This code is free software; you can redistribute it and/or modify it 188.9 + * under the terms of the GNU General Public License version 2 only, as 188.10 + * published by the Free Software Foundation. Oracle designates this 188.11 + * particular file as subject to the "Classpath" exception as provided 188.12 + * by Oracle in the LICENSE file that accompanied this code. 188.13 + * 188.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 188.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 188.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 188.17 + * version 2 for more details (a copy is included in the LICENSE file that 188.18 + * accompanied this code). 188.19 + * 188.20 + * You should have received a copy of the GNU General Public License version 188.21 + * 2 along with this work; if not, write to the Free Software Foundation, 188.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 188.23 + * 188.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 188.25 + * or visit www.oracle.com if you need additional information or have any 188.26 + * questions. 188.27 + */ 188.28 + 188.29 +package jdk.nashorn.test.models; 188.30 + 188.31 +import java.io.File; 188.32 +import java.io.IOException; 188.33 +import java.io.Reader; 188.34 +import java.net.URL; 188.35 +import jdk.nashorn.internal.runtime.Source; 188.36 + 188.37 +/** 188.38 + * Helper class to facilitate script access of nashorn Source class. 188.39 + */ 188.40 +public final class SourceHelper { 188.41 + private SourceHelper() {} 188.42 + 188.43 + public static String baseURL(final URL url) { 188.44 + return Source.baseURL(url); 188.45 + } 188.46 + 188.47 + public static String readFully(final File file) throws IOException { 188.48 + return new String(Source.readFully(file)); 188.49 + } 188.50 + 188.51 + public static String readFully(final URL url) throws IOException { 188.52 + return new Source(url.toString(), url).getString(); 188.53 + } 188.54 + 188.55 + public static String readFully(final Reader reader) throws IOException { 188.56 + return new String(Source.readFully(reader)); 188.57 + } 188.58 +}
189.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 189.2 +++ b/test/src/jdk/nashorn/test/models/StringArgs.java Mon Apr 01 21:42:31 2013 -0700 189.3 @@ -0,0 +1,39 @@ 189.4 +/* 189.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 189.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 189.7 + * 189.8 + * This code is free software; you can redistribute it and/or modify it 189.9 + * under the terms of the GNU General Public License version 2 only, as 189.10 + * published by the Free Software Foundation. Oracle designates this 189.11 + * particular file as subject to the "Classpath" exception as provided 189.12 + * by Oracle in the LICENSE file that accompanied this code. 189.13 + * 189.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 189.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 189.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 189.17 + * version 2 for more details (a copy is included in the LICENSE file that 189.18 + * accompanied this code). 189.19 + * 189.20 + * You should have received a copy of the GNU General Public License version 189.21 + * 2 along with this work; if not, write to the Free Software Foundation, 189.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 189.23 + * 189.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 189.25 + * or visit www.oracle.com if you need additional information or have any 189.26 + * questions. 189.27 + */ 189.28 + 189.29 +package jdk.nashorn.test.models; 189.30 + 189.31 +import java.util.List; 189.32 + 189.33 +public class StringArgs { 189.34 + 189.35 + public static void checkString(List<?> list) { 189.36 + for (Object s : list) { 189.37 + if (!(s instanceof String)) { 189.38 + throw new AssertionError("Not a String: " + s); 189.39 + } 189.40 + } 189.41 + } 189.42 +}
190.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 190.2 +++ b/test/src/jdk/nashorn/test/models/Toothpaste.java Mon Apr 01 21:42:31 2013 -0700 190.3 @@ -0,0 +1,34 @@ 190.4 +/* 190.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 190.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 190.7 + * 190.8 + * This code is free software; you can redistribute it and/or modify it 190.9 + * under the terms of the GNU General Public License version 2 only, as 190.10 + * published by the Free Software Foundation. Oracle designates this 190.11 + * particular file as subject to the "Classpath" exception as provided 190.12 + * by Oracle in the LICENSE file that accompanied this code. 190.13 + * 190.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 190.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 190.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 190.17 + * version 2 for more details (a copy is included in the LICENSE file that 190.18 + * accompanied this code). 190.19 + * 190.20 + * You should have received a copy of the GNU General Public License version 190.21 + * 2 along with this work; if not, write to the Free Software Foundation, 190.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 190.23 + * 190.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 190.25 + * or visit www.oracle.com if you need additional information or have any 190.26 + * questions. 190.27 + */ 190.28 + 190.29 +package jdk.nashorn.test.models; 190.30 + 190.31 +public abstract class Toothpaste { 190.32 + public void applyToBrush() { 190.33 + applyToBrushImpl(); 190.34 + } 190.35 + 190.36 + protected abstract void applyToBrushImpl(); 190.37 +}