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 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 | 533 |
534 void StackGuard::Continue(InterruptFlag after_what) { | 534 void StackGuard::Continue(InterruptFlag after_what) { |
535 ExecutionAccess access(isolate_); | 535 ExecutionAccess access(isolate_); |
536 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what); | 536 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what); |
537 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) { | 537 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) { |
538 reset_limits(access); | 538 reset_limits(access); |
539 } | 539 } |
540 } | 540 } |
541 | 541 |
542 | 542 |
| 543 void StackGuard::RequestInterrupt(InterruptCallback callback, void* data) { |
| 544 ExecutionAccess access(isolate_); |
| 545 thread_local_.interrupt_flags_ |= API_INTERRUPT; |
| 546 thread_local_.interrupt_callback_ = callback; |
| 547 thread_local_.interrupt_callback_data_ = data; |
| 548 set_interrupt_limits(access); |
| 549 } |
| 550 |
| 551 |
| 552 void StackGuard::ClearInterrupt() { |
| 553 thread_local_.interrupt_callback_ = 0; |
| 554 thread_local_.interrupt_callback_data_ = 0; |
| 555 Continue(API_INTERRUPT); |
| 556 } |
| 557 |
| 558 |
| 559 bool StackGuard::IsAPIInterrupt() { |
| 560 ExecutionAccess access(isolate_); |
| 561 return thread_local_.interrupt_flags_ & API_INTERRUPT; |
| 562 } |
| 563 |
| 564 |
| 565 void StackGuard::InvokeInterruptCallback() { |
| 566 InterruptCallback callback = 0; |
| 567 void* data = 0; |
| 568 |
| 569 { |
| 570 ExecutionAccess access(isolate_); |
| 571 callback = thread_local_.interrupt_callback_; |
| 572 data = thread_local_.interrupt_callback_data_; |
| 573 thread_local_.interrupt_callback_ = NULL; |
| 574 thread_local_.interrupt_callback_data_ = NULL; |
| 575 } |
| 576 |
| 577 if (callback != NULL) { |
| 578 VMState<EXTERNAL> state(isolate_); |
| 579 HandleScope handle_scope(isolate_); |
| 580 callback(reinterpret_cast<v8::Isolate*>(isolate_), data); |
| 581 } |
| 582 } |
| 583 |
| 584 |
543 char* StackGuard::ArchiveStackGuard(char* to) { | 585 char* StackGuard::ArchiveStackGuard(char* to) { |
544 ExecutionAccess access(isolate_); | 586 ExecutionAccess access(isolate_); |
545 OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); | 587 OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); |
546 ThreadLocal blank; | 588 ThreadLocal blank; |
547 | 589 |
548 // Set the stack limits using the old thread_local_. | 590 // Set the stack limits using the old thread_local_. |
549 // TODO(isolates): This was the old semantics of constructing a ThreadLocal | 591 // TODO(isolates): This was the old semantics of constructing a ThreadLocal |
550 // (as the ctor called SetStackLimits, which looked at the | 592 // (as the ctor called SetStackLimits, which looked at the |
551 // current thread_local_ from StackGuard)-- but is this | 593 // current thread_local_ from StackGuard)-- but is this |
552 // really what was intended? | 594 // really what was intended? |
(...skipping 21 matching lines...) Expand all Loading... |
574 | 616 |
575 | 617 |
576 void StackGuard::ThreadLocal::Clear() { | 618 void StackGuard::ThreadLocal::Clear() { |
577 real_jslimit_ = kIllegalLimit; | 619 real_jslimit_ = kIllegalLimit; |
578 jslimit_ = kIllegalLimit; | 620 jslimit_ = kIllegalLimit; |
579 real_climit_ = kIllegalLimit; | 621 real_climit_ = kIllegalLimit; |
580 climit_ = kIllegalLimit; | 622 climit_ = kIllegalLimit; |
581 nesting_ = 0; | 623 nesting_ = 0; |
582 postpone_interrupts_nesting_ = 0; | 624 postpone_interrupts_nesting_ = 0; |
583 interrupt_flags_ = 0; | 625 interrupt_flags_ = 0; |
| 626 interrupt_callback_ = 0; |
584 } | 627 } |
585 | 628 |
586 | 629 |
587 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) { | 630 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) { |
588 bool should_set_stack_limits = false; | 631 bool should_set_stack_limits = false; |
589 if (real_climit_ == kIllegalLimit) { | 632 if (real_climit_ == kIllegalLimit) { |
590 // Takes the address of the limit variable in order to find out where | 633 // Takes the address of the limit variable in order to find out where |
591 // the top of stack is right now. | 634 // the top of stack is right now. |
592 const uintptr_t kLimitSize = FLAG_stack_size * KB; | 635 const uintptr_t kLimitSize = FLAG_stack_size * KB; |
593 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize; | 636 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize; |
594 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize); | 637 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize); |
595 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); | 638 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); |
596 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); | 639 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); |
597 real_climit_ = limit; | 640 real_climit_ = limit; |
598 climit_ = limit; | 641 climit_ = limit; |
599 should_set_stack_limits = true; | 642 should_set_stack_limits = true; |
600 } | 643 } |
601 nesting_ = 0; | 644 nesting_ = 0; |
602 postpone_interrupts_nesting_ = 0; | 645 postpone_interrupts_nesting_ = 0; |
603 interrupt_flags_ = 0; | 646 interrupt_flags_ = 0; |
| 647 interrupt_callback_ = 0; |
604 return should_set_stack_limits; | 648 return should_set_stack_limits; |
605 } | 649 } |
606 | 650 |
607 | 651 |
608 void StackGuard::ClearThread(const ExecutionAccess& lock) { | 652 void StackGuard::ClearThread(const ExecutionAccess& lock) { |
609 thread_local_.Clear(); | 653 thread_local_.Clear(); |
610 isolate_->heap()->SetStackLimits(); | 654 isolate_->heap()->SetStackLimits(); |
611 } | 655 } |
612 | 656 |
613 | 657 |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
929 | 973 |
930 | 974 |
931 #endif | 975 #endif |
932 | 976 |
933 MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) { | 977 MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) { |
934 StackGuard* stack_guard = isolate->stack_guard(); | 978 StackGuard* stack_guard = isolate->stack_guard(); |
935 if (stack_guard->ShouldPostponeInterrupts()) { | 979 if (stack_guard->ShouldPostponeInterrupts()) { |
936 return isolate->heap()->undefined_value(); | 980 return isolate->heap()->undefined_value(); |
937 } | 981 } |
938 | 982 |
| 983 if (stack_guard->IsAPIInterrupt()) { |
| 984 stack_guard->InvokeInterruptCallback(); |
| 985 stack_guard->Continue(API_INTERRUPT); |
| 986 } |
| 987 |
939 if (stack_guard->IsGCRequest()) { | 988 if (stack_guard->IsGCRequest()) { |
940 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 989 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
941 "StackGuard GC request"); | 990 "StackGuard GC request"); |
942 stack_guard->Continue(GC_REQUEST); | 991 stack_guard->Continue(GC_REQUEST); |
943 } | 992 } |
944 | 993 |
945 isolate->counters()->stack_interrupts()->Increment(); | 994 isolate->counters()->stack_interrupts()->Increment(); |
946 isolate->counters()->runtime_profiler_ticks()->Increment(); | 995 isolate->counters()->runtime_profiler_ticks()->Increment(); |
947 #ifdef ENABLE_DEBUGGER_SUPPORT | 996 #ifdef ENABLE_DEBUGGER_SUPPORT |
948 if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) { | 997 if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) { |
(...skipping 17 matching lines...) Expand all Loading... |
966 ASSERT(isolate->concurrent_recompilation_enabled()); | 1015 ASSERT(isolate->concurrent_recompilation_enabled()); |
967 stack_guard->Continue(INSTALL_CODE); | 1016 stack_guard->Continue(INSTALL_CODE); |
968 isolate->optimizing_compiler_thread()->InstallOptimizedFunctions(); | 1017 isolate->optimizing_compiler_thread()->InstallOptimizedFunctions(); |
969 } | 1018 } |
970 isolate->runtime_profiler()->OptimizeNow(); | 1019 isolate->runtime_profiler()->OptimizeNow(); |
971 return isolate->heap()->undefined_value(); | 1020 return isolate->heap()->undefined_value(); |
972 } | 1021 } |
973 | 1022 |
974 | 1023 |
975 } } // namespace v8::internal | 1024 } } // namespace v8::internal |
OLD | NEW |