# HG changeset patch # User lagergren # Date 1370863289 -7200 # Node ID 0e1497116130b52daf02141a48b72eff07b78f52 # Parent 5e4244619d7941fca835f3d1b56c6cceefee8b5d 8015892: canBeUndefined too conservative for some use before declaration cases Reviewed-by: attila, hannesw diff -r 5e4244619d79 -r 0e1497116130 nashorn/src/jdk/nashorn/internal/codegen/Attr.java --- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java Fri Jun 07 17:44:25 2013 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java Mon Jun 10 13:21:29 2013 +0200 @@ -202,18 +202,52 @@ private void acceptDeclarations(final FunctionNode functionNode, final Block body) { // This visitor will assign symbol to all declared variables, except function declarations (which are taken care // in a separate step above) and "var" declarations in for loop initializers. + // + // It also handles the case that a variable can be undefined, e.g + // if (cond) { + // x = x.y; + // } + // var x = 17; + // + // by making sure that no identifier has been found earlier in the body than the + // declaration - if such is the case the identifier is flagged as caBeUndefined to + // be safe if it turns into a local var. Otherwise corrupt bytecode results + body.accept(new NodeVisitor(new LexicalContext()) { + private final Set uses = new HashSet<>(); + private final Set canBeUndefined = new HashSet<>(); + @Override public boolean enterFunctionNode(final FunctionNode nestedFn) { return false; } @Override + public Node leaveIdentNode(final IdentNode identNode) { + uses.add(identNode.getName()); + return identNode; + } + + @Override + public boolean enterVarNode(final VarNode varNode) { + final String name = varNode.getName().getName(); + //if this is used the var node symbol needs to be tagged as can be undefined + if (uses.contains(name)) { + canBeUndefined.add(name); + } + return true; + } + + @Override public Node leaveVarNode(final VarNode varNode) { // any declared symbols that aren't visited need to be typed as well, hence the list if (varNode.isStatement()) { final IdentNode ident = varNode.getName(); final Symbol symbol = defineSymbol(body, ident.getName(), IS_VAR); + if (canBeUndefined.contains(ident.getName())) { + symbol.setType(Type.OBJECT); + symbol.setCanBeUndefined(); + } functionNode.addDeclaredSymbol(symbol); if (varNode.isFunctionDeclaration()) { newType(symbol, FunctionNode.FUNCTION_TYPE); diff -r 5e4244619d79 -r 0e1497116130 nashorn/src/jdk/nashorn/internal/ir/Symbol.java --- a/nashorn/src/jdk/nashorn/internal/ir/Symbol.java Fri Jun 07 17:44:25 2013 +0200 +++ b/nashorn/src/jdk/nashorn/internal/ir/Symbol.java Mon Jun 10 13:21:29 2013 +0200 @@ -462,7 +462,7 @@ */ public void setCanBeUndefined() { assert type.isObject() : type; - if(!canBeUndefined()) { + if (!isParam() && !canBeUndefined()) {//parameters are never undefined assert !isShared(); flags |= CAN_BE_UNDEFINED; } diff -r 5e4244619d79 -r 0e1497116130 nashorn/test/script/basic/JDK-8015892.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8015892.js Mon Jun 10 13:21:29 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8015892.js : use before definition with valid declaration that turns into + * local var must be "canBeUndefined" + * + * @test + * @run + */ + +function doIt() { + if (something) { + x = x.obj; + } else { + var x = "x"; + } +} diff -r 5e4244619d79 -r 0e1497116130 nashorn/test/script/basic/fib_wtf.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/fib_wtf.js Mon Jun 10 13:21:29 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * fib_wtf - obfuscated fibonacci + * + * @test + * @run + */ + +function fib(_) { + for(_=[+[],++[[]][+[]],+[],_],_[++[++[++[[]][+[]]][+[]]][+[]]]=(((_[++[++[++[[]][+[]]][+[]]][+[]]]-(++[[]][+[]]))&(((--[[]][+[]])>>>(++[[]][+[]]))))===(_[++[++[++[[]][+[]]][+[]]][+[]]]-(++[[]][+[]])))?(_[++[++[[]][+[]]][+[]]]=++[[]][+[]],_[++[++[++[[]][+[]]][+[]]][+[]]]-(++[[]][+[]])):+[];_[++[++[++[[]][+[]]][+[]]][+[]]]--;_[+[]]=(_[++[[]][+[]]]=_[++[++[[]][+[]]][+[]]]=_[+[]]+_[++[[]][+[]]])-_[+[]]); + return _[++[++[[]][+[]]][+[]]]; +} + +for (var x = -1; x <= 63; x++) { + print(fib(x)); +} diff -r 5e4244619d79 -r 0e1497116130 nashorn/test/script/basic/fib_wtf.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/fib_wtf.js.EXPECTED Mon Jun 10 13:21:29 2013 +0200 @@ -0,0 +1,65 @@ +0 +0 +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +89 +144 +233 +377 +610 +987 +1597 +2584 +4181 +6765 +10946 +17711 +28657 +46368 +75025 +121393 +196418 +317811 +514229 +832040 +1346269 +2178309 +3524578 +5702887 +9227465 +14930352 +24157817 +39088169 +63245986 +102334155 +165580141 +267914296 +433494437 +701408733 +1134903170 +1836311903 +2971215073 +4807526976 +7778742049 +12586269025 +20365011074 +32951280099 +53316291173 +86267571272 +139583862445 +225851433717 +365435296162 +591286729879 +956722026041 +1548008755920 +2504730781961 +4052739537881 +6557470319842