1 | // Copyright 2019 the V8 project authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #ifndef V8_THREAD_LOCAL_TOP_H_ |
6 | #define V8_THREAD_LOCAL_TOP_H_ |
7 | |
8 | #include "src/contexts.h" |
9 | #include "src/globals.h" |
10 | #include "src/thread-id.h" |
11 | |
12 | namespace v8 { |
13 | |
14 | class TryCatch; |
15 | |
16 | namespace internal { |
17 | |
18 | class ExternalCallbackScope; |
19 | class Isolate; |
20 | class PromiseOnStack; |
21 | class Simulator; |
22 | |
23 | class ThreadLocalTop { |
24 | public: |
25 | // TODO(all): This is not particularly beautiful. We should probably |
26 | // refactor this to really consist of just Addresses and 32-bit |
27 | // integer fields. |
28 | static constexpr uint32_t kSizeInBytes = 23 * kSystemPointerSize; |
29 | |
30 | // Does early low-level initialization that does not depend on the |
31 | // isolate being present. |
32 | ThreadLocalTop() = default; |
33 | |
34 | // Initialize the thread data. |
35 | void Initialize(Isolate*); |
36 | |
37 | // The top C++ try catch handler or nullptr if none are registered. |
38 | // |
39 | // This field is not guaranteed to hold an address that can be |
40 | // used for comparison with addresses into the JS stack. If such |
41 | // an address is needed, use try_catch_handler_address. |
42 | v8::TryCatch* try_catch_handler_ = nullptr; |
43 | |
44 | // Get the address of the top C++ try catch handler or nullptr if |
45 | // none are registered. |
46 | // |
47 | // This method always returns an address that can be compared to |
48 | // pointers into the JavaScript stack. When running on actual |
49 | // hardware, try_catch_handler_address and TryCatchHandler return |
50 | // the same pointer. When running on a simulator with a separate JS |
51 | // stack, try_catch_handler_address returns a JS stack address that |
52 | // corresponds to the place on the JS stack where the C++ handler |
53 | // would have been if the stack were not separate. |
54 | Address try_catch_handler_address() { |
55 | return reinterpret_cast<Address>( |
56 | v8::TryCatch::JSStackComparableAddress(try_catch_handler_)); |
57 | } |
58 | |
59 | void Free(); |
60 | |
61 | Isolate* isolate_ = nullptr; |
62 | // The context where the current execution method is created and for variable |
63 | // lookups. |
64 | // TODO(3770): This field is read/written from generated code, so it would |
65 | // be cleaner to make it an "Address raw_context_", and construct a Context |
66 | // object in the getter. Same for {pending_handler_context_} below. In the |
67 | // meantime, assert that the memory layout is the same. |
68 | STATIC_ASSERT(sizeof(Context) == kSystemPointerSize); |
69 | Context context_; |
70 | ThreadId thread_id_ = ThreadId::Invalid(); |
71 | Object pending_exception_; |
72 | |
73 | // Communication channel between Isolate::FindHandler and the CEntry. |
74 | Context pending_handler_context_; |
75 | Address pending_handler_entrypoint_ = kNullAddress; |
76 | Address pending_handler_constant_pool_ = kNullAddress; |
77 | Address pending_handler_fp_ = kNullAddress; |
78 | Address pending_handler_sp_ = kNullAddress; |
79 | |
80 | // Communication channel between Isolate::Throw and message consumers. |
81 | Object pending_message_obj_; |
82 | bool rethrowing_message_ = false; |
83 | |
84 | // Use a separate value for scheduled exceptions to preserve the |
85 | // invariants that hold about pending_exception. We may want to |
86 | // unify them later. |
87 | bool external_caught_exception_ = false; |
88 | Object scheduled_exception_; |
89 | |
90 | // Stack. |
91 | // The frame pointer of the top c entry frame. |
92 | Address c_entry_fp_ = kNullAddress; |
93 | // Try-blocks are chained through the stack. |
94 | Address handler_ = kNullAddress; |
95 | // C function that was called at c entry. |
96 | Address c_function_ = kNullAddress; |
97 | |
98 | // Throwing an exception may cause a Promise rejection. For this purpose |
99 | // we keep track of a stack of nested promises and the corresponding |
100 | // try-catch handlers. |
101 | PromiseOnStack* promise_on_stack_ = nullptr; |
102 | |
103 | // Simulator field is always present to get predictable layout. |
104 | Simulator* simulator_ = nullptr; |
105 | |
106 | // The stack pointer of the bottom JS entry frame. |
107 | Address js_entry_sp_ = kNullAddress; |
108 | // The external callback we're currently in. |
109 | ExternalCallbackScope* external_callback_scope_ = nullptr; |
110 | StateTag current_vm_state_ = EXTERNAL; |
111 | |
112 | // Call back function to report unsafe JS accesses. |
113 | v8::FailedAccessCheckCallback failed_access_check_callback_ = nullptr; |
114 | |
115 | // Address of the thread-local "thread in wasm" flag. |
116 | Address thread_in_wasm_flag_address_ = kNullAddress; |
117 | }; |
118 | |
119 | } // namespace internal |
120 | } // namespace v8 |
121 | |
122 | #endif // V8_THREAD_LOCAL_TOP_H_ |
123 | |