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

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
« no previous file with comments | « runtime/vm/thread.h ('k') | runtime/vm/thread_interrupter.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 #define REUSABLE_HANDLE_SCOPE_INIT(object) 207 #define REUSABLE_HANDLE_SCOPE_INIT(object)
208 #endif // defined(DEBUG) 208 #endif // defined(DEBUG)
209 209
210 #define REUSABLE_HANDLE_INITIALIZERS(object) \ 210 #define REUSABLE_HANDLE_INITIALIZERS(object) \
211 object##_handle_(NULL), 211 object##_handle_(NULL),
212 212
213 213
214 Thread::Thread(bool init_vm_constants) 214 Thread::Thread(bool init_vm_constants)
215 : id_(OSThread::GetCurrentThreadId()), 215 : id_(OSThread::GetCurrentThreadId()),
216 join_id_(OSThread::GetCurrentThreadJoinId()), 216 join_id_(OSThread::GetCurrentThreadJoinId()),
217 thread_interrupt_callback_(NULL), 217 thread_interrupt_disabled_(1), // Thread interrupts disabled by default.
218 thread_interrupt_data_(NULL),
219 isolate_(NULL), 218 isolate_(NULL),
220 heap_(NULL), 219 heap_(NULL),
221 timeline_block_(NULL), 220 timeline_block_(NULL),
222 store_buffer_block_(NULL), 221 store_buffer_block_(NULL),
223 log_(new class Log()), 222 log_(new class Log()),
224 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) 223 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
225 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) 224 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT)
226 reusable_handles_(), 225 reusable_handles_(),
227 cha_(NULL), 226 cha_(NULL),
228 deopt_id_(0), 227 deopt_id_(0),
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 ASSERT(thread->isolate() == NULL); 323 ASSERT(thread->isolate() == NULL);
325 ASSERT(!isolate->HasMutatorThread()); 324 ASSERT(!isolate->HasMutatorThread());
326 thread->isolate_ = isolate; 325 thread->isolate_ = isolate;
327 isolate->MakeCurrentThreadMutator(thread); 326 isolate->MakeCurrentThreadMutator(thread);
328 thread->set_vm_tag(VMTag::kVMTagId); 327 thread->set_vm_tag(VMTag::kVMTagId);
329 ASSERT(thread->store_buffer_block_ == NULL); 328 ASSERT(thread->store_buffer_block_ == NULL);
330 thread->StoreBufferAcquire(); 329 thread->StoreBufferAcquire();
331 ASSERT(isolate->heap() != NULL); 330 ASSERT(isolate->heap() != NULL);
332 thread->heap_ = isolate->heap(); 331 thread->heap_ = isolate->heap();
333 thread->Schedule(isolate); 332 thread->Schedule(isolate);
334 // TODO(koda): Migrate profiler interface to use Thread. 333 thread->EnableThreadInterrupts();
335 Profiler::BeginExecution(isolate);
336 } 334 }
337 335
338 336
339 void Thread::ExitIsolate() { 337 void Thread::ExitIsolate() {
340 Thread* thread = Thread::Current(); 338 Thread* thread = Thread::Current();
341 // TODO(koda): Audit callers; they should know whether they're in an isolate. 339 // TODO(koda): Audit callers; they should know whether they're in an isolate.
342 if (thread == NULL || thread->isolate() == NULL) return; 340 if (thread == NULL || thread->isolate() == NULL) return;
343 #if defined(DEBUG) 341 #if defined(DEBUG)
344 ASSERT(!thread->IsAnyReusableHandleScopeActive()); 342 ASSERT(!thread->IsAnyReusableHandleScopeActive());
345 #endif // DEBUG 343 #endif // DEBUG
344 thread->DisableThreadInterrupts();
346 // Clear since GC will not visit the thread once it is unscheduled. 345 // Clear since GC will not visit the thread once it is unscheduled.
347 thread->ClearReusableHandles(); 346 thread->ClearReusableHandles();
348 Isolate* isolate = thread->isolate(); 347 Isolate* isolate = thread->isolate();
349 Profiler::EndExecution(isolate);
350 thread->Unschedule(); 348 thread->Unschedule();
351 // TODO(koda): Move store_buffer_block_ into State. 349 // TODO(koda): Move store_buffer_block_ into State.
352 thread->StoreBufferRelease(); 350 thread->StoreBufferRelease();
353 if (isolate->is_runnable()) { 351 if (isolate->is_runnable()) {
354 thread->set_vm_tag(VMTag::kIdleTagId); 352 thread->set_vm_tag(VMTag::kIdleTagId);
355 } else { 353 } else {
356 thread->set_vm_tag(VMTag::kLoadWaitTagId); 354 thread->set_vm_tag(VMTag::kLoadWaitTagId);
357 } 355 }
358 isolate->ClearMutatorThread(); 356 isolate->ClearMutatorThread();
359 thread->isolate_ = NULL; 357 thread->isolate_ = NULL;
360 ASSERT(Isolate::Current() == NULL); 358 ASSERT(Isolate::Current() == NULL);
361 thread->heap_ = NULL; 359 thread->heap_ = NULL;
362 } 360 }
363 361
364 362
365 void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) { 363 void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
366 Thread* thread = Thread::Current(); 364 Thread* thread = Thread::Current();
367 ASSERT(thread != NULL); 365 ASSERT(thread != NULL);
368 ASSERT(thread->isolate() == NULL); 366 ASSERT(thread->isolate() == NULL);
369 thread->isolate_ = isolate; 367 thread->isolate_ = isolate;
370 ASSERT(thread->store_buffer_block_ == NULL); 368 ASSERT(thread->store_buffer_block_ == NULL);
371 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge. 369 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge.
372 thread->store_buffer_block_ = 370 thread->store_buffer_block_ =
373 thread->isolate()->store_buffer()->PopEmptyBlock(); 371 thread->isolate()->store_buffer()->PopEmptyBlock();
374 ASSERT(isolate->heap() != NULL); 372 ASSERT(isolate->heap() != NULL);
375 thread->heap_ = isolate->heap(); 373 thread->heap_ = isolate->heap();
376 ASSERT(thread->thread_interrupt_callback_ == NULL);
377 ASSERT(thread->thread_interrupt_data_ == NULL);
378 // Do not update isolate->mutator_thread, but perform sanity check: 374 // Do not update isolate->mutator_thread, but perform sanity check:
379 // this thread should not be both the main mutator and helper. 375 // this thread should not be both the main mutator and helper.
380 ASSERT(!thread->IsMutatorThread()); 376 ASSERT(!thread->IsMutatorThread());
381 thread->Schedule(isolate, bypass_safepoint); 377 thread->Schedule(isolate, bypass_safepoint);
378 thread->EnableThreadInterrupts();
382 } 379 }
383 380
384 381
385 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { 382 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) {
386 Thread* thread = Thread::Current(); 383 Thread* thread = Thread::Current();
384 thread->DisableThreadInterrupts();
387 Isolate* isolate = thread->isolate(); 385 Isolate* isolate = thread->isolate();
388 ASSERT(isolate != NULL); 386 ASSERT(isolate != NULL);
389 thread->Unschedule(bypass_safepoint); 387 thread->Unschedule(bypass_safepoint);
390 // TODO(koda): Move store_buffer_block_ into State. 388 // TODO(koda): Move store_buffer_block_ into State.
391 thread->StoreBufferRelease(); 389 thread->StoreBufferRelease();
392 thread->isolate_ = NULL; 390 thread->isolate_ = NULL;
393 thread->heap_ = NULL; 391 thread->heap_ = NULL;
394 ASSERT(!thread->IsMutatorThread()); 392 ASSERT(!thread->IsMutatorThread());
395 } 393 }
396 394
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 void Thread::StoreBufferAcquire() { 438 void Thread::StoreBufferAcquire() {
441 store_buffer_block_ = isolate()->store_buffer()->PopNonFullBlock(); 439 store_buffer_block_ = isolate()->store_buffer()->PopNonFullBlock();
442 } 440 }
443 441
444 442
445 bool Thread::IsMutatorThread() const { 443 bool Thread::IsMutatorThread() const {
446 return ((isolate_ != NULL) && (isolate_->mutator_thread() == this)); 444 return ((isolate_ != NULL) && (isolate_->mutator_thread() == this));
447 } 445 }
448 446
449 447
448 bool Thread::IsExecutingDartCode() const {
449 return (top_exit_frame_info() == 0) &&
450 (vm_tag() == VMTag::kDartTagId);
451 }
452
453
454 bool Thread::HasExitedDartCode() const {
455 return (top_exit_frame_info() != 0) &&
456 (vm_tag() != VMTag::kDartTagId);
457 }
458
459
450 CHA* Thread::cha() const { 460 CHA* Thread::cha() const {
451 ASSERT(isolate_ != NULL); 461 ASSERT(isolate_ != NULL);
452 return cha_; 462 return cha_;
453 } 463 }
454 464
455 465
456 void Thread::set_cha(CHA* value) { 466 void Thread::set_cha(CHA* value) {
457 ASSERT(isolate_ != NULL); 467 ASSERT(isolate_ != NULL);
458 cha_ = value; 468 cha_ = value;
459 } 469 }
(...skipping 26 matching lines...) Expand all
486 // Visit objects in thread specific handles area. 496 // Visit objects in thread specific handles area.
487 reusable_handles_.VisitObjectPointers(visitor); 497 reusable_handles_.VisitObjectPointers(visitor);
488 498
489 if (pending_functions_ != GrowableObjectArray::null()) { 499 if (pending_functions_ != GrowableObjectArray::null()) {
490 visitor->VisitPointer( 500 visitor->VisitPointer(
491 reinterpret_cast<RawObject**>(&pending_functions_)); 501 reinterpret_cast<RawObject**>(&pending_functions_));
492 } 502 }
493 } 503 }
494 504
495 505
496 void Thread::SetThreadInterrupter(ThreadInterruptCallback callback, 506 void Thread::DisableThreadInterrupts() {
497 void* data) {
498 ASSERT(Thread::Current() == this); 507 ASSERT(Thread::Current() == this);
499 thread_interrupt_callback_ = callback; 508 AtomicOperations::FetchAndIncrement(&thread_interrupt_disabled_);
500 thread_interrupt_data_ = data;
501 } 509 }
502 510
503 511
504 bool Thread::IsThreadInterrupterEnabled(ThreadInterruptCallback* callback, 512 void Thread::EnableThreadInterrupts() {
505 void** data) const { 513 ASSERT(Thread::Current() == this);
506 #if defined(TARGET_OS_WINDOWS) 514 uintptr_t old =
507 // On Windows we expect this to be called from the thread interrupter thread. 515 AtomicOperations::FetchAndDecrement(&thread_interrupt_disabled_);
508 ASSERT(id() != OSThread::GetCurrentThreadId()); 516 if (old == 1) {
509 #else 517 // We just decremented from 1 to 0.
510 // On posix platforms, we expect this to be called from signal handler. 518 // Make sure the thread interrupter is awake.
511 ASSERT(id() == OSThread::GetCurrentThreadId()); 519 ThreadInterrupter::WakeUp();
512 #endif 520 }
513 ASSERT(callback != NULL); 521 if (old == 0) {
514 ASSERT(data != NULL); 522 // We just decremented from 0, this means we've got a mismatched pair
515 *callback = thread_interrupt_callback_; 523 // of calls to EnableThreadInterrupts and DisableThreadInterrupts.
516 *data = thread_interrupt_data_; 524 FATAL("Invalid call to Thread::EnableThreadInterrupts()");
517 return (*callback != NULL) && 525 }
518 (*data != NULL);
519 } 526 }
520 527
521 528
529 bool Thread::ThreadInterruptsEnabled() {
530 return AtomicOperations::LoadRelaxed(&thread_interrupt_disabled_) == 0;
531 }
532
533
522 bool Thread::CanLoadFromThread(const Object& object) { 534 bool Thread::CanLoadFromThread(const Object& object) {
523 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \ 535 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \
524 if (object.raw() == expr) return true; 536 if (object.raw() == expr) return true;
525 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT) 537 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT)
526 #undef CHECK_OBJECT 538 #undef CHECK_OBJECT
527 return false; 539 return false;
528 } 540 }
529 541
530 542
531 intptr_t Thread::OffsetFromThread(const Object& object) { 543 intptr_t Thread::OffsetFromThread(const Object& object) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 595
584 Thread* ThreadIterator::Next() { 596 Thread* ThreadIterator::Next() {
585 ASSERT(Thread::thread_list_lock_ != NULL); 597 ASSERT(Thread::thread_list_lock_ != NULL);
586 ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread()); 598 ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread());
587 Thread* current = next_; 599 Thread* current = next_;
588 next_ = next_->thread_list_next_; 600 next_ = next_->thread_list_next_;
589 return current; 601 return current;
590 } 602 }
591 603
592 604
605 DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread)
606 : StackResource(thread) {
607 if (thread != NULL) {
608 thread->DisableThreadInterrupts();
609 }
610 }
611
612
613 DisableThreadInterruptsScope::~DisableThreadInterruptsScope() {
614 if (thread() != NULL) {
615 thread()->EnableThreadInterrupts();
616 }
617 }
618
593 } // namespace dart 619 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/thread.h ('k') | runtime/vm/thread_interrupter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698