libraries/v8/runtime.cc
// Note that this function is the slow path for resuming generators.  It is only
// called if the suspended activation had operands on the stack, stack handlers
// needing rewinding, or if the resume should throw an exception.  The fast path
// is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is
// inlined into GeneratorNext and GeneratorThrow.  EmitGeneratorResumeResume is
// called in any case, as it needs to reconstruct the stack frame and make space
// for arguments and operands.
Note that this function is the slow path for resuming generators.  It is only
called if the suspended activation had operands on the stack, stack handlers
needing rewinding, or if the resume should throw an exception.  The fast path
is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is
inlined into GeneratorNext and GeneratorThrow.  EmitGeneratorResumeResume is
called in any case, as it needs to reconstruct the stack frame and make space
for arguments and operands.
Note that this function is the slow path for resuming generators . It is only called if the suspended activation had operands on the stack stack handlers needing rewinding or if the resume should throw an exception . The fast path is handled directly in FullCodeGenerator :: EmitGeneratorResume () which is inlined into GeneratorNext and GeneratorThrow . EmitGeneratorResumeResume is called in any case as it needs to reconstruct the stack frame and make space for arguments and operands .
RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) {
  SealHandleScope shs(isolate);
  ASSERT(args.length() == 3);
  CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
  CONVERT_ARG_CHECKED(Object, value, 1);
  CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2);
  JavaScriptFrameIterator stack_iterator(isolate);
  JavaScriptFrame* frame = stack_iterator.frame();
  ASSERT_EQ(frame->function(), generator_object->function());
  ASSERT(frame->function()->is_compiled());
  STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0);
  STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0);
  Address pc = generator_object->function()->code()->instruction_start();
  int offset = generator_object->continuation();
  ASSERT(offset > 0);
  frame->set_pc(pc + offset);
  generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
  FixedArray* operand_stack = generator_object->operand_stack();
  int operands_count = operand_stack->length();
  if (operands_count != 0) {
    frame->RestoreOperandStack(operand_stack,
                               generator_object->stack_handler_index());
    generator_object->set_operand_stack(isolate->heap()->empty_fixed_array());
    generator_object->set_stack_handler_index(-1);
  }
  JSGeneratorObject::ResumeMode resume_mode =
      static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int);
  switch (resume_mode) {
    case JSGeneratorObject::NEXT:
      return value;
    case JSGeneratorObject::THROW:
      return isolate->Throw(value);
  }
  UNREACHABLE();
  return isolate->ThrowIllegalOperation();
}
RUNTIME_FUNCTION ( MaybeObject * , Runtime_ResumeJSGeneratorObject ) { SealHandleScope shs ( isolate ) ; ASSERT ( args . length ( ) == 3 ) ; CONVERT_ARG_CHECKED ( JSGeneratorObject , generator_object , 0 ) ; CONVERT_ARG_CHECKED ( Object , value , 1 ) ; CONVERT_SMI_ARG_CHECKED ( resume_mode_int , 2 ) ; JavaScriptFrameIterator stack_iterator ( isolate ) ; JavaScriptFrame * frame = stack_iterator . frame ( ) ; ASSERT_EQ ( frame -> function ( ) , generator_object -> function ( ) ) ; ASSERT ( frame -> function ( ) -> is_compiled ( ) ) ; STATIC_ASSERT ( JSGeneratorObject :: kGeneratorExecuting <= 0 ) ; STATIC_ASSERT ( JSGeneratorObject :: kGeneratorClosed <= 0 ) ; Address pc = generator_object -> function ( ) -> code ( ) -> instruction_start ( ) ; int offset = generator_object -> continuation ( ) ; ASSERT ( offset > 0 ) ; frame -> set_pc ( pc + offset ) ; generator_object -> set_continuation ( JSGeneratorObject :: kGeneratorExecuting ) ; FixedArray * operand_stack = generator_object -> operand_stack ( ) ; int operands_count = operand_stack -> length ( ) ; if ( operands_count != 0 ) { frame -> RestoreOperandStack ( operand_stack , generator_object -> stack_handler_index ( ) ) ; generator_object -> set_operand_stack ( isolate -> heap ( ) -> empty_fixed_array ( ) ) ; generator_object -> set_stack_handler_index ( -1 ) ; } JSGeneratorObject :: ResumeMode resume_mode = static_cast < JSGeneratorObject :: ResumeMode > ( resume_mode_int ) ; switch ( resume_mode ) { case JSGeneratorObject :: NEXT : return value ; case JSGeneratorObject :: THROW : return isolate -> Throw ( value ) ; } UNREACHABLE ( ) ; return isolate -> ThrowIllegalOperation ( ) ; }
Note that this function is the slow path for resuming generators.
Note that this function is the slow path for resuming generators .