void Interpreter::doReturnNonLocal() { vm_oop_t result = GetFrame()->Pop(); VMFrame* context = GetFrame()->GetOuterContext(); if (!context->HasPreviousFrame()) { VMBlock* block = static_cast<VMBlock*>(GetFrame()->GetArgument(0, 0)); VMFrame* prevFrame = GetFrame()->GetPreviousFrame(); VMFrame* outerContext = prevFrame->GetOuterContext(); vm_oop_t sender = outerContext->GetArgument(0, 0); vm_oop_t arguments[] = {block}; popFrame(); // Pop old arguments from stack VMMethod* method = GetFrame()->GetMethod(); long numberOfArgs = method->GetNumberOfArguments(); for (long i = 0; i < numberOfArgs; ++i) GetFrame()->Pop(); // check if current frame is big enough for this unplanned send // #escapedBlock: needs 2 slots, one for self, and one for the block long additionalStackSlots = 2 - GetFrame()->RemainingStackSize(); if (additionalStackSlots > 0) { GetFrame()->SetBytecodeIndex(bytecodeIndexGlobal); // copy current frame into a bigger one, and replace it SetFrame(VMFrame::EmergencyFrameFrom(GetFrame(), additionalStackSlots)); } AS_OBJ(sender)->Send(escapedBlock, arguments, 1); return; } while (GetFrame() != context) popFrame(); popFrameAndPushResult(result); }
vm_oop_t Interpreter::GetSelf() const { VMFrame* context = GetFrame()->GetOuterContext(); return context->GetArgument(0, 0); }