| 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..d3ca3d6359d9fa07ff07c1d11f85792582735507 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::EmitGeneratorResume(Expression *generator,
 | 
| +    Expression *value,
 | 
| +    JSGeneratorObject::ResumeMode resume_mode) {
 | 
| +  // The value stays in eax, and is ultimately read by the resumed generator, as
 | 
| +  // if the CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it.  ebx
 | 
| +  // will hold the generator object until the activation has been resumed.
 | 
| +  VisitForStackValue(generator);
 | 
| +  VisitForAccumulatorValue(value);
 | 
| +  __ pop(ebx);
 | 
| +
 | 
| +  // Check generator state.
 | 
| +  Label wrong_state, done;
 | 
| +  STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0);
 | 
| +  STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0);
 | 
| +  __ cmp(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset),
 | 
| +         Immediate(Smi::FromInt(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::SEND) {
 | 
| +    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.
 | 
| +  __ Abort("Generator failed to resume.");
 | 
| +
 | 
| +  // 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();
 | 
| 
 |