Permalink
Browse files

[IR] Clean out some old hacks that are no longer needed -- this also …

…fixes

some bugs in 1.9 mode; but this breaks some LocalJumpError specs for the
break instruction (in both 1.8 and 1.9 mode) which needs fixing.
  • Loading branch information...
1 parent 74e77c8 commit 549bec018bb1abfed53de9dd7389115e338dfa7d @subbuss subbuss committed Jan 2, 2012
@@ -51,9 +51,7 @@ public Object interpret(ThreadContext context, DynamicScope currDynScope, IRubyO
Object blk = (Object) blockArg.retrieve(context, self, currDynScope, temp);
if (blk instanceof RubyProc) blk = ((RubyProc)blk).getBlock();
if (blk instanceof RubyNil) blk = Block.NULL_BLOCK;
- // Blocks that get yielded are always normal
Block b = (Block)blk;
- b.type = Block.Type.NORMAL;
if (yieldArg == null) {
return b.yieldSpecific(context);
} else {
@@ -47,9 +47,6 @@ protected Block prepareBlock(ThreadContext context, IRubyObject self, DynamicSco
throw new RuntimeException("Unhandled case in CallInstr:prepareBlock. Got block arg: " + value);
}
- // Blocks passed in through calls are always normal blocks, no matter where they came from
- block.type = Block.Type.NORMAL;
-
return block;
}
}
@@ -5,6 +5,7 @@
import org.jruby.Ruby;
import org.jruby.RubyInstanceConfig;
import org.jruby.RubyModule;
+import org.jruby.RubyProc;
import org.jruby.ast.Node;
import org.jruby.ast.RootNode;
import org.jruby.compiler.ir.IRBuilder;
@@ -66,9 +67,9 @@ public static boolean isDebug() {
return RubyInstanceConfig.IR_DEBUG;
}
- private static IRScope getEvalContainerScope(Ruby runtime, StaticScope evalScope) {
+ private static IRScope getEvalContainerScope(Ruby runtime, StaticScope evalScope) {
// SSS FIXME: Weirdness here. We cannot get the containing IR scope from evalScope because of static-scope wrapping
- // that is going on
+ // that is going on
// 1. In all cases, DynamicScope.getEvalScope wraps the executing static scope in a new local scope.
// 2. For instance-eval (module-eval, class-eval) scenarios, there is an extra scope that is added to
// the stack in ThreadContext.java:preExecuteUnder
@@ -77,10 +78,10 @@ private static IRScope getEvalContainerScope(Ruby runtime, StaticScope evalScope
// work, I unwarp once more and I am guaranteed to get the IR scope I want.
IRScope containingIRScope = ((IRStaticScope)evalScope.getEnclosingScope()).getIRScope();
if (containingIRScope == null) containingIRScope = ((IRStaticScope)evalScope.getEnclosingScope().getEnclosingScope()).getIRScope();
- return containingIRScope;
- }
+ return containingIRScope;
+ }
- private static IRScope getEvalContainerScope19(Ruby runtime, StaticScope evalScope) {
+ private static IRScope getEvalContainerScope19(Ruby runtime, StaticScope evalScope) {
// SSS FIXME: Weirdness here. Different from 1.8. There is no localvar scope wrapping.
// 1. For instance-eval (module-eval, class-eval) scenarios, there is an extra scope that is added to
// the stack in ThreadContext.java:preExecuteUnder
@@ -90,16 +91,16 @@ private static IRScope getEvalContainerScope19(Ruby runtime, StaticScope evalSco
IRScope containingIRScope = ((IRStaticScope)evalScope).getIRScope();
if (containingIRScope == null) containingIRScope = ((IRStaticScope)evalScope.getEnclosingScope()).getIRScope();
if (containingIRScope == null) containingIRScope = ((IRStaticScope)evalScope.getEnclosingScope().getEnclosingScope()).getIRScope();
- return containingIRScope;
- }
+ return containingIRScope;
+ }
public static IRubyObject interpretCommonEval(Ruby runtime, String file, int lineNumber, RootNode rootNode, IRubyObject self, Block block) {
- boolean is_1_9 = runtime.is1_9();
+ boolean is_1_9 = runtime.is1_9();
// SSS FIXME: Is this required here since the IR version cannot change from eval-to-eval? This is much more of a global setting.
if (is_1_9) IRBuilder.setRubyVersion("1.9");
StaticScope ss = rootNode.getStaticScope();
- IRScope containingIRScope = is_1_9 ? getEvalContainerScope19(runtime, ss) : getEvalContainerScope(runtime, ss);
+ IRScope containingIRScope = is_1_9 ? getEvalContainerScope19(runtime, ss) : getEvalContainerScope(runtime, ss);
IREvalScript evalScript = IRBuilder.createIRBuilder(runtime.getIRManager()).buildEvalRoot(ss, containingIRScope, file, lineNumber, rootNode);
evalScript.prepareForInterpretation();
// evalScript.runCompilerPass(new CallSplitter());
@@ -272,7 +273,7 @@ public static IRubyObject interpret(ThreadContext context, IRubyObject self,
break;
}
case RECV_CLOSURE: {
- result = block == Block.NULL_BLOCK ? context.nil : runtime.newProc(Type.PROC, block);
+ result = block == Block.NULL_BLOCK ? context.nil : runtime.newProc(block.type, block);
resultVar = ((ResultInstr)lastInstr).getResult();
ipc++;
break;
@@ -352,7 +353,7 @@ public static IRubyObject interpret(ThreadContext context, IRubyObject self,
return handleReturnJumpInClosure(scope, rj, blockType);
} catch (IRBreakJump bj) {
if ((lastInstr instanceof BreakInstr) || bj.breakInEval) {
- handleBreakJumpInEval(context, scope, bj, blockType, inClosure);
+ handleBreakJump(context, scope, bj, self, blockType, inClosure);
} else if (inLambda(blockType)) {
// We just unwound all the way up because of a non-local break
throw IRException.BREAK_LocalJumpError.getException(runtime);
@@ -448,16 +449,22 @@ private static IRubyObject handleReturnJumpInClosure(IRScope scope, IRReturnJump
throw rj;
}
- private static void handleBreakJumpInEval(ThreadContext context, IRScope scope, IRBreakJump bj, Type blockType, boolean inClosure) throws RaiseException, IRBreakJump {
+ private static void handleBreakJump(ThreadContext context, IRScope scope, IRBreakJump bj, IRubyObject self, Type blockType, boolean inClosure) throws RaiseException, IRBreakJump {
bj.breakInEval = false; // Clear eval flag
// Error
if (!inClosure || inProc(blockType)) throw IRException.BREAK_LocalJumpError.getException(context.getRuntime());
// Lambda special case. We are in a lambda and breaking out of it requires popping out exactly one level up.
- if (inLambda(blockType)) bj.caughtByLambda = true;
+ if (inLambda(blockType)) {
+ if (bj.scopeToReturnTo == null || context.scopeExistsOnCallStack(bj.scopeToReturnTo.getStaticScope())) bj.caughtByLambda = true;
+ // Cannot return to the call that we have long since exited.
+ else throw IRException.BREAK_LocalJumpError.getException(context.getRuntime());
+ }
// If we are in an eval, record it so we can account for it
- else if (scope instanceof IREvalScript) bj.breakInEval = true;
+ else if (scope instanceof IREvalScript) {
+ bj.breakInEval = true;
+ }
// Pass it upward
throw bj;
@@ -127,8 +127,8 @@ private IRubyObject prepareArrayArgsForCall(Ruby ruby, IRubyObject value) {
}
protected IRubyObject[] prepareArgumentsForYield(ThreadContext context, IRubyObject[] args, Block.Type type) {
+ // SSS FIXME: Hmm .. yield can yield to blocks other than NORMAL block type as well.
int blockArity = arity().getValue();
- if (type != Block.Type.NORMAL) throw new RuntimeException("JRuby Internal Error. Trying to yield to a " + type + " block. Only NORMAL blocks can be yielded to.");
if (args.length == 1) {
IRubyObject soleArg = args[0];
@@ -48,6 +48,17 @@ public InterpretedIRBlockBody19(IRClosure closure, Arity arity, int argumentType
}
}
+ private IRubyObject[] getYieldArgs(ThreadContext context, IRubyObject value, boolean isYieldSpecific, boolean isArray, Type type) {
+ IRubyObject[] args;
+ if (value == null) {
+ if (type == Block.Type.LAMBDA) arity().checkArity(context.getRuntime(), new IRubyObject[] {});
+ args = IRubyObject.NULL_ARRAY;
+ } else {
+ args = convertValueIntoArgArray(context, value, isYieldSpecific, isArray);
+ }
+ return args;
+ }
+
// SSS: Looks like yieldSpecific and yieldArray need to treat array unwrapping differently.
// This is a little baffling to me. I think the runtime library code needs to turn off
// the isArray flag if it wants an array and not create this artificial distinction
@@ -71,13 +82,13 @@ public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0, IRubyO
}
private IRubyObject yieldSpecificInternal(ThreadContext context, IRubyObject value, IRubyObject self, RubyModule klass, boolean isArray, Binding binding, Type type) {
- IRubyObject[] args = (value == null) ? IRubyObject.NULL_ARRAY : convertValueIntoArgArray(context, value, true, isArray);
+ IRubyObject[] args = getYieldArgs(context, value, true, isArray, type);
return commonYieldPath(context, args, self, klass, binding, type, Block.NULL_BLOCK);
}
@Override
public IRubyObject yield(ThreadContext context, IRubyObject value, IRubyObject self, RubyModule klass, boolean isArray, Binding binding, Type type) {
- IRubyObject[] args = (value == null) ? IRubyObject.NULL_ARRAY : convertValueIntoArgArray(context, value, false, isArray);
+ IRubyObject[] args = getYieldArgs(context, value, false, isArray, type);
return commonYieldPath(context, args, self, klass, binding, type, Block.NULL_BLOCK);
}

0 comments on commit 549bec0

Please sign in to comment.