# HG changeset patch # User lana # Date 1437690512 25200 # Node ID 1e145ba49d483d6779bd54e615c77a5b02477871 # Parent 730ad816ef170e504f4927f2f2733568b45881bd# Parent fa5c0e50b2cf941e889168d2e2deb0a231ba6657 Merge diff -r 730ad816ef17 -r 1e145ba49d48 nashorn/make/build.xml --- a/nashorn/make/build.xml Thu Jul 23 11:54:34 2015 -0700 +++ b/nashorn/make/build.xml Thu Jul 23 15:28:32 2015 -0700 @@ -48,7 +48,9 @@ - + + + @@ -484,7 +486,7 @@ - + @@ -514,7 +516,7 @@ - + @@ -542,7 +544,7 @@ - + @@ -561,7 +563,7 @@ - + @@ -585,7 +587,7 @@ - + @@ -604,7 +606,7 @@ - + - + @@ -746,7 +748,7 @@ - + @@ -758,7 +760,7 @@ - + diff -r 730ad816ef17 -r 1e145ba49d48 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Thu Jul 23 11:54:34 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Thu Jul 23 15:28:32 2015 -0700 @@ -783,12 +783,13 @@ // If this is a declared variable or a function parameter, delete always fails (except for globals). final String name = ident.getName(); final Symbol symbol = ident.getSymbol(); - final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel()))); - if (failDelete && symbol.isThis()) { + if (symbol.isThis()) { + // Can't delete "this", ignore and return true return LiteralNode.newInstance(unaryNode, true).accept(this); } final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this); + final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel()))); if (!failDelete) { args.add(compilerConstantIdentifier(SCOPE)); @@ -798,6 +799,8 @@ if (failDelete) { request = Request.FAIL_DELETE; + } else if (symbol.isGlobal() && !symbol.isFunctionDeclaration()) { + request = Request.SLOW_DELETE; } } else if (rhs instanceof AccessNode) { final Expression base = ((AccessNode)rhs).getBase(); diff -r 730ad816ef17 -r 1e145ba49d48 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java Thu Jul 23 11:54:34 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java Thu Jul 23 15:28:32 2015 -0700 @@ -56,6 +56,8 @@ REFERENCE_ERROR, /** Delete operator */ DELETE(TokenType.DELETE, Type.BOOLEAN, 1), + /** Delete operator for slow scopes */ + SLOW_DELETE(TokenType.DELETE, Type.BOOLEAN, 1, false), /** Delete operator that always fails -- see Lower */ FAIL_DELETE(TokenType.DELETE, Type.BOOLEAN, 1, false), /** === operator with at least one object */ diff -r 730ad816ef17 -r 1e145ba49d48 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Thu Jul 23 11:54:34 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Thu Jul 23 15:28:32 2015 -0700 @@ -27,6 +27,7 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; +import java.util.Collection; import java.util.List; /** @@ -72,11 +73,6 @@ } @Override - boolean isRecompilable() { - return false; - } - - @Override protected boolean needsCallee() { final boolean needsCallee = code.getFirst().needsCallee(); assert allNeedCallee(needsCallee); @@ -93,6 +89,20 @@ } @Override + CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection forbidden) { + assert isValidCallSite(callSiteType) : callSiteType; + + CompiledFunction best = null; + for (final CompiledFunction candidate: code) { + if (!forbidden.contains(candidate) && candidate.betterThanFinal(best, callSiteType)) { + best = candidate; + } + } + + return best; + } + + @Override MethodType getGenericType() { // We need to ask the code for its generic type. We can't just rely on this function data's arity, as it's not // actually correct for lots of built-ins. E.g. ECMAScript 5.1 section 15.5.3.2 prescribes that diff -r 730ad816ef17 -r 1e145ba49d48 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Thu Jul 23 11:54:34 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Thu Jul 23 15:28:32 2015 -0700 @@ -617,6 +617,7 @@ private CompiledFunction addCode(final MethodHandle target, final Map invalidatedProgramPoints, final MethodType callSiteType, final int fnFlags) { final CompiledFunction cfn = new CompiledFunction(target, this, invalidatedProgramPoints, callSiteType, fnFlags); + assert noDuplicateCode(cfn) : "duplicate code"; code.add(cfn); return cfn; } @@ -683,14 +684,17 @@ @Override synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection forbidden) { - CompiledFunction existingBest = super.getBest(callSiteType, runtimeScope, forbidden); + assert isValidCallSite(callSiteType) : callSiteType; + + CompiledFunction existingBest = pickFunction(callSiteType, false); + if (existingBest == null) { + existingBest = pickFunction(callSiteType, true); // try vararg last + } if (existingBest == null) { existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope, true), callSiteType); } assert existingBest != null; - //we are calling a vararg method with real args - boolean varArgWithRealArgs = existingBest.isVarArg() && !CompiledFunction.isVarArgsType(callSiteType); //if the best one is an apply to call, it has to match the callsite exactly //or we need to regenerate @@ -699,27 +703,18 @@ if (best != null) { return best; } - varArgWithRealArgs = true; - } - if (varArgWithRealArgs) { // special case: we had an apply to call, but we failed to make it fit. // Try to generate a specialized one for this callsite. It may // be another apply to call specialization, or it may not, but whatever // it is, it is a specialization that is guaranteed to fit - final FunctionInitializer fnInit = compileTypeSpecialization(callSiteType, runtimeScope, false); - existingBest = addCode(fnInit, callSiteType); + existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope, false), callSiteType); } return existingBest; } @Override - boolean isRecompilable() { - return true; - } - - @Override public boolean needsCallee() { return getFunctionFlag(FunctionNode.NEEDS_CALLEE); } @@ -827,6 +822,16 @@ return newFn; } + // Make sure code does not contain a compiled function with the same signature as compiledFunction + private boolean noDuplicateCode(final CompiledFunction compiledFunction) { + for (final CompiledFunction cf : code) { + if (cf.type().equals(compiledFunction.type())) { + return false; + } + } + return true; + } + private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); createLogger(); diff -r 730ad816ef17 -r 1e145ba49d48 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java Thu Jul 23 11:54:34 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java Thu Jul 23 15:28:32 2015 -0700 @@ -359,31 +359,13 @@ * scope is not known, but that might cause compilation of code that will need more deoptimization passes. * @return the best function for the specified call site type. */ - CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection forbidden) { - assert callSiteType.parameterCount() >= 2 : callSiteType; // Must have at least (callee, this) - assert callSiteType.parameterType(0).isAssignableFrom(ScriptFunction.class) : callSiteType; // Callee must be assignable from script function - - if (isRecompilable()) { - final CompiledFunction candidate = pickFunction(callSiteType, false); - if (candidate != null) { - return candidate; - } - return pickFunction(callSiteType, true); //try vararg last - } + abstract CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection forbidden); - CompiledFunction best = null; - for (final CompiledFunction candidate: code) { - if (!forbidden.contains(candidate) && candidate.betterThanFinal(best, callSiteType)) { - best = candidate; - } - } - - return best; + boolean isValidCallSite(final MethodType callSiteType) { + return callSiteType.parameterCount() >= 2 && // Must have at least (callee, this) + callSiteType.parameterType(0).isAssignableFrom(ScriptFunction.class); // Callee must be assignable from script function } - - abstract boolean isRecompilable(); - CompiledFunction getGeneric(final ScriptObject runtimeScope) { return getBest(getGenericType(), runtimeScope, CompiledFunction.NO_FUNCTIONS); } diff -r 730ad816ef17 -r 1e145ba49d48 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java Thu Jul 23 11:54:34 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java Thu Jul 23 15:28:32 2015 -0700 @@ -685,6 +685,33 @@ } /** + * ECMA 11.4.1 - delete operator, implementation for slow scopes + * + * This implementation of 'delete' walks the scope chain to find the scope that contains the + * property to be deleted, then invokes delete on it. + * + * @param obj top scope object + * @param property property to delete + * @param strict are we in strict mode + * + * @return true if property was successfully found and deleted + */ + public static boolean SLOW_DELETE(final Object obj, final Object property, final Object strict) { + if (obj instanceof ScriptObject) { + ScriptObject sobj = (ScriptObject) obj; + final String key = property.toString(); + while (sobj != null && sobj.isScope()) { + final FindProperty find = sobj.findProperty(key, false); + if (find != null) { + return sobj.delete(key, Boolean.TRUE.equals(strict)); + } + sobj = sobj.getProto(); + } + } + return DELETE(obj, property, strict); + } + + /** * ECMA 11.4.1 - delete operator, special case * * This is 'delete' that always fails. We have to check strict mode and throw error. diff -r 730ad816ef17 -r 1e145ba49d48 nashorn/test/script/basic/JDK-8131340.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8131340.js Thu Jul 23 15:28:32 2015 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015, 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-8131340: Varargs function is recompiled each time it is linked + * + * @test + * @run + */ + +// This is an indirect test. If repeated calls were to cause recompilation +// this would trigger an assertion in RecompilableScriptFunctionData. + +function varargs() { + return arguments; +} + +varargs(1); +varargs(2); +varargs(3); +varargs(4); +varargs(5); +varargs(6); diff -r 730ad816ef17 -r 1e145ba49d48 nashorn/test/script/basic/JDK-8131683.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8131683.js Thu Jul 23 15:28:32 2015 -0700 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015, 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-8131683: Delete fails over multiple scopes + * + * @test + * @run + */ + +a = 1; +b = 2; +c = 3; + +var A = 1; +var B = 2; +var C = 3; +function D() {} + +print((function() { + var x; // force creation of scope + (function() { x; })(); + return delete a; +})()); + +print((function() { + eval(""); + return delete b; +})()); + +print((function() { + return eval("delete c"); +})()); + +print((function() { + eval("d = 4"); + return eval("delete d"); +})()); + +print(typeof a); +print(typeof b); +print(typeof c); +print(typeof d); + +print((function() { + var x; // force creation of scope + (function() { x; })(); + return delete A; +})()); + +print((function() { + eval(""); + return delete B; +})()); + +print((function() { + return eval("delete C"); +})()); + +print((function() { + eval(""); + return delete D; +})()); + +print(typeof A); +print(typeof B); +print(typeof C); +print(typeof D); + diff -r 730ad816ef17 -r 1e145ba49d48 nashorn/test/script/basic/JDK-8131683.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8131683.js.EXPECTED Thu Jul 23 15:28:32 2015 -0700 @@ -0,0 +1,16 @@ +true +true +true +true +undefined +undefined +undefined +undefined +false +false +false +false +number +number +number +function