@Override protected IRubyObject commonYieldPath( ThreadContext context, Block block, Block.Type type, IRubyObject[] args, IRubyObject self, Block blockArg) { if (callCount >= 0) promoteToFullBuild(context); InterpreterContext ic = ensureInstrsReady(); // Update interpreter context for next time this block is executed // This ensures that if we had determined canCallDirect() is false // based on the old IC, we continue to execute with it. interpreterContext = fullInterpreterContext; Binding binding = block.getBinding(); Visibility oldVis = binding.getFrame().getVisibility(); Frame prevFrame = context.preYieldNoScope(binding); // 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. DynamicScope actualScope = binding.getDynamicScope(); if (ic.pushNewDynScope()) { context.pushScope(block.allocScope(actualScope)); } else if (ic.reuseParentDynScope()) { // Reuse! We can avoid the push only if surrounding vars aren't referenced! context.pushScope(actualScope); } self = IRRuntimeHelpers.updateBlockState(block, self); try { return Interpreter.INTERPRET_BLOCK( context, block, self, ic, args, binding.getMethod(), blockArg); } 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 binding.getFrame().setVisibility(oldVis); if (ic.popDynScope()) { context.postYield(binding, prevFrame); } else { context.postYieldNoScope(prevFrame); } } }
@Override protected void post( ThreadContext context, Binding binding, Visibility visibility, Frame lastFrame) { context.postYieldNoScope(lastFrame); }