OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/isolate.h" | 5 #include "vm/isolate.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "include/dart_native_api.h" | 8 #include "include/dart_native_api.h" |
9 #include "platform/assert.h" | 9 #include "platform/assert.h" |
10 #include "platform/text_buffer.h" | 10 #include "platform/text_buffer.h" |
(...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 pending_service_extension_calls_(GrowableObjectArray::null()), | 815 pending_service_extension_calls_(GrowableObjectArray::null()), |
816 registered_service_extension_handlers_(GrowableObjectArray::null()), | 816 registered_service_extension_handlers_(GrowableObjectArray::null()), |
817 metrics_list_head_(NULL), | 817 metrics_list_head_(NULL), |
818 compilation_allowed_(true), | 818 compilation_allowed_(true), |
819 all_classes_finalized_(false), | 819 all_classes_finalized_(false), |
820 next_(NULL), | 820 next_(NULL), |
821 pause_loop_monitor_(NULL), | 821 pause_loop_monitor_(NULL), |
822 cha_invalidation_gen_(kInvalidGen), | 822 cha_invalidation_gen_(kInvalidGen), |
823 field_invalidation_gen_(kInvalidGen), | 823 field_invalidation_gen_(kInvalidGen), |
824 prefix_invalidation_gen_(kInvalidGen), | 824 prefix_invalidation_gen_(kInvalidGen), |
825 boxed_field_list_monitor_(new Monitor()), | 825 boxed_field_list_mutex_(new Mutex()), |
826 boxed_field_list_(GrowableObjectArray::null()), | 826 boxed_field_list_(GrowableObjectArray::null()), |
827 spawn_count_monitor_(new Monitor()), | 827 spawn_count_monitor_(new Monitor()), |
828 spawn_count_(0) { | 828 spawn_count_(0) { |
829 NOT_IN_PRODUCT(FlagsCopyFrom(api_flags)); | 829 NOT_IN_PRODUCT(FlagsCopyFrom(api_flags)); |
830 // TODO(asiva): A Thread is not available here, need to figure out | 830 // TODO(asiva): A Thread is not available here, need to figure out |
831 // how the vm_tag (kEmbedderTagId) can be set, these tags need to | 831 // how the vm_tag (kEmbedderTagId) can be set, these tags need to |
832 // move to the OSThread structure. | 832 // move to the OSThread structure. |
833 set_user_tag(UserTags::kDefaultUserTag); | 833 set_user_tag(UserTags::kDefaultUserTag); |
834 } | 834 } |
835 | 835 |
(...skipping 20 matching lines...) Expand all Loading... |
856 delete message_handler_; | 856 delete message_handler_; |
857 message_handler_ = NULL; // Fail fast if we send messages to a dead isolate. | 857 message_handler_ = NULL; // Fail fast if we send messages to a dead isolate. |
858 ASSERT(deopt_context_ == NULL); // No deopt in progress when isolate deleted. | 858 ASSERT(deopt_context_ == NULL); // No deopt in progress when isolate deleted. |
859 delete spawn_state_; | 859 delete spawn_state_; |
860 if (FLAG_support_service) { | 860 if (FLAG_support_service) { |
861 delete object_id_ring_; | 861 delete object_id_ring_; |
862 } | 862 } |
863 object_id_ring_ = NULL; | 863 object_id_ring_ = NULL; |
864 delete pause_loop_monitor_; | 864 delete pause_loop_monitor_; |
865 pause_loop_monitor_ = NULL; | 865 pause_loop_monitor_ = NULL; |
866 delete boxed_field_list_monitor_; | 866 delete boxed_field_list_mutex_; |
867 boxed_field_list_monitor_ = NULL; | 867 boxed_field_list_mutex_ = NULL; |
868 ASSERT(spawn_count_ == 0); | 868 ASSERT(spawn_count_ == 0); |
869 delete spawn_count_monitor_; | 869 delete spawn_count_monitor_; |
870 if (compiler_stats_ != NULL) { | 870 if (compiler_stats_ != NULL) { |
871 delete compiler_stats_; | 871 delete compiler_stats_; |
872 compiler_stats_ = NULL; | 872 compiler_stats_ = NULL; |
873 } | 873 } |
874 delete safepoint_handler_; | 874 delete safepoint_handler_; |
875 delete thread_registry_; | 875 delete thread_registry_; |
876 } | 876 } |
877 | 877 |
(...skipping 984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1862 visitor->VisitPointer( | 1862 visitor->VisitPointer( |
1863 reinterpret_cast<RawObject**>(&pending_service_extension_calls_)); | 1863 reinterpret_cast<RawObject**>(&pending_service_extension_calls_)); |
1864 | 1864 |
1865 // Visit the registered service extension handlers. | 1865 // Visit the registered service extension handlers. |
1866 visitor->VisitPointer( | 1866 visitor->VisitPointer( |
1867 reinterpret_cast<RawObject**>(®istered_service_extension_handlers_)); | 1867 reinterpret_cast<RawObject**>(®istered_service_extension_handlers_)); |
1868 | 1868 |
1869 // Visit the boxed_field_list. | 1869 // Visit the boxed_field_list. |
1870 // 'boxed_field_list_' access via mutator and background compilation threads | 1870 // 'boxed_field_list_' access via mutator and background compilation threads |
1871 // is guarded with a monitor. This means that we can visit it only | 1871 // is guarded with a monitor. This means that we can visit it only |
1872 // when at safepoint or the boxed_field_list_monitor_ lock has been taken. | 1872 // when at safepoint or the boxed_field_list_mutex_ lock has been taken. |
1873 visitor->VisitPointer(reinterpret_cast<RawObject**>(&boxed_field_list_)); | 1873 visitor->VisitPointer(reinterpret_cast<RawObject**>(&boxed_field_list_)); |
1874 | 1874 |
1875 // Visit objects in the debugger. | 1875 // Visit objects in the debugger. |
1876 if (FLAG_support_debugger) { | 1876 if (FLAG_support_debugger) { |
1877 debugger()->VisitObjectPointers(visitor); | 1877 debugger()->VisitObjectPointers(visitor); |
1878 } | 1878 } |
1879 | 1879 |
1880 // Visit objects that are being used for deoptimization. | 1880 // Visit objects that are being used for deoptimization. |
1881 if (deopt_context() != NULL) { | 1881 if (deopt_context() != NULL) { |
1882 deopt_context()->VisitObjectPointers(visitor); | 1882 deopt_context()->VisitObjectPointers(visitor); |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2076 | 2076 |
2077 | 2077 |
2078 void Isolate::set_registered_service_extension_handlers( | 2078 void Isolate::set_registered_service_extension_handlers( |
2079 const GrowableObjectArray& value) { | 2079 const GrowableObjectArray& value) { |
2080 registered_service_extension_handlers_ = value.raw(); | 2080 registered_service_extension_handlers_ = value.raw(); |
2081 } | 2081 } |
2082 | 2082 |
2083 | 2083 |
2084 void Isolate::AddDeoptimizingBoxedField(const Field& field) { | 2084 void Isolate::AddDeoptimizingBoxedField(const Field& field) { |
2085 ASSERT(field.IsOriginal()); | 2085 ASSERT(field.IsOriginal()); |
2086 MonitorLocker ml(boxed_field_list_monitor_); | 2086 // The enclosed code allocates objects and can potentially trigger a GC, |
| 2087 // ensure that we account for safepoints when grabbing the lock. |
| 2088 SafepointMutexLocker ml(boxed_field_list_mutex_); |
2087 if (boxed_field_list_ == GrowableObjectArray::null()) { | 2089 if (boxed_field_list_ == GrowableObjectArray::null()) { |
2088 boxed_field_list_ = GrowableObjectArray::New(Heap::kOld); | 2090 boxed_field_list_ = GrowableObjectArray::New(Heap::kOld); |
2089 } | 2091 } |
2090 const GrowableObjectArray& array = | 2092 const GrowableObjectArray& array = |
2091 GrowableObjectArray::Handle(boxed_field_list_); | 2093 GrowableObjectArray::Handle(boxed_field_list_); |
2092 array.Add(field, Heap::kOld); | 2094 array.Add(field, Heap::kOld); |
2093 } | 2095 } |
2094 | 2096 |
2095 | 2097 |
2096 RawField* Isolate::GetDeoptimizingBoxedField() { | 2098 RawField* Isolate::GetDeoptimizingBoxedField() { |
2097 MonitorLocker ml(boxed_field_list_monitor_); | 2099 MutexLocker ml(boxed_field_list_mutex_); |
2098 if (boxed_field_list_ == GrowableObjectArray::null()) { | 2100 if (boxed_field_list_ == GrowableObjectArray::null()) { |
2099 return Field::null(); | 2101 return Field::null(); |
2100 } | 2102 } |
2101 const GrowableObjectArray& array = | 2103 const GrowableObjectArray& array = |
2102 GrowableObjectArray::Handle(boxed_field_list_); | 2104 GrowableObjectArray::Handle(boxed_field_list_); |
2103 if (array.Length() == 0) { | 2105 if (array.Length() == 0) { |
2104 return Field::null(); | 2106 return Field::null(); |
2105 } | 2107 } |
2106 return Field::RawCast(array.RemoveLast()); | 2108 return Field::RawCast(array.RemoveLast()); |
2107 } | 2109 } |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2310 | 2312 |
2311 Dart_MessageNotifyCallback saved_notify_callback = | 2313 Dart_MessageNotifyCallback saved_notify_callback = |
2312 message_notify_callback(); | 2314 message_notify_callback(); |
2313 set_message_notify_callback(Isolate::WakePauseEventHandler); | 2315 set_message_notify_callback(Isolate::WakePauseEventHandler); |
2314 | 2316 |
2315 bool resume = false; | 2317 bool resume = false; |
2316 while (true) { | 2318 while (true) { |
2317 // Handle all available vm service messages, up to a resume | 2319 // Handle all available vm service messages, up to a resume |
2318 // request. | 2320 // request. |
2319 while (!resume && Dart_HasServiceMessages()) { | 2321 while (!resume && Dart_HasServiceMessages()) { |
2320 pause_loop_monitor_->Exit(); | 2322 ml.Exit(); |
2321 resume = Dart_HandleServiceMessages(); | 2323 resume = Dart_HandleServiceMessages(); |
2322 pause_loop_monitor_->Enter(); | 2324 ml.Enter(); |
2323 } | 2325 } |
2324 if (resume) { | 2326 if (resume) { |
2325 break; | 2327 break; |
2326 } | 2328 } |
2327 | 2329 |
2328 // Wait for more service messages. | 2330 // Wait for more service messages. |
2329 Monitor::WaitResult res = ml.Wait(); | 2331 Monitor::WaitResult res = ml.Wait(); |
2330 ASSERT(res == Monitor::kNotified); | 2332 ASSERT(res == Monitor::kNotified); |
2331 } | 2333 } |
2332 set_message_notify_callback(saved_notify_callback); | 2334 set_message_notify_callback(saved_notify_callback); |
2333 Dart_ExitScope(); | 2335 Dart_ExitScope(); |
2334 } | 2336 } |
2335 | 2337 |
2336 | 2338 |
2337 void Isolate::VisitIsolates(IsolateVisitor* visitor) { | 2339 void Isolate::VisitIsolates(IsolateVisitor* visitor) { |
2338 if (visitor == NULL) { | 2340 if (visitor == NULL) { |
2339 return; | 2341 return; |
2340 } | 2342 } |
2341 MonitorLocker ml(isolates_list_monitor_); | 2343 // The visitor could potentially run code that could safepoint so use |
| 2344 // SafepointMonitorLocker to ensure the lock has safepoint checks. |
| 2345 SafepointMonitorLocker ml(isolates_list_monitor_); |
2342 Isolate* current = isolates_list_head_; | 2346 Isolate* current = isolates_list_head_; |
2343 while (current) { | 2347 while (current) { |
2344 visitor->VisitIsolate(current); | 2348 visitor->VisitIsolate(current); |
2345 current = current->next_; | 2349 current = current->next_; |
2346 } | 2350 } |
2347 } | 2351 } |
2348 | 2352 |
2349 | 2353 |
2350 intptr_t Isolate::IsolateListLength() { | 2354 intptr_t Isolate::IsolateListLength() { |
2351 MonitorLocker ml(isolates_list_monitor_); | 2355 MonitorLocker ml(isolates_list_monitor_); |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2521 } | 2525 } |
2522 | 2526 |
2523 | 2527 |
2524 Thread* Isolate::ScheduleThread(bool is_mutator, bool bypass_safepoint) { | 2528 Thread* Isolate::ScheduleThread(bool is_mutator, bool bypass_safepoint) { |
2525 // Schedule the thread into the isolate by associating | 2529 // Schedule the thread into the isolate by associating |
2526 // a 'Thread' structure with it (this is done while we are holding | 2530 // a 'Thread' structure with it (this is done while we are holding |
2527 // the thread registry lock). | 2531 // the thread registry lock). |
2528 Thread* thread = NULL; | 2532 Thread* thread = NULL; |
2529 OSThread* os_thread = OSThread::Current(); | 2533 OSThread* os_thread = OSThread::Current(); |
2530 if (os_thread != NULL) { | 2534 if (os_thread != NULL) { |
2531 MonitorLocker ml(threads_lock()); | 2535 // We are about to associate the thread with an isolate and it would |
| 2536 // not be possible to correctly track no_safepoint_scope_depth for the |
| 2537 // thread in the constructor/destructor of MonitorLocker, |
| 2538 // so we create a MonitorLocker object which does not do any |
| 2539 // no_safepoint_scope_depth increments/decrements. |
| 2540 MonitorLocker ml(threads_lock(), false); |
2532 | 2541 |
2533 // If a safepoint operation is in progress wait for it | 2542 // If a safepoint operation is in progress wait for it |
2534 // to finish before scheduling this thread in. | 2543 // to finish before scheduling this thread in. |
2535 while (!bypass_safepoint && safepoint_handler()->safepoint_in_progress()) { | 2544 while (!bypass_safepoint && safepoint_handler()->safepoint_in_progress()) { |
2536 ml.Wait(); | 2545 ml.Wait(); |
2537 } | 2546 } |
2538 | 2547 |
2539 // Now get a free Thread structure. | 2548 // Now get a free Thread structure. |
2540 thread = thread_registry()->GetFreeThreadLocked(this, is_mutator); | 2549 thread = thread_registry()->GetFreeThreadLocked(this, is_mutator); |
2541 ASSERT(thread != NULL); | 2550 ASSERT(thread != NULL); |
2542 | 2551 |
2543 // Set up other values and set the TLS value. | 2552 // Set up other values and set the TLS value. |
2544 thread->isolate_ = this; | 2553 thread->isolate_ = this; |
2545 ASSERT(heap() != NULL); | 2554 ASSERT(heap() != NULL); |
2546 thread->heap_ = heap(); | 2555 thread->heap_ = heap(); |
2547 thread->set_os_thread(os_thread); | 2556 thread->set_os_thread(os_thread); |
2548 ASSERT(thread->execution_state() == Thread::kThreadInVM); | 2557 ASSERT(thread->execution_state() == Thread::kThreadInVM); |
2549 thread->set_safepoint_state(0); | 2558 thread->set_safepoint_state(0); |
2550 thread->set_vm_tag(VMTag::kVMTagId); | 2559 thread->set_vm_tag(VMTag::kVMTagId); |
| 2560 ASSERT(thread->no_safepoint_scope_depth() == 0); |
2551 os_thread->set_thread(thread); | 2561 os_thread->set_thread(thread); |
2552 if (is_mutator) { | 2562 if (is_mutator) { |
2553 mutator_thread_ = thread; | 2563 mutator_thread_ = thread; |
2554 } | 2564 } |
2555 Thread::SetCurrent(thread); | 2565 Thread::SetCurrent(thread); |
2556 os_thread->EnableThreadInterrupts(); | 2566 os_thread->EnableThreadInterrupts(); |
2557 } | 2567 } |
2558 return thread; | 2568 return thread; |
2559 } | 2569 } |
2560 | 2570 |
2561 | 2571 |
2562 void Isolate::UnscheduleThread(Thread* thread, | 2572 void Isolate::UnscheduleThread(Thread* thread, |
2563 bool is_mutator, | 2573 bool is_mutator, |
2564 bool bypass_safepoint) { | 2574 bool bypass_safepoint) { |
2565 // Disassociate the 'Thread' structure and unschedule the thread | 2575 // Disassociate the 'Thread' structure and unschedule the thread |
2566 // from this isolate. | 2576 // from this isolate. |
2567 MonitorLocker ml(threads_lock()); | 2577 // We are disassociating the thread from an isolate and it would |
| 2578 // not be possible to correctly track no_safepoint_scope_depth for the |
| 2579 // thread in the constructor/destructor of MonitorLocker, |
| 2580 // so we create a MonitorLocker object which does not do any |
| 2581 // no_safepoint_scope_depth increments/decrements. |
| 2582 MonitorLocker ml(threads_lock(), false); |
2568 if (!bypass_safepoint) { | 2583 if (!bypass_safepoint) { |
2569 // Ensure that the thread reports itself as being at a safepoint. | 2584 // Ensure that the thread reports itself as being at a safepoint. |
2570 thread->EnterSafepoint(); | 2585 thread->EnterSafepoint(); |
2571 } | 2586 } |
2572 OSThread* os_thread = thread->os_thread(); | 2587 OSThread* os_thread = thread->os_thread(); |
2573 ASSERT(os_thread != NULL); | 2588 ASSERT(os_thread != NULL); |
2574 os_thread->DisableThreadInterrupts(); | 2589 os_thread->DisableThreadInterrupts(); |
2575 os_thread->set_thread(NULL); | 2590 os_thread->set_thread(NULL); |
2576 OSThread::SetCurrent(os_thread); | 2591 OSThread::SetCurrent(os_thread); |
2577 if (is_mutator) { | 2592 if (is_mutator) { |
2578 mutator_thread_ = NULL; | 2593 mutator_thread_ = NULL; |
2579 } | 2594 } |
2580 thread->isolate_ = NULL; | 2595 thread->isolate_ = NULL; |
2581 thread->heap_ = NULL; | 2596 thread->heap_ = NULL; |
2582 thread->set_os_thread(NULL); | 2597 thread->set_os_thread(NULL); |
2583 thread->set_execution_state(Thread::kThreadInVM); | 2598 thread->set_execution_state(Thread::kThreadInVM); |
2584 thread->set_safepoint_state(0); | 2599 thread->set_safepoint_state(0); |
| 2600 ASSERT(thread->no_safepoint_scope_depth() == 0); |
2585 // Return thread structure. | 2601 // Return thread structure. |
2586 thread_registry()->ReturnThreadLocked(is_mutator, thread); | 2602 thread_registry()->ReturnThreadLocked(is_mutator, thread); |
2587 } | 2603 } |
2588 | 2604 |
2589 | 2605 |
2590 static RawInstance* DeserializeObject(Thread* thread, | 2606 static RawInstance* DeserializeObject(Thread* thread, |
2591 uint8_t* obj_data, | 2607 uint8_t* obj_data, |
2592 intptr_t obj_len) { | 2608 intptr_t obj_len) { |
2593 if (obj_data == NULL) { | 2609 if (obj_data == NULL) { |
2594 return Instance::null(); | 2610 return Instance::null(); |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2810 void IsolateSpawnState::DecrementSpawnCount() { | 2826 void IsolateSpawnState::DecrementSpawnCount() { |
2811 ASSERT(spawn_count_monitor_ != NULL); | 2827 ASSERT(spawn_count_monitor_ != NULL); |
2812 ASSERT(spawn_count_ != NULL); | 2828 ASSERT(spawn_count_ != NULL); |
2813 MonitorLocker ml(spawn_count_monitor_); | 2829 MonitorLocker ml(spawn_count_monitor_); |
2814 ASSERT(*spawn_count_ > 0); | 2830 ASSERT(*spawn_count_ > 0); |
2815 *spawn_count_ = *spawn_count_ - 1; | 2831 *spawn_count_ = *spawn_count_ - 1; |
2816 ml.Notify(); | 2832 ml.Notify(); |
2817 } | 2833 } |
2818 | 2834 |
2819 } // namespace dart | 2835 } // namespace dart |
OLD | NEW |