Merge jdk8-b84

Mon, 01 Apr 2013 21:42:31 -0700

author
lana
date
Mon, 01 Apr 2013 21:42:31 -0700
changeset 150
999cc1bf5520
parent 135
fbbdef940138
parent 149
db8a33cb22b8
child 151
e0378f0a50da
child 159
9b845033c888

Merge

src/jdk/nashorn/api/scripting/resources/init.js file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/ReferenceNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/annotations/ChildNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/annotations/ParentNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/ScriptFunctionTrampolineImpl.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/SpecializedMethodChooser.java file | annotate | diff | comparison | revisions
test/script/basic/runsunspider.js.EXPECTED file | annotate | diff | comparison | revisions
test/script/sandbox/reflection.js.EXPECTED file | annotate | diff | comparison | revisions
test/script/sandbox/unsafe.js.EXPECTED file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/runtime/Nashorn401TestSubject.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/test/models/ConstructorWithArgument.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/test/models/DessertTopping.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/test/models/DessertToppingFloorWaxDriver.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/test/models/FinalClass.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/test/models/FloorWax.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/test/models/NoAccessibleConstructorClass.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/test/models/NonPublicClass.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/test/models/OuterClass.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/test/models/OverloadedSam.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/test/models/OverrideObject.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/test/models/StringArgs.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/test/models/Toothpaste.java file | annotate | diff | comparison | revisions
     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 '&lt;'. 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 '&lt;' 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 &amp; 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 +}

mercurial