Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(213)

Side by Side Diff: runtime/vm/thread.cc

Issue 1412733008: Switch profiler from isolates to threads (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/log.h" 10 #include "vm/log.h"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 while (current != NULL) { 59 while (current != NULL) {
60 ASSERT(current != thread); 60 ASSERT(current != thread);
61 current = current->thread_list_next_; 61 current = current->thread_list_next_;
62 } 62 }
63 } 63 }
64 #endif 64 #endif
65 65
66 // Insert at head of list. 66 // Insert at head of list.
67 thread->thread_list_next_ = thread_list_head_; 67 thread->thread_list_next_ = thread_list_head_;
68 thread_list_head_ = thread; 68 thread_list_head_ = thread;
69
70 // Make sure the thread interrupter is awake.
71 ThreadInterrupter::WakeUp();
Ivan Posva 2015/10/28 19:31:53 Does not match our discussion from earlier today.
Cutch 2015/10/28 19:50:33 Forgot to remove this. It's gone now.
69 } 72 }
70 73
71 74
72 void Thread::RemoveThreadFromList(Thread* thread) { 75 void Thread::RemoveThreadFromList(Thread* thread) {
73 ASSERT(thread != NULL); 76 ASSERT(thread != NULL);
74 ASSERT(thread->isolate() == NULL); 77 ASSERT(thread->isolate() == NULL);
75 ASSERT(thread_list_lock_ != NULL); 78 ASSERT(thread_list_lock_ != NULL);
76 MutexLocker ml(thread_list_lock_); 79 MutexLocker ml(thread_list_lock_);
77 80
78 // Handle case where |thread| is head of list. 81 // Handle case where |thread| is head of list.
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 #define REUSABLE_HANDLE_SCOPE_INIT(object) 192 #define REUSABLE_HANDLE_SCOPE_INIT(object)
190 #endif // defined(DEBUG) 193 #endif // defined(DEBUG)
191 194
192 #define REUSABLE_HANDLE_INITIALIZERS(object) \ 195 #define REUSABLE_HANDLE_INITIALIZERS(object) \
193 object##_handle_(NULL), 196 object##_handle_(NULL),
194 197
195 198
196 Thread::Thread(bool init_vm_constants) 199 Thread::Thread(bool init_vm_constants)
197 : id_(OSThread::GetCurrentThreadId()), 200 : id_(OSThread::GetCurrentThreadId()),
198 join_id_(OSThread::GetCurrentThreadJoinId()), 201 join_id_(OSThread::GetCurrentThreadJoinId()),
199 thread_interrupt_callback_(NULL), 202 thread_interrupt_disabled_(1), // Thread interrupts disabled by default.
200 thread_interrupt_data_(NULL),
201 isolate_(NULL), 203 isolate_(NULL),
202 heap_(NULL), 204 heap_(NULL),
203 timeline_block_(NULL), 205 timeline_block_(NULL),
204 store_buffer_block_(NULL), 206 store_buffer_block_(NULL),
205 log_(new class Log()), 207 log_(new class Log()),
206 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) 208 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
207 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) 209 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT)
208 reusable_handles_(), 210 reusable_handles_(),
209 cha_(NULL), 211 cha_(NULL),
210 deopt_id_(0), 212 deopt_id_(0),
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 ASSERT(thread->isolate() == NULL); 308 ASSERT(thread->isolate() == NULL);
307 ASSERT(!isolate->HasMutatorThread()); 309 ASSERT(!isolate->HasMutatorThread());
308 thread->isolate_ = isolate; 310 thread->isolate_ = isolate;
309 isolate->MakeCurrentThreadMutator(thread); 311 isolate->MakeCurrentThreadMutator(thread);
310 thread->set_vm_tag(VMTag::kVMTagId); 312 thread->set_vm_tag(VMTag::kVMTagId);
311 ASSERT(thread->store_buffer_block_ == NULL); 313 ASSERT(thread->store_buffer_block_ == NULL);
312 thread->StoreBufferAcquire(); 314 thread->StoreBufferAcquire();
313 ASSERT(isolate->heap() != NULL); 315 ASSERT(isolate->heap() != NULL);
314 thread->heap_ = isolate->heap(); 316 thread->heap_ = isolate->heap();
315 thread->Schedule(isolate); 317 thread->Schedule(isolate);
316 // TODO(koda): Migrate profiler interface to use Thread. 318 thread->EnableThreadInterrupts();
317 Profiler::BeginExecution(isolate);
318 } 319 }
319 320
320 321
321 void Thread::ExitIsolate() { 322 void Thread::ExitIsolate() {
322 Thread* thread = Thread::Current(); 323 Thread* thread = Thread::Current();
323 // TODO(koda): Audit callers; they should know whether they're in an isolate. 324 // TODO(koda): Audit callers; they should know whether they're in an isolate.
324 if (thread == NULL || thread->isolate() == NULL) return; 325 if (thread == NULL || thread->isolate() == NULL) return;
325 #if defined(DEBUG) 326 #if defined(DEBUG)
326 ASSERT(!thread->IsAnyReusableHandleScopeActive()); 327 ASSERT(!thread->IsAnyReusableHandleScopeActive());
327 #endif // DEBUG 328 #endif // DEBUG
329 thread->DisableThreadInterrupts();
328 // Clear since GC will not visit the thread once it is unscheduled. 330 // Clear since GC will not visit the thread once it is unscheduled.
329 thread->ClearReusableHandles(); 331 thread->ClearReusableHandles();
330 Isolate* isolate = thread->isolate(); 332 Isolate* isolate = thread->isolate();
331 Profiler::EndExecution(isolate);
332 thread->Unschedule(); 333 thread->Unschedule();
333 // TODO(koda): Move store_buffer_block_ into State. 334 // TODO(koda): Move store_buffer_block_ into State.
334 thread->StoreBufferRelease(); 335 thread->StoreBufferRelease();
335 if (isolate->is_runnable()) { 336 if (isolate->is_runnable()) {
336 thread->set_vm_tag(VMTag::kIdleTagId); 337 thread->set_vm_tag(VMTag::kIdleTagId);
337 } else { 338 } else {
338 thread->set_vm_tag(VMTag::kLoadWaitTagId); 339 thread->set_vm_tag(VMTag::kLoadWaitTagId);
339 } 340 }
340 isolate->ClearMutatorThread(); 341 isolate->ClearMutatorThread();
341 thread->isolate_ = NULL; 342 thread->isolate_ = NULL;
342 ASSERT(Isolate::Current() == NULL); 343 ASSERT(Isolate::Current() == NULL);
343 thread->heap_ = NULL; 344 thread->heap_ = NULL;
344 } 345 }
345 346
346 347
347 void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) { 348 void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
348 Thread* thread = Thread::Current(); 349 Thread* thread = Thread::Current();
349 ASSERT(thread != NULL); 350 ASSERT(thread != NULL);
350 ASSERT(thread->isolate() == NULL); 351 ASSERT(thread->isolate() == NULL);
351 thread->isolate_ = isolate; 352 thread->isolate_ = isolate;
352 ASSERT(thread->store_buffer_block_ == NULL); 353 ASSERT(thread->store_buffer_block_ == NULL);
353 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge. 354 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge.
354 thread->store_buffer_block_ = 355 thread->store_buffer_block_ =
355 thread->isolate()->store_buffer()->PopEmptyBlock(); 356 thread->isolate()->store_buffer()->PopEmptyBlock();
356 ASSERT(isolate->heap() != NULL); 357 ASSERT(isolate->heap() != NULL);
357 thread->heap_ = isolate->heap(); 358 thread->heap_ = isolate->heap();
358 ASSERT(thread->thread_interrupt_callback_ == NULL);
359 ASSERT(thread->thread_interrupt_data_ == NULL);
360 // Do not update isolate->mutator_thread, but perform sanity check: 359 // Do not update isolate->mutator_thread, but perform sanity check:
361 // this thread should not be both the main mutator and helper. 360 // this thread should not be both the main mutator and helper.
362 ASSERT(!thread->IsMutatorThread()); 361 ASSERT(!thread->IsMutatorThread());
363 thread->Schedule(isolate, bypass_safepoint); 362 thread->Schedule(isolate, bypass_safepoint);
363 thread->EnableThreadInterrupts();
364 } 364 }
365 365
366 366
367 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { 367 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) {
368 Thread* thread = Thread::Current(); 368 Thread* thread = Thread::Current();
369 thread->DisableThreadInterrupts();
369 Isolate* isolate = thread->isolate(); 370 Isolate* isolate = thread->isolate();
370 ASSERT(isolate != NULL); 371 ASSERT(isolate != NULL);
371 thread->Unschedule(bypass_safepoint); 372 thread->Unschedule(bypass_safepoint);
372 // TODO(koda): Move store_buffer_block_ into State. 373 // TODO(koda): Move store_buffer_block_ into State.
373 thread->StoreBufferRelease(); 374 thread->StoreBufferRelease();
374 thread->isolate_ = NULL; 375 thread->isolate_ = NULL;
375 thread->heap_ = NULL; 376 thread->heap_ = NULL;
376 ASSERT(!thread->IsMutatorThread()); 377 ASSERT(!thread->IsMutatorThread());
377 } 378 }
378 379
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 void Thread::StoreBufferAcquire() { 423 void Thread::StoreBufferAcquire() {
423 store_buffer_block_ = isolate()->store_buffer()->PopNonFullBlock(); 424 store_buffer_block_ = isolate()->store_buffer()->PopNonFullBlock();
424 } 425 }
425 426
426 427
427 bool Thread::IsMutatorThread() const { 428 bool Thread::IsMutatorThread() const {
428 return ((isolate_ != NULL) && (isolate_->mutator_thread() == this)); 429 return ((isolate_ != NULL) && (isolate_->mutator_thread() == this));
429 } 430 }
430 431
431 432
433 bool Thread::IsExecutingDartCode() const {
434 return (top_exit_frame_info() == 0) &&
435 (vm_tag() == VMTag::kDartTagId);
436 }
437
438
439 bool Thread::HasExitedDartCode() const {
440 return (top_exit_frame_info() != 0) &&
441 (vm_tag() != VMTag::kDartTagId);
442 }
443
444
432 CHA* Thread::cha() const { 445 CHA* Thread::cha() const {
433 ASSERT(isolate_ != NULL); 446 ASSERT(isolate_ != NULL);
434 return cha_; 447 return cha_;
435 } 448 }
436 449
437 450
438 void Thread::set_cha(CHA* value) { 451 void Thread::set_cha(CHA* value) {
439 ASSERT(isolate_ != NULL); 452 ASSERT(isolate_ != NULL);
440 cha_ = value; 453 cha_ = value;
441 } 454 }
(...skipping 26 matching lines...) Expand all
468 // Visit objects in thread specific handles area. 481 // Visit objects in thread specific handles area.
469 reusable_handles_.VisitObjectPointers(visitor); 482 reusable_handles_.VisitObjectPointers(visitor);
470 483
471 if (pending_functions_ != GrowableObjectArray::null()) { 484 if (pending_functions_ != GrowableObjectArray::null()) {
472 visitor->VisitPointer( 485 visitor->VisitPointer(
473 reinterpret_cast<RawObject**>(&pending_functions_)); 486 reinterpret_cast<RawObject**>(&pending_functions_));
474 } 487 }
475 } 488 }
476 489
477 490
478 void Thread::SetThreadInterrupter(ThreadInterruptCallback callback, 491 void Thread::DisableThreadInterrupts() {
479 void* data) {
480 ASSERT(Thread::Current() == this); 492 ASSERT(Thread::Current() == this);
481 thread_interrupt_callback_ = callback; 493 AtomicOperations::FetchAndIncrement(&thread_interrupt_disabled_);
482 thread_interrupt_data_ = data;
483 } 494 }
484 495
485 496
486 bool Thread::IsThreadInterrupterEnabled(ThreadInterruptCallback* callback, 497 void Thread::EnableThreadInterrupts() {
487 void** data) const { 498 ASSERT(Thread::Current() == this);
488 #if defined(TARGET_OS_WINDOWS) 499 uintptr_t old =
489 // On Windows we expect this to be called from the thread interrupter thread. 500 AtomicOperations::FetchAndDecrement(&thread_interrupt_disabled_);
490 ASSERT(id() != OSThread::GetCurrentThreadId()); 501 if (old == 1) {
491 #else 502 // We just decremented from 1 to 0.
492 // On posix platforms, we expect this to be called from signal handler. 503 // Make sure the thread interrupter is awake.
493 ASSERT(id() == OSThread::GetCurrentThreadId()); 504 ThreadInterrupter::WakeUp();
494 #endif 505 }
495 ASSERT(callback != NULL); 506 if (old == 0) {
496 ASSERT(data != NULL); 507 // We just decremented from 0, this means we've got a mismatched pair
497 *callback = thread_interrupt_callback_; 508 // of calls to EnableThreadInterrupts and DisableThreadInterrupts.
498 *data = thread_interrupt_data_; 509 FATAL("Invalid call to Thread::EnableThreadInterrupts()");
499 return (*callback != NULL) && 510 }
500 (*data != NULL);
501 } 511 }
502 512
503 513
514 bool Thread::ThreadInterruptsEnabled() {
515 return AtomicOperations::LoadRelaxed(&thread_interrupt_disabled_) == 0;
516 }
517
518
504 bool Thread::CanLoadFromThread(const Object& object) { 519 bool Thread::CanLoadFromThread(const Object& object) {
505 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \ 520 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \
506 if (object.raw() == expr) return true; 521 if (object.raw() == expr) return true;
507 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT) 522 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT)
508 #undef CHECK_OBJECT 523 #undef CHECK_OBJECT
509 return false; 524 return false;
510 } 525 }
511 526
512 527
513 intptr_t Thread::OffsetFromThread(const Object& object) { 528 intptr_t Thread::OffsetFromThread(const Object& object) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 580
566 Thread* ThreadIterator::Next() { 581 Thread* ThreadIterator::Next() {
567 ASSERT(Thread::thread_list_lock_ != NULL); 582 ASSERT(Thread::thread_list_lock_ != NULL);
568 ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread()); 583 ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread());
569 Thread* current = next_; 584 Thread* current = next_;
570 next_ = next_->thread_list_next_; 585 next_ = next_->thread_list_next_;
571 return current; 586 return current;
572 } 587 }
573 588
574 589
590 DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread)
591 : StackResource(thread) {
592 if (thread != NULL) {
593 thread->DisableThreadInterrupts();
594 }
595 }
596
597
598 DisableThreadInterruptsScope::~DisableThreadInterruptsScope() {
599 if (thread() != NULL) {
600 thread()->EnableThreadInterrupts();
601 }
602 }
603
575 } // namespace dart 604 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698