Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index 843b8d701cbcb3cf2b09d3eedf80bc2cb65c1852..cb84f5bfed4f18541babda11898edba8c0fb026b 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -2309,7 +2309,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSGeneratorObject) { |
if (!maybe_generator->To(&generator)) return maybe_generator; |
} |
generator->set_function(function); |
- generator->set_context(isolate->heap()->undefined_value()); |
+ generator->set_context(Context::cast(frame->context())); |
generator->set_continuation(0); |
generator->set_operand_stack(isolate->heap()->empty_fixed_array()); |
@@ -2317,6 +2317,57 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSGeneratorObject) { |
} |
+RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) { |
+ HandleScope scope(isolate); |
+ ASSERT(args.length() == 1); |
+ CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0); |
+ |
+ JavaScriptFrameIterator stack_iterator(isolate); |
+ JavaScriptFrame *frame = stack_iterator.frame(); |
+ Handle<JSFunction> function(JSFunction::cast(frame->function())); |
Michael Starzinger
2013/04/17 13:43:48
Let's play it safe for now and add the following h
|
+ |
+ intptr_t offset = frame->pc() - function->code()->instruction_start(); |
+ ASSERT(*function == generator_object->function()); |
+ ASSERT(offset >= 0 && Smi::IsValid(offset)); |
+ generator_object->set_continuation(offset); |
+ |
+ // Generator functions force context allocation for locals, so Local0 points |
+ // to the bottom of the operand stack. Assume the stack grows down. |
+ intptr_t stack_size_in_bytes = |
+ (frame->fp() + JavaScriptFrameConstants::kLocal0Offset) - |
+ (frame->sp() - kPointerSize); |
Michael Starzinger
2013/04/17 13:43:48
Just for the record: This magic computation needs
|
+ ASSERT(IsAddressAligned(frame->fp(), kPointerSize)); |
+ ASSERT(IsAligned(stack_size_in_bytes, kPointerSize)); |
+ ASSERT(stack_size_in_bytes >= 0); |
+ ASSERT(Smi::IsValid(stack_size_in_bytes)); |
+ unsigned stack_size = stack_size_in_bytes >> kPointerSizeLog2; |
+ |
+ // We expect there to be at least two values on the stack: the return value of |
+ // the yield expression, and the argument to this runtime call. Neither of |
+ // those should be saved. |
+ ASSERT(stack_size >= 2); |
+ stack_size -= 2; |
+ |
Michael Starzinger
2013/04/17 13:43:48
IIUC the current implementation relies and the con
Michael Starzinger
2013/04/17 13:49:02
That should have been "generator_object->context()
|
+ if (stack_size == 0) { |
+ ASSERT(generator_object->operand_stack() == |
+ isolate->heap()->empty_fixed_array()); |
+ // If there are no operands on the stack, there shouldn't be a handler |
+ // active either. Also, the active context will be the same as the function |
+ // itself, so there is no need to save the context. |
+ ASSERT_EQ(frame->context(), generator_object->context()); |
+ ASSERT(!frame->HasHandler()); |
+ } else { |
+ generator_object->set_context(Context::cast(frame->context())); |
+ // Saving the operand stack or stack handlers is not currently implemented. |
Michael Starzinger
2013/04/17 13:43:48
Let's turn this comment into a TODO.
|
+ UNIMPLEMENTED(); |
+ } |
+ |
+ // The return value is the hole for a suspend return, and anything else for a |
+ // resume return. |
+ return *isolate->factory()->the_hole_value(); |
Michael Starzinger
2013/04/17 13:43:48
Use "isolate->heap()->the_hole_value()" here inste
|
+} |
+ |
+ |
MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate, |
Object* char_code) { |
uint32_t code; |