| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 843b8d701cbcb3cf2b09d3eedf80bc2cb65c1852..87cdaa95802ed755b88e887f2b631af9dfcbf393 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -2295,6 +2295,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSGeneratorObject) {
|
| NoHandleAllocation ha(isolate);
|
| ASSERT(args.length() == 0);
|
| +
|
| JavaScriptFrameIterator it(isolate);
|
| JavaScriptFrame* frame = it.frame();
|
| JSFunction* function = JSFunction::cast(frame->function());
|
| @@ -2309,7 +2310,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 +2318,61 @@ 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()));
|
| + RUNTIME_ASSERT(function->shared()->is_generator());
|
| +
|
| + 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.
|
| + //
|
| + // TODO(wingo): Move these magical calculations to frames.h when the
|
| + // generators implementation has stabilized.
|
| + intptr_t stack_size_in_bytes =
|
| + (frame->fp() + JavaScriptFrameConstants::kLocal0Offset) -
|
| + (frame->sp() - kPointerSize);
|
| + 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;
|
| +
|
| + if (stack_size == 0) {
|
| + ASSERT_EQ(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()));
|
| + // TODO(wingo): Save the operand stack and/or the stack handlers.
|
| + UNIMPLEMENTED();
|
| + }
|
| +
|
| + // The return value is the hole for a suspend return, and anything else for a
|
| + // resume return.
|
| + return isolate->heap()->the_hole_value();
|
| +}
|
| +
|
| +
|
| MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
|
| Object* char_code) {
|
| uint32_t code;
|
|
|