Skip to content


Browse files Browse the repository at this point in the history
Update block scope handling for new ACP support in IR.
  • Loading branch information
headius committed Oct 7, 2014
1 parent 2065177 commit c3866f0
Showing 1 changed file with 27 additions and 9 deletions.
36 changes: 27 additions & 9 deletions core/src/main/java/org/jruby/runtime/
@@ -1,27 +1,36 @@
package org.jruby.runtime;

import org.jruby.EvalType;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Block.Type;
import org.jruby.runtime.builtin.IRubyObject;

import java.lang.invoke.MethodHandle;

public class CompiledIRBlockBody extends IRBlockBody {
protected final IRClosure closure;
protected final MethodHandle handle;
private final boolean sharedScope;
protected boolean pushScope;
protected boolean reuseParentScope;

public CompiledIRBlockBody(StaticScope staticScope, String parameterList, String fileName, int lineNumber, boolean sharedScope, MethodHandle handle, int arity) {
this(staticScope, parameterList.split(","), fileName, lineNumber, sharedScope, handle, Arity.createArity(arity));

public CompiledIRBlockBody(StaticScope staticScope, String[] parameterList, String fileName, int lineNumber, boolean sharedScope, MethodHandle handle, Arity arity) {
super(staticScope, parameterList, fileName, lineNumber, arity);
this.closure = (IRClosure)staticScope.getIRScope();
this.handle = handle;
this.sharedScope = sharedScope;
this.pushScope = !closure.getFlags().contains(IRFlags.DYNSCOPE_ELIMINATED);
this.reuseParentScope = closure.getFlags().contains(IRFlags.REUSE_PARENT_DYNSCOPE);

protected IRubyObject commonYieldPath(ThreadContext context, IRubyObject[] args, IRubyObject self, Binding binding, Type type, Block block) {

// SSS: Important! Use getStaticScope() to use a copy of the static-scope stored in the block-body.
// Do not use 'closure.getStaticScope()' -- that returns the original copy of the static scope.
// This matters because blocks created for Thread bodies modify the static-scope field of the block-body
Expand All @@ -37,27 +46,36 @@ protected IRubyObject commonYieldPath(ThreadContext context, IRubyObject[] args,
self = useBindingSelf(binding);

DynamicScope newScope = null;
DynamicScope prevScope = binding.getDynamicScope();

// CON FIXME: This is copied from InterpretedIRBlockBody, and obviously means all blocks allocate a scope; we must fix that
// SSS FIXME: Maybe, we should allocate a NoVarsScope/DummyScope for for-loop bodies because the static-scope here
// probably points to the parent scope? To be verified and fixed if necessary. There is no harm as it is now. It
// is just wasteful allocation since the scope is not used at all.

// Pass on eval state info to the dynamic scope and clear it on the block-body
newScope = DynamicScope.newDynamicScope(getStaticScope(), prevScope, this.evalType.get());
DynamicScope prevScope = binding.getDynamicScope();
if (this.pushScope) {
context.pushScope(DynamicScope.newDynamicScope(getStaticScope(), prevScope, this.evalType.get()));
} else if (this.reuseParentScope) {
// Reuse!
// We can avoid the push only if surrounding vars aren't referenced!

try {
return (IRubyObject)handle.invokeExact(context, getStaticScope(), self, args, block, binding.getMethod(), type);
} catch (Throwable t) {
return null; // not reached
} finally {
// IMPORTANT: Do not clear eval-type in case this is reused in bindings!
// Ex: eval("...", foo.instance_eval { binding })
// The dyn-scope used for binding needs to have its eval-type set to INSTANCE_EVAL
context.postYield(binding, prevFrame);
if (this.pushScope || this.reuseParentScope) {
context.postYield(binding, prevFrame);
} else {

0 comments on commit c3866f0

Please sign in to comment.