Revision: 15096
Author: [email protected]
Date: Wed Jun 12 12:41:29 2013
Log: MIPS: Allocate generator result objects before unwinding try
handlers
Port r15079 (1ebdfdc6)
Original commit message:
When a generator suspends, it saves its state out to the heap and
unwinds try handlers but doesn't pop anything off the stack. Instead it
relies on no GC happening between the suspend and the return from the
generator. However this was not the case: boxing the result object
could cause GC, which would try to traverse the stack but would
misinterpret words from unwound try handlers as heap objects.
This CL changes to allocate the result objects before the suspend. It
also removes the generators-iteration skip introduced in r15065.
BUG=
Review URL: https://codereview.chromium.org/16820004
http://code.google.com/p/v8/source/detail?r=15096
Modified:
/branches/bleeding_edge/src/mips/full-codegen-mips.cc
=======================================
--- /branches/bleeding_edge/src/mips/full-codegen-mips.cc Mon Jun 10
11:16:27 2013
+++ /branches/bleeding_edge/src/mips/full-codegen-mips.cc Wed Jun 12
12:41:29 2013
@@ -1998,8 +1998,12 @@
VisitForStackValue(expr->expression());
switch (expr->yield_kind()) {
- case Yield::INITIAL:
- case Yield::SUSPEND: {
+ case Yield::SUSPEND:
+ // Pop value from top-of-stack slot; box result into result register.
+ EmitCreateIteratorResult(false);
+ __ push(result_register());
+ // Fall through.
+ case Yield::INITIAL: {
VisitForStackValue(expr->generator_object());
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
__ lw(context_register(),
@@ -2008,12 +2012,8 @@
Label resume;
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ Branch(&resume, ne, result_register(), Operand(at));
- if (expr->yield_kind() == Yield::SUSPEND) {
- EmitReturnIteratorResult(false);
- } else {
- __ pop(result_register());
- EmitReturnSequence();
- }
+ __ pop(result_register());
+ EmitReturnSequence();
__ bind(&resume);
context()->Plug(result_register());
@@ -2025,7 +2025,10 @@
__ li(a1,
Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
__ sw(a1, FieldMemOperand(result_register(),
JSGeneratorObject::kContinuationOffset));
- EmitReturnIteratorResult(true);
+ // Pop value from top-of-stack slot, box result into result register.
+ EmitCreateIteratorResult(true);
+ EmitUnwindBeforeReturn();
+ EmitReturnSequence();
break;
}
@@ -2057,10 +2060,10 @@
// try { received = yield result.value }
__ bind(&l_try);
- __ pop(a0); // result.value
+ EmitCreateIteratorResult(false); // pop and box to
v0
__ PushTryHandler(StackHandler::CATCH, expr->index());
const int handler_size = StackHandlerConstants::kSize;
- __ push(a0); // result.value
+ __ push(a0); // result
__ lw(a3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size));
// g
__ push(a3); // g
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
@@ -2069,7 +2072,8 @@
MemOperand(fp, StandardFrameConstants::kContextOffset));
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ Branch(&l_resume, ne, a0, Operand(at));
- EmitReturnIteratorResult(false);
+ __ pop(v0); // result
+ EmitReturnSequence();
__ mov(a0, v0);
__ bind(&l_resume); // received in a0
__ PopTryHandler();
@@ -2226,13 +2230,20 @@
}
-void FullCodeGenerator::EmitReturnIteratorResult(bool done) {
+void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
Label gc_required;
Label allocated;
Handle<Map> map(isolate()->native_context()->generator_result_map());
__ Allocate(map->instance_size(), a0, a2, a3, &gc_required, TAG_OBJECT);
+ __ jmp(&allocated);
+
+ __ bind(&gc_required);
+ __ Push(Smi::FromInt(map->instance_size()));
+ __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
+ __ lw(context_register(),
+ MemOperand(fp, StandardFrameConstants::kContextOffset));
__ bind(&allocated);
__ li(a1, Operand(map));
@@ -2252,27 +2263,7 @@
// root set.
__ RecordWriteField(a0, JSGeneratorObject::kResultValuePropertyOffset,
a2, a3, kRAHasBeenSaved, kDontSaveFPRegs);
-
- if (done) {
- // Exit all nested statements.
- NestedStatement* current = nesting_stack_;
- int stack_depth = 0;
- int context_length = 0;
- while (current != NULL) {
- current = current->Exit(&stack_depth, &context_length);
- }
- __ Drop(stack_depth);
- }
-
__ mov(result_register(), a0);
- EmitReturnSequence();
-
- __ bind(&gc_required);
- __ Push(Smi::FromInt(map->instance_size()));
- __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
- __ lw(context_register(),
- MemOperand(fp, StandardFrameConstants::kContextOffset));
- __ jmp(&allocated);
}
--
--
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.