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); |
199 // Clear since GC will not visit the thread once it is unscheduled. | 198 // Clear since GC will not visit the thread once it is unscheduled. |
200 thread->ClearReusableHandles(); | 199 thread->ClearReusableHandles(); |
201 thread->StoreBufferRelease(); | 200 thread->StoreBufferRelease(); |
202 Isolate* isolate = thread->isolate(); | |
203 ASSERT(isolate != NULL); | |
204 if (isolate->is_runnable()) { | 201 if (isolate->is_runnable()) { |
205 thread->set_vm_tag(VMTag::kIdleTagId); | 202 thread->set_vm_tag(VMTag::kIdleTagId); |
206 } else { | 203 } else { |
207 thread->set_vm_tag(VMTag::kLoadWaitTagId); | 204 thread->set_vm_tag(VMTag::kLoadWaitTagId); |
208 } | 205 } |
209 const bool kIsMutatorThread = true; | 206 const bool kIsMutatorThread = true; |
210 const bool kDontBypassSafepoints = false; | 207 isolate->UnscheduleThread(thread, kIsMutatorThread); |
211 ThreadRegistry* tr = isolate->thread_registry(); | |
212 tr->Unschedule(thread, kIsMutatorThread, kDontBypassSafepoints); | |
213 isolate->ClearMutatorThread(); | |
214 } | 208 } |
215 | 209 |
216 | 210 |
217 bool Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) { | 211 bool Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) { |
218 const bool kIsNotMutatorThread = false; | 212 const bool kIsNotMutatorThread = false; |
219 ThreadRegistry* tr = isolate->thread_registry(); | 213 Thread* thread = isolate->ScheduleThread(kIsNotMutatorThread, |
220 Thread* thread = tr->Schedule(isolate, kIsNotMutatorThread, bypass_safepoint); | 214 bypass_safepoint); |
221 if (thread != NULL) { | 215 if (thread != NULL) { |
222 ASSERT(thread->store_buffer_block_ == NULL); | 216 ASSERT(thread->store_buffer_block_ == NULL); |
223 // TODO(koda): Use StoreBufferAcquire once we properly flush | 217 // TODO(koda): Use StoreBufferAcquire once we properly flush |
224 // before Scavenge. | 218 // before Scavenge. |
225 thread->store_buffer_block_ = | 219 thread->store_buffer_block_ = |
226 thread->isolate()->store_buffer()->PopEmptyBlock(); | 220 thread->isolate()->store_buffer()->PopEmptyBlock(); |
227 // This thread should not be the main mutator. | 221 // This thread should not be the main mutator. |
228 ASSERT(!thread->IsMutatorThread()); | 222 ASSERT(!thread->IsMutatorThread()); |
229 return true; | 223 return true; |
230 } | 224 } |
231 return false; | 225 return false; |
232 } | 226 } |
233 | 227 |
234 | 228 |
235 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { | 229 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { |
236 Thread* thread = Thread::Current(); | 230 Thread* thread = Thread::Current(); |
237 ASSERT(thread != NULL); | 231 ASSERT(thread != NULL); |
238 ASSERT(!thread->IsMutatorThread()); | 232 ASSERT(!thread->IsMutatorThread()); |
| 233 ASSERT(thread->execution_state() == Thread::kThreadInVM); |
239 thread->StoreBufferRelease(); | 234 thread->StoreBufferRelease(); |
240 Isolate* isolate = thread->isolate(); | 235 Isolate* isolate = thread->isolate(); |
241 ASSERT(isolate != NULL); | 236 ASSERT(isolate != NULL); |
242 const bool kIsNotMutatorThread = false; | 237 const bool kIsNotMutatorThread = false; |
243 ThreadRegistry* tr = isolate->thread_registry(); | 238 isolate->UnscheduleThread(thread, kIsNotMutatorThread, bypass_safepoint); |
244 tr->Unschedule(thread, kIsNotMutatorThread, bypass_safepoint); | |
245 } | 239 } |
246 | 240 |
247 | 241 |
248 void Thread::PrepareForGC() { | 242 void Thread::PrepareForGC() { |
249 ASSERT(isolate()->thread_registry()->AtSafepoint()); | 243 ASSERT(IsAtSafepoint()); |
250 // Prevent scheduling another GC by ignoring the threshold. | 244 // Prevent scheduling another GC by ignoring the threshold. |
| 245 ASSERT(store_buffer_block_ != NULL); |
251 StoreBufferRelease(StoreBuffer::kIgnoreThreshold); | 246 StoreBufferRelease(StoreBuffer::kIgnoreThreshold); |
252 // Make sure to get an *empty* block; the isolate needs all entries | 247 // Make sure to get an *empty* block; the isolate needs all entries |
253 // at GC time. | 248 // at GC time. |
254 // TODO(koda): Replace with an epilogue (PrepareAfterGC) that acquires. | 249 // TODO(koda): Replace with an epilogue (PrepareAfterGC) that acquires. |
255 store_buffer_block_ = isolate()->store_buffer()->PopEmptyBlock(); | 250 store_buffer_block_ = isolate()->store_buffer()->PopEmptyBlock(); |
256 } | 251 } |
257 | 252 |
258 | 253 |
259 void Thread::StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy) { | 254 void Thread::StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy) { |
260 StoreBufferRelease(policy); | 255 StoreBufferRelease(policy); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 | 287 |
293 bool Thread::IsMutatorThread() const { | 288 bool Thread::IsMutatorThread() const { |
294 return ((isolate_ != NULL) && (isolate_->mutator_thread() == this)); | 289 return ((isolate_ != NULL) && (isolate_->mutator_thread() == this)); |
295 } | 290 } |
296 | 291 |
297 | 292 |
298 bool Thread::CanCollectGarbage() const { | 293 bool Thread::CanCollectGarbage() const { |
299 // We have non mutator threads grow the heap instead of triggering | 294 // We have non mutator threads grow the heap instead of triggering |
300 // a garbage collection when they are at a safepoint (e.g: background | 295 // a garbage collection when they are at a safepoint (e.g: background |
301 // compiler thread finalizing and installing code at a safepoint). | 296 // compiler thread finalizing and installing code at a safepoint). |
302 // Note: This code will change once the new Safepoint logic is in place. | 297 return (IsMutatorThread() || IsAtSafepoint()); |
303 return (IsMutatorThread() || | |
304 (isolate_ != NULL && !isolate_->thread_registry()->AtSafepoint())); | |
305 } | 298 } |
306 | 299 |
307 | 300 |
308 bool Thread::IsExecutingDartCode() const { | 301 bool Thread::IsExecutingDartCode() const { |
309 return (top_exit_frame_info() == 0) && | 302 return (top_exit_frame_info() == 0) && |
310 (vm_tag() == VMTag::kDartTagId); | 303 (vm_tag() == VMTag::kDartTagId); |
311 } | 304 } |
312 | 305 |
313 | 306 |
314 bool Thread::HasExitedDartCode() const { | 307 bool Thread::HasExitedDartCode() const { |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 while (scope != NULL && | 440 while (scope != NULL && |
448 scope->stack_marker() != 0 && | 441 scope->stack_marker() != 0 && |
449 scope->stack_marker() == stack_marker) { | 442 scope->stack_marker() == stack_marker) { |
450 api_top_scope_ = scope->previous(); | 443 api_top_scope_ = scope->previous(); |
451 delete scope; | 444 delete scope; |
452 scope = api_top_scope_; | 445 scope = api_top_scope_; |
453 } | 446 } |
454 } | 447 } |
455 | 448 |
456 | 449 |
| 450 void Thread::EnterSafepointUsingLock() { |
| 451 isolate()->safepoint_handler()->EnterSafepointUsingLock(this); |
| 452 } |
| 453 |
| 454 |
| 455 void Thread::ExitSafepointUsingLock() { |
| 456 isolate()->safepoint_handler()->ExitSafepointUsingLock(this); |
| 457 } |
| 458 |
| 459 |
| 460 void Thread::BlockForSafepoint() { |
| 461 isolate()->safepoint_handler()->BlockForSafepoint(this); |
| 462 } |
| 463 |
| 464 |
457 DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread) | 465 DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread) |
458 : StackResource(thread) { | 466 : StackResource(thread) { |
459 if (thread != NULL) { | 467 if (thread != NULL) { |
460 OSThread* os_thread = thread->os_thread(); | 468 OSThread* os_thread = thread->os_thread(); |
461 ASSERT(os_thread != NULL); | 469 ASSERT(os_thread != NULL); |
462 os_thread->DisableThreadInterrupts(); | 470 os_thread->DisableThreadInterrupts(); |
463 } | 471 } |
464 } | 472 } |
465 | 473 |
466 | 474 |
467 DisableThreadInterruptsScope::~DisableThreadInterruptsScope() { | 475 DisableThreadInterruptsScope::~DisableThreadInterruptsScope() { |
468 if (thread() != NULL) { | 476 if (thread() != NULL) { |
469 OSThread* os_thread = thread()->os_thread(); | 477 OSThread* os_thread = thread()->os_thread(); |
470 ASSERT(os_thread != NULL); | 478 ASSERT(os_thread != NULL); |
471 os_thread->EnableThreadInterrupts(); | 479 os_thread->EnableThreadInterrupts(); |
472 } | 480 } |
473 } | 481 } |
474 | 482 |
475 } // namespace dart | 483 } // namespace dart |
OLD | NEW |