@Override
  public Object dispatchWithSelfAndBlock(
      VirtualFrame frame,
      final RubyBasicObject block,
      Object self,
      RubyBasicObject modifiedBlock,
      Object... argumentsObjects) {
    CompilerDirectives.transferToInterpreterAndInvalidate();

    assert block == null || RubyGuards.isRubyProc(block);
    assert modifiedBlock == null || RubyGuards.isRubyProc(modifiedBlock);

    final YieldDispatchNode dispatch =
        atomic(
            new Callable<YieldDispatchNode>() {
              @Override
              public YieldDispatchNode call() {
                // First try to see if we did not a miss a specialization added by another thread.
                final YieldDispatchHeadNode dispatchHead = getHeadNode();
                final YieldDispatchNode first = dispatchHead.getDispatch();

                YieldDispatchNode lookupDispatch = first;
                while (lookupDispatch != null) {
                  if (lookupDispatch.guard(block)) {
                    // This one worked, no need to rewrite anything.
                    return lookupDispatch;
                  }
                  lookupDispatch = lookupDispatch.getNext();
                }

                final YieldDispatchNode newDispatchNode;
                if (depth < DispatchNode.DISPATCH_POLYMORPHIC_MAX) {
                  depth++;
                  newDispatchNode = new CachedYieldDispatchNode(getContext(), block, first);
                } else {
                  newDispatchNode = new GeneralYieldDispatchNode(getContext());
                }

                first.replace(newDispatchNode);
                return first;
              }
            });

    return dispatch.dispatchWithSelfAndBlock(frame, block, self, modifiedBlock, argumentsObjects);
  }
 @Override
 public Object dispatchWithSelfAndBlock(
     VirtualFrame frame,
     RubyProc block,
     Object self,
     RubyProc modifiedBlock,
     Object... argumentsObjects) {
   if (guard(block)) {
     return callNode.call(
         frame,
         RubyArguments.pack(
             block.getMethod(),
             block.getDeclarationFrame(),
             self,
             modifiedBlock,
             argumentsObjects));
   } else {
     return next.dispatchWithSelfAndBlock(frame, block, self, modifiedBlock, argumentsObjects);
   }
 }