Index: src/x64/full-codegen-x64.cc |
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc |
index a20d468bae4721f681b6efdcafb185c7bc54e83e..24591657927d0eeacfa290c578a2df53400ccffc 100644 |
--- a/src/x64/full-codegen-x64.cc |
+++ b/src/x64/full-codegen-x64.cc |
@@ -1924,11 +1924,12 @@ void FullCodeGenerator::VisitYield(Yield* expr) { |
Label resume; |
__ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex); |
__ j(not_equal, &resume); |
- __ pop(result_register()); |
if (expr->yield_kind() == Yield::SUSPEND) { |
- // TODO(wingo): Box into { value: VALUE, done: false }. |
+ EmitReturnIteratorResult(false); |
+ } else { |
+ __ pop(result_register()); |
+ EmitReturnSequence(); |
} |
- EmitReturnSequence(); |
__ bind(&resume); |
context()->Plug(result_register()); |
@@ -1939,19 +1940,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) { |
VisitForAccumulatorValue(expr->generator_object()); |
__ Move(FieldOperand(result_register(), |
JSGeneratorObject::kContinuationOffset), |
- Smi::FromInt(JSGeneratorObject::kGeneratorClosed)); |
- __ pop(result_register()); |
- // TODO(wingo): Box into { value: VALUE, done: true }. |
- |
- // Exit all nested statements. |
- NestedStatement* current = nesting_stack_; |
- int stack_depth = 0; |
- int context_length = 0; |
- while (current != NULL) { |
- current = current->Exit(&stack_depth, &context_length); |
- } |
- __ Drop(stack_depth); |
- EmitReturnSequence(); |
+ Smi::FromInt(0)); |
+ EmitReturnIteratorResult(true); |
break; |
} |
@@ -2058,6 +2048,63 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
} |
+void FullCodeGenerator::EmitReturnIteratorResult(bool done) { |
+ Label gc_required; |
+ Label allocated; |
+ |
+ STATIC_ASSERT(HeapObject::kMapOffset == 0); |
+ STATIC_ASSERT(JSObject::kPropertiesOffset == kPointerSize); |
+ STATIC_ASSERT(JSObject::kElementsOffset == 2 * kPointerSize); |
+ STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize); |
+ STATIC_ASSERT(JSGeneratorObject::kResultValuePropertyIndex == 0); |
+ STATIC_ASSERT(JSGeneratorObject::kResultDonePropertyIndex == 1); |
+ |
+ const int size = 5 * kPointerSize; |
+ __ Allocate(size, rax, rcx, rdx, &gc_required, TAG_OBJECT); |
+ |
+ __ bind(&allocated); |
+ // The object is now in rax. Initialize its map, value, and done fields. |
+ Handle<Map> map(isolate()->native_context()->iterator_result_map()); |
+ __ Move(rbx, map); |
+ __ pop(rcx); |
+ __ Move(rdx, |
+ done |
+ ? isolate()->factory()->true_value() |
+ : isolate()->factory()->false_value()); |
+ __ movq(FieldOperand(rax, 0 * kPointerSize), rbx); // map |
+ __ Move(FieldOperand(rax, 1 * kPointerSize), // properties |
+ isolate()->factory()->empty_fixed_array()); |
+ __ Move(FieldOperand(rax, 2 * kPointerSize), // elements |
+ isolate()->factory()->empty_fixed_array()); |
+ __ movq(FieldOperand(rax, 3 * kPointerSize), rcx); // value |
+ __ movq(FieldOperand(rax, 4 * kPointerSize), rdx); // done? |
+ |
+ // Only the value field needs a write barrier, as the other values are in the |
+ // root set. |
+ __ RecordWriteField(rax, 3 * kPointerSize, rcx, rdx, kDontSaveFPRegs); |
+ |
+ if (done) { |
+ // Exit all nested statements. |
+ NestedStatement* current = nesting_stack_; |
+ int stack_depth = 0; |
+ int context_length = 0; |
+ while (current != NULL) { |
+ current = current->Exit(&stack_depth, &context_length); |
+ } |
+ __ Drop(stack_depth); |
+ } |
+ |
+ EmitReturnSequence(); |
+ |
+ __ bind(&gc_required); |
+ __ Push(Smi::FromInt(size)); |
+ __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
+ __ movq(context_register(), |
+ Operand(rbp, StandardFrameConstants::kContextOffset)); |
+ __ jmp(&allocated); |
+} |
+ |
+ |
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
SetSourcePosition(prop->position()); |
Literal* key = prop->key()->AsLiteral(); |