| 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()) {
|
|
|