| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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/thread.h" | 5 #include "vm/thread.h" |
| 6 | 6 |
| 7 #include "vm/dart_api_state.h" | 7 #include "vm/dart_api_state.h" |
| 8 #include "vm/growable_array.h" | 8 #include "vm/growable_array.h" |
| 9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 10 #include "vm/lockers.h" | 10 #include "vm/lockers.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 #define REUSABLE_HANDLE_SCOPE_INIT(object) | 34 #define REUSABLE_HANDLE_SCOPE_INIT(object) |
| 35 #endif // defined(DEBUG) | 35 #endif // defined(DEBUG) |
| 36 | 36 |
| 37 #define REUSABLE_HANDLE_INITIALIZERS(object) \ | 37 #define REUSABLE_HANDLE_INITIALIZERS(object) \ |
| 38 object##_handle_(NULL), | 38 object##_handle_(NULL), |
| 39 | 39 |
| 40 | 40 |
| 41 Thread::Thread(Isolate* isolate) | 41 Thread::Thread(Isolate* isolate) |
| 42 : BaseThread(false), | 42 : BaseThread(false), |
| 43 os_thread_(NULL), | 43 os_thread_(NULL), |
| 44 thread_lock_(new Monitor()), |
| 44 isolate_(NULL), | 45 isolate_(NULL), |
| 45 heap_(NULL), | 46 heap_(NULL), |
| 46 zone_(NULL), | 47 zone_(NULL), |
| 47 api_reusable_scope_(NULL), | 48 api_reusable_scope_(NULL), |
| 48 api_top_scope_(NULL), | 49 api_top_scope_(NULL), |
| 49 top_exit_frame_info_(0), | 50 top_exit_frame_info_(0), |
| 50 top_resource_(NULL), | 51 top_resource_(NULL), |
| 51 long_jump_base_(NULL), | 52 long_jump_base_(NULL), |
| 52 store_buffer_block_(NULL), | 53 store_buffer_block_(NULL), |
| 53 no_callback_scope_depth_(0), | 54 no_callback_scope_depth_(0), |
| 54 #if defined(DEBUG) | 55 #if defined(DEBUG) |
| 55 top_handle_scope_(NULL), | 56 top_handle_scope_(NULL), |
| 56 no_handle_scope_depth_(0), | 57 no_handle_scope_depth_(0), |
| 57 no_safepoint_scope_depth_(0), | 58 no_safepoint_scope_depth_(0), |
| 58 #endif | 59 #endif |
| 59 reusable_handles_(), | 60 reusable_handles_(), |
| 60 cha_(NULL), | 61 cha_(NULL), |
| 61 deopt_id_(0), | 62 deopt_id_(0), |
| 62 vm_tag_(0), | 63 vm_tag_(0), |
| 63 pending_functions_(GrowableObjectArray::null()), | 64 pending_functions_(GrowableObjectArray::null()), |
| 64 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) | 65 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) |
| 65 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) | 66 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) |
| 67 safepoint_state_(0), |
| 68 execution_state_(kThreadInVM), |
| 66 next_(NULL) { | 69 next_(NULL) { |
| 67 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ | 70 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ |
| 68 member_name = default_init_value; | 71 member_name = default_init_value; |
| 69 CACHED_CONSTANTS_LIST(DEFAULT_INIT) | 72 CACHED_CONSTANTS_LIST(DEFAULT_INIT) |
| 70 #undef DEFAULT_INIT | 73 #undef DEFAULT_INIT |
| 71 | 74 |
| 72 #define DEFAULT_INIT(name) \ | 75 #define DEFAULT_INIT(name) \ |
| 73 name##_entry_point_ = 0; | 76 name##_entry_point_ = 0; |
| 74 RUNTIME_ENTRY_LIST(DEFAULT_INIT) | 77 RUNTIME_ENTRY_LIST(DEFAULT_INIT) |
| 75 #undef DEFAULT_INIT | 78 #undef DEFAULT_INIT |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 RawGrowableObjectArray* Thread::pending_functions() { | 170 RawGrowableObjectArray* Thread::pending_functions() { |
| 168 if (pending_functions_ == GrowableObjectArray::null()) { | 171 if (pending_functions_ == GrowableObjectArray::null()) { |
| 169 pending_functions_ = GrowableObjectArray::New(Heap::kOld); | 172 pending_functions_ = GrowableObjectArray::New(Heap::kOld); |
| 170 } | 173 } |
| 171 return pending_functions_; | 174 return pending_functions_; |
| 172 } | 175 } |
| 173 | 176 |
| 174 | 177 |
| 175 bool Thread::EnterIsolate(Isolate* isolate) { | 178 bool Thread::EnterIsolate(Isolate* isolate) { |
| 176 const bool kIsMutatorThread = true; | 179 const bool kIsMutatorThread = true; |
| 177 const bool kDontBypassSafepoints = false; | 180 Thread* thread = isolate->ScheduleThread(kIsMutatorThread); |
| 178 ThreadRegistry* tr = isolate->thread_registry(); | |
| 179 Thread* thread = tr->Schedule( | |
| 180 isolate, kIsMutatorThread, kDontBypassSafepoints); | |
| 181 if (thread != NULL) { | 181 if (thread != NULL) { |
| 182 isolate->MakeCurrentThreadMutator(thread); | |
| 183 thread->set_vm_tag(VMTag::kVMTagId); | |
| 184 ASSERT(thread->store_buffer_block_ == NULL); | 182 ASSERT(thread->store_buffer_block_ == NULL); |
| 185 thread->StoreBufferAcquire(); | 183 thread->StoreBufferAcquire(); |
| 186 return true; | 184 return true; |
| 187 } | 185 } |
| 188 return false; | 186 return false; |
| 189 } | 187 } |
| 190 | 188 |
| 191 | 189 |
| 192 void Thread::ExitIsolate() { | 190 void Thread::ExitIsolate() { |
| 193 Thread* thread = Thread::Current(); | 191 Thread* thread = Thread::Current(); |
| 194 ASSERT(thread != NULL); | 192 ASSERT(thread != NULL && thread->IsMutatorThread()); |
| 195 ASSERT(thread->IsMutatorThread()); | 193 DEBUG_ASSERT(!thread->IsAnyReusableHandleScopeActive()); |
| 196 #if defined(DEBUG) | 194 |
| 197 ASSERT(!thread->IsAnyReusableHandleScopeActive()); | 195 Isolate* isolate = thread->isolate(); |
| 198 #endif // DEBUG | 196 ASSERT(isolate != NULL); |
| 197 ASSERT((thread->execution_state() == Thread::kThreadInVM) || |
| 198 (thread->execution_state() == Thread::kThreadInNative)); |
| 199 // Clear since GC will not visit the thread once it is unscheduled. | 199 // Clear since GC will not visit the thread once it is unscheduled. |
| 200 thread->ClearReusableHandles(); | 200 thread->ClearReusableHandles(); |
| 201 thread->StoreBufferRelease(); | 201 thread->StoreBufferRelease(); |
| 202 Isolate* isolate = thread->isolate(); | |
| 203 ASSERT(isolate != NULL); | |
| 204 if (isolate->is_runnable()) { | 202 if (isolate->is_runnable()) { |
| 205 thread->set_vm_tag(VMTag::kIdleTagId); | 203 thread->set_vm_tag(VMTag::kIdleTagId); |
| 206 } else { | 204 } else { |
| 207 thread->set_vm_tag(VMTag::kLoadWaitTagId); | 205 thread->set_vm_tag(VMTag::kLoadWaitTagId); |
| 208 } | 206 } |
| 209 const bool kIsMutatorThread = true; | 207 const bool kIsMutatorThread = true; |
| 210 const bool kDontBypassSafepoints = false; | 208 isolate->UnscheduleThread(thread, kIsMutatorThread); |
| 211 ThreadRegistry* tr = isolate->thread_registry(); | |
| 212 tr->Unschedule(thread, kIsMutatorThread, kDontBypassSafepoints); | |
| 213 isolate->ClearMutatorThread(); | |
| 214 } | 209 } |
| 215 | 210 |
| 216 | 211 |
| 217 bool Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) { | 212 bool Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) { |
| 218 const bool kIsNotMutatorThread = false; | 213 const bool kIsNotMutatorThread = false; |
| 219 ThreadRegistry* tr = isolate->thread_registry(); | 214 Thread* thread = isolate->ScheduleThread(kIsNotMutatorThread, |
| 220 Thread* thread = tr->Schedule(isolate, kIsNotMutatorThread, bypass_safepoint); | 215 bypass_safepoint); |
| 221 if (thread != NULL) { | 216 if (thread != NULL) { |
| 222 ASSERT(thread->store_buffer_block_ == NULL); | 217 ASSERT(thread->store_buffer_block_ == NULL); |
| 223 // TODO(koda): Use StoreBufferAcquire once we properly flush | 218 // TODO(koda): Use StoreBufferAcquire once we properly flush |
| 224 // before Scavenge. | 219 // before Scavenge. |
| 225 thread->store_buffer_block_ = | 220 thread->store_buffer_block_ = |
| 226 thread->isolate()->store_buffer()->PopEmptyBlock(); | 221 thread->isolate()->store_buffer()->PopEmptyBlock(); |
| 227 // This thread should not be the main mutator. | 222 // This thread should not be the main mutator. |
| 228 ASSERT(!thread->IsMutatorThread()); | 223 ASSERT(!thread->IsMutatorThread()); |
| 229 return true; | 224 return true; |
| 230 } | 225 } |
| 231 return false; | 226 return false; |
| 232 } | 227 } |
| 233 | 228 |
| 234 | 229 |
| 235 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { | 230 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { |
| 236 Thread* thread = Thread::Current(); | 231 Thread* thread = Thread::Current(); |
| 237 ASSERT(thread != NULL); | 232 ASSERT(thread != NULL); |
| 238 ASSERT(!thread->IsMutatorThread()); | 233 ASSERT(!thread->IsMutatorThread()); |
| 234 ASSERT(thread->execution_state() == Thread::kThreadInVM); |
| 239 thread->StoreBufferRelease(); | 235 thread->StoreBufferRelease(); |
| 240 Isolate* isolate = thread->isolate(); | 236 Isolate* isolate = thread->isolate(); |
| 241 ASSERT(isolate != NULL); | 237 ASSERT(isolate != NULL); |
| 242 const bool kIsNotMutatorThread = false; | 238 const bool kIsNotMutatorThread = false; |
| 243 ThreadRegistry* tr = isolate->thread_registry(); | 239 isolate->UnscheduleThread(thread, kIsNotMutatorThread, bypass_safepoint); |
| 244 tr->Unschedule(thread, kIsNotMutatorThread, bypass_safepoint); | |
| 245 } | 240 } |
| 246 | 241 |
| 247 | 242 |
| 248 void Thread::PrepareForGC() { | 243 void Thread::PrepareForGC() { |
| 249 ASSERT(isolate()->thread_registry()->AtSafepoint()); | 244 ASSERT(IsAtSafepoint()); |
| 250 // Prevent scheduling another GC by ignoring the threshold. | 245 // Prevent scheduling another GC by ignoring the threshold. |
| 246 ASSERT(store_buffer_block_ != NULL); |
| 251 StoreBufferRelease(StoreBuffer::kIgnoreThreshold); | 247 StoreBufferRelease(StoreBuffer::kIgnoreThreshold); |
| 252 // Make sure to get an *empty* block; the isolate needs all entries | 248 // Make sure to get an *empty* block; the isolate needs all entries |
| 253 // at GC time. | 249 // at GC time. |
| 254 // TODO(koda): Replace with an epilogue (PrepareAfterGC) that acquires. | 250 // TODO(koda): Replace with an epilogue (PrepareAfterGC) that acquires. |
| 255 store_buffer_block_ = isolate()->store_buffer()->PopEmptyBlock(); | 251 store_buffer_block_ = isolate()->store_buffer()->PopEmptyBlock(); |
| 256 } | 252 } |
| 257 | 253 |
| 258 | 254 |
| 259 void Thread::StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy) { | 255 void Thread::StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy) { |
| 260 StoreBufferRelease(policy); | 256 StoreBufferRelease(policy); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 while (scope != NULL && | 433 while (scope != NULL && |
| 438 scope->stack_marker() != 0 && | 434 scope->stack_marker() != 0 && |
| 439 scope->stack_marker() == stack_marker) { | 435 scope->stack_marker() == stack_marker) { |
| 440 api_top_scope_ = scope->previous(); | 436 api_top_scope_ = scope->previous(); |
| 441 delete scope; | 437 delete scope; |
| 442 scope = api_top_scope_; | 438 scope = api_top_scope_; |
| 443 } | 439 } |
| 444 } | 440 } |
| 445 | 441 |
| 446 | 442 |
| 443 void Thread::EnterSafepointUsingLock() { |
| 444 isolate()->safepoint_handler()->EnterSafepointUsingLock(this); |
| 445 } |
| 446 |
| 447 |
| 448 void Thread::ExitSafepointUsingLock() { |
| 449 isolate()->safepoint_handler()->ExitSafepointUsingLock(this); |
| 450 } |
| 451 |
| 452 |
| 447 DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread) | 453 DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread) |
| 448 : StackResource(thread) { | 454 : StackResource(thread) { |
| 449 if (thread != NULL) { | 455 if (thread != NULL) { |
| 450 OSThread* os_thread = thread->os_thread(); | 456 OSThread* os_thread = thread->os_thread(); |
| 451 ASSERT(os_thread != NULL); | 457 ASSERT(os_thread != NULL); |
| 452 os_thread->DisableThreadInterrupts(); | 458 os_thread->DisableThreadInterrupts(); |
| 453 } | 459 } |
| 454 } | 460 } |
| 455 | 461 |
| 456 | 462 |
| 457 DisableThreadInterruptsScope::~DisableThreadInterruptsScope() { | 463 DisableThreadInterruptsScope::~DisableThreadInterruptsScope() { |
| 458 if (thread() != NULL) { | 464 if (thread() != NULL) { |
| 459 OSThread* os_thread = thread()->os_thread(); | 465 OSThread* os_thread = thread()->os_thread(); |
| 460 ASSERT(os_thread != NULL); | 466 ASSERT(os_thread != NULL); |
| 461 os_thread->EnableThreadInterrupts(); | 467 os_thread->EnableThreadInterrupts(); |
| 462 } | 468 } |
| 463 } | 469 } |
| 464 | 470 |
| 465 } // namespace dart | 471 } // namespace dart |
| OLD | NEW |