Mercurial > people > rkennke > jdk9-shenandoah-final > nashorn
changeset 434:e27ebcfed6fa
8019822: Duplicate name and signature in finally block
Reviewed-by: jlaskey, sundar
author | attila |
---|---|
date | Fri, 12 Jul 2013 11:58:42 +0200 |
parents | 1a6b1799f533 |
children | 8108ba8366fd 5cdf4352ee0b |
files | src/jdk/nashorn/internal/codegen/CodeGenerator.java test/script/basic/JDK-8019822.js |
diffstat | 2 files changed, 64 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Jul 12 15:27:16 2013 +0530 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Jul 12 11:58:42 2013 +0200 @@ -55,10 +55,12 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.TreeMap; import jdk.nashorn.internal.codegen.ClassEmitter.Flag; import jdk.nashorn.internal.codegen.CompilerConstants.Call; @@ -184,6 +186,8 @@ /** From what size should we use spill instead of fields for JavaScript objects? */ private static final int OBJECT_SPILL_THRESHOLD = 300; + private final Set<String> emittedMethods = new HashSet<>(); + /** * Constructor. * @@ -490,6 +494,9 @@ @Override public boolean enterBlock(final Block block) { + if(lc.isFunctionBody() && emittedMethods.contains(lc.getCurrentFunction().getName())) { + return false; + } method.label(block.getEntryLabel()); initLocals(block); @@ -1007,17 +1014,28 @@ return false; } - LOG.info("=== BEGIN ", functionNode.getName()); - - assert functionNode.getCompileUnit() != null : "no compile unit for " + functionNode.getName() + " " + Debug.id(functionNode); - unit = lc.pushCompileUnit(functionNode.getCompileUnit()); - assert lc.hasCompileUnits(); - - method = lc.pushMethodEmitter(unit.getClassEmitter().method(functionNode)); - // new method - reset last line number - lastLineNumber = -1; - // Mark end for variable tables. - method.begin(); + final String fnName = functionNode.getName(); + // NOTE: we only emit the method for a function with the given name once. We can have multiple functions with + // the same name as a result of inlining finally blocks. However, in the future -- with type specialization, + // notably -- we might need to check for both name *and* signature. Of course, even that might not be + // sufficient; the function might have a code dependency on the type of the variables in its enclosing scopes, + // and the type of such a variable can be different in catch and finally blocks. So, in the future we will have + // to decide to either generate a unique method for each inlined copy of the function, maybe figure out its + // exact type closure and deduplicate based on that, or just decide that functions in finally blocks aren't + // worth it, and generate one method with most generic type closure. + if(!emittedMethods.contains(fnName)) { + LOG.info("=== BEGIN ", fnName); + + assert functionNode.getCompileUnit() != null : "no compile unit for " + fnName + " " + Debug.id(functionNode); + unit = lc.pushCompileUnit(functionNode.getCompileUnit()); + assert lc.hasCompileUnits(); + + method = lc.pushMethodEmitter(unit.getClassEmitter().method(functionNode)); + // new method - reset last line number + lastLineNumber = -1; + // Mark end for variable tables. + method.begin(); + } return true; } @@ -1025,13 +1043,14 @@ @Override public Node leaveFunctionNode(final FunctionNode functionNode) { try { - method.end(); // wrap up this method - unit = lc.popCompileUnit(functionNode.getCompileUnit()); - method = lc.popMethodEmitter(method); - LOG.info("=== END ", functionNode.getName()); + if(emittedMethods.add(functionNode.getName())) { + method.end(); // wrap up this method + unit = lc.popCompileUnit(functionNode.getCompileUnit()); + method = lc.popMethodEmitter(method); + LOG.info("=== END ", functionNode.getName()); + } final FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.EMITTED); - newFunctionObject(newFunctionNode, functionNode); return newFunctionNode; } catch (final Throwable t) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8019822.js Fri Jul 12 11:58:42 2013 +0200 @@ -0,0 +1,29 @@ +/* + * 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-8019822: Duplicate name/signature for a function in finally block + * + * @test + */ +try { function (x) /x/ } finally { (function(id) { return id }); }