Chromium Code Reviews| 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 #ifndef VM_THREAD_H_ | 5 #ifndef VM_THREAD_H_ |
| 6 #define VM_THREAD_H_ | 6 #define VM_THREAD_H_ |
| 7 | 7 |
| 8 #include "include/dart_api.h" | 8 #include "include/dart_api.h" |
| 9 #include "platform/assert.h" | |
| 10 #include "vm/atomic.h" | |
| 11 #include "vm/bitfield.h" | |
| 9 #include "vm/globals.h" | 12 #include "vm/globals.h" |
| 10 #include "vm/handles.h" | 13 #include "vm/handles.h" |
| 11 #include "vm/os_thread.h" | 14 #include "vm/os_thread.h" |
| 12 #include "vm/store_buffer.h" | 15 #include "vm/store_buffer.h" |
| 13 #include "vm/runtime_entry_list.h" | 16 #include "vm/runtime_entry_list.h" |
| 14 | 17 |
| 15 namespace dart { | 18 namespace dart { |
| 16 | 19 |
| 17 class AbstractType; | 20 class AbstractType; |
| 18 class ApiLocalScope; | 21 class ApiLocalScope; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 | 139 |
| 137 // Empties the store buffer block into the isolate. | 140 // Empties the store buffer block into the isolate. |
| 138 void PrepareForGC(); | 141 void PrepareForGC(); |
| 139 | 142 |
| 140 // OSThread corresponding to this thread. | 143 // OSThread corresponding to this thread. |
| 141 OSThread* os_thread() const { return os_thread_; } | 144 OSThread* os_thread() const { return os_thread_; } |
| 142 void set_os_thread(OSThread* os_thread) { | 145 void set_os_thread(OSThread* os_thread) { |
| 143 os_thread_ = os_thread; | 146 os_thread_ = os_thread; |
| 144 } | 147 } |
| 145 | 148 |
| 149 // Monitor corresponding to this thread. | |
| 150 Monitor* thread_lock() const { return thread_lock_; } | |
| 151 | |
| 146 // The topmost zone used for allocation in this thread. | 152 // The topmost zone used for allocation in this thread. |
| 147 Zone* zone() const { return zone_; } | 153 Zone* zone() const { return zone_; } |
| 148 | 154 |
| 149 // The reusable api local scope for this thread. | 155 // The reusable api local scope for this thread. |
| 150 ApiLocalScope* api_reusable_scope() const { return api_reusable_scope_; } | 156 ApiLocalScope* api_reusable_scope() const { return api_reusable_scope_; } |
| 151 void set_api_reusable_scope(ApiLocalScope* value) { | 157 void set_api_reusable_scope(ApiLocalScope* value) { |
| 152 ASSERT(value == NULL || api_reusable_scope_ == NULL); | 158 ASSERT(value == NULL || api_reusable_scope_ == NULL); |
| 153 api_reusable_scope_ = value; | 159 api_reusable_scope_ = value; |
| 154 } | 160 } |
| 155 | 161 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 #if defined(TESTING) | 207 #if defined(TESTING) |
| 202 bool StoreBufferContains(RawObject* obj) const { | 208 bool StoreBufferContains(RawObject* obj) const { |
| 203 return store_buffer_block_->Contains(obj); | 209 return store_buffer_block_->Contains(obj); |
| 204 } | 210 } |
| 205 #endif | 211 #endif |
| 206 void StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy); | 212 void StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy); |
| 207 static intptr_t store_buffer_block_offset() { | 213 static intptr_t store_buffer_block_offset() { |
| 208 return OFFSET_OF(Thread, store_buffer_block_); | 214 return OFFSET_OF(Thread, store_buffer_block_); |
| 209 } | 215 } |
| 210 | 216 |
| 211 uword top_exit_frame_info() const { return top_exit_frame_info_; } | 217 uword top_exit_frame_info() const { |
| 218 return top_exit_frame_info_; | |
| 219 } | |
| 212 static intptr_t top_exit_frame_info_offset() { | 220 static intptr_t top_exit_frame_info_offset() { |
| 213 return OFFSET_OF(Thread, top_exit_frame_info_); | 221 return OFFSET_OF(Thread, top_exit_frame_info_); |
| 214 } | 222 } |
| 215 | 223 |
| 216 StackResource* top_resource() const { return top_resource_; } | 224 StackResource* top_resource() const { return top_resource_; } |
| 217 void set_top_resource(StackResource* value) { | 225 void set_top_resource(StackResource* value) { |
| 218 top_resource_ = value; | 226 top_resource_ = value; |
| 219 } | 227 } |
| 220 static intptr_t top_resource_offset() { | 228 static intptr_t top_resource_offset() { |
| 221 return OFFSET_OF(Thread, top_resource_); | 229 return OFFSET_OF(Thread, top_resource_); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 348 uword vm_tag() const { | 356 uword vm_tag() const { |
| 349 return vm_tag_; | 357 return vm_tag_; |
| 350 } | 358 } |
| 351 void set_vm_tag(uword tag) { | 359 void set_vm_tag(uword tag) { |
| 352 vm_tag_ = tag; | 360 vm_tag_ = tag; |
| 353 } | 361 } |
| 354 static intptr_t vm_tag_offset() { | 362 static intptr_t vm_tag_offset() { |
| 355 return OFFSET_OF(Thread, vm_tag_); | 363 return OFFSET_OF(Thread, vm_tag_); |
| 356 } | 364 } |
| 357 | 365 |
| 366 RawGrowableObjectArray* pending_functions(); | |
| 367 | |
| 358 #if defined(DEBUG) | 368 #if defined(DEBUG) |
| 359 #define REUSABLE_HANDLE_SCOPE_ACCESSORS(object) \ | 369 #define REUSABLE_HANDLE_SCOPE_ACCESSORS(object) \ |
| 360 void set_reusable_##object##_handle_scope_active(bool value) { \ | 370 void set_reusable_##object##_handle_scope_active(bool value) { \ |
| 361 reusable_##object##_handle_scope_active_ = value; \ | 371 reusable_##object##_handle_scope_active_ = value; \ |
| 362 } \ | 372 } \ |
| 363 bool reusable_##object##_handle_scope_active() const { \ | 373 bool reusable_##object##_handle_scope_active() const { \ |
| 364 return reusable_##object##_handle_scope_active_; \ | 374 return reusable_##object##_handle_scope_active_; \ |
| 365 } | 375 } |
| 366 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_ACCESSORS) | 376 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_ACCESSORS) |
| 367 #undef REUSABLE_HANDLE_SCOPE_ACCESSORS | 377 #undef REUSABLE_HANDLE_SCOPE_ACCESSORS |
| 368 | 378 |
| 369 bool IsAnyReusableHandleScopeActive() const { | 379 bool IsAnyReusableHandleScopeActive() const { |
| 370 #define IS_REUSABLE_HANDLE_SCOPE_ACTIVE(object) \ | 380 #define IS_REUSABLE_HANDLE_SCOPE_ACTIVE(object) \ |
| 371 if (reusable_##object##_handle_scope_active_) return true; | 381 if (reusable_##object##_handle_scope_active_) return true; |
| 372 REUSABLE_HANDLE_LIST(IS_REUSABLE_HANDLE_SCOPE_ACTIVE) | 382 REUSABLE_HANDLE_LIST(IS_REUSABLE_HANDLE_SCOPE_ACTIVE) |
| 373 return false; | 383 return false; |
| 374 #undef IS_REUSABLE_HANDLE_SCOPE_ACTIVE | 384 #undef IS_REUSABLE_HANDLE_SCOPE_ACTIVE |
| 375 } | 385 } |
| 376 #endif // defined(DEBUG) | 386 #endif // defined(DEBUG) |
| 377 | 387 |
| 378 void ClearReusableHandles(); | 388 void ClearReusableHandles(); |
| 379 | 389 |
| 380 #define REUSABLE_HANDLE(object) \ | 390 #define REUSABLE_HANDLE(object) \ |
| 381 object& object##Handle() const { \ | 391 object& object##Handle() const { \ |
| 382 return *object##_handle_; \ | 392 return *object##_handle_; \ |
| 383 } | 393 } |
| 384 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE) | 394 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE) |
| 385 #undef REUSABLE_HANDLE | 395 #undef REUSABLE_HANDLE |
| 386 | 396 |
| 387 RawGrowableObjectArray* pending_functions(); | 397 /* |
| 398 * Fields used to support safepointing a thread. | |
| 399 * | |
| 400 * - Bit 0 of the safepoint_state_ field is used to indicate if the thread is | |
| 401 * already at a safepoint, | |
| 402 * - Bit 1 of the safepoint_state_ field is used to indicate if a safepoint | |
| 403 * operation is requested for this thread. | |
| 404 * - Bit 2 of the safepoint_state_ field is used to indicate that the thread | |
| 405 * is blocked for the safepoint operation to complete. | |
| 406 * | |
| 407 * The safepoint execution state (described above) for a thread is stored in | |
| 408 * in the execution_state_ field. | |
| 409 * Potential execution states a thread could be in: | |
| 410 * kThreadInGenerated - The thread is running jitted dart/stub code. | |
| 411 * kThreadInVM - The thread is running VM code. | |
| 412 * kThreadInNative - The thread is running native code. | |
| 413 * kThreadInBlockedState - The thread is blocked waiting for a resource. | |
| 414 */ | |
| 415 static intptr_t safepoint_state_offset() { | |
| 416 return OFFSET_OF(Thread, safepoint_state_); | |
| 417 } | |
| 418 static bool IsAtSafepoint(uint32_t state) { | |
| 419 return AtSafepointField::decode(state); | |
| 420 } | |
| 421 bool IsAtSafepoint() const { | |
| 422 return AtSafepointField::decode(safepoint_state_); | |
| 423 } | |
| 424 static uint32_t SetAtSafepoint(bool value, uint32_t state) { | |
| 425 return AtSafepointField::update(value, state); | |
| 426 } | |
| 427 void SetAtSafepoint(bool value) { | |
| 428 ASSERT(thread_lock()->IsOwnedByCurrentThread()); | |
| 429 safepoint_state_ = AtSafepointField::update(value, safepoint_state_); | |
| 430 } | |
| 431 bool IsSafepointRequested() const { | |
| 432 return SafepointRequestedField::decode(safepoint_state_); | |
| 433 } | |
| 434 static uint32_t SetSafepointRequested(bool value, uint32_t state) { | |
| 435 return SafepointRequestedField::update(value, state); | |
| 436 } | |
| 437 uint32_t SetSafepointRequested(bool value) { | |
| 438 ASSERT(thread_lock()->IsOwnedByCurrentThread()); | |
| 439 uint32_t old_state; | |
| 440 uint32_t new_state; | |
| 441 do { | |
| 442 old_state = safepoint_state_; | |
| 443 new_state = SafepointRequestedField::update(value, old_state); | |
| 444 } while (AtomicOperations::CompareAndSwapUint32(&safepoint_state_, | |
| 445 old_state, | |
| 446 new_state) != old_state); | |
| 447 return old_state; | |
| 448 } | |
| 449 static bool IsBlockedForSafepoint(uint32_t state) { | |
| 450 return BlockedForSafepointField::decode(state); | |
| 451 } | |
| 452 bool IsBlockedForSafepoint() const { | |
| 453 return BlockedForSafepointField::decode(safepoint_state_); | |
| 454 } | |
| 455 void SetBlockedForSafepoint(bool value) { | |
| 456 ASSERT(thread_lock()->IsOwnedByCurrentThread()); | |
| 457 safepoint_state_ = | |
| 458 BlockedForSafepointField::update(value, safepoint_state_); | |
| 459 } | |
| 460 | |
| 461 enum ExecutionState { | |
| 462 kThreadInVM = 0, | |
| 463 kThreadInGenerated, | |
| 464 kThreadInNative, | |
| 465 kThreadInBlockedState | |
| 466 }; | |
| 467 | |
| 468 ExecutionState execution_state() const { | |
| 469 return static_cast<ExecutionState>(execution_state_); | |
| 470 } | |
| 471 void set_execution_state(ExecutionState state) { | |
| 472 execution_state_ = static_cast<uint32_t>(state); | |
| 473 } | |
| 474 static intptr_t execution_state_offset() { | |
| 475 return OFFSET_OF(Thread, execution_state_); | |
| 476 } | |
| 477 | |
| 478 void EnterSafepoint() { | |
| 479 // First try a fast update of the thread state to indicate it is at a | |
| 480 // safepoint. | |
| 481 uint32_t new_state = SetAtSafepoint(true, 0); | |
| 482 uword addr = reinterpret_cast<uword>(this) + safepoint_state_offset(); | |
| 483 if (AtomicOperations::CompareAndSwapUint32( | |
| 484 reinterpret_cast<uint32_t*>(addr), 0, new_state) != 0) { | |
| 485 // Fast update failed which means we could potentially be in the middle | |
| 486 // of a safepoint operation. | |
| 487 EnterSafepointUsingLock(); | |
| 488 } | |
| 489 } | |
| 490 | |
| 491 void ExitSafepoint() { | |
| 492 // First try a fast update of the thread state to indicate it is not at a | |
| 493 // safepoint anymore. | |
| 494 uint32_t old_state = SetAtSafepoint(true, 0); | |
| 495 uword addr = reinterpret_cast<uword>(this) + safepoint_state_offset(); | |
| 496 if (AtomicOperations::CompareAndSwapUint32( | |
| 497 reinterpret_cast<uint32_t*>(addr), old_state, 0) != old_state) { | |
| 498 // Fast update failed which means we could potentially be in the middle | |
| 499 // of a safepoint operation. | |
| 500 ExitSafepointUsingLock(); | |
| 501 } | |
| 502 } | |
| 503 | |
| 504 Thread* next() const { return next_; } | |
| 388 | 505 |
| 389 // Visit all object pointers. | 506 // Visit all object pointers. |
| 390 void VisitObjectPointers(ObjectPointerVisitor* visitor); | 507 void VisitObjectPointers(ObjectPointerVisitor* visitor); |
| 391 | 508 |
| 392 bool IsValidLocalHandle(Dart_Handle object) const; | 509 bool IsValidLocalHandle(Dart_Handle object) const; |
| 393 int CountLocalHandles() const; | 510 int CountLocalHandles() const; |
| 394 int ZoneSizeInBytes() const; | 511 int ZoneSizeInBytes() const; |
| 395 void UnwindScopes(uword stack_marker); | 512 void UnwindScopes(uword stack_marker); |
| 396 | 513 |
| 397 void InitVMConstants(); | 514 void InitVMConstants(); |
| 398 | 515 |
| 399 private: | 516 private: |
| 400 template<class T> T* AllocateReusableHandle(); | 517 template<class T> T* AllocateReusableHandle(); |
| 401 | 518 |
| 402 OSThread* os_thread_; | 519 OSThread* os_thread_; |
| 520 Monitor* thread_lock_; | |
| 403 Isolate* isolate_; | 521 Isolate* isolate_; |
| 404 Heap* heap_; | 522 Heap* heap_; |
| 405 Zone* zone_; | 523 Zone* zone_; |
| 406 ApiLocalScope* api_reusable_scope_; | 524 ApiLocalScope* api_reusable_scope_; |
| 407 ApiLocalScope* api_top_scope_; | 525 ApiLocalScope* api_top_scope_; |
| 408 uword top_exit_frame_info_; | 526 uword top_exit_frame_info_; |
| 409 StackResource* top_resource_; | 527 StackResource* top_resource_; |
| 410 LongJumpScope* long_jump_base_; | 528 LongJumpScope* long_jump_base_; |
| 411 StoreBufferBlock* store_buffer_block_; | 529 StoreBufferBlock* store_buffer_block_; |
| 412 int32_t no_callback_scope_depth_; | 530 int32_t no_callback_scope_depth_; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 445 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_FIELDS) | 563 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_FIELDS) |
| 446 #undef REUSABLE_HANDLE_FIELDS | 564 #undef REUSABLE_HANDLE_FIELDS |
| 447 | 565 |
| 448 #if defined(DEBUG) | 566 #if defined(DEBUG) |
| 449 #define REUSABLE_HANDLE_SCOPE_VARIABLE(object) \ | 567 #define REUSABLE_HANDLE_SCOPE_VARIABLE(object) \ |
| 450 bool reusable_##object##_handle_scope_active_; | 568 bool reusable_##object##_handle_scope_active_; |
| 451 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_VARIABLE); | 569 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_VARIABLE); |
| 452 #undef REUSABLE_HANDLE_SCOPE_VARIABLE | 570 #undef REUSABLE_HANDLE_SCOPE_VARIABLE |
| 453 #endif // defined(DEBUG) | 571 #endif // defined(DEBUG) |
| 454 | 572 |
| 573 class AtSafepointField : public BitField<bool, 0, 1> {}; | |
| 574 class SafepointRequestedField : public BitField<bool, 1, 1> {}; | |
| 575 class BlockedForSafepointField : public BitField<bool, 2, 1> {}; | |
| 576 uint32_t safepoint_state_; | |
|
rmacnak
2016/01/08 21:51:17
Check this in NoSafepointScope.
siva
2016/01/12 21:26:22
I have added a check in SafepointOperationScope to
| |
| 577 uint32_t execution_state_; | |
|
zra
2016/01/08 23:32:07
Is it possible to check that this is correct in th
siva
2016/01/12 21:26:22
Added a note to myself for this. I do not want to
| |
| 578 | |
| 455 Thread* next_; // Used to chain the thread structures in an isolate. | 579 Thread* next_; // Used to chain the thread structures in an isolate. |
| 456 | 580 |
| 457 explicit Thread(Isolate* isolate); | 581 explicit Thread(Isolate* isolate); |
| 458 | 582 |
| 459 void StoreBufferRelease( | 583 void StoreBufferRelease( |
| 460 StoreBuffer::ThresholdPolicy policy = StoreBuffer::kCheckThreshold); | 584 StoreBuffer::ThresholdPolicy policy = StoreBuffer::kCheckThreshold); |
| 461 void StoreBufferAcquire(); | 585 void StoreBufferAcquire(); |
| 462 | 586 |
| 463 void set_zone(Zone* zone) { | 587 void set_zone(Zone* zone) { |
| 464 zone_ = zone; | 588 zone_ = zone; |
| 465 } | 589 } |
| 466 | 590 |
| 467 void set_top_exit_frame_info(uword top_exit_frame_info) { | 591 void set_top_exit_frame_info(uword top_exit_frame_info) { |
| 468 top_exit_frame_info_ = top_exit_frame_info; | 592 top_exit_frame_info_ = top_exit_frame_info; |
| 469 } | 593 } |
| 470 | 594 |
| 595 void set_safepoint_state(uint32_t value) { | |
| 596 safepoint_state_ = value; | |
| 597 } | |
| 598 void EnterSafepointUsingLock(); | |
| 599 void ExitSafepointUsingLock(); | |
| 600 | |
| 471 static void SetCurrent(Thread* current) { | 601 static void SetCurrent(Thread* current) { |
| 472 OSThread::SetCurrentTLS(reinterpret_cast<uword>(current)); | 602 OSThread::SetCurrentTLS(reinterpret_cast<uword>(current)); |
| 473 } | 603 } |
| 474 | 604 |
| 475 #define REUSABLE_FRIEND_DECLARATION(name) \ | 605 #define REUSABLE_FRIEND_DECLARATION(name) \ |
| 476 friend class Reusable##name##HandleScope; | 606 friend class Reusable##name##HandleScope; |
| 477 REUSABLE_HANDLE_LIST(REUSABLE_FRIEND_DECLARATION) | 607 REUSABLE_HANDLE_LIST(REUSABLE_FRIEND_DECLARATION) |
| 478 #undef REUSABLE_FRIEND_DECLARATION | 608 #undef REUSABLE_FRIEND_DECLARATION |
| 479 | 609 |
| 480 friend class ApiZone; | 610 friend class ApiZone; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 496 // Disable thread interrupts. | 626 // Disable thread interrupts. |
| 497 class DisableThreadInterruptsScope : public StackResource { | 627 class DisableThreadInterruptsScope : public StackResource { |
| 498 public: | 628 public: |
| 499 explicit DisableThreadInterruptsScope(Thread* thread); | 629 explicit DisableThreadInterruptsScope(Thread* thread); |
| 500 ~DisableThreadInterruptsScope(); | 630 ~DisableThreadInterruptsScope(); |
| 501 }; | 631 }; |
| 502 | 632 |
| 503 } // namespace dart | 633 } // namespace dart |
| 504 | 634 |
| 505 #endif // VM_THREAD_H_ | 635 #endif // VM_THREAD_H_ |
| OLD | NEW |