Thu, 24 Sep 2015 10:09:56 -0700
Merge
src/jdk/nashorn/internal/codegen/AstSerializer.java | file | annotate | diff | comparison | revisions | |
src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java | file | annotate | diff | comparison | revisions | |
src/jdk/nashorn/internal/objects/PrototypeObject.java | file | annotate | diff | comparison | revisions | |
src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java | file | annotate | diff | comparison | revisions |
1.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Thu Sep 24 10:00:42 2015 -0700 1.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Thu Sep 24 10:09:56 2015 -0700 1.3 @@ -54,10 +54,9 @@ 1.4 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP; 1.5 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP_DESC; 1.6 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE; 1.7 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION; 1.8 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC; 1.9 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC; 1.10 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_TYPE; 1.11 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN; 1.12 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN_DESC; 1.13 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC; 1.14 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY; 1.15 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC; 1.16 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_TYPE; 1.17 @@ -282,9 +281,9 @@ 1.18 assert specs != null; 1.19 if (!specs.isEmpty()) { 1.20 mi.memberInfoArray(className, specs); 1.21 - mi.invokeStatic(SCRIPTFUNCTIONIMPL_TYPE, SCRIPTFUNCTIONIMPL_MAKEFUNCTION, SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC); 1.22 + mi.invokeStatic(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_CREATEBUILTIN, SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC); 1.23 } else { 1.24 - mi.invokeStatic(SCRIPTFUNCTIONIMPL_TYPE, SCRIPTFUNCTIONIMPL_MAKEFUNCTION, SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC); 1.25 + mi.invokeStatic(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_CREATEBUILTIN, SCRIPTFUNCTION_CREATEBUILTIN_DESC); 1.26 } 1.27 1.28 if (arityFound) {
2.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java Thu Sep 24 10:00:42 2015 -0700 2.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java Thu Sep 24 10:09:56 2015 -0700 2.3 @@ -38,9 +38,8 @@ 2.4 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR; 2.5 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC; 2.6 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE; 2.7 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_INIT_DESC3; 2.8 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_INIT_DESC4; 2.9 -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_TYPE; 2.10 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_INIT_DESC3; 2.11 +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_INIT_DESC4; 2.12 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY; 2.13 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC; 2.14 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETPROTOTYPE; 2.15 @@ -55,7 +54,7 @@ 2.16 import jdk.internal.org.objectweb.asm.Handle; 2.17 2.18 /** 2.19 - * This class generates constructor class for a @ClassInfo annotated class. 2.20 + * This class generates constructor class for a @ScriptClass annotated class. 2.21 * 2.22 */ 2.23 public class ConstructorGenerator extends ClassGenerator { 2.24 @@ -75,8 +74,8 @@ 2.25 } 2.26 2.27 byte[] getClassBytes() { 2.28 - // new class extensing from ScriptObject 2.29 - final String superClass = (constructor != null)? SCRIPTFUNCTIONIMPL_TYPE : SCRIPTOBJECT_TYPE; 2.30 + // new class extending from ScriptObject 2.31 + final String superClass = (constructor != null)? SCRIPTFUNCTION_TYPE : SCRIPTOBJECT_TYPE; 2.32 cw.visit(V1_7, ACC_FINAL, className, null, superClass, null); 2.33 if (memberCount > 0) { 2.34 // add fields 2.35 @@ -182,8 +181,8 @@ 2.36 loadMap(mi); 2.37 } else { 2.38 // call Function.<init> 2.39 - superClass = SCRIPTFUNCTIONIMPL_TYPE; 2.40 - superDesc = (memberCount > 0) ? SCRIPTFUNCTIONIMPL_INIT_DESC4 : SCRIPTFUNCTIONIMPL_INIT_DESC3; 2.41 + superClass = SCRIPTFUNCTION_TYPE; 2.42 + superDesc = (memberCount > 0) ? SCRIPTFUNCTION_INIT_DESC4 : SCRIPTFUNCTION_INIT_DESC3; 2.43 mi.loadLiteral(constructor.getName()); 2.44 mi.visitLdcInsn(new Handle(H_INVOKESTATIC, scriptClassInfo.getJavaName(), constructor.getJavaName(), constructor.getJavaDesc())); 2.45 loadMap(mi);
3.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Thu Sep 24 10:00:42 2015 -0700 3.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Thu Sep 24 10:09:56 2015 -0700 3.3 @@ -161,7 +161,7 @@ 3.4 } 3.5 3.6 /** 3.7 - * Tag something as optimitic builtin or not 3.8 + * Tag something as optimistic builtin or not 3.9 * @param isOptimistic boolean, true if builtin constructor 3.10 */ 3.11 public void setIsOptimistic(final boolean isOptimistic) { 3.12 @@ -178,7 +178,7 @@ 3.13 } 3.14 3.15 /** 3.16 - * Set thre SpecializedFunction link logic class for specializations, i.e. optimistic 3.17 + * Set the SpecializedFunction link logic class for specializations, i.e. optimistic 3.18 * builtins 3.19 * @param linkLogicClass link logic class 3.20 */
4.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java Thu Sep 24 10:00:42 2015 -0700 4.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java Thu Sep 24 10:09:56 2015 -0700 4.3 @@ -42,7 +42,7 @@ 4.4 import java.io.IOException; 4.5 4.6 /** 4.7 - * This class generates prototype class for a @ClassInfo annotated class. 4.8 + * This class generates prototype class for a @ScriptClass annotated class. 4.9 * 4.10 */ 4.11 public class PrototypeGenerator extends ClassGenerator { 4.12 @@ -57,7 +57,7 @@ 4.13 } 4.14 4.15 byte[] getClassBytes() { 4.16 - // new class extensing from ScriptObject 4.17 + // new class extending from ScriptObject 4.18 cw.visit(V1_7, ACC_FINAL | ACC_SUPER, className, null, PROTOTYPEOBJECT_TYPE, null); 4.19 if (memberCount > 0) { 4.20 // add fields 4.21 @@ -155,7 +155,7 @@ 4.22 */ 4.23 public static void main(final String[] args) throws IOException { 4.24 if (args.length != 1) { 4.25 - System.err.println("Usage: " + ConstructorGenerator.class.getName() + " <class>"); 4.26 + System.err.println("Usage: " + PrototypeGenerator.class.getName() + " <class>"); 4.27 System.exit(1); 4.28 } 4.29
5.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java Thu Sep 24 10:00:42 2015 -0700 5.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java Thu Sep 24 10:09:56 2015 -0700 5.3 @@ -48,7 +48,7 @@ 5.4 * 5.5 */ 5.6 public final class ScriptClassInfo { 5.7 - // descriptots for various annotations 5.8 + // descriptors for various annotations 5.9 static final String SCRIPT_CLASS_ANNO_DESC = Type.getDescriptor(ScriptClass.class); 5.10 static final String CONSTRUCTOR_ANNO_DESC = Type.getDescriptor(Constructor.class); 5.11 static final String FUNCTION_ANNO_DESC = Type.getDescriptor(Function.class); 5.12 @@ -140,7 +140,7 @@ 5.13 } 5.14 5.15 boolean isPrototypeNeeded() { 5.16 - // Prototype class generation is needed if we have atleast one 5.17 + // Prototype class generation is needed if we have at least one 5.18 // prototype property or @Constructor defined in the class. 5.19 for (final MemberInfo memInfo : members) { 5.20 if (memInfo.getWhere() == Where.PROTOTYPE || memInfo.isConstructor()) {
6.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Thu Sep 24 10:00:42 2015 -0700 6.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Thu Sep 24 10:09:56 2015 -0700 6.3 @@ -118,7 +118,7 @@ 6.4 addScriptMember(memInfo); 6.5 6.6 return new AnnotationVisitor(Opcodes.ASM4, delegateAV) { 6.7 - // These could be "null" if values are not suppiled, 6.8 + // These could be "null" if values are not supplied, 6.9 // in which case we have to use the default values. 6.10 private String name; 6.11 private Integer attributes; 6.12 @@ -194,7 +194,7 @@ 6.13 6.14 final MemberInfo memInfo = new MemberInfo(); 6.15 6.16 - //annokind == e.g. GETTER or SPECIALIZED_FUNCTION 6.17 + // annoKind == GETTER or SPECIALIZED_FUNCTION 6.18 memInfo.setKind(annoKind); 6.19 memInfo.setJavaName(methodName); 6.20 memInfo.setJavaDesc(methodDesc); 6.21 @@ -203,7 +203,7 @@ 6.22 addScriptMember(memInfo); 6.23 6.24 return new AnnotationVisitor(Opcodes.ASM4, delegateAV) { 6.25 - // These could be "null" if values are not suppiled, 6.26 + // These could be "null" if values are not supplied, 6.27 // in which case we have to use the default values. 6.28 private String name; 6.29 private Integer attributes;
7.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java Thu Sep 24 10:00:42 2015 -0700 7.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java Thu Sep 24 10:09:56 2015 -0700 7.3 @@ -65,7 +65,6 @@ 7.4 * 2) add "Map" type static field named "$map". 7.5 * 3) add static initializer block to initialize map. 7.6 */ 7.7 - 7.8 public class ScriptClassInstrumentor extends ClassVisitor { 7.9 private final ScriptClassInfo scriptClassInfo; 7.10 private final int memberCount; 7.11 @@ -267,7 +266,7 @@ 7.12 */ 7.13 public static void main(final String[] args) throws IOException { 7.14 if (args.length != 1) { 7.15 - System.err.println("Usage: " + ScriptClassInfoCollector.class.getName() + " <class>"); 7.16 + System.err.println("Usage: " + ScriptClassInstrumentor.class.getName() + " <class>"); 7.17 System.exit(1); 7.18 } 7.19
8.1 --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Thu Sep 24 10:00:42 2015 -0700 8.2 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Thu Sep 24 10:09:56 2015 -0700 8.3 @@ -31,10 +31,9 @@ 8.4 import java.util.Collections; 8.5 import java.util.List; 8.6 import jdk.internal.org.objectweb.asm.Type; 8.7 -import jdk.nashorn.internal.objects.PrototypeObject; 8.8 -import jdk.nashorn.internal.objects.ScriptFunctionImpl; 8.9 import jdk.nashorn.internal.runtime.AccessorProperty; 8.10 import jdk.nashorn.internal.runtime.PropertyMap; 8.11 +import jdk.nashorn.internal.runtime.PrototypeObject; 8.12 import jdk.nashorn.internal.runtime.ScriptFunction; 8.13 import jdk.nashorn.internal.runtime.ScriptObject; 8.14 import jdk.nashorn.internal.runtime.Specialization; 8.15 @@ -88,7 +87,6 @@ 8.16 static final Type TYPE_PROPERTYMAP = Type.getType(PropertyMap.class); 8.17 static final Type TYPE_PROTOTYPEOBJECT = Type.getType(PrototypeObject.class); 8.18 static final Type TYPE_SCRIPTFUNCTION = Type.getType(ScriptFunction.class); 8.19 - static final Type TYPE_SCRIPTFUNCTIONIMPL = Type.getType(ScriptFunctionImpl.class); 8.20 static final Type TYPE_SCRIPTOBJECT = Type.getType(ScriptObject.class); 8.21 8.22 static final String PROTOTYPE_SUFFIX = "$Prototype"; 8.23 @@ -122,17 +120,14 @@ 8.24 static final String SCRIPTFUNCTION_SETARITY_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE); 8.25 static final String SCRIPTFUNCTION_SETPROTOTYPE = "setPrototype"; 8.26 static final String SCRIPTFUNCTION_SETPROTOTYPE_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT); 8.27 - 8.28 - // ScriptFunctionImpl 8.29 - static final String SCRIPTFUNCTIONIMPL_TYPE = TYPE_SCRIPTFUNCTIONIMPL.getInternalName(); 8.30 - static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION = "makeFunction"; 8.31 - static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC = 8.32 + static final String SCRIPTFUNCTION_CREATEBUILTIN = "createBuiltin"; 8.33 + static final String SCRIPTFUNCTION_CREATEBUILTIN_DESC = 8.34 Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE); 8.35 - static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC = 8.36 + static final String SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC = 8.37 Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY); 8.38 - static final String SCRIPTFUNCTIONIMPL_INIT_DESC3 = 8.39 + static final String SCRIPTFUNCTION_INIT_DESC3 = 8.40 Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY); 8.41 - static final String SCRIPTFUNCTIONIMPL_INIT_DESC4 = 8.42 + static final String SCRIPTFUNCTION_INIT_DESC4 = 8.43 Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_PROPERTYMAP, TYPE_SPECIALIZATION_ARRAY); 8.44 8.45 // ScriptObject
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/samples/exceptionswallow.js Thu Sep 24 10:09:56 2015 -0700 9.3 @@ -0,0 +1,136 @@ 9.4 +#// Usage: jjs exceptionswallow.js -- <directory> 9.5 + 9.6 +/* 9.7 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 9.8 + * 9.9 + * Redistribution and use in source and binary forms, with or without 9.10 + * modification, are permitted provided that the following conditions 9.11 + * are met: 9.12 + * 9.13 + * - Redistributions of source code must retain the above copyright 9.14 + * notice, this list of conditions and the following disclaimer. 9.15 + * 9.16 + * - Redistributions in binary form must reproduce the above copyright 9.17 + * notice, this list of conditions and the following disclaimer in the 9.18 + * documentation and/or other materials provided with the distribution. 9.19 + * 9.20 + * - Neither the name of Oracle nor the names of its 9.21 + * contributors may be used to endorse or promote products derived 9.22 + * from this software without specific prior written permission. 9.23 + * 9.24 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 9.25 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 9.26 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 9.27 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 9.28 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 9.29 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 9.30 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 9.31 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 9.32 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 9.33 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 9.34 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9.35 + */ 9.36 + 9.37 +// This example demonstrates Java subclassing by Java.extend 9.38 +// and javac Compiler and Tree API. This example looks for 9.39 +// empty catch blocks ("exception swallow") and reports those. 9.40 + 9.41 +if (arguments.length == 0) { 9.42 + print("Usage: jjs exceptionswallow.js -- <directory>"); 9.43 + exit(1); 9.44 +} 9.45 + 9.46 +// Java types used 9.47 +var File = Java.type("java.io.File"); 9.48 +var Files = Java.type("java.nio.file.Files"); 9.49 +var StringArray = Java.type("java.lang.String[]"); 9.50 +var ToolProvider = Java.type("javax.tools.ToolProvider"); 9.51 +var Tree = Java.type("com.sun.source.tree.Tree"); 9.52 +var EmptyStatementTree = Java.type("com.sun.source.tree.EmptyStatementTree"); 9.53 +var Trees = Java.type("com.sun.source.util.Trees"); 9.54 +var TreeScanner = Java.type("com.sun.source.util.TreeScanner"); 9.55 + 9.56 +// printEmptyCatch 9.57 + 9.58 +function printEmptyCatch() { 9.59 + // get the system compiler tool 9.60 + var compiler = ToolProvider.systemJavaCompiler; 9.61 + // get standard file manager 9.62 + var fileMgr = compiler.getStandardFileManager(null, null, null); 9.63 + // Using Java.to convert script array (arguments) to a Java String[] 9.64 + var compUnits = fileMgr.getJavaFileObjects( 9.65 + Java.to(arguments, StringArray)); 9.66 + // create a new compilation task 9.67 + var task = compiler.getTask(null, fileMgr, null, null, null, compUnits); 9.68 + 9.69 + // SourcePositions object to get positions of AST nodes 9.70 + var sourcePositions = Trees.instance(task).sourcePositions; 9.71 + 9.72 + // subclass SimpleTreeVisitor - to print empty catch 9.73 + var EmptyCatchFinder = Java.extend(TreeScanner); 9.74 + 9.75 + function hasOnlyEmptyStats(stats) { 9.76 + var itr = stats.iterator(); 9.77 + while (itr.hasNext()) { 9.78 + if (! (itr.next() instanceof EmptyStatementTree)) { 9.79 + return false; 9.80 + } 9.81 + } 9.82 + 9.83 + return true; 9.84 + } 9.85 + 9.86 + var visitor = new EmptyCatchFinder() { 9.87 + // current CompilationUnitTree 9.88 + compUnit: null, 9.89 + // current LineMap (pos -> line, column) 9.90 + lineMap: null, 9.91 + // current compilation unit's file name 9.92 + fileName: null, 9.93 + 9.94 + // overrides of TreeScanner methods 9.95 + 9.96 + visitCompilationUnit: function(node, p) { 9.97 + // capture info about current Compilation unit 9.98 + this.compUnit = node; 9.99 + this.lineMap = node.lineMap; 9.100 + this.fileName = node.sourceFile.name; 9.101 + 9.102 + // Using Java.super API to call super class method here 9.103 + return Java.super(visitor).visitCompilationUnit(node, p); 9.104 + }, 9.105 + 9.106 + visitCatch: function (node, p) { 9.107 + var stats = node.block.statements; 9.108 + if (stats.empty || hasOnlyEmptyStats(stats)) { 9.109 + // print information on this empty catch 9.110 + var pos = sourcePositions.getStartPosition(this.compUnit, node); 9.111 + var line = this.lineMap.getLineNumber(pos); 9.112 + var col = this.lineMap.getColumnNumber(pos); 9.113 + print("Exception swallow" + " @ " + this.fileName + ":" + line + ":" + col); 9.114 + // print(node); 9.115 + } 9.116 + } 9.117 + } 9.118 + 9.119 + for each (var cu in task.parse()) { 9.120 + cu.accept(visitor, null); 9.121 + } 9.122 +} 9.123 + 9.124 +// for each ".java" file in directory (recursively) and check it! 9.125 +function main(dir) { 9.126 + Files.walk(dir.toPath()). 9.127 + forEach(function(p) { 9.128 + var name = p.toFile().absolutePath; 9.129 + if (name.endsWith(".java")) { 9.130 + try { 9.131 + printEmptyCatch(p.toFile().getAbsolutePath()); 9.132 + } catch (e) { 9.133 + print(e); 9.134 + } 9.135 + } 9.136 + }); 9.137 +} 9.138 + 9.139 +main(new File(arguments[0]));
10.1 --- a/samples/find_nonfinals2.js Thu Sep 24 10:00:42 2015 -0700 10.2 +++ b/samples/find_nonfinals2.js Thu Sep 24 10:09:56 2015 -0700 10.3 @@ -43,7 +43,6 @@ 10.4 // Java types used 10.5 var File = Java.type("java.io.File"); 10.6 var Files = Java.type("java.nio.file.Files"); 10.7 -var FileVisitOption = Java.type("java.nio.file.FileVisitOption"); 10.8 var StringArray = Java.type("java.lang.String[]"); 10.9 var ToolProvider = Java.type("javax.tools.ToolProvider"); 10.10 var Tree = Java.type("com.sun.source.tree.Tree"); 10.11 @@ -106,7 +105,7 @@ 10.12 // for each ".java" file in directory (recursively). 10.13 function main(dir) { 10.14 var totalCount = 0; 10.15 - Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS). 10.16 + Files.walk(dir.toPath()). 10.17 forEach(function(p) { 10.18 var name = p.toFile().absolutePath; 10.19 if (name.endsWith(".java")) {
11.1 --- a/samples/javafoovars.js Thu Sep 24 10:00:42 2015 -0700 11.2 +++ b/samples/javafoovars.js Thu Sep 24 10:09:56 2015 -0700 11.3 @@ -42,7 +42,6 @@ 11.4 // Java types used 11.5 var File = Java.type("java.io.File"); 11.6 var Files = Java.type("java.nio.file.Files"); 11.7 -var FileVisitOption = Java.type("java.nio.file.FileVisitOption"); 11.8 var StringArray = Java.type("java.lang.String[]"); 11.9 var ToolProvider = Java.type("javax.tools.ToolProvider"); 11.10 var Tree = Java.type("com.sun.source.tree.Tree"); 11.11 @@ -81,7 +80,7 @@ 11.12 // for each ".java" file in directory (recursively) count "foo". 11.13 function main(dir) { 11.14 var totalCount = 0; 11.15 - Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS). 11.16 + Files.walk(dir.toPath()). 11.17 forEach(function(p) { 11.18 var name = p.toFile().absolutePath; 11.19 if (name.endsWith(".java")) {
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/samples/resourcetrysuggester.js Thu Sep 24 10:09:56 2015 -0700 12.3 @@ -0,0 +1,156 @@ 12.4 +#// Usage: jjs resourcetrysuggester.js -- <directory> 12.5 + 12.6 +/* 12.7 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 12.8 + * 12.9 + * Redistribution and use in source and binary forms, with or without 12.10 + * modification, are permitted provided that the following conditions 12.11 + * are met: 12.12 + * 12.13 + * - Redistributions of source code must retain the above copyright 12.14 + * notice, this list of conditions and the following disclaimer. 12.15 + * 12.16 + * - Redistributions in binary form must reproduce the above copyright 12.17 + * notice, this list of conditions and the following disclaimer in the 12.18 + * documentation and/or other materials provided with the distribution. 12.19 + * 12.20 + * - Neither the name of Oracle nor the names of its 12.21 + * contributors may be used to endorse or promote products derived 12.22 + * from this software without specific prior written permission. 12.23 + * 12.24 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 12.25 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 12.26 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 12.27 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 12.28 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 12.29 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 12.30 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 12.31 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 12.32 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 12.33 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 12.34 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12.35 + */ 12.36 + 12.37 +// This example demonstrates Java subclassing by Java.extend 12.38 +// and javac Compiler and Tree API. This example looks for 12.39 +// finally clauses with "close" call and suggests "resource try"! 12.40 + 12.41 +if (arguments.length == 0) { 12.42 + print("Usage: jjs resourcetrysuggester.js -- <directory>"); 12.43 + exit(1); 12.44 +} 12.45 + 12.46 +// Java types used 12.47 +var ExpressionStatementTree = Java.type("com.sun.source.tree.ExpressionStatementTree"); 12.48 +var File = Java.type("java.io.File"); 12.49 +var Files = Java.type("java.nio.file.Files"); 12.50 +var MemberSelectTree = Java.type("com.sun.source.tree.MemberSelectTree"); 12.51 +var MethodInvocationTree = Java.type("com.sun.source.tree.MethodInvocationTree"); 12.52 +var StringArray = Java.type("java.lang.String[]"); 12.53 +var ToolProvider = Java.type("javax.tools.ToolProvider"); 12.54 +var Tree = Java.type("com.sun.source.tree.Tree"); 12.55 +var Trees = Java.type("com.sun.source.util.Trees"); 12.56 +var TreeScanner = Java.type("com.sun.source.util.TreeScanner"); 12.57 + 12.58 +// resourceTrySuggestions 12.59 + 12.60 +function resourceTrySuggestions() { 12.61 + // get the system compiler tool 12.62 + var compiler = ToolProvider.systemJavaCompiler; 12.63 + // get standard file manager 12.64 + var fileMgr = compiler.getStandardFileManager(null, null, null); 12.65 + // Using Java.to convert script array (arguments) to a Java String[] 12.66 + var compUnits = fileMgr.getJavaFileObjects( 12.67 + Java.to(arguments, StringArray)); 12.68 + // create a new compilation task 12.69 + var task = compiler.getTask(null, fileMgr, null, null, null, compUnits); 12.70 + 12.71 + // SourcePositions object to get positions of AST nodes 12.72 + var sourcePositions = Trees.instance(task).sourcePositions; 12.73 + 12.74 + // subclass SimpleTreeVisitor - to print resource try suggestions 12.75 + var ResourceTrySuggester = Java.extend(TreeScanner); 12.76 + 12.77 + function hasOnlyEmptyStats(stats) { 12.78 + var itr = stats.iterator(); 12.79 + while (itr.hasNext()) { 12.80 + if (! (itr.next() instanceof EmptyStatementTree)) { 12.81 + return false; 12.82 + } 12.83 + } 12.84 + 12.85 + return true; 12.86 + } 12.87 + 12.88 + // does the given statement list has an expression statement which 12.89 + // calls "close" method (don't worry about types - just crude one will do) 12.90 + function hasCloseCall(stats) { 12.91 + var itr = stats.iterator(); 12.92 + while (itr.hasNext()) { 12.93 + var stat = itr.next(); 12.94 + if (stat instanceof ExpressionStatementTree) { 12.95 + var expr = stat.expression; 12.96 + if (expr instanceof MethodInvocationTree) { 12.97 + var method = expr.methodSelect; 12.98 + if (method instanceof MemberSelectTree) { 12.99 + return method.identifier.toString().equals("close"); 12.100 + } 12.101 + } 12.102 + } 12.103 + } 12.104 + return false; 12.105 + } 12.106 + 12.107 + var visitor = new ResourceTrySuggester() { 12.108 + // current CompilationUnitTree 12.109 + compUnit: null, 12.110 + // current LineMap (pos -> line, column) 12.111 + lineMap: null, 12.112 + // current compilation unit's file name 12.113 + fileName: null, 12.114 + 12.115 + // overrides of TreeScanner methods 12.116 + 12.117 + visitCompilationUnit: function(node, p) { 12.118 + // capture info about current Compilation unit 12.119 + this.compUnit = node; 12.120 + this.lineMap = node.lineMap; 12.121 + this.fileName = node.sourceFile.name; 12.122 + 12.123 + // Using Java.super API to call super class method here 12.124 + return Java.super(visitor).visitCompilationUnit(node, p); 12.125 + }, 12.126 + 12.127 + visitTry: function (node, p) { 12.128 + var finallyBlk = node.finallyBlock; 12.129 + if (finallyBlk != null && hasCloseCall(finallyBlk.statements)) { 12.130 + var pos = sourcePositions.getStartPosition(this.compUnit, node); 12.131 + var line = this.lineMap.getLineNumber(pos); 12.132 + var col = this.lineMap.getColumnNumber(pos); 12.133 + print("Consider resource try statement " + " @ " + this.fileName + ":" + line + ":" + col); 12.134 + // print(node); 12.135 + } 12.136 + } 12.137 + } 12.138 + 12.139 + for each (var cu in task.parse()) { 12.140 + cu.accept(visitor, null); 12.141 + } 12.142 +} 12.143 + 12.144 +// for each ".java" file in directory (recursively) and check it! 12.145 +function main(dir) { 12.146 + Files.walk(dir.toPath()). 12.147 + forEach(function(p) { 12.148 + var name = p.toFile().absolutePath; 12.149 + if (name.endsWith(".java")) { 12.150 + try { 12.151 + resourceTrySuggestions(p.toFile().getAbsolutePath()); 12.152 + } catch (e) { 12.153 + print(e); 12.154 + } 12.155 + } 12.156 + }); 12.157 +} 12.158 + 12.159 +main(new File(arguments[0]));
13.1 --- a/samples/zipfs.js Thu Sep 24 10:00:42 2015 -0700 13.2 +++ b/samples/zipfs.js Thu Sep 24 10:09:56 2015 -0700 13.3 @@ -36,13 +36,12 @@ 13.4 13.5 var Files = Java.type("java.nio.file.Files") 13.6 var FileSystems = Java.type("java.nio.file.FileSystems") 13.7 -var FileVisitOption = Java.type("java.nio.file.FileVisitOption") 13.8 var Paths = Java.type("java.nio.file.Paths") 13.9 13.10 var zipfile = Paths.get(arguments[0]) 13.11 var fs = FileSystems.newFileSystem(zipfile, null) 13.12 var root = fs.rootDirectories[0] 13.13 -Files.walk(root, FileVisitOption.FOLLOW_LINKS).forEach( 13.14 +Files.walk(root).forEach( 13.15 function(p) (print(p), print(Files.readAttributes(p, "zip:*"))) 13.16 ) 13.17 fs.close()
14.1 --- a/src/jdk/internal/dynalink/DynamicLinker.java Thu Sep 24 10:00:42 2015 -0700 14.2 +++ b/src/jdk/internal/dynalink/DynamicLinker.java Thu Sep 24 10:09:56 2015 -0700 14.3 @@ -117,7 +117,7 @@ 14.4 * return factory.createLinker(); 14.5 * } 14.6 * 14.7 - * public static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type) { 14.8 + * public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) { 14.9 * return dynamicLinker.link(new MonomorphicCallSite(CallSiteDescriptorFactory.create(lookup, name, type))); 14.10 * } 14.11 * }
15.1 --- a/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java Thu Sep 24 10:00:42 2015 -0700 15.2 +++ b/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java Thu Sep 24 10:09:56 2015 -0700 15.3 @@ -107,7 +107,7 @@ 15.4 private final AccessibleObject target; 15.5 private final MethodType type; 15.6 15.7 - public CallerSensitiveDynamicMethod(final AccessibleObject target) { 15.8 + CallerSensitiveDynamicMethod(final AccessibleObject target) { 15.9 super(getName(target)); 15.10 this.target = target; 15.11 this.type = getMethodType(target); 15.12 @@ -115,8 +115,9 @@ 15.13 15.14 private static String getName(final AccessibleObject target) { 15.15 final Member m = (Member)target; 15.16 - return getMethodNameWithSignature(getMethodType(target), getClassAndMethodName(m.getDeclaringClass(), 15.17 - m.getName())); 15.18 + final boolean constructor = m instanceof Constructor; 15.19 + return getMethodNameWithSignature(getMethodType(target), constructor ? m.getName() : 15.20 + getClassAndMethodName(m.getDeclaringClass(), m.getName()), !constructor); 15.21 } 15.22 15.23 @Override
16.1 --- a/src/jdk/internal/dynalink/beans/FacetIntrospector.java Thu Sep 24 10:00:42 2015 -0700 16.2 +++ b/src/jdk/internal/dynalink/beans/FacetIntrospector.java Thu Sep 24 10:09:56 2015 -0700 16.3 @@ -152,7 +152,7 @@ 16.4 boolean isAccessible(final Member m) { 16.5 final Class<?> declaring = m.getDeclaringClass(); 16.6 // (declaring == clazz) is just an optimization - we're calling this only from code that operates on a 16.7 - // non-restriced class, so if the declaring class is identical to the class being inspected, then forego 16.8 + // non-restricted class, so if the declaring class is identical to the class being inspected, then forego 16.9 // a potentially expensive restricted-package check. 16.10 return declaring == clazz || !CheckRestrictedPackage.isRestrictedClass(declaring); 16.11 }
17.1 --- a/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Thu Sep 24 10:00:42 2015 -0700 17.2 +++ b/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Thu Sep 24 10:09:56 2015 -0700 17.3 @@ -86,7 +86,9 @@ 17.4 import java.lang.invoke.MethodHandle; 17.5 import java.lang.invoke.MethodHandles; 17.6 import java.lang.invoke.MethodType; 17.7 +import java.text.Collator; 17.8 import java.util.ArrayList; 17.9 +import java.util.Collections; 17.10 import java.util.Iterator; 17.11 import java.util.LinkedList; 17.12 import java.util.List; 17.13 @@ -242,6 +244,35 @@ 17.14 return methods.getFirst().isConstructor(); 17.15 } 17.16 17.17 + @Override 17.18 + public String toString() { 17.19 + // First gather the names and sort them. This makes it consistent and easier to read. 17.20 + final List<String> names = new ArrayList<>(methods.size()); 17.21 + int len = 0; 17.22 + for (final SingleDynamicMethod m: methods) { 17.23 + final String name = m.getName(); 17.24 + len += name.length(); 17.25 + names.add(name); 17.26 + } 17.27 + // Case insensitive sorting, so e.g. "Object" doesn't come before "boolean". 17.28 + final Collator collator = Collator.getInstance(); 17.29 + collator.setStrength(Collator.SECONDARY); 17.30 + Collections.sort(names, collator); 17.31 + 17.32 + final String className = getClass().getName(); 17.33 + // Class name length + length of signatures + 2 chars/per signature for indentation and newline + 17.34 + // 3 for brackets and initial newline 17.35 + final int totalLength = className.length() + len + 2 * names.size() + 3; 17.36 + final StringBuilder b = new StringBuilder(totalLength); 17.37 + b.append('[').append(className).append('\n'); 17.38 + for(final String name: names) { 17.39 + b.append(' ').append(name).append('\n'); 17.40 + } 17.41 + b.append(']'); 17.42 + assert b.length() == totalLength; 17.43 + return b.toString(); 17.44 + }; 17.45 + 17.46 ClassLoader getClassLoader() { 17.47 return classLoader; 17.48 }
18.1 --- a/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Thu Sep 24 10:00:42 2015 -0700 18.2 +++ b/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Thu Sep 24 10:09:56 2015 -0700 18.3 @@ -122,13 +122,13 @@ 18.4 * @param constructor does this represent a constructor? 18.5 */ 18.6 SimpleDynamicMethod(final MethodHandle target, final Class<?> clazz, final String name, final boolean constructor) { 18.7 - super(getName(target, clazz, name)); 18.8 + super(getName(target, clazz, name, constructor)); 18.9 this.target = target; 18.10 this.constructor = constructor; 18.11 } 18.12 18.13 - private static String getName(final MethodHandle target, final Class<?> clazz, final String name) { 18.14 - return getMethodNameWithSignature(target.type(), getClassAndMethodName(clazz, name)); 18.15 + private static String getName(final MethodHandle target, final Class<?> clazz, final String name, final boolean constructor) { 18.16 + return getMethodNameWithSignature(target.type(), constructor ? name : getClassAndMethodName(clazz, name), !constructor); 18.17 } 18.18 18.19 @Override
19.1 --- a/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java Thu Sep 24 10:00:42 2015 -0700 19.2 +++ b/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java Thu Sep 24 10:09:56 2015 -0700 19.3 @@ -98,7 +98,6 @@ 19.4 * target method to a call site type (including mapping variable arity methods to a call site signature with different 19.5 * arity). 19.6 * @author Attila Szegedi 19.7 - * @version $Id: $ 19.8 */ 19.9 abstract class SingleDynamicMethod extends DynamicMethod { 19.10 19.11 @@ -143,14 +142,18 @@ 19.12 return getMethodType().parameterList().equals(method.getMethodType().parameterList()); 19.13 } 19.14 19.15 - static String getMethodNameWithSignature(final MethodType type, final String methodName) { 19.16 + static String getMethodNameWithSignature(final MethodType type, final String methodName, final boolean withReturnType) { 19.17 final String typeStr = type.toString(); 19.18 final int retTypeIndex = typeStr.lastIndexOf(')') + 1; 19.19 int secondParamIndex = typeStr.indexOf(',') + 1; 19.20 if(secondParamIndex == 0) { 19.21 secondParamIndex = retTypeIndex - 1; 19.22 } 19.23 - return typeStr.substring(retTypeIndex) + " " + methodName + "(" + typeStr.substring(secondParamIndex, retTypeIndex); 19.24 + final StringBuilder b = new StringBuilder(); 19.25 + if (withReturnType) { 19.26 + b.append(typeStr, retTypeIndex, typeStr.length()).append(' '); 19.27 + } 19.28 + return b.append(methodName).append('(').append(typeStr, secondParamIndex, retTypeIndex).toString(); 19.29 } 19.30 19.31 /**
20.1 --- a/src/jdk/internal/dynalink/linker/GuardedInvocation.java Thu Sep 24 10:00:42 2015 -0700 20.2 +++ b/src/jdk/internal/dynalink/linker/GuardedInvocation.java Thu Sep 24 10:09:56 2015 -0700 20.3 @@ -353,7 +353,7 @@ 20.4 20.5 /** 20.6 * Applies argument filters to both the invocation and the guard (if there is one). 20.7 - * @param pos the position of the first argumen being filtered 20.8 + * @param pos the position of the first argument being filtered 20.9 * @param filters the argument filters 20.10 * @return a filtered invocation 20.11 */
21.1 --- a/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java Thu Sep 24 10:00:42 2015 -0700 21.2 +++ b/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java Thu Sep 24 10:09:56 2015 -0700 21.3 @@ -110,7 +110,7 @@ 21.4 21.5 /** 21.6 * Check if invocation is cacheable 21.7 - * @return true if cachable, false otherwise 21.8 + * @return true if cacheable, false otherwise 21.9 */ 21.10 public boolean isCacheable() { 21.11 return cacheable;
22.1 --- a/src/jdk/nashorn/api/scripting/AbstractJSObject.java Thu Sep 24 10:00:42 2015 -0700 22.2 +++ b/src/jdk/nashorn/api/scripting/AbstractJSObject.java Thu Sep 24 10:09:56 2015 -0700 22.3 @@ -182,7 +182,7 @@ 22.4 /** 22.5 * Checking whether the given object is an instance of 'this' object. 22.6 * 22.7 - * @param instance instace to check 22.8 + * @param instance instance to check 22.9 * @return true if the given 'instance' is an instance of this 'function' object 22.10 */ 22.11 @Override
23.1 --- a/src/jdk/nashorn/api/scripting/JSObject.java Thu Sep 24 10:00:42 2015 -0700 23.2 +++ b/src/jdk/nashorn/api/scripting/JSObject.java Thu Sep 24 10:09:56 2015 -0700 23.3 @@ -141,7 +141,7 @@ 23.4 /** 23.5 * Checking whether the given object is an instance of 'this' object. 23.6 * 23.7 - * @param instance instace to check 23.8 + * @param instance instance to check 23.9 * @return true if the given 'instance' is an instance of this 'function' object 23.10 */ 23.11 public boolean isInstance(final Object instance);
24.1 --- a/src/jdk/nashorn/api/scripting/NashornException.java Thu Sep 24 10:00:42 2015 -0700 24.2 +++ b/src/jdk/nashorn/api/scripting/NashornException.java Thu Sep 24 10:09:56 2015 -0700 24.3 @@ -51,6 +51,8 @@ 24.4 private String fileName; 24.5 // script line number 24.6 private int line; 24.7 + // are the line and fileName unknown? 24.8 + private boolean lineAndFileNameUnknown; 24.9 // script column number 24.10 private int column; 24.11 // underlying ECMA error object - lazily initialized 24.12 @@ -92,27 +94,10 @@ 24.13 */ 24.14 protected NashornException(final String msg, final Throwable cause) { 24.15 super(msg, cause == null ? null : cause); 24.16 - // This is not so pretty - but it gets the job done. Note that the stack 24.17 - // trace has been already filled by "fillInStackTrace" call from 24.18 - // Throwable 24.19 - // constructor and so we don't pay additional cost for it. 24.20 - 24.21 // Hard luck - no column number info 24.22 this.column = -1; 24.23 - 24.24 - // Find the first JavaScript frame by walking and set file, line from it 24.25 - // Usually, we should be able to find it in just few frames depth. 24.26 - for (final StackTraceElement ste : getStackTrace()) { 24.27 - if (ECMAErrors.isScriptFrame(ste)) { 24.28 - // Whatever here is compiled from JavaScript code 24.29 - this.fileName = ste.getFileName(); 24.30 - this.line = ste.getLineNumber(); 24.31 - return; 24.32 - } 24.33 - } 24.34 - 24.35 - this.fileName = null; 24.36 - this.line = 0; 24.37 + // We can retrieve the line number and file name from the stack trace if needed 24.38 + this.lineAndFileNameUnknown = true; 24.39 } 24.40 24.41 /** 24.42 @@ -121,6 +106,7 @@ 24.43 * @return the file name 24.44 */ 24.45 public final String getFileName() { 24.46 + ensureLineAndFileName(); 24.47 return fileName; 24.48 } 24.49 24.50 @@ -131,6 +117,7 @@ 24.51 */ 24.52 public final void setFileName(final String fileName) { 24.53 this.fileName = fileName; 24.54 + lineAndFileNameUnknown = false; 24.55 } 24.56 24.57 /** 24.58 @@ -139,6 +126,7 @@ 24.59 * @return the line number 24.60 */ 24.61 public final int getLineNumber() { 24.62 + ensureLineAndFileName(); 24.63 return line; 24.64 } 24.65 24.66 @@ -148,6 +136,7 @@ 24.67 * @param line the line number 24.68 */ 24.69 public final void setLineNumber(final int line) { 24.70 + lineAndFileNameUnknown = false; 24.71 this.line = line; 24.72 } 24.73 24.74 @@ -274,4 +263,19 @@ 24.75 public void setEcmaError(final Object ecmaError) { 24.76 this.ecmaError = ecmaError; 24.77 } 24.78 + 24.79 + private void ensureLineAndFileName() { 24.80 + if (lineAndFileNameUnknown) { 24.81 + for (final StackTraceElement ste : getStackTrace()) { 24.82 + if (ECMAErrors.isScriptFrame(ste)) { 24.83 + // Whatever here is compiled from JavaScript code 24.84 + fileName = ste.getFileName(); 24.85 + line = ste.getLineNumber(); 24.86 + return; 24.87 + } 24.88 + } 24.89 + 24.90 + lineAndFileNameUnknown = false; 24.91 + } 24.92 + } 24.93 }
25.1 --- a/src/jdk/nashorn/api/scripting/ScriptUtils.java Thu Sep 24 10:00:42 2015 -0700 25.2 +++ b/src/jdk/nashorn/api/scripting/ScriptUtils.java Thu Sep 24 10:09:56 2015 -0700 25.3 @@ -79,7 +79,7 @@ 25.4 * @return a synchronizing wrapper function 25.5 */ 25.6 public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) { 25.7 - return func.makeSynchronizedFunction(unwrap(sync)); 25.8 + return func.createSynchronized(unwrap(sync)); 25.9 } 25.10 25.11 /**
26.1 --- a/src/jdk/nashorn/api/scripting/URLReader.java Thu Sep 24 10:00:42 2015 -0700 26.2 +++ b/src/jdk/nashorn/api/scripting/URLReader.java Thu Sep 24 10:09:56 2015 -0700 26.3 @@ -103,7 +103,7 @@ 26.4 /** 26.5 * Charset used by this reader 26.6 * 26.7 - * @return the Chartset used to convert bytes to chars 26.8 + * @return the Charset used to convert bytes to chars 26.9 */ 26.10 public Charset getCharset() { 26.11 return cs;
27.1 --- a/src/jdk/nashorn/internal/codegen/ApplySpecialization.java Thu Sep 24 10:00:42 2015 -0700 27.2 +++ b/src/jdk/nashorn/internal/codegen/ApplySpecialization.java Thu Sep 24 10:09:56 2015 -0700 27.3 @@ -40,7 +40,6 @@ 27.4 import jdk.nashorn.internal.ir.CallNode; 27.5 import jdk.nashorn.internal.ir.Expression; 27.6 import jdk.nashorn.internal.ir.FunctionNode; 27.7 -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 27.8 import jdk.nashorn.internal.ir.IdentNode; 27.9 import jdk.nashorn.internal.ir.LexicalContext; 27.10 import jdk.nashorn.internal.ir.Node; 27.11 @@ -298,7 +297,28 @@ 27.12 27.13 @Override 27.14 public boolean enterFunctionNode(final FunctionNode functionNode) { 27.15 - if (!USE_APPLY2CALL) { 27.16 + // Cheap tests first 27.17 + if (!( 27.18 + // is the transform globally enabled? 27.19 + USE_APPLY2CALL 27.20 + 27.21 + // Are we compiling lazily? We can't known the number and types of the actual parameters at 27.22 + // the caller when compiling eagerly, so this only works with on-demand compilation. 27.23 + && compiler.isOnDemandCompilation() 27.24 + 27.25 + // Does the function even reference the "arguments" identifier (without redefining it)? If not, 27.26 + // it trivially can't have an expression of form "f.apply(self, arguments)" that this transform 27.27 + // is targeting. 27.28 + && functionNode.needsArguments() 27.29 + 27.30 + // Does the function have eval? If so, it can arbitrarily modify arguments so we can't touch it. 27.31 + && !functionNode.hasEval() 27.32 + 27.33 + // Finally, does the function declare any parameters explicitly? We don't support that. It could 27.34 + // be done, but has some complications. Therefore only a function with no explicit parameters 27.35 + // is considered. 27.36 + && functionNode.getNumOfParams() == 0)) 27.37 + { 27.38 return false; 27.39 } 27.40 27.41 @@ -308,18 +328,6 @@ 27.42 return false; 27.43 } 27.44 27.45 - if (!compiler.isOnDemandCompilation()) { 27.46 - return false; 27.47 - } 27.48 - 27.49 - if (functionNode.getNumOfParams() != 0) { 27.50 - return false; 27.51 - } 27.52 - 27.53 - if (functionNode.hasEval()) { 27.54 - return false; 27.55 - } 27.56 - 27.57 if (!hasApplies(functionNode)) { 27.58 return false; 27.59 } 27.60 @@ -375,7 +383,7 @@ 27.61 callSiteTypes.pop(); 27.62 explodedArguments.pop(); 27.63 27.64 - return newFunctionNode.setState(lc, CompilationState.BUILTINS_TRANSFORMED); 27.65 + return newFunctionNode; 27.66 } 27.67 27.68 private static boolean isApply(final CallNode callNode) {
28.1 --- a/src/jdk/nashorn/internal/codegen/AssignSymbols.java Thu Sep 24 10:00:42 2015 -0700 28.2 +++ b/src/jdk/nashorn/internal/codegen/AssignSymbols.java Thu Sep 24 10:09:56 2015 -0700 28.3 @@ -65,7 +65,6 @@ 28.4 import jdk.nashorn.internal.ir.Expression; 28.5 import jdk.nashorn.internal.ir.ForNode; 28.6 import jdk.nashorn.internal.ir.FunctionNode; 28.7 -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 28.8 import jdk.nashorn.internal.ir.IdentNode; 28.9 import jdk.nashorn.internal.ir.IndexNode; 28.10 import jdk.nashorn.internal.ir.LexicalContext; 28.11 @@ -149,12 +148,14 @@ 28.12 private final Deque<Set<String>> thisProperties = new ArrayDeque<>(); 28.13 private final Map<String, Symbol> globalSymbols = new HashMap<>(); //reuse the same global symbol 28.14 private final Compiler compiler; 28.15 + private final boolean isOnDemand; 28.16 28.17 public AssignSymbols(final Compiler compiler) { 28.18 super(new LexicalContext()); 28.19 this.compiler = compiler; 28.20 this.log = initLogger(compiler.getContext()); 28.21 this.debug = log.isEnabled(); 28.22 + this.isOnDemand = compiler.isOnDemandCompilation(); 28.23 } 28.24 28.25 @Override 28.26 @@ -242,7 +243,7 @@ 28.27 28.28 /** 28.29 * Creates a synthetic initializer for a variable (a var statement that doesn't occur in the source code). Typically 28.30 - * used to create assignmnent of {@code :callee} to the function name symbol in self-referential function 28.31 + * used to create assignment of {@code :callee} to the function name symbol in self-referential function 28.32 * expressions as well as for assignment of {@code :arguments} to {@code arguments}. 28.33 * 28.34 * @param name the ident node identifying the variable to initialize 28.35 @@ -390,7 +391,7 @@ 28.36 28.37 // Create and add to appropriate block. 28.38 symbol = createSymbol(name, flags); 28.39 - symbolBlock.putSymbol(lc, symbol); 28.40 + symbolBlock.putSymbol(symbol); 28.41 28.42 if ((flags & IS_SCOPE) == 0) { 28.43 // Initial assumption; symbol can lose its slot later 28.44 @@ -440,7 +441,7 @@ 28.45 start(block); 28.46 28.47 if (lc.isFunctionBody()) { 28.48 - block.clearSymbols(); 28.49 + assert !block.hasSymbols(); 28.50 final FunctionNode fn = lc.getCurrentFunction(); 28.51 if (isUnparsedFunction(fn)) { 28.52 // It's a skipped nested function. Just mark the symbols being used by it as being in use. 28.53 @@ -459,7 +460,7 @@ 28.54 } 28.55 28.56 private boolean isUnparsedFunction(final FunctionNode fn) { 28.57 - return compiler.isOnDemandCompilation() && fn != lc.getOutermostFunction(); 28.58 + return isOnDemand && fn != lc.getOutermostFunction(); 28.59 } 28.60 28.61 @Override 28.62 @@ -747,28 +748,6 @@ 28.63 } 28.64 } 28.65 28.66 - @Override 28.67 - public Node leaveBlock(final Block block) { 28.68 - // It's not necessary to guard the marking of symbols as locals with this "if" condition for 28.69 - // correctness, it's just an optimization -- runtime type calculation is not used when the compilation 28.70 - // is not an on-demand optimistic compilation, so we can skip locals marking then. 28.71 - if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) { 28.72 - // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand 28.73 - // compilation, and we're skipping parsing the function bodies for nested functions, this 28.74 - // basically only means their parameters. It'd be enough to mistakenly declare to be a local a 28.75 - // symbol in the outer function named the same as one of the parameters, though. 28.76 - if (lc.getFunction(block) == lc.getOutermostFunction()) { 28.77 - for (final Symbol symbol: block.getSymbols()) { 28.78 - if (!symbol.isScope()) { 28.79 - assert symbol.isVar() || symbol.isParam(); 28.80 - compiler.declareLocalSymbol(symbol.getName()); 28.81 - } 28.82 - } 28.83 - } 28.84 - } 28.85 - return block; 28.86 - } 28.87 - 28.88 private Node leaveDELETE(final UnaryNode unaryNode) { 28.89 final FunctionNode currentFunctionNode = lc.getCurrentFunction(); 28.90 final boolean strictMode = currentFunctionNode.isStrict(); 28.91 @@ -786,9 +765,9 @@ 28.92 28.93 if (symbol.isThis()) { 28.94 // Can't delete "this", ignore and return true 28.95 - return LiteralNode.newInstance(unaryNode, true).accept(this); 28.96 + return LiteralNode.newInstance(unaryNode, true); 28.97 } 28.98 - final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this); 28.99 + final Expression literalNode = LiteralNode.newInstance(unaryNode, name); 28.100 final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel()))); 28.101 28.102 if (!failDelete) { 28.103 @@ -799,7 +778,7 @@ 28.104 28.105 if (failDelete) { 28.106 request = Request.FAIL_DELETE; 28.107 - } else if (symbol.isGlobal() && !symbol.isFunctionDeclaration()) { 28.108 + } else if ((symbol.isGlobal() && !symbol.isFunctionDeclaration()) || symbol.isProgramLevel()) { 28.109 request = Request.SLOW_DELETE; 28.110 } 28.111 } else if (rhs instanceof AccessNode) { 28.112 @@ -807,7 +786,7 @@ 28.113 final String property = ((AccessNode)rhs).getProperty(); 28.114 28.115 args.add(base); 28.116 - args.add((Expression)LiteralNode.newInstance(unaryNode, property).accept(this)); 28.117 + args.add(LiteralNode.newInstance(unaryNode, property)); 28.118 args.add(strictFlagNode); 28.119 28.120 } else if (rhs instanceof IndexNode) { 28.121 @@ -820,15 +799,15 @@ 28.122 args.add(strictFlagNode); 28.123 28.124 } else { 28.125 - return LiteralNode.newInstance(unaryNode, true).accept(this); 28.126 + return LiteralNode.newInstance(unaryNode, true); 28.127 } 28.128 - return new RuntimeNode(unaryNode, request, args).accept(this); 28.129 + return new RuntimeNode(unaryNode, request, args); 28.130 } 28.131 28.132 @Override 28.133 public Node leaveForNode(final ForNode forNode) { 28.134 if (forNode.isForIn()) { 28.135 - forNode.setIterator(newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73 28.136 + return forNode.setIterator(lc, newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73 28.137 } 28.138 28.139 return end(forNode); 28.140 @@ -848,7 +827,7 @@ 28.141 lc.applyTopFlags(functionNode)))) 28.142 .setThisProperties(lc, thisProperties.pop().size())); 28.143 } 28.144 - return finalizedFunction.setState(lc, CompilationState.SYMBOLS_ASSIGNED); 28.145 + return finalizedFunction; 28.146 } 28.147 28.148 @Override 28.149 @@ -904,19 +883,18 @@ 28.150 public Node leaveSwitchNode(final SwitchNode switchNode) { 28.151 // We only need a symbol for the tag if it's not an integer switch node 28.152 if(!switchNode.isUniqueInteger()) { 28.153 - switchNode.setTag(newObjectInternal(SWITCH_TAG_PREFIX)); 28.154 + return switchNode.setTag(lc, newObjectInternal(SWITCH_TAG_PREFIX)); 28.155 } 28.156 return switchNode; 28.157 } 28.158 28.159 @Override 28.160 public Node leaveTryNode(final TryNode tryNode) { 28.161 - tryNode.setException(exceptionSymbol()); 28.162 assert tryNode.getFinallyBody() == null; 28.163 28.164 end(tryNode); 28.165 28.166 - return tryNode; 28.167 + return tryNode.setException(lc, exceptionSymbol()); 28.168 } 28.169 28.170 private Node leaveTYPEOF(final UnaryNode unaryNode) { 28.171 @@ -925,13 +903,13 @@ 28.172 final List<Expression> args = new ArrayList<>(); 28.173 if (rhs instanceof IdentNode && !isParamOrVar((IdentNode)rhs)) { 28.174 args.add(compilerConstantIdentifier(SCOPE)); 28.175 - args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null 28.176 + args.add(LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName())); //null 28.177 } else { 28.178 args.add(rhs); 28.179 - args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this' 28.180 + args.add(LiteralNode.newInstance(unaryNode)); //null, do not reuse token of identifier rhs, it can be e.g. 'this' 28.181 } 28.182 28.183 - final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args).accept(this); 28.184 + final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args); 28.185 28.186 end(unaryNode); 28.187 28.188 @@ -939,7 +917,7 @@ 28.189 } 28.190 28.191 private FunctionNode markProgramBlock(final FunctionNode functionNode) { 28.192 - if (compiler.isOnDemandCompilation() || !functionNode.isProgram()) { 28.193 + if (isOnDemand || !functionNode.isProgram()) { 28.194 return functionNode; 28.195 } 28.196
29.1 --- a/src/jdk/nashorn/internal/codegen/AstSerializer.java Thu Sep 24 10:00:42 2015 -0700 29.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 29.3 @@ -1,73 +0,0 @@ 29.4 -/* 29.5 - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 29.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 29.7 - * 29.8 - * This code is free software; you can redistribute it and/or modify it 29.9 - * under the terms of the GNU General Public License version 2 only, as 29.10 - * published by the Free Software Foundation. Oracle designates this 29.11 - * particular file as subject to the "Classpath" exception as provided 29.12 - * by Oracle in the LICENSE file that accompanied this code. 29.13 - * 29.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 29.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 29.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 29.17 - * version 2 for more details (a copy is included in the LICENSE file that 29.18 - * accompanied this code). 29.19 - * 29.20 - * You should have received a copy of the GNU General Public License version 29.21 - * 2 along with this work; if not, write to the Free Software Foundation, 29.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 29.23 - * 29.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 29.25 - * or visit www.oracle.com if you need additional information or have any 29.26 - * questions. 29.27 - */ 29.28 -package jdk.nashorn.internal.codegen; 29.29 - 29.30 -import java.io.ByteArrayOutputStream; 29.31 -import java.io.IOException; 29.32 -import java.io.ObjectOutputStream; 29.33 -import java.util.Collections; 29.34 -import java.util.zip.Deflater; 29.35 -import java.util.zip.DeflaterOutputStream; 29.36 -import jdk.nashorn.internal.ir.Block; 29.37 -import jdk.nashorn.internal.ir.FunctionNode; 29.38 -import jdk.nashorn.internal.ir.LexicalContext; 29.39 -import jdk.nashorn.internal.ir.Node; 29.40 -import jdk.nashorn.internal.ir.Statement; 29.41 -import jdk.nashorn.internal.ir.visitor.NodeVisitor; 29.42 -import jdk.nashorn.internal.runtime.options.Options; 29.43 - 29.44 -/** 29.45 - * This static utility class performs serialization of FunctionNode ASTs to a byte array. 29.46 - * The format is a standard Java serialization stream, deflated. 29.47 - */ 29.48 -final class AstSerializer { 29.49 - // Experimentally, we concluded that compression level 4 gives a good tradeoff between serialization speed 29.50 - // and size. 29.51 - private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4); 29.52 - static byte[] serialize(final FunctionNode fn) { 29.53 - final ByteArrayOutputStream out = new ByteArrayOutputStream(); 29.54 - final Deflater deflater = new Deflater(COMPRESSION_LEVEL); 29.55 - try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) { 29.56 - oout.writeObject(removeInnerFunctionBodies(fn)); 29.57 - } catch (final IOException e) { 29.58 - throw new AssertionError("Unexpected exception serializing function", e); 29.59 - } finally { 29.60 - deflater.end(); 29.61 - } 29.62 - return out.toByteArray(); 29.63 - } 29.64 - 29.65 - private static FunctionNode removeInnerFunctionBodies(final FunctionNode fn) { 29.66 - return (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 29.67 - @Override 29.68 - public Node leaveBlock(final Block block) { 29.69 - if (lc.isFunctionBody() && lc.getFunction(block) != lc.getOutermostFunction()) { 29.70 - return block.setStatements(lc, Collections.<Statement>emptyList()); 29.71 - } 29.72 - return super.leaveBlock(block); 29.73 - } 29.74 - }); 29.75 - } 29.76 -}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/src/jdk/nashorn/internal/codegen/CacheAst.java Thu Sep 24 10:09:56 2015 -0700 30.3 @@ -0,0 +1,87 @@ 30.4 +/* 30.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 30.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 30.7 + * 30.8 + * This code is free software; you can redistribute it and/or modify it 30.9 + * under the terms of the GNU General Public License version 2 only, as 30.10 + * published by the Free Software Foundation. Oracle designates this 30.11 + * particular file as subject to the "Classpath" exception as provided 30.12 + * by Oracle in the LICENSE file that accompanied this code. 30.13 + * 30.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 30.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 30.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 30.17 + * version 2 for more details (a copy is included in the LICENSE file that 30.18 + * accompanied this code). 30.19 + * 30.20 + * You should have received a copy of the GNU General Public License version 30.21 + * 2 along with this work; if not, write to the Free Software Foundation, 30.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 30.23 + * 30.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 30.25 + * or visit www.oracle.com if you need additional information or have any 30.26 + * questions. 30.27 + */ 30.28 + 30.29 +package jdk.nashorn.internal.codegen; 30.30 + 30.31 +import java.util.ArrayDeque; 30.32 +import java.util.Collections; 30.33 +import java.util.Deque; 30.34 +import jdk.nashorn.internal.ir.FunctionNode; 30.35 +import jdk.nashorn.internal.ir.LexicalContext; 30.36 +import jdk.nashorn.internal.ir.Node; 30.37 +import jdk.nashorn.internal.ir.Statement; 30.38 +import jdk.nashorn.internal.ir.visitor.NodeVisitor; 30.39 +import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; 30.40 + 30.41 +class CacheAst extends NodeVisitor<LexicalContext> { 30.42 + private final Deque<RecompilableScriptFunctionData> dataStack = new ArrayDeque<>(); 30.43 + 30.44 + private final Compiler compiler; 30.45 + 30.46 + CacheAst(final Compiler compiler) { 30.47 + super(new LexicalContext()); 30.48 + this.compiler = compiler; 30.49 + assert !compiler.isOnDemandCompilation(); 30.50 + } 30.51 + 30.52 + @Override 30.53 + public boolean enterFunctionNode(final FunctionNode functionNode) { 30.54 + final int id = functionNode.getId(); 30.55 + // It isn't necessary to keep a stack of RecompilableScriptFunctionData, but then we'd need to do a 30.56 + // potentially transitive lookup with compiler.getScriptFunctionData(id) for deeper functions; this way 30.57 + // we keep it constant time. 30.58 + dataStack.push(dataStack.isEmpty() ? compiler.getScriptFunctionData(id) : dataStack.peek().getScriptFunctionData(id)); 30.59 + return true; 30.60 + } 30.61 + 30.62 + @Override 30.63 + public Node leaveFunctionNode(final FunctionNode functionNode) { 30.64 + final RecompilableScriptFunctionData data = dataStack.pop(); 30.65 + if (functionNode.isSplit()) { 30.66 + // NOTE: cache only split function ASTs from eager pass. Caching non-split functions would require 30.67 + // some additional work, namely creating the concept of "uncacheable" function and reworking 30.68 + // ApplySpecialization to ensure that functions undergoing apply-to-call transformations are not 30.69 + // cacheable as well as recomputing Symbol.useCount when caching the eagerly parsed AST. 30.70 + // Recomputing Symbol.useCount would be needed so it will only reflect uses from within the 30.71 + // function being cached (and not reflect uses from its own nested functions or functions it is 30.72 + // nested in). This is consistent with the count an on-demand recompilation of the function would 30.73 + // produce. This is important as the decision to emit shared scope calls is based on this count, 30.74 + // and if it is not matched between a previous version of the code and its deoptimizing rest-of 30.75 + // compilation, it can result in rest-of not emitting a shared scope call where a previous version 30.76 + // of the code (compiled from a cached eager pre-pass seeing higher (global) useCount) would emit 30.77 + // it, causing a mismatch in stack shapes between previous code and its rest-of. 30.78 + data.setCachedAst(functionNode); 30.79 + } 30.80 + 30.81 + if (!dataStack.isEmpty() && ((dataStack.peek().getFunctionFlags() & FunctionNode.IS_SPLIT) != 0)) { 30.82 + // Return a function node with no body so that caching outer functions doesn't hold on to nested 30.83 + // functions' bodies. Note we're doing this only for functions directly nested inside split 30.84 + // functions, since we're only caching the split ones. It is not necessary to limit body removal 30.85 + // to just these functions, but it's a cheap way to prevent unnecessary AST mutations. 30.86 + return functionNode.setBody(lc, functionNode.getBody().setStatements(null, Collections.<Statement>emptyList())); 30.87 + } 30.88 + return functionNode; 30.89 + } 30.90 +}
31.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Sep 24 10:00:42 2015 -0700 31.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Sep 24 10:09:56 2015 -0700 31.3 @@ -93,7 +93,6 @@ 31.4 import jdk.nashorn.internal.ir.ExpressionStatement; 31.5 import jdk.nashorn.internal.ir.ForNode; 31.6 import jdk.nashorn.internal.ir.FunctionNode; 31.7 -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 31.8 import jdk.nashorn.internal.ir.GetSplitState; 31.9 import jdk.nashorn.internal.ir.IdentNode; 31.10 import jdk.nashorn.internal.ir.IfNode; 31.11 @@ -132,7 +131,6 @@ 31.12 import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor; 31.13 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 31.14 import jdk.nashorn.internal.objects.Global; 31.15 -import jdk.nashorn.internal.objects.ScriptFunctionImpl; 31.16 import jdk.nashorn.internal.parser.Lexer.RegexToken; 31.17 import jdk.nashorn.internal.parser.TokenType; 31.18 import jdk.nashorn.internal.runtime.Context; 31.19 @@ -195,9 +193,9 @@ 31.20 private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, 31.21 "ensureNumber", double.class, Object.class, int.class); 31.22 31.23 - private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class, 31.24 + private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunction.class, 31.25 "create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class); 31.26 - private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class, 31.27 + private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunction.class, 31.28 "create", ScriptFunction.class, Object[].class, int.class); 31.29 31.30 private static final Call TO_NUMBER_FOR_EQ = CompilerConstants.staticCallNoLookup(JSType.class, 31.31 @@ -249,7 +247,7 @@ 31.32 private final Set<String> emittedMethods = new HashSet<>(); 31.33 31.34 // Function Id -> ContinuationInfo. Used by compilation of rest-of function only. 31.35 - private final Map<Integer, ContinuationInfo> fnIdToContinuationInfo = new HashMap<>(); 31.36 + private ContinuationInfo continuationInfo; 31.37 31.38 private final Deque<Label> scopeEntryLabels = new ArrayDeque<>(); 31.39 31.40 @@ -349,11 +347,20 @@ 31.41 final int flags = getScopeCallSiteFlags(symbol); 31.42 if (isFastScope(symbol)) { 31.43 // Only generate shared scope getter for fast-scope symbols so we know we can dial in correct scope. 31.44 - if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD && !isOptimisticOrRestOf()) { 31.45 - method.loadCompilerConstant(SCOPE); 31.46 - // As shared scope vars are only used in non-optimistic compilation, we switch from using TypeBounds to 31.47 + if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD && !identNode.isOptimistic()) { 31.48 + // As shared scope vars are only used with non-optimistic identifiers, we switch from using TypeBounds to 31.49 // just a single definitive type, resultBounds.widest. 31.50 - loadSharedScopeVar(resultBounds.widest, symbol, flags); 31.51 + new OptimisticOperation(identNode, TypeBounds.OBJECT) { 31.52 + @Override 31.53 + void loadStack() { 31.54 + method.loadCompilerConstant(SCOPE); 31.55 + } 31.56 + 31.57 + @Override 31.58 + void consumeStack() { 31.59 + loadSharedScopeVar(resultBounds.widest, symbol, flags); 31.60 + } 31.61 + }.emit(); 31.62 } else { 31.63 new LoadFastScopeVar(identNode, resultBounds, flags).emit(); 31.64 } 31.65 @@ -384,10 +391,6 @@ 31.66 return continuationEntryPoints != null; 31.67 } 31.68 31.69 - private boolean isOptimisticOrRestOf() { 31.70 - return useOptimisticTypes() || isRestOf(); 31.71 - } 31.72 - 31.73 private boolean isCurrentContinuationEntryPoint(final int programPoint) { 31.74 return isRestOf() && getCurrentContinuationEntryPoint() == programPoint; 31.75 } 31.76 @@ -464,12 +467,8 @@ 31.77 } 31.78 31.79 private MethodEmitter loadSharedScopeVar(final Type valueType, final Symbol symbol, final int flags) { 31.80 - assert !isOptimisticOrRestOf(); 31.81 - if (isFastScope(symbol)) { 31.82 - method.load(getScopeProtoDepth(lc.getCurrentBlock(), symbol)); 31.83 - } else { 31.84 - method.load(-1); 31.85 - } 31.86 + assert isFastScope(symbol); 31.87 + method.load(getScopeProtoDepth(lc.getCurrentBlock(), symbol)); 31.88 return lc.getScopeGet(unit, symbol, valueType, flags).generateInvoke(method); 31.89 } 31.90 31.91 @@ -1494,7 +1493,7 @@ 31.92 int argsCount; 31.93 @Override 31.94 void loadStack() { 31.95 - /** 31.96 + /* 31.97 * We want to load 'eval' to check if it is indeed global builtin eval. 31.98 * If this eval call is inside a 'with' statement, dyn:getMethod|getProp|getElem 31.99 * would be generated if ident is a "isFunction". But, that would result in a 31.100 @@ -1573,7 +1572,7 @@ 31.101 } else if (useCount <= SharedScopeCall.FAST_SCOPE_CALL_THRESHOLD 31.102 || !isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD 31.103 || CodeGenerator.this.lc.inDynamicScope() 31.104 - || isOptimisticOrRestOf()) { 31.105 + || callNode.isOptimistic()) { 31.106 scopeCall(node, flags); 31.107 } else { 31.108 sharedScopeCall(node, flags); 31.109 @@ -2070,8 +2069,6 @@ 31.110 31.111 @Override 31.112 public boolean enterFunctionNode(final FunctionNode functionNode) { 31.113 - final int fnId = functionNode.getId(); 31.114 - 31.115 if (skipFunction(functionNode)) { 31.116 // In case we are not generating code for the function, we must create or retrieve the function object and 31.117 // load it on the stack here. 31.118 @@ -2109,9 +2106,9 @@ 31.119 method.begin(); 31.120 31.121 if (isRestOf()) { 31.122 - final ContinuationInfo ci = new ContinuationInfo(); 31.123 - fnIdToContinuationInfo.put(fnId, ci); 31.124 - method.gotoLoopStart(ci.getHandlerLabel()); 31.125 + assert continuationInfo == null; 31.126 + continuationInfo = new ContinuationInfo(); 31.127 + method.gotoLoopStart(continuationInfo.getHandlerLabel()); 31.128 } 31.129 } 31.130 31.131 @@ -2144,7 +2141,7 @@ 31.132 markOptimistic = false; 31.133 } 31.134 31.135 - FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.BYTECODE_GENERATED); 31.136 + FunctionNode newFunctionNode = functionNode; 31.137 if (markOptimistic) { 31.138 newFunctionNode = newFunctionNode.setFlag(lc, FunctionNode.IS_DEOPTIMIZABLE); 31.139 } 31.140 @@ -4331,7 +4328,7 @@ 31.141 } 31.142 31.143 private void prologue() { 31.144 - /** 31.145 + /* 31.146 * This loads the parts of the target, e.g base and index. they are kept 31.147 * on the stack throughout the store and used at the end to execute it 31.148 */ 31.149 @@ -4799,7 +4796,7 @@ 31.150 * conversion has no side effects. 31.151 * @param name the name of the property being get 31.152 * @param flags call site flags 31.153 - * @param isMethod whether we're preferrably retrieving a function 31.154 + * @param isMethod whether we're preferably retrieving a function 31.155 * @return the current method emitter 31.156 */ 31.157 MethodEmitter dynamicGet(final String name, final int flags, final boolean isMethod, final boolean isIndex) { 31.158 @@ -5231,7 +5228,7 @@ 31.159 private Type returnValueType; 31.160 // If we are in the middle of an object literal initialization, we need to update the map 31.161 private PropertyMap objectLiteralMap; 31.162 - // Object literal stack depth for object literal - not necessarly top if property is a tree 31.163 + // Object literal stack depth for object literal - not necessarily top if property is a tree 31.164 private int objectLiteralStackDepth = -1; 31.165 // The line number at the continuation point 31.166 private int lineNumber; 31.167 @@ -5308,7 +5305,7 @@ 31.168 } 31.169 31.170 private ContinuationInfo getContinuationInfo() { 31.171 - return fnIdToContinuationInfo.get(lc.getCurrentFunction().getId()); 31.172 + return continuationInfo; 31.173 } 31.174 31.175 private void generateContinuationHandler() { 31.176 @@ -5396,7 +5393,7 @@ 31.177 method.load(lvarTypes.get(slot), slot); 31.178 method.convert(stackTypes[i]); 31.179 // stack: s0=object literal being initialized 31.180 - // change map of s0 so that the property we are initilizing when we failed 31.181 + // change map of s0 so that the property we are initializing when we failed 31.182 // is now ci.returnValueType 31.183 if (i == objectLiteralStackDepth) { 31.184 method.dup();
32.1 --- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java Thu Sep 24 10:00:42 2015 -0700 32.2 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java Thu Sep 24 10:09:56 2015 -0700 32.3 @@ -25,34 +25,21 @@ 32.4 32.5 package jdk.nashorn.internal.codegen; 32.6 32.7 -import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BUILTINS_TRANSFORMED; 32.8 -import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BYTECODE_GENERATED; 32.9 -import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BYTECODE_INSTALLED; 32.10 -import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.CONSTANT_FOLDED; 32.11 -import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.INITIALIZED; 32.12 -import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.LOCAL_VARIABLE_TYPES_CALCULATED; 32.13 -import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.LOWERED; 32.14 -import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.OPTIMISTIC_TYPES_ASSIGNED; 32.15 -import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.PARSED; 32.16 -import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SCOPE_DEPTHS_COMPUTED; 32.17 -import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SPLIT; 32.18 -import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SYMBOLS_ASSIGNED; 32.19 import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote; 32.20 32.21 import java.io.PrintWriter; 32.22 -import java.util.EnumSet; 32.23 import java.util.HashMap; 32.24 import java.util.LinkedHashMap; 32.25 import java.util.Map; 32.26 import java.util.Map.Entry; 32.27 import java.util.Set; 32.28 -import jdk.nashorn.internal.AssertsEnabled; 32.29 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; 32.30 +import jdk.nashorn.internal.ir.Block; 32.31 import jdk.nashorn.internal.ir.FunctionNode; 32.32 -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 32.33 import jdk.nashorn.internal.ir.LexicalContext; 32.34 import jdk.nashorn.internal.ir.LiteralNode; 32.35 import jdk.nashorn.internal.ir.Node; 32.36 +import jdk.nashorn.internal.ir.Symbol; 32.37 import jdk.nashorn.internal.ir.debug.ASTWriter; 32.38 import jdk.nashorn.internal.ir.debug.PrintVisitor; 32.39 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 32.40 @@ -65,15 +52,9 @@ 32.41 * A compilation phase is a step in the processes of turning a JavaScript 32.42 * FunctionNode into bytecode. It has an optional return value. 32.43 */ 32.44 -enum CompilationPhase { 32.45 - /** 32.46 - * Constant folding pass Simple constant folding that will make elementary 32.47 - * constructs go away 32.48 - */ 32.49 - CONSTANT_FOLDING_PHASE( 32.50 - EnumSet.of( 32.51 - INITIALIZED, 32.52 - PARSED)) { 32.53 +abstract class CompilationPhase { 32.54 + 32.55 + private static final class ConstantFoldingPhase extends CompilationPhase { 32.56 @Override 32.57 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.58 return transformFunction(fn, new FoldConstants(compiler)); 32.59 @@ -83,20 +64,15 @@ 32.60 public String toString() { 32.61 return "'Constant Folding'"; 32.62 } 32.63 - }, 32.64 + } 32.65 32.66 /** 32.67 - * Lower (Control flow pass) Finalizes the control flow. Clones blocks for 32.68 - * finally constructs and similar things. Establishes termination criteria 32.69 - * for nodes Guarantee return instructions to method making sure control 32.70 - * flow cannot fall off the end. Replacing high level nodes with lower such 32.71 - * as runtime nodes where applicable. 32.72 + * Constant folding pass Simple constant folding that will make elementary 32.73 + * constructs go away 32.74 */ 32.75 - LOWERING_PHASE( 32.76 - EnumSet.of( 32.77 - INITIALIZED, 32.78 - PARSED, 32.79 - CONSTANT_FOLDED)) { 32.80 + static final CompilationPhase CONSTANT_FOLDING_PHASE = new ConstantFoldingPhase(); 32.81 + 32.82 + private static final class LoweringPhase extends CompilationPhase { 32.83 @Override 32.84 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.85 return transformFunction(fn, new Lower(compiler)); 32.86 @@ -106,42 +82,35 @@ 32.87 public String toString() { 32.88 return "'Control Flow Lowering'"; 32.89 } 32.90 - }, 32.91 + } 32.92 32.93 /** 32.94 - * Phase used only when doing optimistic code generation. It assigns all potentially 32.95 - * optimistic ops a program point so that an UnwarrantedException knows from where 32.96 - * a guess went wrong when creating the continuation to roll back this execution 32.97 + * Lower (Control flow pass) Finalizes the control flow. Clones blocks for 32.98 + * finally constructs and similar things. Establishes termination criteria 32.99 + * for nodes Guarantee return instructions to method making sure control 32.100 + * flow cannot fall off the end. Replacing high level nodes with lower such 32.101 + * as runtime nodes where applicable. 32.102 */ 32.103 - TRANSFORM_BUILTINS_PHASE( 32.104 - EnumSet.of( 32.105 - INITIALIZED, 32.106 - PARSED, 32.107 - CONSTANT_FOLDED, 32.108 - LOWERED)) { 32.109 - //we only do this if we have a param type map, otherwise this is not a specialized recompile 32.110 + static final CompilationPhase LOWERING_PHASE = new LoweringPhase(); 32.111 + 32.112 + private static final class ApplySpecializationPhase extends CompilationPhase { 32.113 @Override 32.114 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.115 - return setStates(transformFunction(fn, new ApplySpecialization(compiler)), BUILTINS_TRANSFORMED); 32.116 + return transformFunction(fn, new ApplySpecialization(compiler)); 32.117 } 32.118 32.119 @Override 32.120 public String toString() { 32.121 return "'Builtin Replacement'"; 32.122 } 32.123 - }, 32.124 + }; 32.125 32.126 /** 32.127 - * Splitter Split the AST into several compile units based on a heuristic size calculation. 32.128 - * Split IR can lead to scope information being changed. 32.129 + * Phase used to transform Function.prototype.apply. 32.130 */ 32.131 - SPLITTING_PHASE( 32.132 - EnumSet.of( 32.133 - INITIALIZED, 32.134 - PARSED, 32.135 - CONSTANT_FOLDED, 32.136 - LOWERED, 32.137 - BUILTINS_TRANSFORMED)) { 32.138 + static final CompilationPhase APPLY_SPECIALIZATION_PHASE = new ApplySpecializationPhase(); 32.139 + 32.140 + private static final class SplittingPhase extends CompilationPhase { 32.141 @Override 32.142 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.143 final CompileUnit outermostCompileUnit = compiler.addCompileUnit(0L); 32.144 @@ -168,16 +137,15 @@ 32.145 public String toString() { 32.146 return "'Code Splitting'"; 32.147 } 32.148 - }, 32.149 + }; 32.150 32.151 - PROGRAM_POINT_PHASE( 32.152 - EnumSet.of( 32.153 - INITIALIZED, 32.154 - PARSED, 32.155 - CONSTANT_FOLDED, 32.156 - LOWERED, 32.157 - BUILTINS_TRANSFORMED, 32.158 - SPLIT)) { 32.159 + /** 32.160 + * Splitter Split the AST into several compile units based on a heuristic size calculation. 32.161 + * Split IR can lead to scope information being changed. 32.162 + */ 32.163 + static final CompilationPhase SPLITTING_PHASE = new SplittingPhase(); 32.164 + 32.165 + private static final class ProgramPointPhase extends CompilationPhase { 32.166 @Override 32.167 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.168 return transformFunction(fn, new ProgramPoints()); 32.169 @@ -187,43 +155,34 @@ 32.170 public String toString() { 32.171 return "'Program Point Calculation'"; 32.172 } 32.173 - }, 32.174 + }; 32.175 32.176 - SERIALIZE_SPLIT_PHASE( 32.177 - EnumSet.of( 32.178 - INITIALIZED, 32.179 - PARSED, 32.180 - CONSTANT_FOLDED, 32.181 - LOWERED, 32.182 - BUILTINS_TRANSFORMED, 32.183 - SPLIT)) { 32.184 + static final CompilationPhase PROGRAM_POINT_PHASE = new ProgramPointPhase(); 32.185 + 32.186 + private static final class CacheAstPhase extends CompilationPhase { 32.187 @Override 32.188 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.189 - return transformFunction(fn, new NodeVisitor<LexicalContext>(new LexicalContext()) { 32.190 - @Override 32.191 - public boolean enterFunctionNode(final FunctionNode functionNode) { 32.192 - if (functionNode.isSplit()) { 32.193 - compiler.serializeAst(functionNode); 32.194 - } 32.195 - return true; 32.196 - } 32.197 - }); 32.198 + if (!compiler.isOnDemandCompilation()) { 32.199 + // Only do this on initial preprocessing of the source code. For on-demand compilations from 32.200 + // source, FindScopeDepths#leaveFunctionNode() calls data.setCachedAst() for the sole function 32.201 + // being compiled. 32.202 + transformFunction(fn, new CacheAst(compiler)); 32.203 + } 32.204 + // NOTE: we're returning the original fn as we have destructively modified the cached functions by 32.205 + // removing their bodies. This step is associating FunctionNode objects with 32.206 + // RecompilableScriptFunctionData; it's not really modifying the AST. 32.207 + return fn; 32.208 } 32.209 32.210 @Override 32.211 public String toString() { 32.212 - return "'Serialize Split Functions'"; 32.213 + return "'Cache ASTs'"; 32.214 } 32.215 - }, 32.216 + }; 32.217 32.218 - SYMBOL_ASSIGNMENT_PHASE( 32.219 - EnumSet.of( 32.220 - INITIALIZED, 32.221 - PARSED, 32.222 - CONSTANT_FOLDED, 32.223 - LOWERED, 32.224 - BUILTINS_TRANSFORMED, 32.225 - SPLIT)) { 32.226 + static final CompilationPhase CACHE_AST_PHASE = new CacheAstPhase(); 32.227 + 32.228 + private static final class SymbolAssignmentPhase extends CompilationPhase { 32.229 @Override 32.230 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.231 return transformFunction(fn, new AssignSymbols(compiler)); 32.232 @@ -233,17 +192,11 @@ 32.233 public String toString() { 32.234 return "'Symbol Assignment'"; 32.235 } 32.236 - }, 32.237 + }; 32.238 32.239 - SCOPE_DEPTH_COMPUTATION_PHASE( 32.240 - EnumSet.of( 32.241 - INITIALIZED, 32.242 - PARSED, 32.243 - CONSTANT_FOLDED, 32.244 - LOWERED, 32.245 - BUILTINS_TRANSFORMED, 32.246 - SPLIT, 32.247 - SYMBOLS_ASSIGNED)) { 32.248 + static final CompilationPhase SYMBOL_ASSIGNMENT_PHASE = new SymbolAssignmentPhase(); 32.249 + 32.250 + private static final class ScopeDepthComputationPhase extends CompilationPhase { 32.251 @Override 32.252 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.253 return transformFunction(fn, new FindScopeDepths(compiler)); 32.254 @@ -253,43 +206,66 @@ 32.255 public String toString() { 32.256 return "'Scope Depth Computation'"; 32.257 } 32.258 - }, 32.259 + }; 32.260 32.261 - OPTIMISTIC_TYPE_ASSIGNMENT_PHASE( 32.262 - EnumSet.of( 32.263 - INITIALIZED, 32.264 - PARSED, 32.265 - CONSTANT_FOLDED, 32.266 - LOWERED, 32.267 - BUILTINS_TRANSFORMED, 32.268 - SPLIT, 32.269 - SYMBOLS_ASSIGNED, 32.270 - SCOPE_DEPTHS_COMPUTED)) { 32.271 + static final CompilationPhase SCOPE_DEPTH_COMPUTATION_PHASE = new ScopeDepthComputationPhase(); 32.272 + 32.273 + private static final class DeclareLocalSymbolsPhase extends CompilationPhase { 32.274 + @Override 32.275 + FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.276 + // It's not necessary to guard the marking of symbols as locals with this "if" condition for 32.277 + // correctness, it's just an optimization -- runtime type calculation is not used when the compilation 32.278 + // is not an on-demand optimistic compilation, so we can skip locals marking then. 32.279 + if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) { 32.280 + fn.getBody().accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 32.281 + @Override 32.282 + public boolean enterFunctionNode(final FunctionNode functionNode) { 32.283 + // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand 32.284 + // compilation, and we're skipping parsing the function bodies for nested functions, this 32.285 + // basically only means their parameters. It'd be enough to mistakenly declare to be a local a 32.286 + // symbol in the outer function named the same as one of the parameters, though. 32.287 + return false; 32.288 + }; 32.289 + @Override 32.290 + public boolean enterBlock(final Block block) { 32.291 + for (final Symbol symbol: block.getSymbols()) { 32.292 + if (!symbol.isScope()) { 32.293 + compiler.declareLocalSymbol(symbol.getName()); 32.294 + } 32.295 + } 32.296 + return true; 32.297 + }; 32.298 + }); 32.299 + } 32.300 + return fn; 32.301 + } 32.302 + 32.303 + @Override 32.304 + public String toString() { 32.305 + return "'Local Symbols Declaration'"; 32.306 + } 32.307 + }; 32.308 + 32.309 + static final CompilationPhase DECLARE_LOCAL_SYMBOLS_PHASE = new DeclareLocalSymbolsPhase(); 32.310 + 32.311 + private static final class OptimisticTypeAssignmentPhase extends CompilationPhase { 32.312 @Override 32.313 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.314 if (compiler.useOptimisticTypes()) { 32.315 return transformFunction(fn, new OptimisticTypesCalculator(compiler)); 32.316 } 32.317 - return setStates(fn, OPTIMISTIC_TYPES_ASSIGNED); 32.318 + return fn; 32.319 } 32.320 32.321 @Override 32.322 public String toString() { 32.323 return "'Optimistic Type Assignment'"; 32.324 } 32.325 - }, 32.326 + } 32.327 32.328 - LOCAL_VARIABLE_TYPE_CALCULATION_PHASE( 32.329 - EnumSet.of( 32.330 - INITIALIZED, 32.331 - PARSED, 32.332 - CONSTANT_FOLDED, 32.333 - LOWERED, 32.334 - BUILTINS_TRANSFORMED, 32.335 - SPLIT, 32.336 - SYMBOLS_ASSIGNED, 32.337 - SCOPE_DEPTHS_COMPUTED, 32.338 - OPTIMISTIC_TYPES_ASSIGNED)) { 32.339 + static final CompilationPhase OPTIMISTIC_TYPE_ASSIGNMENT_PHASE = new OptimisticTypeAssignmentPhase(); 32.340 + 32.341 + private static final class LocalVariableTypeCalculationPhase extends CompilationPhase { 32.342 @Override 32.343 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.344 final FunctionNode newFunctionNode = transformFunction(fn, new LocalVariableTypesCalculator(compiler)); 32.345 @@ -314,25 +290,11 @@ 32.346 public String toString() { 32.347 return "'Local Variable Type Calculation'"; 32.348 } 32.349 - }, 32.350 + }; 32.351 32.352 + static final CompilationPhase LOCAL_VARIABLE_TYPE_CALCULATION_PHASE = new LocalVariableTypeCalculationPhase(); 32.353 32.354 - /** 32.355 - * Reuse compile units, if they are already present. We are using the same compiler 32.356 - * to recompile stuff 32.357 - */ 32.358 - REUSE_COMPILE_UNITS_PHASE( 32.359 - EnumSet.of( 32.360 - INITIALIZED, 32.361 - PARSED, 32.362 - CONSTANT_FOLDED, 32.363 - LOWERED, 32.364 - BUILTINS_TRANSFORMED, 32.365 - SPLIT, 32.366 - SYMBOLS_ASSIGNED, 32.367 - SCOPE_DEPTHS_COMPUTED, 32.368 - OPTIMISTIC_TYPES_ASSIGNED, 32.369 - LOCAL_VARIABLE_TYPES_CALCULATED)) { 32.370 + private static final class ReuseCompileUnitsPhase extends CompilationPhase { 32.371 @Override 32.372 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.373 assert phases.isRestOfCompilation() : "reuse compile units currently only used for Rest-Of methods"; 32.374 @@ -380,16 +342,15 @@ 32.375 public String toString() { 32.376 return "'Reuse Compile Units'"; 32.377 } 32.378 - }, 32.379 + } 32.380 32.381 - REINITIALIZE_SERIALIZED( 32.382 - EnumSet.of( 32.383 - INITIALIZED, 32.384 - PARSED, 32.385 - CONSTANT_FOLDED, 32.386 - LOWERED, 32.387 - BUILTINS_TRANSFORMED, 32.388 - SPLIT)) { 32.389 + /** 32.390 + * Reuse compile units, if they are already present. We are using the same compiler 32.391 + * to recompile stuff 32.392 + */ 32.393 + static final CompilationPhase REUSE_COMPILE_UNITS_PHASE = new ReuseCompileUnitsPhase(); 32.394 + 32.395 + private static final class ReinitializeCachedPhase extends CompilationPhase { 32.396 @Override 32.397 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.398 final Set<CompileUnit> unitSet = CompileUnit.createCompileUnitSet(); 32.399 @@ -430,28 +391,13 @@ 32.400 32.401 @Override 32.402 public String toString() { 32.403 - return "'Deserialize'"; 32.404 + return "'Reinitialize cached'"; 32.405 } 32.406 - }, 32.407 + } 32.408 32.409 - /** 32.410 - * Bytecode generation: 32.411 - * 32.412 - * Generate the byte code class(es) resulting from the compiled FunctionNode 32.413 - */ 32.414 - BYTECODE_GENERATION_PHASE( 32.415 - EnumSet.of( 32.416 - INITIALIZED, 32.417 - PARSED, 32.418 - CONSTANT_FOLDED, 32.419 - LOWERED, 32.420 - BUILTINS_TRANSFORMED, 32.421 - SPLIT, 32.422 - SYMBOLS_ASSIGNED, 32.423 - SCOPE_DEPTHS_COMPUTED, 32.424 - OPTIMISTIC_TYPES_ASSIGNED, 32.425 - LOCAL_VARIABLE_TYPES_CALCULATED)) { 32.426 + static final CompilationPhase REINITIALIZE_CACHED = new ReinitializeCachedPhase(); 32.427 32.428 + private static final class BytecodeGenerationPhase extends CompilationPhase { 32.429 @Override 32.430 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.431 final ScriptEnvironment senv = compiler.getScriptEnvironment(); 32.432 @@ -469,7 +415,7 @@ 32.433 try { 32.434 // Explicitly set BYTECODE_GENERATED here; it can not be set in case of skipping codegen for :program 32.435 // in the lazy + optimistic world. See CodeGenerator.skipFunction(). 32.436 - newFunctionNode = transformFunction(newFunctionNode, codegen).setState(null, BYTECODE_GENERATED); 32.437 + newFunctionNode = transformFunction(newFunctionNode, codegen); 32.438 codegen.generateScopeCalls(); 32.439 } catch (final VerifyError e) { 32.440 if (senv._verify_code || senv._print_code) { 32.441 @@ -517,22 +463,16 @@ 32.442 public String toString() { 32.443 return "'Bytecode Generation'"; 32.444 } 32.445 - }, 32.446 + } 32.447 32.448 - INSTALL_PHASE( 32.449 - EnumSet.of( 32.450 - INITIALIZED, 32.451 - PARSED, 32.452 - CONSTANT_FOLDED, 32.453 - LOWERED, 32.454 - BUILTINS_TRANSFORMED, 32.455 - SPLIT, 32.456 - SYMBOLS_ASSIGNED, 32.457 - SCOPE_DEPTHS_COMPUTED, 32.458 - OPTIMISTIC_TYPES_ASSIGNED, 32.459 - LOCAL_VARIABLE_TYPES_CALCULATED, 32.460 - BYTECODE_GENERATED)) { 32.461 + /** 32.462 + * Bytecode generation: 32.463 + * 32.464 + * Generate the byte code class(es) resulting from the compiled FunctionNode 32.465 + */ 32.466 + static final CompilationPhase BYTECODE_GENERATION_PHASE = new BytecodeGenerationPhase(); 32.467 32.468 + private static final class InstallPhase extends CompilationPhase { 32.469 @Override 32.470 FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 32.471 final DebugLogger log = compiler.getLogger(); 32.472 @@ -600,18 +540,16 @@ 32.473 log.fine(sb.toString()); 32.474 } 32.475 32.476 - return setStates(fn.setRootClass(null, rootClass), BYTECODE_INSTALLED); 32.477 + return fn.setRootClass(null, rootClass); 32.478 } 32.479 32.480 @Override 32.481 public String toString() { 32.482 return "'Class Installation'"; 32.483 } 32.484 + } 32.485 32.486 - }; 32.487 - 32.488 - /** pre conditions required for function node to which this transform is to be applied */ 32.489 - private final EnumSet<CompilationState> pre; 32.490 + static final CompilationPhase INSTALL_PHASE = new InstallPhase(); 32.491 32.492 /** start time of transform - used for timing, see {@link jdk.nashorn.internal.runtime.Timing} */ 32.493 private long startTime; 32.494 @@ -622,21 +560,7 @@ 32.495 /** boolean that is true upon transform completion */ 32.496 private boolean isFinished; 32.497 32.498 - private CompilationPhase(final EnumSet<CompilationState> pre) { 32.499 - this.pre = pre; 32.500 - } 32.501 - 32.502 - private static FunctionNode setStates(final FunctionNode functionNode, final CompilationState state) { 32.503 - if (!AssertsEnabled.assertsEnabled()) { 32.504 - return functionNode; 32.505 - } 32.506 - return transformFunction(functionNode, new NodeVisitor<LexicalContext>(new LexicalContext()) { 32.507 - @Override 32.508 - public Node leaveFunctionNode(final FunctionNode fn) { 32.509 - return fn.setState(lc, state); 32.510 - } 32.511 - }); 32.512 - } 32.513 + private CompilationPhase() {} 32.514 32.515 /** 32.516 * Start a compilation phase 32.517 @@ -646,23 +570,7 @@ 32.518 */ 32.519 protected FunctionNode begin(final Compiler compiler, final FunctionNode functionNode) { 32.520 compiler.getLogger().indent(); 32.521 - 32.522 - assert pre != null; 32.523 - 32.524 - if (!functionNode.hasState(pre)) { 32.525 - final StringBuilder sb = new StringBuilder("Compilation phase "); 32.526 - sb.append(this). 32.527 - append(" is not applicable to "). 32.528 - append(quote(functionNode.getName())). 32.529 - append("\n\tFunctionNode state = "). 32.530 - append(functionNode.getState()). 32.531 - append("\n\tRequired state = "). 32.532 - append(this.pre); 32.533 - 32.534 - throw new CompilationException(sb.toString()); 32.535 - } 32.536 - 32.537 - startTime = System.nanoTime(); 32.538 + startTime = System.nanoTime(); 32.539 32.540 return functionNode; 32.541 } 32.542 @@ -697,7 +605,7 @@ 32.543 abstract FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode functionNode) throws CompilationException; 32.544 32.545 /** 32.546 - * Apply a transform to a function node, returning the transfored function node. If the transform is not 32.547 + * Apply a transform to a function node, returning the transformed function node. If the transform is not 32.548 * applicable, an exception is thrown. Every transform requires the function to have a certain number of 32.549 * states to operate. It can have more states set, but not fewer. The state list, i.e. the constructor 32.550 * arguments to any of the CompilationPhase enum entries, is a set of REQUIRED states.
33.1 --- a/src/jdk/nashorn/internal/codegen/Compiler.java Thu Sep 24 10:00:42 2015 -0700 33.2 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java Thu Sep 24 10:09:56 2015 -0700 33.3 @@ -160,42 +160,40 @@ 33.4 */ 33.5 private static final int COMPILE_UNIT_NAME_BUFFER_SIZE = 32; 33.6 33.7 - private final Map<Integer, byte[]> serializedAsts = new HashMap<>(); 33.8 - 33.9 /** 33.10 * Compilation phases that a compilation goes through 33.11 */ 33.12 public static class CompilationPhases implements Iterable<CompilationPhase> { 33.13 33.14 /** 33.15 - * Singleton that describes compilation up to the phase where a function can be serialized. 33.16 + * Singleton that describes compilation up to the phase where a function can be cached. 33.17 */ 33.18 - private final static CompilationPhases COMPILE_UPTO_SERIALIZABLE = new CompilationPhases( 33.19 + private final static CompilationPhases COMPILE_UPTO_CACHED = new CompilationPhases( 33.20 "Common initial phases", 33.21 CompilationPhase.CONSTANT_FOLDING_PHASE, 33.22 CompilationPhase.LOWERING_PHASE, 33.23 - CompilationPhase.TRANSFORM_BUILTINS_PHASE, 33.24 + CompilationPhase.APPLY_SPECIALIZATION_PHASE, 33.25 CompilationPhase.SPLITTING_PHASE, 33.26 CompilationPhase.PROGRAM_POINT_PHASE, 33.27 - CompilationPhase.SERIALIZE_SPLIT_PHASE 33.28 + CompilationPhase.SYMBOL_ASSIGNMENT_PHASE, 33.29 + CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE, 33.30 + CompilationPhase.CACHE_AST_PHASE 33.31 ); 33.32 33.33 - private final static CompilationPhases COMPILE_SERIALIZABLE_UPTO_BYTECODE = new CompilationPhases( 33.34 + private final static CompilationPhases COMPILE_CACHED_UPTO_BYTECODE = new CompilationPhases( 33.35 "After common phases, before bytecode generator", 33.36 - CompilationPhase.SYMBOL_ASSIGNMENT_PHASE, 33.37 - CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE, 33.38 CompilationPhase.OPTIMISTIC_TYPE_ASSIGNMENT_PHASE, 33.39 CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE 33.40 ); 33.41 33.42 /** 33.43 - * Singleton that describes additional steps to be taken after deserializing, all the way up to (but not 33.44 - * including) generating and installing code. 33.45 + * Singleton that describes additional steps to be taken after retrieving a cached function, all the 33.46 + * way up to (but not including) generating and installing code. 33.47 */ 33.48 - public final static CompilationPhases RECOMPILE_SERIALIZED_UPTO_BYTECODE = new CompilationPhases( 33.49 - "Recompile serialized function up to bytecode", 33.50 - CompilationPhase.REINITIALIZE_SERIALIZED, 33.51 - COMPILE_SERIALIZABLE_UPTO_BYTECODE 33.52 + public final static CompilationPhases RECOMPILE_CACHED_UPTO_BYTECODE = new CompilationPhases( 33.53 + "Recompile cached function up to bytecode", 33.54 + CompilationPhase.REINITIALIZE_CACHED, 33.55 + COMPILE_CACHED_UPTO_BYTECODE 33.56 ); 33.57 33.58 /** 33.59 @@ -211,8 +209,8 @@ 33.60 /** Singleton that describes compilation up to the CodeGenerator, but not actually generating code */ 33.61 public final static CompilationPhases COMPILE_UPTO_BYTECODE = new CompilationPhases( 33.62 "Compile upto bytecode", 33.63 - COMPILE_UPTO_SERIALIZABLE, 33.64 - COMPILE_SERIALIZABLE_UPTO_BYTECODE); 33.65 + COMPILE_UPTO_CACHED, 33.66 + COMPILE_CACHED_UPTO_BYTECODE); 33.67 33.68 /** Singleton that describes a standard eager compilation, but no installation, for example used by --compile-only */ 33.69 public final static CompilationPhases COMPILE_ALL_NO_INSTALL = new CompilationPhases( 33.70 @@ -227,9 +225,9 @@ 33.71 GENERATE_BYTECODE_AND_INSTALL); 33.72 33.73 /** Singleton that describes a full compilation - this includes code installation - from serialized state*/ 33.74 - public final static CompilationPhases COMPILE_ALL_SERIALIZED = new CompilationPhases( 33.75 + public final static CompilationPhases COMPILE_ALL_CACHED = new CompilationPhases( 33.76 "Eager compilation from serializaed state", 33.77 - RECOMPILE_SERIALIZED_UPTO_BYTECODE, 33.78 + RECOMPILE_CACHED_UPTO_BYTECODE, 33.79 GENERATE_BYTECODE_AND_INSTALL); 33.80 33.81 /** 33.82 @@ -248,9 +246,9 @@ 33.83 GENERATE_BYTECODE_AND_INSTALL_RESTOF); 33.84 33.85 /** Compile from serialized for a rest of method */ 33.86 - public final static CompilationPhases COMPILE_SERIALIZED_RESTOF = new CompilationPhases( 33.87 + public final static CompilationPhases COMPILE_CACHED_RESTOF = new CompilationPhases( 33.88 "Compile serialized, rest of", 33.89 - RECOMPILE_SERIALIZED_UPTO_BYTECODE, 33.90 + RECOMPILE_CACHED_UPTO_BYTECODE, 33.91 GENERATE_BYTECODE_AND_INSTALL_RESTOF); 33.92 33.93 private final List<CompilationPhase> phases; 33.94 @@ -313,7 +311,7 @@ 33.95 } 33.96 33.97 boolean isRestOfCompilation() { 33.98 - return this == COMPILE_ALL_RESTOF || this == GENERATE_BYTECODE_AND_INSTALL_RESTOF || this == COMPILE_SERIALIZED_RESTOF; 33.99 + return this == COMPILE_ALL_RESTOF || this == GENERATE_BYTECODE_AND_INSTALL_RESTOF || this == COMPILE_CACHED_RESTOF; 33.100 } 33.101 33.102 String getDesc() { 33.103 @@ -766,14 +764,6 @@ 33.104 compileUnits.addAll(newUnits); 33.105 } 33.106 33.107 - void serializeAst(final FunctionNode fn) { 33.108 - serializedAsts.put(fn.getId(), AstSerializer.serialize(fn)); 33.109 - } 33.110 - 33.111 - byte[] removeSerializedAst(final int fnId) { 33.112 - return serializedAsts.remove(fnId); 33.113 - } 33.114 - 33.115 CompileUnit findUnit(final long weight) { 33.116 for (final CompileUnit unit : compileUnits) { 33.117 if (unit.canHold(weight)) {
34.1 --- a/src/jdk/nashorn/internal/codegen/CompilerConstants.java Thu Sep 24 10:00:42 2015 -0700 34.2 +++ b/src/jdk/nashorn/internal/codegen/CompilerConstants.java Thu Sep 24 10:09:56 2015 -0700 34.3 @@ -192,7 +192,7 @@ 34.4 private static Set<String> symbolNames; 34.5 34.6 /** 34.7 - * Prefix used for internal methods generated in script clases. 34.8 + * Prefix used for internal methods generated in script classes. 34.9 */ 34.10 private static final String INTERNAL_METHOD_PREFIX = ":"; 34.11 34.12 @@ -225,7 +225,7 @@ 34.13 } 34.14 34.15 /** 34.16 - * Check whether a name is that of a reserved compiler constnat 34.17 + * Check whether a name is that of a reserved compiler constant 34.18 * @param name name 34.19 * @return true if compiler constant name 34.20 */
35.1 --- a/src/jdk/nashorn/internal/codegen/FindScopeDepths.java Thu Sep 24 10:00:42 2015 -0700 35.2 +++ b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java Thu Sep 24 10:09:56 2015 -0700 35.3 @@ -34,7 +34,6 @@ 35.4 import java.util.Set; 35.5 import jdk.nashorn.internal.ir.Block; 35.6 import jdk.nashorn.internal.ir.FunctionNode; 35.7 -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 35.8 import jdk.nashorn.internal.ir.IdentNode; 35.9 import jdk.nashorn.internal.ir.LexicalContext; 35.10 import jdk.nashorn.internal.ir.Node; 35.11 @@ -182,14 +181,16 @@ 35.12 @Override 35.13 public Node leaveFunctionNode(final FunctionNode functionNode) { 35.14 final String name = functionNode.getName(); 35.15 - FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.SCOPE_DEPTHS_COMPUTED); 35.16 - 35.17 + FunctionNode newFunctionNode = functionNode; 35.18 if (compiler.isOnDemandCompilation()) { 35.19 final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(newFunctionNode.getId()); 35.20 if (data.inDynamicContext()) { 35.21 log.fine("Reviving scriptfunction ", quote(name), " as defined in previous (now lost) dynamic scope."); 35.22 newFunctionNode = newFunctionNode.setInDynamicContext(lc); 35.23 } 35.24 + if (newFunctionNode == lc.getOutermostFunction() && !newFunctionNode.hasApplyToCallSpecialization()) { 35.25 + data.setCachedAst(newFunctionNode); 35.26 + } 35.27 return newFunctionNode; 35.28 } 35.29 35.30 @@ -210,8 +211,7 @@ 35.31 ObjectClassGenerator.createAllocationStrategy(newFunctionNode.getThisProperties(), compiler.getContext().useDualFields()), 35.32 nestedFunctions, 35.33 externalSymbolDepths.get(fnId), 35.34 - internalSymbols.get(fnId), 35.35 - compiler.removeSerializedAst(fnId)); 35.36 + internalSymbols.get(fnId)); 35.37 35.38 if (lc.getOutermostFunction() != newFunctionNode) { 35.39 final FunctionNode parentFn = lc.getParentFunction(newFunctionNode);
36.1 --- a/src/jdk/nashorn/internal/codegen/FoldConstants.java Thu Sep 24 10:00:42 2015 -0700 36.2 +++ b/src/jdk/nashorn/internal/codegen/FoldConstants.java Thu Sep 24 10:09:56 2015 -0700 36.3 @@ -37,7 +37,6 @@ 36.4 import jdk.nashorn.internal.ir.EmptyNode; 36.5 import jdk.nashorn.internal.ir.Expression; 36.6 import jdk.nashorn.internal.ir.FunctionNode; 36.7 -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 36.8 import jdk.nashorn.internal.ir.IfNode; 36.9 import jdk.nashorn.internal.ir.LexicalContext; 36.10 import jdk.nashorn.internal.ir.LiteralNode; 36.11 @@ -101,7 +100,7 @@ 36.12 36.13 @Override 36.14 public Node leaveFunctionNode(final FunctionNode functionNode) { 36.15 - return functionNode.setState(lc, CompilationState.CONSTANT_FOLDED); 36.16 + return functionNode; 36.17 } 36.18 36.19 @Override
37.1 --- a/src/jdk/nashorn/internal/codegen/Label.java Thu Sep 24 10:00:42 2015 -0700 37.2 +++ b/src/jdk/nashorn/internal/codegen/Label.java Thu Sep 24 10:09:56 2015 -0700 37.3 @@ -447,7 +447,7 @@ 37.4 undefineLocalVariables(liveLocalCount, true); 37.5 // Temporaries are promoted 37.6 firstTemp = liveLocalCount; 37.7 - // No trailing undefineds 37.8 + // No trailing undefined values 37.9 localVariableTypes.subList(firstTemp, localVariableTypes.size()).clear(); 37.10 assert symbolBoundary.length() == firstTemp; 37.11 // Generalize all reference types to Object, and promote boolean to int 37.12 @@ -497,7 +497,7 @@ 37.13 private transient Label.Stack stack; 37.14 37.15 /** ASM representation of this label */ 37.16 - private jdk.internal.org.objectweb.asm.Label label; 37.17 + private transient jdk.internal.org.objectweb.asm.Label label; 37.18 37.19 /** Id for debugging purposes, remove if footprint becomes unmanageable */ 37.20 private final int id;
38.1 --- a/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Thu Sep 24 10:00:42 2015 -0700 38.2 +++ b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Thu Sep 24 10:09:56 2015 -0700 38.3 @@ -54,7 +54,6 @@ 38.4 import jdk.nashorn.internal.ir.ExpressionStatement; 38.5 import jdk.nashorn.internal.ir.ForNode; 38.6 import jdk.nashorn.internal.ir.FunctionNode; 38.7 -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 38.8 import jdk.nashorn.internal.ir.GetSplitState; 38.9 import jdk.nashorn.internal.ir.IdentNode; 38.10 import jdk.nashorn.internal.ir.IfNode; 38.11 @@ -1478,7 +1477,6 @@ 38.12 newFunction = newFunction.setReturnType(lc, returnType); 38.13 38.14 38.15 - newFunction = newFunction.setState(lc, CompilationState.LOCAL_VARIABLE_TYPES_CALCULATED); 38.16 newFunction = newFunction.setParameters(lc, newFunction.visitParameters(applyChangesVisitor)); 38.17 return newFunction; 38.18 }
39.1 --- a/src/jdk/nashorn/internal/codegen/Lower.java Thu Sep 24 10:00:42 2015 -0700 39.2 +++ b/src/jdk/nashorn/internal/codegen/Lower.java Thu Sep 24 10:09:56 2015 -0700 39.3 @@ -51,7 +51,6 @@ 39.4 import jdk.nashorn.internal.ir.ExpressionStatement; 39.5 import jdk.nashorn.internal.ir.ForNode; 39.6 import jdk.nashorn.internal.ir.FunctionNode; 39.7 -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 39.8 import jdk.nashorn.internal.ir.IdentNode; 39.9 import jdk.nashorn.internal.ir.IfNode; 39.10 import jdk.nashorn.internal.ir.IndexNode; 39.11 @@ -266,7 +265,7 @@ 39.12 @Override 39.13 public Node leaveFunctionNode(final FunctionNode functionNode) { 39.14 log.info("END FunctionNode: ", functionNode.getName()); 39.15 - return functionNode.setState(lc, CompilationState.LOWERED); 39.16 + return functionNode; 39.17 } 39.18 39.19 @Override 39.20 @@ -511,7 +510,7 @@ 39.21 } 39.22 39.23 /* 39.24 - * create a new trynode 39.25 + * create a new try node 39.26 * if we have catches: 39.27 * 39.28 * try try 39.29 @@ -522,7 +521,7 @@ 39.30 * catchall 39.31 * rethrow 39.32 * 39.33 - * otheriwse 39.34 + * otherwise 39.35 * 39.36 * try try 39.37 * x x
40.1 --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java Thu Sep 24 10:00:42 2015 -0700 40.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java Thu Sep 24 10:09:56 2015 -0700 40.3 @@ -1159,7 +1159,7 @@ 40.4 /** 40.5 * Pop a value from the stack and store it in a variable denoted by the given symbol. The variable should be either 40.6 * a local variable, or a function parameter (and not a scoped variable). For local variables, this method will also 40.7 - * do the bookeeping of the local variable table as well as mark values in all alternative slots for the symbol as 40.8 + * do the bookkeeping of the local variable table as well as mark values in all alternative slots for the symbol as 40.9 * dead. In this regard it differs from {@link #storeHidden(Type, int)}. 40.10 * 40.11 * @param symbol the symbol to store into.
41.1 --- a/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Thu Sep 24 10:00:42 2015 -0700 41.2 +++ b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Thu Sep 24 10:09:56 2015 -0700 41.3 @@ -786,7 +786,7 @@ 41.4 * @param primitiveSetter primitive setter for the current type with an element of the current type 41.5 * @param objectSetter the object setter 41.6 * 41.7 - * @return method handle that checks if the element to be set is of the currenttype, even though it's boxed 41.8 + * @return method handle that checks if the element to be set is of the current type, even though it's boxed 41.9 * and instead of using the generic object setter, that would blow up the type and invalidate the map, 41.10 * unbox it and call the primitive setter instead 41.11 */
42.1 --- a/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java Thu Sep 24 10:00:42 2015 -0700 42.2 +++ b/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java Thu Sep 24 10:09:56 2015 -0700 42.3 @@ -38,7 +38,6 @@ 42.4 import jdk.nashorn.internal.ir.ExpressionStatement; 42.5 import jdk.nashorn.internal.ir.ForNode; 42.6 import jdk.nashorn.internal.ir.FunctionNode; 42.7 -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 42.8 import jdk.nashorn.internal.ir.IdentNode; 42.9 import jdk.nashorn.internal.ir.IfNode; 42.10 import jdk.nashorn.internal.ir.IndexNode; 42.11 @@ -208,7 +207,7 @@ 42.12 @Override 42.13 public Node leaveFunctionNode(final FunctionNode functionNode) { 42.14 neverOptimistic.pop(); 42.15 - return functionNode.setState(lc, CompilationState.OPTIMISTIC_TYPES_ASSIGNED); 42.16 + return functionNode; 42.17 } 42.18 42.19 @Override
43.1 --- a/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java Thu Sep 24 10:00:42 2015 -0700 43.2 +++ b/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java Thu Sep 24 10:09:56 2015 -0700 43.3 @@ -29,7 +29,6 @@ 43.4 import java.util.List; 43.5 import jdk.nashorn.internal.ir.CompileUnitHolder; 43.6 import jdk.nashorn.internal.ir.FunctionNode; 43.7 -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 43.8 import jdk.nashorn.internal.ir.LexicalContext; 43.9 import jdk.nashorn.internal.ir.LiteralNode; 43.10 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 43.11 @@ -64,7 +63,7 @@ 43.12 43.13 @Override 43.14 public Node leaveFunctionNode(final FunctionNode node) { 43.15 - return node.setCompileUnit(lc, getExistingReplacement(node)).setState(lc, CompilationState.COMPILE_UNITS_REUSED); 43.16 + return node.setCompileUnit(lc, getExistingReplacement(node)); 43.17 } 43.18 43.19 @Override
44.1 --- a/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java Thu Sep 24 10:00:42 2015 -0700 44.2 +++ b/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java Thu Sep 24 10:09:56 2015 -0700 44.3 @@ -175,8 +175,7 @@ 44.4 FunctionNode.IS_ANONYMOUS | FunctionNode.USES_ANCESTOR_SCOPE | FunctionNode.IS_SPLIT 44.5 ) 44.6 .setBody(lc, body) 44.7 - .setCompileUnit(lc, splitNode.getCompileUnit()) 44.8 - .copyCompilationState(lc, originalFn); 44.9 + .setCompileUnit(lc, splitNode.getCompileUnit()); 44.10 44.11 // Call the function: 44.12 // either "(function () { ... }).call(this)"
45.1 --- a/src/jdk/nashorn/internal/codegen/Splitter.java Thu Sep 24 10:00:42 2015 -0700 45.2 +++ b/src/jdk/nashorn/internal/codegen/Splitter.java Thu Sep 24 10:09:56 2015 -0700 45.3 @@ -33,7 +33,6 @@ 45.4 import java.util.Map; 45.5 import jdk.nashorn.internal.ir.Block; 45.6 import jdk.nashorn.internal.ir.FunctionNode; 45.7 -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 45.8 import jdk.nashorn.internal.ir.LexicalContext; 45.9 import jdk.nashorn.internal.ir.LiteralNode; 45.10 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 45.11 @@ -158,7 +157,7 @@ 45.12 45.13 assert functionNode.getCompileUnit() != null; 45.14 45.15 - return functionNode.setState(null, CompilationState.SPLIT); 45.16 + return functionNode; 45.17 } 45.18 45.19 private static List<FunctionNode> directChildren(final FunctionNode functionNode) {
46.1 --- a/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java Thu Sep 24 10:00:42 2015 -0700 46.2 +++ b/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java Thu Sep 24 10:09:56 2015 -0700 46.3 @@ -36,7 +36,7 @@ 46.4 * The bytecode ops are coupled to a MethodVisitor from ASM for 46.5 * byte code generation. They know nothing about our MethodGenerator, 46.6 * which is the abstraction for working with Nashorn JS types 46.7 - * For exmaple, anything like "two or one slots" for a type, which 46.8 + * For example, anything like "two or one slots" for a type, which 46.9 * is represented in bytecode and ASM, is abstracted away in the 46.10 * MethodGenerator. There you just say "dup" or "store". 46.11 *
47.1 --- a/src/jdk/nashorn/internal/ir/Block.java Thu Sep 24 10:00:42 2015 -0700 47.2 +++ b/src/jdk/nashorn/internal/ir/Block.java Thu Sep 24 10:09:56 2015 -0700 47.3 @@ -130,11 +130,42 @@ 47.4 } 47.5 47.6 /** 47.7 - * Clear the symbols in the block. 47.8 - * TODO: make this immutable. 47.9 + * Returns true if this block defines any symbols. 47.10 + * @return true if this block defines any symbols. 47.11 */ 47.12 - public void clearSymbols() { 47.13 - symbols.clear(); 47.14 + public boolean hasSymbols() { 47.15 + return !symbols.isEmpty(); 47.16 + } 47.17 + 47.18 + /** 47.19 + * Replaces symbols defined in this block with different symbols. Used to ensure symbol tables are 47.20 + * immutable upon construction and have copy-on-write semantics. Note that this method only replaces the 47.21 + * symbols in the symbol table, it does not act on any contained AST nodes that might reference the symbols. 47.22 + * Those should be updated separately as this method is meant to be used as part of such an update pass. 47.23 + * @param lc the current lexical context 47.24 + * @param replacements the map of symbol replacements 47.25 + * @return a new block with replaced symbols, or this block if none of the replacements modified the symbol 47.26 + * table. 47.27 + */ 47.28 + public Block replaceSymbols(final LexicalContext lc, final Map<Symbol, Symbol> replacements) { 47.29 + if (symbols.isEmpty()) { 47.30 + return this; 47.31 + } 47.32 + final LinkedHashMap<String, Symbol> newSymbols = new LinkedHashMap<>(symbols); 47.33 + for (final Map.Entry<String, Symbol> entry: newSymbols.entrySet()) { 47.34 + final Symbol newSymbol = replacements.get(entry.getValue()); 47.35 + assert newSymbol != null : "Missing replacement for " + entry.getKey(); 47.36 + entry.setValue(newSymbol); 47.37 + } 47.38 + return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, newSymbols, conversion)); 47.39 + } 47.40 + 47.41 + /** 47.42 + * Returns a copy of this block with a shallow copy of the symbol table. 47.43 + * @return a copy of this block with a shallow copy of the symbol table. 47.44 + */ 47.45 + public Block copyWithNewSymbols() { 47.46 + return new Block(this, finish, statements, flags, new LinkedHashMap<>(symbols), conversion); 47.47 } 47.48 47.49 @Override 47.50 @@ -162,7 +193,7 @@ 47.51 * @return symbol iterator 47.52 */ 47.53 public List<Symbol> getSymbols() { 47.54 - return Collections.unmodifiableList(new ArrayList<>(symbols.values())); 47.55 + return symbols.isEmpty() ? Collections.<Symbol>emptyList() : Collections.unmodifiableList(new ArrayList<>(symbols.values())); 47.56 } 47.57 47.58 /** 47.59 @@ -326,10 +357,9 @@ 47.60 /** 47.61 * Add or overwrite an existing symbol in the block 47.62 * 47.63 - * @param lc get lexical context 47.64 * @param symbol symbol 47.65 */ 47.66 - public void putSymbol(final LexicalContext lc, final Symbol symbol) { 47.67 + public void putSymbol(final Symbol symbol) { 47.68 symbols.put(symbol.getName(), symbol); 47.69 } 47.70
48.1 --- a/src/jdk/nashorn/internal/ir/BlockLexicalContext.java Thu Sep 24 10:00:42 2015 -0700 48.2 +++ b/src/jdk/nashorn/internal/ir/BlockLexicalContext.java Thu Sep 24 10:09:56 2015 -0700 48.3 @@ -34,7 +34,7 @@ 48.4 * This is a subclass of lexical context used for filling 48.5 * blocks (and function nodes) with statements. When popping 48.6 * a block from the lexical context, any statements that have 48.7 - * been generated in it are commited to the block. This saves 48.8 + * been generated in it are committed to the block. This saves 48.9 * unnecessary object mutations and lexical context replacement 48.10 */ 48.11 public class BlockLexicalContext extends LexicalContext {
49.1 --- a/src/jdk/nashorn/internal/ir/ForNode.java Thu Sep 24 10:00:42 2015 -0700 49.2 +++ b/src/jdk/nashorn/internal/ir/ForNode.java Thu Sep 24 10:09:56 2015 -0700 49.3 @@ -43,7 +43,7 @@ 49.4 private final JoinPredecessorExpression modify; 49.5 49.6 /** Iterator symbol. */ 49.7 - private Symbol iterator; 49.8 + private final Symbol iterator; 49.9 49.10 /** Is this a normal for in loop? */ 49.11 public static final int IS_FOR_IN = 1 << 0; 49.12 @@ -70,22 +70,22 @@ 49.13 this.flags = flags; 49.14 this.init = null; 49.15 this.modify = null; 49.16 + this.iterator = null; 49.17 } 49.18 49.19 private ForNode(final ForNode forNode, final Expression init, final JoinPredecessorExpression test, 49.20 - final Block body, final JoinPredecessorExpression modify, final int flags, final boolean controlFlowEscapes, final LocalVariableConversion conversion) { 49.21 + final Block body, final JoinPredecessorExpression modify, final int flags, 49.22 + final boolean controlFlowEscapes, final LocalVariableConversion conversion, final Symbol iterator) { 49.23 super(forNode, test, body, controlFlowEscapes, conversion); 49.24 this.init = init; 49.25 this.modify = modify; 49.26 this.flags = flags; 49.27 - // Even if the for node gets cloned in try/finally, the symbol can be shared as only one branch of the finally 49.28 - // is executed. 49.29 - this.iterator = forNode.iterator; 49.30 + this.iterator = iterator; 49.31 } 49.32 49.33 @Override 49.34 public Node ensureUniqueLabels(final LexicalContext lc) { 49.35 - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); 49.36 + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); 49.37 } 49.38 49.39 @Override 49.40 @@ -158,7 +158,7 @@ 49.41 if (this.init == init) { 49.42 return this; 49.43 } 49.44 - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); 49.45 + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); 49.46 } 49.47 49.48 /** 49.49 @@ -206,10 +206,15 @@ 49.50 49.51 /** 49.52 * Assign an iterator symbol to this ForNode. Used for for in and for each constructs 49.53 + * @param lc the current lexical context 49.54 * @param iterator the iterator symbol 49.55 + * @return a ForNode with the iterator set 49.56 */ 49.57 - public void setIterator(final Symbol iterator) { 49.58 - this.iterator = iterator; 49.59 + public ForNode setIterator(final LexicalContext lc, final Symbol iterator) { 49.60 + if (this.iterator == iterator) { 49.61 + return this; 49.62 + } 49.63 + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); 49.64 } 49.65 49.66 /** 49.67 @@ -230,7 +235,7 @@ 49.68 if (this.modify == modify) { 49.69 return this; 49.70 } 49.71 - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); 49.72 + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); 49.73 } 49.74 49.75 @Override 49.76 @@ -238,7 +243,7 @@ 49.77 if (this.test == test) { 49.78 return this; 49.79 } 49.80 - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); 49.81 + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); 49.82 } 49.83 49.84 @Override 49.85 @@ -251,7 +256,7 @@ 49.86 if (this.body == body) { 49.87 return this; 49.88 } 49.89 - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); 49.90 + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); 49.91 } 49.92 49.93 @Override 49.94 @@ -259,19 +264,19 @@ 49.95 if (this.controlFlowEscapes == controlFlowEscapes) { 49.96 return this; 49.97 } 49.98 - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); 49.99 + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); 49.100 } 49.101 49.102 private ForNode setFlags(final LexicalContext lc, final int flags) { 49.103 if (this.flags == flags) { 49.104 return this; 49.105 } 49.106 - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); 49.107 + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); 49.108 } 49.109 49.110 @Override 49.111 JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) { 49.112 - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); 49.113 + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); 49.114 } 49.115 49.116 @Override
50.1 --- a/src/jdk/nashorn/internal/ir/FunctionNode.java Thu Sep 24 10:00:42 2015 -0700 50.2 +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java Thu Sep 24 10:09:56 2015 -0700 50.3 @@ -33,10 +33,8 @@ 50.4 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES; 50.5 50.6 import java.util.Collections; 50.7 -import java.util.EnumSet; 50.8 import java.util.Iterator; 50.9 import java.util.List; 50.10 -import jdk.nashorn.internal.AssertsEnabled; 50.11 import jdk.nashorn.internal.codegen.CompileUnit; 50.12 import jdk.nashorn.internal.codegen.Compiler; 50.13 import jdk.nashorn.internal.codegen.CompilerConstants; 50.14 @@ -73,40 +71,6 @@ 50.15 SETTER 50.16 } 50.17 50.18 - /** Compilation states available */ 50.19 - public enum CompilationState { 50.20 - /** compiler is ready */ 50.21 - INITIALIZED, 50.22 - /** method has been parsed */ 50.23 - PARSED, 50.24 - /** method has been parsed */ 50.25 - PARSE_ERROR, 50.26 - /** constant folding pass */ 50.27 - CONSTANT_FOLDED, 50.28 - /** method has been lowered */ 50.29 - LOWERED, 50.30 - /** program points have been assigned to unique locations */ 50.31 - PROGRAM_POINTS_ASSIGNED, 50.32 - /** any transformations of builtins have taken place, e.g. apply=>call */ 50.33 - BUILTINS_TRANSFORMED, 50.34 - /** method has been split */ 50.35 - SPLIT, 50.36 - /** method has had symbols assigned */ 50.37 - SYMBOLS_ASSIGNED, 50.38 - /** computed scope depths for symbols */ 50.39 - SCOPE_DEPTHS_COMPUTED, 50.40 - /** method has had types calculated*/ 50.41 - OPTIMISTIC_TYPES_ASSIGNED, 50.42 - /** method has had types calculated */ 50.43 - LOCAL_VARIABLE_TYPES_CALCULATED, 50.44 - /** compile units reused (optional) */ 50.45 - COMPILE_UNITS_REUSED, 50.46 - /** method has been emitted to bytecode */ 50.47 - BYTECODE_GENERATED, 50.48 - /** method has been installed */ 50.49 - BYTECODE_INSTALLED 50.50 - } 50.51 - 50.52 /** Source of entity. */ 50.53 private transient final Source source; 50.54 50.55 @@ -144,10 +108,6 @@ 50.56 /** Method's namespace. */ 50.57 private transient final Namespace namespace; 50.58 50.59 - /** Current compilation state */ 50.60 - @Ignore 50.61 - private final EnumSet<CompilationState> compilationState; 50.62 - 50.63 /** Number of properties of "this" object assigned in this function */ 50.64 @Ignore 50.65 private final int thisProperties; 50.66 @@ -263,6 +223,11 @@ 50.67 */ 50.68 public static final int NEEDS_CALLEE = 1 << 26; 50.69 50.70 + /** 50.71 + * Is the function node cached? 50.72 + */ 50.73 + public static final int IS_CACHED = 1 << 27; 50.74 + 50.75 /** extension callsite flags mask */ 50.76 public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE | 50.77 IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST | 50.78 @@ -322,7 +287,6 @@ 50.79 this.firstToken = firstToken; 50.80 this.lastToken = token; 50.81 this.namespace = namespace; 50.82 - this.compilationState = EnumSet.of(CompilationState.INITIALIZED); 50.83 this.flags = flags; 50.84 this.compileUnit = null; 50.85 this.body = null; 50.86 @@ -339,12 +303,11 @@ 50.87 final String name, 50.88 final Type returnType, 50.89 final CompileUnit compileUnit, 50.90 - final EnumSet<CompilationState> compilationState, 50.91 final Block body, 50.92 final List<IdentNode> parameters, 50.93 final int thisProperties, 50.94 final Class<?> rootClass, 50.95 - final Source source, Namespace namespace) { 50.96 + final Source source, final Namespace namespace) { 50.97 super(functionNode); 50.98 50.99 this.endParserState = endParserState; 50.100 @@ -354,7 +317,6 @@ 50.101 this.returnType = returnType; 50.102 this.compileUnit = compileUnit; 50.103 this.lastToken = lastToken; 50.104 - this.compilationState = compilationState; 50.105 this.body = body; 50.106 this.parameters = parameters; 50.107 this.thisProperties = thisProperties; 50.108 @@ -454,7 +416,6 @@ 50.109 name, 50.110 returnType, 50.111 compileUnit, 50.112 - compilationState, 50.113 body, 50.114 parameters, 50.115 thisProperties, 50.116 @@ -530,80 +491,6 @@ 50.117 } 50.118 50.119 /** 50.120 - * Get the compilation state of this function 50.121 - * @return the compilation state 50.122 - */ 50.123 - public EnumSet<CompilationState> getState() { 50.124 - return compilationState; 50.125 - } 50.126 - 50.127 - /** 50.128 - * Check whether this FunctionNode has reached a give CompilationState. 50.129 - * 50.130 - * @param state the state to check for 50.131 - * @return true of the node is in the given state 50.132 - */ 50.133 - public boolean hasState(final EnumSet<CompilationState> state) { 50.134 - return !AssertsEnabled.assertsEnabled() || compilationState.containsAll(state); 50.135 - } 50.136 - 50.137 - /** 50.138 - * Add a state to the total CompilationState of this node, e.g. if 50.139 - * FunctionNode has been lowered, the compiler will add 50.140 - * {@code CompilationState#LOWERED} to the state vector 50.141 - * 50.142 - * @param lc lexical context 50.143 - * @param state {@link CompilationState} to add 50.144 - * @return function node or a new one if state was changed 50.145 - */ 50.146 - public FunctionNode setState(final LexicalContext lc, final CompilationState state) { 50.147 - if (!AssertsEnabled.assertsEnabled() || this.compilationState.contains(state)) { 50.148 - return this; 50.149 - } 50.150 - final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState); 50.151 - newState.add(state); 50.152 - return setCompilationState(lc, newState); 50.153 - } 50.154 - 50.155 - /** 50.156 - * Copy a compilation state from an original function to this function. Used when creating synthetic 50.157 - * function nodes by the splitter. 50.158 - * 50.159 - * @param lc lexical context 50.160 - * @param original the original function node to copy compilation state from 50.161 - * @return function node or a new one if state was changed 50.162 - */ 50.163 - public FunctionNode copyCompilationState(final LexicalContext lc, final FunctionNode original) { 50.164 - final EnumSet<CompilationState> origState = original.compilationState; 50.165 - if (!AssertsEnabled.assertsEnabled() || this.compilationState.containsAll(origState)) { 50.166 - return this; 50.167 - } 50.168 - final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState); 50.169 - newState.addAll(origState); 50.170 - return setCompilationState(lc, newState); 50.171 - } 50.172 - 50.173 - private FunctionNode setCompilationState(final LexicalContext lc, final EnumSet<CompilationState> compilationState) { 50.174 - return Node.replaceInLexicalContext( 50.175 - lc, 50.176 - this, 50.177 - new FunctionNode( 50.178 - this, 50.179 - lastToken, 50.180 - endParserState, 50.181 - flags, 50.182 - name, 50.183 - returnType, 50.184 - compileUnit, 50.185 - compilationState, 50.186 - body, 50.187 - parameters, 50.188 - thisProperties, 50.189 - rootClass, source, namespace)); 50.190 - } 50.191 - 50.192 - 50.193 - /** 50.194 * Create a unique name in the namespace of this FunctionNode 50.195 * @param base prefix for name 50.196 * @return base if no collision exists, otherwise a name prefix with base 50.197 @@ -668,7 +555,6 @@ 50.198 name, 50.199 returnType, 50.200 compileUnit, 50.201 - compilationState, 50.202 body, 50.203 parameters, 50.204 thisProperties, 50.205 @@ -748,7 +634,7 @@ 50.206 */ 50.207 public boolean needsCallee() { 50.208 // NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units. 50.209 - return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasOptimisticApplyToCall(); 50.210 + return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasApplyToCallSpecialization(); 50.211 } 50.212 50.213 /** 50.214 @@ -765,7 +651,7 @@ 50.215 * Return true if function contains an apply to call transform 50.216 * @return true if this function has transformed apply to call 50.217 */ 50.218 - public boolean hasOptimisticApplyToCall() { 50.219 + public boolean hasApplyToCallSpecialization() { 50.220 return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION); 50.221 } 50.222 50.223 @@ -809,7 +695,6 @@ 50.224 name, 50.225 returnType, 50.226 compileUnit, 50.227 - compilationState, 50.228 body, 50.229 parameters, 50.230 thisProperties, 50.231 @@ -905,7 +790,6 @@ 50.232 name, 50.233 returnType, 50.234 compileUnit, 50.235 - compilationState, 50.236 body, 50.237 parameters, 50.238 thisProperties, 50.239 @@ -966,7 +850,6 @@ 50.240 name, 50.241 returnType, 50.242 compileUnit, 50.243 - compilationState, 50.244 body, 50.245 parameters, 50.246 thisProperties, 50.247 @@ -1002,7 +885,6 @@ 50.248 name, 50.249 returnType, 50.250 compileUnit, 50.251 - compilationState, 50.252 body, 50.253 parameters, 50.254 thisProperties, 50.255 @@ -1040,7 +922,6 @@ 50.256 name, 50.257 returnType, 50.258 compileUnit, 50.259 - compilationState, 50.260 body, 50.261 parameters, 50.262 thisProperties, 50.263 @@ -1116,7 +997,6 @@ 50.264 name, 50.265 returnType, 50.266 compileUnit, 50.267 - compilationState, 50.268 body, 50.269 parameters, 50.270 thisProperties, 50.271 @@ -1204,7 +1084,6 @@ 50.272 name, 50.273 type, 50.274 compileUnit, 50.275 - compilationState, 50.276 body, 50.277 parameters, 50.278 thisProperties, 50.279 @@ -1221,6 +1100,24 @@ 50.280 } 50.281 50.282 /** 50.283 + * Returns true if this function node has been cached. 50.284 + * @return true if this function node has been cached. 50.285 + */ 50.286 + public boolean isCached() { 50.287 + return getFlag(IS_CACHED); 50.288 + } 50.289 + 50.290 + /** 50.291 + * Mark this function node as having been cached. 50.292 + * @param lc the current lexical context 50.293 + * @return a function node equivalent to this one, with the flag set. 50.294 + */ 50.295 + public FunctionNode setCached(final LexicalContext lc) { 50.296 + return setFlag(lc, IS_CACHED); 50.297 + } 50.298 + 50.299 + 50.300 + /** 50.301 * Get the compile unit used to compile this function 50.302 * @see Compiler 50.303 * @return the compile unit 50.304 @@ -1252,7 +1149,6 @@ 50.305 name, 50.306 returnType, 50.307 compileUnit, 50.308 - compilationState, 50.309 body, 50.310 parameters, 50.311 thisProperties, 50.312 @@ -1308,7 +1204,6 @@ 50.313 name, 50.314 returnType, 50.315 compileUnit, 50.316 - compilationState, 50.317 body, 50.318 parameters, 50.319 thisProperties,
51.1 --- a/src/jdk/nashorn/internal/ir/LiteralNode.java Thu Sep 24 10:00:42 2015 -0700 51.2 +++ b/src/jdk/nashorn/internal/ir/LiteralNode.java Thu Sep 24 10:09:56 2015 -0700 51.3 @@ -430,7 +430,7 @@ 51.4 * 51.5 * @param token token 51.6 * @param finish finish 51.7 - * @param value undefined value, passed only for polymorphisism discrimination 51.8 + * @param value undefined value, passed only for polymorphism discrimination 51.9 * 51.10 * @return the new literal node 51.11 */
52.1 --- a/src/jdk/nashorn/internal/ir/RuntimeNode.java Thu Sep 24 10:00:42 2015 -0700 52.2 +++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java Thu Sep 24 10:09:56 2015 -0700 52.3 @@ -276,7 +276,7 @@ 52.4 * 52.5 * @param request a request 52.6 * 52.7 - * @return the inverted rquest, or null if not applicable 52.8 + * @return the inverted request, or null if not applicable 52.9 */ 52.10 public static Request invert(final Request request) { 52.11 switch (request) {
53.1 --- a/src/jdk/nashorn/internal/ir/SwitchNode.java Thu Sep 24 10:00:42 2015 -0700 53.2 +++ b/src/jdk/nashorn/internal/ir/SwitchNode.java Thu Sep 24 10:09:56 2015 -0700 53.3 @@ -53,7 +53,7 @@ 53.4 private final boolean uniqueInteger; 53.5 53.6 /** Tag symbol. */ 53.7 - private Symbol tag; 53.8 + private final Symbol tag; 53.9 53.10 /** 53.11 * Constructor 53.12 @@ -71,15 +71,16 @@ 53.13 this.cases = cases; 53.14 this.defaultCaseIndex = defaultCase == null ? -1 : cases.indexOf(defaultCase); 53.15 this.uniqueInteger = false; 53.16 + this.tag = null; 53.17 } 53.18 53.19 private SwitchNode(final SwitchNode switchNode, final Expression expression, final List<CaseNode> cases, 53.20 - final int defaultCaseIndex, final LocalVariableConversion conversion, final boolean uniqueInteger) { 53.21 + final int defaultCaseIndex, final LocalVariableConversion conversion, final boolean uniqueInteger, final Symbol tag) { 53.22 super(switchNode, conversion); 53.23 this.expression = expression; 53.24 this.cases = cases; 53.25 this.defaultCaseIndex = defaultCaseIndex; 53.26 - this.tag = switchNode.getTag(); //TODO are symbols inherited as references? 53.27 + this.tag = tag; 53.28 this.uniqueInteger = uniqueInteger; 53.29 } 53.30 53.31 @@ -89,7 +90,7 @@ 53.32 for (final CaseNode caseNode : cases) { 53.33 newCases.add(new CaseNode(caseNode, caseNode.getTest(), caseNode.getBody(), caseNode.getLocalVariableConversion())); 53.34 } 53.35 - return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion, uniqueInteger)); 53.36 + return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion, uniqueInteger, tag)); 53.37 } 53.38 53.39 @Override 53.40 @@ -157,7 +158,7 @@ 53.41 if (this.cases == cases) { 53.42 return this; 53.43 } 53.44 - return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger)); 53.45 + return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag)); 53.46 } 53.47 53.48 /** 53.49 @@ -189,7 +190,7 @@ 53.50 if (this.expression == expression) { 53.51 return this; 53.52 } 53.53 - return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger)); 53.54 + return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag)); 53.55 } 53.56 53.57 /** 53.58 @@ -204,10 +205,15 @@ 53.59 /** 53.60 * Set the tag symbol for this switch. The tag symbol is where 53.61 * the switch expression result is stored 53.62 + * @param lc lexical context 53.63 * @param tag a symbol 53.64 + * @return a switch node with the symbol set 53.65 */ 53.66 - public void setTag(final Symbol tag) { 53.67 - this.tag = tag; 53.68 + public SwitchNode setTag(final LexicalContext lc, final Symbol tag) { 53.69 + if (this.tag == tag) { 53.70 + return this; 53.71 + } 53.72 + return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag)); 53.73 } 53.74 53.75 /** 53.76 @@ -229,12 +235,12 @@ 53.77 if(this.uniqueInteger == uniqueInteger) { 53.78 return this; 53.79 } 53.80 - return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger)); 53.81 + return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag)); 53.82 } 53.83 53.84 @Override 53.85 JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) { 53.86 - return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger)); 53.87 + return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag)); 53.88 } 53.89 53.90 }
54.1 --- a/src/jdk/nashorn/internal/ir/Symbol.java Thu Sep 24 10:00:42 2015 -0700 54.2 +++ b/src/jdk/nashorn/internal/ir/Symbol.java Thu Sep 24 10:09:56 2015 -0700 54.3 @@ -25,7 +25,10 @@ 54.4 54.5 package jdk.nashorn.internal.ir; 54.6 54.7 +import java.io.IOException; 54.8 +import java.io.ObjectInputStream; 54.9 import java.io.PrintWriter; 54.10 +import java.io.Serializable; 54.11 import java.util.HashSet; 54.12 import java.util.Set; 54.13 import java.util.StringTokenizer; 54.14 @@ -47,7 +50,9 @@ 54.15 * refer to their location. 54.16 */ 54.17 54.18 -public final class Symbol implements Comparable<Symbol> { 54.19 +public final class Symbol implements Comparable<Symbol>, Cloneable, Serializable { 54.20 + private static final long serialVersionUID = 1L; 54.21 + 54.22 /** Is this Global */ 54.23 public static final int IS_GLOBAL = 1; 54.24 /** Is this a variable */ 54.25 @@ -94,10 +99,10 @@ 54.26 54.27 /** First bytecode method local variable slot for storing the value(s) of this variable. -1 indicates the variable 54.28 * is not stored in local variable slots or it is not yet known. */ 54.29 - private int firstSlot = -1; 54.30 + private transient int firstSlot = -1; 54.31 54.32 /** Field number in scope or property; array index in varargs when not using arguments object. */ 54.33 - private int fieldIndex = -1; 54.34 + private transient int fieldIndex = -1; 54.35 54.36 /** Number of times this symbol is used in code */ 54.37 private int useCount; 54.38 @@ -144,6 +149,15 @@ 54.39 } 54.40 } 54.41 54.42 + @Override 54.43 + public Symbol clone() { 54.44 + try { 54.45 + return (Symbol)super.clone(); 54.46 + } catch (final CloneNotSupportedException e) { 54.47 + throw new AssertionError(e); 54.48 + } 54.49 + } 54.50 + 54.51 private static String align(final String string, final int max) { 54.52 final StringBuilder sb = new StringBuilder(); 54.53 sb.append(string.substring(0, Math.min(string.length(), max))); 54.54 @@ -337,7 +351,7 @@ 54.55 * Flag this symbol as scope as described in {@link Symbol#isScope()} 54.56 * @return the symbol 54.57 */ 54.58 - public Symbol setIsScope() { 54.59 + public Symbol setIsScope() { 54.60 if (!isScope()) { 54.61 if(shouldTrace()) { 54.62 trace("SET IS SCOPE"); 54.63 @@ -609,11 +623,11 @@ 54.64 54.65 /** 54.66 * Increase the symbol's use count by one. 54.67 - * @return the symbol 54.68 */ 54.69 - public Symbol increaseUseCount() { 54.70 - useCount++; 54.71 - return this; 54.72 + public void increaseUseCount() { 54.73 + if (isScope()) { // Avoid dirtying a cache line; we only need the use count for scoped symbols 54.74 + useCount++; 54.75 + } 54.76 } 54.77 54.78 /** 54.79 @@ -669,4 +683,10 @@ 54.80 new Throwable().printStackTrace(Context.getCurrentErr()); 54.81 } 54.82 } 54.83 + 54.84 + private void readObject(final ObjectInputStream in) throws ClassNotFoundException, IOException { 54.85 + in.defaultReadObject(); 54.86 + firstSlot = -1; 54.87 + fieldIndex = -1; 54.88 + } 54.89 }
55.1 --- a/src/jdk/nashorn/internal/ir/TryNode.java Thu Sep 24 10:00:42 2015 -0700 55.2 +++ b/src/jdk/nashorn/internal/ir/TryNode.java Thu Sep 24 10:09:56 2015 -0700 55.3 @@ -65,7 +65,7 @@ 55.4 private final List<Block> inlinedFinallies; 55.5 55.6 /** Exception symbol. */ 55.7 - private Symbol exception; 55.8 + private final Symbol exception; 55.9 55.10 private final LocalVariableConversion conversion; 55.11 55.12 @@ -86,22 +86,23 @@ 55.13 this.finallyBody = finallyBody; 55.14 this.conversion = null; 55.15 this.inlinedFinallies = Collections.emptyList(); 55.16 + this.exception = null; 55.17 } 55.18 55.19 - private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion, final List<Block> inlinedFinallies) { 55.20 + private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion, final List<Block> inlinedFinallies, final Symbol exception) { 55.21 super(tryNode); 55.22 this.body = body; 55.23 this.catchBlocks = catchBlocks; 55.24 this.finallyBody = finallyBody; 55.25 this.conversion = conversion; 55.26 this.inlinedFinallies = inlinedFinallies; 55.27 - this.exception = tryNode.exception; 55.28 + this.exception = exception; 55.29 } 55.30 55.31 @Override 55.32 public Node ensureUniqueLabels(final LexicalContext lc) { 55.33 //try nodes are never in lex context 55.34 - return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies); 55.35 + return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception); 55.36 } 55.37 55.38 @Override 55.39 @@ -160,7 +161,7 @@ 55.40 if (this.body == body) { 55.41 return this; 55.42 } 55.43 - return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies)); 55.44 + return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception)); 55.45 } 55.46 55.47 /** 55.48 @@ -197,7 +198,7 @@ 55.49 if (this.catchBlocks == catchBlocks) { 55.50 return this; 55.51 } 55.52 - return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies)); 55.53 + return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception)); 55.54 } 55.55 55.56 /** 55.57 @@ -209,12 +210,15 @@ 55.58 } 55.59 /** 55.60 * Set the exception symbol for this try block 55.61 + * @param lc lexical context 55.62 * @param exception a symbol for the compiler to store the exception in 55.63 * @return new TryNode or same if unchanged 55.64 */ 55.65 - public TryNode setException(final Symbol exception) { 55.66 - this.exception = exception; 55.67 - return this; 55.68 + public TryNode setException(final LexicalContext lc, final Symbol exception) { 55.69 + if (this.exception == exception) { 55.70 + return this; 55.71 + } 55.72 + return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception)); 55.73 } 55.74 55.75 /** 55.76 @@ -277,7 +281,7 @@ 55.77 if (this.finallyBody == finallyBody) { 55.78 return this; 55.79 } 55.80 - return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies)); 55.81 + return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception)); 55.82 } 55.83 55.84 /** 55.85 @@ -293,7 +297,7 @@ 55.86 return this; 55.87 } 55.88 assert checkInlinedFinallies(inlinedFinallies); 55.89 - return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies)); 55.90 + return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception)); 55.91 } 55.92 55.93 private static boolean checkInlinedFinallies(final List<Block> inlinedFinallies) { 55.94 @@ -314,7 +318,7 @@ 55.95 if(this.conversion == conversion) { 55.96 return this; 55.97 } 55.98 - return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies); 55.99 + return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception); 55.100 } 55.101 55.102 @Override
56.1 --- a/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java Thu Sep 24 10:00:42 2015 -0700 56.2 +++ b/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java Thu Sep 24 10:09:56 2015 -0700 56.3 @@ -36,7 +36,7 @@ 56.4 import jdk.nashorn.internal.ir.debug.NashornTextifier.NashornLabel; 56.5 56.6 /** 56.7 - * Subclass of the ASM classs reader that retains more info, such 56.8 + * Subclass of the ASM class reader that retains more info, such 56.9 * as bytecode offsets 56.10 */ 56.11 public class NashornClassReader extends ClassReader {
57.1 --- a/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java Thu Sep 24 10:00:42 2015 -0700 57.2 +++ b/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java Thu Sep 24 10:09:56 2015 -0700 57.3 @@ -193,7 +193,7 @@ 57.4 } 57.5 57.6 /** 57.7 - * Get the class histograpm 57.8 + * Get the class histogram 57.9 * @return class histogram element list 57.10 */ 57.11 public List<ClassHistogramElement> getClassHistogram() {
58.1 --- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java Thu Sep 24 10:00:42 2015 -0700 58.2 +++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java Thu Sep 24 10:09:56 2015 -0700 58.3 @@ -192,7 +192,7 @@ 58.4 /** 58.5 * Factory method for array data 58.6 * 58.7 - * @param nb underlying nativebuffer 58.8 + * @param nb underlying native buffer 58.9 * @param start start element 58.10 * @param end end element 58.11 *
59.1 --- a/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java Thu Sep 24 10:00:42 2015 -0700 59.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 59.3 @@ -1,51 +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.objects; 59.30 - 59.31 -import jdk.nashorn.internal.runtime.ScriptFunction; 59.32 -import jdk.nashorn.internal.runtime.ScriptFunctionData; 59.33 -import jdk.nashorn.internal.runtime.ScriptObject; 59.34 -import jdk.nashorn.internal.runtime.ScriptRuntime; 59.35 - 59.36 -/** 59.37 - * A {@code ScriptFunctionImpl} subclass for functions created using {@code Function.prototype.bind}. Such functions 59.38 - * must track their {@code [[TargetFunction]]} property for purposes of correctly implementing {@code [[HasInstance]]}; 59.39 - * see {@link ScriptFunction#isInstance(ScriptObject)}. 59.40 - */ 59.41 -final class BoundScriptFunctionImpl extends ScriptFunctionImpl { 59.42 - private final ScriptFunction targetFunction; 59.43 - 59.44 - BoundScriptFunctionImpl(final ScriptFunctionData data, final ScriptFunction targetFunction) { 59.45 - super(data, Global.instance()); 59.46 - setPrototype(ScriptRuntime.UNDEFINED); 59.47 - this.targetFunction = targetFunction; 59.48 - } 59.49 - 59.50 - @Override 59.51 - protected ScriptFunction getTargetFunction() { 59.52 - return targetFunction; 59.53 - } 59.54 -}
60.1 --- a/src/jdk/nashorn/internal/objects/Global.java Thu Sep 24 10:00:42 2015 -0700 60.2 +++ b/src/jdk/nashorn/internal/objects/Global.java Thu Sep 24 10:09:56 2015 -0700 60.3 @@ -1583,7 +1583,11 @@ 60.4 return ScriptFunction.getPrototype(builtinObject); 60.5 } 60.6 60.7 - ScriptObject getFunctionPrototype() { 60.8 + /** 60.9 + * Get the builtin Function prototype. 60.10 + * @return the Function.prototype. 60.11 + */ 60.12 + public ScriptObject getFunctionPrototype() { 60.13 return ScriptFunction.getPrototype(builtinFunction); 60.14 } 60.15 60.16 @@ -1768,7 +1772,12 @@ 60.17 return ScriptFunction.getPrototype(getBuiltinFloat64Array()); 60.18 } 60.19 60.20 - ScriptFunction getTypeErrorThrower() { 60.21 + /** 60.22 + * Return the function that throws TypeError unconditionally. Used as "poison" methods for certain Function properties. 60.23 + * 60.24 + * @return the TypeError throwing function 60.25 + */ 60.26 + public ScriptFunction getTypeErrorThrower() { 60.27 return typeErrorThrower; 60.28 } 60.29 60.30 @@ -2157,7 +2166,7 @@ 60.31 60.32 // We want to avoid adding our generic lexical scope switchpoint to global constant invocations, 60.33 // because those are invalidated per-key in the addBoundProperties method above. 60.34 - // We therefor check if the invocation does already have a switchpoint and the property is non-inherited, 60.35 + // We therefore check if the invocation does already have a switchpoint and the property is non-inherited, 60.36 // assuming this only applies to global constants. If other non-inherited properties will 60.37 // start using switchpoints some time in the future we'll have to revisit this. 60.38 if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) { 60.39 @@ -2202,10 +2211,10 @@ 60.40 * Adds jjs shell interactive mode builtin functions to global scope. 60.41 */ 60.42 public void addShellBuiltins() { 60.43 - Object value = ScriptFunctionImpl.makeFunction("input", ShellFunctions.INPUT); 60.44 + Object value = ScriptFunction.createBuiltin("input", ShellFunctions.INPUT); 60.45 addOwnProperty("input", Attribute.NOT_ENUMERABLE, value); 60.46 60.47 - value = ScriptFunctionImpl.makeFunction("evalinput", ShellFunctions.EVALINPUT); 60.48 + value = ScriptFunction.createBuiltin("evalinput", ShellFunctions.EVALINPUT); 60.49 addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value); 60.50 } 60.51 60.52 @@ -2252,35 +2261,35 @@ 60.53 this.setInitialProto(getObjectPrototype()); 60.54 60.55 // initialize global function properties 60.56 - this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL); 60.57 - 60.58 - this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT, 60.59 + this.eval = this.builtinEval = ScriptFunction.createBuiltin("eval", EVAL); 60.60 + 60.61 + this.parseInt = ScriptFunction.createBuiltin("parseInt", GlobalFunctions.PARSEINT, 60.62 new Specialization[] { 60.63 new Specialization(GlobalFunctions.PARSEINT_Z), 60.64 new Specialization(GlobalFunctions.PARSEINT_I), 60.65 new Specialization(GlobalFunctions.PARSEINT_J), 60.66 new Specialization(GlobalFunctions.PARSEINT_OI), 60.67 new Specialization(GlobalFunctions.PARSEINT_O) }); 60.68 - this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT); 60.69 - this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN, 60.70 + this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT); 60.71 + this.isNaN = ScriptFunction.createBuiltin("isNaN", GlobalFunctions.IS_NAN, 60.72 new Specialization[] { 60.73 new Specialization(GlobalFunctions.IS_NAN_I), 60.74 new Specialization(GlobalFunctions.IS_NAN_J), 60.75 new Specialization(GlobalFunctions.IS_NAN_D) }); 60.76 - this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT); 60.77 - this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN); 60.78 - this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE); 60.79 - this.encodeURI = ScriptFunctionImpl.makeFunction("encodeURI", GlobalFunctions.ENCODE_URI); 60.80 - this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT); 60.81 - this.decodeURI = ScriptFunctionImpl.makeFunction("decodeURI", GlobalFunctions.DECODE_URI); 60.82 - this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT); 60.83 - this.escape = ScriptFunctionImpl.makeFunction("escape", GlobalFunctions.ESCAPE); 60.84 - this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE); 60.85 - this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN); 60.86 - this.load = ScriptFunctionImpl.makeFunction("load", LOAD); 60.87 - this.loadWithNewGlobal = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL); 60.88 - this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT); 60.89 - this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT); 60.90 + this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT); 60.91 + this.isNaN = ScriptFunction.createBuiltin("isNaN", GlobalFunctions.IS_NAN); 60.92 + this.isFinite = ScriptFunction.createBuiltin("isFinite", GlobalFunctions.IS_FINITE); 60.93 + this.encodeURI = ScriptFunction.createBuiltin("encodeURI", GlobalFunctions.ENCODE_URI); 60.94 + this.encodeURIComponent = ScriptFunction.createBuiltin("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT); 60.95 + this.decodeURI = ScriptFunction.createBuiltin("decodeURI", GlobalFunctions.DECODE_URI); 60.96 + this.decodeURIComponent = ScriptFunction.createBuiltin("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT); 60.97 + this.escape = ScriptFunction.createBuiltin("escape", GlobalFunctions.ESCAPE); 60.98 + this.unescape = ScriptFunction.createBuiltin("unescape", GlobalFunctions.UNESCAPE); 60.99 + this.print = ScriptFunction.createBuiltin("print", env._print_no_newline ? PRINT : PRINTLN); 60.100 + this.load = ScriptFunction.createBuiltin("load", LOAD); 60.101 + this.loadWithNewGlobal = ScriptFunction.createBuiltin("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL); 60.102 + this.exit = ScriptFunction.createBuiltin("exit", EXIT); 60.103 + this.quit = ScriptFunction.createBuiltin("quit", EXIT); 60.104 60.105 // built-in constructors 60.106 this.builtinArray = initConstructorAndSwitchPoint("Array", ScriptFunction.class); 60.107 @@ -2360,7 +2369,7 @@ 60.108 // default file name 60.109 addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null); 60.110 // __noSuchProperty__ hook for ScriptContext search of missing variables 60.111 - final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY); 60.112 + final ScriptFunction noSuchProp = ScriptFunction.createStrictBuiltin(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY); 60.113 addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp); 60.114 } 60.115 } 60.116 @@ -2371,17 +2380,17 @@ 60.117 final ScriptObject errorProto = getErrorPrototype(); 60.118 60.119 // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName 60.120 - final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK); 60.121 - final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK); 60.122 + final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", NativeError.GET_STACK); 60.123 + final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", NativeError.SET_STACK); 60.124 errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack); 60.125 - final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER); 60.126 - final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER); 60.127 + final ScriptFunction getLineNumber = ScriptFunction.createBuiltin("getLineNumber", NativeError.GET_LINENUMBER); 60.128 + final ScriptFunction setLineNumber = ScriptFunction.createBuiltin("setLineNumber", NativeError.SET_LINENUMBER); 60.129 errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber); 60.130 - final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER); 60.131 - final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER); 60.132 + final ScriptFunction getColumnNumber = ScriptFunction.createBuiltin("getColumnNumber", NativeError.GET_COLUMNNUMBER); 60.133 + final ScriptFunction setColumnNumber = ScriptFunction.createBuiltin("setColumnNumber", NativeError.SET_COLUMNNUMBER); 60.134 errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber); 60.135 - final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME); 60.136 - final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME); 60.137 + final ScriptFunction getFileName = ScriptFunction.createBuiltin("getFileName", NativeError.GET_FILENAME); 60.138 + final ScriptFunction setFileName = ScriptFunction.createBuiltin("setFileName", NativeError.SET_FILENAME); 60.139 errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName); 60.140 60.141 // ECMA 15.11.4.2 Error.prototype.name 60.142 @@ -2420,20 +2429,22 @@ 60.143 } 60.144 60.145 private void initScripting(final ScriptEnvironment scriptEnv) { 60.146 - Object value; 60.147 - value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE); 60.148 + ScriptObject value; 60.149 + value = ScriptFunction.createBuiltin("readLine", ScriptingFunctions.READLINE); 60.150 addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value); 60.151 60.152 - value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY); 60.153 + value = ScriptFunction.createBuiltin("readFully", ScriptingFunctions.READFULLY); 60.154 addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value); 60.155 60.156 final String execName = ScriptingFunctions.EXEC_NAME; 60.157 - value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC); 60.158 + value = ScriptFunction.createBuiltin(execName, ScriptingFunctions.EXEC); 60.159 + value.addOwnProperty(ScriptingFunctions.THROW_ON_ERROR_NAME, Attribute.NOT_ENUMERABLE, false); 60.160 + 60.161 addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value); 60.162 60.163 // Nashorn extension: global.echo (scripting-mode-only) 60.164 // alias for "print" 60.165 - value = get("print"); 60.166 + value = (ScriptObject)get("print"); 60.167 addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value); 60.168 60.169 // Nashorn extension: global.$OPTIONS (scripting-mode-only) 60.170 @@ -2609,7 +2620,7 @@ 60.171 this.builtinFunction = initConstructor("Function", ScriptFunction.class); 60.172 60.173 // create global anonymous function 60.174 - final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(); 60.175 + final ScriptFunction anon = ScriptFunction.createAnonymous(); 60.176 // need to copy over members of Function.prototype to anon function 60.177 anon.addBoundProperties(getFunctionPrototype()); 60.178 60.179 @@ -2621,10 +2632,7 @@ 60.180 anon.deleteOwnProperty(anon.getMap().findProperty("prototype")); 60.181 60.182 // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3 60.183 - this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0); 60.184 - typeErrorThrower.setPrototype(UNDEFINED); 60.185 - // Non-constructor built-in functions do not have "prototype" property 60.186 - typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype")); 60.187 + this.typeErrorThrower = ScriptFunction.createBuiltin("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER); 60.188 typeErrorThrower.preventExtensions(); 60.189 60.190 // now initialize Object 60.191 @@ -2635,8 +2643,8 @@ 60.192 60.193 // ES6 draft compliant __proto__ property of Object.prototype 60.194 // accessors on Object.prototype for "__proto__" 60.195 - final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__); 60.196 - final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__); 60.197 + final ScriptFunction getProto = ScriptFunction.createBuiltin("getProto", NativeObject.GET__PROTO__); 60.198 + final ScriptFunction setProto = ScriptFunction.createBuiltin("setProto", NativeObject.SET__PROTO__); 60.199 ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto); 60.200 60.201 // Function valued properties of Function.prototype were not properly
61.1 --- a/src/jdk/nashorn/internal/objects/NativeDataView.java Thu Sep 24 10:00:42 2015 -0700 61.2 +++ b/src/jdk/nashorn/internal/objects/NativeDataView.java Thu Sep 24 10:09:56 2015 -0700 61.3 @@ -22,6 +22,7 @@ 61.4 * or visit www.oracle.com if you need additional information or have any 61.5 * questions. 61.6 */ 61.7 + 61.8 package jdk.nashorn.internal.objects; 61.9 61.10 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
62.1 --- a/src/jdk/nashorn/internal/objects/NativeDebug.java Thu Sep 24 10:00:42 2015 -0700 62.2 +++ b/src/jdk/nashorn/internal/objects/NativeDebug.java Thu Sep 24 10:09:56 2015 -0700 62.3 @@ -26,6 +26,7 @@ 62.4 package jdk.nashorn.internal.objects; 62.5 62.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 62.7 + 62.8 import java.io.PrintWriter; 62.9 import java.util.LinkedList; 62.10 import java.util.Objects; 62.11 @@ -246,7 +247,7 @@ 62.12 final PrintWriter out = Context.getCurrentErr(); 62.13 62.14 out.println("ScriptObject count " + ScriptObject.getCount()); 62.15 - out.println("Scope count " + Scope.getCount()); 62.16 + out.println("Scope count " + Scope.getScopeCount()); 62.17 out.println("ScriptObject listeners added " + PropertyListeners.getListenersAdded()); 62.18 out.println("ScriptObject listeners removed " + PropertyListeners.getListenersRemoved()); 62.19 out.println("ScriptFunction constructor calls " + ScriptFunction.getConstructorCount());
63.1 --- a/src/jdk/nashorn/internal/objects/NativeError.java Thu Sep 24 10:00:42 2015 -0700 63.2 +++ b/src/jdk/nashorn/internal/objects/NativeError.java Thu Sep 24 10:09:56 2015 -0700 63.3 @@ -150,8 +150,8 @@ 63.4 initException(sobj); 63.5 sobj.delete(STACK, false); 63.6 if (! sobj.has("stack")) { 63.7 - final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", GET_STACK); 63.8 - final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", SET_STACK); 63.9 + final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", GET_STACK); 63.10 + final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", SET_STACK); 63.11 sobj.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack); 63.12 } 63.13 return UNDEFINED;
64.1 --- a/src/jdk/nashorn/internal/objects/NativeFunction.java Thu Sep 24 10:00:42 2015 -0700 64.2 +++ b/src/jdk/nashorn/internal/objects/NativeFunction.java Thu Sep 24 10:09:56 2015 -0700 64.3 @@ -108,7 +108,7 @@ 64.4 throw new AssertionError("Should not reach here"); 64.5 } 64.6 64.7 - /** 64.8 + /** 64.9 * Given an array-like object, converts it into a Java object array suitable for invocation of ScriptRuntime.apply 64.10 * or for direct invocation of the applied function. 64.11 * @param array the array-like object. Can be null in which case a zero-length array is created.
65.1 --- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Thu Sep 24 10:00:42 2015 -0700 65.2 +++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Thu Sep 24 10:09:56 2015 -0700 65.3 @@ -621,11 +621,11 @@ 65.4 if (find != null) { 65.5 final Object value = find.getObjectValue(); 65.6 if (value instanceof ScriptFunction) { 65.7 - final ScriptFunctionImpl func = (ScriptFunctionImpl)value; 65.8 + final ScriptFunction func = (ScriptFunction)value; 65.9 // TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound 65.10 // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice. 65.11 return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class, 65.12 - func.makeBoundFunction(this, new Object[] { name })), 0, Object.class), 65.13 + func.createBound(this, new Object[] { name })), 0, Object.class), 65.14 testJSAdaptor(adaptee, null, null, null), 65.15 adaptee.getProtoSwitchPoint(__call__, find.getOwner())); 65.16 }
66.1 --- a/src/jdk/nashorn/internal/objects/NativeJava.java Thu Sep 24 10:00:42 2015 -0700 66.2 +++ b/src/jdk/nashorn/internal/objects/NativeJava.java Thu Sep 24 10:09:56 2015 -0700 66.3 @@ -93,7 +93,7 @@ 66.4 @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 66.5 public static Object synchronizedFunc(final Object self, final Object func, final Object obj) { 66.6 if (func instanceof ScriptFunction) { 66.7 - return ((ScriptFunction)func).makeSynchronizedFunction(obj); 66.8 + return ((ScriptFunction)func).createSynchronized(obj); 66.9 } 66.10 66.11 throw typeError("not.a.function", ScriptRuntime.safeToString(func)); 66.12 @@ -342,7 +342,8 @@ 66.13 /** 66.14 * Given a script object and a Java type, converts the script object into the desired Java type. Currently it 66.15 * performs shallow creation of Java arrays, as well as wrapping of objects in Lists, Dequeues, Queues, 66.16 - * and Collections. Example: 66.17 + * and Collections. If conversion is not possible or fails for some reason, TypeError is thrown. 66.18 + * Example: 66.19 * <pre> 66.20 * var anArray = [1, "13", false] 66.21 * var javaIntArray = Java.to(anArray, "int[]") 66.22 @@ -386,7 +387,11 @@ 66.23 } 66.24 66.25 if(targetClass.isArray()) { 66.26 - return JSType.toJavaArray(obj, targetClass.getComponentType()); 66.27 + try { 66.28 + return JSType.toJavaArray(obj, targetClass.getComponentType()); 66.29 + } catch (final Exception exp) { 66.30 + throw typeError(exp, "java.array.conversion.failed", targetClass.getName()); 66.31 + } 66.32 } 66.33 66.34 if (targetClass == List.class || targetClass == Deque.class || targetClass == Queue.class || targetClass == Collection.class) {
67.1 --- a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java Thu Sep 24 10:00:42 2015 -0700 67.2 +++ b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java Thu Sep 24 10:09:56 2015 -0700 67.3 @@ -134,7 +134,7 @@ 67.4 } 67.5 67.6 @Override 67.7 - protected Object invokeNoSuchProperty(final String name, final int programPoint) { 67.8 + protected Object invokeNoSuchProperty(final String name, final boolean isScope, final int programPoint) { 67.9 final Object retval = createProperty(name); 67.10 if (isValid(programPoint)) { 67.11 throw new UnwarrantedOptimismException(retval, programPoint);
68.1 --- a/src/jdk/nashorn/internal/objects/NativeRegExp.java Thu Sep 24 10:00:42 2015 -0700 68.2 +++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java Thu Sep 24 10:09:56 2015 -0700 68.3 @@ -728,7 +728,7 @@ 68.4 * 68.5 * $$ -> $ 68.6 * $& -> the matched substring 68.7 - * $` -> the portion of string that preceeds matched substring 68.8 + * $` -> the portion of string that precedes matched substring 68.9 * $' -> the portion of string that follows the matched substring 68.10 * $n -> the nth capture, where n is [1-9] and $n is NOT followed by a decimal digit 68.11 * $nn -> the nnth capture, where nn is a two digit decimal number [01-99].
69.1 --- a/src/jdk/nashorn/internal/objects/PrototypeObject.java Thu Sep 24 10:00:42 2015 -0700 69.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 69.3 @@ -1,115 +0,0 @@ 69.4 -/* 69.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 69.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 69.7 - * 69.8 - * This code is free software; you can redistribute it and/or modify it 69.9 - * under the terms of the GNU General Public License version 2 only, as 69.10 - * published by the Free Software Foundation. Oracle designates this 69.11 - * particular file as subject to the "Classpath" exception as provided 69.12 - * by Oracle in the LICENSE file that accompanied this code. 69.13 - * 69.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 69.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 69.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 69.17 - * version 2 for more details (a copy is included in the LICENSE file that 69.18 - * accompanied this code). 69.19 - * 69.20 - * You should have received a copy of the GNU General Public License version 69.21 - * 2 along with this work; if not, write to the Free Software Foundation, 69.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 69.23 - * 69.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 69.25 - * or visit www.oracle.com if you need additional information or have any 69.26 - * questions. 69.27 - */ 69.28 - 69.29 -package jdk.nashorn.internal.objects; 69.30 - 69.31 -import static jdk.nashorn.internal.lookup.Lookup.MH; 69.32 -import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 69.33 - 69.34 -import java.lang.invoke.MethodHandle; 69.35 -import java.lang.invoke.MethodHandles; 69.36 -import java.util.ArrayList; 69.37 -import jdk.nashorn.internal.runtime.AccessorProperty; 69.38 -import jdk.nashorn.internal.runtime.Property; 69.39 -import jdk.nashorn.internal.runtime.PropertyMap; 69.40 -import jdk.nashorn.internal.runtime.ScriptFunction; 69.41 -import jdk.nashorn.internal.runtime.ScriptObject; 69.42 - 69.43 -/** 69.44 - * Instances of this class serve as "prototype" object for script functions. 69.45 - * The purpose is to expose "constructor" property from "prototype". Also, nasgen 69.46 - * generated prototype classes extend from this class. 69.47 - * 69.48 - */ 69.49 -public class PrototypeObject extends ScriptObject { 69.50 - private static final PropertyMap map$; 69.51 - 69.52 - private Object constructor; 69.53 - 69.54 - private static final MethodHandle GET_CONSTRUCTOR = findOwnMH("getConstructor", Object.class, Object.class); 69.55 - private static final MethodHandle SET_CONSTRUCTOR = findOwnMH("setConstructor", void.class, Object.class, Object.class); 69.56 - 69.57 - static { 69.58 - final ArrayList<Property> properties = new ArrayList<>(1); 69.59 - properties.add(AccessorProperty.create("constructor", Property.NOT_ENUMERABLE, GET_CONSTRUCTOR, SET_CONSTRUCTOR)); 69.60 - map$ = PropertyMap.newMap(properties); 69.61 - } 69.62 - 69.63 - private PrototypeObject(final Global global, final PropertyMap map) { 69.64 - super(global.getObjectPrototype(), map != map$? map.addAll(map$) : map$); 69.65 - } 69.66 - 69.67 - PrototypeObject() { 69.68 - this(Global.instance(), map$); 69.69 - } 69.70 - 69.71 - /** 69.72 - * PropertyObject constructor 69.73 - * 69.74 - * @param map property map 69.75 - */ 69.76 - PrototypeObject(final PropertyMap map) { 69.77 - this(Global.instance(), map); 69.78 - } 69.79 - 69.80 - PrototypeObject(final ScriptFunction func) { 69.81 - this(Global.instance(), map$); 69.82 - this.constructor = func; 69.83 - } 69.84 - 69.85 - /** 69.86 - * Get the constructor for this {@code PrototypeObject} 69.87 - * @param self self reference 69.88 - * @return constructor, probably, but not necessarily, a {@link ScriptFunction} 69.89 - */ 69.90 - static Object getConstructor(final Object self) { 69.91 - return (self instanceof PrototypeObject) ? 69.92 - ((PrototypeObject)self).getConstructor() : 69.93 - UNDEFINED; 69.94 - } 69.95 - 69.96 - /** 69.97 - * Reset the constructor for this {@code PrototypeObject} 69.98 - * @param self self reference 69.99 - * @param constructor constructor, probably, but not necessarily, a {@link ScriptFunction} 69.100 - */ 69.101 - static void setConstructor(final Object self, final Object constructor) { 69.102 - if (self instanceof PrototypeObject) { 69.103 - ((PrototypeObject)self).setConstructor(constructor); 69.104 - } 69.105 - } 69.106 - 69.107 - private Object getConstructor() { 69.108 - return constructor; 69.109 - } 69.110 - 69.111 - private void setConstructor(final Object constructor) { 69.112 - this.constructor = constructor; 69.113 - } 69.114 - 69.115 - private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { 69.116 - return MH.findStatic(MethodHandles.lookup(), PrototypeObject.class, name, MH.type(rtype, types)); 69.117 - } 69.118 -}
70.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Thu Sep 24 10:00:42 2015 -0700 70.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 70.3 @@ -1,313 +0,0 @@ 70.4 -/* 70.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 70.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 70.7 - * 70.8 - * This code is free software; you can redistribute it and/or modify it 70.9 - * under the terms of the GNU General Public License version 2 only, as 70.10 - * published by the Free Software Foundation. Oracle designates this 70.11 - * particular file as subject to the "Classpath" exception as provided 70.12 - * by Oracle in the LICENSE file that accompanied this code. 70.13 - * 70.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 70.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 70.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 70.17 - * version 2 for more details (a copy is included in the LICENSE file that 70.18 - * accompanied this code). 70.19 - * 70.20 - * You should have received a copy of the GNU General Public License version 70.21 - * 2 along with this work; if not, write to the Free Software Foundation, 70.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 70.23 - * 70.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 70.25 - * or visit www.oracle.com if you need additional information or have any 70.26 - * questions. 70.27 - */ 70.28 - 70.29 -package jdk.nashorn.internal.objects; 70.30 - 70.31 -import static jdk.nashorn.internal.lookup.Lookup.MH; 70.32 -import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 70.33 - 70.34 -import java.lang.invoke.MethodHandle; 70.35 -import java.util.ArrayList; 70.36 -import jdk.nashorn.internal.runtime.AccessorProperty; 70.37 -import jdk.nashorn.internal.runtime.GlobalFunctions; 70.38 -import jdk.nashorn.internal.runtime.Property; 70.39 -import jdk.nashorn.internal.runtime.PropertyMap; 70.40 -import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; 70.41 -import jdk.nashorn.internal.runtime.ScriptFunction; 70.42 -import jdk.nashorn.internal.runtime.ScriptFunctionData; 70.43 -import jdk.nashorn.internal.runtime.ScriptObject; 70.44 -import jdk.nashorn.internal.runtime.Specialization; 70.45 - 70.46 -/** 70.47 - * Concrete implementation of ScriptFunction. This sets correct map for the 70.48 - * function objects -- to expose properties like "prototype", "length" etc. 70.49 - */ 70.50 -public class ScriptFunctionImpl extends ScriptFunction { 70.51 - 70.52 - /** Reference to constructor prototype. */ 70.53 - private Object prototype; 70.54 - 70.55 - // property map for strict mode functions 70.56 - private static final PropertyMap strictmodemap$; 70.57 - // property map for bound functions 70.58 - private static final PropertyMap boundfunctionmap$; 70.59 - // property map for non-strict, non-bound functions. 70.60 - private static final PropertyMap map$; 70.61 - 70.62 - // Marker object for lazily initialized prototype object 70.63 - private static final Object LAZY_PROTOTYPE = new Object(); 70.64 - 70.65 - private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs, final Global global) { 70.66 - super(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); 70.67 - init(global); 70.68 - } 70.69 - 70.70 - /** 70.71 - * Constructor called by Nasgen generated code, no membercount, use the default map. 70.72 - * Creates builtin functions only. 70.73 - * 70.74 - * @param name name of function 70.75 - * @param invokeHandle handle for invocation 70.76 - * @param specs specialized versions of this method, if available, null otherwise 70.77 - */ 70.78 - ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs) { 70.79 - this(name, invokeHandle, specs, Global.instance()); 70.80 - } 70.81 - 70.82 - private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs, final Global global) { 70.83 - super(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); 70.84 - init(global); 70.85 - } 70.86 - 70.87 - /** 70.88 - * Constructor called by Nasgen generated code, no membercount, use the map passed as argument. 70.89 - * Creates builtin functions only. 70.90 - * 70.91 - * @param name name of function 70.92 - * @param invokeHandle handle for invocation 70.93 - * @param map initial property map 70.94 - * @param specs specialized versions of this method, if available, null otherwise 70.95 - */ 70.96 - ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs) { 70.97 - this(name, invokeHandle, map, specs, Global.instance()); 70.98 - } 70.99 - 70.100 - private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags, final Global global) { 70.101 - super(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags); 70.102 - init(global); 70.103 - } 70.104 - 70.105 - /** 70.106 - * Constructor called by Global.newScriptFunction (runtime). 70.107 - * 70.108 - * @param name name of function 70.109 - * @param methodHandle handle for invocation 70.110 - * @param scope scope object 70.111 - * @param specs specialized versions of this method, if available, null otherwise 70.112 - * @param flags {@link ScriptFunctionData} flags 70.113 - */ 70.114 - ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags) { 70.115 - this(name, methodHandle, scope, specs, flags, Global.instance()); 70.116 - } 70.117 - 70.118 - private ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope, final Global global) { 70.119 - super(data, getMap(data.isStrict()), scope); 70.120 - init(global); 70.121 - } 70.122 - 70.123 - /** 70.124 - * Factory method called by compiler generated code for functions that need parent scope. 70.125 - * 70.126 - * @param constants the generated class' constant array 70.127 - * @param index the index of the {@code RecompilableScriptFunctionData} object in the constants array. 70.128 - * @param scope the parent scope object 70.129 - * @return a newly created function object 70.130 - */ 70.131 - public static ScriptFunction create(final Object[] constants, final int index, final ScriptObject scope) { 70.132 - return new ScriptFunctionImpl((RecompilableScriptFunctionData)constants[index], scope, Global.instance()); 70.133 - } 70.134 - 70.135 - /** 70.136 - * Factory method called by compiler generated code for functions that don't need parent scope. 70.137 - * 70.138 - * @param constants the generated class' constant array 70.139 - * @param index the index of the {@code RecompilableScriptFunctionData} object in the constants array. 70.140 - * @return a newly created function object 70.141 - */ 70.142 - public static ScriptFunction create(final Object[] constants, final int index) { 70.143 - return create(constants, index, null); 70.144 - } 70.145 - 70.146 - /** 70.147 - * Only invoked internally from {@link BoundScriptFunctionImpl} constructor. 70.148 - * @param data the script function data for the bound function. 70.149 - * @param global the global object 70.150 - */ 70.151 - ScriptFunctionImpl(final ScriptFunctionData data, final Global global) { 70.152 - super(data, boundfunctionmap$, null); 70.153 - init(global); 70.154 - } 70.155 - 70.156 - static { 70.157 - final ArrayList<Property> properties = new ArrayList<>(3); 70.158 - properties.add(AccessorProperty.create("prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE)); 70.159 - properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null)); 70.160 - properties.add(AccessorProperty.create("name", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null)); 70.161 - map$ = PropertyMap.newMap(properties); 70.162 - strictmodemap$ = createStrictModeMap(map$); 70.163 - boundfunctionmap$ = createBoundFunctionMap(strictmodemap$); 70.164 - } 70.165 - 70.166 - private static PropertyMap createStrictModeMap(final PropertyMap map) { 70.167 - final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE; 70.168 - PropertyMap newMap = map; 70.169 - // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors. 70.170 - newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags)); 70.171 - newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags)); 70.172 - return newMap; 70.173 - } 70.174 - 70.175 - private static boolean isStrict(final int flags) { 70.176 - return (flags & ScriptFunctionData.IS_STRICT) != 0; 70.177 - } 70.178 - 70.179 - // Choose the map based on strict mode! 70.180 - private static PropertyMap getMap(final boolean strict) { 70.181 - return strict ? strictmodemap$ : map$; 70.182 - } 70.183 - 70.184 - private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) { 70.185 - // Bound function map is same as strict function map, but additionally lacks the "prototype" property, see 70.186 - // ECMAScript 5.1 section 15.3.4.5 70.187 - return strictModeMap.deleteProperty(strictModeMap.findProperty("prototype")); 70.188 - } 70.189 - 70.190 - // Instance of this class is used as global anonymous function which 70.191 - // serves as Function.prototype object. 70.192 - private static class AnonymousFunction extends ScriptFunctionImpl { 70.193 - private static final PropertyMap anonmap$ = PropertyMap.newMap(); 70.194 - 70.195 - AnonymousFunction() { 70.196 - super("", GlobalFunctions.ANONYMOUS, anonmap$, null); 70.197 - } 70.198 - } 70.199 - 70.200 - static ScriptFunctionImpl newAnonymousFunction() { 70.201 - return new AnonymousFunction(); 70.202 - } 70.203 - 70.204 - private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs, final int flags) { 70.205 - final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, flags); 70.206 - func.setPrototype(UNDEFINED); 70.207 - // Non-constructor built-in functions do not have "prototype" property 70.208 - func.deleteOwnProperty(func.getMap().findProperty("prototype")); 70.209 - 70.210 - return func; 70.211 - } 70.212 - 70.213 - /** 70.214 - * Factory method for non-constructor built-in functions 70.215 - * 70.216 - * @param name function name 70.217 - * @param methodHandle handle for invocation 70.218 - * @param specs specialized versions of function if available, null otherwise 70.219 - * @return new ScriptFunction 70.220 - */ 70.221 - static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs) { 70.222 - return makeFunction(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN); 70.223 - } 70.224 - 70.225 - /** 70.226 - * Factory method for non-constructor built-in, strict functions 70.227 - * 70.228 - * @param name function name 70.229 - * @param methodHandle handle for invocation 70.230 - * @return new ScriptFunction 70.231 - */ 70.232 - static ScriptFunction makeStrictFunction(final String name, final MethodHandle methodHandle) { 70.233 - return makeFunction(name, methodHandle, null, ScriptFunctionData.IS_BUILTIN | ScriptFunctionData.IS_STRICT ); 70.234 - } 70.235 - 70.236 - /** 70.237 - * Factory method for non-constructor built-in functions 70.238 - * 70.239 - * @param name function name 70.240 - * @param methodHandle handle for invocation 70.241 - * @return new ScriptFunction 70.242 - */ 70.243 - static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle) { 70.244 - return makeFunction(name, methodHandle, null); 70.245 - } 70.246 - 70.247 - @Override 70.248 - public ScriptFunction makeSynchronizedFunction(final Object sync) { 70.249 - final MethodHandle mh = MH.insertArguments(ScriptFunction.INVOKE_SYNC, 0, this, sync); 70.250 - return makeFunction(getName(), mh); 70.251 - } 70.252 - 70.253 - /** 70.254 - * Same as {@link ScriptFunction#makeBoundFunction(Object, Object[])}. The only reason we override it is so that we 70.255 - * can expose it. 70.256 - * @param self the self to bind to this function. Can be null (in which case, null is bound as this). 70.257 - * @param args additional arguments to bind to this function. Can be null or empty to not bind additional arguments. 70.258 - * @return a function with the specified self and parameters bound. 70.259 - */ 70.260 - @Override 70.261 - public ScriptFunction makeBoundFunction(final Object self, final Object[] args) { 70.262 - return super.makeBoundFunction(self, args); 70.263 - } 70.264 - 70.265 - /** 70.266 - * This method is used to create a bound function based on this function. 70.267 - * 70.268 - * @param data the {@code ScriptFunctionData} specifying the functions immutable portion. 70.269 - * @return a function initialized from the specified data. Its parent scope will be set to null, therefore the 70.270 - * passed in data should not expect a callee. 70.271 - */ 70.272 - @Override 70.273 - protected ScriptFunction makeBoundFunction(final ScriptFunctionData data) { 70.274 - return new BoundScriptFunctionImpl(data, getTargetFunction()); 70.275 - } 70.276 - 70.277 - // return Object.prototype - used by "allocate" 70.278 - @Override 70.279 - protected final ScriptObject getObjectPrototype() { 70.280 - return Global.objectPrototype(); 70.281 - } 70.282 - 70.283 - @Override 70.284 - public final Object getPrototype() { 70.285 - if (prototype == LAZY_PROTOTYPE) { 70.286 - prototype = new PrototypeObject(this); 70.287 - } 70.288 - return prototype; 70.289 - } 70.290 - 70.291 - @Override 70.292 - public final void setPrototype(final Object newProto) { 70.293 - if (newProto instanceof ScriptObject && newProto != this.prototype && allocatorMap != null) { 70.294 - // Replace our current allocator map with one that is associated with the new prototype. 70.295 - allocatorMap = allocatorMap.changeProto((ScriptObject)newProto); 70.296 - } 70.297 - this.prototype = newProto; 70.298 - } 70.299 - 70.300 - // Internals below.. 70.301 - private void init(final Global global) { 70.302 - this.setInitialProto(global.getFunctionPrototype()); 70.303 - this.prototype = LAZY_PROTOTYPE; 70.304 - 70.305 - // We have to fill user accessor functions late as these are stored 70.306 - // in this object rather than in the PropertyMap of this object. 70.307 - assert objectSpill == null; 70.308 - final ScriptFunction typeErrorThrower = global.getTypeErrorThrower(); 70.309 - if (findProperty("arguments", true) != null) { 70.310 - initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower); 70.311 - } 70.312 - if (findProperty("caller", true) != null) { 70.313 - initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower); 70.314 - } 70.315 - } 70.316 -}
71.1 --- a/src/jdk/nashorn/internal/parser/Parser.java Thu Sep 24 10:00:42 2015 -0700 71.2 +++ b/src/jdk/nashorn/internal/parser/Parser.java Thu Sep 24 10:09:56 2015 -0700 71.3 @@ -84,7 +84,6 @@ 71.4 import jdk.nashorn.internal.ir.ExpressionStatement; 71.5 import jdk.nashorn.internal.ir.ForNode; 71.6 import jdk.nashorn.internal.ir.FunctionNode; 71.7 -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 71.8 import jdk.nashorn.internal.ir.IdentNode; 71.9 import jdk.nashorn.internal.ir.IfNode; 71.10 import jdk.nashorn.internal.ir.IndexNode; 71.11 @@ -513,8 +512,7 @@ 71.12 71.13 return lc.pop(functionNode). 71.14 setBody(lc, newBody). 71.15 - setLastToken(lc, lastToken). 71.16 - setState(lc, errors.hasErrors() ? CompilationState.PARSE_ERROR : CompilationState.PARSED); 71.17 + setLastToken(lc, lastToken); 71.18 } 71.19 71.20 /** 71.21 @@ -805,7 +803,7 @@ 71.22 if (!oldStrictMode && directiveStmts != null) { 71.23 // check that directives preceding this one do not violate strictness 71.24 for (final Node statement : directiveStmts) { 71.25 - // the get value will force unescape of preceeding 71.26 + // the get value will force unescape of preceding 71.27 // escaped string directives 71.28 getValue(statement.getToken()); 71.29 } 71.30 @@ -2469,7 +2467,7 @@ 71.31 // run: function() { println("run"); } 71.32 // }; 71.33 // 71.34 - // The object literal following the "new Constructor()" expresssion 71.35 + // The object literal following the "new Constructor()" expression 71.36 // is passed as an additional (last) argument to the constructor. 71.37 if (!env._no_syntax_extensions && type == LBRACE) { 71.38 arguments.add(objectLiteral());
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 72.2 +++ b/src/jdk/nashorn/internal/runtime/AstSerializer.java Thu Sep 24 10:09:56 2015 -0700 72.3 @@ -0,0 +1,55 @@ 72.4 +/* 72.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 72.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 72.7 + * 72.8 + * This code is free software; you can redistribute it and/or modify it 72.9 + * under the terms of the GNU General Public License version 2 only, as 72.10 + * published by the Free Software Foundation. Oracle designates this 72.11 + * particular file as subject to the "Classpath" exception as provided 72.12 + * by Oracle in the LICENSE file that accompanied this code. 72.13 + * 72.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 72.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 72.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 72.17 + * version 2 for more details (a copy is included in the LICENSE file that 72.18 + * accompanied this code). 72.19 + * 72.20 + * You should have received a copy of the GNU General Public License version 72.21 + * 2 along with this work; if not, write to the Free Software Foundation, 72.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 72.23 + * 72.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 72.25 + * or visit www.oracle.com if you need additional information or have any 72.26 + * questions. 72.27 + */ 72.28 +package jdk.nashorn.internal.runtime; 72.29 + 72.30 +import java.io.ByteArrayOutputStream; 72.31 +import java.io.IOException; 72.32 +import java.io.ObjectOutputStream; 72.33 +import java.util.zip.Deflater; 72.34 +import java.util.zip.DeflaterOutputStream; 72.35 +import jdk.nashorn.internal.ir.FunctionNode; 72.36 +import jdk.nashorn.internal.runtime.options.Options; 72.37 + 72.38 +/** 72.39 + * This static utility class performs serialization of FunctionNode ASTs to a byte array. 72.40 + * The format is a standard Java serialization stream, deflated. 72.41 + */ 72.42 +final class AstSerializer { 72.43 + // Experimentally, we concluded that compression level 4 gives a good tradeoff between serialization speed 72.44 + // and size. 72.45 + private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4); 72.46 + static byte[] serialize(final FunctionNode fn) { 72.47 + final ByteArrayOutputStream out = new ByteArrayOutputStream(); 72.48 + final Deflater deflater = new Deflater(COMPRESSION_LEVEL); 72.49 + try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) { 72.50 + oout.writeObject(fn); 72.51 + } catch (final IOException e) { 72.52 + throw new AssertionError("Unexpected exception serializing function", e); 72.53 + } finally { 72.54 + deflater.end(); 72.55 + } 72.56 + return out.toByteArray(); 72.57 + } 72.58 +}
73.1 --- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java Thu Sep 24 10:00:42 2015 -0700 73.2 +++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java Thu Sep 24 10:09:56 2015 -0700 73.3 @@ -27,6 +27,7 @@ 73.4 import static jdk.nashorn.internal.lookup.Lookup.MH; 73.5 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 73.6 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; 73.7 + 73.8 import java.lang.invoke.CallSite; 73.9 import java.lang.invoke.MethodHandle; 73.10 import java.lang.invoke.MethodHandles; 73.11 @@ -101,7 +102,7 @@ 73.12 /* 73.13 * An optimistic builtin with isOptimistic=true works like any optimistic generated function, i.e. it 73.14 * can throw unwarranted optimism exceptions. As native functions trivially can't have parts of them 73.15 - * regenerated as restof methods, this only works if the methods are atomic/functional in their behavior 73.16 + * regenerated as "restOf" methods, this only works if the methods are atomic/functional in their behavior 73.17 * and doesn't modify state before an UOE can be thrown. If they aren't, we can reexecute a wider version 73.18 * of the same builtin in a recompilation handler for FinalScriptFunctionData. There are several 73.19 * candidate methods in Native* that would benefit from this, but I haven't had time to implement any 73.20 @@ -566,7 +567,7 @@ 73.21 return handle; 73.22 } 73.23 73.24 - // Otherwise, we need a new level of indirection; need to introduce a mutable call site that can relink itslef 73.25 + // Otherwise, we need a new level of indirection; need to introduce a mutable call site that can relink itself 73.26 // to the compiled function's changed target whenever the optimistic assumptions are invalidated. 73.27 final CallSite cs = new MutableCallSite(handle.type()); 73.28 relinkComposableInvoker(cs, this, isConstructor); 73.29 @@ -820,7 +821,7 @@ 73.30 // isn't available, we'll use the old one bound into the call site. 73.31 final OptimismInfo effectiveOptInfo = currentOptInfo != null ? currentOptInfo : oldOptInfo; 73.32 FunctionNode fn = effectiveOptInfo.reparse(); 73.33 - final boolean serialized = effectiveOptInfo.isSerialized(); 73.34 + final boolean cached = fn.isCached(); 73.35 final Compiler compiler = effectiveOptInfo.getCompiler(fn, ct, re); //set to non rest-of 73.36 73.37 if (!shouldRecompile) { 73.38 @@ -828,11 +829,11 @@ 73.39 // recompiled a deoptimized version for an inner invocation. 73.40 // We still need to do the rest of from the beginning 73.41 logRecompile("Rest-of compilation [STANDALONE] ", fn, ct, effectiveOptInfo.invalidatedProgramPoints); 73.42 - return restOfHandle(effectiveOptInfo, compiler.compile(fn, serialized ? CompilationPhases.COMPILE_SERIALIZED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null); 73.43 + return restOfHandle(effectiveOptInfo, compiler.compile(fn, cached ? CompilationPhases.COMPILE_CACHED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null); 73.44 } 73.45 73.46 logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, ct, effectiveOptInfo.invalidatedProgramPoints); 73.47 - fn = compiler.compile(fn, serialized ? CompilationPhases.RECOMPILE_SERIALIZED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE); 73.48 + fn = compiler.compile(fn, cached ? CompilationPhases.RECOMPILE_CACHED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE); 73.49 log.fine("Reusable IR generated"); 73.50 73.51 // compile the rest of the function, and install it 73.52 @@ -956,10 +957,6 @@ 73.53 FunctionNode reparse() { 73.54 return data.reparse(); 73.55 } 73.56 - 73.57 - boolean isSerialized() { 73.58 - return data.isSerialized(); 73.59 - } 73.60 } 73.61 73.62 @SuppressWarnings("unused")
74.1 --- a/src/jdk/nashorn/internal/runtime/Context.java Thu Sep 24 10:00:42 2015 -0700 74.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java Thu Sep 24 10:09:56 2015 -0700 74.3 @@ -153,7 +153,7 @@ 74.4 * Currently we are conservative and associate the name of a builtin class with all 74.5 * its properties, so it's enough to invalidate a property to break all assumptions 74.6 * about a prototype. This can be changed to a more fine grained approach, but no one 74.7 - * ever needs this, given the very rare occurance of swapping out only parts of 74.8 + * ever needs this, given the very rare occurrence of swapping out only parts of 74.9 * a builtin v.s. the entire builtin object 74.10 */ 74.11 private final Map<String, SwitchPoint> builtinSwitchPoints = new HashMap<>(); 74.12 @@ -1456,7 +1456,7 @@ 74.13 * @param level log level 74.14 * @param mh method handle 74.15 * @param paramStart first parameter to print 74.16 - * @param printReturnValue should we print the return vaulue? 74.17 + * @param printReturnValue should we print the return value? 74.18 * @param text debug printout to add 74.19 * 74.20 * @return instrumented method handle, or null if logger not enabled
75.1 --- a/src/jdk/nashorn/internal/runtime/FindProperty.java Thu Sep 24 10:00:42 2015 -0700 75.2 +++ b/src/jdk/nashorn/internal/runtime/FindProperty.java Thu Sep 24 10:09:56 2015 -0700 75.3 @@ -297,4 +297,3 @@ 75.4 } 75.5 75.6 } 75.7 -
76.1 --- a/src/jdk/nashorn/internal/runtime/GlobalConstants.java Thu Sep 24 10:00:42 2015 -0700 76.2 +++ b/src/jdk/nashorn/internal/runtime/GlobalConstants.java Thu Sep 24 10:09:56 2015 -0700 76.3 @@ -67,7 +67,7 @@ 76.4 * 76.5 * Thus everything registered as a global constant gets an extra chance. Set once, 76.6 * reregister the switchpoint. Set twice or more - don't try again forever, or we'd 76.7 - * just end up relinking our way into megamorphisism. 76.8 + * just end up relinking our way into megamorphism. 76.9 * 76.10 * Also it has to be noted that this kind of linking creates a coupling between a Global 76.11 * and the call sites in compiled code belonging to the Context. For this reason, the
77.1 --- a/src/jdk/nashorn/internal/runtime/GlobalFunctions.java Thu Sep 24 10:00:42 2015 -0700 77.2 +++ b/src/jdk/nashorn/internal/runtime/GlobalFunctions.java Thu Sep 24 10:09:56 2015 -0700 77.3 @@ -187,14 +187,14 @@ 77.4 77.5 double result = 0.0; 77.6 int digit; 77.7 - // we should see atleast one valid digit 77.8 + // we should see at least one valid digit 77.9 boolean entered = false; 77.10 while (idx < length) { 77.11 digit = fastDigit(str.charAt(idx++), radix); 77.12 if (digit < 0) { 77.13 break; 77.14 } 77.15 - // we have seen atleast one valid digit in the specified radix 77.16 + // we have seen at least one valid digit in the specified radix 77.17 entered = true; 77.18 result *= radix; 77.19 result += digit;
78.1 --- a/src/jdk/nashorn/internal/runtime/JSONFunctions.java Thu Sep 24 10:00:42 2015 -0700 78.2 +++ b/src/jdk/nashorn/internal/runtime/JSONFunctions.java Thu Sep 24 10:09:56 2015 -0700 78.3 @@ -26,7 +26,6 @@ 78.4 package jdk.nashorn.internal.runtime; 78.5 78.6 import java.lang.invoke.MethodHandle; 78.7 -import java.util.Iterator; 78.8 import java.util.concurrent.Callable; 78.9 import jdk.nashorn.internal.objects.Global; 78.10 import jdk.nashorn.internal.parser.JSONParser;
79.1 --- a/src/jdk/nashorn/internal/runtime/JSType.java Thu Sep 24 10:00:42 2015 -0700 79.2 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Thu Sep 24 10:09:56 2015 -0700 79.3 @@ -1968,7 +1968,7 @@ 79.4 /** 79.5 * Get the unboxed (primitive) type for an object 79.6 * @param o object 79.7 - * @return primive type or Object.class if not primitive 79.8 + * @return primitive type or Object.class if not primitive 79.9 */ 79.10 public static Class<?> unboxedFieldType(final Object o) { 79.11 if (o == null) {
80.1 --- a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java Thu Sep 24 10:00:42 2015 -0700 80.2 +++ b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java Thu Sep 24 10:09:56 2015 -0700 80.3 @@ -206,7 +206,7 @@ 80.4 } 80.5 80.6 @Override 80.7 - protected Object invokeNoSuchProperty(final String key, final int programPoint) { 80.8 + protected Object invokeNoSuchProperty(final String key, final boolean isScope, final int programPoint) { 80.9 final Object retval = createProperty(key); 80.10 if (isValid(programPoint)) { 80.11 throw new UnwarrantedOptimismException(retval, programPoint);
81.1 --- a/src/jdk/nashorn/internal/runtime/ParserException.java Thu Sep 24 10:00:42 2015 -0700 81.2 +++ b/src/jdk/nashorn/internal/runtime/ParserException.java Thu Sep 24 10:09:56 2015 -0700 81.3 @@ -38,7 +38,7 @@ 81.4 private final Source source; 81.5 // token responsible for this exception 81.6 private final long token; 81.7 - // if this is traslated as ECMA error, which type should be used? 81.8 + // if this is translated as ECMA error, which type should be used? 81.9 private final JSErrorType errorType; 81.10 81.11 /**
82.1 --- a/src/jdk/nashorn/internal/runtime/PropertyListeners.java Thu Sep 24 10:00:42 2015 -0700 82.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyListeners.java Thu Sep 24 10:09:56 2015 -0700 82.3 @@ -28,6 +28,7 @@ 82.4 import java.util.Map; 82.5 import java.util.Set; 82.6 import java.util.WeakHashMap; 82.7 +import java.util.concurrent.atomic.LongAdder; 82.8 82.9 /** 82.10 * Helper class to manage property listeners and notification. 82.11 @@ -37,8 +38,15 @@ 82.12 private Map<String, WeakPropertyMapSet> listeners; 82.13 82.14 // These counters are updated in debug mode 82.15 - private static int listenersAdded; 82.16 - private static int listenersRemoved; 82.17 + private static LongAdder listenersAdded; 82.18 + private static LongAdder listenersRemoved; 82.19 + 82.20 + static { 82.21 + if (Context.DEBUG) { 82.22 + listenersAdded = new LongAdder(); 82.23 + listenersRemoved = new LongAdder(); 82.24 + } 82.25 + } 82.26 82.27 /** 82.28 * Copy constructor 82.29 @@ -54,16 +62,16 @@ 82.30 * Return aggregate listeners added to all PropertyListenerManagers 82.31 * @return the listenersAdded 82.32 */ 82.33 - public static int getListenersAdded() { 82.34 - return listenersAdded; 82.35 + public static long getListenersAdded() { 82.36 + return listenersAdded.longValue(); 82.37 } 82.38 82.39 /** 82.40 * Return aggregate listeners removed from all PropertyListenerManagers 82.41 * @return the listenersRemoved 82.42 */ 82.43 - public static int getListenersRemoved() { 82.44 - return listenersRemoved; 82.45 + public static long getListenersRemoved() { 82.46 + return listenersRemoved.longValue(); 82.47 } 82.48 82.49 /** 82.50 @@ -122,7 +130,7 @@ 82.51 */ 82.52 synchronized final void addListener(final String key, final PropertyMap propertyMap) { 82.53 if (Context.DEBUG) { 82.54 - listenersAdded++; 82.55 + listenersAdded.increment(); 82.56 } 82.57 if (listeners == null) { 82.58 listeners = new WeakHashMap<>(); 82.59 @@ -151,6 +159,9 @@ 82.60 propertyMap.propertyAdded(prop); 82.61 } 82.62 listeners.remove(prop.getKey()); 82.63 + if (Context.DEBUG) { 82.64 + listenersRemoved.increment(); 82.65 + } 82.66 } 82.67 } 82.68 } 82.69 @@ -168,6 +179,9 @@ 82.70 propertyMap.propertyDeleted(prop); 82.71 } 82.72 listeners.remove(prop.getKey()); 82.73 + if (Context.DEBUG) { 82.74 + listenersRemoved.increment(); 82.75 + } 82.76 } 82.77 } 82.78 } 82.79 @@ -187,6 +201,9 @@ 82.80 propertyMap.propertyModified(oldProp, newProp); 82.81 } 82.82 listeners.remove(oldProp.getKey()); 82.83 + if (Context.DEBUG) { 82.84 + listenersRemoved.increment(); 82.85 + } 82.86 } 82.87 } 82.88 }
83.1 --- a/src/jdk/nashorn/internal/runtime/PropertyMap.java Thu Sep 24 10:00:42 2015 -0700 83.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java Thu Sep 24 10:09:56 2015 -0700 83.3 @@ -42,6 +42,7 @@ 83.4 import java.util.Iterator; 83.5 import java.util.NoSuchElementException; 83.6 import java.util.WeakHashMap; 83.7 +import java.util.concurrent.atomic.LongAdder; 83.8 import jdk.nashorn.internal.scripts.JO; 83.9 83.10 /** 83.11 @@ -114,7 +115,7 @@ 83.12 } 83.13 83.14 if (Context.DEBUG) { 83.15 - count++; 83.16 + count.increment(); 83.17 } 83.18 } 83.19 83.20 @@ -135,8 +136,8 @@ 83.21 this.freeSlots = propertyMap.freeSlots; 83.22 83.23 if (Context.DEBUG) { 83.24 - count++; 83.25 - clonedCount++; 83.26 + count.increment(); 83.27 + clonedCount.increment(); 83.28 } 83.29 } 83.30 83.31 @@ -328,7 +329,7 @@ 83.32 if (sp != null) { 83.33 protoGetSwitches.remove(key); 83.34 if (Context.DEBUG) { 83.35 - protoInvalidations++; 83.36 + protoInvalidations.increment(); 83.37 } 83.38 SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 83.39 } 83.40 @@ -343,7 +344,7 @@ 83.41 final int size = protoGetSwitches.size(); 83.42 if (size > 0) { 83.43 if (Context.DEBUG) { 83.44 - protoInvalidations += size; 83.45 + protoInvalidations.add(size); 83.46 } 83.47 SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[size])); 83.48 protoGetSwitches.clear(); 83.49 @@ -704,7 +705,7 @@ 83.50 } 83.51 83.52 if (Context.DEBUG && cachedMap != null) { 83.53 - protoHistoryHit++; 83.54 + protoHistoryHit.increment(); 83.55 } 83.56 83.57 return cachedMap; 83.58 @@ -753,7 +754,7 @@ 83.59 83.60 if (historicMap != null) { 83.61 if (Context.DEBUG) { 83.62 - historyHit++; 83.63 + historyHit.increment(); 83.64 } 83.65 83.66 return historicMap; 83.67 @@ -901,7 +902,7 @@ 83.68 } 83.69 83.70 if (Context.DEBUG) { 83.71 - setProtoNewMapCount++; 83.72 + setProtoNewMapCount.increment(); 83.73 } 83.74 83.75 final PropertyMap newMap = new PropertyMap(this); 83.76 @@ -1021,52 +1022,62 @@ 83.77 } 83.78 83.79 // counters updated only in debug mode 83.80 - private static int count; 83.81 - private static int clonedCount; 83.82 - private static int historyHit; 83.83 - private static int protoInvalidations; 83.84 - private static int protoHistoryHit; 83.85 - private static int setProtoNewMapCount; 83.86 + private static LongAdder count; 83.87 + private static LongAdder clonedCount; 83.88 + private static LongAdder historyHit; 83.89 + private static LongAdder protoInvalidations; 83.90 + private static LongAdder protoHistoryHit; 83.91 + private static LongAdder setProtoNewMapCount; 83.92 + static { 83.93 + if (Context.DEBUG) { 83.94 + count = new LongAdder(); 83.95 + clonedCount = new LongAdder(); 83.96 + historyHit = new LongAdder(); 83.97 + protoInvalidations = new LongAdder(); 83.98 + protoHistoryHit = new LongAdder(); 83.99 + setProtoNewMapCount = new LongAdder(); 83.100 + } 83.101 + } 83.102 83.103 /** 83.104 * @return Total number of maps. 83.105 */ 83.106 - public static int getCount() { 83.107 - return count; 83.108 + public static long getCount() { 83.109 + return count.longValue(); 83.110 } 83.111 83.112 /** 83.113 * @return The number of maps that were cloned. 83.114 */ 83.115 - public static int getClonedCount() { 83.116 - return clonedCount; 83.117 + public static long getClonedCount() { 83.118 + return clonedCount.longValue(); 83.119 } 83.120 83.121 /** 83.122 * @return The number of times history was successfully used. 83.123 */ 83.124 - public static int getHistoryHit() { 83.125 - return historyHit; 83.126 + public static long getHistoryHit() { 83.127 + return historyHit.longValue(); 83.128 } 83.129 83.130 /** 83.131 * @return The number of times prototype changes caused invalidation. 83.132 */ 83.133 - public static int getProtoInvalidations() { 83.134 - return protoInvalidations; 83.135 + public static long getProtoInvalidations() { 83.136 + return protoInvalidations.longValue(); 83.137 } 83.138 83.139 /** 83.140 * @return The number of times proto history was successfully used. 83.141 */ 83.142 - public static int getProtoHistoryHit() { 83.143 - return protoHistoryHit; 83.144 + public static long getProtoHistoryHit() { 83.145 + return protoHistoryHit.longValue(); 83.146 } 83.147 83.148 /** 83.149 * @return The number of times prototypes were modified. 83.150 */ 83.151 - public static int getSetProtoNewMapCount() { 83.152 - return setProtoNewMapCount; 83.153 + public static long getSetProtoNewMapCount() { 83.154 + return setProtoNewMapCount.longValue(); 83.155 } 83.156 }
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 84.2 +++ b/src/jdk/nashorn/internal/runtime/PrototypeObject.java Thu Sep 24 10:09:56 2015 -0700 84.3 @@ -0,0 +1,118 @@ 84.4 +/* 84.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 84.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 84.7 + * 84.8 + * This code is free software; you can redistribute it and/or modify it 84.9 + * under the terms of the GNU General Public License version 2 only, as 84.10 + * published by the Free Software Foundation. Oracle designates this 84.11 + * particular file as subject to the "Classpath" exception as provided 84.12 + * by Oracle in the LICENSE file that accompanied this code. 84.13 + * 84.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 84.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 84.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 84.17 + * version 2 for more details (a copy is included in the LICENSE file that 84.18 + * accompanied this code). 84.19 + * 84.20 + * You should have received a copy of the GNU General Public License version 84.21 + * 2 along with this work; if not, write to the Free Software Foundation, 84.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 84.23 + * 84.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 84.25 + * or visit www.oracle.com if you need additional information or have any 84.26 + * questions. 84.27 + */ 84.28 + 84.29 +package jdk.nashorn.internal.runtime; 84.30 + 84.31 +import static jdk.nashorn.internal.lookup.Lookup.MH; 84.32 +import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 84.33 + 84.34 +import java.lang.invoke.MethodHandle; 84.35 +import java.lang.invoke.MethodHandles; 84.36 +import java.util.ArrayList; 84.37 +import jdk.nashorn.internal.objects.Global; 84.38 + 84.39 +/** 84.40 + * Instances of this class serve as "prototype" object for script functions. 84.41 + * The purpose is to expose "constructor" property from "prototype". Also, nasgen 84.42 + * generated prototype classes extend from this class. 84.43 + */ 84.44 +public class PrototypeObject extends ScriptObject { 84.45 + private static final PropertyMap map$; 84.46 + 84.47 + private Object constructor; 84.48 + 84.49 + private static final MethodHandle GET_CONSTRUCTOR = findOwnMH("getConstructor", Object.class, Object.class); 84.50 + private static final MethodHandle SET_CONSTRUCTOR = findOwnMH("setConstructor", void.class, Object.class, Object.class); 84.51 + 84.52 + static { 84.53 + final ArrayList<Property> properties = new ArrayList<>(1); 84.54 + properties.add(AccessorProperty.create("constructor", Property.NOT_ENUMERABLE, GET_CONSTRUCTOR, SET_CONSTRUCTOR)); 84.55 + map$ = PropertyMap.newMap(properties); 84.56 + } 84.57 + 84.58 + private PrototypeObject(final Global global, final PropertyMap map) { 84.59 + super(global.getObjectPrototype(), map != map$? map.addAll(map$) : map$); 84.60 + } 84.61 + 84.62 + /** 84.63 + * Prototype constructor 84.64 + */ 84.65 + protected PrototypeObject() { 84.66 + this(Global.instance(), map$); 84.67 + } 84.68 + 84.69 + /** 84.70 + * PropertyObject constructor 84.71 + * 84.72 + * @param map property map 84.73 + */ 84.74 + protected PrototypeObject(final PropertyMap map) { 84.75 + this(Global.instance(), map); 84.76 + } 84.77 + 84.78 + /** 84.79 + * PropertyObject constructor 84.80 + * 84.81 + * @param func constructor function 84.82 + */ 84.83 + protected PrototypeObject(final ScriptFunction func) { 84.84 + this(Global.instance(), map$); 84.85 + this.constructor = func; 84.86 + } 84.87 + 84.88 + /** 84.89 + * Get the constructor for this {@code PrototypeObject} 84.90 + * @param self self reference 84.91 + * @return constructor, probably, but not necessarily, a {@link ScriptFunction} 84.92 + */ 84.93 + public static Object getConstructor(final Object self) { 84.94 + return (self instanceof PrototypeObject) ? 84.95 + ((PrototypeObject)self).getConstructor() : 84.96 + UNDEFINED; 84.97 + } 84.98 + 84.99 + /** 84.100 + * Reset the constructor for this {@code PrototypeObject} 84.101 + * @param self self reference 84.102 + * @param constructor constructor, probably, but not necessarily, a {@link ScriptFunction} 84.103 + */ 84.104 + public static void setConstructor(final Object self, final Object constructor) { 84.105 + if (self instanceof PrototypeObject) { 84.106 + ((PrototypeObject)self).setConstructor(constructor); 84.107 + } 84.108 + } 84.109 + 84.110 + private Object getConstructor() { 84.111 + return constructor; 84.112 + } 84.113 + 84.114 + private void setConstructor(final Object constructor) { 84.115 + this.constructor = constructor; 84.116 + } 84.117 + 84.118 + private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { 84.119 + return MH.findStatic(MethodHandles.lookup(), PrototypeObject.class, name, MH.type(rtype, types)); 84.120 + } 84.121 +}
85.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Thu Sep 24 10:00:42 2015 -0700 85.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Thu Sep 24 10:09:56 2015 -0700 85.3 @@ -26,16 +26,25 @@ 85.4 package jdk.nashorn.internal.runtime; 85.5 85.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 85.7 + 85.8 import java.io.IOException; 85.9 import java.lang.invoke.MethodHandle; 85.10 import java.lang.invoke.MethodHandles; 85.11 import java.lang.invoke.MethodType; 85.12 +import java.lang.ref.Reference; 85.13 +import java.lang.ref.SoftReference; 85.14 import java.util.Collection; 85.15 import java.util.Collections; 85.16 import java.util.HashSet; 85.17 +import java.util.IdentityHashMap; 85.18 import java.util.Map; 85.19 import java.util.Set; 85.20 import java.util.TreeMap; 85.21 +import java.util.concurrent.ExecutorService; 85.22 +import java.util.concurrent.LinkedBlockingDeque; 85.23 +import java.util.concurrent.ThreadFactory; 85.24 +import java.util.concurrent.ThreadPoolExecutor; 85.25 +import java.util.concurrent.TimeUnit; 85.26 import jdk.internal.dynalink.support.NameCodec; 85.27 import jdk.nashorn.internal.codegen.Compiler; 85.28 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; 85.29 @@ -45,8 +54,15 @@ 85.30 import jdk.nashorn.internal.codegen.OptimisticTypesPersistence; 85.31 import jdk.nashorn.internal.codegen.TypeMap; 85.32 import jdk.nashorn.internal.codegen.types.Type; 85.33 +import jdk.nashorn.internal.ir.Block; 85.34 +import jdk.nashorn.internal.ir.ForNode; 85.35 import jdk.nashorn.internal.ir.FunctionNode; 85.36 +import jdk.nashorn.internal.ir.IdentNode; 85.37 import jdk.nashorn.internal.ir.LexicalContext; 85.38 +import jdk.nashorn.internal.ir.Node; 85.39 +import jdk.nashorn.internal.ir.SwitchNode; 85.40 +import jdk.nashorn.internal.ir.Symbol; 85.41 +import jdk.nashorn.internal.ir.TryNode; 85.42 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 85.43 import jdk.nashorn.internal.objects.Global; 85.44 import jdk.nashorn.internal.parser.Parser; 85.45 @@ -55,6 +71,7 @@ 85.46 import jdk.nashorn.internal.runtime.logging.DebugLogger; 85.47 import jdk.nashorn.internal.runtime.logging.Loggable; 85.48 import jdk.nashorn.internal.runtime.logging.Logger; 85.49 +import jdk.nashorn.internal.runtime.options.Options; 85.50 /** 85.51 * This is a subclass that represents a script function that may be regenerated, 85.52 * for example with specialization based on call site types, or lazily generated. 85.53 @@ -66,6 +83,8 @@ 85.54 /** Prefix used for all recompiled script classes */ 85.55 public static final String RECOMPILATION_PREFIX = "Recompilation$"; 85.56 85.57 + private static final ExecutorService astSerializerExecutorService = createAstSerializerExecutorService(); 85.58 + 85.59 /** Unique function node id for this function node */ 85.60 private final int functionNodeId; 85.61 85.62 @@ -77,8 +96,12 @@ 85.63 /** Source from which FunctionNode was parsed. */ 85.64 private transient Source source; 85.65 85.66 - /** Serialized, compressed form of the AST. Used by split functions as they can't be reparsed from source. */ 85.67 - private final byte[] serializedAst; 85.68 + /** 85.69 + * Cached form of the AST. Either a {@code SerializedAst} object used by split functions as they can't be 85.70 + * reparsed from source, or a soft reference to a {@code FunctionNode} for other functions (it is safe 85.71 + * to be cleared as they can be reparsed). 85.72 + */ 85.73 + private volatile Object cachedAst; 85.74 85.75 /** Token of this function within the source. */ 85.76 private final long token; 85.77 @@ -128,7 +151,6 @@ 85.78 * @param nestedFunctions nested function map 85.79 * @param externalScopeDepths external scope depths 85.80 * @param internalSymbols internal symbols to method, defined in its scope 85.81 - * @param serializedAst a serialized AST representation. Normally only used for split functions. 85.82 */ 85.83 public RecompilableScriptFunctionData( 85.84 final FunctionNode functionNode, 85.85 @@ -136,8 +158,7 @@ 85.86 final AllocationStrategy allocationStrategy, 85.87 final Map<Integer, RecompilableScriptFunctionData> nestedFunctions, 85.88 final Map<String, Integer> externalScopeDepths, 85.89 - final Set<String> internalSymbols, 85.90 - final byte[] serializedAst) { 85.91 + final Set<String> internalSymbols) { 85.92 85.93 super(functionName(functionNode), 85.94 Math.min(functionNode.getParameters().size(), MAX_ARITY), 85.95 @@ -161,7 +182,6 @@ 85.96 nfn.setParent(this); 85.97 } 85.98 85.99 - this.serializedAst = serializedAst; 85.100 createLogger(); 85.101 } 85.102 85.103 @@ -244,7 +264,7 @@ 85.104 * @return parent data, or null if non exists and also null IF UNKNOWN. 85.105 */ 85.106 public RecompilableScriptFunctionData getParent() { 85.107 - return parent; 85.108 + return parent; 85.109 } 85.110 85.111 void setParent(final RecompilableScriptFunctionData parent) { 85.112 @@ -358,13 +378,11 @@ 85.113 return allocationStrategy.allocate(map); 85.114 } 85.115 85.116 - boolean isSerialized() { 85.117 - return serializedAst != null; 85.118 - } 85.119 - 85.120 FunctionNode reparse() { 85.121 - if (isSerialized()) { 85.122 - return deserialize(); 85.123 + final FunctionNode cachedFunction = getCachedAst(); 85.124 + if (cachedFunction != null) { 85.125 + assert cachedFunction.isCached(); 85.126 + return cachedFunction; 85.127 } 85.128 85.129 final int descPosition = Token.descPosition(token); 85.130 @@ -391,7 +409,104 @@ 85.131 return (isProgram() ? program : extractFunctionFromScript(program)).setName(null, functionName); 85.132 } 85.133 85.134 - private FunctionNode deserialize() { 85.135 + private FunctionNode getCachedAst() { 85.136 + final Object lCachedAst = cachedAst; 85.137 + // Are we softly caching the AST? 85.138 + if (lCachedAst instanceof Reference<?>) { 85.139 + final FunctionNode fn = (FunctionNode)((Reference<?>)lCachedAst).get(); 85.140 + if (fn != null) { 85.141 + // Yes we are - this is fast 85.142 + return cloneSymbols(fn); 85.143 + } 85.144 + // Are we strongly caching a serialized AST (for split functions only)? 85.145 + } else if (lCachedAst instanceof SerializedAst) { 85.146 + final SerializedAst serializedAst = (SerializedAst)lCachedAst; 85.147 + // Even so, are we also softly caching the AST? 85.148 + final FunctionNode cachedFn = serializedAst.cachedAst.get(); 85.149 + if (cachedFn != null) { 85.150 + // Yes we are - this is fast 85.151 + return cloneSymbols(cachedFn); 85.152 + } 85.153 + final FunctionNode deserializedFn = deserialize(serializedAst.serializedAst); 85.154 + // Softly cache after deserialization, maybe next time we won't need to deserialize 85.155 + serializedAst.cachedAst = new SoftReference<>(deserializedFn); 85.156 + return deserializedFn; 85.157 + } 85.158 + // No cached representation; return null for reparsing 85.159 + return null; 85.160 + } 85.161 + 85.162 + /** 85.163 + * Sets the AST to cache in this function 85.164 + * @param astToCache the new AST to cache 85.165 + */ 85.166 + public void setCachedAst(final FunctionNode astToCache) { 85.167 + assert astToCache.getId() == functionNodeId; // same function 85.168 + assert !(cachedAst instanceof SerializedAst); // Can't overwrite serialized AST 85.169 + 85.170 + final boolean isSplit = astToCache.isSplit(); 85.171 + // If we're caching a split function, we're doing it in the eager pass, hence there can be no other 85.172 + // cached representation already. In other words, isSplit implies cachedAst == null. 85.173 + assert !isSplit || cachedAst == null; // 85.174 + 85.175 + final FunctionNode symbolClonedAst = cloneSymbols(astToCache); 85.176 + final Reference<FunctionNode> ref = new SoftReference<>(symbolClonedAst); 85.177 + cachedAst = ref; 85.178 + 85.179 + // Asynchronously serialize split functions. 85.180 + if (isSplit) { 85.181 + astSerializerExecutorService.execute(new Runnable() { 85.182 + @Override 85.183 + public void run() { 85.184 + cachedAst = new SerializedAst(symbolClonedAst, ref); 85.185 + } 85.186 + }); 85.187 + } 85.188 + } 85.189 + 85.190 + /** 85.191 + * Creates the AST serializer executor service used for in-memory serialization of split functions' ASTs. 85.192 + * It is created with an unbounded queue (so it can queue any number of pending tasks). Its core and max 85.193 + * threads is the same, but they are all allowed to time out so when there's no work, they can all go 85.194 + * away. The threads will be daemons, and they will time out if idle for a minute. Their priority is also 85.195 + * slightly lower than normal priority as we'd prefer the CPU to keep running the program; serializing 85.196 + * split function is a memory conservation measure (it allows us to release the AST), it can wait a bit. 85.197 + * @return an executor service with above described characteristics. 85.198 + */ 85.199 + private static ExecutorService createAstSerializerExecutorService() { 85.200 + final int threads = Math.max(1, Options.getIntProperty("nashorn.serialize.threads", Runtime.getRuntime().availableProcessors() / 2)); 85.201 + final ThreadPoolExecutor service = new ThreadPoolExecutor(threads, threads, 1L, TimeUnit.MINUTES, new LinkedBlockingDeque<Runnable>(), 85.202 + new ThreadFactory() { 85.203 + @Override 85.204 + public Thread newThread(final Runnable r) { 85.205 + final Thread t = new Thread(r, "Nashorn AST Serializer"); 85.206 + t.setDaemon(true); 85.207 + t.setPriority(Thread.NORM_PRIORITY - 1); 85.208 + return t; 85.209 + } 85.210 + }); 85.211 + service.allowCoreThreadTimeOut(true); 85.212 + return service; 85.213 + } 85.214 + 85.215 + /** 85.216 + * A tuple of a serialized AST and a soft reference to a deserialized AST. This is used to cache split 85.217 + * functions. Since split functions are altered from their source form, they can't be reparsed from 85.218 + * source. While we could just use the {@code byte[]} representation in {@link RecompilableScriptFunctionData#cachedAst} 85.219 + * we're using this tuple instead to also keep a deserialized AST around in memory to cut down on 85.220 + * deserialization costs. 85.221 + */ 85.222 + private static class SerializedAst { 85.223 + private final byte[] serializedAst; 85.224 + private volatile Reference<FunctionNode> cachedAst; 85.225 + 85.226 + SerializedAst(final FunctionNode fn, final Reference<FunctionNode> cachedAst) { 85.227 + this.serializedAst = AstSerializer.serialize(fn); 85.228 + this.cachedAst = cachedAst; 85.229 + } 85.230 + } 85.231 + 85.232 + private FunctionNode deserialize(final byte[] serializedAst) { 85.233 final ScriptEnvironment env = installer.getOwner(); 85.234 final Timing timing = env._timing; 85.235 final long t1 = System.nanoTime(); 85.236 @@ -402,6 +517,107 @@ 85.237 } 85.238 } 85.239 85.240 + private FunctionNode cloneSymbols(final FunctionNode fn) { 85.241 + final IdentityHashMap<Symbol, Symbol> symbolReplacements = new IdentityHashMap<>(); 85.242 + final boolean cached = fn.isCached(); 85.243 + // blockDefinedSymbols is used to re-mark symbols defined outside the function as global. We only 85.244 + // need to do this when we cache an eagerly parsed function (which currently means a split one, as we 85.245 + // don't cache non-split functions from the eager pass); those already cached, or those not split 85.246 + // don't need this step. 85.247 + final Set<Symbol> blockDefinedSymbols = fn.isSplit() && !cached ? Collections.newSetFromMap(new IdentityHashMap<Symbol, Boolean>()) : null; 85.248 + FunctionNode newFn = (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 85.249 + 85.250 + private Symbol getReplacement(final Symbol original) { 85.251 + if (original == null) { 85.252 + return null; 85.253 + } 85.254 + final Symbol existingReplacement = symbolReplacements.get(original); 85.255 + if (existingReplacement != null) { 85.256 + return existingReplacement; 85.257 + } 85.258 + final Symbol newReplacement = original.clone(); 85.259 + symbolReplacements.put(original, newReplacement); 85.260 + return newReplacement; 85.261 + } 85.262 + 85.263 + @Override 85.264 + public Node leaveIdentNode(final IdentNode identNode) { 85.265 + final Symbol oldSymbol = identNode.getSymbol(); 85.266 + if (oldSymbol != null) { 85.267 + final Symbol replacement = getReplacement(oldSymbol); 85.268 + return identNode.setSymbol(replacement); 85.269 + } 85.270 + return identNode; 85.271 + } 85.272 + 85.273 + @Override 85.274 + public Node leaveForNode(final ForNode forNode) { 85.275 + return ensureUniqueLabels(forNode.setIterator(lc, getReplacement(forNode.getIterator()))); 85.276 + } 85.277 + 85.278 + @Override 85.279 + public Node leaveSwitchNode(final SwitchNode switchNode) { 85.280 + return ensureUniqueLabels(switchNode.setTag(lc, getReplacement(switchNode.getTag()))); 85.281 + } 85.282 + 85.283 + @Override 85.284 + public Node leaveTryNode(final TryNode tryNode) { 85.285 + return ensureUniqueLabels(tryNode.setException(lc, getReplacement(tryNode.getException()))); 85.286 + } 85.287 + 85.288 + @Override 85.289 + public boolean enterBlock(final Block block) { 85.290 + for(final Symbol symbol: block.getSymbols()) { 85.291 + final Symbol replacement = getReplacement(symbol); 85.292 + if (blockDefinedSymbols != null) { 85.293 + blockDefinedSymbols.add(replacement); 85.294 + } 85.295 + } 85.296 + return true; 85.297 + } 85.298 + 85.299 + @Override 85.300 + public Node leaveBlock(final Block block) { 85.301 + return ensureUniqueLabels(block.replaceSymbols(lc, symbolReplacements)); 85.302 + } 85.303 + 85.304 + @Override 85.305 + public Node leaveFunctionNode(final FunctionNode functionNode) { 85.306 + return functionNode.setParameters(lc, functionNode.visitParameters(this)); 85.307 + } 85.308 + 85.309 + @Override 85.310 + protected Node leaveDefault(final Node node) { 85.311 + return ensureUniqueLabels(node); 85.312 + }; 85.313 + 85.314 + private Node ensureUniqueLabels(final Node node) { 85.315 + // If we're returning a cached AST, we must also ensure unique labels 85.316 + return cached ? node.ensureUniqueLabels(lc) : node; 85.317 + } 85.318 + }); 85.319 + 85.320 + if (blockDefinedSymbols != null) { 85.321 + // Mark all symbols not defined in blocks as globals 85.322 + Block newBody = null; 85.323 + for(final Symbol symbol: symbolReplacements.values()) { 85.324 + if(!blockDefinedSymbols.contains(symbol)) { 85.325 + assert symbol.isScope(); // must be scope 85.326 + assert externalScopeDepths.containsKey(symbol.getName()); // must be known to us as an external 85.327 + // Register it in the function body symbol table as a new global symbol 85.328 + symbol.setFlags((symbol.getFlags() & ~Symbol.KINDMASK) | Symbol.IS_GLOBAL); 85.329 + if (newBody == null) { 85.330 + newBody = newFn.getBody().copyWithNewSymbols(); 85.331 + newFn = newFn.setBody(null, newBody); 85.332 + } 85.333 + assert newBody.getExistingSymbol(symbol.getName()) == null; // must not be defined in the body already 85.334 + newBody.putSymbol(symbol); 85.335 + } 85.336 + } 85.337 + } 85.338 + return newFn.setCached(null); 85.339 + } 85.340 + 85.341 private boolean getFunctionFlag(final int flag) { 85.342 return (functionFlags & flag) != 0; 85.343 } 85.344 @@ -512,9 +728,9 @@ 85.345 final FunctionNode fn = reparse(); 85.346 final Compiler compiler = getCompiler(fn, actualCallSiteType, runtimeScope); 85.347 final FunctionNode compiledFn = compiler.compile(fn, 85.348 - isSerialized() ? CompilationPhases.COMPILE_ALL_SERIALIZED : CompilationPhases.COMPILE_ALL); 85.349 + fn.isCached() ? CompilationPhases.COMPILE_ALL_CACHED : CompilationPhases.COMPILE_ALL); 85.350 85.351 - if (persist && !compiledFn.getFlag(FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION)) { 85.352 + if (persist && !compiledFn.hasApplyToCallSpecialization()) { 85.353 compiler.persistClassInfo(cacheKey, compiledFn); 85.354 } 85.355 return new FunctionInitializer(compiledFn, compiler.getInvalidatedProgramPoints());
86.1 --- a/src/jdk/nashorn/internal/runtime/Scope.java Thu Sep 24 10:00:42 2015 -0700 86.2 +++ b/src/jdk/nashorn/internal/runtime/Scope.java Thu Sep 24 10:09:56 2015 -0700 86.3 @@ -27,6 +27,7 @@ 86.4 86.5 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup; 86.6 86.7 +import java.util.concurrent.atomic.LongAdder; 86.8 import jdk.nashorn.internal.codegen.CompilerConstants; 86.9 86.10 /** 86.11 @@ -38,7 +39,7 @@ 86.12 private int splitState = -1; 86.13 86.14 /** This is updated only in debug mode - counts number of {@code ScriptObject} instances created that are scope */ 86.15 - private static int count; 86.16 + private static final LongAdder count = Context.DEBUG ? new LongAdder() : null; 86.17 86.18 /** Method handle that points to {@link Scope#getSplitState}. */ 86.19 public static final CompilerConstants.Call GET_SPLIT_STATE = virtualCallNoLookup(Scope.class, "getSplitState", int.class); 86.20 @@ -52,9 +53,7 @@ 86.21 */ 86.22 public Scope(final PropertyMap map) { 86.23 super(map); 86.24 - if (Context.DEBUG) { 86.25 - count++; 86.26 - } 86.27 + incrementCount(); 86.28 } 86.29 86.30 /** 86.31 @@ -65,9 +64,7 @@ 86.32 */ 86.33 public Scope(final ScriptObject proto, final PropertyMap map) { 86.34 super(proto, map); 86.35 - if (Context.DEBUG) { 86.36 - count++; 86.37 - } 86.38 + incrementCount(); 86.39 } 86.40 86.41 /** 86.42 @@ -79,9 +76,7 @@ 86.43 */ 86.44 public Scope(final PropertyMap map, final long[] primitiveSpill, final Object[] objectSpill) { 86.45 super(map, primitiveSpill, objectSpill); 86.46 - if (Context.DEBUG) { 86.47 - count++; 86.48 - } 86.49 + incrementCount(); 86.50 } 86.51 86.52 @Override 86.53 @@ -123,7 +118,13 @@ 86.54 * 86.55 * @return number of scope ScriptObjects created 86.56 */ 86.57 - public static int getScopeCount() { 86.58 - return count; 86.59 + public static long getScopeCount() { 86.60 + return count != null ? count.sum() : 0; 86.61 + } 86.62 + 86.63 + private static void incrementCount() { 86.64 + if (Context.DEBUG) { 86.65 + count.increment(); 86.66 + } 86.67 } 86.68 }
87.1 --- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Thu Sep 24 10:00:42 2015 -0700 87.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Thu Sep 24 10:09:56 2015 -0700 87.3 @@ -46,6 +46,11 @@ 87.4 * and output and error writers, top level Namespace etc. 87.5 */ 87.6 public final class ScriptEnvironment { 87.7 + // Primarily intended to be used in test environments so that eager compilation tests work without an 87.8 + // error when tested with optimistic compilation. 87.9 + private static final boolean ALLOW_EAGER_COMPILATION_SILENT_OVERRIDE = Options.getBooleanProperty( 87.10 + "nashorn.options.allowEagerCompilationSilentOverride", false); 87.11 + 87.12 /** Output writer for this environment */ 87.13 private final PrintWriter out; 87.14 87.15 @@ -237,8 +242,20 @@ 87.16 } 87.17 _fx = options.getBoolean("fx"); 87.18 _global_per_engine = options.getBoolean("global.per.engine"); 87.19 - _lazy_compilation = options.getBoolean("lazy.compilation"); 87.20 _optimistic_types = options.getBoolean("optimistic.types"); 87.21 + final boolean lazy_compilation = options.getBoolean("lazy.compilation"); 87.22 + if (!lazy_compilation && _optimistic_types) { 87.23 + if (!ALLOW_EAGER_COMPILATION_SILENT_OVERRIDE) { 87.24 + throw new IllegalStateException( 87.25 + ECMAErrors.getMessage( 87.26 + "config.error.eagerCompilationConflictsWithOptimisticTypes", 87.27 + options.getOptionTemplateByKey("lazy.compilation").getName(), 87.28 + options.getOptionTemplateByKey("optimistic.types").getName())); 87.29 + } 87.30 + _lazy_compilation = true; 87.31 + } else { 87.32 + _lazy_compilation = lazy_compilation; 87.33 + } 87.34 _loader_per_compile = options.getBoolean("loader.per.compile"); 87.35 _no_java = options.getBoolean("no.java"); 87.36 _no_syntax_extensions = options.getBoolean("no.syntax.extensions");
88.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Sep 24 10:00:42 2015 -0700 88.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Sep 24 10:09:56 2015 -0700 88.3 @@ -22,7 +22,6 @@ 88.4 * or visit www.oracle.com if you need additional information or have any 88.5 * questions. 88.6 */ 88.7 - 88.8 package jdk.nashorn.internal.runtime; 88.9 88.10 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup; 88.11 @@ -40,6 +39,7 @@ 88.12 import java.util.Collections; 88.13 import java.util.HashSet; 88.14 import java.util.List; 88.15 +import java.util.concurrent.atomic.LongAdder; 88.16 import jdk.internal.dynalink.CallSiteDescriptor; 88.17 import jdk.internal.dynalink.linker.GuardedInvocation; 88.18 import jdk.internal.dynalink.linker.LinkRequest; 88.19 @@ -55,38 +55,54 @@ 88.20 import jdk.nashorn.internal.runtime.logging.DebugLogger; 88.21 88.22 /** 88.23 - * Runtime representation of a JavaScript function. 88.24 + * Runtime representation of a JavaScript function. This class has only private 88.25 + * and protected constructors. There are no *public* constructors - but only 88.26 + * factory methods that follow the naming pattern "createXYZ". 88.27 */ 88.28 -public abstract class ScriptFunction extends ScriptObject { 88.29 +public class ScriptFunction extends ScriptObject { 88.30 88.31 - /** Method handle for prototype getter for this ScriptFunction */ 88.32 + /** 88.33 + * Method handle for prototype getter for this ScriptFunction 88.34 + */ 88.35 public static final MethodHandle G$PROTOTYPE = findOwnMH_S("G$prototype", Object.class, Object.class); 88.36 88.37 - /** Method handle for prototype setter for this ScriptFunction */ 88.38 + /** 88.39 + * Method handle for prototype setter for this ScriptFunction 88.40 + */ 88.41 public static final MethodHandle S$PROTOTYPE = findOwnMH_S("S$prototype", void.class, Object.class, Object.class); 88.42 88.43 - /** Method handle for length getter for this ScriptFunction */ 88.44 + /** 88.45 + * Method handle for length getter for this ScriptFunction 88.46 + */ 88.47 public static final MethodHandle G$LENGTH = findOwnMH_S("G$length", int.class, Object.class); 88.48 88.49 - /** Method handle for name getter for this ScriptFunction */ 88.50 + /** 88.51 + * Method handle for name getter for this ScriptFunction 88.52 + */ 88.53 public static final MethodHandle G$NAME = findOwnMH_S("G$name", Object.class, Object.class); 88.54 88.55 - /** Method handle used for implementing sync() in mozilla_compat */ 88.56 + /** 88.57 + * Method handle used for implementing sync() in mozilla_compat 88.58 + */ 88.59 public static final MethodHandle INVOKE_SYNC = findOwnMH_S("invokeSync", Object.class, ScriptFunction.class, Object.class, Object.class, Object[].class); 88.60 88.61 - /** Method handle for allocate function for this ScriptFunction */ 88.62 + /** 88.63 + * Method handle for allocate function for this ScriptFunction 88.64 + */ 88.65 static final MethodHandle ALLOCATE = findOwnMH_V("allocate", Object.class); 88.66 88.67 private static final MethodHandle WRAPFILTER = findOwnMH_S("wrapFilter", Object.class, Object.class); 88.68 88.69 private static final MethodHandle SCRIPTFUNCTION_GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class); 88.70 88.71 - /** method handle to scope getter for this ScriptFunction */ 88.72 + /** 88.73 + * method handle to scope getter for this ScriptFunction 88.74 + */ 88.75 public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class); 88.76 88.77 - private static final MethodHandle IS_FUNCTION_MH = findOwnMH_S("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class); 88.78 + private static final MethodHandle IS_FUNCTION_MH = findOwnMH_S("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class); 88.79 88.80 - private static final MethodHandle IS_APPLY_FUNCTION = findOwnMH_S("isApplyFunction", boolean.class, boolean.class, Object.class, Object.class); 88.81 + private static final MethodHandle IS_APPLY_FUNCTION = findOwnMH_S("isApplyFunction", boolean.class, boolean.class, Object.class, Object.class); 88.82 88.83 private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH_S("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class); 88.84 88.85 @@ -94,55 +110,298 @@ 88.86 88.87 private static final MethodHandle WRAP_THIS = MH.findStatic(MethodHandles.lookup(), ScriptFunctionData.class, "wrapThis", MH.type(Object.class, Object.class)); 88.88 88.89 - /** The parent scope. */ 88.90 + // various property maps used for different kinds of functions 88.91 + // property map for anonymous function that serves as Function.prototype 88.92 + private static final PropertyMap anonmap$; 88.93 + // property map for strict mode functions 88.94 + private static final PropertyMap strictmodemap$; 88.95 + // property map for bound functions 88.96 + private static final PropertyMap boundfunctionmap$; 88.97 + // property map for non-strict, non-bound functions. 88.98 + private static final PropertyMap map$; 88.99 + 88.100 + // Marker object for lazily initialized prototype object 88.101 + private static final Object LAZY_PROTOTYPE = new Object(); 88.102 + 88.103 + private static PropertyMap createStrictModeMap(final PropertyMap map) { 88.104 + final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE; 88.105 + PropertyMap newMap = map; 88.106 + // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors. 88.107 + newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags)); 88.108 + newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags)); 88.109 + return newMap; 88.110 + } 88.111 + 88.112 + private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) { 88.113 + // Bound function map is same as strict function map, but additionally lacks the "prototype" property, see 88.114 + // ECMAScript 5.1 section 15.3.4.5 88.115 + return strictModeMap.deleteProperty(strictModeMap.findProperty("prototype")); 88.116 + } 88.117 + 88.118 + static { 88.119 + anonmap$ = PropertyMap.newMap(); 88.120 + final ArrayList<Property> properties = new ArrayList<>(3); 88.121 + properties.add(AccessorProperty.create("prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE)); 88.122 + properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null)); 88.123 + properties.add(AccessorProperty.create("name", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null)); 88.124 + map$ = PropertyMap.newMap(properties); 88.125 + strictmodemap$ = createStrictModeMap(map$); 88.126 + boundfunctionmap$ = createBoundFunctionMap(strictmodemap$); 88.127 + } 88.128 + 88.129 + private static boolean isStrict(final int flags) { 88.130 + return (flags & ScriptFunctionData.IS_STRICT) != 0; 88.131 + } 88.132 + 88.133 + // Choose the map based on strict mode! 88.134 + private static PropertyMap getMap(final boolean strict) { 88.135 + return strict ? strictmodemap$ : map$; 88.136 + } 88.137 + 88.138 + /** 88.139 + * The parent scope. 88.140 + */ 88.141 private final ScriptObject scope; 88.142 88.143 private final ScriptFunctionData data; 88.144 88.145 - /** The property map used for newly allocated object when function is used as constructor. */ 88.146 + /** 88.147 + * The property map used for newly allocated object when function is used as 88.148 + * constructor. 88.149 + */ 88.150 protected PropertyMap allocatorMap; 88.151 88.152 /** 88.153 + * Reference to constructor prototype. 88.154 + */ 88.155 + protected Object prototype; 88.156 + 88.157 + /** 88.158 * Constructor 88.159 * 88.160 - * @param name function name 88.161 - * @param methodHandle method handle to function (if specializations are present, assumed to be most generic) 88.162 - * @param map property map 88.163 - * @param scope scope 88.164 - * @param specs specialized version of this function - other method handles 88.165 - * @param flags {@link ScriptFunctionData} flags 88.166 + * @param data static function data 88.167 + * @param map property map 88.168 + * @param scope scope 88.169 */ 88.170 - protected ScriptFunction( 88.171 + private ScriptFunction( 88.172 + final ScriptFunctionData data, 88.173 + final PropertyMap map, 88.174 + final ScriptObject scope, 88.175 + final Global global) { 88.176 + 88.177 + super(map); 88.178 + 88.179 + if (Context.DEBUG) { 88.180 + constructorCount.increment(); 88.181 + } 88.182 + 88.183 + this.data = data; 88.184 + this.scope = scope; 88.185 + this.setInitialProto(global.getFunctionPrototype()); 88.186 + this.prototype = LAZY_PROTOTYPE; 88.187 + 88.188 + // We have to fill user accessor functions late as these are stored 88.189 + // in this object rather than in the PropertyMap of this object. 88.190 + assert objectSpill == null; 88.191 + if (isStrict() || isBoundFunction()) { 88.192 + final ScriptFunction typeErrorThrower = global.getTypeErrorThrower(); 88.193 + initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower); 88.194 + initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower); 88.195 + } 88.196 + } 88.197 + 88.198 + /** 88.199 + * Constructor 88.200 + * 88.201 + * @param name function name 88.202 + * @param methodHandle method handle to function (if specializations are 88.203 + * present, assumed to be most generic) 88.204 + * @param map property map 88.205 + * @param scope scope 88.206 + * @param specs specialized version of this function - other method handles 88.207 + * @param flags {@link ScriptFunctionData} flags 88.208 + */ 88.209 + private ScriptFunction( 88.210 final String name, 88.211 final MethodHandle methodHandle, 88.212 final PropertyMap map, 88.213 final ScriptObject scope, 88.214 final Specialization[] specs, 88.215 - final int flags) { 88.216 - 88.217 - this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope); 88.218 + final int flags, 88.219 + final Global global) { 88.220 + this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope, global); 88.221 } 88.222 88.223 /** 88.224 * Constructor 88.225 * 88.226 - * @param data static function data 88.227 - * @param map property map 88.228 - * @param scope scope 88.229 + * @param name name of function 88.230 + * @param methodHandle handle for invocation 88.231 + * @param scope scope object 88.232 + * @param specs specialized versions of this method, if available, null 88.233 + * otherwise 88.234 + * @param flags {@link ScriptFunctionData} flags 88.235 */ 88.236 - protected ScriptFunction( 88.237 - final ScriptFunctionData data, 88.238 - final PropertyMap map, 88.239 - final ScriptObject scope) { 88.240 + private ScriptFunction( 88.241 + final String name, 88.242 + final MethodHandle methodHandle, 88.243 + final ScriptObject scope, 88.244 + final Specialization[] specs, 88.245 + final int flags) { 88.246 + this(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags, Global.instance()); 88.247 + } 88.248 88.249 - super(map); 88.250 + /** 88.251 + * Constructor called by Nasgen generated code, zero added members, use the 88.252 + * default map. Creates builtin functions only. 88.253 + * 88.254 + * @param name name of function 88.255 + * @param invokeHandle handle for invocation 88.256 + * @param specs specialized versions of this method, if available, null 88.257 + * otherwise 88.258 + */ 88.259 + protected ScriptFunction(final String name, final MethodHandle invokeHandle, final Specialization[] specs) { 88.260 + this(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR, Global.instance()); 88.261 + } 88.262 88.263 - if (Context.DEBUG) { 88.264 - constructorCount++; 88.265 + /** 88.266 + * Constructor called by Nasgen generated code, non zero member count, use 88.267 + * the map passed as argument. Creates builtin functions only. 88.268 + * 88.269 + * @param name name of function 88.270 + * @param invokeHandle handle for invocation 88.271 + * @param map initial property map 88.272 + * @param specs specialized versions of this method, if available, null 88.273 + * otherwise 88.274 + */ 88.275 + protected ScriptFunction(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs) { 88.276 + this(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR, Global.instance()); 88.277 + } 88.278 + 88.279 + // Factory methods to create various functions 88.280 + /** 88.281 + * Factory method called by compiler generated code for functions that need 88.282 + * parent scope. 88.283 + * 88.284 + * @param constants the generated class' constant array 88.285 + * @param index the index of the {@code RecompilableScriptFunctionData} 88.286 + * object in the constants array. 88.287 + * @param scope the parent scope object 88.288 + * @return a newly created function object 88.289 + */ 88.290 + public static ScriptFunction create(final Object[] constants, final int index, final ScriptObject scope) { 88.291 + final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constants[index]; 88.292 + return new ScriptFunction(data, getMap(data.isStrict()), scope, Global.instance()); 88.293 + } 88.294 + 88.295 + /** 88.296 + * Factory method called by compiler generated code for functions that don't 88.297 + * need parent scope. 88.298 + * 88.299 + * @param constants the generated class' constant array 88.300 + * @param index the index of the {@code RecompilableScriptFunctionData} 88.301 + * object in the constants array. 88.302 + * @return a newly created function object 88.303 + */ 88.304 + public static ScriptFunction create(final Object[] constants, final int index) { 88.305 + return create(constants, index, null); 88.306 + } 88.307 + 88.308 + /** 88.309 + * Create anonymous function that serves as Function.prototype 88.310 + * 88.311 + * @return anonymous function object 88.312 + */ 88.313 + public static ScriptFunction createAnonymous() { 88.314 + return new ScriptFunction("", GlobalFunctions.ANONYMOUS, anonmap$, null); 88.315 + } 88.316 + 88.317 + // builtin function create helper factory 88.318 + private static ScriptFunction createBuiltin(final String name, final MethodHandle methodHandle, final Specialization[] specs, final int flags) { 88.319 + final ScriptFunction func = new ScriptFunction(name, methodHandle, null, specs, flags); 88.320 + func.setPrototype(UNDEFINED); 88.321 + // Non-constructor built-in functions do not have "prototype" property 88.322 + func.deleteOwnProperty(func.getMap().findProperty("prototype")); 88.323 + 88.324 + return func; 88.325 + } 88.326 + 88.327 + /** 88.328 + * Factory method for non-constructor built-in functions 88.329 + * 88.330 + * @param name function name 88.331 + * @param methodHandle handle for invocation 88.332 + * @param specs specialized versions of function if available, null 88.333 + * otherwise 88.334 + * @return new ScriptFunction 88.335 + */ 88.336 + public static ScriptFunction createBuiltin(final String name, final MethodHandle methodHandle, final Specialization[] specs) { 88.337 + return ScriptFunction.createBuiltin(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN); 88.338 + } 88.339 + 88.340 + /** 88.341 + * Factory method for non-constructor built-in functions 88.342 + * 88.343 + * @param name function name 88.344 + * @param methodHandle handle for invocation 88.345 + * @return new ScriptFunction 88.346 + */ 88.347 + public static ScriptFunction createBuiltin(final String name, final MethodHandle methodHandle) { 88.348 + return ScriptFunction.createBuiltin(name, methodHandle, null); 88.349 + } 88.350 + 88.351 + /** 88.352 + * Factory method for non-constructor built-in, strict functions 88.353 + * 88.354 + * @param name function name 88.355 + * @param methodHandle handle for invocation 88.356 + * @return new ScriptFunction 88.357 + */ 88.358 + public static ScriptFunction createStrictBuiltin(final String name, final MethodHandle methodHandle) { 88.359 + return ScriptFunction.createBuiltin(name, methodHandle, null, ScriptFunctionData.IS_BUILTIN | ScriptFunctionData.IS_STRICT); 88.360 + } 88.361 + 88.362 + // Subclass to represent bound functions 88.363 + private static class Bound extends ScriptFunction { 88.364 + private final ScriptFunction target; 88.365 + 88.366 + Bound(final ScriptFunctionData boundData, final ScriptFunction target) { 88.367 + super(boundData, boundfunctionmap$, null, Global.instance()); 88.368 + setPrototype(ScriptRuntime.UNDEFINED); 88.369 + this.target = target; 88.370 } 88.371 88.372 - this.data = data; 88.373 - this.scope = scope; 88.374 + @Override 88.375 + protected ScriptFunction getTargetFunction() { 88.376 + return target; 88.377 + } 88.378 + } 88.379 + 88.380 + /** 88.381 + * Creates a version of this function bound to a specific "self" and other 88.382 + * arguments, as per {@code Function.prototype.bind} functionality in 88.383 + * ECMAScript 5.1 section 15.3.4.5. 88.384 + * 88.385 + * @param self the self to bind to this function. Can be null (in which 88.386 + * case, null is bound as this). 88.387 + * @param args additional arguments to bind to this function. Can be null or 88.388 + * empty to not bind additional arguments. 88.389 + * @return a function with the specified self and parameters bound. 88.390 + */ 88.391 + public final ScriptFunction createBound(final Object self, final Object[] args) { 88.392 + return new Bound(data.makeBoundFunctionData(this, self, args), getTargetFunction()); 88.393 + } 88.394 + 88.395 + /** 88.396 + * Create a function that invokes this function synchronized on {@code sync} 88.397 + * or the self object of the invocation. 88.398 + * 88.399 + * @param sync the Object to synchronize on, or undefined 88.400 + * @return synchronized function 88.401 + */ 88.402 + public final ScriptFunction createSynchronized(final Object sync) { 88.403 + final MethodHandle mh = MH.insertArguments(ScriptFunction.INVOKE_SYNC, 0, this, sync); 88.404 + return createBuiltin(getName(), mh); 88.405 } 88.406 88.407 @Override 88.408 @@ -151,8 +410,8 @@ 88.409 } 88.410 88.411 /** 88.412 - * ECMA 15.3.5.3 [[HasInstance]] (V) 88.413 - * Step 3 if "prototype" value is not an Object, throw TypeError 88.414 + * ECMA 15.3.5.3 [[HasInstance]] (V) Step 3 if "prototype" value is not an 88.415 + * Object, throw TypeError 88.416 */ 88.417 @Override 88.418 public boolean isInstance(final ScriptObject instance) { 88.419 @@ -171,22 +430,25 @@ 88.420 } 88.421 88.422 /** 88.423 - * Returns the target function for this function. If the function was not created using 88.424 - * {@link #makeBoundFunction(Object, Object[])}, its target function is itself. If it is bound, its target function 88.425 - * is the target function of the function it was made from (therefore, the target function is always the final, 88.426 - * unbound recipient of the calls). 88.427 + * Returns the target function for this function. If the function was not 88.428 + * created using {@link #createBound(Object, Object[])}, its target 88.429 + * function is itself. If it is bound, its target function is the target 88.430 + * function of the function it was made from (therefore, the target function 88.431 + * is always the final, unbound recipient of the calls). 88.432 + * 88.433 * @return the target function for this function. 88.434 */ 88.435 protected ScriptFunction getTargetFunction() { 88.436 return this; 88.437 } 88.438 88.439 - boolean isBoundFunction() { 88.440 + final boolean isBoundFunction() { 88.441 return getTargetFunction() != this; 88.442 } 88.443 88.444 /** 88.445 * Set the arity of this ScriptFunction 88.446 + * 88.447 * @param arity arity 88.448 */ 88.449 public final void setArity(final int arity) { 88.450 @@ -195,59 +457,66 @@ 88.451 88.452 /** 88.453 * Is this a ECMAScript 'use strict' function? 88.454 + * 88.455 * @return true if function is in strict mode 88.456 */ 88.457 - public boolean isStrict() { 88.458 + public final boolean isStrict() { 88.459 return data.isStrict(); 88.460 } 88.461 88.462 /** 88.463 - * Returns true if this is a non-strict, non-built-in function that requires non-primitive this argument 88.464 - * according to ECMA 10.4.3. 88.465 + * Returns true if this is a non-strict, non-built-in function that requires 88.466 + * non-primitive this argument according to ECMA 10.4.3. 88.467 + * 88.468 * @return true if this argument must be an object 88.469 */ 88.470 - public boolean needsWrappedThis() { 88.471 + public final boolean needsWrappedThis() { 88.472 return data.needsWrappedThis(); 88.473 } 88.474 88.475 private static boolean needsWrappedThis(final Object fn) { 88.476 - return fn instanceof ScriptFunction ? ((ScriptFunction)fn).needsWrappedThis() : false; 88.477 + return fn instanceof ScriptFunction ? ((ScriptFunction) fn).needsWrappedThis() : false; 88.478 } 88.479 88.480 /** 88.481 * Execute this script function. 88.482 - * @param self Target object. 88.483 - * @param arguments Call arguments. 88.484 + * 88.485 + * @param self Target object. 88.486 + * @param arguments Call arguments. 88.487 * @return ScriptFunction result. 88.488 - * @throws Throwable if there is an exception/error with the invocation or thrown from it 88.489 + * @throws Throwable if there is an exception/error with the invocation or 88.490 + * thrown from it 88.491 */ 88.492 - Object invoke(final Object self, final Object... arguments) throws Throwable { 88.493 + final Object invoke(final Object self, final Object... arguments) throws Throwable { 88.494 if (Context.DEBUG) { 88.495 - invokes++; 88.496 + invokes.increment(); 88.497 } 88.498 return data.invoke(this, self, arguments); 88.499 } 88.500 88.501 /** 88.502 * Execute this script function as a constructor. 88.503 - * @param arguments Call arguments. 88.504 + * 88.505 + * @param arguments Call arguments. 88.506 * @return Newly constructed result. 88.507 - * @throws Throwable if there is an exception/error with the invocation or thrown from it 88.508 + * @throws Throwable if there is an exception/error with the invocation or 88.509 + * thrown from it 88.510 */ 88.511 - Object construct(final Object... arguments) throws Throwable { 88.512 + final Object construct(final Object... arguments) throws Throwable { 88.513 return data.construct(this, arguments); 88.514 } 88.515 88.516 /** 88.517 - * Allocate function. Called from generated {@link ScriptObject} code 88.518 - * for allocation as a factory method 88.519 + * Allocate function. Called from generated {@link ScriptObject} code for 88.520 + * allocation as a factory method 88.521 * 88.522 - * @return a new instance of the {@link ScriptObject} whose allocator this is 88.523 + * @return a new instance of the {@link ScriptObject} whose allocator this 88.524 + * is 88.525 */ 88.526 @SuppressWarnings("unused") 88.527 private Object allocate() { 88.528 if (Context.DEBUG) { 88.529 - allocations++; 88.530 + allocations.increment(); 88.531 } 88.532 88.533 assert !isBoundFunction(); // allocate never invoked on bound functions 88.534 @@ -257,7 +526,7 @@ 88.535 if (object != null) { 88.536 final Object prototype = getPrototype(); 88.537 if (prototype instanceof ScriptObject) { 88.538 - object.setInitialProto((ScriptObject)prototype); 88.539 + object.setInitialProto((ScriptObject) prototype); 88.540 } 88.541 88.542 if (object.getProto() == null) { 88.543 @@ -277,43 +546,28 @@ 88.544 88.545 /** 88.546 * Return Object.prototype - used by "allocate" 88.547 + * 88.548 * @return Object.prototype 88.549 */ 88.550 - protected abstract ScriptObject getObjectPrototype(); 88.551 - 88.552 - /** 88.553 - * Creates a version of this function bound to a specific "self" and other arguments, as per 88.554 - * {@code Function.prototype.bind} functionality in ECMAScript 5.1 section 15.3.4.5. 88.555 - * @param self the self to bind to this function. Can be null (in which case, null is bound as this). 88.556 - * @param args additional arguments to bind to this function. Can be null or empty to not bind additional arguments. 88.557 - * @return a function with the specified self and parameters bound. 88.558 - */ 88.559 - protected ScriptFunction makeBoundFunction(final Object self, final Object[] args) { 88.560 - return makeBoundFunction(data.makeBoundFunctionData(this, self, args)); 88.561 + protected final ScriptObject getObjectPrototype() { 88.562 + return Global.objectPrototype(); 88.563 } 88.564 88.565 - /** 88.566 - * Create a version of this function as in {@link ScriptFunction#makeBoundFunction(Object, Object[])}, 88.567 - * but using a {@link ScriptFunctionData} for the bound data. 88.568 - * 88.569 - * @param boundData ScriptFuntionData for the bound function 88.570 - * @return a function with the bindings performed according to the given data 88.571 - */ 88.572 - protected abstract ScriptFunction makeBoundFunction(ScriptFunctionData boundData); 88.573 - 88.574 @Override 88.575 public final String safeToString() { 88.576 return toSource(); 88.577 } 88.578 88.579 @Override 88.580 - public String toString() { 88.581 + public final String toString() { 88.582 return data.toString(); 88.583 } 88.584 88.585 /** 88.586 - * Get this function as a String containing its source code. If no source code 88.587 - * exists in this ScriptFunction, its contents will be displayed as {@code [native code]} 88.588 + * Get this function as a String containing its source code. If no source 88.589 + * code exists in this ScriptFunction, its contents will be displayed as 88.590 + * {@code [native code]} 88.591 + * 88.592 * @return string representation of this function's source 88.593 */ 88.594 public final String toSource() { 88.595 @@ -322,27 +576,32 @@ 88.596 88.597 /** 88.598 * Get the prototype object for this function 88.599 + * 88.600 * @return prototype 88.601 */ 88.602 - public abstract Object getPrototype(); 88.603 + public final Object getPrototype() { 88.604 + if (prototype == LAZY_PROTOTYPE) { 88.605 + prototype = new PrototypeObject(this); 88.606 + } 88.607 + return prototype; 88.608 + } 88.609 88.610 /** 88.611 * Set the prototype object for this function 88.612 - * @param prototype new prototype object 88.613 + * 88.614 + * @param newPrototype new prototype object 88.615 */ 88.616 - public abstract void setPrototype(Object prototype); 88.617 + public final void setPrototype(final Object newPrototype) { 88.618 + if (newPrototype instanceof ScriptObject && newPrototype != this.prototype && allocatorMap != null) { 88.619 + // Replace our current allocator map with one that is associated with the new prototype. 88.620 + allocatorMap = allocatorMap.changeProto((ScriptObject) newPrototype); 88.621 + } 88.622 + this.prototype = newPrototype; 88.623 + } 88.624 88.625 /** 88.626 - * Create a function that invokes this function synchronized on {@code sync} or the self object 88.627 - * of the invocation. 88.628 - * @param sync the Object to synchronize on, or undefined 88.629 - * @return synchronized function 88.630 - */ 88.631 - public abstract ScriptFunction makeSynchronizedFunction(Object sync); 88.632 - 88.633 - /** 88.634 - * Return the invoke handle bound to a given ScriptObject self reference. 88.635 - * If callee parameter is required result is rebound to this. 88.636 + * Return the invoke handle bound to a given ScriptObject self reference. If 88.637 + * callee parameter is required result is rebound to this. 88.638 * 88.639 * @param self self reference 88.640 * @return bound invoke handle 88.641 @@ -352,9 +611,12 @@ 88.642 } 88.643 88.644 /** 88.645 - * Bind the method handle to this {@code ScriptFunction} instance if it needs a callee parameter. If this function's 88.646 - * method handles don't have a callee parameter, the handle is returned unchanged. 88.647 - * @param methodHandle the method handle to potentially bind to this function instance. 88.648 + * Bind the method handle to this {@code ScriptFunction} instance if it 88.649 + * needs a callee parameter. If this function's method handles don't have a 88.650 + * callee parameter, the handle is returned unchanged. 88.651 + * 88.652 + * @param methodHandle the method handle to potentially bind to this 88.653 + * function instance. 88.654 * @return the potentially bound method handle 88.655 */ 88.656 private MethodHandle bindToCalleeIfNeeded(final MethodHandle methodHandle) { 88.657 @@ -364,15 +626,16 @@ 88.658 88.659 /** 88.660 * Get the name for this function 88.661 + * 88.662 * @return the name 88.663 */ 88.664 public final String getName() { 88.665 return data.getName(); 88.666 } 88.667 88.668 - 88.669 /** 88.670 * Get the scope for this function 88.671 + * 88.672 * @return the scope 88.673 */ 88.674 public final ScriptObject getScope() { 88.675 @@ -383,36 +646,37 @@ 88.676 * Prototype getter for this ScriptFunction - follows the naming convention 88.677 * used by Nasgen and the code generator 88.678 * 88.679 - * @param self self reference 88.680 + * @param self self reference 88.681 * @return self's prototype 88.682 */ 88.683 public static Object G$prototype(final Object self) { 88.684 - return self instanceof ScriptFunction ? 88.685 - ((ScriptFunction)self).getPrototype() : 88.686 - UNDEFINED; 88.687 + return self instanceof ScriptFunction 88.688 + ? ((ScriptFunction) self).getPrototype() 88.689 + : UNDEFINED; 88.690 } 88.691 88.692 /** 88.693 * Prototype setter for this ScriptFunction - follows the naming convention 88.694 * used by Nasgen and the code generator 88.695 * 88.696 - * @param self self reference 88.697 + * @param self self reference 88.698 * @param prototype prototype to set 88.699 */ 88.700 public static void S$prototype(final Object self, final Object prototype) { 88.701 if (self instanceof ScriptFunction) { 88.702 - ((ScriptFunction)self).setPrototype(prototype); 88.703 + ((ScriptFunction) self).setPrototype(prototype); 88.704 } 88.705 } 88.706 88.707 /** 88.708 * Length getter - ECMA 15.3.3.2: Function.length 88.709 + * 88.710 * @param self self reference 88.711 * @return length 88.712 */ 88.713 public static int G$length(final Object self) { 88.714 if (self instanceof ScriptFunction) { 88.715 - return ((ScriptFunction)self).data.getArity(); 88.716 + return ((ScriptFunction) self).data.getArity(); 88.717 } 88.718 88.719 return 0; 88.720 @@ -420,12 +684,13 @@ 88.721 88.722 /** 88.723 * Name getter - ECMA Function.name 88.724 + * 88.725 * @param self self refence 88.726 * @return the name, or undefined if none 88.727 */ 88.728 public static Object G$name(final Object self) { 88.729 if (self instanceof ScriptFunction) { 88.730 - return ((ScriptFunction)self).getName(); 88.731 + return ((ScriptFunction) self).getName(); 88.732 } 88.733 88.734 return UNDEFINED; 88.735 @@ -433,6 +698,7 @@ 88.736 88.737 /** 88.738 * Get the prototype for this ScriptFunction 88.739 + * 88.740 * @param constructor constructor 88.741 * @return prototype, or null if given constructor is not a ScriptFunction 88.742 */ 88.743 @@ -440,7 +706,7 @@ 88.744 if (constructor != null) { 88.745 final Object proto = constructor.getPrototype(); 88.746 if (proto instanceof ScriptObject) { 88.747 - return (ScriptObject)proto; 88.748 + return (ScriptObject) proto; 88.749 } 88.750 } 88.751 88.752 @@ -448,29 +714,37 @@ 88.753 } 88.754 88.755 // These counters are updated only in debug mode. 88.756 - private static int constructorCount; 88.757 - private static int invokes; 88.758 - private static int allocations; 88.759 + private static LongAdder constructorCount; 88.760 + private static LongAdder invokes; 88.761 + private static LongAdder allocations; 88.762 + 88.763 + static { 88.764 + if (Context.DEBUG) { 88.765 + constructorCount = new LongAdder(); 88.766 + invokes = new LongAdder(); 88.767 + allocations = new LongAdder(); 88.768 + } 88.769 + } 88.770 88.771 /** 88.772 * @return the constructorCount 88.773 */ 88.774 - public static int getConstructorCount() { 88.775 - return constructorCount; 88.776 + public static long getConstructorCount() { 88.777 + return constructorCount.longValue(); 88.778 } 88.779 88.780 /** 88.781 * @return the invokes 88.782 */ 88.783 - public static int getInvokes() { 88.784 - return invokes; 88.785 + public static long getInvokes() { 88.786 + return invokes.longValue(); 88.787 } 88.788 88.789 /** 88.790 * @return the allocations 88.791 */ 88.792 - public static int getAllocations() { 88.793 - return allocations; 88.794 + public static long getAllocations() { 88.795 + return allocations.longValue(); 88.796 } 88.797 88.798 @Override 88.799 @@ -490,7 +764,6 @@ 88.800 return Context.getGlobal().wrapAsObject(obj); 88.801 } 88.802 88.803 - 88.804 @SuppressWarnings("unused") 88.805 private static Object globalFilter(final Object object) { 88.806 // replace whatever we get with the current global object 88.807 @@ -498,14 +771,16 @@ 88.808 } 88.809 88.810 /** 88.811 - * Some receivers are primitive, in that case, according to the Spec we create a new 88.812 - * native object per callsite with the wrap filter. We can only apply optimistic builtins 88.813 - * if there is no per instance state saved for these wrapped objects (e.g. currently NativeStrings), 88.814 - * otherwise we can't create optimistic versions 88.815 + * Some receivers are primitive, in that case, according to the Spec we 88.816 + * create a new native object per callsite with the wrap filter. We can only 88.817 + * apply optimistic builtins if there is no per instance state saved for 88.818 + * these wrapped objects (e.g. currently NativeStrings), otherwise we can't 88.819 + * create optimistic versions 88.820 * 88.821 - * @param self receiver 88.822 - * @param linkLogicClass linkLogicClass, or null if no link logic exists 88.823 - * @return link logic instance, or null if one could not be constructed for this receiver 88.824 + * @param self receiver 88.825 + * @param linkLogicClass linkLogicClass, or null if no link logic exists 88.826 + * @return link logic instance, or null if one could not be constructed for 88.827 + * this receiver 88.828 */ 88.829 private static LinkLogic getLinkLogic(final Object self, final Class<? extends LinkLogic> linkLogicClass) { 88.830 if (linkLogicClass == null) { 88.831 @@ -518,25 +793,25 @@ 88.832 88.833 final Object wrappedSelf = wrapFilter(self); 88.834 if (wrappedSelf instanceof OptimisticBuiltins) { 88.835 - if (wrappedSelf != self && ((OptimisticBuiltins)wrappedSelf).hasPerInstanceAssumptions()) { 88.836 + if (wrappedSelf != self && ((OptimisticBuiltins) wrappedSelf).hasPerInstanceAssumptions()) { 88.837 return null; //pessimistic - we created a wrapped object different from the primitive, but the assumptions have instance state 88.838 } 88.839 - return ((OptimisticBuiltins)wrappedSelf).getLinkLogic(linkLogicClass); 88.840 + return ((OptimisticBuiltins) wrappedSelf).getLinkLogic(linkLogicClass); 88.841 } 88.842 return null; 88.843 } 88.844 88.845 /** 88.846 - * dyn:call call site signature: (callee, thiz, [args...]) 88.847 - * generated method signature: (callee, thiz, [args...]) 88.848 + * dyn:call call site signature: (callee, thiz, [args...]) generated method 88.849 + * signature: (callee, thiz, [args...]) 88.850 * 88.851 * cases: 88.852 * (a) method has callee parameter 88.853 - * (1) for local/scope calls, we just bind thiz and drop the second argument. 88.854 - * (2) for normal this-calls, we have to swap thiz and callee to get matching signatures. 88.855 + * (1) for local/scope calls, we just bind thiz and drop the second argument. 88.856 + * (2) for normal this-calls, we have to swap thiz and callee to get matching signatures. 88.857 * (b) method doesn't have callee parameter (builtin functions) 88.858 - * (3) for local/scope calls, bind thiz and drop both callee and thiz. 88.859 - * (4) for normal this-calls, drop callee. 88.860 + * (3) for local/scope calls, bind thiz and drop both callee and thiz. 88.861 + * (4) for normal this-calls, drop callee. 88.862 * 88.863 * @return guarded invocation for call 88.864 */ 88.865 @@ -544,11 +819,11 @@ 88.866 protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) { 88.867 final MethodType type = desc.getMethodType(); 88.868 88.869 - final String name = getName(); 88.870 + final String name = getName(); 88.871 final boolean isUnstable = request.isCallSiteUnstable(); 88.872 - final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc); 88.873 - final boolean isCall = !scopeCall && data.isBuiltin() && "call".equals(name); 88.874 - final boolean isApply = !scopeCall && data.isBuiltin() && "apply".equals(name); 88.875 + final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc); 88.876 + final boolean isCall = !scopeCall && data.isBuiltin() && "call".equals(name); 88.877 + final boolean isApply = !scopeCall && data.isBuiltin() && "apply".equals(name); 88.878 88.879 final boolean isApplyOrCall = isCall | isApply; 88.880 88.881 @@ -569,7 +844,7 @@ 88.882 return new GuardedInvocation( 88.883 handle, 88.884 null, 88.885 - (SwitchPoint)null, 88.886 + (SwitchPoint) null, 88.887 ClassCastException.class); 88.888 } 88.889 88.890 @@ -672,14 +947,14 @@ 88.891 this, 88.892 cf.getFlags()) : 88.893 guard, 88.894 - spsArray, 88.895 + spsArray, 88.896 exceptionGuard); 88.897 } 88.898 88.899 private GuardedInvocation createApplyOrCallCall(final boolean isApply, final CallSiteDescriptor desc, final LinkRequest request, final Object[] args) { 88.900 final MethodType descType = desc.getMethodType(); 88.901 final int paramCount = descType.parameterCount(); 88.902 - if(descType.parameterType(paramCount - 1).isArray()) { 88.903 + if (descType.parameterType(paramCount - 1).isArray()) { 88.904 // This is vararg invocation of apply or call. This can normally only happen when we do a recursive 88.905 // invocation of createApplyOrCallCall (because we're doing apply-of-apply). In this case, create delegate 88.906 // linkage by unpacking the vararg invocation and use pairArguments to introduce the necessary spreader. 88.907 @@ -786,7 +1061,7 @@ 88.908 inv = MH.filterArguments(inv, 2, NativeFunction.TO_APPLY_ARGS); 88.909 } else { 88.910 // If the original call site doesn't pass argArray, pass in an empty array 88.911 - inv = MH.insertArguments(inv, 2, (Object)ScriptRuntime.EMPTY_ARRAY); 88.912 + inv = MH.insertArguments(inv, 2, (Object) ScriptRuntime.EMPTY_ARRAY); 88.913 } 88.914 } 88.915 88.916 @@ -851,7 +1126,7 @@ 88.917 final LinkRequest request, final Object[] args) { 88.918 final MethodType descType = desc.getMethodType(); 88.919 final int paramCount = descType.parameterCount(); 88.920 - final Object[] varArgs = (Object[])args[paramCount - 1]; 88.921 + final Object[] varArgs = (Object[]) args[paramCount - 1]; 88.922 // -1 'cause we're not passing the vararg array itself 88.923 final int copiedArgCount = args.length - 1; 88.924 final int varArgCount = varArgs.length; 88.925 @@ -893,7 +1168,7 @@ 88.926 // If the last parameter type of the guard is an array, then it is already itself a guard for a vararg apply 88.927 // invocation. We must filter the last argument with toApplyArgs otherwise deeper levels of nesting will fail 88.928 // with ClassCastException of NativeArray to Object[]. 88.929 - if(guardType.parameterType(guardParamCount - 1).isArray()) { 88.930 + if (guardType.parameterType(guardParamCount - 1).isArray()) { 88.931 arrayConvertingGuard = MH.filterArguments(guard, guardParamCount - 1, NativeFunction.TO_APPLY_ARGS); 88.932 } else { 88.933 arrayConvertingGuard = guard; 88.934 @@ -903,19 +1178,20 @@ 88.935 } 88.936 88.937 private static MethodHandle bindImplicitThis(final Object fn, final MethodHandle mh) { 88.938 - final MethodHandle bound; 88.939 - if(fn instanceof ScriptFunction && ((ScriptFunction)fn).needsWrappedThis()) { 88.940 - bound = MH.filterArguments(mh, 1, SCRIPTFUNCTION_GLOBALFILTER); 88.941 - } else { 88.942 - bound = mh; 88.943 - } 88.944 - return MH.insertArguments(bound, 1, ScriptRuntime.UNDEFINED); 88.945 - } 88.946 + final MethodHandle bound; 88.947 + if (fn instanceof ScriptFunction && ((ScriptFunction) fn).needsWrappedThis()) { 88.948 + bound = MH.filterArguments(mh, 1, SCRIPTFUNCTION_GLOBALFILTER); 88.949 + } else { 88.950 + bound = mh; 88.951 + } 88.952 + return MH.insertArguments(bound, 1, ScriptRuntime.UNDEFINED); 88.953 + } 88.954 88.955 /** 88.956 * Used for noSuchMethod/noSuchProperty and JSAdapter hooks. 88.957 * 88.958 - * These don't want a callee parameter, so bind that. Name binding is optional. 88.959 + * These don't want a callee parameter, so bind that. Name binding is 88.960 + * optional. 88.961 */ 88.962 MethodHandle getCallMethodHandle(final MethodType type, final String bindName) { 88.963 return pairArguments(bindToNameIfNeeded(bindToCalleeIfNeeded(data.getGenericInvoker(scope)), bindName), type); 88.964 @@ -939,10 +1215,11 @@ 88.965 } 88.966 88.967 /** 88.968 - * Get the guard that checks if a {@link ScriptFunction} is equal to 88.969 - * a known ScriptFunction, using reference comparison 88.970 + * Get the guard that checks if a {@link ScriptFunction} is equal to a known 88.971 + * ScriptFunction, using reference comparison 88.972 * 88.973 - * @param function The ScriptFunction to check against. This will be bound to the guard method handle 88.974 + * @param function The ScriptFunction to check against. This will be bound 88.975 + * to the guard method handle 88.976 * 88.977 * @return method handle for guard 88.978 */ 88.979 @@ -957,11 +1234,12 @@ 88.980 } 88.981 88.982 /** 88.983 - * Get a guard that checks if a {@link ScriptFunction} is equal to 88.984 - * a known ScriptFunction using reference comparison, and whether the type of 88.985 - * the second argument (this-object) is not a JavaScript primitive type. 88.986 + * Get a guard that checks if a {@link ScriptFunction} is equal to a known 88.987 + * ScriptFunction using reference comparison, and whether the type of the 88.988 + * second argument (this-object) is not a JavaScript primitive type. 88.989 * 88.990 - * @param function The ScriptFunction to check against. This will be bound to the guard method handle 88.991 + * @param function The ScriptFunction to check against. This will be bound 88.992 + * to the guard method handle 88.993 * 88.994 * @return method handle for guard 88.995 */ 88.996 @@ -972,12 +1250,12 @@ 88.997 88.998 @SuppressWarnings("unused") 88.999 private static boolean isFunctionMH(final Object self, final ScriptFunctionData data) { 88.1000 - return self instanceof ScriptFunction && ((ScriptFunction)self).data == data; 88.1001 + return self instanceof ScriptFunction && ((ScriptFunction) self).data == data; 88.1002 } 88.1003 88.1004 @SuppressWarnings("unused") 88.1005 private static boolean isNonStrictFunction(final Object self, final Object arg, final ScriptFunctionData data) { 88.1006 - return self instanceof ScriptFunction && ((ScriptFunction)self).data == data && arg instanceof ScriptObject; 88.1007 + return self instanceof ScriptFunction && ((ScriptFunction) self).data == data && arg instanceof ScriptObject; 88.1008 } 88.1009 88.1010 //TODO this can probably be removed given that we have builtin switchpoints in the context 88.1011 @@ -990,7 +1268,7 @@ 88.1012 @SuppressWarnings("unused") 88.1013 private static Object[] addZerothElement(final Object[] args, final Object value) { 88.1014 // extends input array with by adding new zeroth element 88.1015 - final Object[] src = args == null? ScriptRuntime.EMPTY_ARRAY : args; 88.1016 + final Object[] src = args == null ? ScriptRuntime.EMPTY_ARRAY : args; 88.1017 final Object[] result = new Object[src.length + 1]; 88.1018 System.arraycopy(src, 0, result, 1, src.length); 88.1019 result[0] = value; 88.1020 @@ -1014,4 +1292,3 @@ 88.1021 return MH.findVirtual(MethodHandles.lookup(), ScriptFunction.class, name, MH.type(rtype, types)); 88.1022 } 88.1023 } 88.1024 -
89.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Thu Sep 24 10:00:42 2015 -0700 89.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Thu Sep 24 10:09:56 2015 -0700 89.3 @@ -151,7 +151,7 @@ 89.4 * Is this a ScriptFunction generated with strict semantics? 89.5 * @return true if strict, false otherwise 89.6 */ 89.7 - public boolean isStrict() { 89.8 + public final boolean isStrict() { 89.9 return (flags & IS_STRICT) != 0; 89.10 } 89.11 89.12 @@ -164,11 +164,11 @@ 89.13 return getName(); 89.14 } 89.15 89.16 - boolean isBuiltin() { 89.17 + final boolean isBuiltin() { 89.18 return (flags & IS_BUILTIN) != 0; 89.19 } 89.20 89.21 - boolean isConstructor() { 89.22 + final boolean isConstructor() { 89.23 return (flags & IS_CONSTRUCTOR) != 0; 89.24 } 89.25 89.26 @@ -179,7 +179,7 @@ 89.27 * according to ECMA 10.4.3. 89.28 * @return true if this argument must be an object 89.29 */ 89.30 - boolean needsWrappedThis() { 89.31 + final boolean needsWrappedThis() { 89.32 return (flags & USES_THIS) != 0 && (flags & IS_STRICT_OR_BUILTIN) == 0; 89.33 } 89.34 89.35 @@ -318,7 +318,7 @@ 89.36 * Used to find an apply to call version that fits this callsite. 89.37 * We cannot just, as in the normal matcher case, return e.g. (Object, Object, int) 89.38 * for (Object, Object, int, int, int) or we will destroy the semantics and get 89.39 - * a function that, when padded with undefineds, behaves differently 89.40 + * a function that, when padded with undefined values, behaves differently 89.41 * @param type actual call site type 89.42 * @return apply to call that perfectly fits this callsite or null if none found 89.43 */ 89.44 @@ -397,7 +397,7 @@ 89.45 89.46 /** 89.47 * This method is used to create the immutable portion of a bound function. 89.48 - * See {@link ScriptFunction#makeBoundFunction(Object, Object[])} 89.49 + * See {@link ScriptFunction#createBound(Object, Object[])} 89.50 * 89.51 * @param fn the original function being bound 89.52 * @param self this reference to bind. Can be null.
90.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Sep 24 10:00:42 2015 -0700 90.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Sep 24 10:09:56 2015 -0700 90.3 @@ -64,6 +64,7 @@ 90.4 import java.util.List; 90.5 import java.util.Map; 90.6 import java.util.Set; 90.7 +import java.util.concurrent.atomic.LongAdder; 90.8 import jdk.internal.dynalink.CallSiteDescriptor; 90.9 import jdk.internal.dynalink.linker.GuardedInvocation; 90.10 import jdk.internal.dynalink.linker.LinkRequest; 90.11 @@ -148,7 +149,7 @@ 90.12 /** Method handle to retrieve prototype of this object */ 90.13 public static final MethodHandle GETPROTO = findOwnMH_V("getProto", ScriptObject.class); 90.14 90.15 - static final MethodHandle MEGAMORPHIC_GET = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class); 90.16 + static final MethodHandle MEGAMORPHIC_GET = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class, boolean.class); 90.17 static final MethodHandle GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class); 90.18 static final MethodHandle DECLARE_AND_SET = findOwnMH_V("declareAndSet", void.class, String.class, Object.class); 90.19 90.20 @@ -211,7 +212,7 @@ 90.21 */ 90.22 public ScriptObject(final PropertyMap map) { 90.23 if (Context.DEBUG) { 90.24 - ScriptObject.count++; 90.25 + ScriptObject.count.increment(); 90.26 } 90.27 this.arrayData = ArrayData.EMPTY_ARRAY; 90.28 this.setMap(map == null ? PropertyMap.newMap() : map); 90.29 @@ -224,7 +225,7 @@ 90.30 * same combination of prototype and property map. 90.31 * 90.32 * @param proto the prototype object 90.33 - * @param map intial {@link PropertyMap} 90.34 + * @param map initial {@link PropertyMap} 90.35 */ 90.36 protected ScriptObject(final ScriptObject proto, final PropertyMap map) { 90.37 this(map); 90.38 @@ -1257,7 +1258,7 @@ 90.39 if (oldProto != newProto) { 90.40 proto = newProto; 90.41 90.42 - // Let current listeners know that the protototype has changed and set our map 90.43 + // Let current listeners know that the prototype has changed and set our map 90.44 final PropertyListeners listeners = getMap().getListeners(); 90.45 if (listeners != null) { 90.46 listeners.protoChanged(); 90.47 @@ -1452,7 +1453,7 @@ 90.48 * in {@link ScriptFunction} for hasInstance implementation, walks 90.49 * the proto chain 90.50 * 90.51 - * @param instance instace to check 90.52 + * @param instance instance to check 90.53 * @return true if 'instance' is an instance of this object 90.54 */ 90.55 public boolean isInstance(final ScriptObject instance) { 90.56 @@ -1869,7 +1870,7 @@ 90.57 * @param desc the call site descriptor. 90.58 * @param request the link request 90.59 * 90.60 - * @return GuardedInvocation to be invoed at call site. 90.61 + * @return GuardedInvocation to be invoked at call site. 90.62 */ 90.63 protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) { 90.64 return notAFunction(desc); 90.65 @@ -2019,19 +2020,19 @@ 90.66 90.67 private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) { 90.68 Context.getContextTrusted().getLogger(ObjectClassGenerator.class).warning("Megamorphic getter: " + desc + " " + name + " " +isMethod); 90.69 - final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod); 90.70 + final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod, NashornCallSiteDescriptor.isScope(desc)); 90.71 final MethodHandle guard = getScriptObjectGuard(desc.getMethodType(), true); 90.72 return new GuardedInvocation(invoker, guard); 90.73 } 90.74 90.75 @SuppressWarnings("unused") 90.76 - private Object megamorphicGet(final String key, final boolean isMethod) { 90.77 + private Object megamorphicGet(final String key, final boolean isMethod, final boolean isScope) { 90.78 final FindProperty find = findProperty(key, true); 90.79 if (find != null) { 90.80 return find.getObjectValue(); 90.81 } 90.82 90.83 - return isMethod ? getNoSuchMethod(key, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, INVALID_PROGRAM_POINT); 90.84 + return isMethod ? getNoSuchMethod(key, isScope, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, isScope, INVALID_PROGRAM_POINT); 90.85 } 90.86 90.87 // Marks a property as declared and sets its value. Used as slow path for block-scoped LET and CONST 90.88 @@ -2301,7 +2302,7 @@ 90.89 MH.dropArguments( 90.90 MH.constant( 90.91 ScriptFunction.class, 90.92 - func.makeBoundFunction(thiz, new Object[] { name })), 90.93 + func.createBound(thiz, new Object[] { name })), 90.94 0, 90.95 Object.class), 90.96 NashornGuards.combineGuards( 90.97 @@ -2366,20 +2367,21 @@ 90.98 /** 90.99 * Invoke fall back if a property is not found. 90.100 * @param name Name of property. 90.101 + * @param isScope is this a scope access? 90.102 * @param programPoint program point 90.103 * @return Result from call. 90.104 */ 90.105 - protected Object invokeNoSuchProperty(final String name, final int programPoint) { 90.106 + protected Object invokeNoSuchProperty(final String name, final boolean isScope, final int programPoint) { 90.107 final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true); 90.108 + final Object func = (find != null)? find.getObjectValue() : null; 90.109 90.110 Object ret = UNDEFINED; 90.111 - 90.112 - if (find != null) { 90.113 - final Object func = find.getObjectValue(); 90.114 - 90.115 - if (func instanceof ScriptFunction) { 90.116 - ret = ScriptRuntime.apply((ScriptFunction)func, this, name); 90.117 - } 90.118 + if (func instanceof ScriptFunction) { 90.119 + final ScriptFunction sfunc = (ScriptFunction)func; 90.120 + final Object self = isScope && sfunc.isStrict()? UNDEFINED : this; 90.121 + ret = ScriptRuntime.apply(sfunc, self, name); 90.122 + } else if (isScope) { 90.123 + throw referenceError("not.defined", name); 90.124 } 90.125 90.126 if (isValid(programPoint)) { 90.127 @@ -2393,21 +2395,27 @@ 90.128 /** 90.129 * Get __noSuchMethod__ as a function bound to this object and {@code name} if it is defined. 90.130 * @param name the method name 90.131 + * @param isScope is this a scope access? 90.132 * @return the bound function, or undefined 90.133 */ 90.134 - private Object getNoSuchMethod(final String name, final int programPoint) { 90.135 + private Object getNoSuchMethod(final String name, final boolean isScope, final int programPoint) { 90.136 final FindProperty find = findProperty(NO_SUCH_METHOD_NAME, true); 90.137 90.138 if (find == null) { 90.139 - return invokeNoSuchProperty(name, programPoint); 90.140 + return invokeNoSuchProperty(name, isScope, programPoint); 90.141 } 90.142 90.143 final Object value = find.getObjectValue(); 90.144 if (!(value instanceof ScriptFunction)) { 90.145 + if (isScope) { 90.146 + throw referenceError("not.defined", name); 90.147 + } 90.148 return UNDEFINED; 90.149 } 90.150 90.151 - return ((ScriptFunction)value).makeBoundFunction(this, new Object[] {name}); 90.152 + final ScriptFunction func = (ScriptFunction)value; 90.153 + final Object self = isScope && func.isStrict()? UNDEFINED : this; 90.154 + return func.createBound(self, new Object[] {name}); 90.155 } 90.156 90.157 private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final String name) { 90.158 @@ -2722,7 +2730,7 @@ 90.159 } 90.160 } 90.161 90.162 - return JSType.toInt32(invokeNoSuchProperty(key, programPoint)); 90.163 + return JSType.toInt32(invokeNoSuchProperty(key, false, programPoint)); 90.164 } 90.165 90.166 @Override 90.167 @@ -2804,7 +2812,7 @@ 90.168 } 90.169 } 90.170 90.171 - return JSType.toLong(invokeNoSuchProperty(key, programPoint)); 90.172 + return JSType.toLong(invokeNoSuchProperty(key, false, programPoint)); 90.173 } 90.174 90.175 @Override 90.176 @@ -2886,7 +2894,7 @@ 90.177 } 90.178 } 90.179 90.180 - return JSType.toNumber(invokeNoSuchProperty(key, INVALID_PROGRAM_POINT)); 90.181 + return JSType.toNumber(invokeNoSuchProperty(key, false, INVALID_PROGRAM_POINT)); 90.182 } 90.183 90.184 @Override 90.185 @@ -2967,7 +2975,7 @@ 90.186 } 90.187 } 90.188 90.189 - return invokeNoSuchProperty(key, INVALID_PROGRAM_POINT); 90.190 + return invokeNoSuchProperty(key, false, INVALID_PROGRAM_POINT); 90.191 } 90.192 90.193 @Override 90.194 @@ -3796,15 +3804,20 @@ 90.195 } 90.196 90.197 /** This is updated only in debug mode - counts number of {@code ScriptObject} instances created */ 90.198 - private static int count; 90.199 - 90.200 + private static LongAdder count; 90.201 + 90.202 + static { 90.203 + if (Context.DEBUG) { 90.204 + count = new LongAdder(); 90.205 + } 90.206 + } 90.207 /** 90.208 * Get number of {@code ScriptObject} instances created. If not running in debug 90.209 * mode this is always 0 90.210 * 90.211 * @return number of ScriptObjects created 90.212 */ 90.213 - public static int getCount() { 90.214 - return count; 90.215 + public static long getCount() { 90.216 + return count.longValue(); 90.217 } 90.218 }
91.1 --- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Thu Sep 24 10:00:42 2015 -0700 91.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Thu Sep 24 10:09:56 2015 -0700 91.3 @@ -26,6 +26,7 @@ 91.4 package jdk.nashorn.internal.runtime; 91.5 91.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 91.7 +import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError; 91.8 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 91.9 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 91.10 91.11 @@ -70,6 +71,9 @@ 91.12 /** EXIT name - special property used by $EXEC API. */ 91.13 public static final String EXIT_NAME = "$EXIT"; 91.14 91.15 + /** THROW_ON_ERROR name - special property of the $EXEC function used by $EXEC API. */ 91.16 + public static final String THROW_ON_ERROR_NAME = "throwOnError"; 91.17 + 91.18 /** Names of special properties used by $ENV API. */ 91.19 public static final String ENV_NAME = "$ENV"; 91.20 91.21 @@ -244,6 +248,19 @@ 91.22 } 91.23 } 91.24 91.25 + // if we got a non-zero exit code ("failure"), then we have to decide to throw error or not 91.26 + if (exit != 0) { 91.27 + // get the $EXEC function object from the global object 91.28 + final Object exec = global.get(EXEC_NAME); 91.29 + assert exec instanceof ScriptObject : EXEC_NAME + " is not a script object!"; 91.30 + 91.31 + // Check if the user has set $EXEC.throwOnError property to true. If so, throw RangeError 91.32 + // If that property is not set or set to false, then silently proceed with the rest. 91.33 + if (JSType.toBoolean(((ScriptObject)exec).get(THROW_ON_ERROR_NAME))) { 91.34 + throw rangeError("exec.returned.non.zero", ScriptRuntime.safeToString(exit)); 91.35 + } 91.36 + } 91.37 + 91.38 // Return the result from stdout. 91.39 return out; 91.40 }
92.1 --- a/src/jdk/nashorn/internal/runtime/Timing.java Thu Sep 24 10:00:42 2015 -0700 92.2 +++ b/src/jdk/nashorn/internal/runtime/Timing.java Thu Sep 24 10:09:56 2015 -0700 92.3 @@ -28,12 +28,14 @@ 92.4 import java.io.IOException; 92.5 import java.io.StringReader; 92.6 import java.util.ArrayList; 92.7 -import java.util.LinkedHashMap; 92.8 import java.util.List; 92.9 import java.util.Map; 92.10 +import java.util.concurrent.ConcurrentHashMap; 92.11 +import java.util.concurrent.LinkedBlockingQueue; 92.12 import java.util.concurrent.TimeUnit; 92.13 +import java.util.concurrent.atomic.LongAdder; 92.14 +import java.util.function.Function; 92.15 import java.util.function.Supplier; 92.16 - 92.17 import jdk.nashorn.internal.codegen.CompileUnit; 92.18 import jdk.nashorn.internal.runtime.logging.DebugLogger; 92.19 import jdk.nashorn.internal.runtime.logging.Loggable; 92.20 @@ -156,11 +158,15 @@ 92.21 } 92.22 92.23 final class TimeSupplier implements Supplier<String> { 92.24 - private final Map<String, Long> timings; 92.25 - 92.26 - TimeSupplier() { 92.27 - timings = new LinkedHashMap<>(); 92.28 - } 92.29 + private final Map<String, LongAdder> timings = new ConcurrentHashMap<>(); 92.30 + private final LinkedBlockingQueue<String> orderedTimingNames = new LinkedBlockingQueue<>(); 92.31 + private final Function<String, LongAdder> newTimingCreator = new Function<String, LongAdder>() { 92.32 + @Override 92.33 + public LongAdder apply(final String s) { 92.34 + orderedTimingNames.add(s); 92.35 + return new LongAdder(); 92.36 + } 92.37 + }; 92.38 92.39 String[] getStrings() { 92.40 final List<String> strs = new ArrayList<>(); 92.41 @@ -184,26 +190,26 @@ 92.42 int maxKeyLength = 0; 92.43 int maxValueLength = 0; 92.44 92.45 - for (final Map.Entry<String, Long> entry : timings.entrySet()) { 92.46 + for (final Map.Entry<String, LongAdder> entry : timings.entrySet()) { 92.47 maxKeyLength = Math.max(maxKeyLength, entry.getKey().length()); 92.48 - maxValueLength = Math.max(maxValueLength, toMillisPrint(entry.getValue()).length()); 92.49 + maxValueLength = Math.max(maxValueLength, toMillisPrint(entry.getValue().longValue()).length()); 92.50 } 92.51 maxKeyLength++; 92.52 92.53 final StringBuilder sb = new StringBuilder(); 92.54 sb.append("Accumulated compilation phase timings:\n\n"); 92.55 - for (final Map.Entry<String, Long> entry : timings.entrySet()) { 92.56 + for (final String timingName: orderedTimingNames) { 92.57 int len; 92.58 92.59 len = sb.length(); 92.60 - sb.append(entry.getKey()); 92.61 + sb.append(timingName); 92.62 len = sb.length() - len; 92.63 92.64 while (len++ < maxKeyLength) { 92.65 sb.append(' '); 92.66 } 92.67 92.68 - final Long duration = entry.getValue(); 92.69 + final long duration = timings.get(timingName).longValue(); 92.70 final String strDuration = toMillisPrint(duration); 92.71 len = strDuration.length(); 92.72 for (int i = 0; i < maxValueLength - len; i++) { 92.73 @@ -233,11 +239,7 @@ 92.74 } 92.75 92.76 private void accumulateTime(final String module, final long duration) { 92.77 - Long accumulatedTime = timings.get(module); 92.78 - if (accumulatedTime == null) { 92.79 - accumulatedTime = 0L; 92.80 - } 92.81 - timings.put(module, accumulatedTime + duration); 92.82 + timings.computeIfAbsent(module, newTimingCreator).add(duration); 92.83 } 92.84 } 92.85 }
93.1 --- a/src/jdk/nashorn/internal/runtime/WithObject.java Thu Sep 24 10:00:42 2015 -0700 93.2 +++ b/src/jdk/nashorn/internal/runtime/WithObject.java Thu Sep 24 10:09:56 2015 -0700 93.3 @@ -26,6 +26,7 @@ 93.4 package jdk.nashorn.internal.runtime; 93.5 93.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 93.7 +import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 93.8 93.9 import java.lang.invoke.MethodHandle; 93.10 import java.lang.invoke.MethodHandles; 93.11 @@ -209,16 +210,18 @@ 93.12 } 93.13 93.14 @Override 93.15 - protected Object invokeNoSuchProperty(final String name, final int programPoint) { 93.16 + protected Object invokeNoSuchProperty(final String name, final boolean isScope, final int programPoint) { 93.17 FindProperty find = expression.findProperty(NO_SUCH_PROPERTY_NAME, true); 93.18 if (find != null) { 93.19 final Object func = find.getObjectValue(); 93.20 if (func instanceof ScriptFunction) { 93.21 - return ScriptRuntime.apply((ScriptFunction)func, expression, name); 93.22 + final ScriptFunction sfunc = (ScriptFunction)func; 93.23 + final Object self = isScope && sfunc.isStrict()? UNDEFINED : expression; 93.24 + return ScriptRuntime.apply(sfunc, self, name); 93.25 } 93.26 } 93.27 93.28 - return getProto().invokeNoSuchProperty(name, programPoint); 93.29 + return getProto().invokeNoSuchProperty(name, isScope, programPoint); 93.30 } 93.31 93.32 @Override 93.33 @@ -352,7 +355,7 @@ 93.34 } 93.35 93.36 private static Object bindToExpression(final ScriptFunction fn, final Object receiver) { 93.37 - return fn.makeBoundFunction(withFilterExpression(receiver), ScriptRuntime.EMPTY_ARRAY); 93.38 + return fn.createBound(withFilterExpression(receiver), ScriptRuntime.EMPTY_ARRAY); 93.39 } 93.40 93.41 private MethodHandle expressionGuard(final String name, final ScriptObject owner) {
94.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Thu Sep 24 10:00:42 2015 -0700 94.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Thu Sep 24 10:09:56 2015 -0700 94.3 @@ -191,7 +191,7 @@ 94.4 94.5 /** 94.6 * Return element setter for a {@link ContinuousArrayData} 94.7 - * @param clazz clazz for exact type guard 94.8 + * @param clazz class for exact type guard 94.9 * @param setHas set has guard 94.10 * @param elementType element type 94.11 * @return method handle for element setter
95.1 --- a/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java Thu Sep 24 10:00:42 2015 -0700 95.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java Thu Sep 24 10:09:56 2015 -0700 95.3 @@ -34,7 +34,7 @@ 95.4 * This filter handles the presence of undefined array elements. 95.5 */ 95.6 final class UndefinedArrayFilter extends ArrayFilter { 95.7 - /** Bit vector tracking undefines. */ 95.8 + /** Bit vector tracking undefined slots. */ 95.9 private final BitVector undefined; 95.10 95.11 UndefinedArrayFilter(final ArrayData underlying) {
96.1 --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Thu Sep 24 10:00:42 2015 -0700 96.2 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Thu Sep 24 10:09:56 2015 -0700 96.3 @@ -50,7 +50,6 @@ 96.4 import jdk.nashorn.internal.codegen.ObjectClassGenerator; 96.5 import jdk.nashorn.internal.lookup.MethodHandleFactory; 96.6 import jdk.nashorn.internal.lookup.MethodHandleFunctionality; 96.7 -import jdk.nashorn.internal.objects.ScriptFunctionImpl; 96.8 import jdk.nashorn.internal.runtime.ECMAException; 96.9 import jdk.nashorn.internal.runtime.JSType; 96.10 import jdk.nashorn.internal.runtime.OptimisticReturnFilters; 96.11 @@ -70,7 +69,7 @@ 96.12 private static final MethodHandle VOID_TO_OBJECT = MH.constant(Object.class, ScriptRuntime.UNDEFINED); 96.13 96.14 /** 96.15 - * The default dynalink relink threshold for megamorphisism is 8. In the case 96.16 + * The default dynalink relink threshold for megamorphism is 8. In the case 96.17 * of object fields only, it is fine. However, with dual fields, in order to get 96.18 * performance on benchmarks with a lot of object instantiation and then field 96.19 * reassignment, it can take slightly more relinks to become stable with type 96.20 @@ -214,7 +213,7 @@ 96.21 * @param type method type 96.22 * @param programPoint program point to bind to callsite 96.23 * 96.24 - * @return callsite for a math instrinic node 96.25 + * @return callsite for a math intrinsic node 96.26 */ 96.27 public static CallSite mathBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int programPoint) { 96.28 final MethodHandle mh; 96.29 @@ -397,8 +396,8 @@ 96.30 * @throws ECMAException with {@code TypeError} if the object is not a callable. 96.31 */ 96.32 public static Object bindCallable(final Object callable, final Object boundThis, final Object[] boundArgs) { 96.33 - if (callable instanceof ScriptFunctionImpl) { 96.34 - return ((ScriptFunctionImpl)callable).makeBoundFunction(boundThis, boundArgs); 96.35 + if (callable instanceof ScriptFunction) { 96.36 + return ((ScriptFunction)callable).createBound(boundThis, boundArgs); 96.37 } else if (callable instanceof BoundCallable) { 96.38 return ((BoundCallable)callable).bind(boundArgs); 96.39 } else if (isCallable(callable)) {
97.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Thu Sep 24 10:00:42 2015 -0700 97.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Thu Sep 24 10:09:56 2015 -0700 97.3 @@ -571,7 +571,7 @@ 97.4 mv.visitVarInsn(ALOAD, 0); 97.5 if (fromFunction && !mi.getName().equals(samName)) { 97.6 // Constructors initializing from a ScriptFunction only initialize methods with the SAM name. 97.7 - // NOTE: if there's a concrete overloaded method sharing the SAM name, it'll be overriden too. This 97.8 + // NOTE: if there's a concrete overloaded method sharing the SAM name, it'll be overridden too. This 97.9 // is a deliberate design choice. All other method handles are initialized to null. 97.10 mv.visitInsn(ACONST_NULL); 97.11 } else {
98.1 --- a/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java Thu Sep 24 10:00:42 2015 -0700 98.2 +++ b/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java Thu Sep 24 10:09:56 2015 -0700 98.3 @@ -43,6 +43,7 @@ 98.4 import java.util.Random; 98.5 import java.util.Set; 98.6 import java.util.concurrent.atomic.AtomicInteger; 98.7 +import java.util.concurrent.atomic.LongAdder; 98.8 import jdk.internal.dynalink.ChainedCallSite; 98.9 import jdk.internal.dynalink.DynamicLinker; 98.10 import jdk.internal.dynalink.linker.GuardedInvocation; 98.11 @@ -70,7 +71,7 @@ 98.12 LinkerCallSite(final NashornCallSiteDescriptor descriptor) { 98.13 super(descriptor); 98.14 if (Context.DEBUG) { 98.15 - LinkerCallSite.count++; 98.16 + LinkerCallSite.count.increment(); 98.17 } 98.18 } 98.19 98.20 @@ -173,7 +174,7 @@ 98.21 * @return self reference 98.22 */ 98.23 public static Object increaseMissCount(final String desc, final Object self) { 98.24 - ++missCount; 98.25 + missCount.increment(); 98.26 if (r.nextInt(100) < missSamplingPercentage) { 98.27 final AtomicInteger i = missCounts.get(desc); 98.28 if (i == null) { 98.29 @@ -500,7 +501,7 @@ 98.30 * @param desc callsite descriptor string 98.31 * @param args arguments to function 98.32 * 98.33 - * @throws Throwable if invocation failes or throws exception/error 98.34 + * @throws Throwable if invocation fails or throws exception/error 98.35 */ 98.36 @SuppressWarnings("unused") 98.37 public void traceMiss(final String desc, final Object... args) throws Throwable { 98.38 @@ -509,12 +510,19 @@ 98.39 } 98.40 98.41 // counters updated in debug mode 98.42 - private static int count; 98.43 + private static LongAdder count; 98.44 private static final HashMap<String, AtomicInteger> missCounts = new HashMap<>(); 98.45 - private static int missCount; 98.46 + private static LongAdder missCount; 98.47 private static final Random r = new Random(); 98.48 private static final int missSamplingPercentage = Options.getIntProperty("nashorn.tcs.miss.samplePercent", 1); 98.49 98.50 + static { 98.51 + if (Context.DEBUG) { 98.52 + count = new LongAdder(); 98.53 + missCount = new LongAdder(); 98.54 + } 98.55 + } 98.56 + 98.57 @Override 98.58 protected int getMaxChainLength() { 98.59 return 8; 98.60 @@ -524,16 +532,16 @@ 98.61 * Get the callsite count 98.62 * @return the count 98.63 */ 98.64 - public static int getCount() { 98.65 - return count; 98.66 + public static long getCount() { 98.67 + return count.longValue(); 98.68 } 98.69 98.70 /** 98.71 * Get the callsite miss count 98.72 * @return the missCount 98.73 */ 98.74 - public static int getMissCount() { 98.75 - return missCount; 98.76 + public static long getMissCount() { 98.77 + return missCount.longValue(); 98.78 } 98.79 98.80 /**
99.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Thu Sep 24 10:00:42 2015 -0700 99.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Thu Sep 24 10:09:56 2015 -0700 99.3 @@ -26,7 +26,6 @@ 99.4 package jdk.nashorn.internal.runtime.linker; 99.5 99.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 99.7 -import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 99.8 99.9 import java.lang.invoke.MethodHandle; 99.10 import java.lang.invoke.MethodHandles; 99.11 @@ -42,13 +41,11 @@ 99.12 import jdk.internal.dynalink.linker.LinkerServices; 99.13 import jdk.internal.dynalink.linker.MethodHandleTransformer; 99.14 import jdk.internal.dynalink.support.DefaultInternalObjectFilter; 99.15 -import jdk.internal.dynalink.support.Guards; 99.16 import jdk.internal.dynalink.support.Lookup; 99.17 import jdk.nashorn.api.scripting.ScriptUtils; 99.18 import jdk.nashorn.internal.runtime.ConsString; 99.19 import jdk.nashorn.internal.runtime.Context; 99.20 import jdk.nashorn.internal.runtime.ScriptObject; 99.21 -import jdk.nashorn.internal.runtime.ScriptRuntime; 99.22 import jdk.nashorn.internal.runtime.options.Options; 99.23 99.24 /** 99.25 @@ -171,7 +168,7 @@ 99.26 } 99.27 99.28 for (final Class<?> iface : clazz.getInterfaces()) { 99.29 - // check accessiblity up-front 99.30 + // check accessibility up-front 99.31 if (! Context.isAccessibleClass(iface)) { 99.32 continue; 99.33 }
100.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Thu Sep 24 10:00:42 2015 -0700 100.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Thu Sep 24 10:09:56 2015 -0700 100.3 @@ -323,7 +323,7 @@ 100.4 * {@code NashornCallSiteDescriptor}. This allows for graceful interoperability when linking Nashorn with code 100.5 * generated outside of Nashorn. 100.6 * @param flag the tested flag 100.7 - * @return true if the flag is set, false otherwise (it will be false if the decriptor is not a Nashorn call site 100.8 + * @return true if the flag is set, false otherwise (it will be false if the descriptor is not a Nashorn call site 100.9 * descriptor). 100.10 */ 100.11 private static boolean isFlag(final CallSiteDescriptor desc, final int flag) {
101.1 --- a/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java Thu Sep 24 10:00:42 2015 -0700 101.2 +++ b/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java Thu Sep 24 10:09:56 2015 -0700 101.3 @@ -163,7 +163,7 @@ 101.4 101.5 /** 101.6 * Does this option automatically enable another option, i.e. a dependency. 101.7 - * @return the dependecy or null if non exists 101.8 + * @return the dependency or null if none exists 101.9 */ 101.10 public String getDependency() { 101.11 return this.dependency; 101.12 @@ -304,8 +304,8 @@ 101.13 } 101.14 } 101.15 101.16 - boolean matches(final String key0) { 101.17 - return key0.equals(this.shortName) || key0.equals(this.name); 101.18 + boolean nameMatches(final String aName) { 101.19 + return aName.equals(this.shortName) || aName.equals(this.name); 101.20 } 101.21 101.22 private static final int LINE_BREAK = 64;
102.1 --- a/src/jdk/nashorn/internal/runtime/options/Options.java Thu Sep 24 10:00:42 2015 -0700 102.2 +++ b/src/jdk/nashorn/internal/runtime/options/Options.java Thu Sep 24 10:09:56 2015 -0700 102.3 @@ -519,9 +519,25 @@ 102.4 } 102.5 } 102.6 102.7 - private static OptionTemplate getOptionTemplate(final String key) { 102.8 + /** 102.9 + * Retrieves an option template identified by key. 102.10 + * @param shortKey the short (that is without the e.g. "nashorn.option." part) key 102.11 + * @return the option template identified by the key 102.12 + * @throws IllegalArgumentException if the key doesn't specify an existing template 102.13 + */ 102.14 + public OptionTemplate getOptionTemplateByKey(final String shortKey) { 102.15 + final String fullKey = key(shortKey); 102.16 + for(final OptionTemplate t: validOptions) { 102.17 + if(t.getKey().equals(fullKey)) { 102.18 + return t; 102.19 + } 102.20 + } 102.21 + throw new IllegalArgumentException(shortKey); 102.22 + } 102.23 + 102.24 + private static OptionTemplate getOptionTemplateByName(final String name) { 102.25 for (final OptionTemplate t : Options.validOptions) { 102.26 - if (t.matches(key)) { 102.27 + if (t.nameMatches(name)) { 102.28 return t; 102.29 } 102.30 } 102.31 @@ -681,7 +697,7 @@ 102.32 } 102.33 102.34 final String token = st.nextToken(); 102.35 - this.template = Options.getOptionTemplate(token); 102.36 + this.template = getOptionTemplateByName(token); 102.37 if (this.template == null) { 102.38 throw new IllegalArgumentException(argument); 102.39 }
103.1 --- a/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java Thu Sep 24 10:00:42 2015 -0700 103.2 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java Thu Sep 24 10:09:56 2015 -0700 103.3 @@ -65,7 +65,7 @@ 103.4 103.5 final boolean DONT_OPTIMIZE = false; 103.6 103.7 - final boolean USE_STRING_TEMPLATES = true; // use embeded string templates in Regex object as byte arrays instead of compiling them into int bytecode array 103.8 + final boolean USE_STRING_TEMPLATES = true; // use embedded string templates in Regex object as byte arrays instead of compiling them into int bytecode array 103.9 103.10 final boolean NON_UNICODE_SDW = true; 103.11
104.1 --- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties Thu Sep 24 10:00:42 2015 -0700 104.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties Thu Sep 24 10:09:56 2015 -0700 104.3 @@ -150,6 +150,7 @@ 104.4 type.error.method.not.constructor=Java method {0} cannot be used as a constructor. 104.5 type.error.env.not.object=$ENV must be an Object. 104.6 type.error.unsupported.java.to.type=Unsupported Java.to target type {0}. 104.7 +type.error.java.array.conversion.failed=Java.to conversion to array type {0} failed 104.8 type.error.constructor.requires.new=Constructor {0} requires "new". 104.9 type.error.new.on.nonpublic.javatype=new cannot be used with non-public java type {0}. 104.10 104.11 @@ -163,6 +164,7 @@ 104.12 range.error.invalid.date=Invalid Date 104.13 range.error.too.many.errors=Script contains too many errors: {0} errors 104.14 range.error.concat.string.too.big=Concatenated String is too big 104.15 +range.error.exec.returned.non.zero=$EXEC returned non-zero exit code: {0} 104.16 104.17 reference.error.not.defined="{0}" is not defined 104.18 reference.error.cant.be.used.as.lhs="{0}" can not be used as the left-hand side of assignment 104.19 @@ -173,7 +175,9 @@ 104.20 syntax.error.unprotected.switch.declaration=Unsupported {0} declaration in unprotected switch statement 104.21 104.22 io.error.cant.write=cannot write "{0}" 104.23 + 104.24 config.error.no.dest=no destination directory supplied 104.25 +config.error.eagerCompilationConflictsWithOptimisticTypes={0}=false (eager compilation) is not compatible with {1}=true. 104.26 104.27 uri.error.bad.uri=Bad URI "{0}" near offset {1} 104.28 list.adapter.null.global=Attempted to create the adapter from outside a JavaScript execution context.
105.1 --- a/src/jdk/nashorn/internal/runtime/resources/parser.js Thu Sep 24 10:00:42 2015 -0700 105.2 +++ b/src/jdk/nashorn/internal/runtime/resources/parser.js Thu Sep 24 10:09:56 2015 -0700 105.3 @@ -55,7 +55,7 @@ 105.4 // do not start with '/'. If regexp, then eval it to make RegExp object 105.5 return value.startsWith('/')? eval(value) : value.substring(1); 105.6 } else { 105.7 - // anythin else is returned "as is"" 105.8 + // anything else is returned "as is" 105.9 return value; 105.10 } 105.11 });
106.1 --- a/test/script/basic/JDK-8043232.js Thu Sep 24 10:00:42 2015 -0700 106.2 +++ b/test/script/basic/JDK-8043232.js Thu Sep 24 10:09:56 2015 -0700 106.3 @@ -29,14 +29,14 @@ 106.4 */ 106.5 106.6 // call explicit constructor 106.7 -print(new (java.awt["Color(int,int,int)"])(255,0,255)); 106.8 +print(new (java.lang["String(char[],int,int)"])(['a','b', 'c', 'd'], 1, 3)); 106.9 // print the constructor itself 106.10 -print(java.awt["Color(int,int,int)"]); 106.11 +print(java.lang["String(char[],int,int)"]); 106.12 106.13 // store constructor to call later 106.14 -var Color = java.awt["Color(int,int,int)"]; 106.15 +var Color = java.lang["String(char[],int,int)"]; 106.16 // call stored constructor 106.17 -print(new Color(33, 233, 2)) 106.18 +print(new Color(['r','r', 'e', 'd'], 1, 3)) 106.19 106.20 // check if default constructor works 106.21 var obj = new (java.lang["Object()"])();
107.1 --- a/test/script/basic/JDK-8043232.js.EXPECTED Thu Sep 24 10:00:42 2015 -0700 107.2 +++ b/test/script/basic/JDK-8043232.js.EXPECTED Thu Sep 24 10:09:56 2015 -0700 107.3 @@ -1,14 +1,28 @@ 107.4 -java.awt.Color[r=255,g=0,b=255] 107.5 -[jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] 107.6 -java.awt.Color[r=33,g=233,b=2] 107.7 +bcd 107.8 +[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] 107.9 +red 107.10 TypeError: No such Java class: java.lang.NonExistent 107.11 TypeError: No such Java constructor: Object(String) 107.12 TypeError: Java constructor signature invalid: Object()xxxxx 107.13 TypeError: Java constructor signature invalid: Object( 107.14 TypeError: Java constructor signature invalid: Object) 107.15 -TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.lang.System.getProperty] cannot be used as a constructor. 107.16 -TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println] cannot be used as a constructor. 107.17 -TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] requires "new". 107.18 +TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod 107.19 + String java.lang.System.getProperty(String,String) 107.20 + String java.lang.System.getProperty(String) 107.21 +] cannot be used as a constructor. 107.22 +TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod 107.23 + void java.io.PrintStream.println() 107.24 + void java.io.PrintStream.println(boolean) 107.25 + void java.io.PrintStream.println(char) 107.26 + void java.io.PrintStream.println(char[]) 107.27 + void java.io.PrintStream.println(double) 107.28 + void java.io.PrintStream.println(float) 107.29 + void java.io.PrintStream.println(int) 107.30 + void java.io.PrintStream.println(long) 107.31 + void java.io.PrintStream.println(Object) 107.32 + void java.io.PrintStream.println(String) 107.33 +] cannot be used as a constructor. 107.34 +TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new". 107.35 TypeError: No such Java constructor: Runnable() 107.36 TypeError: No such Java constructor: Runnable(int) 107.37 java.lang.InstantiationException: java.io.InputStream
108.1 --- a/test/script/basic/JDK-8044750.js Thu Sep 24 10:00:42 2015 -0700 108.2 +++ b/test/script/basic/JDK-8044750.js Thu Sep 24 10:09:56 2015 -0700 108.3 @@ -25,6 +25,8 @@ 108.4 * JDK-8044750: megamorphic getter for scope objects does not call __noSuchProperty__ hook 108.5 * 108.6 * @test 108.7 + * @fork 108.8 + * @option -Dnashorn.unstable.relink.threshold=16 108.9 * @run 108.10 */ 108.11 108.12 @@ -40,7 +42,9 @@ 108.13 } 108.14 } 108.15 108.16 -for (var i = 0; i < 20; i++) { 108.17 +var LIMIT = 20; // should be more than megamorphic threshold set via @option 108.18 + 108.19 +for (var i = 0; i < LIMIT; i++) { 108.20 var obj = {}; 108.21 obj.foo = i; 108.22 obj[i] = i; 108.23 @@ -51,3 +55,30 @@ 108.24 // callsite inside func should see __noSuchProperty__ 108.25 // hook on global scope object. 108.26 func({}); 108.27 + 108.28 +function checkFoo() { 108.29 + with({}) { 108.30 + try { 108.31 + foo; 108.32 + return true; 108.33 + } catch (e) { 108.34 + return false; 108.35 + } 108.36 + } 108.37 +} 108.38 + 108.39 +var oldNoSuchProperty = this.__noSuchProperty__; 108.40 +delete this.__noSuchProperty__; 108.41 + 108.42 +// keep deleting/restorting __noSuchProperty__ alternatively 108.43 +// to make "foo" access in checkFoo function megamorphic! 108.44 + 108.45 +for (var i = 0; i < LIMIT; i++) { 108.46 + // no __noSuchProperty__ and 'with' scope object has no 'foo' 108.47 + delete __noSuchProperty__; 108.48 + Assert.assertFalse(checkFoo(), "Expected false in iteration " + i); 108.49 + 108.50 + // __noSuchProperty__ is exists but 'with' scope object has no 'foo' 108.51 + this.__noSuchProperty__ = oldNoSuchProperty; 108.52 + Assert.assertTrue(checkFoo(), "Expected true in iteration " + i); 108.53 +}
109.1 --- a/test/script/basic/JDK-8049086.js Thu Sep 24 10:00:42 2015 -0700 109.2 +++ b/test/script/basic/JDK-8049086.js Thu Sep 24 10:09:56 2015 -0700 109.3 @@ -58,7 +58,7 @@ 109.4 // (a) Java methods (b) Java classes (as these respond to new) 109.5 // (c) FunctionalInterface objects (d) JSObjects that are 'functions' 109.6 109.7 -print("java.awt.Color is java function? " + Java.isJavaFunction(java.awt.Color)); 109.8 +print("java.lang.String is java function? " + Java.isJavaFunction(java.lang.String)); 109.9 print("java.lang.Runnable instance is java function? " 109.10 + Java.isJavaFunction(new java.lang.Runnable(function() {}))); 109.11 print("eval is java function? " + Java.isJavaFunction(eval));
110.1 --- a/test/script/basic/JDK-8049086.js.EXPECTED Thu Sep 24 10:00:42 2015 -0700 110.2 +++ b/test/script/basic/JDK-8049086.js.EXPECTED Thu Sep 24 10:09:56 2015 -0700 110.3 @@ -13,7 +13,7 @@ 110.4 Object is script object? true 110.5 {} is script object? true 110.6 /foo/ is script object? true 110.7 -java.awt.Color is java function? true 110.8 +java.lang.String is java function? true 110.9 java.lang.Runnable instance is java function? true 110.10 eval is java function? false 110.11 println is java function? true
111.1 --- a/test/script/basic/JDK-8049242.js Thu Sep 24 10:00:42 2015 -0700 111.2 +++ b/test/script/basic/JDK-8049242.js Thu Sep 24 10:09:56 2015 -0700 111.3 @@ -29,14 +29,14 @@ 111.4 */ 111.5 111.6 // call explicit constructor 111.7 -print(new (Java.type("java.awt.Color")["(int,int,int)"])(255,0,255)); 111.8 +print(new (Java.type("java.lang.String")["(char[],int,int)"])(['a', 'b', 'c'],0, 3)); 111.9 // print the constructor itself 111.10 -print(Java.type("java.awt.Color")["(int,int,int)"]); 111.11 +print(Java.type("java.lang.String")["(char[],int,int)"]); 111.12 111.13 // store constructor to call later 111.14 -var Color = Java.type("java.awt.Color")["(int,int,int)"]; 111.15 +var Color = Java.type("java.lang.String")["(char[],int,int)"]; 111.16 // call stored constructor 111.17 -print(new Color(33, 233, 2)) 111.18 +print(new Color(['j', 'a', 'v', 'a'], 1, 3)) 111.19 111.20 // check if default constructor works 111.21 var obj = new (Java.type("java.lang.Object")["()"])();
112.1 --- a/test/script/basic/JDK-8049242.js.EXPECTED Thu Sep 24 10:00:42 2015 -0700 112.2 +++ b/test/script/basic/JDK-8049242.js.EXPECTED Thu Sep 24 10:09:56 2015 -0700 112.3 @@ -1,10 +1,10 @@ 112.4 -java.awt.Color[r=255,g=0,b=255] 112.5 -[jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] 112.6 -java.awt.Color[r=33,g=233,b=2] 112.7 +abc 112.8 +[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] 112.9 +ava 112.10 TypeError: null is not a function 112.11 TypeError: null is not a function 112.12 TypeError: null is not a function 112.13 -TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] requires "new". 112.14 +TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new". 112.15 TypeError: null is not a function 112.16 TypeError: null is not a function 112.17 java.lang.InstantiationException: java.io.InputStream
113.1 --- a/test/script/basic/JDK-8053905.js Thu Sep 24 10:00:42 2015 -0700 113.2 +++ b/test/script/basic/JDK-8053905.js Thu Sep 24 10:09:56 2015 -0700 113.3 @@ -28,6 +28,7 @@ 113.4 * @runif external.octane 113.5 * @fork 113.6 * @option -Dnashorn.compiler.splitter.threshold=1000 113.7 + * @option -Dnashorn.options.allowEagerCompilationSilentOverride 113.8 * @option -scripting 113.9 * @option --lazy-compilation=false 113.10 */
114.1 --- a/test/script/basic/JDK-8058561.js Thu Sep 24 10:00:42 2015 -0700 114.2 +++ b/test/script/basic/JDK-8058561.js Thu Sep 24 10:09:56 2015 -0700 114.3 @@ -26,7 +26,9 @@ 114.4 * 114.5 * @test 114.6 * @run 114.7 + * @fork 114.8 * @option --lazy-compilation=false 114.9 + * @option -Dnashorn.options.allowEagerCompilationSilentOverride 114.10 */ 114.11 114.12 // Just attempting to compile this caused the NPE
115.1 --- a/test/script/basic/JDK-8078612_eager_1a.js Thu Sep 24 10:00:42 2015 -0700 115.2 +++ b/test/script/basic/JDK-8078612_eager_1a.js Thu Sep 24 10:09:56 2015 -0700 115.3 @@ -29,6 +29,7 @@ 115.4 * @option -pcc 115.5 * @option --lazy-compilation=false 115.6 * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache 115.7 + * @option -Dnashorn.options.allowEagerCompilationSilentOverride 115.8 * @fork 115.9 */ 115.10
116.1 --- a/test/script/basic/JDK-8078612_eager_1b.js Thu Sep 24 10:00:42 2015 -0700 116.2 +++ b/test/script/basic/JDK-8078612_eager_1b.js Thu Sep 24 10:09:56 2015 -0700 116.3 @@ -29,6 +29,7 @@ 116.4 * @option -pcc 116.5 * @option --lazy-compilation=false 116.6 * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache 116.7 + * @option -Dnashorn.options.allowEagerCompilationSilentOverride 116.8 * @fork 116.9 */ 116.10
117.1 --- a/test/script/basic/JDK-8078612_eager_2a.js Thu Sep 24 10:00:42 2015 -0700 117.2 +++ b/test/script/basic/JDK-8078612_eager_2a.js Thu Sep 24 10:09:56 2015 -0700 117.3 @@ -29,6 +29,7 @@ 117.4 * @option -pcc 117.5 * @option --lazy-compilation=false 117.6 * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache 117.7 + * @option -Dnashorn.options.allowEagerCompilationSilentOverride 117.8 * @fork 117.9 */ 117.10
118.1 --- a/test/script/basic/JDK-8078612_eager_2b.js Thu Sep 24 10:00:42 2015 -0700 118.2 +++ b/test/script/basic/JDK-8078612_eager_2b.js Thu Sep 24 10:09:56 2015 -0700 118.3 @@ -29,6 +29,7 @@ 118.4 * @option -pcc 118.5 * @option --lazy-compilation=false 118.6 * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache 118.7 + * @option -Dnashorn.options.allowEagerCompilationSilentOverride 118.8 * @fork 118.9 */ 118.10
119.1 --- a/test/script/basic/JDK-8079470.js.EXPECTED Thu Sep 24 10:00:42 2015 -0700 119.2 +++ b/test/script/basic/JDK-8079470.js.EXPECTED Thu Sep 24 10:09:56 2015 -0700 119.3 @@ -1,2 +1,2 @@ 119.4 -TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod File java.io.File.java.io.File(String,String)] with the passed arguments; they do not match any of its method signatures. 119.5 -TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] with the passed arguments; they do not match any of its method signatures. 119.6 +TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.io.File(String,String)] with the passed arguments; they do not match any of its method signatures. 119.7 +TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.awt.Color(int,int,int)] with the passed arguments; they do not match any of its method signatures.
120.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 120.2 +++ b/test/script/basic/JDK-8134939.js Thu Sep 24 10:09:56 2015 -0700 120.3 @@ -0,0 +1,43 @@ 120.4 +/* 120.5 + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. 120.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 120.7 + * 120.8 + * This code is free software; you can redistribute it and/or modify it 120.9 + * under the terms of the GNU General Public License version 2 only, as 120.10 + * published by the Free Software Foundation. 120.11 + * 120.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 120.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 120.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 120.15 + * version 2 for more details (a copy is included in the LICENSE file that 120.16 + * accompanied this code). 120.17 + * 120.18 + * You should have received a copy of the GNU General Public License version 120.19 + * 2 along with this work; if not, write to the Free Software Foundation, 120.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 120.21 + * 120.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 120.23 + * or visit www.oracle.com if you need additional information or have any 120.24 + * questions. 120.25 + */ 120.26 + 120.27 +/** 120.28 + * JDK-8134939: Improve toString method of Dynalink OverloadedDynamicMethod 120.29 + * 120.30 + * @test 120.31 + * @run 120.32 + */ 120.33 + 120.34 +var overloadedSetter = new (Java.type("jdk.nashorn.test.models.OverloadedSetter")); 120.35 + 120.36 +Assert.assertEquals(String(overloadedSetter.foo), 120.37 + "[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" + 120.38 + " String jdk.nashorn.test.models.OverloadedSetter.foo(String)\n" + 120.39 + " void jdk.nashorn.test.models.OverloadedSetter.foo(int)\n" + 120.40 + "]"); 120.41 + 120.42 +Assert.assertEquals(String(overloadedSetter.setColor), 120.43 + "[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" + 120.44 + " void jdk.nashorn.test.models.OverloadedSetter.setColor(int)\n" + 120.45 + " void jdk.nashorn.test.models.OverloadedSetter.setColor(String)\n" + 120.46 + "]");
121.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 121.2 +++ b/test/script/basic/JDK-8136544.js Thu Sep 24 10:09:56 2015 -0700 121.3 @@ -0,0 +1,65 @@ 121.4 +/* 121.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 121.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 121.7 + * 121.8 + * This code is free software; you can redistribute it and/or modify it 121.9 + * under the terms of the GNU General Public License version 2 only, as 121.10 + * published by the Free Software Foundation. 121.11 + * 121.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 121.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 121.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 121.15 + * version 2 for more details (a copy is included in the LICENSE file that 121.16 + * accompanied this code). 121.17 + * 121.18 + * You should have received a copy of the GNU General Public License version 121.19 + * 2 along with this work; if not, write to the Free Software Foundation, 121.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 121.21 + * 121.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 121.23 + * or visit www.oracle.com if you need additional information or have any 121.24 + * questions. 121.25 + */ 121.26 + 121.27 +/** 121.28 + * JDK-8136544: Call site switching to megamorphic causes incorrect property read 121.29 + * 121.30 + * @test 121.31 + * @fork 121.32 + * @option -Dnashorn.unstable.relink.threshold=8 121.33 + * @run 121.34 + */ 121.35 + 121.36 +var ScriptContext = Java.type("javax.script.ScriptContext"); 121.37 +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); 121.38 +var m = new ScriptEngineManager(); 121.39 +var e = m.getEngineByName("nashorn"); 121.40 + 121.41 +var scope = e.getBindings(ScriptContext.ENGINE_SCOPE); 121.42 +var MYVAR = "myvar"; 121.43 + 121.44 +function loopupVar() { 121.45 + try { 121.46 + e.eval(MYVAR); 121.47 + return true; 121.48 + } catch (e) { 121.49 + return false; 121.50 + } 121.51 +} 121.52 + 121.53 +// make sure we exercise callsite beyond megamorphic threshold we set 121.54 +// in this test via nashorn.unstable.relink.threshold property 121.55 +// In each iteration, callsite is exercised twice (two evals) 121.56 +// So, LIMIT should be more than 4 to exercise megamorphic callsites. 121.57 + 121.58 +var LIMIT = 5; // This LIMIT should be more than 4 121.59 + 121.60 +for (var i = 0; i < LIMIT; i++) { 121.61 + // remove the variable and lookup 121.62 + delete scope[MYVAR]; 121.63 + Assert.assertFalse(loopupVar(), "Expected true in iteration " + i); 121.64 + 121.65 + // set that variable and check again 121.66 + scope[MYVAR] = "foo"; 121.67 + Assert.assertTrue(loopupVar(), "Expected false in iteration " + i); 121.68 +}
122.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 122.2 +++ b/test/script/basic/JDK-8136694.js Thu Sep 24 10:09:56 2015 -0700 122.3 @@ -0,0 +1,74 @@ 122.4 +/* 122.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 122.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 122.7 + * 122.8 + * This code is free software; you can redistribute it and/or modify it 122.9 + * under the terms of the GNU General Public License version 2 only, as 122.10 + * published by the Free Software Foundation. 122.11 + * 122.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 122.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 122.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 122.15 + * version 2 for more details (a copy is included in the LICENSE file that 122.16 + * accompanied this code). 122.17 + * 122.18 + * You should have received a copy of the GNU General Public License version 122.19 + * 2 along with this work; if not, write to the Free Software Foundation, 122.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 122.21 + * 122.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 122.23 + * or visit www.oracle.com if you need additional information or have any 122.24 + * questions. 122.25 + */ 122.26 + 122.27 +/** 122.28 + * JDK-8136694: Megemorphic scope access does not throw ReferenceError when property is missing 122.29 + * 122.30 + * @test 122.31 + * @fork 122.32 + * @option -Dnashorn.unstable.relink.threshold=16 122.33 + * @run 122.34 + */ 122.35 + 122.36 +function checkFoo() { 122.37 + try { 122.38 + // The 'foo' access becomes megamorphic 122.39 + foo; 122.40 + return true; 122.41 + } catch (e) { 122.42 + return false; 122.43 + } 122.44 +} 122.45 + 122.46 + 122.47 +// Similar check for 'with' blocks as well. 122.48 +function checkFooInWith() { 122.49 + with({}) { 122.50 + try { 122.51 + // The 'foo' access becomes megamorphic 122.52 + foo; 122.53 + return true; 122.54 + } catch (e) { 122.55 + return false; 122.56 + } 122.57 + } 122.58 +} 122.59 + 122.60 +function loop(checker) { 122.61 + // LIMIT has to be more than the megamorphic threashold 122.62 + // set via @option in this test header! 122.63 + var LIMIT = 20; 122.64 + for (var i = 0; i < LIMIT; i++) { 122.65 + // make sure global has no "foo" 122.66 + delete foo; 122.67 + Assert.assertFalse(checker(), "Expected false in interation " + i); 122.68 + 122.69 + // now add 'foo' in global 122.70 + foo = 44; 122.71 + Assert.assertTrue(checker(), "Expected true in interation " + i); 122.72 + } 122.73 +} 122.74 + 122.75 + 122.76 +loop(checkFoo); 122.77 +loop(checkFooInWith);
123.1 --- a/test/script/basic/javaarrayconversion.js Thu Sep 24 10:00:42 2015 -0700 123.2 +++ b/test/script/basic/javaarrayconversion.js Thu Sep 24 10:09:56 2015 -0700 123.3 @@ -128,24 +128,32 @@ 123.4 // Converting to string, toString takes precedence over valueOf 123.5 test({ valueOf: function() { return "42"; }, toString: function() { return "43"; } }, "java.lang.String", "43") 123.6 123.7 +function assertCanConvert(sourceType, targetType) { 123.8 + Java.to([new (Java.type(sourceType))()], targetType + "[]") 123.9 + ++testCount; 123.10 +} 123.11 + 123.12 function assertCantConvert(sourceType, targetType) { 123.13 try { 123.14 - Java.to([new Java.type(sourceType)()], targetType + "[]") 123.15 + Java.to([new (Java.type(sourceType))()], targetType + "[]") 123.16 throw "no TypeError encountered" 123.17 } catch(e) { 123.18 - if(!(e instanceof TypeError)) { 123.19 + if(!(e instanceof TypeError) || 123.20 + !e.message.startsWith("Java.to conversion to array type")) { 123.21 throw e; 123.22 } 123.23 ++testCount; 123.24 } 123.25 } 123.26 123.27 +// Arbitrary POJOs to JS Primitive type should work 123.28 +assertCanConvert("java.util.BitSet", "int") 123.29 +assertCanConvert("java.util.BitSet", "double") 123.30 +assertCanConvert("java.util.BitSet", "long") 123.31 +assertCanConvert("java.util.BitSet", "boolean") 123.32 +assertCanConvert("java.util.BitSet", "java.lang.String") 123.33 + 123.34 // Arbitrary POJOs can't be converted to Java values 123.35 -assertCantConvert("java.util.BitSet", "int") 123.36 -assertCantConvert("java.util.BitSet", "double") 123.37 -assertCantConvert("java.util.BitSet", "long") 123.38 -assertCantConvert("java.util.BitSet", "boolean") 123.39 -assertCantConvert("java.util.BitSet", "java.lang.String") 123.40 assertCantConvert("java.util.BitSet", "java.lang.Double") 123.41 assertCantConvert("java.util.BitSet", "java.lang.Long") 123.42
124.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 124.2 +++ b/test/script/trusted/JDK-8087292.js Thu Sep 24 10:09:56 2015 -0700 124.3 @@ -0,0 +1,54 @@ 124.4 +/* 124.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 124.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 124.7 + * 124.8 + * This code is free software; you can redistribute it and/or modify it 124.9 + * under the terms of the GNU General Public License version 2 only, as 124.10 + * published by the Free Software Foundation. 124.11 + * 124.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 124.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 124.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 124.15 + * version 2 for more details (a copy is included in the LICENSE file that 124.16 + * accompanied this code). 124.17 + * 124.18 + * You should have received a copy of the GNU General Public License version 124.19 + * 2 along with this work; if not, write to the Free Software Foundation, 124.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 124.21 + * 124.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 124.23 + * or visit www.oracle.com if you need additional information or have any 124.24 + * questions. 124.25 + */ 124.26 + 124.27 +/** 124.28 + * JDK-8087292: nashorn should have a "fail-fast" option for scripting, analog to bash "set -e" 124.29 + * 124.30 + * @test 124.31 + * @option -scripting 124.32 + * @run 124.33 + */ 124.34 + 124.35 +function tryExec() { 124.36 + try { 124.37 + `java` 124.38 + } catch (e) { 124.39 + print(e); 124.40 + } 124.41 + 124.42 + // make sure we got non-zero ("failure") exit code! 124.43 + if ($EXIT == 0) { 124.44 + print("Error: expected $EXIT code to be non-zero"); 124.45 + } 124.46 +} 124.47 + 124.48 +// no exception now! 124.49 +tryExec(); 124.50 + 124.51 +// turn on error with non-zero exit code 124.52 +$EXEC.throwOnError = true; 124.53 +tryExec(); 124.54 + 124.55 +// no exception after this 124.56 +$EXEC.throwOnError = false; 124.57 +tryExec();
125.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 125.2 +++ b/test/script/trusted/JDK-8087292.js.EXPECTED Thu Sep 24 10:09:56 2015 -0700 125.3 @@ -0,0 +1,1 @@ 125.4 +RangeError: $EXEC returned non-zero exit code: 1
126.1 --- a/test/script/trusted/classfilter.js.EXPECTED Thu Sep 24 10:00:42 2015 -0700 126.2 +++ b/test/script/trusted/classfilter.js.EXPECTED Thu Sep 24 10:09:56 2015 -0700 126.3 @@ -4,7 +4,18 @@ 126.4 typeof java.util.Map evalutes to function 126.5 typeof java.util.HashMap evalutes to function 126.6 var m = new java.util.HashMap(); m.put('foo', 42); m evalutes to {foo=42} 126.7 -java.lang.System.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println] 126.8 +java.lang.System.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod 126.9 + void java.io.PrintStream.println() 126.10 + void java.io.PrintStream.println(boolean) 126.11 + void java.io.PrintStream.println(char) 126.12 + void java.io.PrintStream.println(char[]) 126.13 + void java.io.PrintStream.println(double) 126.14 + void java.io.PrintStream.println(float) 126.15 + void java.io.PrintStream.println(int) 126.16 + void java.io.PrintStream.println(long) 126.17 + void java.io.PrintStream.println(Object) 126.18 + void java.io.PrintStream.println(String) 126.19 +] 126.20 java.lang.System.exit evalutes to [jdk.internal.dynalink.beans.SimpleDynamicMethod void java.lang.System.exit(int)] 126.21 new javax.script.SimpleBindings throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.SimpleBindings 126.22 Java.type('javax.script.ScriptContext') throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.ScriptContext
127.1 --- a/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java Thu Sep 24 10:00:42 2015 -0700 127.2 +++ b/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java Thu Sep 24 10:09:56 2015 -0700 127.3 @@ -26,6 +26,7 @@ 127.4 127.5 import static org.testng.Assert.assertEquals; 127.6 import static org.testng.Assert.assertNotNull; 127.7 +import static org.testng.Assert.assertFalse; 127.8 import static org.testng.Assert.assertTrue; 127.9 import static org.testng.Assert.fail; 127.10 import javax.script.Bindings; 127.11 @@ -820,4 +821,38 @@ 127.12 public void recursiveEvalCallScriptContextTest() throws ScriptException { 127.13 new RecursiveEval().program(); 127.14 } 127.15 + 127.16 + private static final String VAR_NAME = "myvar"; 127.17 + 127.18 + private static boolean lookupVar(final ScriptEngine engine, final String varName) { 127.19 + try { 127.20 + engine.eval(varName); 127.21 + return true; 127.22 + } catch (final ScriptException se) { 127.23 + return false; 127.24 + } 127.25 + } 127.26 + 127.27 + // @bug 8136544: Call site switching to megamorphic causes incorrect property read 127.28 + @Test 127.29 + public void megamorphicPropertyReadTest() throws ScriptException { 127.30 + final NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); 127.31 + final ScriptEngine engine = factory.getScriptEngine(); 127.32 + final Bindings scope = engine.getBindings(ScriptContext.ENGINE_SCOPE); 127.33 + boolean ret; 127.34 + 127.35 + // Why 16 is the upper limit of this loop? The default nashorn dynalink megamorphic threshold is 16. 127.36 + // See jdk.nashorn.internal.runtime.linker.Bootstrap.NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD 127.37 + // We do, 'eval' of the same in this loop twice. So, 16*2 = 32 times that callsite in the script 127.38 + // is exercised - much beyond the default megamorphic threshold. 127.39 + 127.40 + for (int i = 0; i < 16; i++) { 127.41 + scope.remove(VAR_NAME); 127.42 + ret = lookupVar(engine, VAR_NAME); 127.43 + assertFalse(ret, "Expected false in iteration " + i); 127.44 + scope.put(VAR_NAME, "foo"); 127.45 + ret = lookupVar(engine, VAR_NAME); 127.46 + assertTrue(ret, "Expected true in iteration " + i); 127.47 + } 127.48 + } 127.49 }