Tue, 16 Sep 2014 13:59:37 -0700
Merge
bin/fixorphantests.sh | file | annotate | diff | comparison | revisions | |
bin/fixwhitespace.sh | file | annotate | diff | comparison | revisions | |
bin/jjsdebug.sh | file | annotate | diff | comparison | revisions | |
bin/rm-non-tracked.sh | file | annotate | diff | comparison | revisions | |
bin/run_octane.sh | file | annotate | diff | comparison | revisions | |
test/script/basic/JDK-8048079_1.js | file | annotate | diff | comparison | revisions | |
test/script/basic/JDK-8048079_1.js.EXPECTED | file | annotate | diff | comparison | revisions | |
test/script/basic/JDK-8048079_2.js | file | annotate | diff | comparison | revisions | |
test/script/basic/JDK-8048079_2.js.EXPECTED | file | annotate | diff | comparison | revisions |
1.1 --- a/bin/fixorphantests.sh Thu Sep 11 15:34:13 2014 -0700 1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 @@ -1,52 +0,0 @@ 1.4 -#!/bin/sh 1.5 -# 1.6 -# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 1.7 -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 -# 1.9 -# This code is free software; you can redistribute it and/or modify it 1.10 -# under the terms of the GNU General Public License version 2 only, as 1.11 -# published by the Free Software Foundation. 1.12 -# 1.13 -# This code is distributed in the hope that it will be useful, but WITHOUT 1.14 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.15 -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.16 -# version 2 for more details (a copy is included in the LICENSE file that 1.17 -# accompanied this code). 1.18 -# 1.19 -# You should have received a copy of the GNU General Public License version 1.20 -# 2 along with this work; if not, write to the Free Software Foundation, 1.21 -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.22 -# 1.23 -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.24 -# or visit www.oracle.com if you need additional information or have any 1.25 -# questions. 1.26 -# 1.27 - 1.28 -#ensure that all tests tagged with @test are also tagged with @run 1.29 - 1.30 -for f in $(find test/script/basic/*.js); do 1.31 - grep @test $f >/dev/null 1.32 - TEST=$? 1.33 - grep @run $f >/dev/null 1.34 - RUN=$? 1.35 - 1.36 - if [ $TEST -eq 0 ] && [ ! $RUN -eq 0 ]; then 1.37 - echo "repairing ${f}..." 1.38 - TEMP=$(mktemp /tmp/scratch.XXXXXX) 1.39 - 1.40 - #IFS='', -raw flag to preserve white space 1.41 - while IFS='' read -r line; do 1.42 - echo $line | grep @test >/dev/null 1.43 - TEST=$? 1.44 - printf "%s\n" "$line" 1.45 - if [ $TEST -eq 0 ]; then 1.46 - printf "%s\n" "$line" | sed s/@test/@run/g 1.47 - fi 1.48 - done < $f >$TEMP 1.49 - 1.50 - cp $TEMP $f 1.51 - 1.52 - rm -fr $TEMP 1.53 - fi 1.54 - 1.55 -done
2.1 --- a/bin/fixwhitespace.sh Thu Sep 11 15:34:13 2014 -0700 2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 2.3 @@ -1,37 +0,0 @@ 2.4 -#!/bin/bash 2.5 -# 2.6 -# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 2.7 -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 -# 2.9 -# This code is free software; you can redistribute it and/or modify it 2.10 -# under the terms of the GNU General Public License version 2 only, as 2.11 -# published by the Free Software Foundation. 2.12 -# 2.13 -# This code is distributed in the hope that it will be useful, but WITHOUT 2.14 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.15 -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.16 -# version 2 for more details (a copy is included in the LICENSE file that 2.17 -# accompanied this code). 2.18 -# 2.19 -# You should have received a copy of the GNU General Public License version 2.20 -# 2 along with this work; if not, write to the Free Software Foundation, 2.21 -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.22 -# 2.23 -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.24 -# or visit www.oracle.com if you need additional information or have any 2.25 -# questions. 2.26 -# 2.27 - 2.28 -fix() { 2.29 - #convert tabs to spaces 2.30 - find . -name $1 -exec sed -i "" 's/ / /g' {} \; 2.31 - #remove trailing whitespace 2.32 - find . -name $1 -exec sed -i "" 's/[ ]*$//' \{} \; 2.33 -} 2.34 - 2.35 -if [ ! -z $1 ]; then 2.36 - fix $1; 2.37 -else 2.38 - fix "*.java" 2.39 - fix "*.js" 2.40 -fi
3.1 --- a/bin/jjsdebug.sh Thu Sep 11 15:34:13 2014 -0700 3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 3.3 @@ -1,25 +0,0 @@ 3.4 -#!/bin/sh 3.5 -# 3.6 -# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3.7 -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 -# 3.9 -# This code is free software; you can redistribute it and/or modify it 3.10 -# under the terms of the GNU General Public License version 2 only, as 3.11 -# published by the Free Software Foundation. 3.12 -# 3.13 -# This code is distributed in the hope that it will be useful, but WITHOUT 3.14 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.15 -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.16 -# version 2 for more details (a copy is included in the LICENSE file that 3.17 -# accompanied this code). 3.18 -# 3.19 -# You should have received a copy of the GNU General Public License version 3.20 -# 2 along with this work; if not, write to the Free Software Foundation, 3.21 -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.22 -# 3.23 -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.24 -# or visit www.oracle.com if you need additional information or have any 3.25 -# questions. 3.26 -# 3.27 - 3.28 -$JAVA_HOME/bin/jjs -J-Djava.ext.dirs=`dirname $0`/../dist -J-agentlib:jdwp=transport=dt_socket,address=localhost:9009,server=y,suspend=y $*
4.1 --- a/bin/rm-non-tracked.sh Thu Sep 11 15:34:13 2014 -0700 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,24 +0,0 @@ 4.4 -#!/bin/bash 4.5 -# 4.6 -# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 4.7 -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.8 -# 4.9 -# This code is free software; you can redistribute it and/or modify it 4.10 -# under the terms of the GNU General Public License version 2 only, as 4.11 -# published by the Free Software Foundation. 4.12 -# 4.13 -# This code is distributed in the hope that it will be useful, but WITHOUT 4.14 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.15 -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.16 -# version 2 for more details (a copy is included in the LICENSE file that 4.17 -# accompanied this code). 4.18 -# 4.19 -# You should have received a copy of the GNU General Public License version 4.20 -# 2 along with this work; if not, write to the Free Software Foundation, 4.21 -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.22 -# 4.23 -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.24 -# or visit www.oracle.com if you need additional information or have any 4.25 -# questions. 4.26 -# 4.27 -hg status|grep ^\?|awk '{print $2}'|xargs rm
5.1 --- a/bin/run_octane.sh Thu Sep 11 15:34:13 2014 -0700 5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 5.3 @@ -1,51 +0,0 @@ 5.4 -#!/bin/bash 5.5 -# 5.6 -# Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 5.7 -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.8 -# 5.9 -# This code is free software; you can redistribute it and/or modify it 5.10 -# under the terms of the GNU General Public License version 2 only, as 5.11 -# published by the Free Software Foundation. 5.12 -# 5.13 -# This code is distributed in the hope that it will be useful, but WITHOUT 5.14 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.15 -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.16 -# version 2 for more details (a copy is included in the LICENSE file that 5.17 -# accompanied this code). 5.18 -# 5.19 -# You should have received a copy of the GNU General Public License version 5.20 -# 2 along with this work; if not, write to the Free Software Foundation, 5.21 -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.22 -# 5.23 -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.24 -# or visit www.oracle.com if you need additional information or have any 5.25 -# questions. 5.26 -# 5.27 - 5.28 -LOG="./octane_$(date|sed "s/ /_/g"|sed "s/:/_/g").log" 5.29 - 5.30 -run_one() { 5.31 - sh ../bin/runopt.sh -scripting ../test/script/basic/run-octane.js -- $1 --verbose --iterations 25 | tee -a $LOG 5.32 -} 5.33 - 5.34 -if [ -z $1 ]; then 5.35 - 5.36 - run_one "box2d" 5.37 - run_one "code-load" 5.38 - run_one "crypto" 5.39 - run_one "deltablue" 5.40 - run_one "earley-boyer" 5.41 - run_one "gbemu" 5.42 - run_one "mandreel" 5.43 - run_one "navier-stokes" 5.44 - run_one "pdfjs" 5.45 - run_one "raytrace" 5.46 - run_one "regexp" 5.47 - run_one "richards" 5.48 - run_one "splay" 5.49 - run_one "typescript" 5.50 - run_one "zlib" 5.51 - 5.52 -else 5.53 - run_one $1 5.54 -fi
6.1 --- a/make/build.xml Thu Sep 11 15:34:13 2014 -0700 6.2 +++ b/make/build.xml Tue Sep 16 13:59:37 2014 -0700 6.3 @@ -340,6 +340,13 @@ 6.4 permission java.util.PropertyPermission "nashorn.test.*", "read"; 6.5 }; 6.6 6.7 +grant codeBase "file:/${basedir}/test/script/basic/es6/*" { 6.8 + permission java.io.FilePermission "${basedir}/test/script/-", "read"; 6.9 + permission java.io.FilePermission "$${user.dir}", "read"; 6.10 + permission java.util.PropertyPermission "user.dir", "read"; 6.11 + permission java.util.PropertyPermission "nashorn.test.*", "read"; 6.12 +}; 6.13 + 6.14 grant codeBase "file:/${basedir}/test/script/basic/JDK-8010946-privileged.js" { 6.15 permission java.util.PropertyPermission "java.security.policy", "read"; 6.16 };
7.1 --- a/src/jdk/nashorn/internal/codegen/AssignSymbols.java Thu Sep 11 15:34:13 2014 -0700 7.2 +++ b/src/jdk/nashorn/internal/codegen/AssignSymbols.java Tue Sep 16 13:59:37 2014 -0700 7.3 @@ -36,6 +36,7 @@ 7.4 import static jdk.nashorn.internal.codegen.CompilerConstants.THIS; 7.5 import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS; 7.6 import static jdk.nashorn.internal.ir.Symbol.HAS_OBJECT_VALUE; 7.7 +import static jdk.nashorn.internal.ir.Symbol.IS_CONST; 7.8 import static jdk.nashorn.internal.ir.Symbol.IS_FUNCTION_SELF; 7.9 import static jdk.nashorn.internal.ir.Symbol.IS_GLOBAL; 7.10 import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL; 7.11 @@ -83,11 +84,13 @@ 7.12 import jdk.nashorn.internal.ir.UnaryNode; 7.13 import jdk.nashorn.internal.ir.VarNode; 7.14 import jdk.nashorn.internal.ir.WithNode; 7.15 -import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor; 7.16 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 7.17 import jdk.nashorn.internal.runtime.Context; 7.18 -import jdk.nashorn.internal.runtime.Property; 7.19 -import jdk.nashorn.internal.runtime.PropertyMap; 7.20 +import jdk.nashorn.internal.runtime.ECMAErrors; 7.21 +import jdk.nashorn.internal.runtime.ErrorManager; 7.22 +import jdk.nashorn.internal.runtime.JSErrorType; 7.23 +import jdk.nashorn.internal.runtime.ParserException; 7.24 +import jdk.nashorn.internal.runtime.Source; 7.25 import jdk.nashorn.internal.runtime.logging.DebugLogger; 7.26 import jdk.nashorn.internal.runtime.logging.Loggable; 7.27 import jdk.nashorn.internal.runtime.logging.Logger; 7.28 @@ -101,7 +104,7 @@ 7.29 * visitor. 7.30 */ 7.31 @Logger(name="symbols") 7.32 -final class AssignSymbols extends NodeOperatorVisitor<LexicalContext> implements Loggable { 7.33 +final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggable { 7.34 private final DebugLogger log; 7.35 private final boolean debug; 7.36 7.37 @@ -190,22 +193,21 @@ 7.38 * @param body the body of the FunctionNode we are entering 7.39 */ 7.40 private void acceptDeclarations(final FunctionNode functionNode, final Block body) { 7.41 - // This visitor will assign symbol to all declared variables, except function declarations (which are taken care 7.42 - // in a separate step above) and "var" declarations in for loop initializers. 7.43 - // 7.44 + // This visitor will assign symbol to all declared variables, except "var" declarations in for loop initializers. 7.45 body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 7.46 @Override 7.47 - public boolean enterFunctionNode(final FunctionNode nestedFn) { 7.48 - // Don't descend into nested functions 7.49 - return false; 7.50 + protected boolean enterDefault(final Node node) { 7.51 + // Don't bother visiting expressions; var is a statement, it can't be inside an expression. 7.52 + // This will also prevent visiting nested functions (as FunctionNode is an expression). 7.53 + return !(node instanceof Expression); 7.54 } 7.55 7.56 @Override 7.57 public Node leaveVarNode(final VarNode varNode) { 7.58 if (varNode.isStatement()) { 7.59 final IdentNode ident = varNode.getName(); 7.60 - final Symbol symbol = defineSymbol(body, ident.getName(), IS_VAR); 7.61 - functionNode.addDeclaredSymbol(symbol); 7.62 + final Block block = varNode.isBlockScoped() ? getLexicalContext().getCurrentBlock() : body; 7.63 + final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags()); 7.64 if (varNode.isFunctionDeclaration()) { 7.65 symbol.setIsFunctionDeclaration(); 7.66 } 7.67 @@ -303,23 +305,31 @@ 7.68 return functionNode.setBody(lc, body.setStatements(lc, newStatements)); 7.69 } 7.70 7.71 - private Symbol defineGlobalSymbol(final Block block, final String name) { 7.72 - return defineSymbol(block, name, IS_GLOBAL); 7.73 - } 7.74 - 7.75 /** 7.76 * Defines a new symbol in the given block. 7.77 * 7.78 * @param block the block in which to define the symbol 7.79 * @param name name of symbol. 7.80 + * @param origin origin node 7.81 * @param symbolFlags Symbol flags. 7.82 * 7.83 * @return Symbol for given name or null for redefinition. 7.84 */ 7.85 - private Symbol defineSymbol(final Block block, final String name, final int symbolFlags) { 7.86 + private Symbol defineSymbol(final Block block, final String name, final Node origin, final int symbolFlags) { 7.87 int flags = symbolFlags; 7.88 - Symbol symbol = findSymbol(block, name); // Locate symbol. 7.89 - final boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL; 7.90 + final boolean isBlockScope = (flags & IS_LET) != 0 || (flags & IS_CONST) != 0; 7.91 + final boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL; 7.92 + 7.93 + Symbol symbol; 7.94 + final FunctionNode function; 7.95 + if (isBlockScope) { 7.96 + // block scoped variables always live in current block, no need to look for existing symbols in parent blocks. 7.97 + symbol = block.getExistingSymbol(name); 7.98 + function = lc.getCurrentFunction(); 7.99 + } else { 7.100 + symbol = findSymbol(block, name); 7.101 + function = lc.getFunction(block); 7.102 + } 7.103 7.104 // Global variables are implicitly always scope variables too. 7.105 if (isGlobal) { 7.106 @@ -333,7 +343,6 @@ 7.107 final boolean isParam = (flags & KINDMASK) == IS_PARAM; 7.108 final boolean isVar = (flags & KINDMASK) == IS_VAR; 7.109 7.110 - final FunctionNode function = lc.getFunction(block); 7.111 if (symbol != null) { 7.112 // Symbol was already defined. Check if it needs to be redefined. 7.113 if (isParam) { 7.114 @@ -345,10 +354,21 @@ 7.115 throw new AssertionError("duplicate parameter"); 7.116 } 7.117 } else if (isVar) { 7.118 - if ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET) { 7.119 + if (isBlockScope) { 7.120 + // Check redeclaration in same block 7.121 + if (symbol.hasBeenDeclared()) { 7.122 + throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin); 7.123 + } else { 7.124 + symbol.setHasBeenDeclared(); 7.125 + } 7.126 + } else if ((flags & IS_INTERNAL) != 0) { 7.127 // Always create a new definition. 7.128 symbol = null; 7.129 } else { 7.130 + // Found LET or CONST in parent scope of same function - s SyntaxError 7.131 + if (symbol.isBlockScoped() && isLocal(lc.getCurrentFunction(), symbol)) { 7.132 + throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin); 7.133 + } 7.134 // Not defined in this function. Create a new definition. 7.135 if (!isLocal(function, symbol) || symbol.less(IS_VAR)) { 7.136 symbol = null; 7.137 @@ -359,10 +379,10 @@ 7.138 7.139 if (symbol == null) { 7.140 // If not found, then create a new one. 7.141 - Block symbolBlock; 7.142 + final Block symbolBlock; 7.143 7.144 // Determine where to create it. 7.145 - if (isVar && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) { 7.146 + if (isVar && ((flags & IS_INTERNAL) != 0 || isBlockScope)) { 7.147 symbolBlock = block; //internal vars are always defined in the block closest to them 7.148 } else if (isGlobal) { 7.149 symbolBlock = lc.getOutermostFunction().getBody(); 7.150 @@ -420,15 +440,30 @@ 7.151 @Override 7.152 public boolean enterBlock(final Block block) { 7.153 start(block); 7.154 - block.clearSymbols(); 7.155 7.156 if (lc.isFunctionBody()) { 7.157 + block.clearSymbols(); 7.158 + final FunctionNode fn = lc.getCurrentFunction(); 7.159 + if (isUnparsedFunction(fn)) { 7.160 + // It's a skipped nested function. Just mark the symbols being used by it as being in use. 7.161 + for(final String name: compiler.getScriptFunctionData(fn.getId()).getExternalSymbolNames()) { 7.162 + nameIsUsed(name, null); 7.163 + } 7.164 + // Don't bother descending into it, it must be empty anyway. 7.165 + assert block.getStatements().isEmpty(); 7.166 + return false; 7.167 + } 7.168 + 7.169 enterFunctionBody(); 7.170 } 7.171 7.172 return true; 7.173 } 7.174 7.175 + private boolean isUnparsedFunction(final FunctionNode fn) { 7.176 + return compiler.isOnDemandCompilation() && fn != lc.getOutermostFunction(); 7.177 + } 7.178 + 7.179 @Override 7.180 public boolean enterCatchNode(final CatchNode catchNode) { 7.181 final IdentNode exception = catchNode.getException(); 7.182 @@ -441,7 +476,10 @@ 7.183 // If the name of the exception starts with ":e", this is a synthetic catch block, likely a catch-all. Its 7.184 // symbol is naturally internal, and should be treated as such. 7.185 final boolean isInternal = exname.startsWith(EXCEPTION_PREFIX.symbolName()); 7.186 - defineSymbol(block, exname, IS_VAR | IS_LET | (isInternal ? IS_INTERNAL : 0) | HAS_OBJECT_VALUE); 7.187 + // IS_LET flag is required to make sure symbol is not visible outside catch block. However, we need to 7.188 + // clear the IS_LET flag after creation to allow redefinition of symbol inside the catch block. 7.189 + final Symbol symbol = defineSymbol(block, exname, catchNode, IS_VAR | IS_LET | (isInternal ? IS_INTERNAL : 0) | HAS_OBJECT_VALUE); 7.190 + symbol.clearFlag(IS_LET); 7.191 7.192 return true; 7.193 } 7.194 @@ -452,15 +490,13 @@ 7.195 7.196 initFunctionWideVariables(functionNode, body); 7.197 7.198 - if (functionNode.isProgram()) { 7.199 - initGlobalSymbols(body); 7.200 - } else if (!functionNode.isDeclared() && !functionNode.isAnonymous()) { 7.201 + if (!functionNode.isProgram() && !functionNode.isDeclared() && !functionNode.isAnonymous()) { 7.202 // It's neither declared nor program - it's a function expression then; assign it a self-symbol unless it's 7.203 // anonymous. 7.204 final String name = functionNode.getIdent().getName(); 7.205 assert name != null; 7.206 assert body.getExistingSymbol(name) == null; 7.207 - defineSymbol(body, name, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE); 7.208 + defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE); 7.209 if(functionNode.allVarsInScope()) { // basically, has deep eval 7.210 lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL); 7.211 } 7.212 @@ -471,41 +507,48 @@ 7.213 7.214 @Override 7.215 public boolean enterFunctionNode(final FunctionNode functionNode) { 7.216 - // TODO: once we have information on symbols used by nested functions, we can stop descending into nested 7.217 - // functions with on-demand compilation, e.g. add 7.218 - // if(!thisProperties.isEmpty() && env.isOnDemandCompilation()) { 7.219 - // return false; 7.220 - // } 7.221 start(functionNode, false); 7.222 7.223 thisProperties.push(new HashSet<String>()); 7.224 7.225 - //an outermost function in our lexical context that is not a program 7.226 - //is possible - it is a function being compiled lazily 7.227 if (functionNode.isDeclared()) { 7.228 + // Can't use lc.getCurrentBlock() as we can have an outermost function in our lexical context that 7.229 + // is not a program - it is a function being compiled on-demand. 7.230 final Iterator<Block> blocks = lc.getBlocks(); 7.231 if (blocks.hasNext()) { 7.232 - defineSymbol(blocks.next(), functionNode.getIdent().getName(), IS_VAR | (functionNode.isAnonymous()? IS_INTERNAL : 0)); 7.233 + final IdentNode ident = functionNode.getIdent(); 7.234 + defineSymbol(blocks.next(), ident.getName(), ident, IS_VAR | (functionNode.isAnonymous()? IS_INTERNAL : 0)); 7.235 } 7.236 } 7.237 7.238 + // Every function has a body, even the ones skipped on reparse (they have an empty one). We're 7.239 + // asserting this as even for those, enterBlock() must be invoked to correctly process symbols that 7.240 + // are used in them. 7.241 + assert functionNode.getBody() != null; 7.242 + 7.243 return true; 7.244 } 7.245 7.246 @Override 7.247 public boolean enterVarNode(final VarNode varNode) { 7.248 start(varNode); 7.249 - defineSymbol(lc.getCurrentBlock(), varNode.getName().getName(), IS_VAR | (lc.getCurrentFunction().isProgram() ? IS_SCOPE : 0)); 7.250 return true; 7.251 } 7.252 7.253 + @Override 7.254 + public Node leaveVarNode(final VarNode varNode) { 7.255 + final IdentNode ident = varNode.getName(); 7.256 + defineSymbol(lc.getCurrentBlock(), ident.getName(), ident, varNode.getSymbolFlags() | (lc.getCurrentFunction().isProgram() ? IS_SCOPE : 0)); 7.257 + return super.leaveVarNode(varNode); 7.258 + } 7.259 + 7.260 private Symbol exceptionSymbol() { 7.261 return newObjectInternal(EXCEPTION_PREFIX); 7.262 } 7.263 7.264 /** 7.265 * This has to run before fix assignment types, store any type specializations for 7.266 - * paramters, then turn then to objects for the generic version of this method 7.267 + * parameters, then turn them into objects for the generic version of this method. 7.268 * 7.269 * @param functionNode functionNode 7.270 */ 7.271 @@ -597,7 +640,7 @@ 7.272 } 7.273 7.274 private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags) { 7.275 - defineSymbol(block, cc.symbolName(), flags).setNeedsSlot(true); 7.276 + defineSymbol(block, cc.symbolName(), null, flags).setNeedsSlot(true); 7.277 } 7.278 7.279 private void initFunctionWideVariables(final FunctionNode functionNode, final Block body) { 7.280 @@ -608,7 +651,7 @@ 7.281 initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL | HAS_OBJECT_VALUE); 7.282 if (functionNode.needsArguments()) { 7.283 initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | HAS_OBJECT_VALUE); 7.284 - defineSymbol(body, ARGUMENTS_VAR.symbolName(), IS_VAR | HAS_OBJECT_VALUE); 7.285 + defineSymbol(body, ARGUMENTS_VAR.symbolName(), null, IS_VAR | HAS_OBJECT_VALUE); 7.286 } 7.287 } 7.288 7.289 @@ -617,20 +660,6 @@ 7.290 initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL); 7.291 } 7.292 7.293 - 7.294 - /** 7.295 - * Move any properties from the global map into the scope of this function (which must be a program function). 7.296 - * @param block the function node body for which to init scope vars 7.297 - */ 7.298 - private void initGlobalSymbols(final Block block) { 7.299 - final PropertyMap map = Context.getGlobalMap(); 7.300 - 7.301 - for (final Property property : map.getProperties()) { 7.302 - final Symbol symbol = defineGlobalSymbol(block, property.getKey()); 7.303 - log.info("Added global symbol from property map ", symbol); 7.304 - } 7.305 - } 7.306 - 7.307 /** 7.308 * Initialize parameters for function node. 7.309 * @param functionNode the function node 7.310 @@ -639,7 +668,7 @@ 7.311 final boolean isVarArg = functionNode.isVarArg(); 7.312 final boolean scopeParams = functionNode.allVarsInScope() || isVarArg; 7.313 for (final IdentNode param : functionNode.getParameters()) { 7.314 - final Symbol symbol = defineSymbol(body, param.getName(), IS_PARAM); 7.315 + final Symbol symbol = defineSymbol(body, param.getName(), param, IS_PARAM); 7.316 if(scopeParams) { 7.317 // NOTE: this "set is scope" is a poor substitute for clear expression of where the symbol is stored. 7.318 // It will force creation of scopes where they would otherwise not necessarily be needed (functions 7.319 @@ -665,10 +694,29 @@ 7.320 return definingFn == function; 7.321 } 7.322 7.323 + private void checkConstAssignment(final IdentNode ident) { 7.324 + // Check for reassignment of constant 7.325 + final Symbol symbol = ident.getSymbol(); 7.326 + if (symbol.isConst()) { 7.327 + throwParserException(ECMAErrors.getMessage("syntax.error.assign.constant", symbol.getName()), ident); 7.328 + } 7.329 + } 7.330 + 7.331 @Override 7.332 - public Node leaveASSIGN(final BinaryNode binaryNode) { 7.333 + public Node leaveBinaryNode(final BinaryNode binaryNode) { 7.334 + if (binaryNode.isAssignment() && binaryNode.lhs() instanceof IdentNode) { 7.335 + checkConstAssignment((IdentNode) binaryNode.lhs()); 7.336 + } 7.337 + switch (binaryNode.tokenType()) { 7.338 + case ASSIGN: 7.339 + return leaveASSIGN(binaryNode); 7.340 + default: 7.341 + return super.leaveBinaryNode(binaryNode); 7.342 + } 7.343 + } 7.344 + 7.345 + private Node leaveASSIGN(final BinaryNode binaryNode) { 7.346 // If we're assigning a property of the this object ("this.foo = ..."), record it. 7.347 - 7.348 final Expression lhs = binaryNode.lhs(); 7.349 if (lhs instanceof AccessNode) { 7.350 final AccessNode accessNode = (AccessNode) lhs; 7.351 @@ -684,23 +732,43 @@ 7.352 } 7.353 7.354 @Override 7.355 + public Node leaveUnaryNode(final UnaryNode unaryNode) { 7.356 + if (unaryNode.isAssignment() && unaryNode.getExpression() instanceof IdentNode) { 7.357 + checkConstAssignment((IdentNode) unaryNode.getExpression()); 7.358 + } 7.359 + switch (unaryNode.tokenType()) { 7.360 + case DELETE: 7.361 + return leaveDELETE(unaryNode); 7.362 + case TYPEOF: 7.363 + return leaveTYPEOF(unaryNode); 7.364 + default: 7.365 + return super.leaveUnaryNode(unaryNode); 7.366 + } 7.367 + } 7.368 + 7.369 + @Override 7.370 public Node leaveBlock(final Block block) { 7.371 - // It's not necessary to guard the marking of symbols as locals with this "if"condition for correctness, it's 7.372 - // just an optimization -- runtime type calculation is not used when the compilation is not an on-demand 7.373 - // optimistic compilation, so we can skip locals marking then. 7.374 + // It's not necessary to guard the marking of symbols as locals with this "if" condition for 7.375 + // correctness, it's just an optimization -- runtime type calculation is not used when the compilation 7.376 + // is not an on-demand optimistic compilation, so we can skip locals marking then. 7.377 if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) { 7.378 - for (final Symbol symbol: block.getSymbols()) { 7.379 - if (!symbol.isScope()) { 7.380 - assert symbol.isVar() || symbol.isParam(); 7.381 - compiler.declareLocalSymbol(symbol.getName()); 7.382 + // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand 7.383 + // compilation, and we're skipping parsing the function bodies for nested functions, this 7.384 + // basically only means their parameters. It'd be enough to mistakenly declare to be a local a 7.385 + // symbol in the outer function named the same as one of the parameters, though. 7.386 + if (lc.getFunction(block) == lc.getOutermostFunction()) { 7.387 + for (final Symbol symbol: block.getSymbols()) { 7.388 + if (!symbol.isScope()) { 7.389 + assert symbol.isVar() || symbol.isParam(); 7.390 + compiler.declareLocalSymbol(symbol.getName()); 7.391 + } 7.392 } 7.393 } 7.394 } 7.395 return block; 7.396 } 7.397 7.398 - @Override 7.399 - public Node leaveDELETE(final UnaryNode unaryNode) { 7.400 + private Node leaveDELETE(final UnaryNode unaryNode) { 7.401 final FunctionNode currentFunctionNode = lc.getCurrentFunction(); 7.402 final boolean strictMode = currentFunctionNode.isStrict(); 7.403 final Expression rhs = unaryNode.getExpression(); 7.404 @@ -764,24 +832,45 @@ 7.405 7.406 @Override 7.407 public Node leaveFunctionNode(final FunctionNode functionNode) { 7.408 - 7.409 - return markProgramBlock( 7.410 + final FunctionNode finalizedFunction; 7.411 + if (isUnparsedFunction(functionNode)) { 7.412 + finalizedFunction = functionNode; 7.413 + } else { 7.414 + finalizedFunction = 7.415 + markProgramBlock( 7.416 removeUnusedSlots( 7.417 createSyntheticInitializers( 7.418 finalizeParameters( 7.419 lc.applyTopFlags(functionNode)))) 7.420 - .setThisProperties(lc, thisProperties.pop().size()) 7.421 - .setState(lc, CompilationState.SYMBOLS_ASSIGNED)); 7.422 + .setThisProperties(lc, thisProperties.pop().size())); 7.423 + } 7.424 + return finalizedFunction.setState(lc, CompilationState.SYMBOLS_ASSIGNED); 7.425 } 7.426 7.427 @Override 7.428 public Node leaveIdentNode(final IdentNode identNode) { 7.429 - final String name = identNode.getName(); 7.430 - 7.431 if (identNode.isPropertyName()) { 7.432 return identNode; 7.433 } 7.434 7.435 + final Symbol symbol = nameIsUsed(identNode.getName(), identNode); 7.436 + 7.437 + if (!identNode.isInitializedHere()) { 7.438 + symbol.increaseUseCount(); 7.439 + } 7.440 + 7.441 + IdentNode newIdentNode = identNode.setSymbol(symbol); 7.442 + 7.443 + // If a block-scoped var is used before its declaration mark it as dead. 7.444 + // We can only statically detect this for local vars, cross-function symbols require runtime checks. 7.445 + if (symbol.isBlockScoped() && !symbol.hasBeenDeclared() && !identNode.isDeclaredHere() && isLocal(lc.getCurrentFunction(), symbol)) { 7.446 + newIdentNode = newIdentNode.markDead(); 7.447 + } 7.448 + 7.449 + return end(newIdentNode); 7.450 + } 7.451 + 7.452 + private Symbol nameIsUsed(final String name, final IdentNode origin) { 7.453 final Block block = lc.getCurrentBlock(); 7.454 7.455 Symbol symbol = findSymbol(block, name); 7.456 @@ -799,18 +888,12 @@ 7.457 // if symbol is non-local or we're in a with block, we need to put symbol in scope (if it isn't already) 7.458 maybeForceScope(symbol); 7.459 } else { 7.460 - log.info("No symbol exists. Declare as global: ", symbol); 7.461 - symbol = defineGlobalSymbol(block, name); 7.462 - Symbol.setSymbolIsScope(lc, symbol); 7.463 + log.info("No symbol exists. Declare as global: ", name); 7.464 + symbol = defineSymbol(block, name, origin, IS_GLOBAL | IS_SCOPE); 7.465 } 7.466 7.467 functionUsesSymbol(symbol); 7.468 - 7.469 - if (!identNode.isInitializedHere()) { 7.470 - symbol.increaseUseCount(); 7.471 - } 7.472 - 7.473 - return end(identNode.setSymbol(symbol)); 7.474 + return symbol; 7.475 } 7.476 7.477 @Override 7.478 @@ -834,8 +917,7 @@ 7.479 return tryNode; 7.480 } 7.481 7.482 - @Override 7.483 - public Node leaveTYPEOF(final UnaryNode unaryNode) { 7.484 + private Node leaveTYPEOF(final UnaryNode unaryNode) { 7.485 final Expression rhs = unaryNode.getExpression(); 7.486 7.487 final List<Expression> args = new ArrayList<>(); 7.488 @@ -859,7 +941,6 @@ 7.489 return functionNode; 7.490 } 7.491 7.492 - assert functionNode.getId() == 1; 7.493 return functionNode.setBody(lc, functionNode.getBody().setFlag(lc, Block.IS_GLOBAL_SCOPE)); 7.494 } 7.495 7.496 @@ -875,7 +956,7 @@ 7.497 } 7.498 7.499 private Symbol newInternal(final CompilerConstants cc, final int flags) { 7.500 - return defineSymbol(lc.getCurrentBlock(), lc.getCurrentFunction().uniqueName(cc.symbolName()), IS_VAR | IS_INTERNAL | flags); //NASHORN-73 7.501 + return defineSymbol(lc.getCurrentBlock(), lc.getCurrentFunction().uniqueName(cc.symbolName()), null, IS_VAR | IS_INTERNAL | flags); //NASHORN-73 7.502 } 7.503 7.504 private Symbol newObjectInternal(final CompilerConstants cc) { 7.505 @@ -915,7 +996,8 @@ 7.506 return false; 7.507 } 7.508 7.509 - if (lc.getCurrentFunction().allVarsInScope()) { 7.510 + final FunctionNode func = lc.getCurrentFunction(); 7.511 + if ( func.allVarsInScope() || (!symbol.isBlockScoped() && func.isProgram())) { 7.512 return true; 7.513 } 7.514 7.515 @@ -955,4 +1037,16 @@ 7.516 final List<ArrayUnit> units = ((ArrayLiteralNode)expr).getUnits(); 7.517 return !(units == null || units.isEmpty()); 7.518 } 7.519 + 7.520 + private void throwParserException(final String message, final Node origin) { 7.521 + if (origin == null) { 7.522 + throw new ParserException(message); 7.523 + } 7.524 + final Source source = compiler.getSource(); 7.525 + final long token = origin.getToken(); 7.526 + final int line = source.getLine(origin.getStart()); 7.527 + final int column = source.getColumn(origin.getStart()); 7.528 + final String formatted = ErrorManager.format(message, source, line, column, token); 7.529 + throw new ParserException(JSErrorType.SYNTAX_ERROR, formatted, source, line, column, token); 7.530 + } 7.531 }
8.1 --- a/src/jdk/nashorn/internal/codegen/ClassEmitter.java Thu Sep 11 15:34:13 2014 -0700 8.2 +++ b/src/jdk/nashorn/internal/codegen/ClassEmitter.java Tue Sep 16 13:59:37 2014 -0700 8.3 @@ -59,6 +59,7 @@ 8.4 import java.util.EnumSet; 8.5 import java.util.HashSet; 8.6 import java.util.Set; 8.7 + 8.8 import jdk.internal.org.objectweb.asm.ClassWriter; 8.9 import jdk.internal.org.objectweb.asm.MethodVisitor; 8.10 import jdk.internal.org.objectweb.asm.util.TraceClassVisitor; 8.11 @@ -135,6 +136,16 @@ 8.12 /** Set of constants access methods required. */ 8.13 private Set<Class<?>> constantMethodNeeded; 8.14 8.15 + private int methodCount; 8.16 + 8.17 + private int initCount; 8.18 + 8.19 + private int clinitCount; 8.20 + 8.21 + private int fieldCount; 8.22 + 8.23 + private final Set<String> methodNames; 8.24 + 8.25 /** 8.26 * Constructor - only used internally in this class as it breaks 8.27 * abstraction towards ASM or other code generator below 8.28 @@ -146,6 +157,11 @@ 8.29 this.context = context; 8.30 this.cw = cw; 8.31 this.methodsStarted = new HashSet<>(); 8.32 + this.methodNames = new HashSet<>(); 8.33 + } 8.34 + 8.35 + public Set<String> getMethodNames() { 8.36 + return methodNames; 8.37 } 8.38 8.39 /** 8.40 @@ -209,6 +225,38 @@ 8.41 } 8.42 8.43 /** 8.44 + * Get the method count, including init and clinit methods 8.45 + * @return method count 8.46 + */ 8.47 + public int getMethodCount() { 8.48 + return methodCount; 8.49 + } 8.50 + 8.51 + /** 8.52 + * Get the clinit count 8.53 + * @return clinit count 8.54 + */ 8.55 + public int getClinitCount() { 8.56 + return clinitCount; 8.57 + } 8.58 + 8.59 + /** 8.60 + * Get the init count 8.61 + * @return init count 8.62 + */ 8.63 + public int getInitCount() { 8.64 + return initCount; 8.65 + } 8.66 + 8.67 + /** 8.68 + * Get the field count 8.69 + * @return field count 8.70 + */ 8.71 + public int getFieldCount() { 8.72 + return fieldCount; 8.73 + } 8.74 + 8.75 + /** 8.76 * Convert a binary name to a package/class name. 8.77 * 8.78 * @param name Binary name. 8.79 @@ -359,9 +407,16 @@ 8.80 */ 8.81 @Override 8.82 public void end() { 8.83 - assert classStarted; 8.84 + assert classStarted : "class not started for " + unitClassName; 8.85 8.86 if (unitClassName != null) { 8.87 + final MethodEmitter initMethod = init(EnumSet.of(Flag.PRIVATE)); 8.88 + initMethod.begin(); 8.89 + initMethod.load(Type.OBJECT, 0); 8.90 + initMethod.newInstance(jdk.nashorn.internal.scripts.JS.class); 8.91 + initMethod.returnVoid(); 8.92 + initMethod.end(); 8.93 + 8.94 defineCommonUtilities(); 8.95 } 8.96 8.97 @@ -419,6 +474,8 @@ 8.98 } 8.99 8.100 SplitMethodEmitter method(final SplitNode splitNode, final String methodName, final Class<?> rtype, final Class<?>... ptypes) { 8.101 + methodCount++; 8.102 + methodNames.add(methodName); 8.103 return new SplitMethodEmitter(this, methodVisitor(EnumSet.of(Flag.PUBLIC, Flag.STATIC), methodName, rtype, ptypes), splitNode); 8.104 } 8.105 8.106 @@ -446,6 +503,8 @@ 8.107 * @return method emitter to use for weaving this method 8.108 */ 8.109 MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final Class<?> rtype, final Class<?>... ptypes) { 8.110 + methodCount++; 8.111 + methodNames.add(methodName); 8.112 return new MethodEmitter(this, methodVisitor(methodFlags, methodName, rtype, ptypes)); 8.113 } 8.114 8.115 @@ -471,6 +530,8 @@ 8.116 * @return method emitter to use for weaving this method 8.117 */ 8.118 MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final String descriptor) { 8.119 + methodCount++; 8.120 + methodNames.add(methodName); 8.121 return new MethodEmitter(this, cw.visitMethod(Flag.getValue(methodFlags), methodName, descriptor, null, null)); 8.122 } 8.123 8.124 @@ -481,6 +542,8 @@ 8.125 * @return method emitter to use for weaving this method 8.126 */ 8.127 MethodEmitter method(final FunctionNode functionNode) { 8.128 + methodCount++; 8.129 + methodNames.add(functionNode.getName()); 8.130 final FunctionSignature signature = new FunctionSignature(functionNode); 8.131 final MethodVisitor mv = cw.visitMethod( 8.132 ACC_PUBLIC | ACC_STATIC | (functionNode.isVarArg() ? ACC_VARARGS : 0), 8.133 @@ -499,6 +562,8 @@ 8.134 * @return method emitter to use for weaving this method 8.135 */ 8.136 MethodEmitter restOfMethod(final FunctionNode functionNode) { 8.137 + methodCount++; 8.138 + methodNames.add(functionNode.getName()); 8.139 final MethodVisitor mv = cw.visitMethod( 8.140 ACC_PUBLIC | ACC_STATIC, 8.141 functionNode.getName(), 8.142 @@ -516,6 +581,7 @@ 8.143 * @return method emitter to use for weaving <clinit> 8.144 */ 8.145 MethodEmitter clinit() { 8.146 + clinitCount++; 8.147 return method(EnumSet.of(Flag.STATIC), CLINIT.symbolName(), void.class); 8.148 } 8.149 8.150 @@ -525,6 +591,7 @@ 8.151 * @return method emitter to use for weaving <init>()V 8.152 */ 8.153 MethodEmitter init() { 8.154 + initCount++; 8.155 return method(INIT.symbolName(), void.class); 8.156 } 8.157 8.158 @@ -535,6 +602,7 @@ 8.159 * @return method emitter to use for weaving <init>()V 8.160 */ 8.161 MethodEmitter init(final Class<?>... ptypes) { 8.162 + initCount++; 8.163 return method(INIT.symbolName(), void.class, ptypes); 8.164 } 8.165 8.166 @@ -547,6 +615,7 @@ 8.167 * @return method emitter to use for weaving <init>(...)V 8.168 */ 8.169 MethodEmitter init(final EnumSet<Flag> flags, final Class<?>... ptypes) { 8.170 + initCount++; 8.171 return method(flags, INIT.symbolName(), void.class, ptypes); 8.172 } 8.173 8.174 @@ -561,6 +630,7 @@ 8.175 * @see ClassEmitter.Flag 8.176 */ 8.177 final void field(final EnumSet<Flag> fieldFlags, final String fieldName, final Class<?> fieldType, final Object value) { 8.178 + fieldCount++; 8.179 cw.visitField(Flag.getValue(fieldFlags), fieldName, typeDescriptor(fieldType), null, value).visitEnd(); 8.180 } 8.181
9.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Sep 11 15:34:13 2014 -0700 9.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Tue Sep 16 13:59:37 2014 -0700 9.3 @@ -52,6 +52,7 @@ 9.4 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 9.5 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; 9.6 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_APPLY_TO_CALL; 9.7 +import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_DECLARE; 9.8 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_FAST_SCOPE; 9.9 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC; 9.10 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT; 9.11 @@ -302,6 +303,7 @@ 9.12 * @return the method generator used 9.13 */ 9.14 private MethodEmitter loadIdent(final IdentNode identNode, final TypeBounds resultBounds) { 9.15 + checkTemporalDeadZone(identNode); 9.16 final Symbol symbol = identNode.getSymbol(); 9.17 9.18 if (!symbol.isScope()) { 9.19 @@ -334,6 +336,15 @@ 9.20 return method; 9.21 } 9.22 9.23 + // Any access to LET and CONST variables before their declaration must throw ReferenceError. 9.24 + // This is called the temporal dead zone (TDZ). See https://gist.github.com/rwaldron/f0807a758aa03bcdd58a 9.25 + private void checkTemporalDeadZone(final IdentNode identNode) { 9.26 + if (identNode.isDead()) { 9.27 + method.load(identNode.getSymbol().getName()); 9.28 + method.invoke(ScriptRuntime.THROW_REFERENCE_ERROR); 9.29 + } 9.30 + } 9.31 + 9.32 private boolean isRestOf() { 9.33 return continuationEntryPoints != null; 9.34 } 9.35 @@ -1611,9 +1622,18 @@ 9.36 9.37 @Override 9.38 protected void evaluate() { 9.39 - method.load(ITERATOR_TYPE, iterSlot); 9.40 - // TODO: optimistic for-in iteration 9.41 - method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "next", Object.class)); 9.42 + new OptimisticOperation((Optimistic)forNode.getInit(), TypeBounds.UNBOUNDED) { 9.43 + @Override 9.44 + void loadStack() { 9.45 + method.load(ITERATOR_TYPE, iterSlot); 9.46 + } 9.47 + 9.48 + @Override 9.49 + void consumeStack() { 9.50 + method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "next", Object.class)); 9.51 + convertOptimisticReturnValue(); 9.52 + } 9.53 + }.emit(); 9.54 } 9.55 }.store(); 9.56 body.accept(this); 9.57 @@ -3216,27 +3236,34 @@ 9.58 return false; 9.59 } 9.60 final Expression init = varNode.getInit(); 9.61 - 9.62 - if (init == null) { 9.63 - return false; 9.64 - } 9.65 - 9.66 - enterStatement(varNode); 9.67 - 9.68 final IdentNode identNode = varNode.getName(); 9.69 final Symbol identSymbol = identNode.getSymbol(); 9.70 assert identSymbol != null : "variable node " + varNode + " requires a name with a symbol"; 9.71 - 9.72 + final boolean needsScope = identSymbol.isScope(); 9.73 + 9.74 + if (init == null) { 9.75 + if (needsScope && varNode.isBlockScoped()) { 9.76 + // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ) 9.77 + method.loadCompilerConstant(SCOPE); 9.78 + method.loadUndefined(Type.OBJECT); 9.79 + final int flags = CALLSITE_SCOPE | getCallSiteFlags() | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0); 9.80 + assert isFastScope(identSymbol); 9.81 + storeFastScopeVar(identSymbol, flags); 9.82 + } 9.83 + return false; 9.84 + } 9.85 + 9.86 + enterStatement(varNode); 9.87 assert method != null; 9.88 9.89 - final boolean needsScope = identSymbol.isScope(); 9.90 if (needsScope) { 9.91 method.loadCompilerConstant(SCOPE); 9.92 } 9.93 9.94 if (needsScope) { 9.95 loadExpressionUnbounded(init); 9.96 - final int flags = CALLSITE_SCOPE | getCallSiteFlags(); 9.97 + // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ) 9.98 + final int flags = CALLSITE_SCOPE | getCallSiteFlags() | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0); 9.99 if (isFastScope(identSymbol)) { 9.100 storeFastScopeVar(identSymbol, flags); 9.101 } else { 9.102 @@ -4343,6 +4370,9 @@ 9.103 protected abstract void evaluate(); 9.104 9.105 void store() { 9.106 + if (target instanceof IdentNode) { 9.107 + checkTemporalDeadZone((IdentNode)target); 9.108 + } 9.109 prologue(); 9.110 evaluate(); // leaves an operation of whatever the operationType was on the stack 9.111 storeNonDiscard();
10.1 --- a/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java Thu Sep 11 15:34:13 2014 -0700 10.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java Tue Sep 16 13:59:37 2014 -0700 10.3 @@ -31,6 +31,7 @@ 10.4 import java.util.Deque; 10.5 import java.util.HashMap; 10.6 import java.util.Map; 10.7 + 10.8 import jdk.nashorn.internal.IntDeque; 10.9 import jdk.nashorn.internal.codegen.types.Type; 10.10 import jdk.nashorn.internal.ir.Block; 10.11 @@ -158,7 +159,9 @@ 10.12 10.13 CompileUnit popCompileUnit(final CompileUnit oldUnit) { 10.14 assert compileUnits.peek() == oldUnit; 10.15 - compileUnits.pop(); 10.16 + final CompileUnit unit = compileUnits.pop(); 10.17 + assert unit.hasCode() : "compile unit popped without code"; 10.18 + unit.setUsed(); 10.19 return compileUnits.isEmpty() ? null : compileUnits.peek(); 10.20 } 10.21
11.1 --- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java Thu Sep 11 15:34:13 2014 -0700 11.2 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java Tue Sep 16 13:59:37 2014 -0700 11.3 @@ -48,6 +48,7 @@ 11.4 import java.util.Map; 11.5 import java.util.Map.Entry; 11.6 import java.util.Set; 11.7 + 11.8 import jdk.nashorn.internal.AssertsEnabled; 11.9 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; 11.10 import jdk.nashorn.internal.ir.FunctionNode; 11.11 @@ -300,6 +301,7 @@ 11.12 } 11.13 }, 11.14 11.15 + 11.16 /** 11.17 * Reuse compile units, if they are already present. We are using the same compiler 11.18 * to recompile stuff 11.19 @@ -334,6 +336,8 @@ 11.20 if (phases.isRestOfCompilation()) { 11.21 sb.append("$restOf"); 11.22 } 11.23 + //it's ok to not copy the initCount, methodCount and clinitCount here, as codegen is what 11.24 + //fills those out anyway. Thus no need for a copy constructor 11.25 final CompileUnit newUnit = compiler.createCompileUnit(sb.toString(), oldUnit.getWeight()); 11.26 log.fine("Creating new compile unit ", oldUnit, " => ", newUnit); 11.27 map.put(oldUnit, newUnit); 11.28 @@ -430,8 +434,14 @@ 11.29 11.30 FunctionNode newFunctionNode = fn; 11.31 11.32 + //root class is special, as it is bootstrapped from createProgramFunction, thus it's skipped 11.33 + //in CodeGeneration - the rest can be used as a working "is compile unit used" metric 11.34 + fn.getCompileUnit().setUsed(); 11.35 + 11.36 compiler.getLogger().fine("Starting bytecode generation for ", quote(fn.getName()), " - restOf=", phases.isRestOfCompilation()); 11.37 + 11.38 final CodeGenerator codegen = new CodeGenerator(compiler, phases.isRestOfCompilation() ? compiler.getContinuationEntryPoints() : null); 11.39 + 11.40 try { 11.41 // Explicitly set BYTECODE_GENERATED here; it can not be set in case of skipping codegen for :program 11.42 // in the lazy + optimistic world. See CodeGenerator.skipFunction(). 11.43 @@ -455,12 +465,18 @@ 11.44 final ClassEmitter classEmitter = compileUnit.getClassEmitter(); 11.45 classEmitter.end(); 11.46 11.47 + if (!compileUnit.isUsed()) { 11.48 + compiler.getLogger().fine("Skipping unused compile unit ", compileUnit); 11.49 + continue; 11.50 + } 11.51 + 11.52 final byte[] bytecode = classEmitter.toByteArray(); 11.53 assert bytecode != null; 11.54 11.55 final String className = compileUnit.getUnitClassName(); 11.56 + compiler.addClass(className, bytecode); //classes are only added to the bytecode map if compile unit is used 11.57 11.58 - compiler.addClass(className, bytecode); 11.59 + CompileUnit.increaseEmitCount(); 11.60 11.61 // should we verify the generated code? 11.62 if (senv._verify_code) { 11.63 @@ -536,6 +552,9 @@ 11.64 11.65 // initialize function in the compile units 11.66 for (final CompileUnit unit : compiler.getCompileUnits()) { 11.67 + if (!unit.isUsed()) { 11.68 + continue; 11.69 + } 11.70 unit.setCode(installedClasses.get(unit.getUnitClassName())); 11.71 } 11.72
12.1 --- a/src/jdk/nashorn/internal/codegen/CompileUnit.java Thu Sep 11 15:34:13 2014 -0700 12.2 +++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java Tue Sep 16 13:59:37 2014 -0700 12.3 @@ -42,6 +42,10 @@ 12.4 12.5 private Class<?> clazz; 12.6 12.7 + private boolean isUsed; 12.8 + 12.9 + private static int emittedUnitCount; 12.10 + 12.11 CompileUnit(final String className, final ClassEmitter classEmitter, final long initialWeight) { 12.12 this.className = className; 12.13 this.weight = initialWeight; 12.14 @@ -52,6 +56,33 @@ 12.15 return new TreeSet<>(); 12.16 } 12.17 12.18 + static void increaseEmitCount() { 12.19 + emittedUnitCount++; 12.20 + } 12.21 + 12.22 + public static int getEmittedUnitCount() { 12.23 + return emittedUnitCount; 12.24 + } 12.25 + 12.26 + /** 12.27 + * Check if this compile unit is used 12.28 + * @return true if tagged as in use - i.e active code that needs to be generated 12.29 + */ 12.30 + public boolean isUsed() { 12.31 + return isUsed; 12.32 + } 12.33 + 12.34 + public boolean hasCode() { 12.35 + return (classEmitter.getMethodCount() - classEmitter.getInitCount() - classEmitter.getClinitCount()) > 0; 12.36 + } 12.37 + 12.38 + /** 12.39 + * Tag this compile unit as used 12.40 + */ 12.41 + public void setUsed() { 12.42 + this.isUsed = true; 12.43 + } 12.44 + 12.45 /** 12.46 * Return the class that contains the code for this unit, null if not 12.47 * generated yet 12.48 @@ -121,7 +152,8 @@ 12.49 12.50 @Override 12.51 public String toString() { 12.52 - return "[CompileUnit className=" + shortName(className) + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + ']'; 12.53 + final String methods = classEmitter != null ? classEmitter.getMethodNames().toString() : "<anon>"; 12.54 + return "[CompileUnit className=" + shortName(className) + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + " hasCode=" + methods + ']'; 12.55 } 12.56 12.57 @Override
13.1 --- a/src/jdk/nashorn/internal/codegen/Compiler.java Thu Sep 11 15:34:13 2014 -0700 13.2 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java Tue Sep 16 13:59:37 2014 -0700 13.3 @@ -38,7 +38,6 @@ 13.4 import java.util.Arrays; 13.5 import java.util.Collections; 13.6 import java.util.Comparator; 13.7 -import java.util.EnumSet; 13.8 import java.util.HashMap; 13.9 import java.util.Iterator; 13.10 import java.util.LinkedHashMap; 13.11 @@ -51,18 +50,21 @@ 13.12 import java.util.function.Consumer; 13.13 import java.util.logging.Level; 13.14 import jdk.internal.dynalink.support.NameCodec; 13.15 -import jdk.nashorn.internal.codegen.ClassEmitter.Flag; 13.16 import jdk.nashorn.internal.codegen.types.Type; 13.17 +import jdk.nashorn.internal.ir.Expression; 13.18 import jdk.nashorn.internal.ir.FunctionNode; 13.19 import jdk.nashorn.internal.ir.Optimistic; 13.20 import jdk.nashorn.internal.ir.debug.ClassHistogramElement; 13.21 import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator; 13.22 import jdk.nashorn.internal.runtime.CodeInstaller; 13.23 import jdk.nashorn.internal.runtime.Context; 13.24 +import jdk.nashorn.internal.runtime.ErrorManager; 13.25 import jdk.nashorn.internal.runtime.FunctionInitializer; 13.26 +import jdk.nashorn.internal.runtime.ParserException; 13.27 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; 13.28 import jdk.nashorn.internal.runtime.ScriptEnvironment; 13.29 import jdk.nashorn.internal.runtime.ScriptObject; 13.30 +import jdk.nashorn.internal.runtime.ScriptRuntime; 13.31 import jdk.nashorn.internal.runtime.Source; 13.32 import jdk.nashorn.internal.runtime.logging.DebugLogger; 13.33 import jdk.nashorn.internal.runtime.logging.Loggable; 13.34 @@ -89,6 +91,8 @@ 13.35 13.36 private final String sourceName; 13.37 13.38 + private final ErrorManager errors; 13.39 + 13.40 private final boolean optimistic; 13.41 13.42 private final Map<String, byte[]> bytecode; 13.43 @@ -244,6 +248,15 @@ 13.44 return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()])); 13.45 } 13.46 13.47 + @SuppressWarnings("unused") //TODO I'll use this soon 13.48 + private CompilationPhases replace(final CompilationPhase phase, final CompilationPhase newPhase) { 13.49 + final LinkedList<CompilationPhase> list = new LinkedList<>(); 13.50 + for (final CompilationPhase p : phases) { 13.51 + list.add(p == phase ? newPhase : p); 13.52 + } 13.53 + return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()])); 13.54 + } 13.55 + 13.56 private CompilationPhases addAfter(final CompilationPhase phase, final CompilationPhase newPhase) { 13.57 final LinkedList<CompilationPhase> list = new LinkedList<>(); 13.58 for (final CompilationPhase p : phases) { 13.59 @@ -311,6 +324,7 @@ 13.60 * @param env script environment 13.61 * @param installer code installer 13.62 * @param source source to compile 13.63 + * @param errors error manager 13.64 * @param isStrict is this a strict compilation 13.65 */ 13.66 public Compiler( 13.67 @@ -318,8 +332,9 @@ 13.68 final ScriptEnvironment env, 13.69 final CodeInstaller<ScriptEnvironment> installer, 13.70 final Source source, 13.71 + final ErrorManager errors, 13.72 final boolean isStrict) { 13.73 - this(context, env, installer, source, isStrict, false, null, null, null, null, null, null); 13.74 + this(context, env, installer, source, errors, isStrict, false, null, null, null, null, null, null); 13.75 } 13.76 13.77 /** 13.78 @@ -329,6 +344,7 @@ 13.79 * @param env script environment 13.80 * @param installer code installer 13.81 * @param source source to compile 13.82 + * @param errors error manager 13.83 * @param isStrict is this a strict compilation 13.84 * @param isOnDemand is this an on demand compilation 13.85 * @param compiledFunction compiled function, if any 13.86 @@ -343,6 +359,7 @@ 13.87 final ScriptEnvironment env, 13.88 final CodeInstaller<ScriptEnvironment> installer, 13.89 final Source source, 13.90 + final ErrorManager errors, 13.91 final boolean isStrict, 13.92 final boolean isOnDemand, 13.93 final RecompilableScriptFunctionData compiledFunction, 13.94 @@ -359,6 +376,7 @@ 13.95 this.bytecode = new LinkedHashMap<>(); 13.96 this.log = initLogger(context); 13.97 this.source = source; 13.98 + this.errors = errors; 13.99 this.sourceName = FunctionNode.getSourceName(source); 13.100 this.onDemand = isOnDemand; 13.101 this.compiledFunction = compiledFunction; 13.102 @@ -464,6 +482,19 @@ 13.103 return typeEvaluator.getOptimisticType(node); 13.104 } 13.105 13.106 + /** 13.107 + * Returns true if the expression can be safely evaluated, and its value is an object known to always use 13.108 + * String as the type of its property names retrieved through 13.109 + * {@link ScriptRuntime#toPropertyIterator(Object)}. It is used to avoid optimistic assumptions about its 13.110 + * property name types. 13.111 + * @param expr the expression to test 13.112 + * @return true if the expression can be safely evaluated, and its value is an object known to always use 13.113 + * String as the type of its property iterators. 13.114 + */ 13.115 + boolean hasStringPropertyIterator(final Expression expr) { 13.116 + return typeEvaluator.hasStringPropertyIterator(expr); 13.117 + } 13.118 + 13.119 void addInvalidatedProgramPoint(final int programPoint, final Type type) { 13.120 invalidatedProgramPoints.put(programPoint, type); 13.121 } 13.122 @@ -524,7 +555,17 @@ 13.123 13.124 for (final CompilationPhase phase : phases) { 13.125 log.fine(phase, " starting for ", quote(name)); 13.126 - newFunctionNode = phase.apply(this, phases, newFunctionNode); 13.127 + 13.128 + try { 13.129 + newFunctionNode = phase.apply(this, phases, newFunctionNode); 13.130 + } catch (final ParserException error) { 13.131 + errors.error(error); 13.132 + if (env._dump_on_error) { 13.133 + error.printStackTrace(env.getErr()); 13.134 + } 13.135 + return null; 13.136 + } 13.137 + 13.138 log.fine(phase, " done for function ", quote(name)); 13.139 13.140 if (env._print_mem_usage) { 13.141 @@ -656,16 +697,8 @@ 13.142 CompileUnit createCompileUnit(final String unitClassName, final long initialWeight) { 13.143 final ClassEmitter classEmitter = new ClassEmitter(context, sourceName, unitClassName, isStrict()); 13.144 final CompileUnit compileUnit = new CompileUnit(unitClassName, classEmitter, initialWeight); 13.145 - 13.146 classEmitter.begin(); 13.147 13.148 - final MethodEmitter initMethod = classEmitter.init(EnumSet.of(Flag.PRIVATE)); 13.149 - initMethod.begin(); 13.150 - initMethod.load(Type.OBJECT, 0); 13.151 - initMethod.newInstance(jdk.nashorn.internal.scripts.JS.class); 13.152 - initMethod.returnVoid(); 13.153 - initMethod.end(); 13.154 - 13.155 return compileUnit; 13.156 } 13.157 13.158 @@ -703,13 +736,6 @@ 13.159 return name.replace('/', '.'); 13.160 } 13.161 13.162 - RecompilableScriptFunctionData getProgram() { 13.163 - if (compiledFunction == null) { 13.164 - return null; 13.165 - } 13.166 - return compiledFunction.getProgram(); 13.167 - } 13.168 - 13.169 RecompilableScriptFunctionData getScriptFunctionData(final int functionId) { 13.170 return compiledFunction == null ? null : compiledFunction.getScriptFunctionData(functionId); 13.171 }
14.1 --- a/src/jdk/nashorn/internal/codegen/DumpBytecode.java Thu Sep 11 15:34:13 2014 -0700 14.2 +++ b/src/jdk/nashorn/internal/codegen/DumpBytecode.java Tue Sep 16 13:59:37 2014 -0700 14.3 @@ -89,7 +89,7 @@ 14.4 14.5 14.6 // should code be dumped to disk - only valid in compile_only mode? 14.7 - if (env._dest_dir != null && env._compile_only) { 14.8 + if (env._dest_dir != null) { 14.9 final String fileName = className.replace('.', File.separatorChar) + ".class"; 14.10 final int index = fileName.lastIndexOf(File.separatorChar); 14.11
15.1 --- a/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java Thu Sep 11 15:34:13 2014 -0700 15.2 +++ b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java Tue Sep 16 13:59:37 2014 -0700 15.3 @@ -69,9 +69,7 @@ 15.4 * Constructor 15.5 * 15.6 * @param codegen code generator 15.7 - * @param keys keys for fields in object 15.8 - * @param symbols symbols for fields in object 15.9 - * @param values list of values corresponding to keys 15.10 + * @param tuples tuples for fields in object 15.11 */ 15.12 FieldObjectCreator(final CodeGenerator codegen, final List<MapTuple<T>> tuples) { 15.13 this(codegen, tuples, false, false); 15.14 @@ -81,9 +79,7 @@ 15.15 * Constructor 15.16 * 15.17 * @param codegen code generator 15.18 - * @param keys keys for fields in object 15.19 - * @param symbols symbols for fields in object 15.20 - * @param values values (or null where no value) to be written to the fields 15.21 + * @param tuples tuples for fields in object 15.22 * @param isScope is this a scope object 15.23 * @param hasArguments does the created object have an "arguments" property 15.24 */ 15.25 @@ -165,7 +161,7 @@ 15.26 * @param method Script method. 15.27 * @param key Property key. 15.28 * @param fieldIndex Field number. 15.29 - * @param value Value to store. 15.30 + * @param tuple Tuple to store. 15.31 */ 15.32 private void putField(final MethodEmitter method, final String key, final int fieldIndex, final MapTuple<T> tuple) { 15.33 method.dup(); 15.34 @@ -188,7 +184,7 @@ 15.35 * 15.36 * @param method Script method. 15.37 * @param index Slot index. 15.38 - * @param value Value to store. 15.39 + * @param tuple Tuple to store. 15.40 */ 15.41 private void putSlot(final MethodEmitter method, final long index, final MapTuple<T> tuple) { 15.42 method.dup();
16.1 --- a/src/jdk/nashorn/internal/codegen/FindScopeDepths.java Thu Sep 11 15:34:13 2014 -0700 16.2 +++ b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java Tue Sep 16 13:59:37 2014 -0700 16.3 @@ -25,8 +25,6 @@ 16.4 16.5 package jdk.nashorn.internal.codegen; 16.6 16.7 -import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getClassName; 16.8 -import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getPaddedFieldCount; 16.9 import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote; 16.10 16.11 import java.util.HashMap; 16.12 @@ -34,6 +32,7 @@ 16.13 import java.util.Iterator; 16.14 import java.util.Map; 16.15 import java.util.Set; 16.16 +import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor; 16.17 import jdk.nashorn.internal.ir.Block; 16.18 import jdk.nashorn.internal.ir.FunctionNode; 16.19 import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 16.20 @@ -44,7 +43,6 @@ 16.21 import jdk.nashorn.internal.ir.WithNode; 16.22 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 16.23 import jdk.nashorn.internal.runtime.Context; 16.24 -import jdk.nashorn.internal.runtime.PropertyMap; 16.25 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; 16.26 import jdk.nashorn.internal.runtime.logging.DebugLogger; 16.27 import jdk.nashorn.internal.runtime.logging.Loggable; 16.28 @@ -208,14 +206,10 @@ 16.29 16.30 assert nestedFunctions != null; 16.31 // Generate the object class and property map in case this function is ever used as constructor 16.32 - final int fieldCount = getPaddedFieldCount(newFunctionNode.getThisProperties()); 16.33 - final String allocatorClassName = Compiler.binaryName(getClassName(fieldCount)); 16.34 - final PropertyMap allocatorMap = PropertyMap.newMap(null, allocatorClassName, 0, fieldCount, 0); 16.35 final RecompilableScriptFunctionData data = new RecompilableScriptFunctionData( 16.36 newFunctionNode, 16.37 compiler.getCodeInstaller(), 16.38 - allocatorClassName, 16.39 - allocatorMap, 16.40 + new AllocatorDescriptor(newFunctionNode.getThisProperties()), 16.41 nestedFunctions, 16.42 externalSymbolDepths.get(fnId), 16.43 internalSymbols.get(fnId)
17.1 --- a/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Thu Sep 11 15:34:13 2014 -0700 17.2 +++ b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Tue Sep 16 13:59:37 2014 -0700 17.3 @@ -551,13 +551,19 @@ 17.4 17.5 final Expression init = forNode.getInit(); 17.6 if(forNode.isForIn()) { 17.7 - forNode.getModify().accept(this); 17.8 - enterTestFirstLoop(forNode, null, init); 17.9 + final JoinPredecessorExpression iterable = forNode.getModify(); 17.10 + iterable.accept(this); 17.11 + enterTestFirstLoop(forNode, null, init, 17.12 + // If we're iterating over property names, and we can discern from the runtime environment 17.13 + // of the compilation that the object being iterated over must use strings for property 17.14 + // names (e.g., it is a native JS object or array), then we'll not bother trying to treat 17.15 + // the property names optimistically. 17.16 + !forNode.isForEach() && compiler.hasStringPropertyIterator(iterable.getExpression())); 17.17 } else { 17.18 if(init != null) { 17.19 init.accept(this); 17.20 } 17.21 - enterTestFirstLoop(forNode, forNode.getModify(), null); 17.22 + enterTestFirstLoop(forNode, forNode.getModify(), null, false); 17.23 } 17.24 return false; 17.25 } 17.26 @@ -792,7 +798,8 @@ 17.27 return false; 17.28 } 17.29 17.30 - private void enterTestFirstLoop(final LoopNode loopNode, final JoinPredecessorExpression modify, final Expression iteratorValues) { 17.31 + private void enterTestFirstLoop(final LoopNode loopNode, final JoinPredecessorExpression modify, 17.32 + final Expression iteratorValues, final boolean iteratorValuesAreObject) { 17.33 final JoinPredecessorExpression test = loopNode.getTest(); 17.34 if(isAlwaysFalse(test)) { 17.35 test.accept(this); 17.36 @@ -814,8 +821,12 @@ 17.37 jumpToLabel(test, breakLabel); 17.38 } 17.39 if(iteratorValues instanceof IdentNode) { 17.40 - // Receives iterator values; they're currently all objects (JDK-8034954). 17.41 - onAssignment((IdentNode)iteratorValues, LvarType.OBJECT); 17.42 + final IdentNode ident = (IdentNode)iteratorValues; 17.43 + // Receives iterator values; the optimistic type of the iterator values is tracked on the 17.44 + // identifier, but we override optimism if it's known that the object being iterated over will 17.45 + // never have primitive property names. 17.46 + onAssignment(ident, iteratorValuesAreObject ? LvarType.OBJECT : 17.47 + toLvarType(compiler.getOptimisticType(ident))); 17.48 } 17.49 final Block body = loopNode.getBody(); 17.50 body.accept(this); 17.51 @@ -955,7 +966,7 @@ 17.52 if(whileNode.isDoWhile()) { 17.53 enterDoWhileLoop(whileNode); 17.54 } else { 17.55 - enterTestFirstLoop(whileNode, null, null); 17.56 + enterTestFirstLoop(whileNode, null, null, false); 17.57 } 17.58 return false; 17.59 }
18.1 --- a/src/jdk/nashorn/internal/codegen/Lower.java Thu Sep 11 15:34:13 2014 -0700 18.2 +++ b/src/jdk/nashorn/internal/codegen/Lower.java Tue Sep 16 13:59:37 2014 -0700 18.3 @@ -71,7 +71,6 @@ 18.4 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 18.5 import jdk.nashorn.internal.parser.Token; 18.6 import jdk.nashorn.internal.parser.TokenType; 18.7 -import jdk.nashorn.internal.runtime.CodeInstaller; 18.8 import jdk.nashorn.internal.runtime.Context; 18.9 import jdk.nashorn.internal.runtime.JSType; 18.10 import jdk.nashorn.internal.runtime.Source; 18.11 @@ -93,9 +92,6 @@ 18.12 18.13 private final DebugLogger log; 18.14 18.15 - // needed only to get unique eval id 18.16 - private final CodeInstaller<?> installer; 18.17 - 18.18 /** 18.19 * Constructor. 18.20 */ 18.21 @@ -143,7 +139,6 @@ 18.22 } 18.23 }); 18.24 18.25 - this.installer = compiler.getCodeInstaller(); 18.26 this.log = initLogger(compiler.getContext()); 18.27 } 18.28 18.29 @@ -566,16 +561,13 @@ 18.30 private String evalLocation(final IdentNode node) { 18.31 final Source source = lc.getCurrentFunction().getSource(); 18.32 final int pos = node.position(); 18.33 - // Code installer is null when running with --compile-only, use 0 as id in that case 18.34 - final long id = installer == null ? 0 : installer.getUniqueEvalId(); 18.35 return new StringBuilder(). 18.36 append(source.getName()). 18.37 append('#'). 18.38 append(source.getLine(pos)). 18.39 append(':'). 18.40 append(source.getColumn(pos)). 18.41 - append("<eval>@"). 18.42 - append(id). 18.43 + append("<eval>"). 18.44 toString(); 18.45 } 18.46
19.1 --- a/src/jdk/nashorn/internal/codegen/MapCreator.java Thu Sep 11 15:34:13 2014 -0700 19.2 +++ b/src/jdk/nashorn/internal/codegen/MapCreator.java Tue Sep 16 13:59:37 2014 -0700 19.3 @@ -52,8 +52,7 @@ 19.4 * Constructor 19.5 * 19.6 * @param structure structure to generate map for (a JO subclass) 19.7 - * @param keys list of keys for map 19.8 - * @param symbols list of symbols for map 19.9 + * @param tuples list of tuples for map 19.10 */ 19.11 MapCreator(final Class<? extends ScriptObject> structure, final List<MapTuple<T>> tuples) { 19.12 this.structure = structure; 19.13 @@ -149,6 +148,15 @@ 19.14 flags |= Property.IS_FUNCTION_DECLARATION; 19.15 } 19.16 19.17 + if (symbol.isConst()) { 19.18 + flags |= Property.NOT_WRITABLE; 19.19 + } 19.20 + 19.21 + // Mark symbol as needing declaration. Access before declaration will throw a ReferenceError. 19.22 + if (symbol.isBlockScoped() && symbol.isScope()) { 19.23 + flags |= Property.NEEDS_DECLARATION; 19.24 + } 19.25 + 19.26 return flags; 19.27 } 19.28 }
20.1 --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java Thu Sep 11 15:34:13 2014 -0700 20.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java Tue Sep 16 13:59:37 2014 -0700 20.3 @@ -2233,9 +2233,8 @@ 20.4 /** 20.5 * Generate dynamic setter. Pop receiver and property from stack. 20.6 * 20.7 - * @param valueType the type of the value to set 20.8 - * @param name name of property 20.9 - * @param flags call site flags 20.10 + * @param name name of property 20.11 + * @param flags call site flags 20.12 */ 20.13 void dynamicSet(final String name, final int flags) { 20.14 assert !isOptimistic(flags); 20.15 @@ -2462,7 +2461,6 @@ 20.16 * Register line number at a label 20.17 * 20.18 * @param line line number 20.19 - * @param label label 20.20 */ 20.21 void lineNumber(final int line) { 20.22 if (context.getEnv()._debug_lines) {
21.1 --- a/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Thu Sep 11 15:34:13 2014 -0700 21.2 +++ b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Tue Sep 16 13:59:37 2014 -0700 21.3 @@ -308,7 +308,7 @@ 21.4 newEmptyInit(className, classEmitter); 21.5 newAllocate(className, classEmitter); 21.6 21.7 - return toByteArray(classEmitter); 21.8 + return toByteArray(className, classEmitter); 21.9 } 21.10 21.11 /** 21.12 @@ -341,7 +341,7 @@ 21.13 initWithArguments.returnVoid(); 21.14 initWithArguments.end(); 21.15 21.16 - return toByteArray(classEmitter); 21.17 + return toByteArray(className, classEmitter); 21.18 } 21.19 21.20 /** 21.21 @@ -484,15 +484,13 @@ 21.22 * @param classEmitter Open class emitter. 21.23 * @return Byte codes for the class. 21.24 */ 21.25 - private byte[] toByteArray(final ClassEmitter classEmitter) { 21.26 + private byte[] toByteArray(final String className, final ClassEmitter classEmitter) { 21.27 classEmitter.end(); 21.28 21.29 final byte[] code = classEmitter.toByteArray(); 21.30 final ScriptEnvironment env = context.getEnv(); 21.31 21.32 - if (env._print_code && env._print_code_dir == null) { 21.33 - env.getErr().println(ClassEmitter.disassemble(code)); 21.34 - } 21.35 + DumpBytecode.dumpBytecode(env, log, code, className); 21.36 21.37 if (env._verify_code) { 21.38 context.verify(code); 21.39 @@ -827,5 +825,45 @@ 21.40 return MH.findStatic(MethodHandles.lookup(), ObjectClassGenerator.class, name, MH.type(rtype, types)); 21.41 } 21.42 21.43 + /** 21.44 + * Describes the allocator class name and property map for a constructor function with the specified 21.45 + * number of "this" properties that it initializes. 21.46 + * 21.47 + */ 21.48 + public static class AllocatorDescriptor { 21.49 + private final String allocatorClassName; 21.50 + private final PropertyMap allocatorMap; 21.51 21.52 + /** 21.53 + * Creates a new allocator descriptor 21.54 + * @param thisProperties the number of "this" properties that the function initializes 21.55 + */ 21.56 + public AllocatorDescriptor(final int thisProperties) { 21.57 + final int paddedFieldCount = getPaddedFieldCount(thisProperties); 21.58 + this.allocatorClassName = Compiler.binaryName(getClassName(paddedFieldCount)); 21.59 + this.allocatorMap = PropertyMap.newMap(null, allocatorClassName, 0, paddedFieldCount, 0); 21.60 + } 21.61 + 21.62 + /** 21.63 + * Returns the name of the class that the function allocates 21.64 + * @return the name of the class that the function allocates 21.65 + */ 21.66 + public String getAllocatorClassName() { 21.67 + return allocatorClassName; 21.68 + } 21.69 + 21.70 + /** 21.71 + * Returns the allocator map for the function. 21.72 + * @return the allocator map for the function. 21.73 + */ 21.74 + public PropertyMap getAllocatorMap() { 21.75 + return allocatorMap; 21.76 + } 21.77 + 21.78 + @Override 21.79 + public String toString() { 21.80 + return "AllocatorDescriptor[allocatorClassName=" + allocatorClassName + ", allocatorMap.size=" + 21.81 + allocatorMap.size() + "]"; 21.82 + } 21.83 + } 21.84 }
22.1 --- a/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java Thu Sep 11 15:34:13 2014 -0700 22.2 +++ b/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java Tue Sep 16 13:59:37 2014 -0700 22.3 @@ -31,9 +31,11 @@ 22.4 import java.io.File; 22.5 import java.io.FileInputStream; 22.6 import java.io.FileOutputStream; 22.7 +import java.io.IOException; 22.8 import java.io.InputStream; 22.9 import java.net.URL; 22.10 import java.nio.file.Files; 22.11 +import java.nio.file.Path; 22.12 import java.security.AccessController; 22.13 import java.security.MessageDigest; 22.14 import java.security.PrivilegedAction; 22.15 @@ -41,6 +43,14 @@ 22.16 import java.util.Base64; 22.17 import java.util.Date; 22.18 import java.util.Map; 22.19 +import java.util.Timer; 22.20 +import java.util.TimerTask; 22.21 +import java.util.concurrent.TimeUnit; 22.22 +import java.util.concurrent.atomic.AtomicBoolean; 22.23 +import java.util.function.Function; 22.24 +import java.util.function.IntFunction; 22.25 +import java.util.function.Predicate; 22.26 +import java.util.stream.Stream; 22.27 import jdk.nashorn.internal.codegen.types.Type; 22.28 import jdk.nashorn.internal.runtime.Context; 22.29 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; 22.30 @@ -49,30 +59,66 @@ 22.31 import jdk.nashorn.internal.runtime.options.Options; 22.32 22.33 /** 22.34 - * Static utility that encapsulates persistence of decompilation information for functions. Normally, the type info 22.35 - * persistence feature is enabled and operates in an operating-system specific per-user cache directory. You can 22.36 - * override the directory by specifying it in the {@code nashorn.typeInfo.cacheDir} directory. Also, you can disable the 22.37 - * type info persistence altogether by specifying the {@code nashorn.typeInfo.disabled} system property. 22.38 + * Static utility that encapsulates persistence of type information for functions compiled with optimistic 22.39 + * typing. With this feature enabled, when a JavaScript function is recompiled because it gets deoptimized, 22.40 + * the type information for deoptimization is stored in a cache file. If the same function is compiled in a 22.41 + * subsequent JVM invocation, the type information is used for initial compilation, thus allowing the system 22.42 + * to skip a lot of intermediate recompilations and immediately emit a version of the code that has its 22.43 + * optimistic types at (or near) the steady state. 22.44 + * </p><p> 22.45 + * Normally, the type info persistence feature is disabled. When the {@code nashorn.typeInfo.maxFiles} system 22.46 + * property is specified with a value greater than 0, it is enabled and operates in an operating-system 22.47 + * specific per-user cache directory. You can override the directory by specifying it in the 22.48 + * {@code nashorn.typeInfo.cacheDir} directory. The maximum number of files is softly enforced by a task that 22.49 + * cleans up the directory periodically on a separate thread. It is run after some delay after a new file is 22.50 + * added to the cache. The default delay is 20 seconds, and can be set using the 22.51 + * {@code nashorn.typeInfo.cleanupDelaySeconds} system property. You can also specify the word 22.52 + * {@code unlimited} as the value for {@code nashorn.typeInfo.maxFiles} in which case the type info cache is 22.53 + * allowed to grow without limits. 22.54 */ 22.55 public final class OptimisticTypesPersistence { 22.56 + // Default is 0, for disabling the feature when not specified. A reasonable default when enabled is 22.57 + // dependent on the application; setting it to e.g. 20000 is probably good enough for most uses and will 22.58 + // usually cap the cache directory to about 80MB presuming a 4kB filesystem allocation unit. There is one 22.59 + // file per JavaScript function. 22.60 + private static final int DEFAULT_MAX_FILES = 0; 22.61 + // Constants for signifying that the cache should not be limited 22.62 + private static final int UNLIMITED_FILES = -1; 22.63 + // Maximum number of files that should be cached on disk. The maximum will be softly enforced. 22.64 + private static final int MAX_FILES = getMaxFiles(); 22.65 + // Number of seconds to wait between adding a new file to the cache and running a cleanup process 22.66 + private static final int DEFAULT_CLEANUP_DELAY = 20; 22.67 + private static final int CLEANUP_DELAY = Math.max(0, Options.getIntProperty( 22.68 + "nashorn.typeInfo.cleanupDelaySeconds", DEFAULT_CLEANUP_DELAY)); 22.69 // The name of the default subdirectory within the system cache directory where we store type info. 22.70 private static final String DEFAULT_CACHE_SUBDIR_NAME = "com.oracle.java.NashornTypeInfo"; 22.71 // The directory where we cache type info 22.72 - private static final File cacheDir = createCacheDir(); 22.73 + private static final File baseCacheDir = createBaseCacheDir(); 22.74 + private static final File cacheDir = createCacheDir(baseCacheDir); 22.75 // In-process locks to make sure we don't have a cross-thread race condition manipulating any file. 22.76 private static final Object[] locks = cacheDir == null ? null : createLockArray(); 22.77 - 22.78 // Only report one read/write error every minute 22.79 private static final long ERROR_REPORT_THRESHOLD = 60000L; 22.80 22.81 private static volatile long lastReportedError; 22.82 - 22.83 + private static final AtomicBoolean scheduledCleanup; 22.84 + private static final Timer cleanupTimer; 22.85 + static { 22.86 + if (baseCacheDir == null || MAX_FILES == UNLIMITED_FILES) { 22.87 + scheduledCleanup = null; 22.88 + cleanupTimer = null; 22.89 + } else { 22.90 + scheduledCleanup = new AtomicBoolean(); 22.91 + cleanupTimer = new Timer(true); 22.92 + } 22.93 + } 22.94 /** 22.95 - * Retrieves an opaque descriptor for the persistence location for a given function. It should be passed to 22.96 - * {@link #load(Object)} and {@link #store(Object, Map)} methods. 22.97 + * Retrieves an opaque descriptor for the persistence location for a given function. It should be passed 22.98 + * to {@link #load(Object)} and {@link #store(Object, Map)} methods. 22.99 * @param source the source where the function comes from 22.100 * @param functionId the unique ID number of the function within the source 22.101 - * @param paramTypes the types of the function parameters (as persistence is per parameter type specialization). 22.102 + * @param paramTypes the types of the function parameters (as persistence is per parameter type 22.103 + * specialization). 22.104 * @return an opaque descriptor for the persistence location. Can be null if persistence is disabled. 22.105 */ 22.106 public static Object getLocationDescriptor(final Source source, final int functionId, final Type[] paramTypes) { 22.107 @@ -82,7 +128,8 @@ 22.108 final StringBuilder b = new StringBuilder(48); 22.109 // Base64-encode the digest of the source, and append the function id. 22.110 b.append(source.getDigest()).append('-').append(functionId); 22.111 - // Finally, if this is a parameter-type specialized version of the function, add the parameter types to the file name. 22.112 + // Finally, if this is a parameter-type specialized version of the function, add the parameter types 22.113 + // to the file name. 22.114 if(paramTypes != null && paramTypes.length > 0) { 22.115 b.append('-'); 22.116 for(final Type t: paramTypes) { 22.117 @@ -118,6 +165,11 @@ 22.118 @Override 22.119 public Void run() { 22.120 synchronized(getFileLock(file)) { 22.121 + if (!file.exists()) { 22.122 + // If the file already exists, we aren't increasing the number of cached files, so 22.123 + // don't schedule cleanup. 22.124 + scheduleCleanup(); 22.125 + } 22.126 try (final FileOutputStream out = new FileOutputStream(file)) { 22.127 out.getChannel().lock(); // lock exclusive 22.128 final DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(out)); 22.129 @@ -174,19 +226,19 @@ 22.130 } 22.131 } 22.132 22.133 - private static File createCacheDir() { 22.134 - if(Options.getBooleanProperty("nashorn.typeInfo.disabled")) { 22.135 + private static File createBaseCacheDir() { 22.136 + if(MAX_FILES == 0 || Options.getBooleanProperty("nashorn.typeInfo.disabled")) { 22.137 return null; 22.138 } 22.139 try { 22.140 - return createCacheDirPrivileged(); 22.141 + return createBaseCacheDirPrivileged(); 22.142 } catch(final Exception e) { 22.143 getLogger().warning("Failed to create cache dir", e); 22.144 return null; 22.145 } 22.146 } 22.147 22.148 - private static File createCacheDirPrivileged() { 22.149 + private static File createBaseCacheDirPrivileged() { 22.150 return AccessController.doPrivileged(new PrivilegedAction<File>() { 22.151 @Override 22.152 public File run() { 22.153 @@ -195,14 +247,35 @@ 22.154 if(explicitDir != null) { 22.155 dir = new File(explicitDir); 22.156 } else { 22.157 - // When no directory is explicitly specified, get an operating system specific cache directory, 22.158 - // and create "com.oracle.java.NashornTypeInfo" in it. 22.159 + // When no directory is explicitly specified, get an operating system specific cache 22.160 + // directory, and create "com.oracle.java.NashornTypeInfo" in it. 22.161 final File systemCacheDir = getSystemCacheDir(); 22.162 dir = new File(systemCacheDir, DEFAULT_CACHE_SUBDIR_NAME); 22.163 if (isSymbolicLink(dir)) { 22.164 return null; 22.165 } 22.166 } 22.167 + return dir; 22.168 + } 22.169 + }); 22.170 + } 22.171 + 22.172 + private static File createCacheDir(final File baseDir) { 22.173 + if (baseDir == null) { 22.174 + return null; 22.175 + } 22.176 + try { 22.177 + return createCacheDirPrivileged(baseDir); 22.178 + } catch(final Exception e) { 22.179 + getLogger().warning("Failed to create cache dir", e); 22.180 + return null; 22.181 + } 22.182 + } 22.183 + 22.184 + private static File createCacheDirPrivileged(final File baseDir) { 22.185 + return AccessController.doPrivileged(new PrivilegedAction<File>() { 22.186 + @Override 22.187 + public File run() { 22.188 final String versionDirName; 22.189 try { 22.190 versionDirName = getVersionDirName(); 22.191 @@ -210,12 +283,12 @@ 22.192 getLogger().warning("Failed to calculate version dir name", e); 22.193 return null; 22.194 } 22.195 - final File versionDir = new File(dir, versionDirName); 22.196 + final File versionDir = new File(baseDir, versionDirName); 22.197 if (isSymbolicLink(versionDir)) { 22.198 return null; 22.199 } 22.200 versionDir.mkdirs(); 22.201 - if(versionDir.isDirectory()) { 22.202 + if (versionDir.isDirectory()) { 22.203 getLogger().info("Optimistic type persistence directory is " + versionDir); 22.204 return versionDir; 22.205 } 22.206 @@ -235,12 +308,12 @@ 22.207 // Mac OS X stores caches in ~/Library/Caches 22.208 return new File(new File(System.getProperty("user.home"), "Library"), "Caches"); 22.209 } else if(os.startsWith("Windows")) { 22.210 - // On Windows, temp directory is the best approximation of a cache directory, as its contents persist across 22.211 - // reboots and various cleanup utilities know about it. java.io.tmpdir normally points to a user-specific 22.212 - // temp directory, %HOME%\LocalSettings\Temp. 22.213 + // On Windows, temp directory is the best approximation of a cache directory, as its contents 22.214 + // persist across reboots and various cleanup utilities know about it. java.io.tmpdir normally 22.215 + // points to a user-specific temp directory, %HOME%\LocalSettings\Temp. 22.216 return new File(System.getProperty("java.io.tmpdir")); 22.217 } else { 22.218 - // In all other cases we're presumably dealing with a UNIX flavor (Linux, Solaris, etc.); "~/.cache" 22.219 + // In other cases we're presumably dealing with a UNIX flavor (Linux, Solaris, etc.); "~/.cache" 22.220 return new File(System.getProperty("user.home"), ".cache"); 22.221 } 22.222 } 22.223 @@ -278,7 +351,8 @@ 22.224 final int packageNameLen = className.lastIndexOf('.'); 22.225 final String dirStr = fileStr.substring(0, fileStr.length() - packageNameLen - 1); 22.226 final File dir = new File(dirStr); 22.227 - return "dev-" + new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(getLastModifiedClassFile(dir, 0L))); 22.228 + return "dev-" + new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(getLastModifiedClassFile( 22.229 + dir, 0L))); 22.230 } else { 22.231 throw new AssertionError(); 22.232 } 22.233 @@ -335,4 +409,108 @@ 22.234 return DebugLogger.DISABLED_LOGGER; 22.235 } 22.236 } 22.237 + 22.238 + private static void scheduleCleanup() { 22.239 + if (MAX_FILES != UNLIMITED_FILES && scheduledCleanup.compareAndSet(false, true)) { 22.240 + cleanupTimer.schedule(new TimerTask() { 22.241 + @Override 22.242 + public void run() { 22.243 + scheduledCleanup.set(false); 22.244 + try { 22.245 + doCleanup(); 22.246 + } catch (final IOException e) { 22.247 + // Ignore it. While this is unfortunate, we don't have good facility for reporting 22.248 + // this, as we're running in a thread that has no access to Context, so we can't grab 22.249 + // a DebugLogger. 22.250 + } 22.251 + } 22.252 + }, TimeUnit.SECONDS.toMillis(CLEANUP_DELAY)); 22.253 + } 22.254 + } 22.255 + 22.256 + private static void doCleanup() throws IOException { 22.257 + final long start = System.nanoTime(); 22.258 + final Path[] files = getAllRegularFilesInLastModifiedOrder(); 22.259 + final int nFiles = files.length; 22.260 + final int filesToDelete = Math.max(0, nFiles - MAX_FILES); 22.261 + int filesDeleted = 0; 22.262 + for (int i = 0; i < nFiles && filesDeleted < filesToDelete; ++i) { 22.263 + try { 22.264 + Files.deleteIfExists(files[i]); 22.265 + // Even if it didn't exist, we increment filesDeleted; it existed a moment earlier; something 22.266 + // else deleted it for us; that's okay with us. 22.267 + filesDeleted++; 22.268 + } catch (final Exception e) { 22.269 + // does not increase filesDeleted 22.270 + } 22.271 + files[i] = null; // gc eligible 22.272 + }; 22.273 + final long duration = System.nanoTime() - start; 22.274 + } 22.275 + 22.276 + private static Path[] getAllRegularFilesInLastModifiedOrder() throws IOException { 22.277 + try (final Stream<Path> filesStream = Files.walk(baseCacheDir.toPath())) { 22.278 + // TODO: rewrite below once we can use JDK8 syntactic constructs 22.279 + return filesStream 22.280 + .filter(new Predicate<Path>() { 22.281 + @Override 22.282 + public boolean test(final Path path) { 22.283 + return !Files.isDirectory(path); 22.284 + }; 22.285 + }) 22.286 + .map(new Function<Path, PathAndTime>() { 22.287 + @Override 22.288 + public PathAndTime apply(final Path path) { 22.289 + return new PathAndTime(path); 22.290 + } 22.291 + }) 22.292 + .sorted() 22.293 + .map(new Function<PathAndTime, Path>() { 22.294 + @Override 22.295 + public Path apply(final PathAndTime pathAndTime) { 22.296 + return pathAndTime.path; 22.297 + } 22.298 + }) 22.299 + .toArray(new IntFunction<Path[]>() { // Replace with Path::new 22.300 + @Override 22.301 + public Path[] apply(final int length) { 22.302 + return new Path[length]; 22.303 + } 22.304 + }); 22.305 + } 22.306 + } 22.307 + 22.308 + private static class PathAndTime implements Comparable<PathAndTime> { 22.309 + private final Path path; 22.310 + private final long time; 22.311 + 22.312 + PathAndTime(final Path path) { 22.313 + this.path = path; 22.314 + this.time = getTime(path); 22.315 + } 22.316 + 22.317 + @Override 22.318 + public int compareTo(final PathAndTime other) { 22.319 + return Long.compare(time, other.time); 22.320 + } 22.321 + 22.322 + private static long getTime(final Path path) { 22.323 + try { 22.324 + return Files.getLastModifiedTime(path).toMillis(); 22.325 + } catch (IOException e) { 22.326 + // All files for which we can't retrieve the last modified date will be considered oldest. 22.327 + return -1L; 22.328 + } 22.329 + } 22.330 + } 22.331 + 22.332 + private static int getMaxFiles() { 22.333 + final String str = Options.getStringProperty("nashorn.typeInfo.maxFiles", null); 22.334 + if (str == null) { 22.335 + return DEFAULT_MAX_FILES; 22.336 + } else if ("unlimited".equals(str)) { 22.337 + return UNLIMITED_FILES; 22.338 + } 22.339 + return Math.max(0, Integer.parseInt(str)); 22.340 + } 22.341 }
23.1 --- a/src/jdk/nashorn/internal/codegen/TypeEvaluator.java Thu Sep 11 15:34:13 2014 -0700 23.2 +++ b/src/jdk/nashorn/internal/codegen/TypeEvaluator.java Tue Sep 16 13:59:37 2014 -0700 23.3 @@ -55,6 +55,19 @@ 23.4 this.runtimeScope = runtimeScope; 23.5 } 23.6 23.7 + /** 23.8 + * Returns true if the expression can be safely evaluated, and its value is an object known to always use 23.9 + * String as the type of its property names retrieved through 23.10 + * {@link ScriptRuntime#toPropertyIterator(Object)}. It is used to avoid optimistic assumptions about its 23.11 + * property name types. 23.12 + * @param expr the expression to test 23.13 + * @return true if the expression can be safely evaluated, and its value is an object known to always use 23.14 + * String as the type of its property iterators. 23.15 + */ 23.16 + boolean hasStringPropertyIterator(final Expression expr) { 23.17 + return evaluateSafely(expr) instanceof ScriptObject; 23.18 + } 23.19 + 23.20 Type getOptimisticType(final Optimistic node) { 23.21 assert compiler.useOptimisticTypes(); 23.22 23.23 @@ -108,7 +121,7 @@ 23.24 23.25 // Safely evaluate the property, and return the narrowest type for the actual value (e.g. Type.INT for a boxed 23.26 // integer). 23.27 - final Object value = property.getObjectValue(owner, owner); 23.28 + final Object value = property.needsDeclaration() ? ScriptRuntime.UNDEFINED : property.getObjectValue(owner, owner); 23.29 if (value == ScriptRuntime.UNDEFINED) { 23.30 return null; 23.31 }
24.1 --- a/src/jdk/nashorn/internal/codegen/types/Type.java Thu Sep 11 15:34:13 2014 -0700 24.2 +++ b/src/jdk/nashorn/internal/codegen/types/Type.java Tue Sep 16 13:59:37 2014 -0700 24.3 @@ -333,7 +333,7 @@ 24.4 */ 24.5 public static Map<Integer, Type> readTypeMap(final DataInput input) throws IOException { 24.6 final int size = input.readInt(); 24.7 - if (size == 0) { 24.8 + if (size <= 0) { 24.9 return null; 24.10 } 24.11 final Map<Integer, Type> map = new TreeMap<>(); 24.12 @@ -345,7 +345,7 @@ 24.13 case 'L': type = Type.OBJECT; break; 24.14 case 'D': type = Type.NUMBER; break; 24.15 case 'J': type = Type.LONG; break; 24.16 - default: throw new AssertionError(); 24.17 + default: continue; 24.18 } 24.19 map.put(pp, type); 24.20 }
25.1 --- a/src/jdk/nashorn/internal/ir/Block.java Thu Sep 11 15:34:13 2014 -0700 25.2 +++ b/src/jdk/nashorn/internal/ir/Block.java Tue Sep 16 13:59:37 2014 -0700 25.3 @@ -277,6 +277,14 @@ 25.4 } 25.5 25.6 /** 25.7 + * Returns the number of statements in the block. 25.8 + * @return the number of statements in the block. 25.9 + */ 25.10 + public int getStatementCount() { 25.11 + return statements.size(); 25.12 + } 25.13 + 25.14 + /** 25.15 * Returns the line number of the first statement in the block. 25.16 * @return the line number of the first statement in the block, or -1 if the block has no statements. 25.17 */
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/src/jdk/nashorn/internal/ir/CompileUnitHolder.java Tue Sep 16 13:59:37 2014 -0700 26.3 @@ -0,0 +1,40 @@ 26.4 +/* 26.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 26.7 + * 26.8 + * This code is free software; you can redistribute it and/or modify it 26.9 + * under the terms of the GNU General Public License version 2 only, as 26.10 + * published by the Free Software Foundation. Oracle designates this 26.11 + * particular file as subject to the "Classpath" exception as provided 26.12 + * by Oracle in the LICENSE file that accompanied this code. 26.13 + * 26.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 26.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 26.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 26.17 + * version 2 for more details (a copy is included in the LICENSE file that 26.18 + * accompanied this code). 26.19 + * 26.20 + * You should have received a copy of the GNU General Public License version 26.21 + * 2 along with this work; if not, write to the Free Software Foundation, 26.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 26.23 + * 26.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 26.25 + * or visit www.oracle.com if you need additional information or have any 26.26 + * questions. 26.27 + */ 26.28 + 26.29 +package jdk.nashorn.internal.ir; 26.30 + 26.31 +import jdk.nashorn.internal.codegen.CompileUnit; 26.32 + 26.33 +/** 26.34 + * Marker interface for things in the IR that can hold compile units. 26.35 + * {@link CompileUnit} 26.36 + */ 26.37 +public interface CompileUnitHolder { 26.38 + /** 26.39 + * Return the compile unit held by this instance 26.40 + * @return compile unit 26.41 + */ 26.42 + public CompileUnit getCompileUnit(); 26.43 +}
27.1 --- a/src/jdk/nashorn/internal/ir/FunctionNode.java Thu Sep 11 15:34:13 2014 -0700 27.2 +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java Tue Sep 16 13:59:37 2014 -0700 27.3 @@ -34,10 +34,8 @@ 27.4 27.5 import java.util.Collections; 27.6 import java.util.EnumSet; 27.7 -import java.util.HashSet; 27.8 import java.util.Iterator; 27.9 import java.util.List; 27.10 -import java.util.Set; 27.11 import java.util.function.Function; 27.12 import jdk.nashorn.internal.AssertsEnabled; 27.13 import jdk.nashorn.internal.codegen.CompileUnit; 27.14 @@ -48,6 +46,7 @@ 27.15 import jdk.nashorn.internal.ir.annotations.Ignore; 27.16 import jdk.nashorn.internal.ir.annotations.Immutable; 27.17 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 27.18 +import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; 27.19 import jdk.nashorn.internal.runtime.ScriptFunction; 27.20 import jdk.nashorn.internal.runtime.Source; 27.21 import jdk.nashorn.internal.runtime.UserAccessorProperty; 27.22 @@ -57,7 +56,7 @@ 27.23 * IR representation for function (or script.) 27.24 */ 27.25 @Immutable 27.26 -public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode> { 27.27 +public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder { 27.28 /** Type used for all FunctionNodes */ 27.29 public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class); 27.30 27.31 @@ -110,8 +109,11 @@ 27.32 /** Source of entity. */ 27.33 private final Source source; 27.34 27.35 - /** Unique ID used for recompilation among other things */ 27.36 - private final int id; 27.37 + /** 27.38 + * Opaque object representing parser state at the end of the function. Used when reparsing outer functions 27.39 + * to skip parsing inner functions. 27.40 + */ 27.41 + private final Object endParserState; 27.42 27.43 /** External function identifier. */ 27.44 @Ignore 27.45 @@ -138,10 +140,6 @@ 27.46 /** Last token of function. **/ 27.47 private final long lastToken; 27.48 27.49 - /** Declared symbols in this function node */ 27.50 - @Ignore 27.51 - private final Set<Symbol> declaredSymbols; 27.52 - 27.53 /** Method's namespace. */ 27.54 private final Namespace namespace; 27.55 27.56 @@ -260,6 +258,14 @@ 27.57 /** trace callsite values in this function? */ 27.58 public static final int IS_TRACE_VALUES = 1 << 26; 27.59 27.60 + /** 27.61 + * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a 27.62 + * parameter on invocation. Note that we aren't, in fact using this flag in function nodes. 27.63 + * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData} 27.64 + * will, however, cache the value of this flag. 27.65 + */ 27.66 + public static final int NEEDS_CALLEE = 1 << 27; 27.67 + 27.68 /** extension callsite flags mask */ 27.69 public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE | 27.70 IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST | 27.71 @@ -275,16 +281,9 @@ 27.72 /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */ 27.73 private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL; 27.74 27.75 - /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval. 27.76 - * We also pessimistically need a parent scope if we have lazy children that have not yet been compiled */ 27.77 + /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval. */ 27.78 private static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL; 27.79 27.80 - /** Used to signify "null", e.g. if someone asks for the parent of the program node */ 27.81 - public static final int NO_FUNCTION_ID = 0; 27.82 - 27.83 - /** Where to start assigning global and unique function node ids */ 27.84 - public static final int FIRST_FUNCTION_ID = NO_FUNCTION_ID + 1; 27.85 - 27.86 /** What is the return type of this function? */ 27.87 private Type returnType = Type.UNKNOWN; 27.88 27.89 @@ -292,11 +291,10 @@ 27.90 * Constructor 27.91 * 27.92 * @param source the source 27.93 - * @param id unique id 27.94 * @param lineNumber line number 27.95 * @param token token 27.96 * @param finish finish 27.97 - * @param firstToken first token of the funtion node (including the function declaration) 27.98 + * @param firstToken first token of the function node (including the function declaration) 27.99 * @param namespace the namespace 27.100 * @param ident the identifier 27.101 * @param name the name of the function 27.102 @@ -306,7 +304,6 @@ 27.103 */ 27.104 public FunctionNode( 27.105 final Source source, 27.106 - final int id, 27.107 final int lineNumber, 27.108 final long token, 27.109 final int finish, 27.110 @@ -320,7 +317,6 @@ 27.111 super(token, finish); 27.112 27.113 this.source = source; 27.114 - this.id = id; 27.115 this.lineNumber = lineNumber; 27.116 this.ident = ident; 27.117 this.name = name; 27.118 @@ -330,17 +326,18 @@ 27.119 this.lastToken = token; 27.120 this.namespace = namespace; 27.121 this.compilationState = EnumSet.of(CompilationState.INITIALIZED); 27.122 - this.declaredSymbols = new HashSet<>(); 27.123 this.flags = flags; 27.124 this.compileUnit = null; 27.125 this.body = null; 27.126 this.thisProperties = 0; 27.127 this.rootClass = null; 27.128 + this.endParserState = null; 27.129 } 27.130 27.131 private FunctionNode( 27.132 final FunctionNode functionNode, 27.133 final long lastToken, 27.134 + Object endParserState, 27.135 final int flags, 27.136 final String name, 27.137 final Type returnType, 27.138 @@ -352,6 +349,7 @@ 27.139 final Class<?> rootClass) { 27.140 super(functionNode); 27.141 27.142 + this.endParserState = endParserState; 27.143 this.lineNumber = functionNode.lineNumber; 27.144 this.flags = flags; 27.145 this.name = name; 27.146 @@ -366,10 +364,8 @@ 27.147 27.148 // the fields below never change - they are final and assigned in constructor 27.149 this.source = functionNode.source; 27.150 - this.id = functionNode.id; 27.151 this.ident = functionNode.ident; 27.152 this.namespace = functionNode.namespace; 27.153 - this.declaredSymbols = functionNode.declaredSymbols; 27.154 this.kind = functionNode.kind; 27.155 this.firstToken = functionNode.firstToken; 27.156 } 27.157 @@ -435,11 +431,11 @@ 27.158 } 27.159 27.160 /** 27.161 - * Get the unique ID for this function 27.162 + * Get the unique ID for this function within the script file. 27.163 * @return the id 27.164 */ 27.165 public int getId() { 27.166 - return id; 27.167 + return position(); 27.168 } 27.169 27.170 /** 27.171 @@ -541,6 +537,7 @@ 27.172 new FunctionNode( 27.173 this, 27.174 lastToken, 27.175 + endParserState, 27.176 flags, 27.177 name, 27.178 returnType, 27.179 @@ -612,6 +609,7 @@ 27.180 new FunctionNode( 27.181 this, 27.182 lastToken, 27.183 + endParserState, 27.184 flags, 27.185 name, 27.186 returnType, 27.187 @@ -650,15 +648,24 @@ 27.188 } 27.189 27.190 /** 27.191 - * Check if the {@code eval} keyword is used in this function 27.192 + * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}). 27.193 * 27.194 - * @return true if {@code eval} is used 27.195 + * @return true if {@code eval} is called. 27.196 */ 27.197 public boolean hasEval() { 27.198 return getFlag(HAS_EVAL); 27.199 } 27.200 27.201 /** 27.202 + * Returns true if a function nested (directly or transitively) within this function {@link #hasEval()}. 27.203 + * 27.204 + * @return true if a nested function calls {@code eval}. 27.205 + */ 27.206 + public boolean hasNestedEval() { 27.207 + return getFlag(HAS_NESTED_EVAL); 27.208 + } 27.209 + 27.210 + /** 27.211 * Get the first token for this function 27.212 * @return the first token 27.213 */ 27.214 @@ -724,24 +731,6 @@ 27.215 } 27.216 27.217 /** 27.218 - * Return a set of symbols declared in this function node. This 27.219 - * is only relevant after Attr, otherwise it will be an empty 27.220 - * set as no symbols have been introduced 27.221 - * @return set of declared symbols in function 27.222 - */ 27.223 - public Set<Symbol> getDeclaredSymbols() { 27.224 - return Collections.unmodifiableSet(declaredSymbols); 27.225 - } 27.226 - 27.227 - /** 27.228 - * Add a declared symbol to this function node 27.229 - * @param symbol symbol that is declared 27.230 - */ 27.231 - public void addDeclaredSymbol(final Symbol symbol) { 27.232 - declaredSymbols.add(symbol); 27.233 - } 27.234 - 27.235 - /** 27.236 * Get the function body 27.237 * @return the function body 27.238 */ 27.239 @@ -765,6 +754,7 @@ 27.240 new FunctionNode( 27.241 this, 27.242 lastToken, 27.243 + endParserState, 27.244 flags | 27.245 (body.needsScope() ? 27.246 FunctionNode.HAS_SCOPE_BLOCK : 27.247 @@ -863,6 +853,7 @@ 27.248 new FunctionNode( 27.249 this, 27.250 lastToken, 27.251 + endParserState, 27.252 flags, 27.253 name, 27.254 returnType, 27.255 @@ -923,6 +914,7 @@ 27.256 new FunctionNode( 27.257 this, 27.258 lastToken, 27.259 + endParserState, 27.260 flags, 27.261 name, 27.262 returnType, 27.263 @@ -935,6 +927,41 @@ 27.264 } 27.265 27.266 /** 27.267 + * Returns the end parser state for this function. 27.268 + * @return the end parser state for this function. 27.269 + */ 27.270 + public Object getEndParserState() { 27.271 + return endParserState; 27.272 + } 27.273 + 27.274 + /** 27.275 + * Set the end parser state for this function. 27.276 + * @param lc lexical context 27.277 + * @param endParserState the parser state to set 27.278 + * @return function node or a new one if state was changed 27.279 + */ 27.280 + public FunctionNode setEndParserState(final LexicalContext lc, final Object endParserState) { 27.281 + if (this.endParserState == endParserState) { 27.282 + return this; 27.283 + } 27.284 + return Node.replaceInLexicalContext( 27.285 + lc, 27.286 + this, 27.287 + new FunctionNode( 27.288 + this, 27.289 + lastToken, 27.290 + endParserState, 27.291 + flags, 27.292 + name, 27.293 + returnType, 27.294 + compileUnit, 27.295 + compilationState, 27.296 + body, 27.297 + parameters, 27.298 + thisProperties, rootClass)); 27.299 + } 27.300 + 27.301 + /** 27.302 * Get the name of this function 27.303 * @return the name 27.304 */ 27.305 @@ -958,6 +985,7 @@ 27.306 new FunctionNode( 27.307 this, 27.308 lastToken, 27.309 + endParserState, 27.310 flags, 27.311 name, 27.312 returnType, 27.313 @@ -970,13 +998,13 @@ 27.314 } 27.315 27.316 /** 27.317 - * Check if this function should have all its variables in its own scope. Scripts, split sub-functions, and 27.318 + * Check if this function should have all its variables in its own scope. Split sub-functions, and 27.319 * functions having with and/or eval blocks are such. 27.320 * 27.321 * @return true if all variables should be in scope 27.322 */ 27.323 public boolean allVarsInScope() { 27.324 - return isProgram() || getFlag(HAS_ALL_VARS_IN_SCOPE); 27.325 + return getFlag(HAS_ALL_VARS_IN_SCOPE); 27.326 } 27.327 27.328 /** 27.329 @@ -1023,6 +1051,7 @@ 27.330 new FunctionNode( 27.331 this, 27.332 lastToken, 27.333 + endParserState, 27.334 flags, 27.335 name, 27.336 returnType, 27.337 @@ -1101,6 +1130,7 @@ 27.338 new FunctionNode( 27.339 this, 27.340 lastToken, 27.341 + endParserState, 27.342 flags, 27.343 name, 27.344 type, 27.345 @@ -1126,6 +1156,7 @@ 27.346 * @see Compiler 27.347 * @return the compile unit 27.348 */ 27.349 + @Override 27.350 public CompileUnit getCompileUnit() { 27.351 return compileUnit; 27.352 } 27.353 @@ -1147,6 +1178,7 @@ 27.354 new FunctionNode( 27.355 this, 27.356 lastToken, 27.357 + endParserState, 27.358 flags, 27.359 name, 27.360 returnType, 27.361 @@ -1202,6 +1234,7 @@ 27.362 new FunctionNode( 27.363 this, 27.364 lastToken, 27.365 + endParserState, 27.366 flags, 27.367 name, 27.368 returnType,
28.1 --- a/src/jdk/nashorn/internal/ir/IdentNode.java Thu Sep 11 15:34:13 2014 -0700 28.2 +++ b/src/jdk/nashorn/internal/ir/IdentNode.java Tue Sep 16 13:59:37 2014 -0700 28.3 @@ -46,6 +46,8 @@ 28.4 private static final int INITIALIZED_HERE = 1 << 1; 28.5 private static final int FUNCTION = 1 << 2; 28.6 private static final int FUTURESTRICT_NAME = 1 << 3; 28.7 + private static final int IS_DECLARED_HERE = 1 << 4; 28.8 + private static final int IS_DEAD = 1 << 5; 28.9 28.10 /** Identifier. */ 28.11 private final String name; 28.12 @@ -247,6 +249,45 @@ 28.13 } 28.14 28.15 /** 28.16 + * Is this a LET or CONST identifier used before its declaration? 28.17 + * 28.18 + * @return true if identifier is dead 28.19 + */ 28.20 + public boolean isDead() { 28.21 + return (flags & IS_DEAD) != 0; 28.22 + } 28.23 + 28.24 + /** 28.25 + * Flag this IdentNode as a LET or CONST identifier used before its declaration. 28.26 + * 28.27 + * @return a new IdentNode equivalent to this but marked as dead. 28.28 + */ 28.29 + public IdentNode markDead() { 28.30 + return new IdentNode(this, name, type, flags | IS_DEAD, programPoint, conversion); 28.31 + } 28.32 + 28.33 + /** 28.34 + * Is this IdentNode declared here? 28.35 + * 28.36 + * @return true if identifier is declared here 28.37 + */ 28.38 + public boolean isDeclaredHere() { 28.39 + return (flags & IS_DECLARED_HERE) != 0; 28.40 + } 28.41 + 28.42 + /** 28.43 + * Flag this IdentNode as being declared here. 28.44 + * 28.45 + * @return a new IdentNode equivalent to this but marked as declared here. 28.46 + */ 28.47 + public IdentNode setIsDeclaredHere() { 28.48 + if (isDeclaredHere()) { 28.49 + return this; 28.50 + } 28.51 + return new IdentNode(this, name, type, flags | IS_DECLARED_HERE, programPoint, conversion); 28.52 + } 28.53 + 28.54 + /** 28.55 * Check if the name of this IdentNode is same as that of a compile-time property (currently __DIR__, __FILE__, and 28.56 * __LINE__). 28.57 *
29.1 --- a/src/jdk/nashorn/internal/ir/LexicalContext.java Thu Sep 11 15:34:13 2014 -0700 29.2 +++ b/src/jdk/nashorn/internal/ir/LexicalContext.java Tue Sep 16 13:59:37 2014 -0700 29.3 @@ -351,8 +351,7 @@ 29.4 } 29.5 29.6 /** 29.7 - * Get the function for this block. If the block is itself a function 29.8 - * this returns identity 29.9 + * Get the function for this block. 29.10 * @param block block for which to get function 29.11 * @return function for block 29.12 */
30.1 --- a/src/jdk/nashorn/internal/ir/LiteralNode.java Thu Sep 11 15:34:13 2014 -0700 30.2 +++ b/src/jdk/nashorn/internal/ir/LiteralNode.java Tue Sep 16 13:59:37 2014 -0700 30.3 @@ -603,7 +603,7 @@ 30.4 * An ArrayUnit is a range in an ArrayLiteral. ArrayLiterals can 30.5 * be split if they are too large, for bytecode generation reasons 30.6 */ 30.7 - public static final class ArrayUnit { 30.8 + public static final class ArrayUnit implements CompileUnitHolder { 30.9 /** Compile unit associated with the postsets range. */ 30.10 private final CompileUnit compileUnit; 30.11 30.12 @@ -642,6 +642,7 @@ 30.13 * The array compile unit 30.14 * @return array compile unit 30.15 */ 30.16 + @Override 30.17 public CompileUnit getCompileUnit() { 30.18 return compileUnit; 30.19 }
31.1 --- a/src/jdk/nashorn/internal/ir/SplitNode.java Thu Sep 11 15:34:13 2014 -0700 31.2 +++ b/src/jdk/nashorn/internal/ir/SplitNode.java Tue Sep 16 13:59:37 2014 -0700 31.3 @@ -39,7 +39,7 @@ 31.4 * Node indicating code is split across classes. 31.5 */ 31.6 @Immutable 31.7 -public class SplitNode extends LexicalContextStatement implements Labels { 31.8 +public class SplitNode extends LexicalContextStatement implements Labels, CompileUnitHolder { 31.9 /** Split node method name. */ 31.10 private final String name; 31.11 31.12 @@ -116,6 +116,7 @@ 31.13 * Get the compile unit for this split node 31.14 * @return compile unit 31.15 */ 31.16 + @Override 31.17 public CompileUnit getCompileUnit() { 31.18 return compileUnit; 31.19 }
32.1 --- a/src/jdk/nashorn/internal/ir/Symbol.java Thu Sep 11 15:34:13 2014 -0700 32.2 +++ b/src/jdk/nashorn/internal/ir/Symbol.java Tue Sep 16 13:59:37 2014 -0700 32.3 @@ -54,17 +54,17 @@ 32.4 public static final int IS_VAR = 2; 32.5 /** Is this a parameter */ 32.6 public static final int IS_PARAM = 3; 32.7 - /** Is this a constant */ 32.8 - public static final int IS_CONSTANT = 4; 32.9 /** Mask for kind flags */ 32.10 - public static final int KINDMASK = (1 << 3) - 1; // Kinds are represented by lower three bits 32.11 + public static final int KINDMASK = (1 << 2) - 1; // Kinds are represented by lower two bits 32.12 32.13 /** Is this symbol in scope */ 32.14 - public static final int IS_SCOPE = 1 << 3; 32.15 + public static final int IS_SCOPE = 1 << 2; 32.16 /** Is this a this symbol */ 32.17 - public static final int IS_THIS = 1 << 4; 32.18 + public static final int IS_THIS = 1 << 3; 32.19 /** Is this a let */ 32.20 - public static final int IS_LET = 1 << 5; 32.21 + public static final int IS_LET = 1 << 4; 32.22 + /** Is this a const */ 32.23 + public static final int IS_CONST = 1 << 5; 32.24 /** Is this an internal symbol, never represented explicitly in source code */ 32.25 public static final int IS_INTERNAL = 1 << 6; 32.26 /** Is this a function self-reference symbol */ 32.27 @@ -83,6 +83,8 @@ 32.28 public static final int HAS_DOUBLE_VALUE = 1 << 13; 32.29 /** Is this symbol known to store an object value ? */ 32.30 public static final int HAS_OBJECT_VALUE = 1 << 14; 32.31 + /** Is this symbol seen a declaration? Used for block scoped LET and CONST symbols only. */ 32.32 + public static final int HAS_BEEN_DECLARED = 1 << 15; 32.33 32.34 /** Null or name identifying symbol. */ 32.35 private final String name; 32.36 @@ -184,14 +186,17 @@ 32.37 sb.append(" global"); 32.38 break; 32.39 case IS_VAR: 32.40 - sb.append(" var"); 32.41 + if (isConst()) { 32.42 + sb.append(" const"); 32.43 + } else if (isLet()) { 32.44 + sb.append(" let"); 32.45 + } else { 32.46 + sb.append(" var"); 32.47 + } 32.48 break; 32.49 case IS_PARAM: 32.50 sb.append(" param"); 32.51 break; 32.52 - case IS_CONSTANT: 32.53 - sb.append(" const"); 32.54 - break; 32.55 default: 32.56 break; 32.57 } 32.58 @@ -204,10 +209,6 @@ 32.59 sb.append(" internal"); 32.60 } 32.61 32.62 - if (isLet()) { 32.63 - sb.append(" let"); 32.64 - } 32.65 - 32.66 if (isThis()) { 32.67 sb.append(" this"); 32.68 } 32.69 @@ -410,8 +411,8 @@ 32.70 * Check if this symbol is a constant 32.71 * @return true if a constant 32.72 */ 32.73 - public boolean isConstant() { 32.74 - return (flags & KINDMASK) == IS_CONSTANT; 32.75 + public boolean isConst() { 32.76 + return (flags & IS_CONST) != 0; 32.77 } 32.78 32.79 /** 32.80 @@ -440,15 +441,6 @@ 32.81 } 32.82 32.83 /** 32.84 - * Flag this symbol as a let 32.85 - */ 32.86 - public void setIsLet() { 32.87 - if (!isLet()) { 32.88 - flags |= IS_LET; 32.89 - } 32.90 - } 32.91 - 32.92 - /** 32.93 * Flag this symbol as a function's self-referencing symbol. 32.94 * @return true if this symbol as a function's self-referencing symbol. 32.95 */ 32.96 @@ -456,6 +448,20 @@ 32.97 return (flags & IS_FUNCTION_SELF) != 0; 32.98 } 32.99 32.100 + public boolean isBlockScoped() { 32.101 + return isLet() || isConst(); 32.102 + } 32.103 + 32.104 + public boolean hasBeenDeclared() { 32.105 + return (flags & HAS_BEEN_DECLARED) != 0; 32.106 + } 32.107 + 32.108 + public void setHasBeenDeclared() { 32.109 + if (!hasBeenDeclared()) { 32.110 + flags |= HAS_BEEN_DECLARED; 32.111 + } 32.112 + } 32.113 + 32.114 /** 32.115 * Get the index of the field used to store this symbol, should it be an AccessorProperty 32.116 * and get allocated in a JO-prefixed ScriptObject subclass.
33.1 --- a/src/jdk/nashorn/internal/ir/VarNode.java Thu Sep 11 15:34:13 2014 -0700 33.2 +++ b/src/jdk/nashorn/internal/ir/VarNode.java Tue Sep 16 13:59:37 2014 -0700 33.3 @@ -27,6 +27,7 @@ 33.4 33.5 import jdk.nashorn.internal.ir.annotations.Immutable; 33.6 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 33.7 +import jdk.nashorn.internal.parser.Token; 33.8 33.9 /** 33.10 * Node represents a var/let declaration. 33.11 @@ -43,12 +44,18 @@ 33.12 private final int flags; 33.13 33.14 /** Flag that determines if this function node is a statement */ 33.15 - public static final int IS_STATEMENT = 1 << 0; 33.16 + public static final int IS_STATEMENT = 1 << 0; 33.17 + 33.18 + /** Flag for ES6 LET declaration */ 33.19 + public static final int IS_LET = 1 << 1; 33.20 + 33.21 + /** Flag for ES6 CONST declaration */ 33.22 + public static final int IS_CONST = 1 << 2; 33.23 33.24 /** Flag that determines if this is the last function declaration in a function 33.25 * This is used to micro optimize the placement of return value assignments for 33.26 * a program node */ 33.27 - public static final int IS_LAST_FUNCTION_DECLARATION = 1 << 1; 33.28 + public static final int IS_LAST_FUNCTION_DECLARATION = 1 << 3; 33.29 33.30 /** 33.31 * Constructor 33.32 @@ -109,6 +116,43 @@ 33.33 } 33.34 33.35 /** 33.36 + * Is this a VAR node block scoped? This returns true for ECMAScript 6 LET and CONST nodes. 33.37 + * @return true if an ES6 LET or CONST node 33.38 + */ 33.39 + public boolean isBlockScoped() { 33.40 + return getFlag(IS_LET) || getFlag(IS_CONST); 33.41 + } 33.42 + 33.43 + /** 33.44 + * Is this an ECMAScript 6 LET node? 33.45 + * @return true if LET node 33.46 + */ 33.47 + public boolean isLet() { 33.48 + return getFlag(IS_LET); 33.49 + } 33.50 + 33.51 + /** 33.52 + * Is this an ECMAScript 6 CONST node? 33.53 + * @return true if CONST node 33.54 + */ 33.55 + public boolean isConst() { 33.56 + return getFlag(IS_CONST); 33.57 + } 33.58 + 33.59 + /** 33.60 + * Return the flags to use for symbols for this declaration. 33.61 + * @return the symbol flags 33.62 + */ 33.63 + public int getSymbolFlags() { 33.64 + if (isLet()) { 33.65 + return Symbol.IS_VAR | Symbol.IS_LET; 33.66 + } else if (isConst()) { 33.67 + return Symbol.IS_VAR | Symbol.IS_CONST; 33.68 + } 33.69 + return Symbol.IS_VAR; 33.70 + } 33.71 + 33.72 + /** 33.73 * Does this variable declaration have an init value 33.74 * @return true if an init exists, false otherwise 33.75 */ 33.76 @@ -139,7 +183,7 @@ 33.77 33.78 @Override 33.79 public void toString(final StringBuilder sb, final boolean printType) { 33.80 - sb.append("var "); 33.81 + sb.append(Token.descType(getToken()).getName()).append(' '); 33.82 name.toString(sb, printType); 33.83 33.84 if (init != null) {
34.1 --- a/src/jdk/nashorn/internal/objects/Global.java Thu Sep 11 15:34:13 2014 -0700 34.2 +++ b/src/jdk/nashorn/internal/objects/Global.java Tue Sep 16 13:59:37 2014 -0700 34.3 @@ -631,6 +631,24 @@ 34.4 } 34.5 34.6 /** 34.7 + * Returns a method handle that creates a wrapper object for a JS primitive value. 34.8 + * 34.9 + * @param self receiver object 34.10 + * @return method handle to create wrapper objects for primitive receiver 34.11 + */ 34.12 + public static MethodHandle getPrimitiveWrapFilter(final Object self) { 34.13 + if (self instanceof String || self instanceof ConsString) { 34.14 + return NativeString.WRAPFILTER; 34.15 + } else if (self instanceof Number) { 34.16 + return NativeNumber.WRAPFILTER; 34.17 + } else if (self instanceof Boolean) { 34.18 + return NativeBoolean.WRAPFILTER; 34.19 + } 34.20 + throw new IllegalArgumentException("Unsupported primitive: " + self); 34.21 + } 34.22 + 34.23 + 34.24 + /** 34.25 * Create a new empty script object 34.26 * 34.27 * @return the new ScriptObject
35.1 --- a/src/jdk/nashorn/internal/objects/NativeBoolean.java Thu Sep 11 15:34:13 2014 -0700 35.2 +++ b/src/jdk/nashorn/internal/objects/NativeBoolean.java Tue Sep 16 13:59:37 2014 -0700 35.3 @@ -51,9 +51,9 @@ 35.4 public final class NativeBoolean extends ScriptObject { 35.5 private final boolean value; 35.6 35.7 - // Method handle to create an object wrapper for a primitive boolean 35.8 - private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeBoolean.class, Object.class)); 35.9 - // Method handle to retrieve the Boolean prototype object 35.10 + /** Method handle to create an object wrapper for a primitive boolean. */ 35.11 + static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeBoolean.class, Object.class)); 35.12 + /** Method handle to retrieve the Boolean prototype object. */ 35.13 private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class)); 35.14 35.15 // initialized by nasgen
36.1 --- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Thu Sep 11 15:34:13 2014 -0700 36.2 +++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Tue Sep 16 13:59:37 2014 -0700 36.3 @@ -28,6 +28,7 @@ 36.4 import static jdk.nashorn.internal.lookup.Lookup.MH; 36.5 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 36.6 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 36.7 +import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 36.8 36.9 import java.lang.invoke.MethodHandle; 36.10 import java.lang.invoke.MethodHandles; 36.11 @@ -697,7 +698,7 @@ 36.12 if (methodHandle != null) { 36.13 return new GuardedInvocation( 36.14 methodHandle, 36.15 - testJSAdaptor(adaptee, findData.getGetter(Object.class, UnwarrantedOptimismException.INVALID_PROGRAM_POINT), findData.getOwner(), func), 36.16 + testJSAdaptor(adaptee, findData.getGetter(Object.class, INVALID_PROGRAM_POINT, null), findData.getOwner(), func), 36.17 adaptee.getProtoSwitchPoint(hook, findData.getOwner())); 36.18 } 36.19 }
37.1 --- a/src/jdk/nashorn/internal/objects/NativeNumber.java Thu Sep 11 15:34:13 2014 -0700 37.2 +++ b/src/jdk/nashorn/internal/objects/NativeNumber.java Tue Sep 16 13:59:37 2014 -0700 37.3 @@ -57,9 +57,9 @@ 37.4 @ScriptClass("Number") 37.5 public final class NativeNumber extends ScriptObject { 37.6 37.7 - // Method handle to create an object wrapper for a primitive number 37.8 - private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeNumber.class, Object.class)); 37.9 - // Method handle to retrieve the Number prototype object 37.10 + /** Method handle to create an object wrapper for a primitive number. */ 37.11 + static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeNumber.class, Object.class)); 37.12 + /** Method handle to retrieve the Number prototype object. */ 37.13 private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class)); 37.14 37.15 /** ECMA 15.7.3.2 largest positive finite value */
38.1 --- a/src/jdk/nashorn/internal/objects/NativeString.java Thu Sep 11 15:34:13 2014 -0700 38.2 +++ b/src/jdk/nashorn/internal/objects/NativeString.java Tue Sep 16 13:59:37 2014 -0700 38.3 @@ -71,9 +71,9 @@ 38.4 38.5 private final CharSequence value; 38.6 38.7 - // Method handle to create an object wrapper for a primitive string 38.8 - private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeString.class, Object.class)); 38.9 - // Method handle to retrieve the String prototype object 38.10 + /** Method handle to create an object wrapper for a primitive string */ 38.11 + static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeString.class, Object.class)); 38.12 + /** Method handle to retrieve the String prototype object */ 38.13 private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class)); 38.14 38.15 // initialized by nasgen
39.1 --- a/src/jdk/nashorn/internal/parser/AbstractParser.java Thu Sep 11 15:34:13 2014 -0700 39.2 +++ b/src/jdk/nashorn/internal/parser/AbstractParser.java Tue Sep 16 13:59:37 2014 -0700 39.3 @@ -326,18 +326,28 @@ 39.4 } 39.5 39.6 /** 39.7 - * Check next token and advance. 39.8 + * Check current token and advance to the next token. 39.9 * 39.10 * @param expected Expected tokenType. 39.11 * 39.12 * @throws ParserException on unexpected token type 39.13 */ 39.14 protected final void expect(final TokenType expected) throws ParserException { 39.15 + expectDontAdvance(expected); 39.16 + next(); 39.17 + } 39.18 + 39.19 + /** 39.20 + * Check current token, but don't advance to the next token. 39.21 + * 39.22 + * @param expected Expected tokenType. 39.23 + * 39.24 + * @throws ParserException on unexpected token type 39.25 + */ 39.26 + protected final void expectDontAdvance(final TokenType expected) throws ParserException { 39.27 if (type != expected) { 39.28 throw error(expectMessage(expected)); 39.29 } 39.30 - 39.31 - next(); 39.32 } 39.33 39.34 /**
40.1 --- a/src/jdk/nashorn/internal/parser/Lexer.java Thu Sep 11 15:34:13 2014 -0700 40.2 +++ b/src/jdk/nashorn/internal/parser/Lexer.java Tue Sep 16 13:59:37 2014 -0700 40.3 @@ -35,6 +35,7 @@ 40.4 import static jdk.nashorn.internal.parser.TokenType.ESCSTRING; 40.5 import static jdk.nashorn.internal.parser.TokenType.EXECSTRING; 40.6 import static jdk.nashorn.internal.parser.TokenType.FLOATING; 40.7 +import static jdk.nashorn.internal.parser.TokenType.FUNCTION; 40.8 import static jdk.nashorn.internal.parser.TokenType.HEXADECIMAL; 40.9 import static jdk.nashorn.internal.parser.TokenType.LBRACE; 40.10 import static jdk.nashorn.internal.parser.TokenType.LPAREN; 40.11 @@ -85,6 +86,9 @@ 40.12 /** Type of last token added. */ 40.13 private TokenType last; 40.14 40.15 + private final boolean pauseOnFunctionBody; 40.16 + private boolean pauseOnNextLeftBrace; 40.17 + 40.18 private static final String SPACETAB = " \t"; // ASCII space and tab 40.19 private static final String LFCR = "\n\r"; // line feed and carriage return (ctrl-m) 40.20 40.21 @@ -182,20 +186,23 @@ 40.22 * @param scripting are we in scripting mode 40.23 */ 40.24 public Lexer(final Source source, final TokenStream stream, final boolean scripting) { 40.25 - this(source, 0, source.getLength(), stream, scripting); 40.26 + this(source, 0, source.getLength(), stream, scripting, false); 40.27 } 40.28 40.29 /** 40.30 - * Contructor 40.31 + * Constructor 40.32 * 40.33 * @param source the source 40.34 * @param start start position in source from which to start lexing 40.35 * @param len length of source segment to lex 40.36 * @param stream token stream to lex 40.37 * @param scripting are we in scripting mode 40.38 + * @param pauseOnFunctionBody if true, lexer will return from {@link #lexify()} when it encounters a 40.39 + * function body. This is used with the feature where the parser is skipping nested function bodies to 40.40 + * avoid reading ahead unnecessarily when we skip the function bodies. 40.41 */ 40.42 40.43 - public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting) { 40.44 + public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting, final boolean pauseOnFunctionBody) { 40.45 super(source.getContent(), 1, start, len); 40.46 this.source = source; 40.47 this.stream = stream; 40.48 @@ -203,6 +210,8 @@ 40.49 this.nested = false; 40.50 this.pendingLine = 1; 40.51 this.last = EOL; 40.52 + 40.53 + this.pauseOnFunctionBody = pauseOnFunctionBody; 40.54 } 40.55 40.56 private Lexer(final Lexer lexer, final State state) { 40.57 @@ -216,6 +225,7 @@ 40.58 pendingLine = state.pendingLine; 40.59 linePosition = state.linePosition; 40.60 last = EOL; 40.61 + pauseOnFunctionBody = false; 40.62 } 40.63 40.64 static class State extends Scanner.State { 40.65 @@ -810,6 +820,9 @@ 40.66 final int length = scanIdentifier(); 40.67 // Check to see if it is a keyword. 40.68 final TokenType type = TokenLookup.lookupKeyword(content, start, length); 40.69 + if (type == FUNCTION && pauseOnFunctionBody) { 40.70 + pauseOnNextLeftBrace = true; 40.71 + } 40.72 // Add keyword or identifier token. 40.73 add(type, start); 40.74 } 40.75 @@ -1597,6 +1610,9 @@ 40.76 // We break to let the parser decide what it is. 40.77 if (canStartLiteral(type)) { 40.78 break; 40.79 + } else if (type == LBRACE && pauseOnNextLeftBrace) { 40.80 + pauseOnNextLeftBrace = false; 40.81 + break; 40.82 } 40.83 } else if (Character.isJavaIdentifierStart(ch0) || ch0 == '\\' && ch1 == 'u') { 40.84 // Scan and add identifier or keyword.
41.1 --- a/src/jdk/nashorn/internal/parser/Parser.java Thu Sep 11 15:34:13 2014 -0700 41.2 +++ b/src/jdk/nashorn/internal/parser/Parser.java Tue Sep 16 13:59:37 2014 -0700 41.3 @@ -45,6 +45,7 @@ 41.4 import static jdk.nashorn.internal.parser.TokenType.IF; 41.5 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX; 41.6 import static jdk.nashorn.internal.parser.TokenType.LBRACE; 41.7 +import static jdk.nashorn.internal.parser.TokenType.LET; 41.8 import static jdk.nashorn.internal.parser.TokenType.LPAREN; 41.9 import static jdk.nashorn.internal.parser.TokenType.RBRACE; 41.10 import static jdk.nashorn.internal.parser.TokenType.RBRACKET; 41.11 @@ -147,7 +148,7 @@ 41.12 /** to receive line information from Lexer when scanning multine literals. */ 41.13 protected final Lexer.LineInfoReceiver lineInfoReceiver; 41.14 41.15 - private int nextFunctionId; 41.16 + private RecompilableScriptFunctionData reparsedFunction; 41.17 41.18 /** 41.19 * Constructor 41.20 @@ -170,7 +171,7 @@ 41.21 * @param log debug logger if one is needed 41.22 */ 41.23 public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final DebugLogger log) { 41.24 - this(env, source, errors, strict, FunctionNode.FIRST_FUNCTION_ID, 0, log); 41.25 + this(env, source, errors, strict, 0, log); 41.26 } 41.27 41.28 /** 41.29 @@ -180,15 +181,13 @@ 41.30 * @param source source to parse 41.31 * @param errors error manager 41.32 * @param strict parser created with strict mode enabled. 41.33 - * @param nextFunctionId starting value for assigning new unique ids to function nodes 41.34 * @param lineOffset line offset to start counting lines from 41.35 * @param log debug logger if one is needed 41.36 */ 41.37 - public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int nextFunctionId, final int lineOffset, final DebugLogger log) { 41.38 + public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) { 41.39 super(source, errors, strict, lineOffset); 41.40 this.env = env; 41.41 this.namespace = new Namespace(env.getNamespace()); 41.42 - this.nextFunctionId = nextFunctionId; 41.43 this.scripting = env._scripting; 41.44 if (this.scripting) { 41.45 this.lineInfoReceiver = new Lexer.LineInfoReceiver() { 41.46 @@ -227,6 +226,16 @@ 41.47 } 41.48 41.49 /** 41.50 + * Sets the {@link RecompilableScriptFunctionData} representing the function being reparsed (when this 41.51 + * parser instance is used to reparse a previously parsed function, as part of its on-demand compilation). 41.52 + * This will trigger various special behaviors, such as skipping nested function bodies. 41.53 + * @param reparsedFunction the function being reparsed. 41.54 + */ 41.55 + public void setReparsedFunction(final RecompilableScriptFunctionData reparsedFunction) { 41.56 + this.reparsedFunction = reparsedFunction; 41.57 + } 41.58 + 41.59 + /** 41.60 * Execute parse and return the resulting function node. 41.61 * Errors will be thrown and the error manager will contain information 41.62 * if parsing should fail 41.63 @@ -263,7 +272,7 @@ 41.64 41.65 try { 41.66 stream = new TokenStream(); 41.67 - lexer = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions); 41.68 + lexer = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, reparsedFunction != null); 41.69 lexer.line = lexer.pendingLine = lineOffset + 1; 41.70 line = lineOffset; 41.71 41.72 @@ -471,7 +480,6 @@ 41.73 final FunctionNode functionNode = 41.74 new FunctionNode( 41.75 source, 41.76 - nextFunctionId++, 41.77 functionLine, 41.78 token, 41.79 Token.descPosition(token), 41.80 @@ -579,6 +587,10 @@ 41.81 } 41.82 } 41.83 41.84 + private boolean useBlockScope() { 41.85 + return env._es6; 41.86 + } 41.87 + 41.88 private static boolean isArguments(final String name) { 41.89 return ARGUMENTS_NAME.equals(name); 41.90 } 41.91 @@ -694,9 +706,20 @@ 41.92 FunctionNode.Kind.SCRIPT, 41.93 functionLine); 41.94 41.95 + // If ES6 block scope is enabled add a per-script block for top-level LET and CONST declarations. 41.96 + final int startLine = start; 41.97 + Block outer = useBlockScope() ? newBlock() : null; 41.98 functionDeclarations = new ArrayList<>(); 41.99 - sourceElements(allowPropertyFunction); 41.100 - addFunctionDeclarations(script); 41.101 + 41.102 + try { 41.103 + sourceElements(allowPropertyFunction); 41.104 + addFunctionDeclarations(script); 41.105 + } finally { 41.106 + if (outer != null) { 41.107 + outer = restoreBlock(outer); 41.108 + appendStatement(new BlockStatement(startLine, outer)); 41.109 + } 41.110 + } 41.111 functionDeclarations = null; 41.112 41.113 expect(EOF); 41.114 @@ -868,7 +891,7 @@ 41.115 block(); 41.116 break; 41.117 case VAR: 41.118 - variableStatement(true); 41.119 + variableStatement(type, true); 41.120 break; 41.121 case SEMICOLON: 41.122 emptyStatement(); 41.123 @@ -918,8 +941,12 @@ 41.124 expect(SEMICOLON); 41.125 break; 41.126 default: 41.127 + if (useBlockScope() && (type == LET || type == CONST)) { 41.128 + variableStatement(type, true); 41.129 + break; 41.130 + } 41.131 if (env._const_as_var && type == CONST) { 41.132 - variableStatement(true); 41.133 + variableStatement(TokenType.VAR, true); 41.134 break; 41.135 } 41.136 41.137 @@ -1035,11 +1062,17 @@ 41.138 * Parse a VAR statement. 41.139 * @param isStatement True if a statement (not used in a FOR.) 41.140 */ 41.141 - private List<VarNode> variableStatement(final boolean isStatement) { 41.142 + private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) { 41.143 // VAR tested in caller. 41.144 next(); 41.145 41.146 final List<VarNode> vars = new ArrayList<>(); 41.147 + int varFlags = VarNode.IS_STATEMENT; 41.148 + if (varType == LET) { 41.149 + varFlags |= VarNode.IS_LET; 41.150 + } else if (varType == CONST) { 41.151 + varFlags |= VarNode.IS_CONST; 41.152 + } 41.153 41.154 while (true) { 41.155 // Get starting token. 41.156 @@ -1063,10 +1096,12 @@ 41.157 } finally { 41.158 defaultNames.pop(); 41.159 } 41.160 + } else if (varType == CONST) { 41.161 + throw error(AbstractParser.message("missing.const.assignment", name.getName())); 41.162 } 41.163 41.164 // Allocate var node. 41.165 - final VarNode var = new VarNode(varLine, varToken, finish, name, init); 41.166 + final VarNode var = new VarNode(varLine, varToken, finish, name.setIsDeclaredHere(), init, varFlags); 41.167 vars.add(var); 41.168 appendStatement(var); 41.169 41.170 @@ -1180,9 +1215,12 @@ 41.171 * Parse a FOR statement. 41.172 */ 41.173 private void forStatement() { 41.174 + // When ES6 for-let is enabled we create a container block to capture the LET. 41.175 + final int startLine = start; 41.176 + Block outer = useBlockScope() ? newBlock() : null; 41.177 + 41.178 // Create FOR node, capturing FOR token. 41.179 ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, ForNode.IS_FOR); 41.180 - 41.181 lc.push(forNode); 41.182 41.183 try { 41.184 @@ -1203,14 +1241,19 @@ 41.185 switch (type) { 41.186 case VAR: 41.187 // Var statements captured in for outer block. 41.188 - vars = variableStatement(false); 41.189 + vars = variableStatement(type, false); 41.190 break; 41.191 case SEMICOLON: 41.192 break; 41.193 default: 41.194 + if (useBlockScope() && (type == LET || type == CONST)) { 41.195 + // LET/CONST captured in container block created above. 41.196 + vars = variableStatement(type, false); 41.197 + break; 41.198 + } 41.199 if (env._const_as_var && type == CONST) { 41.200 // Var statements captured in for outer block. 41.201 - vars = variableStatement(false); 41.202 + vars = variableStatement(TokenType.VAR, false); 41.203 break; 41.204 } 41.205 41.206 @@ -1290,8 +1333,13 @@ 41.207 appendStatement(forNode); 41.208 } finally { 41.209 lc.pop(forNode); 41.210 + if (outer != null) { 41.211 + outer.setFinish(forNode.getFinish()); 41.212 + outer = restoreBlock(outer); 41.213 + appendStatement(new BlockStatement(startLine, outer)); 41.214 + } 41.215 } 41.216 - } 41.217 + } 41.218 41.219 /** 41.220 * ... IterationStatement : 41.221 @@ -1722,7 +1770,7 @@ 41.222 } 41.223 } 41.224 41.225 - /** 41.226 + /** 41.227 * ThrowStatement : 41.228 * throw Expression ; // [no LineTerminator here] 41.229 * 41.230 @@ -2609,7 +2657,7 @@ 41.231 FunctionNode functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL, functionLine); 41.232 41.233 if (isStatement) { 41.234 - if (topLevel) { 41.235 + if (topLevel || useBlockScope()) { 41.236 functionNode = functionNode.setFlag(lc, FunctionNode.IS_DECLARED); 41.237 } else if (isStrictMode) { 41.238 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken); 41.239 @@ -2661,9 +2709,16 @@ 41.240 } 41.241 41.242 if (isStatement) { 41.243 - final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, VarNode.IS_STATEMENT); 41.244 + int varFlags = VarNode.IS_STATEMENT; 41.245 + if (!topLevel && useBlockScope()) { 41.246 + // mark ES6 block functions as lexically scoped 41.247 + varFlags |= VarNode.IS_LET; 41.248 + } 41.249 + final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, varFlags); 41.250 if (topLevel) { 41.251 functionDeclarations.add(varNode); 41.252 + } else if (useBlockScope()) { 41.253 + prependStatement(varNode); // Hoist to beginning of current block 41.254 } else { 41.255 appendStatement(varNode); 41.256 } 41.257 @@ -2780,10 +2835,14 @@ 41.258 FunctionNode functionNode = null; 41.259 long lastToken = 0L; 41.260 41.261 + final boolean parseBody; 41.262 + Object endParserState = null; 41.263 try { 41.264 // Create a new function block. 41.265 functionNode = newFunctionNode(firstToken, ident, parameters, kind, functionLine); 41.266 - 41.267 + assert functionNode != null; 41.268 + final int functionId = functionNode.getId(); 41.269 + parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId(); 41.270 // Nashorn extension: expression closures 41.271 if (!env._no_syntax_extensions && type != LBRACE) { 41.272 /* 41.273 @@ -2799,34 +2858,143 @@ 41.274 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode); 41.275 // EOL uses length field to store the line number 41.276 final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken)); 41.277 - final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr); 41.278 - appendStatement(returnNode); 41.279 + // Only create the return node if we aren't skipping nested functions. Note that we aren't 41.280 + // skipping parsing of these extended functions; they're considered to be small anyway. Also, 41.281 + // they don't end with a single well known token, so it'd be very hard to get correctly (see 41.282 + // the note below for reasoning on skipping happening before instead of after RBRACE for 41.283 + // details). 41.284 + if (parseBody) { 41.285 + final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr); 41.286 + appendStatement(returnNode); 41.287 + } 41.288 functionNode.setFinish(lastFinish); 41.289 - 41.290 } else { 41.291 - expect(LBRACE); 41.292 - 41.293 - // Gather the function elements. 41.294 - final List<Statement> prevFunctionDecls = functionDeclarations; 41.295 - functionDeclarations = new ArrayList<>(); 41.296 - try { 41.297 - sourceElements(false); 41.298 - addFunctionDeclarations(functionNode); 41.299 - } finally { 41.300 - functionDeclarations = prevFunctionDecls; 41.301 + expectDontAdvance(LBRACE); 41.302 + if (parseBody || !skipFunctionBody(functionNode)) { 41.303 + next(); 41.304 + // Gather the function elements. 41.305 + final List<Statement> prevFunctionDecls = functionDeclarations; 41.306 + functionDeclarations = new ArrayList<>(); 41.307 + try { 41.308 + sourceElements(false); 41.309 + addFunctionDeclarations(functionNode); 41.310 + } finally { 41.311 + functionDeclarations = prevFunctionDecls; 41.312 + } 41.313 + 41.314 + lastToken = token; 41.315 + if (parseBody) { 41.316 + // Since the lexer can read ahead and lexify some number of tokens in advance and have 41.317 + // them buffered in the TokenStream, we need to produce a lexer state as it was just 41.318 + // before it lexified RBRACE, and not whatever is its current (quite possibly well read 41.319 + // ahead) state. 41.320 + endParserState = new ParserState(Token.descPosition(token), line, linePosition); 41.321 + 41.322 + // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of 41.323 + // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the 41.324 + // state after it. The reason is that RBRACE is a well-known token that we can expect and 41.325 + // will never involve us getting into a weird lexer state, and as such is a great reparse 41.326 + // point. Typical example of a weird lexer state after RBRACE would be: 41.327 + // function this_is_skipped() { ... } "use strict"; 41.328 + // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead 41.329 + // of compensating for the possibility of a string literal (or similar) after RBRACE, 41.330 + // we'll rather just restart parsing from this well-known, friendly token instead. 41.331 + } 41.332 } 41.333 - 41.334 - lastToken = token; 41.335 expect(RBRACE); 41.336 functionNode.setFinish(finish); 41.337 } 41.338 } finally { 41.339 functionNode = restoreFunctionNode(functionNode, lastToken); 41.340 } 41.341 + 41.342 + // NOTE: we can only do alterations to the function node after restoreFunctionNode. 41.343 + 41.344 + if (parseBody) { 41.345 + functionNode = functionNode.setEndParserState(lc, endParserState); 41.346 + } else if (functionNode.getBody().getStatementCount() > 0){ 41.347 + // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see 41.348 + // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to 41.349 + // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as 41.350 + // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away 41.351 + // nested bodies early if we were supposed to skip 'em. 41.352 + functionNode = functionNode.setBody(null, functionNode.getBody().setStatements(null, 41.353 + Collections.<Statement>emptyList())); 41.354 + } 41.355 + 41.356 + if (reparsedFunction != null) { 41.357 + // We restore the flags stored in the function's ScriptFunctionData that we got when we first 41.358 + // eagerly parsed the code. We're doing it because some flags would be set based on the 41.359 + // content of the function, or even content of its nested functions, most of which are normally 41.360 + // skipped during an on-demand compilation. 41.361 + final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId()); 41.362 + if (data != null) { 41.363 + // Data can be null if when we originally parsed the file, we removed the function declaration 41.364 + // as it was dead code. 41.365 + functionNode = functionNode.setFlags(lc, data.getFunctionFlags()); 41.366 + // This compensates for missing markEval() in case the function contains an inner function 41.367 + // that contains eval(), that now we didn't discover since we skipped the inner function. 41.368 + if (functionNode.hasNestedEval()) { 41.369 + assert functionNode.hasScopeBlock(); 41.370 + functionNode = functionNode.setBody(lc, functionNode.getBody().setNeedsScope(null)); 41.371 + } 41.372 + } 41.373 + } 41.374 printAST(functionNode); 41.375 return functionNode; 41.376 } 41.377 41.378 + private boolean skipFunctionBody(final FunctionNode functionNode) { 41.379 + if (reparsedFunction == null) { 41.380 + // Not reparsing, so don't skip any function body. 41.381 + return false; 41.382 + } 41.383 + // Skip to the RBRACE of this function, and continue parsing from there. 41.384 + final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId()); 41.385 + if (data == null) { 41.386 + // Nested function is not known to the reparsed function. This can happen if the FunctionNode was 41.387 + // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the 41.388 + // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it. 41.389 + return false; 41.390 + } 41.391 + final ParserState parserState = (ParserState)data.getEndParserState(); 41.392 + assert parserState != null; 41.393 + 41.394 + stream.reset(); 41.395 + lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions); 41.396 + line = parserState.line; 41.397 + linePosition = parserState.linePosition; 41.398 + // Doesn't really matter, but it's safe to treat it as if there were a semicolon before 41.399 + // the RBRACE. 41.400 + type = SEMICOLON; 41.401 + k = -1; 41.402 + next(); 41.403 + 41.404 + return true; 41.405 + } 41.406 + 41.407 + /** 41.408 + * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer 41.409 + * for resuming parsing after skipping a function body. 41.410 + */ 41.411 + private static class ParserState { 41.412 + private final int position; 41.413 + private final int line; 41.414 + private final int linePosition; 41.415 + 41.416 + ParserState(final int position, final int line, final int linePosition) { 41.417 + this.position = position; 41.418 + this.line = line; 41.419 + this.linePosition = linePosition; 41.420 + } 41.421 + 41.422 + Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting) { 41.423 + final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, true); 41.424 + newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON)); 41.425 + return newLexer; 41.426 + } 41.427 + } 41.428 + 41.429 private void printAST(final FunctionNode functionNode) { 41.430 if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) { 41.431 env.getErr().println(new ASTWriter(functionNode)); 41.432 @@ -2838,7 +3006,6 @@ 41.433 } 41.434 41.435 private void addFunctionDeclarations(final FunctionNode functionNode) { 41.436 - assert lc.peek() == lc.getFunctionBody(functionNode); 41.437 VarNode lastDecl = null; 41.438 for (int i = functionDeclarations.size() - 1; i >= 0; i--) { 41.439 Statement decl = functionDeclarations.get(i); 41.440 @@ -3200,6 +3367,9 @@ 41.441 } else { 41.442 lc.setFlag(fn, FunctionNode.HAS_NESTED_EVAL); 41.443 } 41.444 + // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip 41.445 + // parsing a nested function. functionBody() contains code to compensate for the lack of invoking 41.446 + // this method when the parser skips a nested function. 41.447 lc.setBlockNeedsScope(lc.getFunctionBody(fn)); 41.448 } 41.449 }
42.1 --- a/src/jdk/nashorn/internal/parser/TokenStream.java Thu Sep 11 15:34:13 2014 -0700 42.2 +++ b/src/jdk/nashorn/internal/parser/TokenStream.java Tue Sep 16 13:59:37 2014 -0700 42.3 @@ -209,4 +209,8 @@ 42.4 in = count; 42.5 buffer = newBuffer; 42.6 } 42.7 + 42.8 + void reset() { 42.9 + in = out = count = base = 0; 42.10 + } 42.11 }
43.1 --- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java Thu Sep 11 15:34:13 2014 -0700 43.2 +++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java Tue Sep 16 13:59:37 2014 -0700 43.3 @@ -549,6 +549,8 @@ 43.4 type == Object.class : 43.5 "invalid getter type " + type + " for " + getKey(); 43.6 43.7 + checkUndeclared(); 43.8 + 43.9 //all this does is add a return value filter for object fields only 43.10 final MethodHandle[] getterCache = GETTER_CACHE; 43.11 final MethodHandle cachedGetter = getterCache[i]; 43.12 @@ -579,6 +581,8 @@ 43.13 return getOptimisticPrimitiveGetter(type, programPoint); 43.14 } 43.15 43.16 + checkUndeclared(); 43.17 + 43.18 return debug( 43.19 createGetter( 43.20 getCurrentType(), 43.21 @@ -608,6 +612,13 @@ 43.22 return newMap; 43.23 } 43.24 43.25 + private void checkUndeclared() { 43.26 + if ((getFlags() & NEEDS_DECLARATION) != 0) { 43.27 + // a lexically defined variable that hasn't seen its declaration - throw ReferenceError 43.28 + throw ECMAErrors.referenceError("not.defined", getKey()); 43.29 + } 43.30 + } 43.31 + 43.32 // the final three arguments are for debug printout purposes only 43.33 @SuppressWarnings("unused") 43.34 private static Object replaceMap(final Object sobj, final PropertyMap newMap) { 43.35 @@ -635,13 +646,14 @@ 43.36 43.37 @Override 43.38 public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) { 43.39 - final int i = getAccessorTypeIndex(type); 43.40 - final int ci = isUndefined() ? -1 : getAccessorTypeIndex(getCurrentType()); 43.41 - final Class<?> forType = isUndefined() ? type : getCurrentType(); 43.42 + checkUndeclared(); 43.43 + 43.44 + final int typeIndex = getAccessorTypeIndex(type); 43.45 + final int currentTypeIndex = getAccessorTypeIndex(getCurrentType()); 43.46 43.47 //if we are asking for an object setter, but are still a primitive type, we might try to box it 43.48 MethodHandle mh; 43.49 - if (needsInvalidator(i, ci)) { 43.50 + if (needsInvalidator(typeIndex, currentTypeIndex)) { 43.51 final Property newProperty = getWiderProperty(type); 43.52 final PropertyMap newMap = getWiderMap(currentMap, newProperty); 43.53 43.54 @@ -652,6 +664,7 @@ 43.55 mh = ObjectClassGenerator.createGuardBoxedPrimitiveSetter(ct, generateSetter(ct, ct), mh); 43.56 } 43.57 } else { 43.58 + final Class<?> forType = isUndefined() ? type : getCurrentType(); 43.59 mh = generateSetter(!forType.isPrimitive() ? Object.class : forType, type); 43.60 } 43.61 43.62 @@ -692,11 +705,12 @@ 43.63 if (OBJECT_FIELDS_ONLY) { 43.64 return false; 43.65 } 43.66 - return getCurrentType() != Object.class && (isConfigurable() || isWritable()); 43.67 + // Return true for currently undefined even if non-writable/configurable to allow initialization of ES6 CONST. 43.68 + return getCurrentType() == null || (getCurrentType() != Object.class && (isConfigurable() || isWritable())); 43.69 } 43.70 43.71 - private boolean needsInvalidator(final int ti, final int fti) { 43.72 - return canChangeType() && ti > fti; 43.73 + private boolean needsInvalidator(final int typeIndex, final int currentTypeIndex) { 43.74 + return canChangeType() && typeIndex > currentTypeIndex; 43.75 } 43.76 43.77 @Override
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 44.2 +++ b/src/jdk/nashorn/internal/runtime/AllocationStrategy.java Tue Sep 16 13:59:37 2014 -0700 44.3 @@ -0,0 +1,104 @@ 44.4 +/* 44.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 44.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 44.7 + * 44.8 + * This code is free software; you can redistribute it and/or modify it 44.9 + * under the terms of the GNU General Public License version 2 only, as 44.10 + * published by the Free Software Foundation. Oracle designates this 44.11 + * particular file as subject to the "Classpath" exception as provided 44.12 + * by Oracle in the LICENSE file that accompanied this code. 44.13 + * 44.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 44.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 44.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 44.17 + * version 2 for more details (a copy is included in the LICENSE file that 44.18 + * accompanied this code). 44.19 + * 44.20 + * You should have received a copy of the GNU General Public License version 44.21 + * 2 along with this work; if not, write to the Free Software Foundation, 44.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 44.23 + * 44.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 44.25 + * or visit www.oracle.com if you need additional information or have any 44.26 + * questions. 44.27 + */ 44.28 +package jdk.nashorn.internal.runtime; 44.29 + 44.30 +import static jdk.nashorn.internal.lookup.Lookup.MH; 44.31 + 44.32 +import java.io.Serializable; 44.33 +import java.lang.invoke.MethodHandle; 44.34 +import java.lang.invoke.MethodHandles; 44.35 +import jdk.nashorn.internal.codegen.CompilerConstants; 44.36 +import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor; 44.37 + 44.38 +/** 44.39 + * Encapsulates the allocation strategy for a function when used as a constructor. Basically the same as 44.40 + * {@link AllocatorDescriptor}, but with an additionally cached resolved method handle. There is also a 44.41 + * canonical default allocation strategy for functions that don't assign any "this" properties (vast majority 44.42 + * of all functions), therefore saving some storage space in {@link RecompilableScriptFunctionData} that would 44.43 + * otherwise be lost to identical tuples of (map, className, handle) fields. 44.44 + */ 44.45 +final class AllocationStrategy implements Serializable { 44.46 + private static final long serialVersionUID = 1L; 44.47 + 44.48 + private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); 44.49 + 44.50 + private static final AllocationStrategy DEFAULT_STRATEGY = new AllocationStrategy(new AllocatorDescriptor(0)); 44.51 + 44.52 + /** Allocator map from allocator descriptor */ 44.53 + private final PropertyMap allocatorMap; 44.54 + 44.55 + /** Name of class where allocator function resides */ 44.56 + private final String allocatorClassName; 44.57 + 44.58 + /** lazily generated allocator */ 44.59 + private transient MethodHandle allocator; 44.60 + 44.61 + private AllocationStrategy(final AllocatorDescriptor desc) { 44.62 + this.allocatorMap = desc.getAllocatorMap(); 44.63 + // These classes get loaded, so an interned variant of their name is most likely around anyway. 44.64 + this.allocatorClassName = desc.getAllocatorClassName().intern(); 44.65 + } 44.66 + 44.67 + private boolean matches(final AllocatorDescriptor desc) { 44.68 + return desc.getAllocatorMap().size() == allocatorMap.size() && 44.69 + desc.getAllocatorClassName().equals(allocatorClassName); 44.70 + } 44.71 + 44.72 + static AllocationStrategy get(final AllocatorDescriptor desc) { 44.73 + return DEFAULT_STRATEGY.matches(desc) ? DEFAULT_STRATEGY : new AllocationStrategy(desc); 44.74 + } 44.75 + 44.76 + PropertyMap getAllocatorMap() { 44.77 + return allocatorMap; 44.78 + } 44.79 + 44.80 + ScriptObject allocate(final PropertyMap map) { 44.81 + try { 44.82 + if (allocator == null) { 44.83 + allocator = MH.findStatic(LOOKUP, Context.forStructureClass(allocatorClassName), 44.84 + CompilerConstants.ALLOCATE.symbolName(), MH.type(ScriptObject.class, PropertyMap.class)); 44.85 + } 44.86 + return (ScriptObject)allocator.invokeExact(map); 44.87 + } catch (final RuntimeException | Error e) { 44.88 + throw e; 44.89 + } catch (final Throwable t) { 44.90 + throw new RuntimeException(t); 44.91 + } 44.92 + } 44.93 + 44.94 + private Object readResolve() { 44.95 + if(allocatorMap.size() == DEFAULT_STRATEGY.allocatorMap.size() && 44.96 + allocatorClassName.equals(DEFAULT_STRATEGY.allocatorClassName)) { 44.97 + return DEFAULT_STRATEGY; 44.98 + } 44.99 + return this; 44.100 + } 44.101 + 44.102 + @Override 44.103 + public String toString() { 44.104 + return "AllocationStrategy[allocatorClassName=" + allocatorClassName + ", allocatorMap.size=" + 44.105 + allocatorMap.size() + "]"; 44.106 + } 44.107 +}
45.1 --- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java Thu Sep 11 15:34:13 2014 -0700 45.2 +++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java Tue Sep 16 13:59:37 2014 -0700 45.3 @@ -80,12 +80,6 @@ 45.4 public long getUniqueScriptId(); 45.5 45.6 /** 45.7 - * Get next unique eval id 45.8 - * @return unique eval id 45.9 - */ 45.10 - public long getUniqueEvalId(); 45.11 - 45.12 - /** 45.13 * Store a compiled script for later reuse 45.14 * @param source the script source 45.15 * @param mainClassName the main class name
46.1 --- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java Thu Sep 11 15:34:13 2014 -0700 46.2 +++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java Tue Sep 16 13:59:37 2014 -0700 46.3 @@ -27,7 +27,6 @@ 46.4 import static jdk.nashorn.internal.lookup.Lookup.MH; 46.5 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 46.6 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; 46.7 - 46.8 import java.lang.invoke.CallSite; 46.9 import java.lang.invoke.MethodHandle; 46.10 import java.lang.invoke.MethodHandles; 46.11 @@ -39,6 +38,7 @@ 46.12 import java.util.TreeMap; 46.13 import java.util.function.Supplier; 46.14 import java.util.logging.Level; 46.15 + 46.16 import jdk.internal.dynalink.linker.GuardedInvocation; 46.17 import jdk.nashorn.internal.codegen.Compiler; 46.18 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
47.1 --- a/src/jdk/nashorn/internal/runtime/Context.java Thu Sep 11 15:34:13 2014 -0700 47.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java Tue Sep 16 13:59:37 2014 -0700 47.3 @@ -196,16 +196,11 @@ 47.4 } 47.5 47.6 @Override 47.7 - public long getUniqueEvalId() { 47.8 - return context.getUniqueEvalId(); 47.9 - } 47.10 - 47.11 - @Override 47.12 - public void storeScript(final String classInfoFile, final Source source, final String mainClassName, 47.13 + public void storeScript(final String cacheKey, final Source source, final String mainClassName, 47.14 final Map<String,byte[]> classBytes, final Map<Integer, FunctionInitializer> initializers, 47.15 final Object[] constants, final int compilationId) { 47.16 if (context.codeStore != null) { 47.17 - context.codeStore.storeScript(classInfoFile, source, mainClassName, classBytes, initializers, constants, compilationId); 47.18 + context.codeStore.storeScript(cacheKey, source, mainClassName, classBytes, initializers, constants, compilationId); 47.19 } 47.20 } 47.21 47.22 @@ -334,9 +329,6 @@ 47.23 /** Unique id for script. Used only when --loader-per-compile=false */ 47.24 private final AtomicLong uniqueScriptId; 47.25 47.26 - /** Unique id for 'eval' */ 47.27 - private final AtomicLong uniqueEvalId; 47.28 - 47.29 /** Optional class filter to use for Java classes. Can be null. */ 47.30 private final ClassFilter classFilter; 47.31 47.32 @@ -450,7 +442,6 @@ 47.33 this.uniqueScriptId = new AtomicLong(); 47.34 } 47.35 this.errors = errors; 47.36 - this.uniqueEvalId = new AtomicLong(); 47.37 47.38 // if user passed -classpath option, make a class loader with that and set it as 47.39 // thread context class loader so that script can access classes from that path. 47.40 @@ -1132,7 +1123,7 @@ 47.41 if (storedScript == null) { 47.42 functionNode = new Parser(env, source, errMan, strict, getLogger(Parser.class)).parse(); 47.43 47.44 - if (errors.hasErrors()) { 47.45 + if (errMan.hasErrors()) { 47.46 return null; 47.47 } 47.48 47.49 @@ -1162,9 +1153,13 @@ 47.50 env, 47.51 installer, 47.52 source, 47.53 + errMan, 47.54 strict | functionNode.isStrict()); 47.55 47.56 final FunctionNode compiledFunction = compiler.compile(functionNode, phases); 47.57 + if (errMan.hasErrors()) { 47.58 + return null; 47.59 + } 47.60 script = compiledFunction.getRootClass(); 47.61 compiler.persistClassInfo(cacheKey, compiledFunction); 47.62 } else { 47.63 @@ -1186,10 +1181,6 @@ 47.64 }, CREATE_LOADER_ACC_CTXT); 47.65 } 47.66 47.67 - private long getUniqueEvalId() { 47.68 - return uniqueEvalId.getAndIncrement(); 47.69 - } 47.70 - 47.71 private long getUniqueScriptId() { 47.72 return uniqueScriptId.getAndIncrement(); 47.73 }
48.1 --- a/src/jdk/nashorn/internal/runtime/FindProperty.java Thu Sep 11 15:34:13 2014 -0700 48.2 +++ b/src/jdk/nashorn/internal/runtime/FindProperty.java Tue Sep 16 13:59:37 2014 -0700 48.3 @@ -29,7 +29,9 @@ 48.4 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; 48.5 48.6 import java.lang.invoke.MethodHandle; 48.7 +import jdk.internal.dynalink.linker.LinkRequest; 48.8 import jdk.nashorn.internal.codegen.ObjectClassGenerator; 48.9 +import jdk.nashorn.internal.objects.Global; 48.10 48.11 /** 48.12 * This class represents the result from a find property search. 48.13 @@ -58,6 +60,18 @@ 48.14 } 48.15 48.16 /** 48.17 + * Return a copy of this FindProperty with a different property. 48.18 + * 48.19 + * @param newProperty the new property 48.20 + * @return the new FindProperty instance 48.21 + */ 48.22 + public FindProperty replaceProperty(final Property newProperty) { 48.23 + assert this.property.getKey().equals(newProperty.getKey()); 48.24 + assert this.property.getSlot() == newProperty.getSlot(); 48.25 + return new FindProperty(self, prototype, newProperty); 48.26 + } 48.27 + 48.28 + /** 48.29 * Ask for a getter that returns the given type. The type has nothing to do with the 48.30 * internal representation of the property. It may be an Object (boxing primitives) or 48.31 * a primitive (primitive fields with -Dnashorn.fields.dual=true) 48.32 @@ -67,25 +81,17 @@ 48.33 * @param programPoint program point, or INVALID_PROGRAM_POINT if pessimistic 48.34 * @return method handle for the getter 48.35 */ 48.36 - public MethodHandle getGetter(final Class<?> type, final int programPoint) { 48.37 + public MethodHandle getGetter(final Class<?> type, final int programPoint, final LinkRequest request) { 48.38 final MethodHandle getter; 48.39 if (isValid(programPoint)) { 48.40 getter = property.getOptimisticGetter(type, programPoint); 48.41 } else { 48.42 getter = property.getGetter(type); 48.43 } 48.44 - return getGetterInner(getter); 48.45 - } 48.46 - 48.47 - private MethodHandle getGetterInner(final MethodHandle getter) { 48.48 if (property instanceof UserAccessorProperty) { 48.49 - final UserAccessorProperty uc = (UserAccessorProperty)property; 48.50 - final ScriptObject owner = getOwner(); 48.51 - final ScriptObject container = (owner != null) ? owner : self; 48.52 - return MH.insertArguments(getter, 0, uc.getAccessors(container)); 48.53 + return insertAccessorsGetter((UserAccessorProperty) property, request, getter); 48.54 } 48.55 return getter; 48.56 - 48.57 } 48.58 48.59 /** 48.60 @@ -99,18 +105,31 @@ 48.61 * 48.62 * @return method handle for the getter 48.63 */ 48.64 - public MethodHandle getSetter(final Class<?> type, final boolean strict) { 48.65 - final MethodHandle setter = property.getSetter(type, getOwner().getMap()); 48.66 + public MethodHandle getSetter(final Class<?> type, final boolean strict, final LinkRequest request) { 48.67 + MethodHandle setter = property.getSetter(type, getOwner().getMap()); 48.68 if (property instanceof UserAccessorProperty) { 48.69 - final UserAccessorProperty uc = (UserAccessorProperty)property; 48.70 - final ScriptObject owner = getOwner(); 48.71 - final ScriptObject container = (owner != null) ? owner : self; 48.72 - return MH.insertArguments(setter, 0, uc.getAccessors(container), strict ? property.getKey() : null); 48.73 + setter = MH.insertArguments(setter, 1, strict ? property.getKey() : null); 48.74 + return insertAccessorsGetter((UserAccessorProperty) property, request, setter); 48.75 } 48.76 48.77 return setter; 48.78 } 48.79 48.80 + // Fold an accessor getter into the method handle of a user accessor property. 48.81 + private MethodHandle insertAccessorsGetter(final UserAccessorProperty uap, final LinkRequest request, final MethodHandle mh) { 48.82 + MethodHandle superGetter = uap.getAccessorsGetter(); 48.83 + if (isInherited()) { 48.84 + superGetter = ScriptObject.addProtoFilter(superGetter, getProtoChainLength()); 48.85 + } 48.86 + if (request != null && !(request.getReceiver() instanceof ScriptObject)) { 48.87 + final MethodHandle wrapFilter = Global.getPrimitiveWrapFilter(request.getReceiver()); 48.88 + superGetter = MH.filterArguments(superGetter, 0, wrapFilter.asType(wrapFilter.type().changeReturnType(superGetter.type().parameterType(0)))); 48.89 + } 48.90 + superGetter = MH.asType(superGetter, superGetter.type().changeParameterType(0, Object.class)); 48.91 + 48.92 + return MH.foldArguments(mh, superGetter); 48.93 + } 48.94 + 48.95 /** 48.96 * Return the {@code ScriptObject} owning of the property: this means the prototype. 48.97 * @return owner of property 48.98 @@ -124,7 +143,7 @@ 48.99 * @return appropriate receiver 48.100 */ 48.101 public ScriptObject getGetterReceiver() { 48.102 - return property != null && property.hasGetterFunction(prototype) ? self : prototype; 48.103 + return property != null && property instanceof UserAccessorProperty ? self : prototype; 48.104 } 48.105 48.106 /**
49.1 --- a/src/jdk/nashorn/internal/runtime/GlobalConstants.java Thu Sep 11 15:34:13 2014 -0700 49.2 +++ b/src/jdk/nashorn/internal/runtime/GlobalConstants.java Tue Sep 16 13:59:37 2014 -0700 49.3 @@ -28,6 +28,8 @@ 49.4 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; 49.5 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall; 49.6 import static jdk.nashorn.internal.lookup.Lookup.MH; 49.7 +import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 49.8 +import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.getProgramPoint; 49.9 import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote; 49.10 49.11 import java.lang.invoke.MethodHandle; 49.12 @@ -370,22 +372,19 @@ 49.13 * @param find property lookup 49.14 * @param receiver receiver 49.15 * @param desc callsite descriptor 49.16 - * @param request link request 49.17 - * @param operator operator 49.18 * 49.19 * @return resulting getter, or null if failed to create constant 49.20 */ 49.21 - synchronized GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc, final LinkRequest request, final String operator) { 49.22 - if (GLOBAL_ONLY && !find.getOwner().isGlobal()) { 49.23 + synchronized GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc) { 49.24 + // Also return null if property may have side effects 49.25 + if ((GLOBAL_ONLY && !find.getOwner().isGlobal()) || find.getProperty() instanceof UserAccessorProperty) { 49.26 return null; 49.27 } 49.28 49.29 - final int programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ? 49.30 - NashornCallSiteDescriptor.getProgramPoint(desc) : 49.31 - UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 49.32 - final boolean isOptimistic = programPoint != UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 49.33 - final Class<?> retType = desc.getMethodType().returnType(); 49.34 - final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 49.35 + final boolean isOptimistic = NashornCallSiteDescriptor.isOptimistic(desc); 49.36 + final int programPoint = isOptimistic ? getProgramPoint(desc) : INVALID_PROGRAM_POINT; 49.37 + final Class<?> retType = desc.getMethodType().returnType(); 49.38 + final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 49.39 49.40 final Access acc = getOrCreateSwitchPoint(name); 49.41
50.1 --- a/src/jdk/nashorn/internal/runtime/JSType.java Thu Sep 11 15:34:13 2014 -0700 50.2 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Tue Sep 16 13:59:37 2014 -0700 50.3 @@ -938,11 +938,8 @@ 50.4 * @return double 50.5 */ 50.6 public static int toInt32Optimistic(final Object obj, final int programPoint) { 50.7 - if (obj != null) { 50.8 - final Class<?> clz = obj.getClass(); 50.9 - if (clz == Integer.class) { 50.10 - return ((Integer)obj).intValue(); 50.11 - } 50.12 + if (obj != null && obj.getClass() == Integer.class) { 50.13 + return ((Integer)obj).intValue(); 50.14 } 50.15 throw new UnwarrantedOptimismException(obj, programPoint); 50.16 }
51.1 --- a/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java Thu Sep 11 15:34:13 2014 -0700 51.2 +++ b/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java Tue Sep 16 13:59:37 2014 -0700 51.3 @@ -191,19 +191,20 @@ 51.4 } 51.5 51.6 /** 51.7 - * Returns the argument value as an int. If the argument is not a Number object that can be exactly represented as 51.8 - * an int, throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code 51.9 - * can use it. See {code CodeGenerator.ENSURE_INT}. 51.10 + * Returns the argument value as an int. If the argument is not a wrapper for a primitive numeric type 51.11 + * with a value that can be exactly represented as an int, throw an {@link UnwarrantedOptimismException}. 51.12 + * This method is only public so that generated script code can use it. See {code CodeGenerator.ENSURE_INT}. 51.13 * @param arg the original argument. 51.14 * @param programPoint the program point used in the exception 51.15 * @return the value of the argument as an int. 51.16 - * @throws UnwarrantedOptimismException if the argument is not a Number that can be exactly represented as an int. 51.17 + * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type with 51.18 + * a value that can be exactly represented as an int. 51.19 */ 51.20 public static int ensureInt(final Object arg, final int programPoint) { 51.21 // NOTE: this doesn't delegate to ensureInt(double, int) as in that case if arg were a Long, it would throw a 51.22 // (potentially imprecise) Double in the UnwarrantedOptimismException. This way, it will put the correct valued 51.23 // Long into the exception. 51.24 - if (arg instanceof Number) { 51.25 + if (isPrimitiveNumberWrapper(arg)) { 51.26 final double d = ((Number)arg).doubleValue(); 51.27 if (JSType.isRepresentableAsInt(d) && !JSType.isNegativeZero(d)) { 51.28 return (int)d; 51.29 @@ -212,6 +213,15 @@ 51.30 throw new UnwarrantedOptimismException(arg, programPoint); 51.31 } 51.32 51.33 + private static boolean isPrimitiveNumberWrapper(final Object obj) { 51.34 + if (obj == null) { 51.35 + return false; 51.36 + } 51.37 + final Class<?> c = obj.getClass(); 51.38 + return c == Integer.class || c == Double.class || c == Long.class || 51.39 + c == Float.class || c == Short.class || c == Byte.class; 51.40 + } 51.41 + 51.42 @SuppressWarnings("unused") 51.43 private static int ensureInt(final boolean arg, final int programPoint) { 51.44 throw new UnwarrantedOptimismException(arg, programPoint, Type.OBJECT); 51.45 @@ -236,35 +246,40 @@ 51.46 } 51.47 51.48 /** 51.49 - * Returns the argument value as a long. If the argument is not a Number object that can be exactly represented as 51.50 - * a long, throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code 51.51 - * can use it. See {code CodeGenerator.ENSURE_LONG}. 51.52 + * Returns the argument value as a long. If the argument is not a wrapper for a primitive numeric type 51.53 + * with a value that can be exactly represented as a long, throw an {@link UnwarrantedOptimismException}. 51.54 + * This method is only public so that generated script code can use it. See {code CodeGenerator.ENSURE_LONG}. 51.55 * @param arg the original argument. 51.56 * @param programPoint the program point used in the exception 51.57 * @return the value of the argument as a long. 51.58 - * @throws UnwarrantedOptimismException if the argument is not a Number that can be exactly represented as a long. 51.59 + * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type with 51.60 + * a value that can be exactly represented as a long 51.61 */ 51.62 public static long ensureLong(final Object arg, final int programPoint) { 51.63 - if (arg instanceof Long) { 51.64 - // Must check for Long separately, as Long.doubleValue() isn't precise. 51.65 - return ((Long)arg).longValue(); 51.66 - } else if (arg instanceof Number) { 51.67 - return ensureLong(((Number)arg).doubleValue(), programPoint); 51.68 + if (arg != null) { 51.69 + final Class<?> c = arg.getClass(); 51.70 + if (c == Long.class) { 51.71 + // Must check for Long separately, as Long.doubleValue() isn't precise. 51.72 + return ((Long)arg).longValue(); 51.73 + } else if (c == Integer.class || c == Double.class || c == Float.class || c == Short.class || 51.74 + c == Byte.class) { 51.75 + return ensureLong(((Number)arg).doubleValue(), programPoint); 51.76 + } 51.77 } 51.78 throw new UnwarrantedOptimismException(arg, programPoint); 51.79 } 51.80 51.81 /** 51.82 - * Returns the argument value as a double. If the argument is not a Number object, throw an 51.83 - * {@link UnwarrantedOptimismException}.This method is only public so that generated script code can use it. See 51.84 - * {code CodeGenerator.ENSURE_NUMBER}. 51.85 + * Returns the argument value as a double. If the argument is not a a wrapper for a primitive numeric type 51.86 + * throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code 51.87 + * can use it. See {code CodeGenerator.ENSURE_NUMBER}. 51.88 * @param arg the original argument. 51.89 * @param programPoint the program point used in the exception 51.90 * @return the value of the argument as a double. 51.91 - * @throws UnwarrantedOptimismException if the argument is not a Number that can be exactly represented as a long. 51.92 + * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type. 51.93 */ 51.94 public static double ensureNumber(final Object arg, final int programPoint) { 51.95 - if (arg instanceof Number) { // arg == null -> false 51.96 + if (isPrimitiveNumberWrapper(arg)) { 51.97 return ((Number)arg).doubleValue(); 51.98 } 51.99 throw new UnwarrantedOptimismException(arg, programPoint);
52.1 --- a/src/jdk/nashorn/internal/runtime/Property.java Thu Sep 11 15:34:13 2014 -0700 52.2 +++ b/src/jdk/nashorn/internal/runtime/Property.java Tue Sep 16 13:59:37 2014 -0700 52.3 @@ -82,11 +82,14 @@ 52.4 * is narrower than object, e.g. Math.PI which is declared 52.5 * as a double 52.6 */ 52.7 - public static final int IS_NASGEN_PRIMITIVE = 1 << 6; 52.8 + public static final int IS_NASGEN_PRIMITIVE = 1 << 6; 52.9 52.10 /** Is this property bound to a receiver? This means get/set operations will be delegated to 52.11 * a statically defined object instead of the object passed as callsite parameter. */ 52.12 - public static final int IS_BOUND = 1 << 8; 52.13 + public static final int IS_BOUND = 1 << 7; 52.14 + 52.15 + /** Is this a lexically scoped LET or CONST variable that is dead until it is declared. */ 52.16 + public static final int NEEDS_DECLARATION = 1 << 8; 52.17 52.18 /** Property key. */ 52.19 private final String key; 52.20 @@ -287,6 +290,15 @@ 52.21 } 52.22 52.23 /** 52.24 + * Is this a LET or CONST property that needs to see its declaration before being usable? 52.25 + * 52.26 + * @return true if this is a block-scoped variable 52.27 + */ 52.28 + public boolean needsDeclaration() { 52.29 + return (flags & NEEDS_DECLARATION) == NEEDS_DECLARATION; 52.30 + } 52.31 + 52.32 + /** 52.33 * Add more property flags to the property. Properties are immutable here, 52.34 * so any property change that results in a larger flag set results in the 52.35 * property being cloned. Use only the return value
53.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Thu Sep 11 15:34:13 2014 -0700 53.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Tue Sep 16 13:59:37 2014 -0700 53.3 @@ -42,6 +42,7 @@ 53.4 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; 53.5 import jdk.nashorn.internal.codegen.CompilerConstants; 53.6 import jdk.nashorn.internal.codegen.FunctionSignature; 53.7 +import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor; 53.8 import jdk.nashorn.internal.codegen.OptimisticTypesPersistence; 53.9 import jdk.nashorn.internal.codegen.TypeMap; 53.10 import jdk.nashorn.internal.codegen.types.Type; 53.11 @@ -55,7 +56,6 @@ 53.12 import jdk.nashorn.internal.runtime.logging.DebugLogger; 53.13 import jdk.nashorn.internal.runtime.logging.Loggable; 53.14 import jdk.nashorn.internal.runtime.logging.Logger; 53.15 - 53.16 /** 53.17 * This is a subclass that represents a script function that may be regenerated, 53.18 * for example with specialization based on call site types, or lazily generated. 53.19 @@ -81,26 +81,29 @@ 53.20 /** Token of this function within the source. */ 53.21 private final long token; 53.22 53.23 - /** Allocator map from makeMap() */ 53.24 - private final PropertyMap allocatorMap; 53.25 + /** 53.26 + * Represents the allocation strategy (property map, script object class, and method handle) for when 53.27 + * this function is used as a constructor. Note that majority of functions (those not setting any this.* 53.28 + * properties) will share a single canonical "default strategy" instance. 53.29 + */ 53.30 + private final AllocationStrategy allocationStrategy; 53.31 + 53.32 + /** 53.33 + * Opaque object representing parser state at the end of the function. Used when reparsing outer function 53.34 + * to help with skipping parsing inner functions. 53.35 + */ 53.36 + private final Object endParserState; 53.37 53.38 /** Code installer used for all further recompilation/specialization of this ScriptFunction */ 53.39 private transient CodeInstaller<ScriptEnvironment> installer; 53.40 53.41 - /** Name of class where allocator function resides */ 53.42 - private final String allocatorClassName; 53.43 - 53.44 - /** lazily generated allocator */ 53.45 - private transient MethodHandle allocator; 53.46 - 53.47 private final Map<Integer, RecompilableScriptFunctionData> nestedFunctions; 53.48 53.49 /** Id to parent function if one exists */ 53.50 private RecompilableScriptFunctionData parent; 53.51 53.52 - private final boolean isDeclared; 53.53 - private final boolean isAnonymous; 53.54 - private final boolean needsCallee; 53.55 + /** Copy of the {@link FunctionNode} flags. */ 53.56 + private final int functionFlags; 53.57 53.58 private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); 53.59 53.60 @@ -119,8 +122,7 @@ 53.61 * 53.62 * @param functionNode functionNode that represents this function code 53.63 * @param installer installer for code regeneration versions of this function 53.64 - * @param allocatorClassName name of our allocator class, will be looked up dynamically if used as a constructor 53.65 - * @param allocatorMap allocator map to seed instances with, when constructing 53.66 + * @param allocationDescriptor descriptor for the allocation behavior when this function is used as a constructor 53.67 * @param nestedFunctions nested function map 53.68 * @param externalScopeDepths external scope depths 53.69 * @param internalSymbols internal symbols to method, defined in its scope 53.70 @@ -128,30 +130,27 @@ 53.71 public RecompilableScriptFunctionData( 53.72 final FunctionNode functionNode, 53.73 final CodeInstaller<ScriptEnvironment> installer, 53.74 - final String allocatorClassName, 53.75 - final PropertyMap allocatorMap, 53.76 + final AllocatorDescriptor allocationDescriptor, 53.77 final Map<Integer, RecompilableScriptFunctionData> nestedFunctions, 53.78 final Map<String, Integer> externalScopeDepths, 53.79 final Set<String> internalSymbols) { 53.80 53.81 super(functionName(functionNode), 53.82 Math.min(functionNode.getParameters().size(), MAX_ARITY), 53.83 - getFlags(functionNode)); 53.84 + getDataFlags(functionNode)); 53.85 53.86 this.functionName = functionNode.getName(); 53.87 this.lineNumber = functionNode.getLineNumber(); 53.88 - this.isDeclared = functionNode.isDeclared(); 53.89 - this.needsCallee = functionNode.needsCallee(); 53.90 - this.isAnonymous = functionNode.isAnonymous(); 53.91 + this.functionFlags = functionNode.getFlags() | (functionNode.needsCallee() ? FunctionNode.NEEDS_CALLEE : 0); 53.92 this.functionNodeId = functionNode.getId(); 53.93 this.source = functionNode.getSource(); 53.94 + this.endParserState = functionNode.getEndParserState(); 53.95 this.token = tokenFor(functionNode); 53.96 this.installer = installer; 53.97 - this.allocatorClassName = allocatorClassName; 53.98 - this.allocatorMap = allocatorMap; 53.99 - this.nestedFunctions = nestedFunctions; 53.100 - this.externalScopeDepths = externalScopeDepths; 53.101 - this.internalSymbols = new HashSet<>(internalSymbols); 53.102 + this.allocationStrategy = AllocationStrategy.get(allocationDescriptor); 53.103 + this.nestedFunctions = smallMap(nestedFunctions); 53.104 + this.externalScopeDepths = smallMap(externalScopeDepths); 53.105 + this.internalSymbols = smallSet(new HashSet<>(internalSymbols)); 53.106 53.107 for (final RecompilableScriptFunctionData nfn : nestedFunctions.values()) { 53.108 assert nfn.getParent() == null; 53.109 @@ -161,6 +160,27 @@ 53.110 createLogger(); 53.111 } 53.112 53.113 + private static <K, V> Map<K, V> smallMap(final Map<K, V> map) { 53.114 + if (map == null || map.isEmpty()) { 53.115 + return Collections.emptyMap(); 53.116 + } else if (map.size() == 1) { 53.117 + final Map.Entry<K, V> entry = map.entrySet().iterator().next(); 53.118 + return Collections.singletonMap(entry.getKey(), entry.getValue()); 53.119 + } else { 53.120 + return map; 53.121 + } 53.122 + } 53.123 + 53.124 + private static <T> Set<T> smallSet(final Set<T> set) { 53.125 + if (set == null || set.isEmpty()) { 53.126 + return Collections.emptySet(); 53.127 + } else if (set.size() == 1) { 53.128 + return Collections.singleton(set.iterator().next()); 53.129 + } else { 53.130 + return set; 53.131 + } 53.132 + } 53.133 + 53.134 @Override 53.135 public DebugLogger getLogger() { 53.136 return log; 53.137 @@ -190,11 +210,7 @@ 53.138 * @return the external symbol table with proto depths 53.139 */ 53.140 public int getExternalSymbolDepth(final String symbolName) { 53.141 - final Map<String, Integer> map = externalScopeDepths; 53.142 - if (map == null) { 53.143 - return -1; 53.144 - } 53.145 - final Integer depth = map.get(symbolName); 53.146 + final Integer depth = externalScopeDepths.get(symbolName); 53.147 if (depth == null) { 53.148 return -1; 53.149 } 53.150 @@ -202,6 +218,23 @@ 53.151 } 53.152 53.153 /** 53.154 + * Returns the names of all external symbols this function uses. 53.155 + * @return the names of all external symbols this function uses. 53.156 + */ 53.157 + public Set<String> getExternalSymbolNames() { 53.158 + return Collections.unmodifiableSet(externalScopeDepths.keySet()); 53.159 + } 53.160 + 53.161 + /** 53.162 + * Returns the opaque object representing the parser state at the end of this function's body, used to 53.163 + * skip parsing this function when reparsing its containing outer function. 53.164 + * @return the object representing the end parser state 53.165 + */ 53.166 + public Object getEndParserState() { 53.167 + return endParserState; 53.168 + } 53.169 + 53.170 + /** 53.171 * Get the parent of this RecompilableScriptFunctionData. If we are 53.172 * a nested function, we have a parent. Note that "null" return value 53.173 * can also mean that we have a parent but it is unknown, so this can 53.174 @@ -269,7 +302,7 @@ 53.175 53.176 @Override 53.177 public boolean inDynamicContext() { 53.178 - return (flags & IN_DYNAMIC_CONTEXT) != 0; 53.179 + return getFunctionFlag(FunctionNode.IN_DYNAMIC_CONTEXT); 53.180 } 53.181 53.182 private static String functionName(final FunctionNode fn) { 53.183 @@ -293,7 +326,7 @@ 53.184 return Token.toDesc(TokenType.FUNCTION, position, length); 53.185 } 53.186 53.187 - private static int getFlags(final FunctionNode functionNode) { 53.188 + private static int getDataFlags(final FunctionNode functionNode) { 53.189 int flags = IS_CONSTRUCTOR; 53.190 if (functionNode.isStrict()) { 53.191 flags |= IS_STRICT; 53.192 @@ -307,37 +340,20 @@ 53.193 if (functionNode.isVarArg()) { 53.194 flags |= IS_VARIABLE_ARITY; 53.195 } 53.196 - if (functionNode.inDynamicContext()) { 53.197 - flags |= IN_DYNAMIC_CONTEXT; 53.198 - } 53.199 return flags; 53.200 } 53.201 53.202 @Override 53.203 PropertyMap getAllocatorMap() { 53.204 - return allocatorMap; 53.205 + return allocationStrategy.getAllocatorMap(); 53.206 } 53.207 53.208 @Override 53.209 ScriptObject allocate(final PropertyMap map) { 53.210 - try { 53.211 - ensureHasAllocator(); //if allocatorClass name is set to null (e.g. for bound functions) we don't even try 53.212 - return allocator == null ? null : (ScriptObject)allocator.invokeExact(map); 53.213 - } catch (final RuntimeException | Error e) { 53.214 - throw e; 53.215 - } catch (final Throwable t) { 53.216 - throw new RuntimeException(t); 53.217 - } 53.218 - } 53.219 - 53.220 - private void ensureHasAllocator() throws ClassNotFoundException { 53.221 - if (allocator == null && allocatorClassName != null) { 53.222 - this.allocator = MH.findStatic(LOOKUP, Context.forStructureClass(allocatorClassName), CompilerConstants.ALLOCATE.symbolName(), MH.type(ScriptObject.class, PropertyMap.class)); 53.223 - } 53.224 + return allocationStrategy.allocate(map); 53.225 } 53.226 53.227 FunctionNode reparse() { 53.228 - final boolean isProgram = functionNodeId == FunctionNode.FIRST_FUNCTION_ID; 53.229 // NOTE: If we aren't recompiling the top-level program, we decrease functionNodeId 'cause we'll have a synthetic program node 53.230 final int descPosition = Token.descPosition(token); 53.231 final Context context = Context.getContextTrusted(); 53.232 @@ -346,18 +362,27 @@ 53.233 source, 53.234 new Context.ThrowErrorManager(), 53.235 isStrict(), 53.236 - functionNodeId - (isProgram ? 0 : 1), 53.237 lineNumber - 1, 53.238 context.getLogger(Parser.class)); // source starts at line 0, so even though lineNumber is the correct declaration line, back off one to make it exclusive 53.239 53.240 - if (isAnonymous) { 53.241 + if (getFunctionFlag(FunctionNode.IS_ANONYMOUS)) { 53.242 parser.setFunctionName(functionName); 53.243 } 53.244 + parser.setReparsedFunction(this); 53.245 53.246 - final FunctionNode program = parser.parse(CompilerConstants.PROGRAM.symbolName(), descPosition, Token.descLength(token), true); 53.247 - // Parser generates a program AST even if we're recompiling a single function, so when we are only recompiling a 53.248 - // single function, extract it from the program. 53.249 - return (isProgram ? program : extractFunctionFromScript(program)).setName(null, functionName); 53.250 + final FunctionNode program = parser.parse(CompilerConstants.PROGRAM.symbolName(), descPosition, 53.251 + Token.descLength(token), true); 53.252 + // Parser generates a program AST even if we're recompiling a single function, so when we are only 53.253 + // recompiling a single function, extract it from the program. 53.254 + return (isProgram() ? program : extractFunctionFromScript(program)).setName(null, functionName); 53.255 + } 53.256 + 53.257 + private boolean getFunctionFlag(final int flag) { 53.258 + return (functionFlags & flag) != 0; 53.259 + } 53.260 + 53.261 + private boolean isProgram() { 53.262 + return getFunctionFlag(FunctionNode.IS_PROGRAM); 53.263 } 53.264 53.265 TypeMap typeMap(final MethodType fnCallSiteType) { 53.266 @@ -394,6 +419,7 @@ 53.267 context.getEnv(), 53.268 installer, 53.269 functionNode.getSource(), // source 53.270 + context.getErrorManager(), 53.271 isStrict() | functionNode.isStrict(), // is strict 53.272 true, // is on demand 53.273 this, // compiledFunction, i.e. this RecompilableScriptFunctionData 53.274 @@ -545,7 +571,7 @@ 53.275 assert fns.size() == 1 : "got back more than one method in recompilation"; 53.276 final FunctionNode f = fns.iterator().next(); 53.277 assert f.getId() == functionNodeId; 53.278 - if (!isDeclared && f.isDeclared()) { 53.279 + if (!getFunctionFlag(FunctionNode.IS_DECLARED) && f.isDeclared()) { 53.280 return f.clearFlag(null, FunctionNode.IS_DECLARED); 53.281 } 53.282 return f; 53.283 @@ -668,7 +694,15 @@ 53.284 53.285 @Override 53.286 public boolean needsCallee() { 53.287 - return needsCallee; 53.288 + return getFunctionFlag(FunctionNode.NEEDS_CALLEE); 53.289 + } 53.290 + 53.291 + /** 53.292 + * Returns the {@link FunctionNode} flags associated with this function data. 53.293 + * @return the {@link FunctionNode} flags associated with this function data. 53.294 + */ 53.295 + public int getFunctionFlags() { 53.296 + return functionFlags; 53.297 } 53.298 53.299 @Override 53.300 @@ -720,21 +754,6 @@ 53.301 } 53.302 53.303 /** 53.304 - * Get the uppermost parent, the program, for this data 53.305 - * @return program 53.306 - */ 53.307 - public RecompilableScriptFunctionData getProgram() { 53.308 - RecompilableScriptFunctionData program = this; 53.309 - while (true) { 53.310 - final RecompilableScriptFunctionData p = program.getParent(); 53.311 - if (p == null) { 53.312 - return program; 53.313 - } 53.314 - program = p; 53.315 - } 53.316 - } 53.317 - 53.318 - /** 53.319 * Check whether a certain name is a global symbol, i.e. only exists as defined 53.320 * in outermost scope and not shadowed by being parameter or assignment in inner 53.321 * scopes
54.1 --- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Thu Sep 11 15:34:13 2014 -0700 54.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Tue Sep 16 13:59:37 2014 -0700 54.3 @@ -94,6 +94,9 @@ 54.4 /** Use single Global instance per jsr223 engine instance. */ 54.5 public final boolean _global_per_engine; 54.6 54.7 + /** Enable experimental ECMAScript 6 features. */ 54.8 + public final boolean _es6; 54.9 + 54.10 /** Argument passed to compile only if optimistic compilation should take place */ 54.11 public static final String COMPILE_ONLY_OPTIMISTIC_ARG = "optimistic"; 54.12 54.13 @@ -258,6 +261,15 @@ 54.14 _version = options.getBoolean("version"); 54.15 _verify_code = options.getBoolean("verify.code"); 54.16 54.17 + final String language = options.getString("language"); 54.18 + if (language == null || language.equals("es5")) { 54.19 + _es6 = false; 54.20 + } else if (language.equals("es6")) { 54.21 + _es6 = true; 54.22 + } else { 54.23 + throw new RuntimeException("Unsupported language: " + language); 54.24 + } 54.25 + 54.26 String dir = null; 54.27 String func = null; 54.28 final String pc = options.getString("print.code");
55.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Sep 11 15:34:13 2014 -0700 55.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java Tue Sep 16 13:59:37 2014 -0700 55.3 @@ -36,6 +36,7 @@ 55.4 import java.lang.invoke.MethodType; 55.5 import java.lang.invoke.SwitchPoint; 55.6 import java.util.Collections; 55.7 + 55.8 import jdk.internal.dynalink.CallSiteDescriptor; 55.9 import jdk.internal.dynalink.linker.GuardedInvocation; 55.10 import jdk.internal.dynalink.linker.LinkRequest; 55.11 @@ -44,6 +45,9 @@ 55.12 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 55.13 import jdk.nashorn.internal.objects.Global; 55.14 import jdk.nashorn.internal.objects.NativeFunction; 55.15 +import jdk.nashorn.internal.runtime.ScriptFunctionData; 55.16 +import jdk.nashorn.internal.runtime.ScriptObject; 55.17 +import jdk.nashorn.internal.runtime.ScriptRuntime; 55.18 import jdk.nashorn.internal.runtime.linker.Bootstrap; 55.19 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; 55.20 55.21 @@ -621,6 +625,23 @@ 55.22 appliedType = appliedType.changeParameterType(1, Object.class); 55.23 } 55.24 55.25 + /* 55.26 + * dropArgs is a synthetic method handle that contains any args that we need to 55.27 + * get rid of that come after the arguments array in the apply case. We adapt 55.28 + * the callsite to ask for 3 args only and then dropArguments on the method handle 55.29 + * to make it fit the extraneous args. 55.30 + */ 55.31 + MethodType dropArgs = MH.type(void.class); 55.32 + if (isApply && !isFailedApplyToCall) { 55.33 + final int pc = appliedType.parameterCount(); 55.34 + for (int i = 3; i < pc; i++) { 55.35 + dropArgs = dropArgs.appendParameterTypes(appliedType.parameterType(i)); 55.36 + } 55.37 + if (pc > 3) { 55.38 + appliedType = appliedType.dropParameterTypes(3, pc); 55.39 + } 55.40 + } 55.41 + 55.42 if (isApply || isFailedApplyToCall) { 55.43 if (passesArgs) { 55.44 // R(this, args) => R(this, Object[]) 55.45 @@ -702,6 +723,15 @@ 55.46 } 55.47 inv = MH.dropArguments(inv, 0, applyFnType); 55.48 55.49 + /* 55.50 + * Dropargs can only be non-()V in the case of isApply && !isFailedApplyToCall, which 55.51 + * is when we need to add arguments to the callsite to catch and ignore the synthetic 55.52 + * extra args that someone has added to the command line. 55.53 + */ 55.54 + for (int i = 0; i < dropArgs.parameterCount(); i++) { 55.55 + inv = MH.dropArguments(inv, 4 + i, dropArgs.parameterType(i)); 55.56 + } 55.57 + 55.58 MethodHandle guard = appliedInvocation.getGuard(); 55.59 // If the guard checks the value of "this" but we aren't passing thisArg, insert the default one 55.60 if (!passesThis && guard.type().parameterCount() > 1) {
56.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Thu Sep 11 15:34:13 2014 -0700 56.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java Tue Sep 16 13:59:37 2014 -0700 56.3 @@ -90,8 +90,6 @@ 56.4 public static final int USES_THIS = 1 << 4; 56.5 /** Is this a variable arity function? */ 56.6 public static final int IS_VARIABLE_ARITY = 1 << 5; 56.7 - /** Is this declared in a dynamic context */ 56.8 - public static final int IN_DYNAMIC_CONTEXT = 1 << 6; 56.9 56.10 /** Flag for strict or built-in functions */ 56.11 public static final int IS_STRICT_OR_BUILTIN = IS_STRICT | IS_BUILTIN;
57.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Sep 11 15:34:13 2014 -0700 57.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Tue Sep 16 13:59:37 2014 -0700 57.3 @@ -158,6 +158,7 @@ 57.4 57.5 static final MethodHandle MEGAMORPHIC_GET = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class); 57.6 static final MethodHandle GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class); 57.7 + static final MethodHandle DECLARE_AND_SET = findOwnMH_V("declareAndSet", void.class, String.class, Object.class); 57.8 57.9 private static final MethodHandle TRUNCATINGFILTER = findOwnMH_S("truncatingFilter", Object[].class, int.class, Object[].class); 57.10 private static final MethodHandle KNOWNFUNCPROPGUARDSELF = findOwnMH_S("knownFunctionPropertyGuardSelf", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, ScriptFunction.class); 57.11 @@ -1049,7 +1050,7 @@ 57.12 } 57.13 57.14 private static int getIntValue(final FindProperty find, final int programPoint) { 57.15 - final MethodHandle getter = find.getGetter(int.class, programPoint); 57.16 + final MethodHandle getter = find.getGetter(int.class, programPoint, null); 57.17 if (getter != null) { 57.18 try { 57.19 return (int)getter.invokeExact((Object)find.getGetterReceiver()); 57.20 @@ -1064,7 +1065,7 @@ 57.21 } 57.22 57.23 private static long getLongValue(final FindProperty find, final int programPoint) { 57.24 - final MethodHandle getter = find.getGetter(long.class, programPoint); 57.25 + final MethodHandle getter = find.getGetter(long.class, programPoint, null); 57.26 if (getter != null) { 57.27 try { 57.28 return (long)getter.invokeExact((Object)find.getGetterReceiver()); 57.29 @@ -1079,7 +1080,7 @@ 57.30 } 57.31 57.32 private static double getDoubleValue(final FindProperty find, final int programPoint) { 57.33 - final MethodHandle getter = find.getGetter(double.class, programPoint); 57.34 + final MethodHandle getter = find.getGetter(double.class, programPoint, null); 57.35 if (getter != null) { 57.36 try { 57.37 return (double)getter.invokeExact((Object)find.getGetterReceiver()); 57.38 @@ -1970,7 +1971,7 @@ 57.39 } 57.40 } 57.41 57.42 - final GuardedInvocation cinv = Global.getConstants().findGetMethod(find, this, desc, request, operator); 57.43 + final GuardedInvocation cinv = Global.getConstants().findGetMethod(find, this, desc); 57.44 if (cinv != null) { 57.45 return cinv; 57.46 } 57.47 @@ -1982,7 +1983,7 @@ 57.48 NashornCallSiteDescriptor.getProgramPoint(desc) : 57.49 UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 57.50 57.51 - mh = find.getGetter(returnType, programPoint); 57.52 + mh = find.getGetter(returnType, programPoint, request); 57.53 // Get the appropriate guard for this callsite and property. 57.54 final MethodHandle guard = NashornGuards.getGuard(this, property, desc, explicitInstanceOfCheck); 57.55 final ScriptObject owner = find.getOwner(); 57.56 @@ -1994,8 +1995,9 @@ 57.57 mh = Lookup.emptyGetter(returnType); 57.58 protoSwitchPoint = getProtoSwitchPoint(name, owner); 57.59 } else if (!find.isSelf()) { 57.60 - assert mh.type().returnType().equals(returnType) : "returntype mismatch for getter " + mh.type().returnType() + " != " + returnType; 57.61 - if (!property.hasGetterFunction(owner)) { 57.62 + assert mh.type().returnType().equals(returnType) : 57.63 + "return type mismatch for getter " + mh.type().returnType() + " != " + returnType; 57.64 + if (!(property instanceof UserAccessorProperty)) { 57.65 // Add a filter that replaces the self object with the prototype owning the property. 57.66 mh = addProtoFilter(mh, find.getProtoChainLength()); 57.67 } 57.68 @@ -2027,6 +2029,22 @@ 57.69 return isMethod ? getNoSuchMethod(key, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, INVALID_PROGRAM_POINT); 57.70 } 57.71 57.72 + // Marks a property as declared and sets its value. Used as slow path for block-scoped LET and CONST 57.73 + @SuppressWarnings("unused") 57.74 + private void declareAndSet(final String key, final Object value) { 57.75 + final PropertyMap map = getMap(); 57.76 + final FindProperty find = findProperty(key, false); 57.77 + assert find != null; 57.78 + 57.79 + final Property property = find.getProperty(); 57.80 + assert property != null; 57.81 + assert property.needsDeclaration(); 57.82 + 57.83 + final PropertyMap newMap = map.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION)); 57.84 + setMap(newMap); 57.85 + set(key, value, true); 57.86 + } 57.87 + 57.88 /** 57.89 * Find the appropriate GETINDEX method for an invoke dynamic call. 57.90 * 57.91 @@ -2140,7 +2158,7 @@ 57.92 } 57.93 57.94 if (find != null) { 57.95 - if (!find.getProperty().isWritable()) { 57.96 + if (!find.getProperty().isWritable() && !NashornCallSiteDescriptor.isDeclaration(desc)) { 57.97 // Existing, non-writable property 57.98 return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true); 57.99 } 57.100 @@ -2150,7 +2168,7 @@ 57.101 } 57.102 } 57.103 57.104 - final GuardedInvocation inv = new SetMethodCreator(this, find, desc, explicitInstanceOfCheck).createGuardedInvocation(); 57.105 + final GuardedInvocation inv = new SetMethodCreator(this, find, desc, request).createGuardedInvocation(); 57.106 57.107 final GuardedInvocation cinv = Global.getConstants().findSetMethod(find, this, inv, desc, request); 57.108 if (cinv != null) { 57.109 @@ -2303,13 +2321,13 @@ 57.110 find.isSelf()? 57.111 getKnownFunctionPropertyGuardSelf( 57.112 getMap(), 57.113 - find.getGetter(Object.class, INVALID_PROGRAM_POINT), 57.114 + find.getGetter(Object.class, INVALID_PROGRAM_POINT, request), 57.115 func) 57.116 : 57.117 //TODO this always does a scriptobject check 57.118 getKnownFunctionPropertyGuardProto( 57.119 getMap(), 57.120 - find.getGetter(Object.class, INVALID_PROGRAM_POINT), 57.121 + find.getGetter(Object.class, INVALID_PROGRAM_POINT, request), 57.122 find.getProtoChainLength(), 57.123 func), 57.124 getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
58.1 --- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Thu Sep 11 15:34:13 2014 -0700 58.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Tue Sep 16 13:59:37 2014 -0700 58.3 @@ -108,6 +108,11 @@ 58.4 public static final Call APPLY = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "apply", Object.class, ScriptFunction.class, Object.class, Object[].class); 58.5 58.6 /** 58.7 + * Throws a reference error for an undefined variable. 58.8 + */ 58.9 + public static final Call THROW_REFERENCE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwReferenceError", void.class, String.class); 58.10 + 58.11 + /** 58.12 * Converts a switch tag value to a simple integer. deflt value if it can't. 58.13 * 58.14 * @param tag Switch statement tag value. 58.15 @@ -382,6 +387,15 @@ 58.16 } 58.17 58.18 /** 58.19 + * Throws a reference error for an undefined variable. 58.20 + * 58.21 + * @param name the variable name 58.22 + */ 58.23 + public static void throwReferenceError(final String name) { 58.24 + throw referenceError("not.defined", name); 58.25 + } 58.26 + 58.27 + /** 58.28 * Call a script function as a constructor with given args. 58.29 * 58.30 * @param target ScriptFunction object.
59.1 --- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Thu Sep 11 15:34:13 2014 -0700 59.2 +++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Tue Sep 16 13:59:37 2014 -0700 59.3 @@ -33,6 +33,7 @@ 59.4 import java.lang.invoke.SwitchPoint; 59.5 import jdk.internal.dynalink.CallSiteDescriptor; 59.6 import jdk.internal.dynalink.linker.GuardedInvocation; 59.7 +import jdk.internal.dynalink.linker.LinkRequest; 59.8 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; 59.9 import jdk.nashorn.internal.runtime.linker.NashornGuards; 59.10 59.11 @@ -48,7 +49,7 @@ 59.12 private final FindProperty find; 59.13 private final CallSiteDescriptor desc; 59.14 private final Class<?> type; 59.15 - private final boolean explicitInstanceOfCheck; 59.16 + private final LinkRequest request; 59.17 59.18 /** 59.19 * Creates a new property setter method creator. 59.20 @@ -56,14 +57,15 @@ 59.21 * @param find a result of a {@link ScriptObject#findProperty(String, boolean)} on the object for the property we 59.22 * want to create a setter for. Can be null if the property does not yet exist on the object. 59.23 * @param desc the descriptor of the call site that triggered the property setter lookup 59.24 + * @param request the link request 59.25 */ 59.26 - SetMethodCreator(final ScriptObject sobj, final FindProperty find, final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck) { 59.27 - this.sobj = sobj; 59.28 - this.map = sobj.getMap(); 59.29 - this.find = find; 59.30 - this.desc = desc; 59.31 - this.type = desc.getMethodType().parameterType(1); 59.32 - this.explicitInstanceOfCheck = explicitInstanceOfCheck; 59.33 + SetMethodCreator(final ScriptObject sobj, final FindProperty find, final CallSiteDescriptor desc, final LinkRequest request) { 59.34 + this.sobj = sobj; 59.35 + this.map = sobj.getMap(); 59.36 + this.find = find; 59.37 + this.desc = desc; 59.38 + this.type = desc.getMethodType().parameterType(1); 59.39 + this.request = request; 59.40 59.41 } 59.42 59.43 @@ -111,6 +113,7 @@ 59.44 // getGuard() and getException() either both return null, or neither does. The reason for that is that now 59.45 // getGuard returns a map guard that casts its argument to ScriptObject, and if that fails, we need to 59.46 // relink on ClassCastException. 59.47 + final boolean explicitInstanceOfCheck = NashornGuards.explicitInstanceOfCheck(desc, request); 59.48 return new GuardedInvocation(methodHandle, NashornGuards.getGuard(sobj, property, desc, explicitInstanceOfCheck), 59.49 (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class); 59.50 } 59.51 @@ -140,13 +143,36 @@ 59.52 59.53 private SetMethod createExistingPropertySetter() { 59.54 final Property property = find.getProperty(); 59.55 - final MethodHandle methodHandle = find.getSetter(type, NashornCallSiteDescriptor.isStrict(desc)); 59.56 + final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc); 59.57 + final MethodHandle methodHandle; 59.58 + 59.59 + if (NashornCallSiteDescriptor.isDeclaration(desc)) { 59.60 + assert property.needsDeclaration(); 59.61 + // This is a LET or CONST being declared. The property is already there but flagged as needing declaration. 59.62 + // We create a new PropertyMap with the flag removed. The map is installed with a fast compare-and-set 59.63 + // method if the pre-callsite map is stable (which should be the case for function scopes except for 59.64 + // non-strict functions containing eval() with var). Otherwise we have to use a slow setter that creates 59.65 + // a new PropertyMap on the fly. 59.66 + final PropertyMap oldMap = getMap(); 59.67 + final Property newProperty = property.removeFlags(Property.NEEDS_DECLARATION); 59.68 + final PropertyMap newMap = oldMap.replaceProperty(property, newProperty); 59.69 + final MethodHandle fastSetter = find.replaceProperty(newProperty).getSetter(type, isStrict, request); 59.70 + final MethodHandle slowSetter = MH.insertArguments(ScriptObject.DECLARE_AND_SET, 1, getName()).asType(fastSetter.type()); 59.71 + 59.72 + // cas map used as guard, if true that means we can do the set fast 59.73 + MethodHandle casMap = MH.insertArguments(ScriptObject.CAS_MAP, 1, oldMap, newMap); 59.74 + casMap = MH.dropArguments(casMap, 1, type); 59.75 + casMap = MH.asType(casMap, casMap.type().changeParameterType(0, Object.class)); 59.76 + methodHandle = MH.guardWithTest(casMap, fastSetter, slowSetter); 59.77 + } else { 59.78 + methodHandle = find.getSetter(type, isStrict, request); 59.79 + } 59.80 59.81 assert methodHandle != null; 59.82 assert property != null; 59.83 59.84 final MethodHandle boundHandle; 59.85 - if (!property.hasSetterFunction(find.getOwner()) && find.isInherited()) { 59.86 + if (!(property instanceof UserAccessorProperty) && find.isInherited()) { 59.87 boundHandle = ScriptObject.addProtoFilter(methodHandle, find.getProtoChainLength()); 59.88 } else { 59.89 boundHandle = methodHandle;
60.1 --- a/src/jdk/nashorn/internal/runtime/Timing.java Thu Sep 11 15:34:13 2014 -0700 60.2 +++ b/src/jdk/nashorn/internal/runtime/Timing.java Tue Sep 16 13:59:37 2014 -0700 60.3 @@ -33,6 +33,8 @@ 60.4 import java.util.Map; 60.5 import java.util.concurrent.TimeUnit; 60.6 import java.util.function.Supplier; 60.7 + 60.8 +import jdk.nashorn.internal.codegen.CompileUnit; 60.9 import jdk.nashorn.internal.runtime.logging.DebugLogger; 60.10 import jdk.nashorn.internal.runtime.logging.Loggable; 60.11 import jdk.nashorn.internal.runtime.logging.Logger; 60.12 @@ -189,7 +191,7 @@ 60.13 maxKeyLength++; 60.14 60.15 final StringBuilder sb = new StringBuilder(); 60.16 - sb.append("Accumulated complation phase Timings:\n\n"); 60.17 + sb.append("Accumulated compilation phase timings:\n\n"); 60.18 for (final Map.Entry<String, Long> entry : timings.entrySet()) { 60.19 int len; 60.20 60.21 @@ -224,6 +226,9 @@ 60.22 append((int)(knownTime * 100.0 / total)). 60.23 append("%])"); 60.24 60.25 + sb.append("\n\nEmitted compile units: "). 60.26 + append(CompileUnit.getEmittedUnitCount()); 60.27 + 60.28 return sb.toString(); 60.29 } 60.30
61.1 --- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Thu Sep 11 15:34:13 2014 -0700 61.2 +++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Tue Sep 16 13:59:37 2014 -0700 61.3 @@ -34,8 +34,8 @@ 61.4 61.5 import java.lang.invoke.MethodHandle; 61.6 import java.lang.invoke.MethodHandles; 61.7 +import java.lang.invoke.MethodType; 61.8 import java.util.concurrent.Callable; 61.9 -import jdk.nashorn.internal.codegen.CompilerConstants; 61.10 import jdk.nashorn.internal.lookup.Lookup; 61.11 import jdk.nashorn.internal.runtime.linker.Bootstrap; 61.12 61.13 @@ -48,7 +48,7 @@ 61.14 61.15 private static final long serialVersionUID = -5928687246526840321L; 61.16 61.17 - static class Accessors { 61.18 + static final class Accessors { 61.19 Object getter; 61.20 Object setter; 61.21 61.22 @@ -67,20 +67,20 @@ 61.23 } 61.24 } 61.25 61.26 + private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); 61.27 + 61.28 /** Getter method handle */ 61.29 - private final static CompilerConstants.Call USER_ACCESSOR_GETTER = staticCall(MethodHandles.lookup(), UserAccessorProperty.class, 61.30 - "userAccessorGetter", Object.class, Accessors.class, Object.class); 61.31 + private final static MethodHandle INVOKE_GETTER_ACCESSOR = findOwnMH_S("invokeGetterAccessor", Object.class, Accessors.class, Object.class); 61.32 61.33 /** Setter method handle */ 61.34 - private final static CompilerConstants.Call USER_ACCESSOR_SETTER = staticCall(MethodHandles.lookup(), UserAccessorProperty.class, 61.35 - "userAccessorSetter", void.class, Accessors.class, String.class, Object.class, Object.class); 61.36 + private final static MethodHandle INVOKE_SETTER_ACCESSOR = findOwnMH_S("invokeSetterAccessor", void.class, Accessors.class, String.class, Object.class, Object.class); 61.37 61.38 /** Dynamic invoker for getter */ 61.39 - private static final Object INVOKE_UA_GETTER = new Object(); 61.40 + private static final Object GETTER_INVOKER_KEY = new Object(); 61.41 61.42 private static MethodHandle getINVOKE_UA_GETTER() { 61.43 61.44 - return Context.getGlobal().getDynamicInvoker(INVOKE_UA_GETTER, 61.45 + return Context.getGlobal().getDynamicInvoker(GETTER_INVOKER_KEY, 61.46 new Callable<MethodHandle>() { 61.47 @Override 61.48 public MethodHandle call() { 61.49 @@ -91,10 +91,10 @@ 61.50 } 61.51 61.52 /** Dynamic invoker for setter */ 61.53 - private static Object INVOKE_UA_SETTER = new Object(); 61.54 + private static Object SETTER_INVOKER_KEY = new Object(); 61.55 61.56 private static MethodHandle getINVOKE_UA_SETTER() { 61.57 - return Context.getGlobal().getDynamicInvoker(INVOKE_UA_SETTER, 61.58 + return Context.getGlobal().getDynamicInvoker(SETTER_INVOKER_KEY, 61.59 new Callable<MethodHandle>() { 61.60 @Override 61.61 public MethodHandle call() { 61.62 @@ -190,7 +190,7 @@ 61.63 61.64 @Override 61.65 public Object getObjectValue(final ScriptObject self, final ScriptObject owner) { 61.66 - return userAccessorGetter(getAccessors((owner != null) ? owner : self), self); 61.67 + return invokeGetterAccessor(getAccessors((owner != null) ? owner : self), self); 61.68 } 61.69 61.70 @Override 61.71 @@ -210,13 +210,13 @@ 61.72 61.73 @Override 61.74 public void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) { 61.75 - userAccessorSetter(getAccessors((owner != null) ? owner : self), strict ? getKey() : null, self, value); 61.76 + invokeSetterAccessor(getAccessors((owner != null) ? owner : self), strict ? getKey() : null, self, value); 61.77 } 61.78 61.79 @Override 61.80 public MethodHandle getGetter(final Class<?> type) { 61.81 //this returns a getter on the format (Accessors, Object receiver) 61.82 - return Lookup.filterReturnType(USER_ACCESSOR_GETTER.methodHandle(), type); 61.83 + return Lookup.filterReturnType(INVOKE_GETTER_ACCESSOR, type); 61.84 } 61.85 61.86 @Override 61.87 @@ -260,7 +260,7 @@ 61.88 61.89 @Override 61.90 public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) { 61.91 - return USER_ACCESSOR_SETTER.methodHandle(); 61.92 + return INVOKE_SETTER_ACCESSOR; 61.93 } 61.94 61.95 @Override 61.96 @@ -269,11 +269,21 @@ 61.97 return (value instanceof ScriptFunction) ? (ScriptFunction)value : null; 61.98 } 61.99 61.100 + /** 61.101 + * Get the getter for the {@code Accessors} object. 61.102 + * This is the the super {@code Object} type getter with {@code Accessors} return type. 61.103 + * 61.104 + * @return The getter handle for the Accessors 61.105 + */ 61.106 + MethodHandle getAccessorsGetter() { 61.107 + return super.getGetter(Object.class).asType(MethodType.methodType(Accessors.class, Object.class)); 61.108 + } 61.109 + 61.110 // User defined getter and setter are always called by "dyn:call". Note that the user 61.111 // getter/setter may be inherited. If so, proto is bound during lookup. In either 61.112 // inherited or self case, slot is also bound during lookup. Actual ScriptFunction 61.113 // to be called is retrieved everytime and applied. 61.114 - static Object userAccessorGetter(final Accessors gs, final Object self) { 61.115 + private static Object invokeGetterAccessor(final Accessors gs, final Object self) { 61.116 final Object func = gs.getter; 61.117 if (func instanceof ScriptFunction) { 61.118 try { 61.119 @@ -288,7 +298,7 @@ 61.120 return UNDEFINED; 61.121 } 61.122 61.123 - static void userAccessorSetter(final Accessors gs, final String name, final Object self, final Object value) { 61.124 + private static void invokeSetterAccessor(final Accessors gs, final String name, final Object self, final Object value) { 61.125 final Object func = gs.setter; 61.126 if (func instanceof ScriptFunction) { 61.127 try { 61.128 @@ -303,4 +313,8 @@ 61.129 } 61.130 } 61.131 61.132 + private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) { 61.133 + return MH.findStatic(LOOKUP, UserAccessorProperty.class, name, MH.type(rtype, types)); 61.134 + } 61.135 + 61.136 }
62.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Thu Sep 11 15:34:13 2014 -0700 62.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Tue Sep 16 13:59:37 2014 -0700 62.3 @@ -628,18 +628,20 @@ 62.4 Class<?> widest = Integer.class; 62.5 62.6 for (final Object item : items) { 62.7 - final Class<?> itemClass = item == null ? null : item.getClass(); 62.8 + if (item == null) { 62.9 + return Object.class; 62.10 + } 62.11 + final Class<?> itemClass = item.getClass(); 62.12 if (itemClass == Long.class) { 62.13 if (widest == Integer.class) { 62.14 widest = Long.class; 62.15 } 62.16 - } else if (itemClass == Double.class) { 62.17 + } else if (itemClass == Double.class || itemClass == Float.class) { 62.18 if (widest == Integer.class || widest == Long.class) { 62.19 widest = Double.class; 62.20 } 62.21 - } else if (!(item instanceof Number)) { 62.22 - widest = Object.class; 62.23 - break; 62.24 + } else if (itemClass != Integer.class && itemClass != Short.class && itemClass != Byte.class) { 62.25 + return Object.class; 62.26 } 62.27 } 62.28
63.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Thu Sep 11 15:34:13 2014 -0700 63.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Tue Sep 16 13:59:37 2014 -0700 63.3 @@ -54,23 +54,25 @@ 63.4 public static final int CALLSITE_OPTIMISTIC = 1 << 3; 63.5 /** Is this really an apply that we try to call as a call? */ 63.6 public static final int CALLSITE_APPLY_TO_CALL = 1 << 4; 63.7 + /** Does this a callsite for a variable declaration? */ 63.8 + public static final int CALLSITE_DECLARE = 1 << 5; 63.9 63.10 /** Flags that the call site is profiled; Contexts that have {@code "profile.callsites"} boolean property set emit 63.11 * code where call sites have this flag set. */ 63.12 - public static final int CALLSITE_PROFILE = 1 << 5; 63.13 + public static final int CALLSITE_PROFILE = 1 << 6; 63.14 /** Flags that the call site is traced; Contexts that have {@code "trace.callsites"} property set emit code where 63.15 * call sites have this flag set. */ 63.16 - public static final int CALLSITE_TRACE = 1 << 6; 63.17 + public static final int CALLSITE_TRACE = 1 << 7; 63.18 /** Flags that the call site linkage miss (and thus, relinking) is traced; Contexts that have the keyword 63.19 * {@code "miss"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */ 63.20 - public static final int CALLSITE_TRACE_MISSES = 1 << 7; 63.21 + public static final int CALLSITE_TRACE_MISSES = 1 << 8; 63.22 /** Flags that entry/exit to/from the method linked at call site are traced; Contexts that have the keyword 63.23 * {@code "enterexit"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */ 63.24 - public static final int CALLSITE_TRACE_ENTEREXIT = 1 << 8; 63.25 + public static final int CALLSITE_TRACE_ENTEREXIT = 1 << 9; 63.26 /** Flags that values passed as arguments to and returned from the method linked at call site are traced; Contexts 63.27 * that have the keyword {@code "values"} in their {@code "trace.callsites"} property emit code where call sites 63.28 * have this flag set. */ 63.29 - public static final int CALLSITE_TRACE_VALUES = 1 << 9; 63.30 + public static final int CALLSITE_TRACE_VALUES = 1 << 10; 63.31 63.32 //we could have more tracing flags here, for example CALLSITE_TRACE_SCOPE, but bits are a bit precious 63.33 //right now given the program points 63.34 @@ -82,10 +84,10 @@ 63.35 * TODO: rethink if we need the various profile/trace flags or the linker can use the Context instead to query its 63.36 * trace/profile settings. 63.37 */ 63.38 - public static final int CALLSITE_PROGRAM_POINT_SHIFT = 10; 63.39 + public static final int CALLSITE_PROGRAM_POINT_SHIFT = 11; 63.40 63.41 /** 63.42 - * Maximum program point value. 22 bits should be enough for anyone 63.43 + * Maximum program point value. 21 bits should be enough for anyone 63.44 */ 63.45 public static final int MAX_PROGRAM_POINT_VALUE = (1 << 32 - CALLSITE_PROGRAM_POINT_SHIFT) - 1; 63.46 63.47 @@ -123,6 +125,9 @@ 63.48 assert (flags & CALLSITE_FAST_SCOPE) == 0 : "can't be fastscope without scope"; 63.49 sb.append("scope "); 63.50 } 63.51 + if ((flags & CALLSITE_DECLARE) != 0) { 63.52 + sb.append("declare "); 63.53 + } 63.54 } 63.55 if ((flags & CALLSITE_APPLY_TO_CALL) != 0) { 63.56 sb.append("apply2call "); 63.57 @@ -329,6 +334,15 @@ 63.58 } 63.59 63.60 /** 63.61 + * Does this callsite contain a declaration for its target? 63.62 + * @param desc descriptor 63.63 + * @return true if contains declaration 63.64 + */ 63.65 + public static boolean isDeclaration(final CallSiteDescriptor desc) { 63.66 + return isFlag(desc, CALLSITE_DECLARE); 63.67 + } 63.68 + 63.69 + /** 63.70 * Get a program point from a descriptor (must be optimistic) 63.71 * @param desc descriptor 63.72 * @return program point
64.1 --- a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Thu Sep 11 15:34:13 2014 -0700 64.2 +++ b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Tue Sep 16 13:59:37 2014 -0700 64.3 @@ -32,11 +32,10 @@ 64.4 import jdk.internal.dynalink.CallSiteDescriptor; 64.5 import jdk.internal.dynalink.linker.GuardedInvocation; 64.6 import jdk.internal.dynalink.linker.LinkRequest; 64.7 -import jdk.internal.dynalink.support.CallSiteDescriptorFactory; 64.8 import jdk.internal.dynalink.support.Guards; 64.9 -import jdk.nashorn.internal.lookup.Lookup; 64.10 import jdk.nashorn.internal.runtime.FindProperty; 64.11 import jdk.nashorn.internal.runtime.ScriptObject; 64.12 +import jdk.nashorn.internal.runtime.UserAccessorProperty; 64.13 64.14 /** 64.15 * Implements lookup of methods to link for dynamic operations on JavaScript primitive values (booleans, strings, and 64.16 @@ -86,15 +85,6 @@ 64.17 final ScriptObject wrappedReceiver, final MethodHandle wrapFilter, 64.18 final MethodHandle protoFilter) { 64.19 final CallSiteDescriptor desc = request.getCallSiteDescriptor(); 64.20 - final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); 64.21 - if ("setProp".equals(operator) || "setElem".equals(operator)) { 64.22 - final MethodType type = desc.getMethodType(); 64.23 - MethodHandle method = MH.asType(Lookup.EMPTY_SETTER, MH.type(void.class, Object.class, type.parameterType(1))); 64.24 - if (type.parameterCount() == 3) { 64.25 - method = MH.dropArguments(method, 2, type.parameterType(2)); 64.26 - } 64.27 - return new GuardedInvocation(method, guard); 64.28 - } 64.29 64.30 if(desc.getNameTokenCount() > 2) { 64.31 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); 64.32 @@ -102,7 +92,7 @@ 64.33 if(find == null) { 64.34 // Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it. 64.35 return null; 64.36 - } else if (find.isInherited() && !find.getProperty().hasGetterFunction(find.getOwner())) { 64.37 + } else if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) { 64.38 // If property is found in the prototype object bind the method handle directly to 64.39 // the proto filter instead of going through wrapper instantiation below. 64.40 final ScriptObject proto = wrappedReceiver.getProto();
65.1 --- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties Thu Sep 11 15:34:13 2014 -0700 65.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties Tue Sep 16 13:59:37 2014 -0700 65.3 @@ -58,6 +58,7 @@ 65.4 parser.error.regex.repeated.flag=Repeated RegExp flag: {0} 65.5 parser.error.regex.syntax={0} 65.6 parser.error.trailing.comma.in.json=Trailing comma is not allowed in JSON 65.7 +parser.error.missing.const.assignment=Missing assignment to constant "{0}" 65.8 65.9 # strict mode error messages 65.10 parser.error.strict.no.with="with" statement cannot be used in strict mode 65.11 @@ -162,6 +163,8 @@ 65.12 65.13 syntax.error.invalid.json=Invalid JSON: {0} 65.14 syntax.error.strict.cant.delete=cannot delete "{0}" in strict mode 65.15 +syntax.error.redeclare.variable=Variable "{0}" has already been declared 65.16 +syntax.error.assign.constant=Assignment to constant "{0}" 65.17 65.18 io.error.cant.write=cannot write "{0}" 65.19 config.error.no.dest=no destination directory supplied
66.1 --- a/src/jdk/nashorn/internal/runtime/resources/Options.properties Thu Sep 11 15:34:13 2014 -0700 66.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Options.properties Tue Sep 16 13:59:37 2014 -0700 66.3 @@ -329,6 +329,14 @@ 66.4 desc="Enable scripting features." \ 66.5 } 66.6 66.7 +nashorn.option.language = { \ 66.8 + name="--language", \ 66.9 + type=String, \ 66.10 + params=[es5|es6], \ 66.11 + default=es5, \ 66.12 + desc="Specify ECMAScript language version." \ 66.13 +} 66.14 + 66.15 nashorn.option.stdout = { \ 66.16 name="--stdout", \ 66.17 is_undocumented=true, \
67.1 --- a/src/jdk/nashorn/tools/Shell.java Thu Sep 11 15:34:13 2014 -0700 67.2 +++ b/src/jdk/nashorn/tools/Shell.java Tue Sep 16 13:59:37 2014 -0700 67.3 @@ -246,12 +246,21 @@ 67.4 67.5 // For each file on the command line. 67.6 for (final String fileName : files) { 67.7 - final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors, env._strict, FunctionNode.FIRST_FUNCTION_ID, 0, context.getLogger(Parser.class)).parse(); 67.8 + final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors, env._strict, 0, context.getLogger(Parser.class)).parse(); 67.9 67.10 if (errors.getNumberOfErrors() != 0) { 67.11 return COMPILATION_ERROR; 67.12 } 67.13 67.14 + new Compiler( 67.15 + context, 67.16 + env, 67.17 + null, //null - pass no code installer - this is compile only 67.18 + functionNode.getSource(), 67.19 + context.getErrorManager(), 67.20 + env._strict | functionNode.isStrict()). 67.21 + compile(functionNode, CompilationPhases.COMPILE_ALL_NO_INSTALL); 67.22 + 67.23 if (env._print_ast) { 67.24 context.getErr().println(new ASTWriter(functionNode)); 67.25 } 67.26 @@ -260,14 +269,9 @@ 67.27 context.getErr().println(new PrintVisitor(functionNode)); 67.28 } 67.29 67.30 - //null - pass no code installer - this is compile only 67.31 - new Compiler( 67.32 - context, 67.33 - env, 67.34 - null, 67.35 - functionNode.getSource(), 67.36 - env._strict | functionNode.isStrict()). 67.37 - compile(functionNode, CompilationPhases.COMPILE_ALL_NO_INSTALL); 67.38 + if (errors.getNumberOfErrors() != 0) { 67.39 + return COMPILATION_ERROR; 67.40 + } 67.41 } 67.42 } finally { 67.43 env.getOut().flush();
68.1 --- a/test/script/basic/JDK-8030182_2.js Thu Sep 11 15:34:13 2014 -0700 68.2 +++ b/test/script/basic/JDK-8030182_2.js Tue Sep 16 13:59:37 2014 -0700 68.3 @@ -41,6 +41,6 @@ 68.4 try { 68.5 eval(str); 68.6 } catch (e) { 68.7 - print(e.stack.replace(/\\/g, '/').replace(/<eval>@[0-9]+/, '<eval>@<id>')); 68.8 + print(e.stack.replace(/\\/g, '/')); 68.9 } 68.10
69.1 --- a/test/script/basic/JDK-8030182_2.js.EXPECTED Thu Sep 11 15:34:13 2014 -0700 69.2 +++ b/test/script/basic/JDK-8030182_2.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 69.3 @@ -1,3 +1,3 @@ 69.4 ReferenceError: "g" is not defined 69.5 - at <program> (test/script/basic/JDK-8030182_2.js#42:4<eval>@<id>:-1) 69.6 + at <program> (test/script/basic/JDK-8030182_2.js#42:4<eval>:-1) 69.7 at <program> (test/script/basic/JDK-8030182_2.js:42)
70.1 --- a/test/script/basic/JDK-8048079_1.js Thu Sep 11 15:34:13 2014 -0700 70.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 70.3 @@ -1,35 +0,0 @@ 70.4 -/* 70.5 - * Copyright (c) 2010, 2014, 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. 70.11 - * 70.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 70.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 70.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 70.15 - * version 2 for more details (a copy is included in the LICENSE file that 70.16 - * accompanied this code). 70.17 - * 70.18 - * You should have received a copy of the GNU General Public License version 70.19 - * 2 along with this work; if not, write to the Free Software Foundation, 70.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 70.21 - * 70.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 70.23 - * or visit www.oracle.com if you need additional information or have any 70.24 - * questions. 70.25 - */ 70.26 - 70.27 -/** 70.28 - * JDK-8048079: Persistent code store is broken after optimistic types merge 70.29 - * 70.30 - * @test 70.31 - * @run 70.32 - * @option -pcc 70.33 - * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache 70.34 - * @fork 70.35 - */ 70.36 - 70.37 -load(__DIR__ + 'prototype.js'); 70.38 -load(__DIR__ + 'yui.js');
71.1 --- a/test/script/basic/JDK-8048079_1.js.EXPECTED Thu Sep 11 15:34:13 2014 -0700 71.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 71.3 @@ -1,3 +0,0 @@ 71.4 -parsed and compiled ok prototype.js 71.5 -parsed and compiled ok yui-min.js 71.6 -parsed and compiled ok yui.js
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 72.2 +++ b/test/script/basic/JDK-8048079_1a.js Tue Sep 16 13:59:37 2014 -0700 72.3 @@ -0,0 +1,34 @@ 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. 72.11 + * 72.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 72.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 72.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 72.15 + * version 2 for more details (a copy is included in the LICENSE file that 72.16 + * accompanied this code). 72.17 + * 72.18 + * You should have received a copy of the GNU General Public License version 72.19 + * 2 along with this work; if not, write to the Free Software Foundation, 72.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 72.21 + * 72.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 72.23 + * or visit www.oracle.com if you need additional information or have any 72.24 + * questions. 72.25 + */ 72.26 + 72.27 +/** 72.28 + * JDK-8048079: Persistent code store is broken after optimistic types merge 72.29 + * 72.30 + * @test 72.31 + * @runif external.prototype 72.32 + * @option -pcc 72.33 + * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache 72.34 + * @fork 72.35 + */ 72.36 + 72.37 +load(__DIR__ + 'prototype.js');
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 73.2 +++ b/test/script/basic/JDK-8048079_1a.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 73.3 @@ -0,0 +1,1 @@ 73.4 +parsed and compiled ok prototype.js
74.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 74.2 +++ b/test/script/basic/JDK-8048079_1b.js Tue Sep 16 13:59:37 2014 -0700 74.3 @@ -0,0 +1,34 @@ 74.4 +/* 74.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 74.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 74.7 + * 74.8 + * This code is free software; you can redistribute it and/or modify it 74.9 + * under the terms of the GNU General Public License version 2 only, as 74.10 + * published by the Free Software Foundation. 74.11 + * 74.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 74.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 74.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 74.15 + * version 2 for more details (a copy is included in the LICENSE file that 74.16 + * accompanied this code). 74.17 + * 74.18 + * You should have received a copy of the GNU General Public License version 74.19 + * 2 along with this work; if not, write to the Free Software Foundation, 74.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 74.21 + * 74.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 74.23 + * or visit www.oracle.com if you need additional information or have any 74.24 + * questions. 74.25 + */ 74.26 + 74.27 +/** 74.28 + * JDK-8048079: Persistent code store is broken after optimistic types merge 74.29 + * 74.30 + * @test 74.31 + * @runif external.yui 74.32 + * @option -pcc 74.33 + * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache 74.34 + * @fork 74.35 + */ 74.36 + 74.37 +load(__DIR__ + 'yui.js');
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 75.2 +++ b/test/script/basic/JDK-8048079_1b.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 75.3 @@ -0,0 +1,2 @@ 75.4 +parsed and compiled ok yui-min.js 75.5 +parsed and compiled ok yui.js
76.1 --- a/test/script/basic/JDK-8048079_2.js Thu Sep 11 15:34:13 2014 -0700 76.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 76.3 @@ -1,35 +0,0 @@ 76.4 -/* 76.5 - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 76.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 76.7 - * 76.8 - * This code is free software; you can redistribute it and/or modify it 76.9 - * under the terms of the GNU General Public License version 2 only, as 76.10 - * published by the Free Software Foundation. 76.11 - * 76.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 76.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 76.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 76.15 - * version 2 for more details (a copy is included in the LICENSE file that 76.16 - * accompanied this code). 76.17 - * 76.18 - * You should have received a copy of the GNU General Public License version 76.19 - * 2 along with this work; if not, write to the Free Software Foundation, 76.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 76.21 - * 76.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 76.23 - * or visit www.oracle.com if you need additional information or have any 76.24 - * questions. 76.25 - */ 76.26 - 76.27 -/** 76.28 - * JDK-8048079: Persistent code store is broken after optimistic types merge 76.29 - * 76.30 - * @test 76.31 - * @run 76.32 - * @option -pcc 76.33 - * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache 76.34 - * @fork 76.35 - */ 76.36 - 76.37 -load(__DIR__ + 'prototype.js'); 76.38 -load(__DIR__ + 'yui.js');
77.1 --- a/test/script/basic/JDK-8048079_2.js.EXPECTED Thu Sep 11 15:34:13 2014 -0700 77.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 77.3 @@ -1,3 +0,0 @@ 77.4 -parsed and compiled ok prototype.js 77.5 -parsed and compiled ok yui-min.js 77.6 -parsed and compiled ok yui.js
78.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 78.2 +++ b/test/script/basic/JDK-8048079_2a.js Tue Sep 16 13:59:37 2014 -0700 78.3 @@ -0,0 +1,34 @@ 78.4 +/* 78.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 78.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 78.7 + * 78.8 + * This code is free software; you can redistribute it and/or modify it 78.9 + * under the terms of the GNU General Public License version 2 only, as 78.10 + * published by the Free Software Foundation. 78.11 + * 78.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 78.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 78.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 78.15 + * version 2 for more details (a copy is included in the LICENSE file that 78.16 + * accompanied this code). 78.17 + * 78.18 + * You should have received a copy of the GNU General Public License version 78.19 + * 2 along with this work; if not, write to the Free Software Foundation, 78.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 78.21 + * 78.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 78.23 + * or visit www.oracle.com if you need additional information or have any 78.24 + * questions. 78.25 + */ 78.26 + 78.27 +/** 78.28 + * JDK-8048079: Persistent code store is broken after optimistic types merge. 78.29 + * Same script as JDK-8048079_1a.js to exercise code cache. 78.30 + * @test 78.31 + * @runif external.prototype 78.32 + * @option -pcc 78.33 + * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache 78.34 + * @fork 78.35 + */ 78.36 + 78.37 +load(__DIR__ + 'prototype.js');
79.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 79.2 +++ b/test/script/basic/JDK-8048079_2a.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 79.3 @@ -0,0 +1,1 @@ 79.4 +parsed and compiled ok prototype.js
80.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 80.2 +++ b/test/script/basic/JDK-8048079_2b.js Tue Sep 16 13:59:37 2014 -0700 80.3 @@ -0,0 +1,34 @@ 80.4 +/* 80.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 80.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 80.7 + * 80.8 + * This code is free software; you can redistribute it and/or modify it 80.9 + * under the terms of the GNU General Public License version 2 only, as 80.10 + * published by the Free Software Foundation. 80.11 + * 80.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 80.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 80.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 80.15 + * version 2 for more details (a copy is included in the LICENSE file that 80.16 + * accompanied this code). 80.17 + * 80.18 + * You should have received a copy of the GNU General Public License version 80.19 + * 2 along with this work; if not, write to the Free Software Foundation, 80.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 80.21 + * 80.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 80.23 + * or visit www.oracle.com if you need additional information or have any 80.24 + * questions. 80.25 + */ 80.26 + 80.27 +/** 80.28 + * JDK-8048079: Persistent code store is broken after optimistic types merge 80.29 + * Same script as JDK-8048079_1b.js to exercise code cache again. 80.30 + * @test 80.31 + * @runif external.yui 80.32 + * @option -pcc 80.33 + * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache 80.34 + * @fork 80.35 + */ 80.36 + 80.37 +load(__DIR__ + 'yui.js');
81.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 81.2 +++ b/test/script/basic/JDK-8048079_2b.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 81.3 @@ -0,0 +1,2 @@ 81.4 +parsed and compiled ok yui-min.js 81.5 +parsed and compiled ok yui.js
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 82.2 +++ b/test/script/basic/JDK-8056129.js Tue Sep 16 13:59:37 2014 -0700 82.3 @@ -0,0 +1,42 @@ 82.4 +/* 82.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 82.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 82.7 + * 82.8 + * This code is free software; you can redistribute it and/or modify it 82.9 + * under the terms of the GNU General Public License version 2 only, as 82.10 + * published by the Free Software Foundation. 82.11 + * 82.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 82.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 82.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 82.15 + * version 2 for more details (a copy is included in the LICENSE file that 82.16 + * accompanied this code). 82.17 + * 82.18 + * You should have received a copy of the GNU General Public License version 82.19 + * 2 along with this work; if not, write to the Free Software Foundation, 82.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 82.21 + * 82.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 82.23 + * or visit www.oracle.com if you need additional information or have any 82.24 + * questions. 82.25 + */ 82.26 + 82.27 +/** 82.28 + * JDK-8056129: AtomicInteger is treated as primitive number with optimistic compilation 82.29 + * 82.30 + * @test 82.31 + * @run 82.32 + */ 82.33 + 82.34 +var AtomicInteger = java.util.concurrent.atomic.AtomicInteger; 82.35 + 82.36 +function getAtomic() { 82.37 + return new AtomicInteger() 82.38 +} 82.39 +var x = getAtomic() 82.40 +print(x instanceof AtomicInteger) 82.41 + 82.42 +var a = [] 82.43 +a.push(x) 82.44 +var y = a[0] 82.45 +print(y instanceof AtomicInteger)
83.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 83.2 +++ b/test/script/basic/JDK-8056129.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 83.3 @@ -0,0 +1,2 @@ 83.4 +true 83.5 +true
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 84.2 +++ b/test/script/basic/JDK-8057019-2.js Tue Sep 16 13:59:37 2014 -0700 84.3 @@ -0,0 +1,33 @@ 84.4 +/* 84.5 + * Copyright (c) 2010, 2014, 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. 84.11 + * 84.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 84.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 84.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 84.15 + * version 2 for more details (a copy is included in the LICENSE file that 84.16 + * accompanied this code). 84.17 + * 84.18 + * You should have received a copy of the GNU General Public License version 84.19 + * 2 along with this work; if not, write to the Free Software Foundation, 84.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 84.21 + * 84.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 84.23 + * or visit www.oracle.com if you need additional information or have any 84.24 + * questions. 84.25 + */ 84.26 + 84.27 +/** 84.28 + * this apply with extra arguments 84.29 + * (with apply to call enabled) 84.30 + * 84.31 + * @test 84.32 + * @run 84.33 + */ 84.34 + 84.35 +load(__DIR__ + 'JDK-8057019-payload.js'); 84.36 +
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 85.2 +++ b/test/script/basic/JDK-8057019-2.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 85.3 @@ -0,0 +1,24 @@ 85.4 +1 2 undefined 85.5 +1 2 3 85.6 +1 2 3 85.7 +1 2 undefined 85.8 +1 2 3 85.9 +1 2 3 85.10 +1 2 undefined 85.11 +1 2 3 85.12 +1 2 3 85.13 +1 2 undefined 85.14 +1 2 3 85.15 +1 2 3 85.16 +1 2 undefined 85.17 +1 2 3 85.18 +1 2 3 85.19 +23 apa gorilla 85.20 +23 apa gorilla 85.21 +23 apa gorilla 85.22 +23 apa gorilla 85.23 +23 apa gorilla 85.24 +23 apa gorilla 85.25 +TypeError: Function.prototype.apply expects an Array for second argument 85.26 +TypeError: Function.prototype.apply expects an Array for second argument 85.27 +TypeError: Function.prototype.apply expects an Array for second argument
86.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 86.2 +++ b/test/script/basic/JDK-8057019-payload.js Tue Sep 16 13:59:37 2014 -0700 86.3 @@ -0,0 +1,102 @@ 86.4 +/* 86.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 86.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 86.7 + * 86.8 + * This code is free software; you can redistribute it and/or modify it 86.9 + * under the terms of the GNU General Public License version 2 only, as 86.10 + * published by the Free Software Foundation. 86.11 + * 86.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 86.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 86.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 86.15 + * version 2 for more details (a copy is included in the LICENSE file that 86.16 + * accompanied this code). 86.17 + * 86.18 + * You should have received a copy of the GNU General Public License version 86.19 + * 2 along with this work; if not, write to the Free Software Foundation, 86.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 86.21 + * 86.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 86.23 + * or visit www.oracle.com if you need additional information or have any 86.24 + * questions. 86.25 + */ 86.26 + 86.27 +/** 86.28 + * this apply with extra arguments 86.29 + * 86.30 + * @subtest 86.31 + */ 86.32 + 86.33 +function func(x, y, z) { 86.34 + print(x, y, z); 86.35 +} 86.36 + 86.37 +function g() { 86.38 + func.apply(this, arguments); 86.39 +} 86.40 +function h() { 86.41 + func.apply(this, arguments, 23); 86.42 +} 86.43 +function i() { 86.44 + func.apply(this, arguments, 23, 4711); 86.45 +} 86.46 +function j() { 86.47 + func.apply(this, arguments, 23, 4711, "apa", "dingo", "gorilla"); 86.48 +} 86.49 +function k() { 86.50 + func.apply(this, arguments, 23); 86.51 +} 86.52 +function l() { 86.53 + func.apply(this, [23, "apa", "gorilla", "dingo"], 17); 86.54 +} 86.55 +function m() { 86.56 + func.apply(this, [23, "apa", "gorilla", "dingo"]); 86.57 +} 86.58 +function n() { 86.59 + func.apply(this, "significant"); 86.60 +} 86.61 + 86.62 +g(1,2); 86.63 +g(1,2,3); 86.64 +g(1,2,3,4); 86.65 + 86.66 +h(1,2); 86.67 +h(1,2,3); 86.68 +h(1,2,3,4); 86.69 + 86.70 +i(1,2); 86.71 +i(1,2,3); 86.72 +i(1,2,3,4); 86.73 + 86.74 +j(1,2); 86.75 +j(1,2,3); 86.76 +j(1,2,3,4); 86.77 + 86.78 +k(1,2); 86.79 +k(1,2,3); 86.80 +k(1,2,3,4); 86.81 + 86.82 +l(1,2); 86.83 +l(1,2,3); 86.84 +l(1,2,3,4); 86.85 + 86.86 +m(1,2); 86.87 +m(1,2,3); 86.88 +m(1,2,3,4); 86.89 + 86.90 +try { 86.91 + n(1,2); 86.92 +} catch (e) { 86.93 + print(e); 86.94 +} 86.95 +try { 86.96 + n(1,2,3); 86.97 +} catch (e) { 86.98 + print(e); 86.99 +} 86.100 + 86.101 +try { 86.102 + n(1,2,3,4); 86.103 +} catch (e) { 86.104 + print(e); 86.105 +}
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 87.2 +++ b/test/script/basic/JDK-8057019.js Tue Sep 16 13:59:37 2014 -0700 87.3 @@ -0,0 +1,35 @@ 87.4 +/* 87.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 87.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 87.7 + * 87.8 + * This code is free software; you can redistribute it and/or modify it 87.9 + * under the terms of the GNU General Public License version 2 only, as 87.10 + * published by the Free Software Foundation. 87.11 + * 87.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 87.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 87.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 87.15 + * version 2 for more details (a copy is included in the LICENSE file that 87.16 + * accompanied this code). 87.17 + * 87.18 + * You should have received a copy of the GNU General Public License version 87.19 + * 2 along with this work; if not, write to the Free Software Foundation, 87.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 87.21 + * 87.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 87.23 + * or visit www.oracle.com if you need additional information or have any 87.24 + * questions. 87.25 + */ 87.26 + 87.27 +/** 87.28 + * this apply with extra arguments 87.29 + * (turning off apply to call) 87.30 + * 87.31 + * @fork 87.32 + * @option -Dnashorn.apply2call=false 87.33 + * @test 87.34 + * @run 87.35 + */ 87.36 + 87.37 +load(__DIR__ + 'JDK-8057019-payload.js'); 87.38 +
88.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 88.2 +++ b/test/script/basic/JDK-8057019.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 88.3 @@ -0,0 +1,24 @@ 88.4 +1 2 undefined 88.5 +1 2 3 88.6 +1 2 3 88.7 +1 2 undefined 88.8 +1 2 3 88.9 +1 2 3 88.10 +1 2 undefined 88.11 +1 2 3 88.12 +1 2 3 88.13 +1 2 undefined 88.14 +1 2 3 88.15 +1 2 3 88.16 +1 2 undefined 88.17 +1 2 3 88.18 +1 2 3 88.19 +23 apa gorilla 88.20 +23 apa gorilla 88.21 +23 apa gorilla 88.22 +23 apa gorilla 88.23 +23 apa gorilla 88.24 +23 apa gorilla 88.25 +TypeError: Function.prototype.apply expects an Array for second argument 88.26 +TypeError: Function.prototype.apply expects an Array for second argument 88.27 +TypeError: Function.prototype.apply expects an Array for second argument
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 89.2 +++ b/test/script/basic/JDK-8058179.js Tue Sep 16 13:59:37 2014 -0700 89.3 @@ -0,0 +1,48 @@ 89.4 +/* 89.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 89.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 89.7 + * 89.8 + * This code is free software; you can redistribute it and/or modify it 89.9 + * under the terms of the GNU General Public License version 2 only, as 89.10 + * published by the Free Software Foundation. 89.11 + * 89.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 89.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 89.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 89.15 + * version 2 for more details (a copy is included in the LICENSE file that 89.16 + * accompanied this code). 89.17 + * 89.18 + * You should have received a copy of the GNU General Public License version 89.19 + * 2 along with this work; if not, write to the Free Software Foundation, 89.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 89.21 + * 89.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 89.23 + * or visit www.oracle.com if you need additional information or have any 89.24 + * questions. 89.25 + */ 89.26 + 89.27 +/** 89.28 + * JDK-8058179: Global constants get in the way of self-modifying properties 89.29 + * 89.30 + * @test 89.31 + * @run 89.32 + */ 89.33 + 89.34 +var global = this; 89.35 + 89.36 +Object.defineProperty(global, "value", { 89.37 + get: function() { 89.38 + print("getting value"); 89.39 + global["value"] = "value 2"; 89.40 + return "value 1"; 89.41 + }, 89.42 + set: function(value) { 89.43 + print("setting value: " + value); 89.44 + delete global["value"]; 89.45 + global["value"] = value; 89.46 + }, 89.47 + configurable: true 89.48 +}); 89.49 + 89.50 +print(value); 89.51 +print(value);
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 90.2 +++ b/test/script/basic/JDK-8058179.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 90.3 @@ -0,0 +1,4 @@ 90.4 +getting value 90.5 +setting value: value 2 90.6 +value 1 90.7 +value 2
91.1 --- a/test/script/basic/apply_to_call/apply_to_call4.js.EXPECTED Thu Sep 11 15:34:13 2014 -0700 91.2 +++ b/test/script/basic/apply_to_call/apply_to_call4.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 91.3 @@ -15,8 +15,8 @@ 91.4 2.3 91.5 3.4 91.6 test 5 done 91.7 -a=object 91.8 -17 91.9 +a=number 91.10 +22 91.11 undefined 91.12 Now it's time for transforms 91.13 19
92.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 92.2 +++ b/test/script/basic/es6/block-function-decl.js Tue Sep 16 13:59:37 2014 -0700 92.3 @@ -0,0 +1,51 @@ 92.4 +/* 92.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 92.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 92.7 + * 92.8 + * This code is free software; you can redistribute it and/or modify it 92.9 + * under the terms of the GNU General Public License version 2 only, as 92.10 + * published by the Free Software Foundation. 92.11 + * 92.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 92.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 92.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 92.15 + * version 2 for more details (a copy is included in the LICENSE file that 92.16 + * accompanied this code). 92.17 + * 92.18 + * You should have received a copy of the GNU General Public License version 92.19 + * 2 along with this work; if not, write to the Free Software Foundation, 92.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 92.21 + * 92.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 92.23 + * or visit www.oracle.com if you need additional information or have any 92.24 + * questions. 92.25 + */ 92.26 + 92.27 +/** 92.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 92.29 + * 92.30 + * @test 92.31 + * @run 92.32 + * @option --language=es6 92.33 + */ 92.34 + 92.35 +"use strict"; 92.36 + 92.37 +{ 92.38 + // f is defined on block level 92.39 + print(f); 92.40 + f(); 92.41 + function f() { 92.42 + print("in f"); 92.43 + } 92.44 + print(f); 92.45 + f(); 92.46 +} 92.47 + 92.48 +try { 92.49 + print(typeof f); 92.50 + f(); 92.51 +} catch (e) { 92.52 + print(e); 92.53 +} 92.54 +
93.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 93.2 +++ b/test/script/basic/es6/block-function-decl.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 93.3 @@ -0,0 +1,10 @@ 93.4 +function f() { 93.5 + print("in f"); 93.6 + } 93.7 +in f 93.8 +function f() { 93.9 + print("in f"); 93.10 + } 93.11 +in f 93.12 +undefined 93.13 +ReferenceError: "f" is not defined
94.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 94.2 +++ b/test/script/basic/es6/const-empty.js Tue Sep 16 13:59:37 2014 -0700 94.3 @@ -0,0 +1,37 @@ 94.4 +/* 94.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 94.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 94.7 + * 94.8 + * This code is free software; you can redistribute it and/or modify it 94.9 + * under the terms of the GNU General Public License version 2 only, as 94.10 + * published by the Free Software Foundation. 94.11 + * 94.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 94.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 94.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 94.15 + * version 2 for more details (a copy is included in the LICENSE file that 94.16 + * accompanied this code). 94.17 + * 94.18 + * You should have received a copy of the GNU General Public License version 94.19 + * 2 along with this work; if not, write to the Free Software Foundation, 94.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 94.21 + * 94.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 94.23 + * or visit www.oracle.com if you need additional information or have any 94.24 + * questions. 94.25 + */ 94.26 + 94.27 +/** 94.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 94.29 + * 94.30 + * @test 94.31 + * @run 94.32 + * @option --language=es6 94.33 + */ 94.34 + 94.35 +try { 94.36 + eval('"use strict";\n' + 94.37 + 'const x;\n'); 94.38 +} catch (e) { 94.39 + print(e); 94.40 +}
95.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 95.2 +++ b/test/script/basic/es6/const-empty.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 95.3 @@ -0,0 +1,3 @@ 95.4 +SyntaxError: test/script/basic/es6/const-empty.js#33:4<eval>:2:7 Missing assignment to constant "x" 95.5 +const x; 95.6 + ^
96.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 96.2 +++ b/test/script/basic/es6/const-reassign.js Tue Sep 16 13:59:37 2014 -0700 96.3 @@ -0,0 +1,174 @@ 96.4 +/* 96.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 96.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 96.7 + * 96.8 + * This code is free software; you can redistribute it and/or modify it 96.9 + * under the terms of the GNU General Public License version 2 only, as 96.10 + * published by the Free Software Foundation. 96.11 + * 96.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 96.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 96.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 96.15 + * version 2 for more details (a copy is included in the LICENSE file that 96.16 + * accompanied this code). 96.17 + * 96.18 + * You should have received a copy of the GNU General Public License version 96.19 + * 2 along with this work; if not, write to the Free Software Foundation, 96.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 96.21 + * 96.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 96.23 + * or visit www.oracle.com if you need additional information or have any 96.24 + * questions. 96.25 + */ 96.26 + 96.27 +/** 96.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 96.29 + * 96.30 + * @test 96.31 + * @run 96.32 + * @option --language=es6 */ 96.33 + 96.34 +"use strict"; 96.35 + 96.36 +try { 96.37 + eval('"use strict";\n' + 96.38 + 'const x = 2;\n' + 96.39 + 'x = 1;\n'); 96.40 +} catch (e) { 96.41 + print(e.name); 96.42 +} 96.43 + 96.44 +try { 96.45 + eval('"use strict";\n' + 96.46 + 'const x = 2;\n' + 96.47 + 'x++;\n'); 96.48 + fail("const assignment didn't throw"); 96.49 +} catch (e) { 96.50 + print(e.name); 96.51 +} 96.52 + 96.53 +try { 96.54 + eval('"use strict";\n' + 96.55 + 'const x = 2;\n' + 96.56 + 'x--;\n'); 96.57 + fail("const assignment didn't throw"); 96.58 +} catch (e) { 96.59 + print(e.name); 96.60 +} 96.61 + 96.62 +try { 96.63 + eval('"use strict";\n' + 96.64 + 'const x = 2;\n' + 96.65 + '++x;\n'); 96.66 + fail("const assignment didn't throw"); 96.67 +} catch (e) { 96.68 + print(e.name); 96.69 +} 96.70 + 96.71 +try { 96.72 + eval('"use strict";\n' + 96.73 + 'const x = 2;\n' + 96.74 + '--x;\n'); 96.75 + fail("const assignment didn't throw"); 96.76 +} catch (e) { 96.77 + print(e.name); 96.78 +} 96.79 + 96.80 +try { 96.81 + eval('"use strict";\n' + 96.82 + 'const x = 2;\n' + 96.83 + 'x += 1;\n'); 96.84 + fail("const assignment didn't throw"); 96.85 +} catch (e) { 96.86 + print(e.name); 96.87 +} 96.88 + 96.89 +try { 96.90 + eval('"use strict";\n' + 96.91 + 'const x = 2;\n' + 96.92 + 'x *= 1;\n'); 96.93 + fail("const assignment didn't throw"); 96.94 +} catch (e) { 96.95 + print(e.name); 96.96 +} 96.97 + 96.98 +try { 96.99 + eval('"use strict";\n' + 96.100 + 'const x = 2;\n' + 96.101 + 'x /= 1;\n'); 96.102 + fail("const assignment didn't throw"); 96.103 +} catch (e) { 96.104 + print(e.name); 96.105 +} 96.106 + 96.107 +try { 96.108 + eval('"use strict";\n' + 96.109 + 'const x = 2;\n' + 96.110 + 'x %= 1;\n'); 96.111 + fail("const assignment didn't throw"); 96.112 +} catch (e) { 96.113 + print(e.name); 96.114 +} 96.115 + 96.116 +try { 96.117 + eval('"use strict";\n' + 96.118 + 'const x = 2;\n' + 96.119 + 'x |= 1;\n'); 96.120 + fail("const assignment didn't throw"); 96.121 +} catch (e) { 96.122 + print(e.name); 96.123 +} 96.124 + 96.125 +try { 96.126 + eval('"use strict";\n' + 96.127 + 'const x = 2;\n' + 96.128 + 'x &= 1;\n'); 96.129 + fail("const assignment didn't throw"); 96.130 +} catch (e) { 96.131 + print(e.name); 96.132 +} 96.133 + 96.134 +try { 96.135 + eval('"use strict";\n' + 96.136 + 'const x = 2;\n' + 96.137 + 'x ^= 1;\n'); 96.138 + fail("const assignment didn't throw"); 96.139 +} catch (e) { 96.140 + print(e.name); 96.141 +} 96.142 + 96.143 +try { 96.144 + eval('"use strict";\n' + 96.145 + 'const x = 2;\n' + 96.146 + 'x <<= 1;\n'); 96.147 + fail("const assignment didn't throw"); 96.148 +} catch (e) { 96.149 + print(e.name); 96.150 +} 96.151 + 96.152 +try { 96.153 + eval('"use strict";\n' + 96.154 + 'const x = 2;\n' + 96.155 + 'x >>= 1;\n'); 96.156 + fail("const assignment didn't throw"); 96.157 +} catch (e) { 96.158 + print(e.name); 96.159 +} 96.160 + 96.161 +try { 96.162 + eval('"use strict";\n' + 96.163 + 'const x = 2;\n' + 96.164 + 'x >>>= 1;\n'); 96.165 + fail("const assignment didn't throw"); 96.166 +} catch (e) { 96.167 + print(e.name); 96.168 +} 96.169 + 96.170 +try { 96.171 + eval('"use strict";\n' + 96.172 + 'const x = 2;\n' + 96.173 + 'delete x;\n'); 96.174 + fail("const assignment didn't throw"); 96.175 +} catch (e) { 96.176 + print(e.name); 96.177 +}
97.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 97.2 +++ b/test/script/basic/es6/const-reassign.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 97.3 @@ -0,0 +1,16 @@ 97.4 +SyntaxError 97.5 +SyntaxError 97.6 +SyntaxError 97.7 +SyntaxError 97.8 +SyntaxError 97.9 +SyntaxError 97.10 +SyntaxError 97.11 +SyntaxError 97.12 +SyntaxError 97.13 +SyntaxError 97.14 +SyntaxError 97.15 +SyntaxError 97.16 +SyntaxError 97.17 +SyntaxError 97.18 +SyntaxError 97.19 +SyntaxError
98.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 98.2 +++ b/test/script/basic/es6/const-redeclare-extra.js Tue Sep 16 13:59:37 2014 -0700 98.3 @@ -0,0 +1,59 @@ 98.4 +/* 98.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 98.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 98.7 + * 98.8 + * This code is free software; you can redistribute it and/or modify it 98.9 + * under the terms of the GNU General Public License version 2 only, as 98.10 + * published by the Free Software Foundation. 98.11 + * 98.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 98.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 98.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 98.15 + * version 2 for more details (a copy is included in the LICENSE file that 98.16 + * accompanied this code). 98.17 + * 98.18 + * You should have received a copy of the GNU General Public License version 98.19 + * 2 along with this work; if not, write to the Free Software Foundation, 98.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 98.21 + * 98.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 98.23 + * or visit www.oracle.com if you need additional information or have any 98.24 + * questions. 98.25 + */ 98.26 + 98.27 +/** 98.28 + * JDK-8057678: Tests for let&const keywords in Nashorn 98.29 + * 98.30 + * @test 98.31 + * @run 98.32 + * @option --language=es6 98.33 + * @option -scripting 98.34 + */ 98.35 + 98.36 + 98.37 +function tryIt (code) { 98.38 + try { 98.39 + eval(code) 98.40 + } catch (e) { 98.41 + print(e) 98.42 + } 98.43 +} 98.44 + 98.45 +tryIt(<<CODE 98.46 + "use strict"; 98.47 + const x = 2; 98.48 + var x = {}; 98.49 +CODE) 98.50 + 98.51 +tryIt(<<CODE 98.52 + "use strict"; 98.53 + var x = 2; 98.54 + const x = {}; 98.55 +CODE) 98.56 + 98.57 +tryIt(<<CODE 98.58 + "use strict"; 98.59 + function x () {} 98.60 + const x = 5; 98.61 +CODE) 98.62 +
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 99.2 +++ b/test/script/basic/es6/const-redeclare-extra.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 99.3 @@ -0,0 +1,9 @@ 99.4 +SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:8 Variable "x" has already been declared 99.5 + var x = {}; 99.6 + ^ 99.7 +SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:2:8 Variable "x" has already been declared 99.8 + var x = 2; 99.9 + ^ 99.10 +SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:2:13 Variable "x" has already been declared 99.11 + function x () {} 99.12 + ^
100.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 100.2 +++ b/test/script/basic/es6/const-redeclare.js Tue Sep 16 13:59:37 2014 -0700 100.3 @@ -0,0 +1,38 @@ 100.4 +/* 100.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 100.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 100.7 + * 100.8 + * This code is free software; you can redistribute it and/or modify it 100.9 + * under the terms of the GNU General Public License version 2 only, as 100.10 + * published by the Free Software Foundation. 100.11 + * 100.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 100.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 100.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 100.15 + * version 2 for more details (a copy is included in the LICENSE file that 100.16 + * accompanied this code). 100.17 + * 100.18 + * You should have received a copy of the GNU General Public License version 100.19 + * 2 along with this work; if not, write to the Free Software Foundation, 100.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 100.21 + * 100.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 100.23 + * or visit www.oracle.com if you need additional information or have any 100.24 + * questions. 100.25 + */ 100.26 + 100.27 +/** 100.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 100.29 + * 100.30 + * @test 100.31 + * @run 100.32 + * @option --language=es6 100.33 + */ 100.34 + 100.35 +try { 100.36 + eval('"use strict";\n' + 100.37 + 'const x = 2;\n' + 100.38 + 'const x = 2;\n'); 100.39 +} catch (e) { 100.40 + print(e); 100.41 +}
101.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 101.2 +++ b/test/script/basic/es6/const-redeclare.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 101.3 @@ -0,0 +1,3 @@ 101.4 +SyntaxError: test/script/basic/es6/const-redeclare.js#33:4<eval>:2:6 Variable "x" has already been declared 101.5 +const x = 2; 101.6 + ^
102.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 102.2 +++ b/test/script/basic/es6/const-self.js Tue Sep 16 13:59:37 2014 -0700 102.3 @@ -0,0 +1,42 @@ 102.4 +/* 102.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 102.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 102.7 + * 102.8 + * This code is free software; you can redistribute it and/or modify it 102.9 + * under the terms of the GNU General Public License version 2 only, as 102.10 + * published by the Free Software Foundation. 102.11 + * 102.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 102.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 102.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 102.15 + * version 2 for more details (a copy is included in the LICENSE file that 102.16 + * accompanied this code). 102.17 + * 102.18 + * You should have received a copy of the GNU General Public License version 102.19 + * 2 along with this work; if not, write to the Free Software Foundation, 102.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 102.21 + * 102.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 102.23 + * or visit www.oracle.com if you need additional information or have any 102.24 + * questions. 102.25 + */ 102.26 + 102.27 +/** 102.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 102.29 + * 102.30 + * @test 102.31 + * @run 102.32 + * @option --language=es6 */ 102.33 + 102.34 +"use strict"; 102.35 + 102.36 +const a = 1, b = a; 102.37 + 102.38 +print(a, b); 102.39 + 102.40 +try { 102.41 + eval('"use strict";\n' + 102.42 + 'const a = a;\n'); 102.43 +} catch (e) { 102.44 + print(e); 102.45 +}
103.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 103.2 +++ b/test/script/basic/es6/const-self.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 103.3 @@ -0,0 +1,2 @@ 103.4 +1 1 103.5 +ReferenceError: "a" is not defined
104.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 104.2 +++ b/test/script/basic/es6/const-tdz.js Tue Sep 16 13:59:37 2014 -0700 104.3 @@ -0,0 +1,81 @@ 104.4 +/* 104.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 104.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 104.7 + * 104.8 + * This code is free software; you can redistribute it and/or modify it 104.9 + * under the terms of the GNU General Public License version 2 only, as 104.10 + * published by the Free Software Foundation. 104.11 + * 104.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 104.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 104.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 104.15 + * version 2 for more details (a copy is included in the LICENSE file that 104.16 + * accompanied this code). 104.17 + * 104.18 + * You should have received a copy of the GNU General Public License version 104.19 + * 2 along with this work; if not, write to the Free Software Foundation, 104.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 104.21 + * 104.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 104.23 + * or visit www.oracle.com if you need additional information or have any 104.24 + * questions. 104.25 + */ 104.26 + 104.27 +/** 104.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 104.29 + * 104.30 + * @test 104.31 + * @run 104.32 + * @option --language=es6 */ 104.33 + 104.34 +"use strict"; 104.35 + 104.36 +{ 104.37 + print("test 1"); 104.38 + 104.39 + function f() { 104.40 + try { 104.41 + print(a); 104.42 + } catch (a) { 104.43 + print(a); 104.44 + } 104.45 + } 104.46 + 104.47 + f(); 104.48 + const a = 1; 104.49 + f(); 104.50 +} 104.51 + 104.52 +{ 104.53 + print("test 2"); 104.54 + 104.55 + function f() { 104.56 + try { 104.57 + print(a); 104.58 + } catch (a) { 104.59 + print(a); 104.60 + } 104.61 + } 104.62 + 104.63 + f(); 104.64 + const a = 2; 104.65 + f(); 104.66 +} 104.67 + 104.68 +{ 104.69 + print("test 3"); 104.70 + { 104.71 + try { 104.72 + print(a); 104.73 + } catch (a) { 104.74 + print(a); 104.75 + } 104.76 + } 104.77 + 104.78 + const a = 3; 104.79 + 104.80 + { 104.81 + print(a); 104.82 + } 104.83 +} 104.84 +
105.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 105.2 +++ b/test/script/basic/es6/const-tdz.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 105.3 @@ -0,0 +1,9 @@ 105.4 +test 1 105.5 +ReferenceError: "a" is not defined 105.6 +1 105.7 +test 2 105.8 +ReferenceError: "a" is not defined 105.9 +2 105.10 +test 3 105.11 +ReferenceError: "a" is not defined 105.12 +3
106.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 106.2 +++ b/test/script/basic/es6/const.js Tue Sep 16 13:59:37 2014 -0700 106.3 @@ -0,0 +1,69 @@ 106.4 +/* 106.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 106.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 106.7 + * 106.8 + * This code is free software; you can redistribute it and/or modify it 106.9 + * under the terms of the GNU General Public License version 2 only, as 106.10 + * published by the Free Software Foundation. 106.11 + * 106.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 106.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 106.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 106.15 + * version 2 for more details (a copy is included in the LICENSE file that 106.16 + * accompanied this code). 106.17 + * 106.18 + * You should have received a copy of the GNU General Public License version 106.19 + * 2 along with this work; if not, write to the Free Software Foundation, 106.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 106.21 + * 106.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 106.23 + * or visit www.oracle.com if you need additional information or have any 106.24 + * questions. 106.25 + */ 106.26 + 106.27 +/** 106.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 106.29 + * 106.30 + * @test 106.31 + * @run 106.32 + * @option --language=es6 106.33 + */ 106.34 + 106.35 +"use strict"; 106.36 + 106.37 +const a = 2; 106.38 +const c = 2; 106.39 +print(a, c); 106.40 + 106.41 +function f(x) { 106.42 + const a = 5; 106.43 + const c = 10; 106.44 + print(a, c); 106.45 + if (x) { 106.46 + const a = 42; 106.47 + const c = 43; 106.48 + print(a, c); 106.49 + } 106.50 + print(a, c); 106.51 + 106.52 + function inner() { 106.53 + (function() { 106.54 + print(a, c); 106.55 + })(); 106.56 + } 106.57 + inner(); 106.58 +} 106.59 + 106.60 +f(true); 106.61 +f(false); 106.62 + 106.63 +(function() { 106.64 + (function() { 106.65 + print(a, c); 106.66 + })(); 106.67 +})(); 106.68 + 106.69 +function outer() { 106.70 + print(a, c); 106.71 +} 106.72 +outer();
107.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 107.2 +++ b/test/script/basic/es6/const.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 107.3 @@ -0,0 +1,10 @@ 107.4 +2 2 107.5 +5 10 107.6 +42 43 107.7 +5 10 107.8 +5 10 107.9 +5 10 107.10 +5 10 107.11 +5 10 107.12 +2 2 107.13 +2 2
108.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 108.2 +++ b/test/script/basic/es6/for-let.js Tue Sep 16 13:59:37 2014 -0700 108.3 @@ -0,0 +1,41 @@ 108.4 +/* 108.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 108.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 108.7 + * 108.8 + * This code is free software; you can redistribute it and/or modify it 108.9 + * under the terms of the GNU General Public License version 2 only, as 108.10 + * published by the Free Software Foundation. 108.11 + * 108.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 108.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 108.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 108.15 + * version 2 for more details (a copy is included in the LICENSE file that 108.16 + * accompanied this code). 108.17 + * 108.18 + * You should have received a copy of the GNU General Public License version 108.19 + * 2 along with this work; if not, write to the Free Software Foundation, 108.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 108.21 + * 108.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 108.23 + * or visit www.oracle.com if you need additional information or have any 108.24 + * questions. 108.25 + */ 108.26 + 108.27 +/** 108.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 108.29 + * 108.30 + * @test 108.31 + * @run 108.32 + * @option --language=es6 */ 108.33 + 108.34 +"use strict"; 108.35 + 108.36 +for (let i = 0; i < 10; i++) { 108.37 + print(i); 108.38 +} 108.39 + 108.40 +try { 108.41 + print(i); 108.42 +} catch (e) { 108.43 + print(e); 108.44 +}
109.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 109.2 +++ b/test/script/basic/es6/for-let.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 109.3 @@ -0,0 +1,11 @@ 109.4 +0 109.5 +1 109.6 +2 109.7 +3 109.8 +4 109.9 +5 109.10 +6 109.11 +7 109.12 +8 109.13 +9 109.14 +ReferenceError: "i" is not defined
110.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 110.2 +++ b/test/script/basic/es6/let-eval.js Tue Sep 16 13:59:37 2014 -0700 110.3 @@ -0,0 +1,98 @@ 110.4 +/* 110.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 110.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 110.7 + * 110.8 + * This code is free software; you can redistribute it and/or modify it 110.9 + * under the terms of the GNU General Public License version 2 only, as 110.10 + * published by the Free Software Foundation. 110.11 + * 110.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 110.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 110.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 110.15 + * version 2 for more details (a copy is included in the LICENSE file that 110.16 + * accompanied this code). 110.17 + * 110.18 + * You should have received a copy of the GNU General Public License version 110.19 + * 2 along with this work; if not, write to the Free Software Foundation, 110.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 110.21 + * 110.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 110.23 + * or visit www.oracle.com if you need additional information or have any 110.24 + * questions. 110.25 + */ 110.26 + 110.27 +/** 110.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 110.29 + * 110.30 + * @test 110.31 + * @run 110.32 + * @option --language=es6 */ 110.33 + 110.34 +"use strict"; 110.35 + 110.36 +function f() { 110.37 + var a; 110.38 + let b; 110.39 + const c = 0; 110.40 + 110.41 + print(a, b, c); 110.42 + 110.43 + try { 110.44 + eval("x = 1; print('x: ' + x);"); 110.45 + print("assignment to x succeeded"); 110.46 + } catch (e) { 110.47 + print(e); 110.48 + } 110.49 + try { 110.50 + eval("'use strict'; let z = 1; print('z: ' + z);"); 110.51 + print("assignment to z succeeded"); 110.52 + eval("print('z: ' + z);"); 110.53 + } catch (e) { 110.54 + print(e); 110.55 + } 110.56 + 110.57 + try { 110.58 + eval("a = 1; print(a);"); 110.59 + print("assignment to a succeeded"); 110.60 + } catch (e) { 110.61 + print(e); 110.62 + } 110.63 + print("a: " + a); 110.64 + 110.65 + try { 110.66 + eval("b = 1; print('b: ' + b);"); 110.67 + print("assignment to b succeeded"); 110.68 + } catch (e) { 110.69 + print(e); 110.70 + } 110.71 + print("b: " + b); 110.72 + 110.73 + try { 110.74 + eval("c = 1; print('c: ' + c);"); 110.75 + print("assignment to c succeeded"); 110.76 + } catch (e) { 110.77 + print(e); 110.78 + } 110.79 + print("c: " + c); 110.80 + 110.81 + eval("a = 2; let b = 3;"); 110.82 + 110.83 + try { 110.84 + print(a, b, c); 110.85 + } catch (e) { 110.86 + print(e); 110.87 + } 110.88 + 110.89 + let x; 110.90 + 110.91 + try { 110.92 + print(a, b, c, x); 110.93 + } catch (e) { 110.94 + print(e); 110.95 + } 110.96 + 110.97 +} 110.98 + 110.99 +f(); 110.100 + 110.101 +print(typeof a, typeof b, typeof c, typeof x, typeof z);
111.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 111.2 +++ b/test/script/basic/es6/let-eval.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 111.3 @@ -0,0 +1,16 @@ 111.4 +undefined undefined 0 111.5 +ReferenceError: "x" is not defined 111.6 +z: 1 111.7 +assignment to z succeeded 111.8 +ReferenceError: "z" is not defined 111.9 +1 111.10 +assignment to a succeeded 111.11 +a: 1 111.12 +b: 1 111.13 +assignment to b succeeded 111.14 +b: 1 111.15 +TypeError: "c" is not a writable property of [object Object] 111.16 +c: 0 111.17 +2 1 0 111.18 +2 1 0 undefined 111.19 +undefined undefined undefined undefined undefined
112.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 112.2 +++ b/test/script/basic/es6/let-load-lib.js Tue Sep 16 13:59:37 2014 -0700 112.3 @@ -0,0 +1,48 @@ 112.4 +/* 112.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 112.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 112.7 + * 112.8 + * This code is free software; you can redistribute it and/or modify it 112.9 + * under the terms of the GNU General Public License version 2 only, as 112.10 + * published by the Free Software Foundation. 112.11 + * 112.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 112.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 112.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 112.15 + * version 2 for more details (a copy is included in the LICENSE file that 112.16 + * accompanied this code). 112.17 + * 112.18 + * You should have received a copy of the GNU General Public License version 112.19 + * 2 along with this work; if not, write to the Free Software Foundation, 112.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 112.21 + * 112.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 112.23 + * or visit www.oracle.com if you need additional information or have any 112.24 + * questions. 112.25 + */ 112.26 + 112.27 +/** 112.28 + * @subtest 112.29 + */ 112.30 + 112.31 +"use strict"; 112.32 + 112.33 +// var should be visible in other script, let and const not 112.34 +var a = 1; 112.35 +let b = 2; 112.36 +const c = 3; 112.37 + 112.38 +// top level function should be visible 112.39 +function top() { 112.40 + print("top level function"); 112.41 +} 112.42 + 112.43 +// block level function not visible outside script 112.44 +{ 112.45 + function block() { 112.46 + print("block function"); 112.47 + } 112.48 + 112.49 + top(); 112.50 + block(); 112.51 +}
113.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 113.2 +++ b/test/script/basic/es6/let-load.js Tue Sep 16 13:59:37 2014 -0700 113.3 @@ -0,0 +1,62 @@ 113.4 +/* 113.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 113.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 113.7 + * 113.8 + * This code is free software; you can redistribute it and/or modify it 113.9 + * under the terms of the GNU General Public License version 2 only, as 113.10 + * published by the Free Software Foundation. 113.11 + * 113.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 113.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 113.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 113.15 + * version 2 for more details (a copy is included in the LICENSE file that 113.16 + * accompanied this code). 113.17 + * 113.18 + * You should have received a copy of the GNU General Public License version 113.19 + * 2 along with this work; if not, write to the Free Software Foundation, 113.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 113.21 + * 113.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 113.23 + * or visit www.oracle.com if you need additional information or have any 113.24 + * questions. 113.25 + */ 113.26 + 113.27 +/** 113.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 113.29 + * 113.30 + * @test 113.31 + * @run 113.32 + * @option --language=es6 */ 113.33 + 113.34 +"use strict"; 113.35 + 113.36 +load(__DIR__ + "let-load-lib.js"); 113.37 + 113.38 +{ 113.39 + let a = 20; 113.40 + const c = 30; 113.41 + print("print local defs: " + a, c); 113.42 +} 113.43 + 113.44 +print("imported var: " + a); 113.45 +try { 113.46 + print("imported let: " + b); 113.47 +} catch (e) { 113.48 + print(e); 113.49 +} 113.50 + 113.51 +try { 113.52 + print("imported const: " + c); 113.53 +} catch (e) { 113.54 + print(e); 113.55 +} 113.56 + 113.57 +top(); 113.58 + 113.59 +try { 113.60 + block(); 113.61 +} catch (e) { 113.62 + print(e); 113.63 +} 113.64 + 113.65 +
114.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 114.2 +++ b/test/script/basic/es6/let-load.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 114.3 @@ -0,0 +1,8 @@ 114.4 +top level function 114.5 +block function 114.6 +print local defs: 20 30 114.7 +imported var: 1 114.8 +ReferenceError: "b" is not defined 114.9 +ReferenceError: "c" is not defined 114.10 +top level function 114.11 +ReferenceError: "block" is not defined
115.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 115.2 +++ b/test/script/basic/es6/let-nodeclare.js Tue Sep 16 13:59:37 2014 -0700 115.3 @@ -0,0 +1,52 @@ 115.4 +/* 115.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 115.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 115.7 + * 115.8 + * This code is free software; you can redistribute it and/or modify it 115.9 + * under the terms of the GNU General Public License version 2 only, as 115.10 + * published by the Free Software Foundation. 115.11 + * 115.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 115.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 115.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 115.15 + * version 2 for more details (a copy is included in the LICENSE file that 115.16 + * accompanied this code). 115.17 + * 115.18 + * You should have received a copy of the GNU General Public License version 115.19 + * 2 along with this work; if not, write to the Free Software Foundation, 115.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 115.21 + * 115.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 115.23 + * or visit www.oracle.com if you need additional information or have any 115.24 + * questions. 115.25 + */ 115.26 + 115.27 +/** 115.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 115.29 + * 115.30 + * @test 115.31 + * @run 115.32 + * @option --language=es6 */ 115.33 + 115.34 +"use strict"; 115.35 + 115.36 +try { 115.37 + if (true) { 115.38 + let x = 2; 115.39 + print(x); 115.40 + } 115.41 + print(x); 115.42 +} catch (e) { 115.43 + print(e); 115.44 +} 115.45 + 115.46 + 115.47 +try { 115.48 + if (true) { 115.49 + const x = 2; 115.50 + print(x); 115.51 + } 115.52 + print(x); 115.53 +} catch (e) { 115.54 + print(e); 115.55 +}
116.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 116.2 +++ b/test/script/basic/es6/let-nodeclare.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 116.3 @@ -0,0 +1,4 @@ 116.4 +2 116.5 +ReferenceError: "x" is not defined 116.6 +2 116.7 +ReferenceError: "x" is not defined
117.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 117.2 +++ b/test/script/basic/es6/let-redeclare-extra.js Tue Sep 16 13:59:37 2014 -0700 117.3 @@ -0,0 +1,70 @@ 117.4 +/* 117.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 117.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 117.7 + * 117.8 + * This code is free software; you can redistribute it and/or modify it 117.9 + * under the terms of the GNU General Public License version 2 only, as 117.10 + * published by the Free Software Foundation. 117.11 + * 117.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 117.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 117.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 117.15 + * version 2 for more details (a copy is included in the LICENSE file that 117.16 + * accompanied this code). 117.17 + * 117.18 + * You should have received a copy of the GNU General Public License version 117.19 + * 2 along with this work; if not, write to the Free Software Foundation, 117.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 117.21 + * 117.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 117.23 + * or visit www.oracle.com if you need additional information or have any 117.24 + * questions. 117.25 + */ 117.26 + 117.27 +/** 117.28 + * JDK-8057678: Tests for let&const keywords in Nashorn 117.29 + * 117.30 + * @test 117.31 + * @run 117.32 + * @option --language=es6 117.33 + * @option -scripting 117.34 + */ 117.35 + 117.36 +function tryIt (code) { 117.37 + try { 117.38 + eval(code) 117.39 + } catch (e) { 117.40 + print(e) 117.41 + } 117.42 +} 117.43 + 117.44 +tryIt(<<CODE 117.45 + "use strict"; 117.46 + let x = 2; 117.47 + const x = function (a,b,c) {}; 117.48 +CODE) 117.49 + 117.50 +tryIt(<<CODE 117.51 + "use strict"; 117.52 + let x = {}; 117.53 + var x = 2; 117.54 +CODE) 117.55 + 117.56 +tryIt(<<CODE 117.57 + "use strict"; 117.58 + var x = 2; 117.59 + let x = undefined; 117.60 +CODE) 117.61 + 117.62 +tryIt(<<CODE 117.63 + "use strict"; 117.64 + const x = function (){}; 117.65 + let x = {}; 117.66 +CODE) 117.67 + 117.68 + 117.69 +tryIt(<<CODE 117.70 + "use strict"; 117.71 + let a = 2; 117.72 + function a () {}; 117.73 +CODE) 117.74 \ No newline at end of file
118.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 118.2 +++ b/test/script/basic/es6/let-redeclare-extra.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 118.3 @@ -0,0 +1,15 @@ 118.4 +SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "x" has already been declared 118.5 + let x = 2; 118.6 + ^ 118.7 +SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:8 Variable "x" has already been declared 118.8 + var x = 2; 118.9 + ^ 118.10 +SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "x" has already been declared 118.11 + var x = 2; 118.12 + ^ 118.13 +SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:10 Variable "x" has already been declared 118.14 + const x = function (){}; 118.15 + ^ 118.16 +SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:13 Variable "a" has already been declared 118.17 + function a () {}; 118.18 + ^
119.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 119.2 +++ b/test/script/basic/es6/let-redeclare.js Tue Sep 16 13:59:37 2014 -0700 119.3 @@ -0,0 +1,38 @@ 119.4 +/* 119.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 119.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 119.7 + * 119.8 + * This code is free software; you can redistribute it and/or modify it 119.9 + * under the terms of the GNU General Public License version 2 only, as 119.10 + * published by the Free Software Foundation. 119.11 + * 119.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 119.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 119.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 119.15 + * version 2 for more details (a copy is included in the LICENSE file that 119.16 + * accompanied this code). 119.17 + * 119.18 + * You should have received a copy of the GNU General Public License version 119.19 + * 2 along with this work; if not, write to the Free Software Foundation, 119.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 119.21 + * 119.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 119.23 + * or visit www.oracle.com if you need additional information or have any 119.24 + * questions. 119.25 + */ 119.26 + 119.27 +/** 119.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 119.29 + * 119.30 + * @test 119.31 + * @run 119.32 + * @option --language=es6 119.33 + */ 119.34 + 119.35 +try { 119.36 + eval('"use strict";\n' + 119.37 + 'let x = 2;\n' + 119.38 + 'let x = 2;\n'); 119.39 +} catch (e) { 119.40 + print(e); 119.41 +}
120.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 120.2 +++ b/test/script/basic/es6/let-redeclare.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 120.3 @@ -0,0 +1,3 @@ 120.4 +SyntaxError: test/script/basic/es6/let-redeclare.js#33:4<eval>:2:4 Variable "x" has already been declared 120.5 +let x = 2; 120.6 + ^
121.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 121.2 +++ b/test/script/basic/es6/let-self.js Tue Sep 16 13:59:37 2014 -0700 121.3 @@ -0,0 +1,42 @@ 121.4 +/* 121.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 121.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 121.7 + * 121.8 + * This code is free software; you can redistribute it and/or modify it 121.9 + * under the terms of the GNU General Public License version 2 only, as 121.10 + * published by the Free Software Foundation. 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-8051889: Implement block scoping in symbol assignment and scope computation 121.29 + * 121.30 + * @test 121.31 + * @run 121.32 + * @option --language=es6 */ 121.33 + 121.34 +"use strict"; 121.35 + 121.36 +let a, b = a; 121.37 + 121.38 +print(a, b); 121.39 + 121.40 +try { 121.41 + eval('"use strict";\n' + 121.42 + 'let a = a;\n'); 121.43 +} catch (e) { 121.44 + print(e); 121.45 +}
122.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 122.2 +++ b/test/script/basic/es6/let-self.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 122.3 @@ -0,0 +1,2 @@ 122.4 +undefined undefined 122.5 +ReferenceError: "a" is not defined
123.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 123.2 +++ b/test/script/basic/es6/let-tdz.js Tue Sep 16 13:59:37 2014 -0700 123.3 @@ -0,0 +1,97 @@ 123.4 +/* 123.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 123.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 123.7 + * 123.8 + * This code is free software; you can redistribute it and/or modify it 123.9 + * under the terms of the GNU General Public License version 2 only, as 123.10 + * published by the Free Software Foundation. 123.11 + * 123.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 123.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 123.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 123.15 + * version 2 for more details (a copy is included in the LICENSE file that 123.16 + * accompanied this code). 123.17 + * 123.18 + * You should have received a copy of the GNU General Public License version 123.19 + * 2 along with this work; if not, write to the Free Software Foundation, 123.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 123.21 + * 123.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 123.23 + * or visit www.oracle.com if you need additional information or have any 123.24 + * questions. 123.25 + */ 123.26 + 123.27 +/** 123.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 123.29 + * 123.30 + * @test 123.31 + * @run 123.32 + * @option --language=es6 */ 123.33 + 123.34 +"use strict"; 123.35 + 123.36 +{ 123.37 + print("test 1"); 123.38 + 123.39 + function f() { 123.40 + try { 123.41 + print(a); 123.42 + } catch (a) { 123.43 + print(a); 123.44 + } 123.45 + } 123.46 + 123.47 + f(); 123.48 + let a = 1; 123.49 + f(); 123.50 +} 123.51 + 123.52 +{ 123.53 + print("test 2"); 123.54 + 123.55 + function f() { 123.56 + try { 123.57 + print(a); 123.58 + } catch (a) { 123.59 + print(a); 123.60 + } 123.61 + } 123.62 + 123.63 + f(); 123.64 + let a = 2; 123.65 + f(); 123.66 +} 123.67 + 123.68 +{ 123.69 + print("test 3"); 123.70 + 123.71 + { 123.72 + try { 123.73 + print(a); 123.74 + } catch (a) { 123.75 + print(a); 123.76 + } 123.77 + } 123.78 + 123.79 + let a = 3; 123.80 + 123.81 + { 123.82 + print(a); 123.83 + } 123.84 +} 123.85 + 123.86 +{ 123.87 + print("test 4"); 123.88 + let a; 123.89 + 123.90 + { 123.91 + print(a); 123.92 + } 123.93 + 123.94 + a = 4; 123.95 + 123.96 + { 123.97 + print(a); 123.98 + } 123.99 +} 123.100 +
124.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 124.2 +++ b/test/script/basic/es6/let-tdz.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 124.3 @@ -0,0 +1,12 @@ 124.4 +test 1 124.5 +ReferenceError: "a" is not defined 124.6 +1 124.7 +test 2 124.8 +ReferenceError: "a" is not defined 124.9 +2 124.10 +test 3 124.11 +ReferenceError: "a" is not defined 124.12 +3 124.13 +test 4 124.14 +undefined 124.15 +4
125.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 125.2 +++ b/test/script/basic/es6/let.js Tue Sep 16 13:59:37 2014 -0700 125.3 @@ -0,0 +1,69 @@ 125.4 +/* 125.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 125.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 125.7 + * 125.8 + * This code is free software; you can redistribute it and/or modify it 125.9 + * under the terms of the GNU General Public License version 2 only, as 125.10 + * published by the Free Software Foundation. 125.11 + * 125.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 125.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 125.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 125.15 + * version 2 for more details (a copy is included in the LICENSE file that 125.16 + * accompanied this code). 125.17 + * 125.18 + * You should have received a copy of the GNU General Public License version 125.19 + * 2 along with this work; if not, write to the Free Software Foundation, 125.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 125.21 + * 125.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 125.23 + * or visit www.oracle.com if you need additional information or have any 125.24 + * questions. 125.25 + */ 125.26 + 125.27 +/** 125.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 125.29 + * 125.30 + * @test 125.31 + * @run 125.32 + * @option --language=es6 */ 125.33 + 125.34 +"use strict"; 125.35 + 125.36 +let a = 2; 125.37 +let c = 2; 125.38 +print(a, c); 125.39 + 125.40 +function f(x) { 125.41 + let a = 5; 125.42 + const c = 10; 125.43 + print(a, c); 125.44 + if (x) { 125.45 + let a = 42; 125.46 + const c = 43; 125.47 + print(a, c); 125.48 + } 125.49 + print(a, c); 125.50 + 125.51 + function inner() { 125.52 + (function() { 125.53 + print(a, c); 125.54 + })(); 125.55 + } 125.56 + inner(); 125.57 +} 125.58 + 125.59 +f(true); 125.60 +f(false); 125.61 + 125.62 +(function() { 125.63 + (function() { 125.64 + print(a, c); 125.65 + })(); 125.66 +})(); 125.67 + 125.68 +function outer() { 125.69 + print(a, c); 125.70 +} 125.71 +outer(); 125.72 +
126.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 126.2 +++ b/test/script/basic/es6/let.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 126.3 @@ -0,0 +1,10 @@ 126.4 +2 2 126.5 +5 10 126.6 +42 43 126.7 +5 10 126.8 +5 10 126.9 +5 10 126.10 +5 10 126.11 +5 10 126.12 +2 2 126.13 +2 2
127.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 127.2 +++ b/test/script/basic/es6/let_const_closure.js Tue Sep 16 13:59:37 2014 -0700 127.3 @@ -0,0 +1,123 @@ 127.4 +/* 127.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 127.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 127.7 + * 127.8 + * This code is free software; you can redistribute it and/or modify it 127.9 + * under the terms of the GNU General Public License version 2 only, as 127.10 + * published by the Free Software Foundation. 127.11 + * 127.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 127.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 127.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 127.15 + * version 2 for more details (a copy is included in the LICENSE file that 127.16 + * accompanied this code). 127.17 + * 127.18 + * You should have received a copy of the GNU General Public License version 127.19 + * 2 along with this work; if not, write to the Free Software Foundation, 127.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 127.21 + * 127.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 127.23 + * or visit www.oracle.com if you need additional information or have any 127.24 + * questions. 127.25 + */ 127.26 + 127.27 +/** 127.28 + * JDK-8057678: Tests for let&const keywords in Nashorn 127.29 + * 127.30 + * @test 127.31 + * @run 127.32 + * @option --language=es6 127.33 + * @option -scripting 127.34 + */ 127.35 + 127.36 +function tryIt(code) { 127.37 + try { 127.38 + eval(code) 127.39 + } catch (e) { 127.40 + print(e) 127.41 + } 127.42 +} 127.43 + 127.44 + 127.45 +tryIt(<<CODE 127.46 + function a () { 127.47 + this.val = 41 127.48 + let self = this 127.49 + this.b = function () { 127.50 + return self.val; 127.51 + } 127.52 + } 127.53 + c = new a() 127.54 + print(c.b.call(null)) 127.55 +CODE) 127.56 + 127.57 + 127.58 +tryIt(<<CODE 127.59 + function a () { 127.60 + this.val = 42 127.61 + let self = this 127.62 + this.b = function () { 127.63 + return this.val; 127.64 + }.bind(self) 127.65 + } 127.66 + c = new a() 127.67 + print(c.b.call(null)) 127.68 +CODE) 127.69 + 127.70 +tryIt(<<CODE 127.71 + function a () { 127.72 + this.val = 43 127.73 + const self = this 127.74 + this.b = function () { 127.75 + return self.val; 127.76 + } 127.77 + } 127.78 + c = new a() 127.79 + print(c.b.call(null)) 127.80 +CODE) 127.81 + 127.82 +tryIt(<<CODE 127.83 + function a () { 127.84 + this.val = 44 127.85 + const self = this 127.86 + this.b = function () { 127.87 + return this.val; 127.88 + }.bind(self) 127.89 + } 127.90 + c = new a() 127.91 + print(c.b.call(null)) 127.92 +CODE) 127.93 + 127.94 +tryIt(<<CODE 127.95 + let a = {name : 'test'} 127.96 + let f = function () { 127.97 + print(this.name) 127.98 + } 127.99 + let nf = f.bind(a) 127.100 + nf() 127.101 + if (true) { 127.102 + let a = null 127.103 + nf() 127.104 + } 127.105 + nf() 127.106 +CODE) 127.107 + 127.108 + 127.109 +tryIt(<<CODE 127.110 + let arr = [] 127.111 + for (let i = 0; i < 3; i++) { 127.112 + arr[i] = function(){return i;} 127.113 + } 127.114 + for (let i in arr) { 127.115 + print(arr[i]()) 127.116 + } 127.117 + arr = [] 127.118 + for (var i = 0; i < 3; i++) { 127.119 + (function(i){ 127.120 + arr[i] = function(){return i;} 127.121 + })(i) 127.122 + } 127.123 + for (let i in arr) { 127.124 + print(arr[i]()) 127.125 + } 127.126 +CODE) 127.127 \ No newline at end of file
128.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 128.2 +++ b/test/script/basic/es6/let_const_closure.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 128.3 @@ -0,0 +1,13 @@ 128.4 +41 128.5 +42 128.6 +43 128.7 +44 128.8 +test 128.9 +test 128.10 +test 128.11 +3 128.12 +3 128.13 +3 128.14 +0 128.15 +1 128.16 +2
129.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 129.2 +++ b/test/script/basic/es6/let_const_reuse.js Tue Sep 16 13:59:37 2014 -0700 129.3 @@ -0,0 +1,71 @@ 129.4 +/* 129.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 129.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 129.7 + * 129.8 + * This code is free software; you can redistribute it and/or modify it 129.9 + * under the terms of the GNU General Public License version 2 only, as 129.10 + * published by the Free Software Foundation. 129.11 + * 129.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 129.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 129.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 129.15 + * version 2 for more details (a copy is included in the LICENSE file that 129.16 + * accompanied this code). 129.17 + * 129.18 + * You should have received a copy of the GNU General Public License version 129.19 + * 2 along with this work; if not, write to the Free Software Foundation, 129.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 129.21 + * 129.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 129.23 + * or visit www.oracle.com if you need additional information or have any 129.24 + * questions. 129.25 + */ 129.26 + 129.27 +/** 129.28 + * JDK-8057678: Tests for let&const keywords in Nashorn 129.29 + * 129.30 + * @test 129.31 + * @run 129.32 + * @option --language=es6 129.33 + * @option -scripting 129.34 + */ 129.35 + 129.36 +function tryIt (code) { 129.37 + try { 129.38 + eval(code) 129.39 + } catch (e) { 129.40 + print(e) 129.41 + } 129.42 +} 129.43 + 129.44 +tryIt(<<CODE 129.45 + let a = 23 129.46 + if (true) { 129.47 + a-- 129.48 + let a = 43; 129.49 + } 129.50 +CODE) 129.51 + 129.52 +tryIt(<<CODE 129.53 + const a = 23 129.54 + if (true) { 129.55 + a-- 129.56 + const a = 43; 129.57 + } 129.58 +CODE) 129.59 + 129.60 +tryIt(<<CODE 129.61 + let a = 23 129.62 + if (true) { 129.63 + a-- 129.64 + const a = 43; 129.65 + } 129.66 +CODE) 129.67 + 129.68 +tryIt(<<CODE 129.69 + const a = 23 129.70 + if (true) { 129.71 + a-- 129.72 + let a = 43; 129.73 + } 129.74 +CODE)
130.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 130.2 +++ b/test/script/basic/es6/let_const_reuse.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 130.3 @@ -0,0 +1,8 @@ 130.4 +ReferenceError: "a" is not defined 130.5 +SyntaxError: test/script/basic/es6/let_const_reuse.js#35:9<eval>:3:8 Assignment to constant "a" 130.6 + a-- 130.7 + ^ 130.8 +SyntaxError: test/script/basic/es6/let_const_reuse.js#35:9<eval>:3:8 Assignment to constant "a" 130.9 + a-- 130.10 + ^ 130.11 +ReferenceError: "a" is not defined
131.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 131.2 +++ b/test/script/basic/es6/let_different_types.js Tue Sep 16 13:59:37 2014 -0700 131.3 @@ -0,0 +1,73 @@ 131.4 +/* 131.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 131.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 131.7 + * 131.8 + * This code is free software; you can redistribute it and/or modify it 131.9 + * under the terms of the GNU General Public License version 2 only, as 131.10 + * published by the Free Software Foundation. 131.11 + * 131.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 131.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 131.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 131.15 + * version 2 for more details (a copy is included in the LICENSE file that 131.16 + * accompanied this code). 131.17 + * 131.18 + * You should have received a copy of the GNU General Public License version 131.19 + * 2 along with this work; if not, write to the Free Software Foundation, 131.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 131.21 + * 131.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 131.23 + * or visit www.oracle.com if you need additional information or have any 131.24 + * questions. 131.25 + */ 131.26 + 131.27 +/** 131.28 + * JDK-8057678: Tests for let&const keywords in Nashorn 131.29 + * 131.30 + * @test 131.31 + * @run 131.32 + * @option --language=es6 131.33 + * @option -scripting 131.34 + */ 131.35 + 131.36 +function tryIt (code) { 131.37 + try { 131.38 + eval(code) 131.39 + } catch (e) { 131.40 + print(e) 131.41 + } 131.42 +} 131.43 + 131.44 +tryIt(<<CODE 131.45 + let a = function () { var a = "Hello World!"; return a; } 131.46 + print(typeof a) 131.47 + { 131.48 + let a = 34; 131.49 + print(typeof a) 131.50 + if (true) { 131.51 + let c = 54.7 131.52 + var d = c 131.53 + print(typeof c) 131.54 + print(typeof d) 131.55 + } 131.56 + } 131.57 + print(typeof a) 131.58 + print(typeof a()) 131.59 + print(typeof c) 131.60 + print(typeof d) 131.61 + print(d) 131.62 +CODE) 131.63 + 131.64 +tryIt(<<CODE 131.65 + let a = {} 131.66 + if (true) { 131.67 + function a () { 131.68 + print (typeof a) 131.69 + return 'Hello World!' 131.70 + } 131.71 + print(typeof a) 131.72 + print(a()) 131.73 + } 131.74 + print(typeof a) 131.75 +CODE) 131.76 +
132.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 132.2 +++ b/test/script/basic/es6/let_different_types.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 132.3 @@ -0,0 +1,13 @@ 132.4 +function 132.5 +number 132.6 +number 132.7 +number 132.8 +function 132.9 +string 132.10 +undefined 132.11 +number 132.12 +54.7 132.13 +function 132.14 +function 132.15 +Hello World! 132.16 +object
133.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 133.2 +++ b/test/script/basic/es6/let_loops.js Tue Sep 16 13:59:37 2014 -0700 133.3 @@ -0,0 +1,80 @@ 133.4 +/* 133.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 133.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 133.7 + * 133.8 + * This code is free software; you can redistribute it and/or modify it 133.9 + * under the terms of the GNU General Public License version 2 only, as 133.10 + * published by the Free Software Foundation. 133.11 + * 133.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 133.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 133.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 133.15 + * version 2 for more details (a copy is included in the LICENSE file that 133.16 + * accompanied this code). 133.17 + * 133.18 + * You should have received a copy of the GNU General Public License version 133.19 + * 2 along with this work; if not, write to the Free Software Foundation, 133.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 133.21 + * 133.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 133.23 + * or visit www.oracle.com if you need additional information or have any 133.24 + * questions. 133.25 + */ 133.26 + 133.27 +/** 133.28 + * JDK-8057678: Tests for let&const keywords in Nashorn 133.29 + * 133.30 + * @test 133.31 + * @run 133.32 + * @option --language=es6 133.33 + * @option -scripting 133.34 + */ 133.35 + 133.36 + 133.37 +function tryIt (code) { 133.38 + try { 133.39 + eval(code) 133.40 + } catch (e) { 133.41 + print(e) 133.42 + } 133.43 +} 133.44 + 133.45 +tryIt(<<CODE 133.46 + let a = 2; 133.47 + do { 133.48 + a--; 133.49 + let b = a; 133.50 + } while (a > 0); 133.51 + print(a) 133.52 + print(b) 133.53 +CODE) 133.54 + 133.55 +tryIt(<<CODE 133.56 + let a = 2 133.57 + while(a > 0) { 133.58 + a-- 133.59 + let b = a 133.60 + } 133.61 + print(a) 133.62 + print(b) 133.63 +CODE) 133.64 + 133.65 +tryIt(<<CODE 133.66 + let a = 2 133.67 + while(a > 0) { 133.68 + a-- 133.69 + const b = a 133.70 + } 133.71 + print(a) 133.72 + print(b) 133.73 +CODE) 133.74 + 133.75 +tryIt(<<CODE 133.76 + let a = 2; 133.77 + do { 133.78 + a--; 133.79 + const b = a; 133.80 + } while (a > 0); 133.81 + print(a) 133.82 + print(b) 133.83 +CODE)
134.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 134.2 +++ b/test/script/basic/es6/let_loops.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 134.3 @@ -0,0 +1,8 @@ 134.4 +0 134.5 +ReferenceError: "b" is not defined 134.6 +0 134.7 +ReferenceError: "b" is not defined 134.8 +0 134.9 +ReferenceError: "b" is not defined 134.10 +0 134.11 +ReferenceError: "b" is not defined
135.1 --- a/test/script/basic/optimistic_check_type.js Thu Sep 11 15:34:13 2014 -0700 135.2 +++ b/test/script/basic/optimistic_check_type.js Tue Sep 16 13:59:37 2014 -0700 135.3 @@ -36,13 +36,18 @@ 135.4 135.5 // Testing conditional operator 135.6 print(inspect("" ? b : x.a, "ternary operator")) 135.7 -print(inspect(x.b ? b : x.a, "ternary operator")) 135.8 -print(inspect(c ? b : a, "ternary operator")) 135.9 -print(inspect(!c ? b : a, "ternary operator")) 135.10 -print(inspect(d ? b : x.c, "ternary operator")) 135.11 +var b1 = b; 135.12 +print(inspect(x.b ? b1 : x.a, "ternary operator")) 135.13 +var b2 = b; 135.14 +print(inspect(c ? b2 : a, "ternary operator")) 135.15 +var b3 = b; 135.16 +print(inspect(!c ? b3 : a, "ternary operator")) 135.17 +var b4 = b; 135.18 +print(inspect(d ? b4 : x.c, "ternary operator")) 135.19 print(inspect(x.c ? a : c, "ternary operator")) 135.20 print(inspect(c ? d : a, "ternary operator")) 135.21 -print(inspect(c ? +a : b, "ternary operator")) 135.22 +var b5 = b; 135.23 +print(inspect(c ? +a : b5, "ternary operator")) 135.24 135.25 // Testing format methods 135.26 print(inspect(b.toFixed(2), "global double toFixed()")) 135.27 @@ -53,11 +58,14 @@ 135.28 print(inspect(trees[1], "member object")) 135.29 trees[1] = undefined; 135.30 print(inspect(trees[1], "member undefined")) 135.31 -print(inspect(1 in trees ? b : a, "conditional on array member")) 135.32 +var b6=b; 135.33 +print(inspect(1 in trees ? b6 : a, "conditional on array member")) 135.34 delete trees[2] 135.35 -print(inspect(2 in trees ? b : a, "conditional on array member")) 135.36 +var b7=b; 135.37 +print(inspect(2 in trees ? b7 : a, "conditional on array member")) 135.38 print(inspect(3 in trees ? trees[2]="bay" : a, "conditional on array member")) 135.39 -print(inspect("oak" in trees ? b : a, "conditional on array member")) 135.40 +var b8=b; 135.41 +print(inspect("oak" in trees ? b8 : a, "conditional on array member")) 135.42 135.43 // Testing nested functions and return value 135.44 function f1() {
136.1 --- a/test/script/basic/splitter.js Thu Sep 11 15:34:13 2014 -0700 136.2 +++ b/test/script/basic/splitter.js Tue Sep 16 13:59:37 2014 -0700 136.3 @@ -30,7 +30,5 @@ 136.4 * @fork 136.5 */ 136.6 136.7 -load(__DIR__ + 'prototype.js'); 136.8 -load(__DIR__ + 'yui.js'); 136.9 load(__DIR__ + 'NASHORN-689.js'); 136.10 load(__DIR__ + 'NASHORN-58.js');
137.1 --- a/test/script/basic/splitter.js.EXPECTED Thu Sep 11 15:34:13 2014 -0700 137.2 +++ b/test/script/basic/splitter.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 137.3 @@ -1,6 +1,3 @@ 137.4 -parsed and compiled ok prototype.js 137.5 -parsed and compiled ok yui-min.js 137.6 -parsed and compiled ok yui.js 137.7 a=10 137.8 a=9 137.9 a=8
138.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 138.2 +++ b/test/script/basic/splitter_prototype.js Tue Sep 16 13:59:37 2014 -0700 138.3 @@ -0,0 +1,33 @@ 138.4 +/* 138.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 138.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 138.7 + * 138.8 + * This code is free software; you can redistribute it and/or modify it 138.9 + * under the terms of the GNU General Public License version 2 only, as 138.10 + * published by the Free Software Foundation. 138.11 + * 138.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 138.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 138.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 138.15 + * version 2 for more details (a copy is included in the LICENSE file that 138.16 + * accompanied this code). 138.17 + * 138.18 + * You should have received a copy of the GNU General Public License version 138.19 + * 2 along with this work; if not, write to the Free Software Foundation, 138.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 138.21 + * 138.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 138.23 + * or visit www.oracle.com if you need additional information or have any 138.24 + * questions. 138.25 + */ 138.26 + 138.27 +/** 138.28 + * Test various scripts with low splitter threshold 138.29 + * 138.30 + * @test 138.31 + * @option -Dnashorn.compiler.splitter.threshold=200 138.32 + * @runif external.prototype 138.33 + * @fork 138.34 + */ 138.35 + 138.36 +load(__DIR__ + 'prototype.js');
139.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 139.2 +++ b/test/script/basic/splitter_prototype.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 139.3 @@ -0,0 +1,1 @@ 139.4 +parsed and compiled ok prototype.js
140.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 140.2 +++ b/test/script/basic/splitter_yui.js Tue Sep 16 13:59:37 2014 -0700 140.3 @@ -0,0 +1,33 @@ 140.4 +/* 140.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 140.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 140.7 + * 140.8 + * This code is free software; you can redistribute it and/or modify it 140.9 + * under the terms of the GNU General Public License version 2 only, as 140.10 + * published by the Free Software Foundation. 140.11 + * 140.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 140.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 140.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 140.15 + * version 2 for more details (a copy is included in the LICENSE file that 140.16 + * accompanied this code). 140.17 + * 140.18 + * You should have received a copy of the GNU General Public License version 140.19 + * 2 along with this work; if not, write to the Free Software Foundation, 140.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 140.21 + * 140.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 140.23 + * or visit www.oracle.com if you need additional information or have any 140.24 + * questions. 140.25 + */ 140.26 + 140.27 +/** 140.28 + * Test various scripts with low splitter threshold 140.29 + * 140.30 + * @test 140.31 + * @option -Dnashorn.compiler.splitter.threshold=200 140.32 + * @runif external.yui 140.33 + * @fork 140.34 + */ 140.35 + 140.36 +load(__DIR__ + 'yui.js');
141.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 141.2 +++ b/test/script/basic/splitter_yui.js.EXPECTED Tue Sep 16 13:59:37 2014 -0700 141.3 @@ -0,0 +1,2 @@ 141.4 +parsed and compiled ok yui-min.js 141.5 +parsed and compiled ok yui.js
142.1 --- a/test/script/trusted/JDK-8006529.js Thu Sep 11 15:34:13 2014 -0700 142.2 +++ b/test/script/trusted/JDK-8006529.js Tue Sep 16 13:59:37 2014 -0700 142.3 @@ -120,7 +120,7 @@ 142.4 142.5 var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class) 142.6 var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class) 142.7 -var CompilerConstructor = Compiler.class.getConstructor(Context.class, ScriptEnvironment.class, CodeInstaller.class, Source.class, boolean.class); 142.8 +var CompilerConstructor = Compiler.class.getConstructor(Context.class, ScriptEnvironment.class, CodeInstaller.class, Source.class, ErrorManager.class, boolean.class); 142.9 142.10 // compile(script) -- compiles a script specified as a string with its 142.11 // source code, returns a jdk.nashorn.internal.ir.FunctionNode object 142.12 @@ -134,7 +134,7 @@ 142.13 var parser = ParserConstructor.newInstance(env, source, ThrowErrorManager.class.newInstance()); 142.14 var func = parseMethod.invoke(parser); 142.15 142.16 - var compiler = CompilerConstructor.newInstance(ctxt, env, null, source, false); 142.17 + var compiler = CompilerConstructor.newInstance(ctxt, env, null, source, null, false); 142.18 142.19 return compileMethod.invoke(compiler, func, phases); 142.20 };
143.1 --- a/test/src/jdk/nashorn/api/scripting/ScopeTest.java Thu Sep 11 15:34:13 2014 -0700 143.2 +++ b/test/src/jdk/nashorn/api/scripting/ScopeTest.java Tue Sep 16 13:59:37 2014 -0700 143.3 @@ -407,6 +407,75 @@ 143.4 Assert.assertEquals(e.eval(sharedScript, newCtxt), "newer context"); 143.5 } 143.6 143.7 + 143.8 + /** 143.9 + * Test multi-threaded access to prototype user accessor properties for shared script classes with multiple globals. 143.10 + */ 143.11 + @Test 143.12 + public static void multiThreadedAccessorTest() throws ScriptException, InterruptedException { 143.13 + final ScriptEngineManager m = new ScriptEngineManager(); 143.14 + final ScriptEngine e = m.getEngineByName("nashorn"); 143.15 + final Bindings b = e.createBindings(); 143.16 + final ScriptContext origContext = e.getContext(); 143.17 + final ScriptContext newCtxt = new SimpleScriptContext(); 143.18 + newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE); 143.19 + 143.20 + e.eval("Object.defineProperty(Object.prototype, 'foo', { get: function() 'original context' })", origContext); 143.21 + e.eval("Object.defineProperty(Object.prototype, 'foo', { get: function() 'new context', configurable: true })", newCtxt); 143.22 + final String sharedScript = "({}).foo"; 143.23 + 143.24 + final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000)); 143.25 + final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000)); 143.26 + t1.start(); 143.27 + t2.start(); 143.28 + t1.join(); 143.29 + t2.join(); 143.30 + 143.31 + final Object obj3 = e.eval("delete Object.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt); 143.32 + assertEquals(obj3, "newer context"); 143.33 + final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000)); 143.34 + final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000)); 143.35 + 143.36 + t3.start(); 143.37 + t4.start(); 143.38 + t3.join(); 143.39 + t4.join(); 143.40 + } 143.41 + 143.42 + /** 143.43 + * Test multi-threaded access to primitive prototype user accessor properties for shared script classes with multiple globals. 143.44 + */ 143.45 + @Test 143.46 + public static void multiThreadedPrimitiveAccessorTest() throws ScriptException, InterruptedException { 143.47 + final ScriptEngineManager m = new ScriptEngineManager(); 143.48 + final ScriptEngine e = m.getEngineByName("nashorn"); 143.49 + final Bindings b = e.createBindings(); 143.50 + final ScriptContext origContext = e.getContext(); 143.51 + final ScriptContext newCtxt = new SimpleScriptContext(); 143.52 + newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE); 143.53 + 143.54 + e.eval("Object.defineProperty(String.prototype, 'foo', { get: function() 'original context' })", origContext); 143.55 + e.eval("Object.defineProperty(String.prototype, 'foo', { get: function() 'new context' })", newCtxt); 143.56 + final String sharedScript = "''.foo"; 143.57 + 143.58 + final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000)); 143.59 + final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000)); 143.60 + t1.start(); 143.61 + t2.start(); 143.62 + t1.join(); 143.63 + t2.join(); 143.64 + 143.65 + final Object obj3 = e.eval("delete String.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt); 143.66 + assertEquals(obj3, "newer context"); 143.67 + final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000)); 143.68 + final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000)); 143.69 + 143.70 + t3.start(); 143.71 + t4.start(); 143.72 + t3.join(); 143.73 + t4.join(); 143.74 + } 143.75 + 143.76 /** 143.77 * Test multi-threaded scope function invocation for shared script classes with multiple globals. 143.78 */
144.1 --- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Thu Sep 11 15:34:13 2014 -0700 144.2 +++ b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Tue Sep 16 13:59:37 2014 -0700 144.3 @@ -98,11 +98,16 @@ 144.4 compileTestSet(new File(TEST262_SUITE_DIR), new TestFilter() { 144.5 @Override 144.6 public boolean exclude(final File file, final String content) { 144.7 - return content.indexOf("@negative") != -1; 144.8 + return content != null && content.contains("@negative"); 144.9 } 144.10 }); 144.11 } 144.12 - compileTestSet(new File(TEST_BASIC_DIR), null); 144.13 + compileTestSet(new File(TEST_BASIC_DIR), new TestFilter() { 144.14 + @Override 144.15 + public boolean exclude(final File file, final String content) { 144.16 + return file.getName().equals("es6"); 144.17 + } 144.18 + }); 144.19 compileTestSet(new File(TEST_NODE_DIR, "node"), null); 144.20 compileTestSet(new File(TEST_NODE_DIR, "src"), null); 144.21 } 144.22 @@ -136,6 +141,9 @@ 144.23 private int skipped; 144.24 144.25 private void compileJSDirectory(final File dir, final TestFilter filter) { 144.26 + if (filter != null && filter.exclude(dir, null)) { 144.27 + return; 144.28 + } 144.29 for (final File f : dir.listFiles()) { 144.30 if (f.isDirectory()) { 144.31 compileJSDirectory(f, filter);
145.1 --- a/test/src/jdk/nashorn/internal/parser/ParserTest.java Thu Sep 11 15:34:13 2014 -0700 145.2 +++ b/test/src/jdk/nashorn/internal/parser/ParserTest.java Tue Sep 16 13:59:37 2014 -0700 145.3 @@ -82,11 +82,16 @@ 145.4 parseTestSet(TEST262_SUITE_DIR, new TestFilter() { 145.5 @Override 145.6 public boolean exclude(final File file, final String content) { 145.7 - return content.indexOf("@negative") != -1; 145.8 + return content != null && content.contains("@negative"); 145.9 } 145.10 }); 145.11 } 145.12 - parseTestSet(TEST_BASIC_DIR, null); 145.13 + parseTestSet(TEST_BASIC_DIR, new TestFilter() { 145.14 + @Override 145.15 + public boolean exclude(final File file, final String content) { 145.16 + return file.getName().equals("es6"); 145.17 + } 145.18 + }); 145.19 } 145.20 145.21 private void parseTestSet(final String testSet, final TestFilter filter) { 145.22 @@ -120,6 +125,9 @@ 145.23 private int skipped; 145.24 145.25 private void parseJSDirectory(final File dir, final TestFilter filter) { 145.26 + if (filter != null && filter.exclude(dir, null)) { 145.27 + return; 145.28 + } 145.29 for (final File f : dir.listFiles()) { 145.30 if (f.isDirectory()) { 145.31 parseJSDirectory(f, filter);
146.1 --- a/test/src/jdk/nashorn/internal/test/framework/TestFinder.java Thu Sep 11 15:34:13 2014 -0700 146.2 +++ b/test/src/jdk/nashorn/internal/test/framework/TestFinder.java Tue Sep 16 13:59:37 2014 -0700 146.3 @@ -261,14 +261,17 @@ 146.4 isTest = false; 146.5 isNotTest = true; 146.6 break; 146.7 - case "@runif": 146.8 - if (System.getProperty(scanner.next()) != null) { 146.9 + case "@runif": { 146.10 + final String prop = scanner.next(); 146.11 + if (System.getProperty(prop) != null) { 146.12 shouldRun = true; 146.13 } else { 146.14 + factory.log("WARNING: (" + prop + ") skipping " + testFile); 146.15 isTest = false; 146.16 isNotTest = true; 146.17 } 146.18 break; 146.19 + } 146.20 case "@run": 146.21 shouldRun = true; 146.22 break;