Chromium Code Reviews| Index: src/ia32/full-codegen-ia32.cc |
| diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc |
| index 113ca4b480a9827d30d47cd927168f2dfd6f2284..20f3aea03210b694d115b82b0a312923f66f1c5a 100644 |
| --- a/src/ia32/full-codegen-ia32.cc |
| +++ b/src/ia32/full-codegen-ia32.cc |
| @@ -1937,6 +1937,98 @@ void FullCodeGenerator::VisitYield(Yield* expr) { |
| } |
| +void FullCodeGenerator::EmitResume(Expression *generator_expr, |
| + Expression *value_expr, |
| + JSGeneratorObject::ResumeMode resume_mode) { |
| + // ebx will hold the generator object until the activation has been resumed. |
| + VisitForAccumulatorValue(generator_expr); |
| + __ mov(ebx, result_register()); |
|
Michael Starzinger
2013/04/21 22:45:21
The ebx register might get clobbered while evaluat
wingo
2013/04/23 13:51:04
Good catch! Fixed.
|
| + |
| + // The value stays in eax, and is ultimately read by the resumed generator, as |
| + // if the CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. |
| + VisitForAccumulatorValue(value_expr); |
| + |
| + // Check generator state. |
| + Label wrong_state, done; |
| + __ mov(edx, FieldOperand(ebx, JSGeneratorObject::kContinuationOffset)); |
| + __ SmiUntag(edx); |
|
Michael Starzinger
2013/04/21 22:45:21
No need to untag and compare, we can compare right
wingo
2013/04/23 13:51:04
Done.
|
| + __ cmp(edx, Immediate(0)); |
| + __ j(less_equal, &wrong_state); |
| + |
| + // Load suspended function and context. |
| + __ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContextOffset)); |
| + __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset)); |
| + |
| + // Push holes for arguments to generator function. |
| + __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| + __ mov(edx, |
| + FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); |
| + __ mov(ecx, isolate()->factory()->the_hole_value()); |
| + Label push_argument_holes; |
| + __ bind(&push_argument_holes); |
| + __ push(ecx); |
| + __ sub(edx, Immediate(1)); |
| + __ j(not_carry, &push_argument_holes); |
| + |
| + // Enter a new JavaScript frame, and initialize its slots as they were when |
| + // the generator was suspended. |
| + Label push_frame, resume_frame; |
| + __ bind(&push_frame); |
| + __ call(&resume_frame); |
| + __ jmp(&done); |
| + __ bind(&resume_frame); |
| + __ push(ebp); // Caller's frame pointer. |
| + __ mov(ebp, esp); |
| + __ push(esi); // Callee's context. |
| + __ push(edi); // Callee's JS Function. |
| + |
| + // Load the operand stack size. |
| + __ mov(edx, FieldOperand(ebx, JSGeneratorObject::kOperandStackOffset)); |
| + __ mov(edx, FieldOperand(edx, FixedArray::kLengthOffset)); |
| + __ SmiUntag(edx); |
| + |
| + // If we are sending a value and there is no operand stack, we can jump back |
| + // in directly. |
| + if (resume_mode == JSGeneratorObject::kSend) { |
| + Label slow_resume; |
| + __ cmp(edx, Immediate(0)); |
| + __ j(not_zero, &slow_resume); |
| + __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); |
| + __ mov(ecx, FieldOperand(ebx, JSGeneratorObject::kContinuationOffset)); |
| + __ SmiUntag(ecx); |
| + __ add(edx, ecx); |
| + __ mov(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset), |
| + Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))); |
| + __ jmp(edx); |
| + __ bind(&slow_resume); |
| + } |
| + |
| + // Otherwise, we push holes for the operand stack and call the runtime to fix |
| + // up the stack and the handlers. |
| + Label push_operand_holes, call_resume; |
| + __ bind(&push_operand_holes); |
| + __ sub(edx, Immediate(1)); |
| + __ j(carry, &call_resume); |
| + __ push(ecx); |
| + __ jmp(&push_operand_holes); |
| + __ bind(&call_resume); |
| + __ push(ebx); |
| + __ push(result_register()); |
| + __ Push(Smi::FromInt(resume_mode)); |
| + __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
| + // Not reached: the runtime call returns elsewhere. |
| + __ int3(); |
| + |
| + // Throw error if we attempt to operate on a running generator. |
| + __ bind(&wrong_state); |
| + __ push(ebx); |
| + __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); |
| + |
| + __ bind(&done); |
| + context()->Plug(result_register()); |
| +} |
| + |
| + |
| void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| SetSourcePosition(prop->position()); |
| Literal* key = prop->key()->AsLiteral(); |