Chromium Code Reviews| Index: src/ia32/full-codegen-ia32.cc |
| diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc |
| index 67497864d575848bfaeb39f4598ef902181cf8ff..6c2ed7cb12b473d4f1bf71c6b8debca4e1bcac96 100644 |
| --- a/src/ia32/full-codegen-ia32.cc |
| +++ b/src/ia32/full-codegen-ia32.cc |
| @@ -1921,8 +1921,95 @@ 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. |
| + __ mov(eax, isolate()->factory()->undefined_value()); |
| + __ jmp(&l_send); |
| + |
| + // catch (e) { receiver = iter; f = iter.throw; arg = e; } |
|
rossberg
2013/05/13 11:14:56
...; goto l_call;
|
| + __ bind(&l_catch); |
| + handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
| + __ push(Operand(esp, 1 * kPointerSize)); // iter |
| + __ push(eax); // exception |
| + __ mov(edx, Operand(esp, 3 * kPointerSize)); // iter |
|
rossberg
2013/05/13 11:14:56
Nit: Why not do this 2 lines earlier and then push
|
| + __ mov(ecx, isolate()->factory()->throw_string()); // "throw" |
| + Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize(); |
| + CallIC(throw_ic); // iter.throw in eax |
| + __ jmp(&l_call); |
| + |
| + // try { received = yield result.value } |
| + __ bind(&l_try); |
| + __ pop(eax); // result.value |
| + __ PushTryHandler(StackHandler::CATCH, expr->index()); |
| + const int handler_size = StackHandlerConstants::kSize; |
| + __ push(eax); // result.value |
| + __ push(Operand(esp, (0 + 1) * kPointerSize + handler_size)); // g |
| + __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| + __ mov(context_register(), |
| + Operand(ebp, StandardFrameConstants::kContextOffset)); |
| + __ CompareRoot(eax, Heap::kTheHoleValueRootIndex); |
| + __ j(not_equal, &l_resume); |
| + EmitReturnIteratorResult(false); |
| + __ bind(&l_resume); // received in eax |
| + __ PopTryHandler(); |
| + |
| + // receiver = iter; f = iter.send; arg = received; |
| + __ bind(&l_send); |
| + __ push(Operand(esp, 1 * kPointerSize)); // iter |
| + __ push(eax); // received |
| + __ mov(edx, Operand(esp, 3 * kPointerSize)); // iter |
|
rossberg
2013/05/13 11:14:56
Nit: same here
|
| + __ mov(ecx, isolate()->factory()->send_string()); // "send" |
| + Handle<Code> send_ic = isolate()->builtins()->LoadIC_Initialize(); |
| + CallIC(send_ic); // iter.send in rax |
|
rossberg
2013/05/13 11:14:56
s/rax/eax/
|
| + |
| + // result = f.call(receiver, arg); |
| + __ bind(&l_call); |
| + Label l_call_runtime; |
| + __ JumpIfSmi(eax, &l_call_runtime); |
| + __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
| + __ j(not_equal, &l_call_runtime); |
| + __ mov(edi, eax); |
| + ParameterCount count(1); |
| + __ InvokeFunction(edi, count, CALL_FUNCTION, |
| + NullCallWrapper(), CALL_AS_METHOD); |
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| + __ jmp(&l_loop); |
| + __ bind(&l_call_runtime); |
| + __ push(eax); |
| + __ CallRuntime(Runtime::kCall, 3); |
| + |
| + // val = result.value; if (!result.done) goto l_try; |
| + __ bind(&l_loop); |
| + // result.value |
| + __ push(eax); // save result |
| + __ mov(edx, eax); // result |
| + __ mov(ecx, isolate()->factory()->value_string()); // "value" |
| + Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize(); |
| + CallIC(value_ic); // result.value in rax |
| + __ pop(ebx); // result |
| + __ push(eax); // result.value |
| + __ mov(edx, ebx); // result |
| + __ mov(ecx, isolate()->factory()->done_string()); // "done" |
| + Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize(); |
| + CallIC(done_ic); // result.done in rax |
| + ToBooleanStub stub(eax); |
| + __ push(eax); |
| + __ CallStub(&stub); |
| + __ test(eax, eax); |
| + __ j(zero, &l_try); |
| + |
| + // result.value |
| + __ pop(eax); // result.value |
| + context()->DropAndPlug(2, eax); // drop iter and g |
| + break; |
| + } |
| } |
| } |