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 |