--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Oct 01 10:26:53 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Oct 01 12:22:12 2014 +0200
@@ -2800,6 +2800,7 @@
final boolean hasReturn = method.hasReturn();
final SplitMethodEmitter splitMethod = ((SplitMethodEmitter)method);
final List<Label> targets = splitMethod.getExternalTargets();
+ final boolean hasControlFlow = hasReturn || !targets.isEmpty();
final List<BreakableNode> targetNodes = splitMethod.getExternalTargetNodes();
final Type returnType = lc.getCurrentFunction().getReturnType();
@@ -2807,6 +2808,9 @@
// Wrap up this method.
if(method.isReachable()) {
+ if (hasControlFlow) {
+ method.setSplitState(-1);
+ }
method.loadCompilerConstant(RETURN, returnType);
method._return(returnType);
}
@@ -2824,17 +2828,16 @@
throw e;
}
+ //no external jump targets or return in switch node
+ if (!hasControlFlow) {
+ return splitNode;
+ }
+
// Handle return from split method if there was one.
final MethodEmitter caller = method;
final int targetCount = targets.size();
- //no external jump targets or return in switch node
- if (!hasReturn && targets.isEmpty()) {
- return splitNode;
- }
-
- caller.loadCompilerConstant(SCOPE);
- caller.checkcast(Scope.class);
+ caller.loadScope();
caller.invoke(Scope.GET_SPLIT_STATE);
final Label breakLabel = new Label("no_split_state");
@@ -2866,19 +2869,16 @@
caller.loadCompilerConstant(RETURN, returnType);
caller._return(returnType);
} else {
- // Clear split state.
- caller.loadCompilerConstant(SCOPE);
- caller.checkcast(Scope.class);
- caller.load(-1);
- caller.invoke(Scope.SET_SPLIT_STATE);
final BreakableNode targetNode = targetNodes.get(i - 1);
final Label label = targets.get(i - 1);
- final JoinPredecessor jumpOrigin = splitNode.getJumpOrigin(label);
- if(jumpOrigin != null) {
- method.beforeJoinPoint(jumpOrigin);
+ if (!lc.isExternalTarget(splitNode, targetNode)) {
+ final JoinPredecessor jumpOrigin = splitNode.getJumpOrigin(label);
+ if(jumpOrigin != null) {
+ method.beforeJoinPoint(jumpOrigin);
+ }
+ popScopesUntil(targetNode);
}
- popScopesUntil(targetNode);
- caller.splitAwareGoto(lc, targets.get(i - 1), targetNode);
+ caller.splitAwareGoto(lc, label, targetNode);
}
}
caller.label(breakLabel);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Oct 01 10:26:53 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Oct 01 12:22:12 2014 +0200
@@ -103,6 +103,7 @@
import jdk.nashorn.internal.runtime.Debug;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.RewriteException;
+import jdk.nashorn.internal.runtime.Scope;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
@@ -1046,6 +1047,14 @@
return load(getCompilerConstantSymbol(cc), type != null ? type : getCompilerConstantType(cc));
}
+ MethodEmitter loadScope() {
+ return loadCompilerConstant(SCOPE).checkcast(Scope.class);
+ }
+
+ MethodEmitter setSplitState(final int state) {
+ return loadScope().load(state).invoke(Scope.SET_SPLIT_STATE);
+ }
+
void storeCompilerConstant(final CompilerConstants cc) {
storeCompilerConstant(cc, null);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitMethodEmitter.java Wed Oct 01 10:26:53 2014 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitMethodEmitter.java Wed Oct 01 12:22:12 2014 +0200
@@ -25,8 +25,6 @@
package jdk.nashorn.internal.codegen;
-import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
-
import java.util.ArrayList;
import java.util.List;
import jdk.internal.org.objectweb.asm.MethodVisitor;
@@ -34,7 +32,6 @@
import jdk.nashorn.internal.ir.BreakableNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.SplitNode;
-import jdk.nashorn.internal.runtime.Scope;
/**
* Emitter used for splitting methods. Needs to keep track of if there are jump targets
@@ -65,15 +62,13 @@
assert splitNode != null;
final int index = findExternalTarget(lc, label, targetNode);
if (index >= 0) {
- loadCompilerConstant(SCOPE);
- checkcast(Scope.class);
- load(index + 1);
- invoke(Scope.SET_SPLIT_STATE);
- loadUndefined(Type.OBJECT);
- _return(functionNode.getReturnType());
- return;
+ setSplitState(index + 1); // 0 is ordinary return
+ final Type retType = functionNode.getReturnType();
+ loadUndefined(retType);
+ _return(retType);
+ } else {
+ super.splitAwareGoto(lc, label, targetNode);
}
- super.splitAwareGoto(lc, label, targetNode);
}
private int findExternalTarget(final LexicalContext lc, final Label label, final BreakableNode targetNode) {
@@ -94,11 +89,7 @@
@Override
MethodEmitter registerReturn() {
setHasReturn();
- loadCompilerConstant(SCOPE);
- checkcast(Scope.class);
- load(0);
- invoke(Scope.SET_SPLIT_STATE);
- return this;
+ return setSplitState(0);
}
final List<Label> getExternalTargets() {