From 1391e80f2606b449bce620076f6e3c1c8c0c2285 Mon Sep 17 00:00:00 2001 From: "palfia@homejinni.com" Date: Tue, 7 May 2013 23:14:36 +0000 Subject: [PATCH] MIPS: Generators return boxed values Port r14563 (6d01adb8) Original commit message: Generators now box their return values in object literals of the form { value: VAL, done: DONE } where DONE is false for yield expressions, and true for return statements. BUG= Review URL: https://codereview.chromium.org/15009008 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14582 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/full-codegen-mips.cc | 70 +++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 15 deletions(-) diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index ea4c5146b2..c7dae7f4ba 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -1943,11 +1943,12 @@ void FullCodeGenerator::VisitYield(Yield* expr) { Label resume; __ LoadRoot(at, Heap::kTheHoleValueRootIndex); __ Branch(&resume, ne, result_register(), Operand(at)); - __ 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()); @@ -1959,18 +1960,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ li(a1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); __ sw(a1, FieldMemOperand(result_register(), JSGeneratorObject::kContinuationOffset)); - __ 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(); + EmitReturnIteratorResult(true); break; } @@ -2076,6 +2066,56 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, } +void FullCodeGenerator::EmitReturnIteratorResult(bool done) { + Label gc_required; + Label allocated; + + Handle map(isolate()->native_context()->generator_result_map()); + + __ Allocate(map->instance_size(), a0, a2, a3, &gc_required, TAG_OBJECT); + + __ bind(&allocated); + __ li(a1, Operand(map)); + __ pop(a2); + __ li(a3, Operand(isolate()->factory()->ToBoolean(done))); + __ li(t0, Operand(isolate()->factory()->empty_fixed_array())); + ASSERT_EQ(map->instance_size(), 5 * kPointerSize); + __ sw(a1, FieldMemOperand(a0, HeapObject::kMapOffset)); + __ sw(t0, FieldMemOperand(a0, JSObject::kPropertiesOffset)); + __ sw(t0, FieldMemOperand(a0, JSObject::kElementsOffset)); + __ sw(a2, + FieldMemOperand(a0, JSGeneratorObject::kResultValuePropertyOffset)); + __ sw(a3, + FieldMemOperand(a0, JSGeneratorObject::kResultDonePropertyOffset)); + + // Only the value field needs a write barrier, as the other values are in the + // root set. + __ RecordWriteField(a0, JSGeneratorObject::kResultValuePropertyOffset, + a2, a3, kRAHasBeenSaved, 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); + } + + __ mov(result_register(), a0); + EmitReturnSequence(); + + __ bind(&gc_required); + __ Push(Smi::FromInt(map->instance_size())); + __ CallRuntime(Runtime::kAllocateInNewSpace, 1); + __ lw(context_register(), + MemOperand(fp, StandardFrameConstants::kContextOffset)); + __ jmp(&allocated); +} + + void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); Literal* key = prop->key()->AsLiteral();