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.


Reply via email to