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
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_THREAD_H_
6#define RUNTIME_VM_THREAD_H_
7
8#if defined(SHOULD_NOT_INCLUDE_RUNTIME)
9#error "Should not include runtime"
10#endif
11
12#include "include/dart_api.h"
13#include "platform/assert.h"
14#include "platform/atomic.h"
15#include "platform/safe_stack.h"
16#include "vm/bitfield.h"
17#include "vm/compiler/runtime_api.h"
18#include "vm/constants.h"
19#include "vm/globals.h"
20#include "vm/handles.h"
21#include "vm/heap/pointer_block.h"
22#include "vm/os_thread.h"
23#include "vm/random.h"
24#include "vm/runtime_entry_list.h"
25#include "vm/thread_stack_resource.h"
26#include "vm/thread_state.h"
27namespace dart {
28
29class AbstractType;
30class ApiLocalScope;
31class Array;
32class CompilerState;
33class Class;
34class Code;
35class Bytecode;
36class Error;
37class ExceptionHandlers;
38class Field;
39class FieldTable;
40class Function;
41class GrowableObjectArray;
42class HandleScope;
43class Heap;
44class HierarchyInfo;
45class Instance;
46class Interpreter;
47class Isolate;
48class IsolateGroup;
49class Library;
50class Object;
51class OSThread;
52class JSONObject;
53class PcDescriptors;
54class RuntimeEntry;
55class Smi;
56class StackResource;
57class StackTrace;
58class String;
59class TimelineStream;
60class TypeArguments;
61class TypeParameter;
62class TypeUsageInfo;
63class Zone;
64
65namespace compiler {
66namespace target {
67class Thread;
68} // namespace target
69} // namespace compiler
70
71#define REUSABLE_HANDLE_LIST(V) \
72 V(AbstractType) \
73 V(Array) \
74 V(Class) \
75 V(Code) \
76 V(Bytecode) \
77 V(Error) \
78 V(ExceptionHandlers) \
79 V(Field) \
80 V(Function) \
81 V(GrowableObjectArray) \
82 V(Instance) \
83 V(Library) \
84 V(Object) \
85 V(PcDescriptors) \
86 V(Smi) \
87 V(String) \
88 V(TypeArguments) \
89 V(TypeParameter)
90
91#define CACHED_VM_STUBS_LIST(V) \
92 V(CodePtr, write_barrier_code_, StubCode::WriteBarrier().raw(), nullptr) \
93 V(CodePtr, array_write_barrier_code_, StubCode::ArrayWriteBarrier().raw(), \
94 nullptr) \
95 V(CodePtr, fix_callers_target_code_, StubCode::FixCallersTarget().raw(), \
96 nullptr) \
97 V(CodePtr, fix_allocation_stub_code_, \
98 StubCode::FixAllocationStubTarget().raw(), nullptr) \
99 V(CodePtr, invoke_dart_code_stub_, StubCode::InvokeDartCode().raw(), \
100 nullptr) \
101 V(CodePtr, invoke_dart_code_from_bytecode_stub_, \
102 StubCode::InvokeDartCodeFromBytecode().raw(), nullptr) \
103 V(CodePtr, call_to_runtime_stub_, StubCode::CallToRuntime().raw(), nullptr) \
104 V(CodePtr, null_error_shared_without_fpu_regs_stub_, \
105 StubCode::NullErrorSharedWithoutFPURegs().raw(), nullptr) \
106 V(CodePtr, null_error_shared_with_fpu_regs_stub_, \
107 StubCode::NullErrorSharedWithFPURegs().raw(), nullptr) \
108 V(CodePtr, null_arg_error_shared_without_fpu_regs_stub_, \
109 StubCode::NullArgErrorSharedWithoutFPURegs().raw(), nullptr) \
110 V(CodePtr, null_arg_error_shared_with_fpu_regs_stub_, \
111 StubCode::NullArgErrorSharedWithFPURegs().raw(), nullptr) \
112 V(CodePtr, null_cast_error_shared_without_fpu_regs_stub_, \
113 StubCode::NullCastErrorSharedWithoutFPURegs().raw(), nullptr) \
114 V(CodePtr, null_cast_error_shared_with_fpu_regs_stub_, \
115 StubCode::NullCastErrorSharedWithFPURegs().raw(), nullptr) \
116 V(CodePtr, range_error_shared_without_fpu_regs_stub_, \
117 StubCode::RangeErrorSharedWithoutFPURegs().raw(), nullptr) \
118 V(CodePtr, range_error_shared_with_fpu_regs_stub_, \
119 StubCode::RangeErrorSharedWithFPURegs().raw(), nullptr) \
120 V(CodePtr, allocate_mint_with_fpu_regs_stub_, \
121 StubCode::AllocateMintSharedWithFPURegs().raw(), nullptr) \
122 V(CodePtr, allocate_mint_without_fpu_regs_stub_, \
123 StubCode::AllocateMintSharedWithoutFPURegs().raw(), nullptr) \
124 V(CodePtr, allocate_object_stub_, StubCode::AllocateObject().raw(), nullptr) \
125 V(CodePtr, allocate_object_parameterized_stub_, \
126 StubCode::AllocateObjectParameterized().raw(), nullptr) \
127 V(CodePtr, allocate_object_slow_stub_, StubCode::AllocateObjectSlow().raw(), \
128 nullptr) \
129 V(CodePtr, stack_overflow_shared_without_fpu_regs_stub_, \
130 StubCode::StackOverflowSharedWithoutFPURegs().raw(), nullptr) \
131 V(CodePtr, stack_overflow_shared_with_fpu_regs_stub_, \
132 StubCode::StackOverflowSharedWithFPURegs().raw(), nullptr) \
133 V(CodePtr, switchable_call_miss_stub_, StubCode::SwitchableCallMiss().raw(), \
134 nullptr) \
135 V(CodePtr, throw_stub_, StubCode::Throw().raw(), nullptr) \
136 V(CodePtr, re_throw_stub_, StubCode::Throw().raw(), nullptr) \
137 V(CodePtr, assert_boolean_stub_, StubCode::AssertBoolean().raw(), nullptr) \
138 V(CodePtr, optimize_stub_, StubCode::OptimizeFunction().raw(), nullptr) \
139 V(CodePtr, deoptimize_stub_, StubCode::Deoptimize().raw(), nullptr) \
140 V(CodePtr, lazy_deopt_from_return_stub_, \
141 StubCode::DeoptimizeLazyFromReturn().raw(), nullptr) \
142 V(CodePtr, lazy_deopt_from_throw_stub_, \
143 StubCode::DeoptimizeLazyFromThrow().raw(), nullptr) \
144 V(CodePtr, slow_type_test_stub_, StubCode::SlowTypeTest().raw(), nullptr) \
145 V(CodePtr, lazy_specialize_type_test_stub_, \
146 StubCode::LazySpecializeTypeTest().raw(), nullptr) \
147 V(CodePtr, enter_safepoint_stub_, StubCode::EnterSafepoint().raw(), nullptr) \
148 V(CodePtr, exit_safepoint_stub_, StubCode::ExitSafepoint().raw(), nullptr) \
149 V(CodePtr, call_native_through_safepoint_stub_, \
150 StubCode::CallNativeThroughSafepoint().raw(), nullptr)
151
152#define CACHED_NON_VM_STUB_LIST(V) \
153 V(ObjectPtr, object_null_, Object::null(), nullptr) \
154 V(BoolPtr, bool_true_, Object::bool_true().raw(), nullptr) \
155 V(BoolPtr, bool_false_, Object::bool_false().raw(), nullptr)
156
157// List of VM-global objects/addresses cached in each Thread object.
158// Important: constant false must immediately follow constant true.
159#define CACHED_VM_OBJECTS_LIST(V) \
160 CACHED_NON_VM_STUB_LIST(V) \
161 CACHED_VM_STUBS_LIST(V)
162
163// This assertion marks places which assume that boolean false immediate
164// follows bool true in the CACHED_VM_OBJECTS_LIST
165#define ASSERT_BOOL_FALSE_FOLLOWS_BOOL_TRUE() \
166 ASSERT((Thread::bool_true_offset() + kWordSize) == \
167 Thread::bool_false_offset());
168
169#define CACHED_VM_STUBS_ADDRESSES_LIST(V) \
170 V(uword, write_barrier_entry_point_, StubCode::WriteBarrier().EntryPoint(), \
171 0) \
172 V(uword, array_write_barrier_entry_point_, \
173 StubCode::ArrayWriteBarrier().EntryPoint(), 0) \
174 V(uword, call_to_runtime_entry_point_, \
175 StubCode::CallToRuntime().EntryPoint(), 0) \
176 V(uword, allocate_mint_with_fpu_regs_entry_point_, \
177 StubCode::AllocateMintSharedWithFPURegs().EntryPoint(), 0) \
178 V(uword, allocate_mint_without_fpu_regs_entry_point_, \
179 StubCode::AllocateMintSharedWithoutFPURegs().EntryPoint(), 0) \
180 V(uword, allocate_object_entry_point_, \
181 StubCode::AllocateObject().EntryPoint(), 0) \
182 V(uword, allocate_object_parameterized_entry_point_, \
183 StubCode::AllocateObjectParameterized().EntryPoint(), 0) \
184 V(uword, allocate_object_slow_entry_point_, \
185 StubCode::AllocateObjectSlow().EntryPoint(), 0) \
186 V(uword, stack_overflow_shared_without_fpu_regs_entry_point_, \
187 StubCode::StackOverflowSharedWithoutFPURegs().EntryPoint(), 0) \
188 V(uword, stack_overflow_shared_with_fpu_regs_entry_point_, \
189 StubCode::StackOverflowSharedWithFPURegs().EntryPoint(), 0) \
190 V(uword, megamorphic_call_checked_entry_, \
191 StubCode::MegamorphicCall().EntryPoint(), 0) \
192 V(uword, switchable_call_miss_entry_, \
193 StubCode::SwitchableCallMiss().EntryPoint(), 0) \
194 V(uword, optimize_entry_, StubCode::OptimizeFunction().EntryPoint(), 0) \
195 V(uword, deoptimize_entry_, StubCode::Deoptimize().EntryPoint(), 0) \
196 V(uword, call_native_through_safepoint_entry_point_, \
197 StubCode::CallNativeThroughSafepoint().EntryPoint(), 0) \
198 V(uword, slow_type_test_entry_point_, StubCode::SlowTypeTest().EntryPoint(), \
199 0)
200
201#define CACHED_ADDRESSES_LIST(V) \
202 CACHED_VM_STUBS_ADDRESSES_LIST(V) \
203 V(uword, bootstrap_native_wrapper_entry_point_, \
204 NativeEntry::BootstrapNativeCallWrapperEntry(), 0) \
205 V(uword, no_scope_native_wrapper_entry_point_, \
206 NativeEntry::NoScopeNativeCallWrapperEntry(), 0) \
207 V(uword, auto_scope_native_wrapper_entry_point_, \
208 NativeEntry::AutoScopeNativeCallWrapperEntry(), 0) \
209 V(uword, interpret_call_entry_point_, RuntimeEntry::InterpretCallEntry(), 0) \
210 V(StringPtr*, predefined_symbols_address_, Symbols::PredefinedAddress(), \
211 NULL) \
212 V(uword, double_nan_address_, reinterpret_cast<uword>(&double_nan_constant), \
213 0) \
214 V(uword, double_negate_address_, \
215 reinterpret_cast<uword>(&double_negate_constant), 0) \
216 V(uword, double_abs_address_, reinterpret_cast<uword>(&double_abs_constant), \
217 0) \
218 V(uword, float_not_address_, reinterpret_cast<uword>(&float_not_constant), \
219 0) \
220 V(uword, float_negate_address_, \
221 reinterpret_cast<uword>(&float_negate_constant), 0) \
222 V(uword, float_absolute_address_, \
223 reinterpret_cast<uword>(&float_absolute_constant), 0) \
224 V(uword, float_zerow_address_, \
225 reinterpret_cast<uword>(&float_zerow_constant), 0)
226
227#define CACHED_CONSTANTS_LIST(V) \
228 CACHED_VM_OBJECTS_LIST(V) \
229 CACHED_ADDRESSES_LIST(V)
230
231enum class ValidationPolicy {
232 kValidateFrames = 0,
233 kDontValidateFrames = 1,
234};
235
236// A VM thread; may be executing Dart code or performing helper tasks like
237// garbage collection or compilation. The Thread structure associated with
238// a thread is allocated by EnsureInit before entering an isolate, and destroyed
239// automatically when the underlying OS thread exits. NOTE: On Windows, CleanUp
240// must currently be called manually (issue 23474).
241class Thread : public ThreadState {
242 public:
243 // The kind of task this thread is performing. Sampled by the profiler.
244 enum TaskKind {
245 kUnknownTask = 0x0,
246 kMutatorTask = 0x1,
247 kCompilerTask = 0x2,
248 kMarkerTask = 0x4,
249 kSweeperTask = 0x8,
250 kCompactorTask = 0x10,
251 kScavengerTask = 0x20,
252 };
253 // Converts a TaskKind to its corresponding C-String name.
254 static const char* TaskKindToCString(TaskKind kind);
255
256 ~Thread();
257
258 // The currently executing thread, or NULL if not yet initialized.
259 static Thread* Current() {
260#if defined(HAS_C11_THREAD_LOCAL)
261 return static_cast<Thread*>(OSThread::CurrentVMThread());
262#else
263 BaseThread* thread = OSThread::GetCurrentTLS();
264 if (thread == NULL || thread->is_os_thread()) {
265 return NULL;
266 }
267 return static_cast<Thread*>(thread);
268#endif
269 }
270
271 // Makes the current thread enter 'isolate'.
272 static bool EnterIsolate(Isolate* isolate);
273 // Makes the current thread exit its isolate.
274 static void ExitIsolate();
275
276 // A VM thread other than the main mutator thread can enter an isolate as a
277 // "helper" to gain limited concurrent access to the isolate. One example is
278 // SweeperTask (which uses the class table, which is copy-on-write).
279 // TODO(koda): Properly synchronize heap access to expand allowed operations.
280 static bool EnterIsolateAsHelper(Isolate* isolate,
281 TaskKind kind,
282 bool bypass_safepoint = false);
283 static void ExitIsolateAsHelper(bool bypass_safepoint = false);
284
285 static bool EnterIsolateGroupAsHelper(IsolateGroup* isolate_group,
286 TaskKind kind,
287 bool bypass_safepoint);
288 static void ExitIsolateGroupAsHelper(bool bypass_safepoint);
289
290 // Empties the store buffer block into the isolate.
291 void ReleaseStoreBuffer();
292 void AcquireMarkingStack();
293 void ReleaseMarkingStack();
294
295 void SetStackLimit(uword value);
296 void ClearStackLimit();
297
298 // Access to the current stack limit for generated code. Either the true OS
299 // thread's stack limit minus some headroom, or a special value to trigger
300 // interrupts.
301 uword stack_limit_address() const {
302 return reinterpret_cast<uword>(&stack_limit_);
303 }
304 static intptr_t stack_limit_offset() {
305 return OFFSET_OF(Thread, stack_limit_);
306 }
307
308 // The true stack limit for this OS thread.
309 static intptr_t saved_stack_limit_offset() {
310 return OFFSET_OF(Thread, saved_stack_limit_);
311 }
312 uword saved_stack_limit() const { return saved_stack_limit_; }
313
314#if defined(USING_SAFE_STACK)
315 uword saved_safestack_limit() const { return saved_safestack_limit_; }
316 void set_saved_safestack_limit(uword limit) {
317 saved_safestack_limit_ = limit;
318 }
319#endif
320 static uword saved_shadow_call_stack_offset() {
321 return OFFSET_OF(Thread, saved_shadow_call_stack_);
322 }
323
324 // Stack overflow flags
325 enum {
326 kOsrRequest = 0x1, // Current stack overflow caused by OSR request.
327 };
328
329 uword write_barrier_mask() const { return write_barrier_mask_; }
330
331 static intptr_t write_barrier_mask_offset() {
332 return OFFSET_OF(Thread, write_barrier_mask_);
333 }
334 static intptr_t stack_overflow_flags_offset() {
335 return OFFSET_OF(Thread, stack_overflow_flags_);
336 }
337
338 int32_t IncrementAndGetStackOverflowCount() {
339 return ++stack_overflow_count_;
340 }
341
342 static uword stack_overflow_shared_stub_entry_point_offset(bool fpu_regs) {
343 return fpu_regs
344 ? stack_overflow_shared_with_fpu_regs_entry_point_offset()
345 : stack_overflow_shared_without_fpu_regs_entry_point_offset();
346 }
347
348 static intptr_t safepoint_state_offset() {
349 return OFFSET_OF(Thread, safepoint_state_);
350 }
351
352 static intptr_t callback_code_offset() {
353 return OFFSET_OF(Thread, ffi_callback_code_);
354 }
355
356 // Tag state is maintained on transitions.
357 enum {
358 // Always true in generated state.
359 kDidNotExit = 0,
360 // The VM did exit the generated state through FFI.
361 // This can be true in both native and VM state.
362 kExitThroughFfi = 1,
363 // The VM exited the generated state through FFI.
364 // This can be true in both native and VM state.
365 kExitThroughRuntimeCall = 2,
366 };
367
368 static intptr_t exit_through_ffi_offset() {
369 return OFFSET_OF(Thread, exit_through_ffi_);
370 }
371
372 TaskKind task_kind() const { return task_kind_; }
373
374 // Retrieves and clears the stack overflow flags. These are set by
375 // the generated code before the slow path runtime routine for a
376 // stack overflow is called.
377 uword GetAndClearStackOverflowFlags();
378
379 // Interrupt bits.
380 enum {
381 kVMInterrupt = 0x1, // Internal VM checks: safepoints, store buffers, etc.
382 kMessageInterrupt = 0x2, // An interrupt to process an out of band message.
383
384 kInterruptsMask = (kVMInterrupt | kMessageInterrupt),
385 };
386
387 void ScheduleInterrupts(uword interrupt_bits);
388 void ScheduleInterruptsLocked(uword interrupt_bits);
389 ErrorPtr HandleInterrupts();
390 uword GetAndClearInterrupts();
391 bool HasScheduledInterrupts() const {
392 return (stack_limit_ & kInterruptsMask) != 0;
393 }
394
395 // Monitor corresponding to this thread.
396 Monitor* thread_lock() const { return &thread_lock_; }
397
398 // The reusable api local scope for this thread.
399 ApiLocalScope* api_reusable_scope() const { return api_reusable_scope_; }
400 void set_api_reusable_scope(ApiLocalScope* value) {
401 ASSERT(value == NULL || api_reusable_scope_ == NULL);
402 api_reusable_scope_ = value;
403 }
404
405 // The api local scope for this thread, this where all local handles
406 // are allocated.
407 ApiLocalScope* api_top_scope() const { return api_top_scope_; }
408 void set_api_top_scope(ApiLocalScope* value) { api_top_scope_ = value; }
409 static intptr_t api_top_scope_offset() {
410 return OFFSET_OF(Thread, api_top_scope_);
411 }
412
413 void EnterApiScope();
414 void ExitApiScope();
415
416 // The isolate that this thread is operating on, or nullptr if none.
417 Isolate* isolate() const { return isolate_; }
418 static intptr_t isolate_offset() { return OFFSET_OF(Thread, isolate_); }
419
420 // The isolate group that this thread is operating on, or nullptr if none.
421 IsolateGroup* isolate_group() const { return isolate_group_; }
422
423 static intptr_t field_table_values_offset() {
424 return OFFSET_OF(Thread, field_table_values_);
425 }
426
427 bool IsMutatorThread() const { return is_mutator_thread_; }
428
429 bool CanCollectGarbage() const;
430
431 // Offset of Dart TimelineStream object.
432 static intptr_t dart_stream_offset() {
433 return OFFSET_OF(Thread, dart_stream_);
434 }
435
436 // Is |this| executing Dart code?
437 bool IsExecutingDartCode() const;
438
439 // Has |this| exited Dart code?
440 bool HasExitedDartCode() const;
441
442 CompilerState& compiler_state() {
443 ASSERT(compiler_state_ != nullptr);
444 return *compiler_state_;
445 }
446
447 HierarchyInfo* hierarchy_info() const {
448 ASSERT(isolate_ != NULL);
449 return hierarchy_info_;
450 }
451
452 void set_hierarchy_info(HierarchyInfo* value) {
453 ASSERT(isolate_ != NULL);
454 ASSERT((hierarchy_info_ == NULL && value != NULL) ||
455 (hierarchy_info_ != NULL && value == NULL));
456 hierarchy_info_ = value;
457 }
458
459 TypeUsageInfo* type_usage_info() const {
460 ASSERT(isolate_ != NULL);
461 return type_usage_info_;
462 }
463
464 void set_type_usage_info(TypeUsageInfo* value) {
465 ASSERT(isolate_ != NULL);
466 ASSERT((type_usage_info_ == NULL && value != NULL) ||
467 (type_usage_info_ != NULL && value == NULL));
468 type_usage_info_ = value;
469 }
470
471#if !defined(DART_PRECOMPILED_RUNTIME)
472 Interpreter* interpreter() const { return interpreter_; }
473 void set_interpreter(Interpreter* value) { interpreter_ = value; }
474#endif
475
476 int32_t no_callback_scope_depth() const { return no_callback_scope_depth_; }
477
478 void IncrementNoCallbackScopeDepth() {
479 ASSERT(no_callback_scope_depth_ < INT_MAX);
480 no_callback_scope_depth_ += 1;
481 }
482
483 void DecrementNoCallbackScopeDepth() {
484 ASSERT(no_callback_scope_depth_ > 0);
485 no_callback_scope_depth_ -= 1;
486 }
487
488 void StoreBufferAddObject(ObjectPtr obj);
489 void StoreBufferAddObjectGC(ObjectPtr obj);
490#if defined(TESTING)
491 bool StoreBufferContains(ObjectPtr obj) const {
492 return store_buffer_block_->Contains(obj);
493 }
494#endif
495 void StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy);
496 static intptr_t store_buffer_block_offset() {
497 return OFFSET_OF(Thread, store_buffer_block_);
498 }
499
500 bool is_marking() const { return marking_stack_block_ != NULL; }
501 void MarkingStackAddObject(ObjectPtr obj);
502 void DeferredMarkingStackAddObject(ObjectPtr obj);
503 void MarkingStackBlockProcess();
504 void DeferredMarkingStackBlockProcess();
505 static intptr_t marking_stack_block_offset() {
506 return OFFSET_OF(Thread, marking_stack_block_);
507 }
508
509 uword top_exit_frame_info() const { return top_exit_frame_info_; }
510 void set_top_exit_frame_info(uword top_exit_frame_info) {
511 top_exit_frame_info_ = top_exit_frame_info;
512 }
513 static intptr_t top_exit_frame_info_offset() {
514 return OFFSET_OF(Thread, top_exit_frame_info_);
515 }
516
517 // Heap of the isolate that this thread is operating on.
518 Heap* heap() const { return heap_; }
519 static intptr_t heap_offset() { return OFFSET_OF(Thread, heap_); }
520
521 uword top() const { return top_; }
522 uword end() const { return end_; }
523 void set_top(uword top) { top_ = top; }
524 void set_end(uword end) { end_ = end; }
525 static intptr_t top_offset() { return OFFSET_OF(Thread, top_); }
526 static intptr_t end_offset() { return OFFSET_OF(Thread, end_); }
527
528 int32_t no_safepoint_scope_depth() const {
529#if defined(DEBUG)
530 return no_safepoint_scope_depth_;
531#else
532 return 0;
533#endif
534 }
535
536 void IncrementNoSafepointScopeDepth() {
537#if defined(DEBUG)
538 ASSERT(no_safepoint_scope_depth_ < INT_MAX);
539 no_safepoint_scope_depth_ += 1;
540#endif
541 }
542
543 void DecrementNoSafepointScopeDepth() {
544#if defined(DEBUG)
545 ASSERT(no_safepoint_scope_depth_ > 0);
546 no_safepoint_scope_depth_ -= 1;
547#endif
548 }
549
550#define DEFINE_OFFSET_METHOD(type_name, member_name, expr, default_init_value) \
551 static intptr_t member_name##offset() { \
552 return OFFSET_OF(Thread, member_name); \
553 }
554 CACHED_CONSTANTS_LIST(DEFINE_OFFSET_METHOD)
555#undef DEFINE_OFFSET_METHOD
556
557#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \
558 defined(TARGET_ARCH_X64)
559 static intptr_t write_barrier_wrappers_thread_offset(Register reg) {
560 ASSERT((kDartAvailableCpuRegs & (1 << reg)) != 0);
561 intptr_t index = 0;
562 for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
563 if ((kDartAvailableCpuRegs & (1 << i)) == 0) continue;
564 if (i == reg) break;
565 ++index;
566 }
567 return OFFSET_OF(Thread, write_barrier_wrappers_entry_points_) +
568 index * sizeof(uword);
569 }
570
571 static intptr_t WriteBarrierWrappersOffsetForRegister(Register reg) {
572 intptr_t index = 0;
573 for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
574 if ((kDartAvailableCpuRegs & (1 << i)) == 0) continue;
575 if (i == reg) {
576 return index * kStoreBufferWrapperSize;
577 }
578 ++index;
579 }
580 UNREACHABLE();
581 return 0;
582 }
583#endif
584
585#define DEFINE_OFFSET_METHOD(name) \
586 static intptr_t name##_entry_point_offset() { \
587 return OFFSET_OF(Thread, name##_entry_point_); \
588 }
589 RUNTIME_ENTRY_LIST(DEFINE_OFFSET_METHOD)
590#undef DEFINE_OFFSET_METHOD
591
592#define DEFINE_OFFSET_METHOD(returntype, name, ...) \
593 static intptr_t name##_entry_point_offset() { \
594 return OFFSET_OF(Thread, name##_entry_point_); \
595 }
596 LEAF_RUNTIME_ENTRY_LIST(DEFINE_OFFSET_METHOD)
597#undef DEFINE_OFFSET_METHOD
598
599 ObjectPoolPtr global_object_pool() const { return global_object_pool_; }
600 void set_global_object_pool(ObjectPoolPtr raw_value) {
601 global_object_pool_ = raw_value;
602 }
603
604 const uword* dispatch_table_array() const { return dispatch_table_array_; }
605 void set_dispatch_table_array(const uword* array) {
606 dispatch_table_array_ = array;
607 }
608
609 static bool CanLoadFromThread(const Object& object);
610 static intptr_t OffsetFromThread(const Object& object);
611 static bool ObjectAtOffset(intptr_t offset, Object* object);
612 static intptr_t OffsetFromThread(const RuntimeEntry* runtime_entry);
613
614#if defined(DEBUG)
615 // For asserts only. Has false positives when running with a simulator or
616 // SafeStack.
617 bool TopErrorHandlerIsSetJump() const;
618 bool TopErrorHandlerIsExitFrame() const;
619#endif
620
621 uword vm_tag() const { return vm_tag_; }
622 void set_vm_tag(uword tag) { vm_tag_ = tag; }
623 static intptr_t vm_tag_offset() { return OFFSET_OF(Thread, vm_tag_); }
624
625 int64_t unboxed_int64_runtime_arg() const {
626 return unboxed_int64_runtime_arg_;
627 }
628 void set_unboxed_int64_runtime_arg(int64_t value) {
629 unboxed_int64_runtime_arg_ = value;
630 }
631 static intptr_t unboxed_int64_runtime_arg_offset() {
632 return OFFSET_OF(Thread, unboxed_int64_runtime_arg_);
633 }
634
635 GrowableObjectArrayPtr pending_functions();
636 void clear_pending_functions();
637
638 static intptr_t global_object_pool_offset() {
639 return OFFSET_OF(Thread, global_object_pool_);
640 }
641
642 static intptr_t dispatch_table_array_offset() {
643 return OFFSET_OF(Thread, dispatch_table_array_);
644 }
645
646 ObjectPtr active_exception() const { return active_exception_; }
647 void set_active_exception(const Object& value);
648 static intptr_t active_exception_offset() {
649 return OFFSET_OF(Thread, active_exception_);
650 }
651
652 ObjectPtr active_stacktrace() const { return active_stacktrace_; }
653 void set_active_stacktrace(const Object& value);
654 static intptr_t active_stacktrace_offset() {
655 return OFFSET_OF(Thread, active_stacktrace_);
656 }
657
658 uword resume_pc() const { return resume_pc_; }
659 void set_resume_pc(uword value) { resume_pc_ = value; }
660 static uword resume_pc_offset() { return OFFSET_OF(Thread, resume_pc_); }
661
662 ErrorPtr sticky_error() const;
663 void set_sticky_error(const Error& value);
664 void ClearStickyError();
665 DART_WARN_UNUSED_RESULT ErrorPtr StealStickyError();
666
667 StackTracePtr async_stack_trace() const;
668 void set_async_stack_trace(const StackTrace& stack_trace);
669 void set_raw_async_stack_trace(StackTracePtr raw_stack_trace);
670 void clear_async_stack_trace();
671 static intptr_t async_stack_trace_offset() {
672 return OFFSET_OF(Thread, async_stack_trace_);
673 }
674
675#if defined(DEBUG)
676#define REUSABLE_HANDLE_SCOPE_ACCESSORS(object) \
677 void set_reusable_##object##_handle_scope_active(bool value) { \
678 reusable_##object##_handle_scope_active_ = value; \
679 } \
680 bool reusable_##object##_handle_scope_active() const { \
681 return reusable_##object##_handle_scope_active_; \
682 }
683 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_ACCESSORS)
684#undef REUSABLE_HANDLE_SCOPE_ACCESSORS
685
686 bool IsAnyReusableHandleScopeActive() const {
687#define IS_REUSABLE_HANDLE_SCOPE_ACTIVE(object) \
688 if (reusable_##object##_handle_scope_active_) { \
689 return true; \
690 }
691 REUSABLE_HANDLE_LIST(IS_REUSABLE_HANDLE_SCOPE_ACTIVE)
692 return false;
693#undef IS_REUSABLE_HANDLE_SCOPE_ACTIVE
694 }
695#endif // defined(DEBUG)
696
697 void ClearReusableHandles();
698
699#define REUSABLE_HANDLE(object) \
700 object& object##Handle() const { return *object##_handle_; }
701 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE)
702#undef REUSABLE_HANDLE
703
704 /*
705 * Fields used to support safepointing a thread.
706 *
707 * - Bit 0 of the safepoint_state_ field is used to indicate if the thread is
708 * already at a safepoint,
709 * - Bit 1 of the safepoint_state_ field is used to indicate if a safepoint
710 * operation is requested for this thread.
711 * - Bit 2 of the safepoint_state_ field is used to indicate that the thread
712 * is blocked for the safepoint operation to complete.
713 *
714 * The safepoint execution state (described above) for a thread is stored in
715 * in the execution_state_ field.
716 * Potential execution states a thread could be in:
717 * kThreadInGenerated - The thread is running jitted dart/stub code.
718 * kThreadInVM - The thread is running VM code.
719 * kThreadInNative - The thread is running native code.
720 * kThreadInBlockedState - The thread is blocked waiting for a resource.
721 */
722 static bool IsAtSafepoint(uword state) {
723 return AtSafepointField::decode(state);
724 }
725 bool IsAtSafepoint() const {
726 return AtSafepointField::decode(safepoint_state_);
727 }
728 static uword SetAtSafepoint(bool value, uword state) {
729 return AtSafepointField::update(value, state);
730 }
731 void SetAtSafepoint(bool value) {
732 ASSERT(thread_lock()->IsOwnedByCurrentThread());
733 safepoint_state_ = AtSafepointField::update(value, safepoint_state_);
734 }
735 bool IsSafepointRequested() const {
736 return SafepointRequestedField::decode(safepoint_state_);
737 }
738 static uword SetSafepointRequested(bool value, uword state) {
739 return SafepointRequestedField::update(value, state);
740 }
741 uword SetSafepointRequested(bool value) {
742 ASSERT(thread_lock()->IsOwnedByCurrentThread());
743 if (value) {
744 // acquire pulls from the release in TryEnterSafepoint.
745 return safepoint_state_.fetch_or(SafepointRequestedField::encode(true),
746 std::memory_order_acquire);
747 } else {
748 // release pushes to the acquire in TryExitSafepoint.
749 return safepoint_state_.fetch_and(~SafepointRequestedField::encode(true),
750 std::memory_order_release);
751 }
752 }
753 static bool IsBlockedForSafepoint(uword state) {
754 return BlockedForSafepointField::decode(state);
755 }
756 bool IsBlockedForSafepoint() const {
757 return BlockedForSafepointField::decode(safepoint_state_);
758 }
759 void SetBlockedForSafepoint(bool value) {
760 ASSERT(thread_lock()->IsOwnedByCurrentThread());
761 safepoint_state_ =
762 BlockedForSafepointField::update(value, safepoint_state_);
763 }
764 bool BypassSafepoints() const {
765 return BypassSafepointsField::decode(safepoint_state_);
766 }
767 static uword SetBypassSafepoints(bool value, uword state) {
768 return BypassSafepointsField::update(value, state);
769 }
770
771 enum ExecutionState {
772 kThreadInVM = 0,
773 kThreadInGenerated,
774 kThreadInNative,
775 kThreadInBlockedState
776 };
777
778 ExecutionState execution_state() const {
779 return static_cast<ExecutionState>(execution_state_);
780 }
781 // Normally execution state is only accessed for the current thread.
782 NO_SANITIZE_THREAD
783 ExecutionState execution_state_cross_thread_for_testing() const {
784 return static_cast<ExecutionState>(execution_state_);
785 }
786 void set_execution_state(ExecutionState state) {
787 execution_state_ = static_cast<uword>(state);
788 }
789 static intptr_t execution_state_offset() {
790 return OFFSET_OF(Thread, execution_state_);
791 }
792
793 virtual bool MayAllocateHandles() {
794 return (execution_state() == kThreadInVM) ||
795 (execution_state() == kThreadInGenerated);
796 }
797
798 static uword safepoint_state_unacquired() { return SetAtSafepoint(false, 0); }
799 static uword safepoint_state_acquired() { return SetAtSafepoint(true, 0); }
800
801 bool TryEnterSafepoint() {
802 uword old_state = 0;
803 uword new_state = SetAtSafepoint(true, 0);
804 return safepoint_state_.compare_exchange_strong(old_state, new_state,
805 std::memory_order_release);
806 }
807
808 void EnterSafepoint() {
809 ASSERT(no_safepoint_scope_depth() == 0);
810 // First try a fast update of the thread state to indicate it is at a
811 // safepoint.
812 if (!TryEnterSafepoint()) {
813 // Fast update failed which means we could potentially be in the middle
814 // of a safepoint operation.
815 EnterSafepointUsingLock();
816 }
817 }
818
819 bool TryExitSafepoint() {
820 uword old_state = SetAtSafepoint(true, 0);
821 uword new_state = 0;
822 return safepoint_state_.compare_exchange_strong(old_state, new_state,
823 std::memory_order_acquire);
824 }
825
826 void ExitSafepoint() {
827 // First try a fast update of the thread state to indicate it is not at a
828 // safepoint anymore.
829 if (!TryExitSafepoint()) {
830 // Fast update failed which means we could potentially be in the middle
831 // of a safepoint operation.
832 ExitSafepointUsingLock();
833 }
834 }
835
836 void CheckForSafepoint() {
837 ASSERT(no_safepoint_scope_depth() == 0);
838 if (IsSafepointRequested()) {
839 BlockForSafepoint();
840 }
841 }
842
843 int32_t AllocateFfiCallbackId();
844
845 // Store 'code' for the native callback identified by 'callback_id'.
846 //
847 // Expands the callback code array as necessary to accomodate the callback ID.
848 void SetFfiCallbackCode(int32_t callback_id, const Code& code);
849
850 // Ensure that 'callback_id' refers to a valid callback in this isolate.
851 //
852 // If "entry != 0", additionally checks that entry is inside the instructions
853 // of this callback.
854 //
855 // Aborts if any of these conditions fails.
856 void VerifyCallbackIsolate(int32_t callback_id, uword entry);
857
858 Thread* next() const { return next_; }
859
860 // Visit all object pointers.
861 void VisitObjectPointers(ObjectPointerVisitor* visitor,
862 ValidationPolicy validate_frames);
863 void RememberLiveTemporaries();
864 void DeferredMarkLiveTemporaries();
865
866 bool IsValidHandle(Dart_Handle object) const;
867 bool IsValidLocalHandle(Dart_Handle object) const;
868 intptr_t CountLocalHandles() const;
869 int ZoneSizeInBytes() const;
870 void UnwindScopes(uword stack_marker);
871
872 void InitVMConstants();
873
874 uint64_t GetRandomUInt64() { return thread_random_.NextUInt64(); }
875
876 uint64_t* GetFfiMarshalledArguments(intptr_t size) {
877 if (ffi_marshalled_arguments_size_ < size) {
878 if (ffi_marshalled_arguments_size_ > 0) {
879 free(ffi_marshalled_arguments_);
880 }
881 ffi_marshalled_arguments_ =
882 reinterpret_cast<uint64_t*>(malloc(size * sizeof(uint64_t)));
883 }
884 return ffi_marshalled_arguments_;
885 }
886
887#ifndef PRODUCT
888 void PrintJSON(JSONStream* stream) const;
889#endif
890
891 private:
892 template <class T>
893 T* AllocateReusableHandle();
894
895 enum class RestoreWriteBarrierInvariantOp {
896 kAddToRememberedSet,
897 kAddToDeferredMarkingStack
898 };
899 friend class RestoreWriteBarrierInvariantVisitor;
900 void RestoreWriteBarrierInvariant(RestoreWriteBarrierInvariantOp op);
901
902 // Set the current compiler state and return the previous compiler state.
903 CompilerState* SetCompilerState(CompilerState* state) {
904 CompilerState* previous = compiler_state_;
905 compiler_state_ = state;
906 return previous;
907 }
908
909 // Accessed from generated code.
910 // ** This block of fields must come first! **
911 // For AOT cross-compilation, we rely on these members having the same offsets
912 // in SIMARM(IA32) and ARM, and the same offsets in SIMARM64(X64) and ARM64.
913 // We use only word-sized fields to avoid differences in struct packing on the
914 // different architectures. See also CheckOffsets in dart.cc.
915 RelaxedAtomic<uword> stack_limit_;
916 uword write_barrier_mask_;
917 Isolate* isolate_;
918 const uword* dispatch_table_array_;
919 uword top_ = 0;
920 uword end_ = 0;
921 // Offsets up to this point can all fit in a byte on X64. All of the above
922 // fields are very abundantly accessed from code. Thus, keeping them first
923 // is important for code size (although code size on X64 is not a priority).
924 uword saved_stack_limit_;
925 uword stack_overflow_flags_;
926 InstancePtr* field_table_values_;
927 Heap* heap_;
928 uword volatile top_exit_frame_info_;
929 StoreBufferBlock* store_buffer_block_;
930 MarkingStackBlock* marking_stack_block_;
931 MarkingStackBlock* deferred_marking_stack_block_;
932 uword volatile vm_tag_;
933 StackTracePtr async_stack_trace_;
934 // Memory location dedicated for passing unboxed int64 values from
935 // generated code to runtime.
936 // TODO(dartbug.com/33549): Clean this up when unboxed values
937 // could be passed as arguments.
938 ALIGN8 int64_t unboxed_int64_runtime_arg_;
939
940// State that is cached in the TLS for fast access in generated code.
941#define DECLARE_MEMBERS(type_name, member_name, expr, default_init_value) \
942 type_name member_name;
943 CACHED_CONSTANTS_LIST(DECLARE_MEMBERS)
944#undef DECLARE_MEMBERS
945
946#define DECLARE_MEMBERS(name) uword name##_entry_point_;
947 RUNTIME_ENTRY_LIST(DECLARE_MEMBERS)
948#undef DECLARE_MEMBERS
949
950#define DECLARE_MEMBERS(returntype, name, ...) uword name##_entry_point_;
951 LEAF_RUNTIME_ENTRY_LIST(DECLARE_MEMBERS)
952#undef DECLARE_MEMBERS
953
954#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \
955 defined(TARGET_ARCH_X64)
956 uword write_barrier_wrappers_entry_points_[kNumberOfDartAvailableCpuRegs];
957#endif
958
959 // JumpToExceptionHandler state:
960 ObjectPtr active_exception_;
961 ObjectPtr active_stacktrace_;
962 ObjectPoolPtr global_object_pool_;
963 uword resume_pc_;
964 uword saved_shadow_call_stack_ = 0;
965 uword execution_state_;
966 std::atomic<uword> safepoint_state_;
967 GrowableObjectArrayPtr ffi_callback_code_;
968 uword exit_through_ffi_ = 0;
969 ApiLocalScope* api_top_scope_;
970
971 // ---- End accessed from generated code. ----
972
973 // The layout of Thread object up to this point should not depend
974 // on DART_PRECOMPILED_RUNTIME, as it is accessed from generated code.
975 // The code is generated without DART_PRECOMPILED_RUNTIME, but used with
976 // DART_PRECOMPILED_RUNTIME.
977
978 TaskKind task_kind_;
979 TimelineStream* dart_stream_;
980 IsolateGroup* isolate_group_ = nullptr;
981 mutable Monitor thread_lock_;
982 ApiLocalScope* api_reusable_scope_;
983 int32_t no_callback_scope_depth_;
984#if defined(DEBUG)
985 int32_t no_safepoint_scope_depth_;
986#endif
987 VMHandles reusable_handles_;
988 intptr_t defer_oob_messages_count_;
989 uint16_t deferred_interrupts_mask_;
990 uint16_t deferred_interrupts_;
991 int32_t stack_overflow_count_;
992
993 // Compiler state:
994 CompilerState* compiler_state_ = nullptr;
995 HierarchyInfo* hierarchy_info_;
996 TypeUsageInfo* type_usage_info_;
997 GrowableObjectArrayPtr pending_functions_;
998
999 ErrorPtr sticky_error_;
1000
1001 Random thread_random_;
1002
1003 intptr_t ffi_marshalled_arguments_size_ = 0;
1004 uint64_t* ffi_marshalled_arguments_;
1005
1006 InstancePtr* field_table_values() const { return field_table_values_; }
1007
1008// Reusable handles support.
1009#define REUSABLE_HANDLE_FIELDS(object) object* object##_handle_;
1010 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_FIELDS)
1011#undef REUSABLE_HANDLE_FIELDS
1012
1013#if defined(DEBUG)
1014#define REUSABLE_HANDLE_SCOPE_VARIABLE(object) \
1015 bool reusable_##object##_handle_scope_active_;
1016 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_VARIABLE);
1017#undef REUSABLE_HANDLE_SCOPE_VARIABLE
1018#endif // defined(DEBUG)
1019
1020 // Generated code assumes that AtSafepointField is the LSB.
1021 class AtSafepointField : public BitField<uword, bool, 0, 1> {};
1022 class SafepointRequestedField : public BitField<uword, bool, 1, 1> {};
1023 class BlockedForSafepointField : public BitField<uword, bool, 2, 1> {};
1024 class BypassSafepointsField : public BitField<uword, bool, 3, 1> {};
1025
1026#if defined(USING_SAFE_STACK)
1027 uword saved_safestack_limit_;
1028#endif
1029
1030#if !defined(DART_PRECOMPILED_RUNTIME)
1031 Interpreter* interpreter_;
1032#endif
1033
1034 Thread* next_; // Used to chain the thread structures in an isolate.
1035 bool is_mutator_thread_ = false;
1036
1037 explicit Thread(bool is_vm_isolate);
1038
1039 void StoreBufferRelease(
1040 StoreBuffer::ThresholdPolicy policy = StoreBuffer::kCheckThreshold);
1041 void StoreBufferAcquire();
1042
1043 void MarkingStackRelease();
1044 void MarkingStackAcquire();
1045 void DeferredMarkingStackRelease();
1046 void DeferredMarkingStackAcquire();
1047
1048 void set_safepoint_state(uint32_t value) { safepoint_state_ = value; }
1049 void EnterSafepointUsingLock();
1050 void ExitSafepointUsingLock();
1051 void BlockForSafepoint();
1052
1053 void FinishEntering(TaskKind kind);
1054 void PrepareLeaving();
1055
1056 static void SetCurrent(Thread* current) { OSThread::SetCurrentTLS(current); }
1057
1058 void DeferOOBMessageInterrupts();
1059 void RestoreOOBMessageInterrupts();
1060
1061#define REUSABLE_FRIEND_DECLARATION(name) \
1062 friend class Reusable##name##HandleScope;
1063 REUSABLE_HANDLE_LIST(REUSABLE_FRIEND_DECLARATION)
1064#undef REUSABLE_FRIEND_DECLARATION
1065
1066 friend class ApiZone;
1067 friend class Interpreter;
1068 friend class InterruptChecker;
1069 friend class Isolate;
1070 friend class IsolateGroup;
1071 friend class IsolateTestHelper;
1072 friend class NoOOBMessageScope;
1073 friend class Simulator;
1074 friend class StackZone;
1075 friend class ThreadRegistry;
1076 friend class NoActiveIsolateScope;
1077 friend class CompilerState;
1078 friend class compiler::target::Thread;
1079 friend class FieldTable;
1080 friend Isolate* CreateWithinExistingIsolateGroup(IsolateGroup*,
1081 const char*,
1082 char**);
1083 DISALLOW_COPY_AND_ASSIGN(Thread);
1084};
1085
1086#if defined(HOST_OS_WINDOWS)
1087// Clears the state of the current thread and frees the allocation.
1088void WindowsThreadCleanUp();
1089#endif
1090
1091// Disable thread interrupts.
1092class DisableThreadInterruptsScope : public StackResource {
1093 public:
1094 explicit DisableThreadInterruptsScope(Thread* thread);
1095 ~DisableThreadInterruptsScope();
1096};
1097
1098// Within a NoSafepointScope, the thread must not reach any safepoint. Used
1099// around code that manipulates raw object pointers directly without handles.
1100#if defined(DEBUG)
1101class NoSafepointScope : public ThreadStackResource {
1102 public:
1103 explicit NoSafepointScope(Thread* thread = nullptr)
1104 : ThreadStackResource(thread != nullptr ? thread : Thread::Current()) {
1105 this->thread()->IncrementNoSafepointScopeDepth();
1106 }
1107 ~NoSafepointScope() { thread()->DecrementNoSafepointScopeDepth(); }
1108
1109 private:
1110 DISALLOW_COPY_AND_ASSIGN(NoSafepointScope);
1111};
1112#else // defined(DEBUG)
1113class NoSafepointScope : public ValueObject {
1114 public:
1115 explicit NoSafepointScope(Thread* thread = nullptr) {}
1116
1117 private:
1118 DISALLOW_COPY_AND_ASSIGN(NoSafepointScope);
1119};
1120#endif // defined(DEBUG)
1121
1122} // namespace dart
1123
1124#endif // RUNTIME_VM_THREAD_H_
1125