Revision: 15113
Author: [email protected]
Date: Thu Jun 13 03:57:11 2013
Log: Delegating yield does not re-box result objects
Delegating yield (yield*) should just pass on the iterator results it
receives instead of re-boxing them.
[email protected]
TEST=mjsunit/harmony/generators-iteration
BUG=
Review URL: https://codereview.chromium.org/16695006
http://code.google.com/p/v8/source/detail?r=15113
Modified:
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
/branches/bleeding_edge/test/mjsunit/harmony/generators-iteration.js
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Thu Jun 13 03:18:28
2013
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Thu Jun 13 03:57:11
2013
@@ -2044,9 +2044,11 @@
__ push(r0); // exception
__ jmp(&l_call);
- // try { received = yield result.value }
+ // try { received = %yield result }
+ // Shuffle the received result above a try handler and yield it
without
+ // re-boxing.
__ bind(&l_try);
- EmitCreateIteratorResult(false); // pop and box to
r0
+ __ pop(r0); // result
__ PushTryHandler(StackHandler::CATCH, expr->index());
const int handler_size = StackHandlerConstants::kSize;
__ push(r0); // result
@@ -2075,16 +2077,9 @@
CallIC(ic);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- // val = result.value; if (!result.done) goto l_try;
+ // if (!result.done) goto l_try;
__ bind(&l_loop);
- // result.value
__ push(r0); // save result
- __ LoadRoot(r2, Heap::kvalue_stringRootIndex); // "value"
- Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(value_ic); // result.value
in r0
- __ pop(r1); // result
- __ push(r0); // result.value
- __ mov(r0, r1); // result
__ LoadRoot(r2, Heap::kdone_stringRootIndex); // "done"
Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
CallIC(done_ic); // result.done in
r0
@@ -2094,7 +2089,10 @@
__ b(eq, &l_try);
// result.value
- __ pop(r0); // result.value
+ __ pop(r0); // result
+ __ LoadRoot(r2, Heap::kvalue_stringRootIndex); // "value"
+ Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
+ CallIC(value_ic); // result.value
in r0
context()->DropAndPlug(2, r0); // drop iter and g
break;
}
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Thu Jun 13
03:18:28 2013
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Thu Jun 13
03:57:11 2013
@@ -2003,9 +2003,11 @@
__ push(eax); // exception
__ jmp(&l_call);
- // try { received = yield result.value }
+ // try { received = %yield result }
+ // Shuffle the received result above a try handler and yield it
without
+ // re-boxing.
__ bind(&l_try);
- EmitCreateIteratorResult(false); // pop and box
to eax
+ __ pop(eax); // result
__ PushTryHandler(StackHandler::CATCH, expr->index());
const int handler_size = StackHandlerConstants::kSize;
__ push(eax); // result
@@ -2034,17 +2036,10 @@
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ Drop(1); // The key is still on the stack; drop it.
- // val = result.value; if (!result.done) goto l_try;
+ // 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 eax
- __ 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
eax
@@ -2054,7 +2049,10 @@
__ j(zero, &l_try);
// result.value
- __ pop(eax); // result.value
+ __ pop(edx); // result
+ __ mov(ecx, isolate()->factory()->value_string()); // "value"
+ Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
+ CallIC(value_ic); // result.value
in eax
context()->DropAndPlug(2, eax); // drop iter and g
break;
}
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Thu Jun 13 03:18:28
2013
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Thu Jun 13 03:57:11
2013
@@ -2026,9 +2026,11 @@
__ push(rax); // exception
__ jmp(&l_call);
- // try { received = yield result.value }
+ // try { received = %yield result }
+ // Shuffle the received result above a try handler and yield it
without
+ // re-boxing.
__ bind(&l_try);
- EmitCreateIteratorResult(false); // pop and box
to rax
+ __ pop(rax); // result
__ PushTryHandler(StackHandler::CATCH, expr->index());
const int handler_size = StackHandlerConstants::kSize;
__ push(rax); // result
@@ -2057,16 +2059,9 @@
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
__ Drop(1); // The key is still on the stack; drop it.
- // val = result.value; if (!result.done) goto l_try;
+ // if (!result.done) goto l_try;
__ bind(&l_loop);
- // result.value
__ push(rax); // save result
- __ LoadRoot(rcx, Heap::kvalue_stringRootIndex); // "value"
- Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
- CallIC(value_ic); // result.value
in rax
- __ pop(rbx); // result
- __ push(rax); // result.value
- __ movq(rax, rbx); // result
__ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done"
Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
CallIC(done_ic); // result.done in
rax
@@ -2076,7 +2071,10 @@
__ j(zero, &l_try);
// result.value
- __ pop(rax); // result.value
+ __ pop(rax); // result
+ __ LoadRoot(rcx, Heap::kvalue_stringRootIndex); // "value"
+ Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize();
+ CallIC(value_ic); // result.value
in rax
context()->DropAndPlug(2, rax); // drop iter and g
break;
}
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/generators-iteration.js
Wed Jun 12 05:52:16 2013
+++ /branches/bleeding_edge/test/mjsunit/harmony/generators-iteration.js
Thu Jun 13 03:57:11 2013
@@ -346,6 +346,36 @@
"foo",
[3, undefined]);
+// Test that yield* re-yields received results without re-boxing.
+function TestDelegatingYield() {
+ function results(results) {
+ var i = 0;
+ function next() {
+ return results[i++];
+ }
+ return { next: next }
+ }
+ function* yield_results(expected) {
+ return yield* results(expected);
+ }
+ function collect_results(iter) {
+ var ret = [];
+ var result;
+ do {
+ result = iter.next();
+ ret.push(result);
+ } while (!result.done);
+ return ret;
+ }
+ // We have to put a full result for the end, because the return will
re-box.
+ var expected = [{value: 1}, 13, "foo", {value: 34, done: true}];
+
+ // Sanity check.
+ assertEquals(expected, collect_results(results(expected)));
+ assertEquals(expected, collect_results(yield_results(expected)));
+}
+TestDelegatingYield();
+
function TestTryCatch(instantiate) {
function* g() { yield 1; try { yield 2; } catch (e) { yield e; } yield
3; }
function Sentinel() {}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.