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 |