OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2414 generator->set_function(function); | 2414 generator->set_function(function); |
2415 generator->set_context(Context::cast(frame->context())); | 2415 generator->set_context(Context::cast(frame->context())); |
2416 generator->set_continuation(0); | 2416 generator->set_continuation(0); |
2417 generator->set_operand_stack(isolate->heap()->empty_fixed_array()); | 2417 generator->set_operand_stack(isolate->heap()->empty_fixed_array()); |
2418 | 2418 |
2419 return generator; | 2419 return generator; |
2420 } | 2420 } |
2421 | 2421 |
2422 | 2422 |
2423 RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) { | 2423 RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) { |
2424 HandleScope scope(isolate); | 2424 NoHandleAllocation ha(isolate); |
2425 ASSERT(args.length() == 1); | 2425 ASSERT(args.length() == 1); |
2426 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0); | 2426 CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0); |
2427 | 2427 |
2428 JavaScriptFrameIterator stack_iterator(isolate); | 2428 JavaScriptFrameIterator stack_iterator(isolate); |
2429 JavaScriptFrame *frame = stack_iterator.frame(); | 2429 JavaScriptFrame *frame = stack_iterator.frame(); |
2430 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 2430 JSFunction *function = JSFunction::cast(frame->function()); |
Michael Starzinger
2013/04/26 09:53:16
style: The '*' sticks to the left. There are sever
wingo
2013/04/26 10:11:42
Fixed this and other locations.
| |
2431 RUNTIME_ASSERT(function->shared()->is_generator()); | 2431 RUNTIME_ASSERT(function->shared()->is_generator()); |
2432 ASSERT_EQ(function, generator_object->function()); | |
2432 | 2433 |
2433 intptr_t offset = frame->pc() - function->code()->instruction_start(); | 2434 // We expect there to be at least two values on the operand stack: the return |
2434 ASSERT(*function == generator_object->function()); | 2435 // value of the yield expression, and the argument to this runtime call. |
2435 ASSERT(offset > 0 && Smi::IsValid(offset)); | 2436 // Neither of those should be saved. |
2436 generator_object->set_continuation(static_cast<int>(offset)); | 2437 int operands_count = frame->ComputeOperandsCount(); |
2438 ASSERT(operands_count >= 2); | |
2439 operands_count -= 2; | |
2437 | 2440 |
2438 // Generator functions force context allocation for locals, so Local0 points | 2441 if (operands_count == 0) { |
2439 // to the bottom of the operand stack. Assume the stack grows down. | |
2440 // | |
2441 // TODO(wingo): Move these magical calculations to frames.h when the | |
2442 // generators implementation has stabilized. | |
2443 intptr_t stack_size_in_bytes = | |
2444 (frame->fp() + JavaScriptFrameConstants::kLocal0Offset) - | |
2445 (frame->sp() - kPointerSize); | |
2446 ASSERT(IsAddressAligned(frame->fp(), kPointerSize)); | |
2447 ASSERT(IsAligned(stack_size_in_bytes, kPointerSize)); | |
2448 ASSERT(stack_size_in_bytes >= 0); | |
2449 ASSERT(Smi::IsValid(stack_size_in_bytes)); | |
2450 intptr_t stack_size = stack_size_in_bytes >> kPointerSizeLog2; | |
2451 | |
2452 // We expect there to be at least two values on the stack: the return value of | |
2453 // the yield expression, and the argument to this runtime call. Neither of | |
2454 // those should be saved. | |
2455 ASSERT(stack_size >= 2); | |
2456 stack_size -= 2; | |
2457 | |
2458 if (stack_size == 0) { | |
2459 ASSERT_EQ(generator_object->operand_stack(), | 2442 ASSERT_EQ(generator_object->operand_stack(), |
2460 isolate->heap()->empty_fixed_array()); | 2443 isolate->heap()->empty_fixed_array()); |
2461 // If there are no operands on the stack, there shouldn't be a handler | 2444 // If there are no operands on the stack, there shouldn't be a handler |
2462 // active either. | 2445 // active either. |
2463 ASSERT(!frame->HasHandler()); | 2446 ASSERT(!frame->HasHandler()); |
2464 } else { | 2447 } else { |
2465 // TODO(wingo): Save the operand stack and/or the stack handlers. | 2448 if (frame->HasHandler()) { |
2466 UNIMPLEMENTED(); | 2449 // TODO(wingo): Unwind the stack handlers. |
2450 UNIMPLEMENTED(); | |
2451 } | |
2452 | |
2453 FixedArray* operand_stack; | |
2454 MaybeObject* alloc = isolate->heap()->AllocateFixedArray(operands_count); | |
2455 if (!alloc->To(&operand_stack)) | |
Michael Starzinger
2013/04/26 09:53:16
nit: Conditional fits into one line.
wingo
2013/04/26 10:11:42
Done.
| |
2456 return alloc; | |
2457 | |
2458 for (int i = 0; i < operands_count; i++) | |
Michael Starzinger
2013/04/26 09:53:16
style: Add curly braces around loop body.
wingo
2013/04/26 10:11:42
Done.
| |
2459 // Since operand_stack is in NewSpace, no write barrier is needed. | |
2460 operand_stack->set(i, frame->GetOperand(i), SKIP_WRITE_BARRIER); | |
Michael Starzinger
2013/04/26 09:53:16
The allocation function above doesn't guarantee th
wingo
2013/04/26 10:11:42
Good catch!
| |
2461 generator_object->set_operand_stack(operand_stack); | |
2467 } | 2462 } |
2468 | 2463 |
2464 // Set continuation down here to avoid side effects if the operand stack | |
2465 // allocation fails. | |
2466 intptr_t offset = frame->pc() - function->code()->instruction_start(); | |
2467 ASSERT(offset > 0 && Smi::IsValid(offset)); | |
2468 generator_object->set_continuation(offset); | |
2469 | |
2469 // It's possible for the context to be other than the initial context even if | 2470 // It's possible for the context to be other than the initial context even if |
2470 // there is no stack handler active. For example, this is the case in the | 2471 // there is no stack handler active. For example, this is the case in the |
2471 // body of a "with" statement. Therefore we always save the context. | 2472 // body of a "with" statement. Therefore we always save the context. |
2472 generator_object->set_context(Context::cast(frame->context())); | 2473 generator_object->set_context(Context::cast(frame->context())); |
2473 | 2474 |
2474 // The return value is the hole for a suspend return, and anything else for a | 2475 // The return value is the hole for a suspend return, and anything else for a |
2475 // resume return. | 2476 // resume return. |
2476 return isolate->heap()->the_hole_value(); | 2477 return isolate->heap()->the_hole_value(); |
2477 } | 2478 } |
2478 | 2479 |
2479 | 2480 |
2480 // Note that this function is the slow path for resuming generators. It is only | 2481 // Note that this function is the slow path for resuming generators. It is only |
2481 // called if the suspended activation had operands on the stack, stack handlers | 2482 // called if the suspended activation had operands on the stack, stack handlers |
2482 // needing rewinding, or if the resume should throw an exception. The fast path | 2483 // needing rewinding, or if the resume should throw an exception. The fast path |
2483 // is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is | 2484 // is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is |
2484 // inlined into GeneratorNext, GeneratorSend, and GeneratorThrow. | 2485 // inlined into GeneratorNext, GeneratorSend, and GeneratorThrow. |
2485 // EmitGeneratorResumeResume is called in any case, as it needs to reconstruct | 2486 // EmitGeneratorResumeResume is called in any case, as it needs to reconstruct |
2486 // the stack frame and make space for arguments and operands. | 2487 // the stack frame and make space for arguments and operands. |
2487 RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) { | 2488 RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) { |
2488 HandleScope scope(isolate); | 2489 NoHandleAllocation ha(isolate); |
2489 ASSERT(args.length() == 3); | 2490 ASSERT(args.length() == 3); |
2490 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0); | 2491 CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0); |
2491 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); | 2492 CONVERT_ARG_CHECKED(Object, value, 1); |
2492 CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2); | 2493 CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2); |
2493 JavaScriptFrameIterator stack_iterator(isolate); | 2494 JavaScriptFrameIterator stack_iterator(isolate); |
2494 JavaScriptFrame *frame = stack_iterator.frame(); | 2495 JavaScriptFrame *frame = stack_iterator.frame(); |
Michael Starzinger
2013/04/26 09:53:16
style: The '*' sticks to the left.
wingo
2013/04/26 10:11:42
Done.
| |
2495 | 2496 |
2496 ASSERT_EQ(frame->function(), generator_object->function()); | 2497 ASSERT_EQ(frame->function(), generator_object->function()); |
2497 | 2498 |
2498 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0); | 2499 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0); |
2499 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0); | 2500 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0); |
2500 | 2501 |
2501 Address pc = generator_object->function()->code()->instruction_start(); | 2502 Address pc = generator_object->function()->code()->instruction_start(); |
2502 int offset = generator_object->continuation(); | 2503 int offset = generator_object->continuation(); |
2503 ASSERT(offset > 0); | 2504 ASSERT(offset > 0); |
2504 frame->set_pc(pc + offset); | 2505 frame->set_pc(pc + offset); |
2505 generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting); | 2506 generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting); |
2506 | 2507 |
2507 if (generator_object->operand_stack()->length() != 0) { | 2508 FixedArray *operand_stack = generator_object->operand_stack(); |
2508 // TODO(wingo): Copy operand stack. Rewind handlers. | 2509 int operands_count = operand_stack->length(); |
2509 UNIMPLEMENTED(); | 2510 if (operands_count != 0) { |
2511 // TODO(wingo): Rewind stack handlers. However until | |
2512 // SuspendJSGeneratorObject unwinds them, we won't see frames with stack | |
2513 // handlers here. | |
2514 for (int i = 0; i < operands_count; i++) { | |
2515 ASSERT_EQ(frame->GetOperand(i), isolate->heap()->the_hole_value()); | |
2516 Memory::Object_at(frame->GetOperandSlot(i)) = operand_stack->get(i); | |
2517 } | |
2518 generator_object->set_operand_stack(isolate->heap()->empty_fixed_array()); | |
2510 } | 2519 } |
2511 | 2520 |
2512 JSGeneratorObject::ResumeMode resume_mode = | 2521 JSGeneratorObject::ResumeMode resume_mode = |
2513 static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int); | 2522 static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int); |
2514 switch (resume_mode) { | 2523 switch (resume_mode) { |
2515 case JSGeneratorObject::SEND: | 2524 case JSGeneratorObject::SEND: |
2516 return *value; | 2525 return value; |
2517 case JSGeneratorObject::THROW: | 2526 case JSGeneratorObject::THROW: |
2518 return isolate->Throw(*value); | 2527 return isolate->Throw(value); |
2519 } | 2528 } |
2520 | 2529 |
2521 UNREACHABLE(); | 2530 UNREACHABLE(); |
2522 return isolate->ThrowIllegalOperation(); | 2531 return isolate->ThrowIllegalOperation(); |
2523 } | 2532 } |
2524 | 2533 |
2525 | 2534 |
2526 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowGeneratorStateError) { | 2535 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowGeneratorStateError) { |
2527 HandleScope scope(isolate); | 2536 HandleScope scope(isolate); |
2528 ASSERT(args.length() == 1); | 2537 ASSERT(args.length() == 1); |
(...skipping 10823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13352 // Handle last resort GC and make sure to allow future allocations | 13361 // Handle last resort GC and make sure to allow future allocations |
13353 // to grow the heap without causing GCs (if possible). | 13362 // to grow the heap without causing GCs (if possible). |
13354 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13363 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13355 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 13364 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
13356 "Runtime::PerformGC"); | 13365 "Runtime::PerformGC"); |
13357 } | 13366 } |
13358 } | 13367 } |
13359 | 13368 |
13360 | 13369 |
13361 } } // namespace v8::internal | 13370 } } // namespace v8::internal |
OLD | NEW |