Chromium Code Reviews| Index: src/runtime.cc |
| diff --git a/src/runtime.cc b/src/runtime.cc |
| index c942d029d45e0614ee8e5cd6cf84ebf84fc962b2..29d4558d3214bd0f2f0551b29ecf413f01f4d943 100644 |
| --- a/src/runtime.cc |
| +++ b/src/runtime.cc |
| @@ -2421,51 +2421,52 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSGeneratorObject) { |
| RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) { |
| - HandleScope scope(isolate); |
| + NoHandleAllocation ha(isolate); |
| ASSERT(args.length() == 1); |
| - CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0); |
| + CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0); |
| JavaScriptFrameIterator stack_iterator(isolate); |
| JavaScriptFrame *frame = stack_iterator.frame(); |
| - Handle<JSFunction> function(JSFunction::cast(frame->function())); |
| + JSFunction *function = JSFunction::cast(frame->function()); |
|
Michael Starzinger
2013/04/26 09:53:16
style: The '*' sticks to the left. There are sever
wingo
2013/04/26 10:11:42
Fixed this and other locations.
|
| RUNTIME_ASSERT(function->shared()->is_generator()); |
| + ASSERT_EQ(function, generator_object->function()); |
| - intptr_t offset = frame->pc() - function->code()->instruction_start(); |
| - ASSERT(*function == generator_object->function()); |
| - ASSERT(offset > 0 && Smi::IsValid(offset)); |
| - generator_object->set_continuation(static_cast<int>(offset)); |
| + // We expect there to be at least two values on the operand stack: the return |
| + // value of the yield expression, and the argument to this runtime call. |
| + // Neither of those should be saved. |
| + int operands_count = frame->ComputeOperandsCount(); |
| + ASSERT(operands_count >= 2); |
| + operands_count -= 2; |
| - // 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)); |
| - intptr_t 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) { |
| + if (operands_count == 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. |
| ASSERT(!frame->HasHandler()); |
| } else { |
| - // TODO(wingo): Save the operand stack and/or the stack handlers. |
| - UNIMPLEMENTED(); |
| + if (frame->HasHandler()) { |
| + // TODO(wingo): Unwind the stack handlers. |
| + UNIMPLEMENTED(); |
| + } |
| + |
| + FixedArray* operand_stack; |
| + MaybeObject* alloc = isolate->heap()->AllocateFixedArray(operands_count); |
| + if (!alloc->To(&operand_stack)) |
|
Michael Starzinger
2013/04/26 09:53:16
nit: Conditional fits into one line.
wingo
2013/04/26 10:11:42
Done.
|
| + return alloc; |
| + |
| + for (int i = 0; i < operands_count; i++) |
|
Michael Starzinger
2013/04/26 09:53:16
style: Add curly braces around loop body.
wingo
2013/04/26 10:11:42
Done.
|
| + // Since operand_stack is in NewSpace, no write barrier is needed. |
| + operand_stack->set(i, frame->GetOperand(i), SKIP_WRITE_BARRIER); |
|
Michael Starzinger
2013/04/26 09:53:16
The allocation function above doesn't guarantee th
wingo
2013/04/26 10:11:42
Good catch!
|
| + generator_object->set_operand_stack(operand_stack); |
| } |
| + // Set continuation down here to avoid side effects if the operand stack |
| + // allocation fails. |
| + intptr_t offset = frame->pc() - function->code()->instruction_start(); |
| + ASSERT(offset > 0 && Smi::IsValid(offset)); |
| + generator_object->set_continuation(offset); |
| + |
| // It's possible for the context to be other than the initial context even if |
| // there is no stack handler active. For example, this is the case in the |
| // body of a "with" statement. Therefore we always save the context. |
| @@ -2485,10 +2486,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) { |
| // 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); |
| + NoHandleAllocation ha(isolate); |
| ASSERT(args.length() == 3); |
| - CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0); |
| - CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); |
| + 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(); |
|
Michael Starzinger
2013/04/26 09:53:16
style: The '*' sticks to the left.
wingo
2013/04/26 10:11:42
Done.
|
| @@ -2504,18 +2505,26 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) { |
| 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(); |
| + FixedArray *operand_stack = generator_object->operand_stack(); |
| + int operands_count = operand_stack->length(); |
| + if (operands_count != 0) { |
| + // TODO(wingo): Rewind stack handlers. However until |
| + // SuspendJSGeneratorObject unwinds them, we won't see frames with stack |
| + // handlers here. |
| + for (int i = 0; i < operands_count; i++) { |
| + ASSERT_EQ(frame->GetOperand(i), isolate->heap()->the_hole_value()); |
| + Memory::Object_at(frame->GetOperandSlot(i)) = operand_stack->get(i); |
| + } |
| + generator_object->set_operand_stack(isolate->heap()->empty_fixed_array()); |
| } |
| JSGeneratorObject::ResumeMode resume_mode = |
| static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int); |
| switch (resume_mode) { |
| case JSGeneratorObject::SEND: |
| - return *value; |
| + return value; |
| case JSGeneratorObject::THROW: |
| - return isolate->Throw(*value); |
| + return isolate->Throw(value); |
| } |
| UNREACHABLE(); |