From: palfia@homejinni.com Date: Fri, 17 May 2013 01:10:09 +0000 (+0000) Subject: MIPS: Implement yield* (delegating yield) X-Git-Tag: upstream/4.7.83~14204 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=22fe386d6f1861c2a459785336a17a0010a24417;p=platform%2Fupstream%2Fv8.git MIPS: Implement yield* (delegating yield) Port r14669 (b64ce42a) Original commit message: Ideally this would have been implemented via desugaring at parse-time, but yield* is an expression, and its desugaring includes statements like while and try/catch. We'd have to have BlockExpression in the AST to support that, and it's not worth it for this feature. So instead we implement all of the logic in FullCodeGenerator::VisitYield. Delegating yield AST nodes now have a try handler index, for the try/catch. Otherwise the implementation is straightforward. BUG= Review URL: https://codereview.chromium.org/15210004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14712 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index aa5aa80..bdfa43b 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -1968,8 +1968,108 @@ void FullCodeGenerator::VisitYield(Yield* expr) { break; } - case Yield::DELEGATING: - UNIMPLEMENTED(); + case Yield::DELEGATING: { + VisitForStackValue(expr->generator_object()); + + // Initial stack layout is as follows: + // [sp + 1 * kPointerSize] iter + // [sp + 0 * kPointerSize] g + + Label l_catch, l_try, l_resume, l_send, l_call, l_loop; + // Initial send value is undefined. + __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); + __ Branch(&l_send); + + // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; } + __ bind(&l_catch); + __ mov(a0, v0); + handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); + __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter + __ push(a3); // iter + __ push(a0); // exception + __ mov(a0, a3); // iter + __ push(a0); // push LoadIC state + __ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw" + Handle throw_ic = isolate()->builtins()->LoadIC_Initialize(); + CallIC(throw_ic); // iter.throw in a0 + __ mov(a0, v0); + __ Addu(sp, sp, Operand(kPointerSize)); // drop LoadIC state + __ jmp(&l_call); + + // try { received = yield result.value } + __ bind(&l_try); + __ pop(a0); // result.value + __ PushTryHandler(StackHandler::CATCH, expr->index()); + const int handler_size = StackHandlerConstants::kSize; + __ push(a0); // result.value + __ lw(a3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size)); // g + __ push(a3); // g + __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); + __ mov(a0, v0); + __ lw(context_register(), + MemOperand(fp, StandardFrameConstants::kContextOffset)); + __ LoadRoot(at, Heap::kTheHoleValueRootIndex); + __ Branch(&l_resume, ne, a0, Operand(at)); + EmitReturnIteratorResult(false); + __ mov(a0, v0); + __ bind(&l_resume); // received in a0 + __ PopTryHandler(); + + // receiver = iter; f = iter.send; arg = received; + __ bind(&l_send); + __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter + __ push(a3); // iter + __ push(a0); // received + __ mov(a0, a3); // iter + __ push(a0); // push LoadIC state + __ LoadRoot(a2, Heap::ksend_stringRootIndex); // "send" + Handle send_ic = isolate()->builtins()->LoadIC_Initialize(); + CallIC(send_ic); // iter.send in a0 + __ mov(a0, v0); + __ Addu(sp, sp, Operand(kPointerSize)); // drop LoadIC state + + // result = f.call(receiver, arg); + __ bind(&l_call); + Label l_call_runtime; + __ JumpIfSmi(a0, &l_call_runtime); + __ GetObjectType(a0, a1, a1); + __ Branch(&l_call_runtime, ne, a1, Operand(JS_FUNCTION_TYPE)); + __ mov(a1, a0); + ParameterCount count(1); + __ InvokeFunction(a1, count, CALL_FUNCTION, + NullCallWrapper(), CALL_AS_METHOD); + __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); + __ jmp(&l_loop); + __ bind(&l_call_runtime); + __ push(a0); + __ CallRuntime(Runtime::kCall, 3); + + // val = result.value; if (!result.done) goto l_try; + __ bind(&l_loop); + __ mov(a0, v0); + // result.value + __ push(a0); // save result + __ LoadRoot(a2, Heap::kvalue_stringRootIndex); // "value" + Handle value_ic = isolate()->builtins()->LoadIC_Initialize(); + CallIC(value_ic); // result.value in a0 + __ mov(a0, v0); + __ pop(a1); // result + __ push(a0); // result.value + __ mov(a0, a1); // result + __ push(a0); // push LoadIC state + __ LoadRoot(a2, Heap::kdone_stringRootIndex); // "done" + Handle done_ic = isolate()->builtins()->LoadIC_Initialize(); + CallIC(done_ic); // result.done in v0 + __ Addu(sp, sp, Operand(kPointerSize)); // drop LoadIC state + ToBooleanStub stub(v0); + __ CallStub(&stub); + __ Branch(&l_try, eq, v0, Operand(zero_reg)); + + // result.value + __ pop(v0); // result.value + context()->DropAndPlug(2, v0); // drop iter and g + break; + } } }