Index: src/arm/full-codegen-arm.cc |
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc |
index 06514910ac513324cdc0d5c281ffa3a9ddd8aaa8..1a98cdfed7b88e96e495cadf9b1e8be72726682d 100644 |
--- a/src/arm/full-codegen-arm.cc |
+++ b/src/arm/full-codegen-arm.cc |
@@ -2111,19 +2111,21 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
Expression *value, |
JSGeneratorObject::ResumeMode resume_mode) { |
// The value stays in r0, and is ultimately read by the resumed generator, as |
- // if the CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. r1 |
- // will hold the generator object until the activation has been resumed. |
+ // if the CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it |
+ // is read to throw the value when the resumed generator is already closed. |
+ // r1 will hold the generator object until the activation has been resumed. |
VisitForStackValue(generator); |
VisitForAccumulatorValue(value); |
__ pop(r1); |
// Check generator state. |
- Label wrong_state, done; |
+ Label wrong_state, closed_state, done; |
__ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset)); |
- STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0); |
- STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0); |
+ STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); |
+ STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); |
__ cmp(r3, Operand(Smi::FromInt(0))); |
- __ b(le, &wrong_state); |
+ __ b(eq, &closed_state); |
+ __ b(lt, &wrong_state); |
// Load suspended function and context. |
__ ldr(cp, FieldMemOperand(r1, JSGeneratorObject::kContextOffset)); |
@@ -2198,6 +2200,21 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
// Not reached: the runtime call returns elsewhere. |
__ stop("not-reached"); |
+ // Reach here when generator is closed. |
+ __ bind(&closed_state); |
+ if (resume_mode == JSGeneratorObject::NEXT) { |
+ // Return completed iterator result when generator is closed. |
+ __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
+ __ push(r2); |
+ // Pop value from top-of-stack slot; box result into result register. |
+ EmitCreateIteratorResult(true); |
+ } else { |
+ // Throw the provided value. |
+ __ push(r0); |
+ __ CallRuntime(Runtime::kThrow, 1); |
+ } |
+ __ jmp(&done); |
+ |
// Throw error if we attempt to operate on a running generator. |
__ bind(&wrong_state); |
__ push(r1); |