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()); |
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)) return alloc; |
| 2456 |
| 2457 for (int i = 0; i < operands_count; i++) { |
| 2458 operand_stack->set(i, frame->GetOperand(i)); |
| 2459 } |
| 2460 generator_object->set_operand_stack(operand_stack); |
2467 } | 2461 } |
2468 | 2462 |
| 2463 // Set continuation down here to avoid side effects if the operand stack |
| 2464 // allocation fails. |
| 2465 intptr_t offset = frame->pc() - function->code()->instruction_start(); |
| 2466 ASSERT(offset > 0 && Smi::IsValid(offset)); |
| 2467 generator_object->set_continuation(offset); |
| 2468 |
2469 // It's possible for the context to be other than the initial context even if | 2469 // 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 | 2470 // 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. | 2471 // body of a "with" statement. Therefore we always save the context. |
2472 generator_object->set_context(Context::cast(frame->context())); | 2472 generator_object->set_context(Context::cast(frame->context())); |
2473 | 2473 |
2474 // The return value is the hole for a suspend return, and anything else for a | 2474 // The return value is the hole for a suspend return, and anything else for a |
2475 // resume return. | 2475 // resume return. |
2476 return isolate->heap()->the_hole_value(); | 2476 return isolate->heap()->the_hole_value(); |
2477 } | 2477 } |
2478 | 2478 |
2479 | 2479 |
2480 // Note that this function is the slow path for resuming generators. It is only | 2480 // 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 | 2481 // 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 | 2482 // needing rewinding, or if the resume should throw an exception. The fast path |
2483 // is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is | 2483 // is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is |
2484 // inlined into GeneratorNext, GeneratorSend, and GeneratorThrow. | 2484 // inlined into GeneratorNext, GeneratorSend, and GeneratorThrow. |
2485 // EmitGeneratorResumeResume is called in any case, as it needs to reconstruct | 2485 // EmitGeneratorResumeResume is called in any case, as it needs to reconstruct |
2486 // the stack frame and make space for arguments and operands. | 2486 // the stack frame and make space for arguments and operands. |
2487 RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) { | 2487 RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) { |
2488 HandleScope scope(isolate); | 2488 NoHandleAllocation ha(isolate); |
2489 ASSERT(args.length() == 3); | 2489 ASSERT(args.length() == 3); |
2490 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0); | 2490 CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0); |
2491 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); | 2491 CONVERT_ARG_CHECKED(Object, value, 1); |
2492 CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2); | 2492 CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2); |
2493 JavaScriptFrameIterator stack_iterator(isolate); | 2493 JavaScriptFrameIterator stack_iterator(isolate); |
2494 JavaScriptFrame *frame = stack_iterator.frame(); | 2494 JavaScriptFrame* frame = stack_iterator.frame(); |
2495 | 2495 |
2496 ASSERT_EQ(frame->function(), generator_object->function()); | 2496 ASSERT_EQ(frame->function(), generator_object->function()); |
2497 | 2497 |
2498 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0); | 2498 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0); |
2499 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0); | 2499 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0); |
2500 | 2500 |
2501 Address pc = generator_object->function()->code()->instruction_start(); | 2501 Address pc = generator_object->function()->code()->instruction_start(); |
2502 int offset = generator_object->continuation(); | 2502 int offset = generator_object->continuation(); |
2503 ASSERT(offset > 0); | 2503 ASSERT(offset > 0); |
2504 frame->set_pc(pc + offset); | 2504 frame->set_pc(pc + offset); |
2505 generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting); | 2505 generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting); |
2506 | 2506 |
2507 if (generator_object->operand_stack()->length() != 0) { | 2507 FixedArray* operand_stack = generator_object->operand_stack(); |
2508 // TODO(wingo): Copy operand stack. Rewind handlers. | 2508 int operands_count = operand_stack->length(); |
2509 UNIMPLEMENTED(); | 2509 if (operands_count != 0) { |
| 2510 // TODO(wingo): Rewind stack handlers. However until |
| 2511 // SuspendJSGeneratorObject unwinds them, we won't see frames with stack |
| 2512 // handlers here. |
| 2513 for (int i = 0; i < operands_count; i++) { |
| 2514 ASSERT_EQ(frame->GetOperand(i), isolate->heap()->the_hole_value()); |
| 2515 Memory::Object_at(frame->GetOperandSlot(i)) = operand_stack->get(i); |
| 2516 } |
| 2517 generator_object->set_operand_stack(isolate->heap()->empty_fixed_array()); |
2510 } | 2518 } |
2511 | 2519 |
2512 JSGeneratorObject::ResumeMode resume_mode = | 2520 JSGeneratorObject::ResumeMode resume_mode = |
2513 static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int); | 2521 static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int); |
2514 switch (resume_mode) { | 2522 switch (resume_mode) { |
2515 case JSGeneratorObject::SEND: | 2523 case JSGeneratorObject::SEND: |
2516 return *value; | 2524 return value; |
2517 case JSGeneratorObject::THROW: | 2525 case JSGeneratorObject::THROW: |
2518 return isolate->Throw(*value); | 2526 return isolate->Throw(value); |
2519 } | 2527 } |
2520 | 2528 |
2521 UNREACHABLE(); | 2529 UNREACHABLE(); |
2522 return isolate->ThrowIllegalOperation(); | 2530 return isolate->ThrowIllegalOperation(); |
2523 } | 2531 } |
2524 | 2532 |
2525 | 2533 |
2526 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowGeneratorStateError) { | 2534 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowGeneratorStateError) { |
2527 HandleScope scope(isolate); | 2535 HandleScope scope(isolate); |
2528 ASSERT(args.length() == 1); | 2536 ASSERT(args.length() == 1); |
2529 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); | 2537 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); |
2530 int continuation = generator->continuation(); | 2538 int continuation = generator->continuation(); |
2531 const char *message = continuation == JSGeneratorObject::kGeneratorClosed ? | 2539 const char* message = continuation == JSGeneratorObject::kGeneratorClosed ? |
2532 "generator_finished" : "generator_running"; | 2540 "generator_finished" : "generator_running"; |
2533 Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0); | 2541 Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0); |
2534 Handle<Object> error = isolate->factory()->NewError(message, argv); | 2542 Handle<Object> error = isolate->factory()->NewError(message, argv); |
2535 return isolate->Throw(*error); | 2543 return isolate->Throw(*error); |
2536 } | 2544 } |
2537 | 2545 |
2538 | 2546 |
2539 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate, | 2547 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate, |
2540 Object* char_code) { | 2548 Object* char_code) { |
2541 if (char_code->IsNumber()) { | 2549 if (char_code->IsNumber()) { |
(...skipping 10810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13352 // Handle last resort GC and make sure to allow future allocations | 13360 // Handle last resort GC and make sure to allow future allocations |
13353 // to grow the heap without causing GCs (if possible). | 13361 // to grow the heap without causing GCs (if possible). |
13354 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13362 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13355 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 13363 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
13356 "Runtime::PerformGC"); | 13364 "Runtime::PerformGC"); |
13357 } | 13365 } |
13358 } | 13366 } |
13359 | 13367 |
13360 | 13368 |
13361 } } // namespace v8::internal | 13369 } } // namespace v8::internal |
OLD | NEW |