Index: src/x64/full-codegen-x64.cc |
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc |
index 674f64efe52b137e71210b2b9bad0553b2085798..c1dc54cde9b53fcd2216ed2fe2099fb594e1b07d 100644 |
--- a/src/x64/full-codegen-x64.cc |
+++ b/src/x64/full-codegen-x64.cc |
@@ -2092,19 +2092,21 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
Expression *value, |
JSGeneratorObject::ResumeMode resume_mode) { |
// The value stays in rax, and is ultimately read by the resumed generator, as |
- // if the CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. rbx |
- // 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. |
+ // rbx will hold the generator object until the activation has been resumed. |
VisitForStackValue(generator); |
VisitForAccumulatorValue(value); |
__ pop(rbx); |
// Check generator state. |
- Label wrong_state, done; |
- STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0); |
- STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0); |
+ Label wrong_state, closed_state, done; |
+ STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); |
+ STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); |
__ SmiCompare(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset), |
Smi::FromInt(0)); |
- __ j(less_equal, &wrong_state); |
+ __ j(equal, &closed_state); |
+ __ j(less, &wrong_state); |
// Load suspended function and context. |
__ movq(rsi, FieldOperand(rbx, JSGeneratorObject::kContextOffset)); |
@@ -2175,6 +2177,20 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
// Not reached: the runtime call returns elsewhere. |
__ Abort(kGeneratorFailedToResume); |
+ // Reach here when generator is closed. |
+ __ bind(&closed_state); |
+ if (resume_mode == JSGeneratorObject::NEXT) { |
+ // Return completed iterator result when generator is closed. |
+ __ PushRoot(Heap::kUndefinedValueRootIndex); |
+ // Pop value from top-of-stack slot; box result into result register. |
+ EmitCreateIteratorResult(true); |
+ } else { |
+ // Throw the provided value. |
+ __ push(rax); |
+ __ CallRuntime(Runtime::kThrow, 1); |
+ } |
+ __ jmp(&done); |
+ |
// Throw error if we attempt to operate on a running generator. |
__ bind(&wrong_state); |
__ push(rbx); |