Revision: 14434
Author: [email protected]
Date: Thu Apr 25 03:59:09 2013
Log: Capture receiver in generator object
Previously there has been no reason to context-allocate the receiver, so
access to the receiver always goes through the stack. This was failing
with generators, which assumed that forcing context allocation would
relieve the need of storing anything but the context and the function on
the stack.
This CL adds a slot in generator objects to capture the receiver, and
restores it when resuming a generator.
BUG=v8:2355
TEST=mjsunit/harmony/generators-iteration
Review URL: https://codereview.chromium.org/14158006
Patch from Andy Wingo <[email protected]>.
http://code.google.com/p/v8/source/detail?r=14434
Modified:
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/objects-debug.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/runtime.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 Wed Apr 24 09:07:44
2013
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Thu Apr 25 03:59:09
2013
@@ -1998,20 +1998,25 @@
__ ldr(cp, FieldMemOperand(r1, JSGeneratorObject::kContextOffset));
__ ldr(r4, FieldMemOperand(r1, JSGeneratorObject::kFunctionOffset));
- // Push holes for arguments to generator function.
+ // Load receiver and store as the first argument.
+ __ ldr(r2, FieldMemOperand(r1, JSGeneratorObject::kReceiverOffset));
+ __ push(r2);
+
+ // Push holes for the rest of the arguments to the generator function.
__ ldr(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
__ ldr(r3,
FieldMemOperand(r3,
SharedFunctionInfo::kFormalParameterCountOffset));
__ LoadRoot(r2, Heap::kTheHoleValueRootIndex);
- Label push_argument_holes;
+ Label push_argument_holes, push_frame;
__ bind(&push_argument_holes);
+ __ sub(r3, r3, Operand(1), SetCC);
+ __ b(mi, &push_frame);
__ push(r2);
- __ sub(r3, r3, Operand(1), SetCC);
- __ b(pl, &push_argument_holes);
+ __ jmp(&push_argument_holes);
// Enter a new JavaScript frame, and initialize its slots as they were
when
// the generator was suspended.
- Label push_frame, resume_frame;
+ Label resume_frame;
__ bind(&push_frame);
__ bl(&resume_frame);
__ jmp(&done);
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Wed Apr 24
06:00:16 2013
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Thu Apr 25
03:59:09 2013
@@ -1959,20 +1959,24 @@
__ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContextOffset));
__ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset));
+ // Push receiver.
+ __ push(FieldOperand(ebx, JSGeneratorObject::kReceiverOffset));
+
// Push holes for arguments to generator function.
__ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
__ mov(edx,
FieldOperand(edx,
SharedFunctionInfo::kFormalParameterCountOffset));
__ mov(ecx, isolate()->factory()->the_hole_value());
- Label push_argument_holes;
+ Label push_argument_holes, push_frame;
__ bind(&push_argument_holes);
- __ push(ecx);
__ sub(edx, Immediate(1));
- __ j(not_carry, &push_argument_holes);
+ __ j(carry, &push_frame);
+ __ push(ecx);
+ __ jmp(&push_argument_holes);
// Enter a new JavaScript frame, and initialize its slots as they were
when
// the generator was suspended.
- Label push_frame, resume_frame;
+ Label resume_frame;
__ bind(&push_frame);
__ call(&resume_frame);
__ jmp(&done);
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc Fri Apr 19 06:26:47 2013
+++ /branches/bleeding_edge/src/objects-debug.cc Thu Apr 25 03:59:09 2013
@@ -416,6 +416,7 @@
// initialized by the generator. Hence these weak checks.
VerifyObjectField(kFunctionOffset);
VerifyObjectField(kContextOffset);
+ VerifyObjectField(kReceiverOffset);
VerifyObjectField(kOperandStackOffset);
VerifyObjectField(kContinuationOffset);
}
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Wed Apr 24 04:32:17 2013
+++ /branches/bleeding_edge/src/objects-inl.h Thu Apr 25 03:59:09 2013
@@ -5054,6 +5054,7 @@
ACCESSORS(JSGeneratorObject, function, JSFunction, kFunctionOffset)
ACCESSORS(JSGeneratorObject, context, Context, kContextOffset)
+ACCESSORS(JSGeneratorObject, receiver, Object, kReceiverOffset)
SMI_ACCESSORS(JSGeneratorObject, continuation, kContinuationOffset)
ACCESSORS(JSGeneratorObject, operand_stack, FixedArray,
kOperandStackOffset)
=======================================
--- /branches/bleeding_edge/src/objects.h Wed Apr 24 06:00:16 2013
+++ /branches/bleeding_edge/src/objects.h Thu Apr 25 03:59:09 2013
@@ -6320,6 +6320,9 @@
// [context]: The context of the suspended computation.
DECL_ACCESSORS(context, Context)
+ // [receiver]: The receiver of the suspended computation.
+ DECL_ACCESSORS(receiver, Object)
+
// [continuation]: Offset into code of continuation.
//
// A positive offset indicates a suspended generator. The special
@@ -6345,7 +6348,8 @@
// Layout description.
static const int kFunctionOffset = JSObject::kHeaderSize;
static const int kContextOffset = kFunctionOffset + kPointerSize;
- static const int kContinuationOffset = kContextOffset + kPointerSize;
+ static const int kReceiverOffset = kContextOffset + kPointerSize;
+ static const int kContinuationOffset = kReceiverOffset + kPointerSize;
static const int kOperandStackOffset = kContinuationOffset +
kPointerSize;
static const int kSize = kOperandStackOffset + kPointerSize;
=======================================
--- /branches/bleeding_edge/src/runtime.cc Wed Apr 24 07:44:08 2013
+++ /branches/bleeding_edge/src/runtime.cc Thu Apr 25 03:59:09 2013
@@ -2413,6 +2413,7 @@
}
generator->set_function(function);
generator->set_context(Context::cast(frame->context()));
+ generator->set_receiver(frame->receiver());
generator->set_continuation(0);
generator->set_operand_stack(isolate->heap()->empty_fixed_array());
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Wed Apr 24 06:00:16
2013
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Thu Apr 25 03:59:09
2013
@@ -1983,21 +1983,25 @@
__ movq(rsi, FieldOperand(rbx, JSGeneratorObject::kContextOffset));
__ movq(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset));
+ // Push receiver.
+ __ push(FieldOperand(rbx, JSGeneratorObject::kReceiverOffset));
+
// Push holes for arguments to generator function.
__ movq(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
__ movsxlq(rdx,
FieldOperand(rdx,
SharedFunctionInfo::kFormalParameterCountOffset));
__ LoadRoot(rcx, Heap::kTheHoleValueRootIndex);
- Label push_argument_holes;
+ Label push_argument_holes, push_frame;
__ bind(&push_argument_holes);
- __ push(rcx);
__ subq(rdx, Immediate(1));
- __ j(not_carry, &push_argument_holes);
+ __ j(carry, &push_frame);
+ __ push(rcx);
+ __ jmp(&push_argument_holes);
// Enter a new JavaScript frame, and initialize its slots as they were
when
// the generator was suspended.
- Label push_frame, resume_frame;
+ Label resume_frame;
__ bind(&push_frame);
__ call(&resume_frame);
__ jmp(&done);
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/generators-iteration.js
Wed Apr 24 06:00:16 2013
+++ /branches/bleeding_edge/test/mjsunit/harmony/generators-iteration.js
Thu Apr 25 03:59:09 2013
@@ -211,32 +211,27 @@
["baz", "qux", undefined]);
// Receivers.
-function TestReceivers() {
- TestGenerator(
- function g17() {
- function* g() { yield this.x; yield this.y; }
- var o = { start: g, x: 1, y: 2 };
- return o.start();
- },
- [1, 2, undefined],
- "foo",
- [1, 2, undefined]);
+TestGenerator(
+ function g17() {
+ function* g() { yield this.x; yield this.y; }
+ var o = { start: g, x: 1, y: 2 };
+ return o.start();
+ },
+ [1, 2, undefined],
+ "foo",
+ [1, 2, undefined]);
- TestGenerator(
- function g18() {
- function* g() { yield this.x; yield this.y; }
- var iter = new g;
- iter.x = 1;
- iter.y = 2;
- return iter;
- },
- [1, 2, undefined],
- "foo",
- [1, 2, undefined]);
-}
-// TODO(wingo): Enable this test. Currently accessing "this" doesn't work
as
-// prior to generators, nothing needed to heap-allocate the receiver.
-// TestReceivers();
+TestGenerator(
+ function g18() {
+ function* g() { yield this.x; yield this.y; }
+ var iter = new g;
+ iter.x = 1;
+ iter.y = 2;
+ return iter;
+ },
+ [1, 2, undefined],
+ "foo",
+ [1, 2, undefined]);
function TestRecursion() {
function TestNextRecursion() {
--
--
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.