Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(535)

Unified Diff: src/runtime.cc

Issue 14348003: Add support for yield expressions (Closed) Base URL: git://github.com/v8/v8.git@master
Patch Set: Fix formatting; add asserts; don't skip write barrier Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/frames-inl.h ('k') | test/mjsunit/harmony/generators-iteration.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index c942d029d45e0614ee8e5cd6cf84ebf84fc962b2..ee717c7cee6d627b1c32c3c6b3fea37dc50d7a05 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -2421,51 +2421,51 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSGeneratorObject) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) {
- HandleScope scope(isolate);
+ NoHandleAllocation ha(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0);
+ CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
JavaScriptFrameIterator stack_iterator(isolate);
- JavaScriptFrame *frame = stack_iterator.frame();
- Handle<JSFunction> function(JSFunction::cast(frame->function()));
+ JavaScriptFrame* frame = stack_iterator.frame();
+ JSFunction* function = JSFunction::cast(frame->function());
RUNTIME_ASSERT(function->shared()->is_generator());
+ ASSERT_EQ(function, generator_object->function());
- intptr_t offset = frame->pc() - function->code()->instruction_start();
- ASSERT(*function == generator_object->function());
- ASSERT(offset > 0 && Smi::IsValid(offset));
- generator_object->set_continuation(static_cast<int>(offset));
+ // We expect there to be at least two values on the operand stack: the return
+ // value of the yield expression, and the argument to this runtime call.
+ // Neither of those should be saved.
+ int operands_count = frame->ComputeOperandsCount();
+ ASSERT(operands_count >= 2);
+ operands_count -= 2;
- // Generator functions force context allocation for locals, so Local0 points
- // to the bottom of the operand stack. Assume the stack grows down.
- //
- // TODO(wingo): Move these magical calculations to frames.h when the
- // generators implementation has stabilized.
- intptr_t stack_size_in_bytes =
- (frame->fp() + JavaScriptFrameConstants::kLocal0Offset) -
- (frame->sp() - kPointerSize);
- ASSERT(IsAddressAligned(frame->fp(), kPointerSize));
- ASSERT(IsAligned(stack_size_in_bytes, kPointerSize));
- ASSERT(stack_size_in_bytes >= 0);
- ASSERT(Smi::IsValid(stack_size_in_bytes));
- intptr_t stack_size = stack_size_in_bytes >> kPointerSizeLog2;
-
- // We expect there to be at least two values on the stack: the return value of
- // the yield expression, and the argument to this runtime call. Neither of
- // those should be saved.
- ASSERT(stack_size >= 2);
- stack_size -= 2;
-
- if (stack_size == 0) {
+ if (operands_count == 0) {
ASSERT_EQ(generator_object->operand_stack(),
isolate->heap()->empty_fixed_array());
// If there are no operands on the stack, there shouldn't be a handler
// active either.
ASSERT(!frame->HasHandler());
} else {
- // TODO(wingo): Save the operand stack and/or the stack handlers.
- UNIMPLEMENTED();
+ if (frame->HasHandler()) {
+ // TODO(wingo): Unwind the stack handlers.
+ UNIMPLEMENTED();
+ }
+
+ FixedArray* operand_stack;
+ MaybeObject* alloc = isolate->heap()->AllocateFixedArray(operands_count);
+ if (!alloc->To(&operand_stack)) return alloc;
+
+ for (int i = 0; i < operands_count; i++) {
+ operand_stack->set(i, frame->GetOperand(i));
+ }
+ generator_object->set_operand_stack(operand_stack);
}
+ // Set continuation down here to avoid side effects if the operand stack
+ // allocation fails.
+ intptr_t offset = frame->pc() - function->code()->instruction_start();
+ ASSERT(offset > 0 && Smi::IsValid(offset));
+ generator_object->set_continuation(offset);
+
// It's possible for the context to be other than the initial context even if
// there is no stack handler active. For example, this is the case in the
// body of a "with" statement. Therefore we always save the context.
@@ -2485,13 +2485,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) {
// EmitGeneratorResumeResume is called in any case, as it needs to reconstruct
// the stack frame and make space for arguments and operands.
RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) {
- HandleScope scope(isolate);
+ NoHandleAllocation ha(isolate);
ASSERT(args.length() == 3);
- CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0);
- CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
+ CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
+ CONVERT_ARG_CHECKED(Object, value, 1);
CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2);
JavaScriptFrameIterator stack_iterator(isolate);
- JavaScriptFrame *frame = stack_iterator.frame();
+ JavaScriptFrame* frame = stack_iterator.frame();
ASSERT_EQ(frame->function(), generator_object->function());
@@ -2504,18 +2504,26 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) {
frame->set_pc(pc + offset);
generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
- if (generator_object->operand_stack()->length() != 0) {
- // TODO(wingo): Copy operand stack. Rewind handlers.
- UNIMPLEMENTED();
+ FixedArray* operand_stack = generator_object->operand_stack();
+ int operands_count = operand_stack->length();
+ if (operands_count != 0) {
+ // TODO(wingo): Rewind stack handlers. However until
+ // SuspendJSGeneratorObject unwinds them, we won't see frames with stack
+ // handlers here.
+ for (int i = 0; i < operands_count; i++) {
+ ASSERT_EQ(frame->GetOperand(i), isolate->heap()->the_hole_value());
+ Memory::Object_at(frame->GetOperandSlot(i)) = operand_stack->get(i);
+ }
+ generator_object->set_operand_stack(isolate->heap()->empty_fixed_array());
}
JSGeneratorObject::ResumeMode resume_mode =
static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int);
switch (resume_mode) {
case JSGeneratorObject::SEND:
- return *value;
+ return value;
case JSGeneratorObject::THROW:
- return isolate->Throw(*value);
+ return isolate->Throw(value);
}
UNREACHABLE();
@@ -2528,7 +2536,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowGeneratorStateError) {
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
int continuation = generator->continuation();
- const char *message = continuation == JSGeneratorObject::kGeneratorClosed ?
+ const char* message = continuation == JSGeneratorObject::kGeneratorClosed ?
"generator_finished" : "generator_running";
Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0);
Handle<Object> error = isolate->factory()->NewError(message, argv);
« no previous file with comments | « src/frames-inl.h ('k') | test/mjsunit/harmony/generators-iteration.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698