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.


Reply via email to