Reviewers: Michael Starzinger, rossberg,
Message:
As discussed on es-discuss last month, yield* should not re-box the result
that
it yields.
Description:
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], [email protected]
TEST=mjsunit/harmony/generators-iteration
BUG=
Please review this at https://codereview.chromium.org/16695006/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/arm/full-codegen-arm.cc
M src/ia32/full-codegen-ia32.cc
M src/x64/full-codegen-x64.cc
M test/mjsunit/harmony/generators-iteration.js
Index: src/arm/full-codegen-arm.cc
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index
fdebe15afd08e5ef7129877b925eafac7a8a2e4f..7b2e1adbd7e24d9763b98ee13e6fc73bbd148f8b
100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -2046,9 +2046,11 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ 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
@@ -2077,16 +2079,9 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
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
@@ -2096,7 +2091,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ 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;
}
Index: src/ia32/full-codegen-ia32.cc
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index
9536ccefdf56e74b252d71ecfa54243a425ddf7e..1064f777d6a93fa6f98563ae2b7b60639e82e12f
100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -2005,9 +2005,11 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ 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
@@ -2036,17 +2038,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ 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
@@ -2056,7 +2051,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ 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;
}
Index: src/x64/full-codegen-x64.cc
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index
3b90d4181af2a33c83188de0191861e212993636..559c417dd579fc81c2dbc0f91428c5f76cd572b4
100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -2029,9 +2029,11 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ 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
@@ -2060,16 +2062,9 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ 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
@@ -2079,7 +2074,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ 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;
}
Index: test/mjsunit/harmony/generators-iteration.js
diff --git a/test/mjsunit/harmony/generators-iteration.js
b/test/mjsunit/harmony/generators-iteration.js
index
2ca35f2ee8a4037e86867fe4ecb49fa2eff0b9b6..7211896c6c9a4d78ea08579d5a5a5e6f4463cb1e
100644
--- a/test/mjsunit/harmony/generators-iteration.js
+++ b/test/mjsunit/harmony/generators-iteration.js
@@ -346,6 +346,34 @@ TestGenerator(
"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 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((function*(){return 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.