Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index 1df5653acfc5a772fc96ce4cde3bceac9ddaea12..63f1edb2602ab344be90b0f88e8a460b4a95d022 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -2475,6 +2475,65 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) { |
} |
+// 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, GeneratorSend, 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) { |
+ HandleScope scope(isolate); |
+ ASSERT(args.length() == 3); |
+ CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0); |
+ CONVERT_ARG_HANDLE_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()); |
+ |
+ 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); |
+ |
+ if (generator_object->operand_stack()->length() != 0) { |
+ // TODO(wingo): Copy operand stack. Rewind handlers. |
+ UNIMPLEMENTED(); |
+ } |
+ |
+ JSGeneratorObject::ResumeMode resume_mode = |
+ static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int); |
+ switch (resume_mode) { |
+ case JSGeneratorObject::SEND: |
+ return *value; |
+ case JSGeneratorObject::THROW: |
+ return isolate->Throw(*value); |
+ } |
+ |
+ UNREACHABLE(); |
+ return isolate->ThrowIllegalOperation(); |
+} |
+ |
+ |
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowGeneratorStateError) { |
+ HandleScope scope(isolate); |
+ ASSERT(args.length() == 1); |
+ CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); |
+ int continuation = generator->continuation(); |
+ const char *message = continuation == JSGeneratorObject::kGeneratorClosed ? |
+ "generator_finished" : "generator_running"; |
+ Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0); |
+ Handle<Object> error = isolate->factory()->NewError(message, argv); |
+ return isolate->Throw(*error); |
+} |
+ |
+ |
MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate, |
Object* char_code) { |
if (char_code->IsNumber()) { |