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

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 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 #define REUSABLE_HANDLE_SCOPE_INIT(object) 189 #define REUSABLE_HANDLE_SCOPE_INIT(object)
190 #endif // defined(DEBUG) 190 #endif // defined(DEBUG)
191 191
192 #define REUSABLE_HANDLE_INITIALIZERS(object) \ 192 #define REUSABLE_HANDLE_INITIALIZERS(object) \
193 object##_handle_(NULL), 193 object##_handle_(NULL),
194 194
195 195
196 Thread::Thread(bool init_vm_constants) 196 Thread::Thread(bool init_vm_constants)
197 : id_(OSThread::GetCurrentThreadId()), 197 : id_(OSThread::GetCurrentThreadId()),
198 join_id_(OSThread::GetCurrentThreadJoinId()), 198 join_id_(OSThread::GetCurrentThreadJoinId()),
199 thread_interrupt_callback_(NULL), 199 thread_interrupt_disabled_(1), // Thread interrupts disabled by default.
200 thread_interrupt_data_(NULL),
201 isolate_(NULL), 200 isolate_(NULL),
202 heap_(NULL), 201 heap_(NULL),
203 timeline_block_(NULL), 202 timeline_block_(NULL),
204 store_buffer_block_(NULL), 203 store_buffer_block_(NULL),
205 log_(new class Log()), 204 log_(new class Log()),
206 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) 205 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
207 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) 206 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT)
208 reusable_handles_(), 207 reusable_handles_(),
209 cha_(NULL), 208 cha_(NULL),
210 deopt_id_(0), 209 deopt_id_(0),
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 ASSERT(thread->isolate() == NULL); 305 ASSERT(thread->isolate() == NULL);
307 ASSERT(!isolate->HasMutatorThread()); 306 ASSERT(!isolate->HasMutatorThread());
308 thread->isolate_ = isolate; 307 thread->isolate_ = isolate;
309 isolate->MakeCurrentThreadMutator(thread); 308 isolate->MakeCurrentThreadMutator(thread);
310 thread->set_vm_tag(VMTag::kVMTagId); 309 thread->set_vm_tag(VMTag::kVMTagId);
311 ASSERT(thread->store_buffer_block_ == NULL); 310 ASSERT(thread->store_buffer_block_ == NULL);
312 thread->StoreBufferAcquire(); 311 thread->StoreBufferAcquire();
313 ASSERT(isolate->heap() != NULL); 312 ASSERT(isolate->heap() != NULL);
314 thread->heap_ = isolate->heap(); 313 thread->heap_ = isolate->heap();
315 thread->Schedule(isolate); 314 thread->Schedule(isolate);
316 // TODO(koda): Migrate profiler interface to use Thread. 315 thread->EnableThreadInterrupts();
317 Profiler::BeginExecution(isolate);
318 } 316 }
319 317
320 318
321 void Thread::ExitIsolate() { 319 void Thread::ExitIsolate() {
322 Thread* thread = Thread::Current(); 320 Thread* thread = Thread::Current();
323 // TODO(koda): Audit callers; they should know whether they're in an isolate. 321 // TODO(koda): Audit callers; they should know whether they're in an isolate.
324 if (thread == NULL || thread->isolate() == NULL) return; 322 if (thread == NULL || thread->isolate() == NULL) return;
325 #if defined(DEBUG) 323 #if defined(DEBUG)
326 ASSERT(!thread->IsAnyReusableHandleScopeActive()); 324 ASSERT(!thread->IsAnyReusableHandleScopeActive());
327 #endif // DEBUG 325 #endif // DEBUG
326 thread->DisableThreadInterrupts();
328 // Clear since GC will not visit the thread once it is unscheduled. 327 // Clear since GC will not visit the thread once it is unscheduled.
329 thread->ClearReusableHandles(); 328 thread->ClearReusableHandles();
330 Isolate* isolate = thread->isolate(); 329 Isolate* isolate = thread->isolate();
331 Profiler::EndExecution(isolate);
332 thread->Unschedule(); 330 thread->Unschedule();
333 // TODO(koda): Move store_buffer_block_ into State. 331 // TODO(koda): Move store_buffer_block_ into State.
334 thread->StoreBufferRelease(); 332 thread->StoreBufferRelease();
335 if (isolate->is_runnable()) { 333 if (isolate->is_runnable()) {
336 thread->set_vm_tag(VMTag::kIdleTagId); 334 thread->set_vm_tag(VMTag::kIdleTagId);
337 } else { 335 } else {
338 thread->set_vm_tag(VMTag::kLoadWaitTagId); 336 thread->set_vm_tag(VMTag::kLoadWaitTagId);
339 } 337 }
340 isolate->ClearMutatorThread(); 338 isolate->ClearMutatorThread();
341 thread->isolate_ = NULL; 339 thread->isolate_ = NULL;
342 ASSERT(Isolate::Current() == NULL); 340 ASSERT(Isolate::Current() == NULL);
343 thread->heap_ = NULL; 341 thread->heap_ = NULL;
344 } 342 }
345 343
346 344
347 void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) { 345 void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
348 Thread* thread = Thread::Current(); 346 Thread* thread = Thread::Current();
349 ASSERT(thread != NULL); 347 ASSERT(thread != NULL);
350 ASSERT(thread->isolate() == NULL); 348 ASSERT(thread->isolate() == NULL);
351 thread->isolate_ = isolate; 349 thread->isolate_ = isolate;
352 ASSERT(thread->store_buffer_block_ == NULL); 350 ASSERT(thread->store_buffer_block_ == NULL);
353 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge. 351 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge.
354 thread->store_buffer_block_ = 352 thread->store_buffer_block_ =
355 thread->isolate()->store_buffer()->PopEmptyBlock(); 353 thread->isolate()->store_buffer()->PopEmptyBlock();
356 ASSERT(isolate->heap() != NULL); 354 ASSERT(isolate->heap() != NULL);
357 thread->heap_ = isolate->heap(); 355 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: 356 // Do not update isolate->mutator_thread, but perform sanity check:
361 // this thread should not be both the main mutator and helper. 357 // this thread should not be both the main mutator and helper.
362 ASSERT(!thread->IsMutatorThread()); 358 ASSERT(!thread->IsMutatorThread());
363 thread->Schedule(isolate, bypass_safepoint); 359 thread->Schedule(isolate, bypass_safepoint);
360 thread->EnableThreadInterrupts();
364 } 361 }
365 362
366 363
367 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { 364 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) {
368 Thread* thread = Thread::Current(); 365 Thread* thread = Thread::Current();
366 thread->DisableThreadInterrupts();
369 Isolate* isolate = thread->isolate(); 367 Isolate* isolate = thread->isolate();
370 ASSERT(isolate != NULL); 368 ASSERT(isolate != NULL);
371 thread->Unschedule(bypass_safepoint); 369 thread->Unschedule(bypass_safepoint);
372 // TODO(koda): Move store_buffer_block_ into State. 370 // TODO(koda): Move store_buffer_block_ into State.
373 thread->StoreBufferRelease(); 371 thread->StoreBufferRelease();
374 thread->isolate_ = NULL; 372 thread->isolate_ = NULL;
375 thread->heap_ = NULL; 373 thread->heap_ = NULL;
376 ASSERT(!thread->IsMutatorThread()); 374 ASSERT(!thread->IsMutatorThread());
377 } 375 }
378 376
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 void Thread::StoreBufferAcquire() { 420 void Thread::StoreBufferAcquire() {
423 store_buffer_block_ = isolate()->store_buffer()->PopNonFullBlock(); 421 store_buffer_block_ = isolate()->store_buffer()->PopNonFullBlock();
424 } 422 }
425 423
426 424
427 bool Thread::IsMutatorThread() const { 425 bool Thread::IsMutatorThread() const {
428 return ((isolate_ != NULL) && (isolate_->mutator_thread() == this)); 426 return ((isolate_ != NULL) && (isolate_->mutator_thread() == this));
429 } 427 }
430 428
431 429
430 bool Thread::IsExecutingDartCode() const {
431 return (top_exit_frame_info() == 0) &&
432 (vm_tag() == VMTag::kDartTagId);
433 }
434
435
436 bool Thread::HasExitedDartCode() const {
437 return (top_exit_frame_info() != 0) &&
438 (vm_tag() != VMTag::kDartTagId);
439 }
440
441
432 CHA* Thread::cha() const { 442 CHA* Thread::cha() const {
433 ASSERT(isolate_ != NULL); 443 ASSERT(isolate_ != NULL);
434 return cha_; 444 return cha_;
435 } 445 }
436 446
437 447
438 void Thread::set_cha(CHA* value) { 448 void Thread::set_cha(CHA* value) {
439 ASSERT(isolate_ != NULL); 449 ASSERT(isolate_ != NULL);
440 cha_ = value; 450 cha_ = value;
441 } 451 }
(...skipping 26 matching lines...) Expand all
468 // Visit objects in thread specific handles area. 478 // Visit objects in thread specific handles area.
469 reusable_handles_.VisitObjectPointers(visitor); 479 reusable_handles_.VisitObjectPointers(visitor);
470 480
471 if (pending_functions_ != GrowableObjectArray::null()) { 481 if (pending_functions_ != GrowableObjectArray::null()) {
472 visitor->VisitPointer( 482 visitor->VisitPointer(
473 reinterpret_cast<RawObject**>(&pending_functions_)); 483 reinterpret_cast<RawObject**>(&pending_functions_));
474 } 484 }
475 } 485 }
476 486
477 487
478 void Thread::SetThreadInterrupter(ThreadInterruptCallback callback, 488 void Thread::DisableThreadInterrupts() {
479 void* data) {
480 ASSERT(Thread::Current() == this); 489 ASSERT(Thread::Current() == this);
481 thread_interrupt_callback_ = callback; 490 AtomicOperations::FetchAndIncrement(&thread_interrupt_disabled_);
482 thread_interrupt_data_ = data;
483 } 491 }
484 492
485 493
486 bool Thread::IsThreadInterrupterEnabled(ThreadInterruptCallback* callback, 494 void Thread::EnableThreadInterrupts() {
487 void** data) const { 495 ASSERT(Thread::Current() == this);
488 #if defined(TARGET_OS_WINDOWS) 496 uintptr_t old =
489 // On Windows we expect this to be called from the thread interrupter thread. 497 AtomicOperations::FetchAndDecrement(&thread_interrupt_disabled_);
490 ASSERT(id() != OSThread::GetCurrentThreadId()); 498 if (old == 1) {
491 #else 499 // We just decremented from 1 to 0.
492 // On posix platforms, we expect this to be called from signal handler. 500 // Make sure the thread interrupter is awake.
493 ASSERT(id() == OSThread::GetCurrentThreadId()); 501 ThreadInterrupter::WakeUp();
494 #endif 502 }
495 ASSERT(callback != NULL); 503 if (old == 0) {
496 ASSERT(data != NULL); 504 // We just decremented from 0, this means we've got a mismatched pair
497 *callback = thread_interrupt_callback_; 505 // of calls to EnableThreadInterrupts and DisableThreadInterrupts.
498 *data = thread_interrupt_data_; 506 FATAL("Invalid call to Thread::EnableThreadInterrupts()");
499 return (*callback != NULL) && 507 }
500 (*data != NULL);
501 } 508 }
502 509
503 510
511 bool Thread::ThreadInterruptsEnabled() {
512 return AtomicOperations::LoadRelaxed(&thread_interrupt_disabled_) == 0;
513 }
514
515
504 bool Thread::CanLoadFromThread(const Object& object) { 516 bool Thread::CanLoadFromThread(const Object& object) {
505 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \ 517 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \
506 if (object.raw() == expr) return true; 518 if (object.raw() == expr) return true;
507 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT) 519 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT)
508 #undef CHECK_OBJECT 520 #undef CHECK_OBJECT
509 return false; 521 return false;
510 } 522 }
511 523
512 524
513 intptr_t Thread::OffsetFromThread(const Object& object) { 525 intptr_t Thread::OffsetFromThread(const Object& object) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 577
566 Thread* ThreadIterator::Next() { 578 Thread* ThreadIterator::Next() {
567 ASSERT(Thread::thread_list_lock_ != NULL); 579 ASSERT(Thread::thread_list_lock_ != NULL);
568 ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread()); 580 ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread());
569 Thread* current = next_; 581 Thread* current = next_;
570 next_ = next_->thread_list_next_; 582 next_ = next_->thread_list_next_;
571 return current; 583 return current;
572 } 584 }
573 585
574 586
587 DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread)
588 : StackResource(thread) {
589 if (thread != NULL) {
590 thread->DisableThreadInterrupts();
591 }
592 }
593
594
595 DisableThreadInterruptsScope::~DisableThreadInterruptsScope() {
596 if (thread() != NULL) {
597 thread()->EnableThreadInterrupts();
598 }
599 }
600
575 } // namespace dart 601 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698