| 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/growable_array.h" | 7 #include "vm/growable_array.h" |
| 8 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
| 9 #include "vm/lockers.h" | 9 #include "vm/lockers.h" |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| 11 #include "vm/os_thread.h" | 11 #include "vm/os_thread.h" |
| 12 #include "vm/profiler.h" | 12 #include "vm/profiler.h" |
| 13 #include "vm/stub_code.h" | 13 #include "vm/stub_code.h" |
| 14 #include "vm/thread_interrupter.h" | 14 #include "vm/thread_interrupter.h" |
| 15 #include "vm/thread_registry.h" | 15 #include "vm/thread_registry.h" |
| 16 | 16 |
| 17 namespace dart { | 17 namespace dart { |
| 18 | 18 |
| 19 // The single thread local key which stores all the thread local data | 19 // The single thread local key which stores all the thread local data |
| 20 // for a thread. | 20 // for a thread. |
| 21 ThreadLocalKey Thread::thread_key_ = OSThread::kUnsetThreadLocalKey; | 21 ThreadLocalKey Thread::thread_key_ = OSThread::kUnsetThreadLocalKey; |
| 22 | 22 |
| 23 | 23 |
| 24 static void DeleteThread(void* thread) { | 24 static void DeleteThread(void* thread) { |
| 25 delete reinterpret_cast<Thread*>(thread); | 25 delete reinterpret_cast<Thread*>(thread); |
| 26 } | 26 } |
| 27 | 27 |
| 28 | 28 |
| 29 Thread::~Thread() { | 29 Thread::~Thread() { |
| 30 delete thread_state_; |
| 30 // We should cleanly exit any isolate before destruction. | 31 // We should cleanly exit any isolate before destruction. |
| 31 ASSERT(isolate_ == NULL); | 32 ASSERT(isolate_ == NULL); |
| 32 } | 33 } |
| 33 | 34 |
| 34 | 35 |
| 35 void Thread::InitOnceBeforeIsolate() { | 36 void Thread::InitOnceBeforeIsolate() { |
| 36 ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey); | 37 ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey); |
| 37 thread_key_ = OSThread::CreateThreadLocal(DeleteThread); | 38 thread_key_ = OSThread::CreateThreadLocal(DeleteThread); |
| 38 ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey); | 39 ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey); |
| 39 ASSERT(Thread::Current() == NULL); | 40 ASSERT(Thread::Current() == NULL); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 51 | 52 |
| 52 | 53 |
| 53 void Thread::SetCurrent(Thread* current) { | 54 void Thread::SetCurrent(Thread* current) { |
| 54 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current)); | 55 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current)); |
| 55 } | 56 } |
| 56 | 57 |
| 57 | 58 |
| 58 void Thread::EnsureInit() { | 59 void Thread::EnsureInit() { |
| 59 if (Thread::Current() == NULL) { | 60 if (Thread::Current() == NULL) { |
| 60 SetCurrent(new Thread()); | 61 SetCurrent(new Thread()); |
| 62 ThreadInterrupter::GetCurrentThreadState(); |
| 61 } | 63 } |
| 62 } | 64 } |
| 63 | 65 |
| 64 | 66 |
| 65 #if defined(TARGET_OS_WINDOWS) | 67 #if defined(TARGET_OS_WINDOWS) |
| 66 void Thread::CleanUp() { | 68 void Thread::CleanUp() { |
| 67 Thread* current = Current(); | 69 Thread* current = Current(); |
| 68 if (current != NULL) { | 70 if (current != NULL) { |
| 69 delete current; | 71 delete current; |
| 70 } | 72 } |
| 71 SetCurrent(NULL); | 73 SetCurrent(NULL); |
| 72 } | 74 } |
| 73 #endif | 75 #endif |
| 74 | 76 |
| 75 | 77 |
| 76 Thread::Thread(bool init_vm_constants) | 78 Thread::Thread(bool init_vm_constants) |
| 77 : isolate_(NULL), | 79 : isolate_(NULL), |
| 78 store_buffer_block_(NULL) { | 80 store_buffer_block_(NULL), |
| 81 thread_state_(NULL) { |
| 79 ClearState(); | 82 ClearState(); |
| 80 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ | 83 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ |
| 81 member_name = default_init_value; | 84 member_name = default_init_value; |
| 82 CACHED_CONSTANTS_LIST(DEFAULT_INIT) | 85 CACHED_CONSTANTS_LIST(DEFAULT_INIT) |
| 83 #undef DEFAULT_INIT | 86 #undef DEFAULT_INIT |
| 84 if (init_vm_constants) { | 87 if (init_vm_constants) { |
| 85 InitVMConstants(); | 88 InitVMConstants(); |
| 86 } | 89 } |
| 87 } | 90 } |
| 88 | 91 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 ASSERT(thread->isolate() == NULL); | 127 ASSERT(thread->isolate() == NULL); |
| 125 ASSERT(!isolate->HasMutatorThread()); | 128 ASSERT(!isolate->HasMutatorThread()); |
| 126 thread->isolate_ = isolate; | 129 thread->isolate_ = isolate; |
| 127 isolate->MakeCurrentThreadMutator(thread); | 130 isolate->MakeCurrentThreadMutator(thread); |
| 128 isolate->set_vm_tag(VMTag::kVMTagId); | 131 isolate->set_vm_tag(VMTag::kVMTagId); |
| 129 ASSERT(thread->store_buffer_block_ == NULL); | 132 ASSERT(thread->store_buffer_block_ == NULL); |
| 130 thread->StoreBufferAcquire(); | 133 thread->StoreBufferAcquire(); |
| 131 ASSERT(isolate->heap() != NULL); | 134 ASSERT(isolate->heap() != NULL); |
| 132 thread->heap_ = isolate->heap(); | 135 thread->heap_ = isolate->heap(); |
| 133 thread->Schedule(isolate); | 136 thread->Schedule(isolate); |
| 134 ASSERT(thread->thread_state() == NULL); | |
| 135 InterruptableThreadState* thread_state = | 137 InterruptableThreadState* thread_state = |
| 136 ThreadInterrupter::GetCurrentThreadState(); | 138 ThreadInterrupter::GetCurrentThreadState(); |
| 137 #if defined(DEBUG) | 139 #if defined(DEBUG) |
| 138 thread->set_thread_state(NULL); // Exclude thread itself from the dupe check. | 140 thread->set_thread_state(NULL); // Exclude thread itself from the dupe check. |
| 139 Isolate::CheckForDuplicateThreadState(thread_state); | 141 Isolate::CheckForDuplicateThreadState(thread_state); |
| 140 thread->set_thread_state(thread_state); | 142 thread->set_thread_state(thread_state); |
| 141 #endif | 143 #endif |
| 142 ASSERT(thread_state != NULL); | 144 ASSERT(thread_state != NULL); |
| 143 // TODO(koda): Migrate profiler interface to use Thread. | 145 // TODO(koda): Migrate profiler interface to use Thread. |
| 144 Profiler::BeginExecution(isolate); | 146 Profiler::BeginExecution(isolate); |
| 145 } | 147 } |
| 146 | 148 |
| 147 | 149 |
| 148 void Thread::ExitIsolate() { | 150 void Thread::ExitIsolate() { |
| 149 Thread* thread = Thread::Current(); | 151 Thread* thread = Thread::Current(); |
| 150 // TODO(koda): Audit callers; they should know whether they're in an isolate. | 152 // TODO(koda): Audit callers; they should know whether they're in an isolate. |
| 151 if (thread == NULL || thread->isolate() == NULL) return; | 153 if (thread == NULL || thread->isolate() == NULL) return; |
| 152 Isolate* isolate = thread->isolate(); | 154 Isolate* isolate = thread->isolate(); |
| 153 Profiler::EndExecution(isolate); | 155 Profiler::EndExecution(isolate); |
| 154 thread->set_thread_state(NULL); | |
| 155 thread->Unschedule(); | 156 thread->Unschedule(); |
| 156 // TODO(koda): Move store_buffer_block_ into State. | 157 // TODO(koda): Move store_buffer_block_ into State. |
| 157 thread->StoreBufferRelease(); | 158 thread->StoreBufferRelease(); |
| 158 if (isolate->is_runnable()) { | 159 if (isolate->is_runnable()) { |
| 159 isolate->set_vm_tag(VMTag::kIdleTagId); | 160 isolate->set_vm_tag(VMTag::kIdleTagId); |
| 160 } else { | 161 } else { |
| 161 isolate->set_vm_tag(VMTag::kLoadWaitTagId); | 162 isolate->set_vm_tag(VMTag::kLoadWaitTagId); |
| 162 } | 163 } |
| 163 isolate->ClearMutatorThread(); | 164 isolate->ClearMutatorThread(); |
| 164 thread->isolate_ = NULL; | 165 thread->isolate_ = NULL; |
| 165 ASSERT(Isolate::Current() == NULL); | 166 ASSERT(Isolate::Current() == NULL); |
| 166 thread->heap_ = NULL; | 167 thread->heap_ = NULL; |
| 167 } | 168 } |
| 168 | 169 |
| 169 | 170 |
| 170 void Thread::EnterIsolateAsHelper(Isolate* isolate) { | 171 void Thread::EnterIsolateAsHelper(Isolate* isolate) { |
| 171 Thread* thread = Thread::Current(); | 172 Thread* thread = Thread::Current(); |
| 172 ASSERT(thread != NULL); | 173 ASSERT(thread != NULL); |
| 173 ASSERT(thread->isolate() == NULL); | 174 ASSERT(thread->isolate() == NULL); |
| 174 thread->isolate_ = isolate; | 175 thread->isolate_ = isolate; |
| 175 ASSERT(thread->store_buffer_block_ == NULL); | 176 ASSERT(thread->store_buffer_block_ == NULL); |
| 176 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge. | 177 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge. |
| 177 thread->store_buffer_block_ = | 178 thread->store_buffer_block_ = |
| 178 thread->isolate()->store_buffer()->PopEmptyBlock(); | 179 thread->isolate()->store_buffer()->PopEmptyBlock(); |
| 179 ASSERT(isolate->heap() != NULL); | 180 ASSERT(isolate->heap() != NULL); |
| 180 thread->heap_ = isolate->heap(); | 181 thread->heap_ = isolate->heap(); |
| 181 ASSERT(thread->thread_state() == NULL); | |
| 182 // Do not update isolate->mutator_thread, but perform sanity check: | 182 // Do not update isolate->mutator_thread, but perform sanity check: |
| 183 // this thread should not be both the main mutator and helper. | 183 // this thread should not be both the main mutator and helper. |
| 184 ASSERT(!isolate->MutatorThreadIsCurrentThread()); | 184 ASSERT(!isolate->MutatorThreadIsCurrentThread()); |
| 185 thread->Schedule(isolate); | 185 thread->Schedule(isolate); |
| 186 } | 186 } |
| 187 | 187 |
| 188 | 188 |
| 189 void Thread::ExitIsolateAsHelper() { | 189 void Thread::ExitIsolateAsHelper() { |
| 190 Thread* thread = Thread::Current(); | 190 Thread* thread = Thread::Current(); |
| 191 Isolate* isolate = thread->isolate(); | 191 Isolate* isolate = thread->isolate(); |
| 192 ASSERT(isolate != NULL); | 192 ASSERT(isolate != NULL); |
| 193 thread->Unschedule(); | 193 thread->Unschedule(); |
| 194 // TODO(koda): Move store_buffer_block_ into State. | 194 // TODO(koda): Move store_buffer_block_ into State. |
| 195 thread->StoreBufferRelease(); | 195 thread->StoreBufferRelease(); |
| 196 thread->set_thread_state(NULL); | |
| 197 thread->isolate_ = NULL; | 196 thread->isolate_ = NULL; |
| 198 thread->heap_ = NULL; | 197 thread->heap_ = NULL; |
| 199 ASSERT(!isolate->MutatorThreadIsCurrentThread()); | 198 ASSERT(!isolate->MutatorThreadIsCurrentThread()); |
| 200 } | 199 } |
| 201 | 200 |
| 202 | 201 |
| 203 // TODO(koda): Make non-static and invoke in SafepointThreads. | 202 // TODO(koda): Make non-static and invoke in SafepointThreads. |
| 204 void Thread::PrepareForGC() { | 203 void Thread::PrepareForGC() { |
| 205 Thread* thread = Thread::Current(); | 204 Thread* thread = Thread::Current(); |
| 206 const bool kDoNotCheckThreshold = false; // Prevent scheduling another GC. | 205 const bool kDoNotCheckThreshold = false; // Prevent scheduling another GC. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 #define COMPUTE_OFFSET(type_name, member_name, expr, default_init_value) \ | 271 #define COMPUTE_OFFSET(type_name, member_name, expr, default_init_value) \ |
| 273 ASSERT((expr)->IsVMHeapObject()); \ | 272 ASSERT((expr)->IsVMHeapObject()); \ |
| 274 if (object.raw() == expr) return Thread::member_name##offset(); | 273 if (object.raw() == expr) return Thread::member_name##offset(); |
| 275 CACHED_VM_OBJECTS_LIST(COMPUTE_OFFSET) | 274 CACHED_VM_OBJECTS_LIST(COMPUTE_OFFSET) |
| 276 #undef COMPUTE_OFFSET | 275 #undef COMPUTE_OFFSET |
| 277 UNREACHABLE(); | 276 UNREACHABLE(); |
| 278 return -1; | 277 return -1; |
| 279 } | 278 } |
| 280 | 279 |
| 281 } // namespace dart | 280 } // namespace dart |
| OLD | NEW |