• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_EXECUTION_THREAD_LOCAL_TOP_H_
6 #define V8_EXECUTION_THREAD_LOCAL_TOP_H_
7 
8 #include "include/v8-callbacks.h"
9 #include "include/v8-exception.h"
10 #include "include/v8-unwinder.h"
11 #include "src/common/globals.h"
12 #include "src/execution/thread-id.h"
13 #include "src/objects/contexts.h"
14 #include "src/utils/utils.h"
15 
16 #ifdef V8_ENABLE_CONSERVATIVE_STACK_SCANNING
17 #include "src/heap/base/stack.h"
18 #endif
19 
20 namespace v8 {
21 
22 class TryCatch;
23 
24 namespace internal {
25 
26 class EmbedderState;
27 class ExternalCallbackScope;
28 class Isolate;
29 class Simulator;
30 
31 class ThreadLocalTop {
32  public:
33   // TODO(all): This is not particularly beautiful. We should probably
34   // refactor this to really consist of just Addresses and 32-bit
35   // integer fields.
36 #ifdef V8_ENABLE_CONSERVATIVE_STACK_SCANNING
37   static constexpr uint32_t kSizeInBytes = 26 * kSystemPointerSize;
38 #else
39   static constexpr uint32_t kSizeInBytes = 25 * kSystemPointerSize;
40 #endif
41 
42   // Does early low-level initialization that does not depend on the
43   // isolate being present.
ThreadLocalTop()44   ThreadLocalTop() { Clear(); }
45 
46   void Clear();
47 
48   // Initialize the thread data.
49   void Initialize(Isolate*);
50 
51   // The top C++ try catch handler or nullptr if none are registered.
52   //
53   // This field is not guaranteed to hold an address that can be
54   // used for comparison with addresses into the JS stack. If such
55   // an address is needed, use try_catch_handler_address.
56   v8::TryCatch* try_catch_handler_;
57 
58   // Get the address of the top C++ try catch handler or nullptr if
59   // none are registered.
60   //
61   // This method always returns an address that can be compared to
62   // pointers into the JavaScript stack.  When running on actual
63   // hardware, try_catch_handler_address and TryCatchHandler return
64   // the same pointer.  When running on a simulator with a separate JS
65   // stack, try_catch_handler_address returns a JS stack address that
66   // corresponds to the place on the JS stack where the C++ handler
67   // would have been if the stack were not separate.
try_catch_handler_address()68   Address try_catch_handler_address() {
69     if (try_catch_handler_) {
70       return try_catch_handler_->JSStackComparableAddressPrivate();
71     }
72     return kNullAddress;
73   }
74 
75   // Call depth represents nested v8 api calls. Instead of storing the nesting
76   // level as an integer, we store the stack height of the last API entry. This
77   // additional information is used when we decide whether to trigger a debug
78   // break at a function entry.
79   template <typename Scope>
IncrementCallDepth(Scope * stack_allocated_scope)80   void IncrementCallDepth(Scope* stack_allocated_scope) {
81     stack_allocated_scope->previous_stack_height_ = last_api_entry_;
82 #if defined(USE_SIMULATOR) || defined(V8_USE_ADDRESS_SANITIZER)
83     StoreCurrentStackPosition();
84 #else
85     last_api_entry_ = reinterpret_cast<i::Address>(stack_allocated_scope);
86 #endif
87   }
88 
89 #if defined(USE_SIMULATOR) || defined(V8_USE_ADDRESS_SANITIZER)
90   void StoreCurrentStackPosition();
91 #endif
92 
93   template <typename Scope>
DecrementCallDepth(Scope * stack_allocated_scope)94   void DecrementCallDepth(Scope* stack_allocated_scope) {
95     last_api_entry_ = stack_allocated_scope->previous_stack_height_;
96   }
97 
CallDepthIsZero()98   bool CallDepthIsZero() const { return last_api_entry_ == kNullAddress; }
99 
100   void Free();
101 
102   Isolate* isolate_;
103   // The context where the current execution method is created and for variable
104   // lookups.
105   // TODO(3770): This field is read/written from generated code, so it would
106   // be cleaner to make it an "Address raw_context_", and construct a Context
107   // object in the getter. Same for {pending_handler_context_} below. In the
108   // meantime, assert that the memory layout is the same.
109   STATIC_ASSERT(sizeof(Context) == kSystemPointerSize);
110   Context context_;
111   std::atomic<ThreadId> thread_id_;
112   Object pending_exception_;
113 
114   // Communication channel between Isolate::FindHandler and the CEntry.
115   Context pending_handler_context_;
116   Address pending_handler_entrypoint_;
117   Address pending_handler_constant_pool_;
118   Address pending_handler_fp_;
119   Address pending_handler_sp_;
120   uintptr_t num_frames_above_pending_handler_;
121 
122   Address last_api_entry_;
123 
124   // Communication channel between Isolate::Throw and message consumers.
125   Object pending_message_;
126   bool rethrowing_message_;
127 
128   // Use a separate value for scheduled exceptions to preserve the
129   // invariants that hold about pending_exception.  We may want to
130   // unify them later.
131   bool external_caught_exception_;
132   Object scheduled_exception_;
133 
134   // Stack.
135   // The frame pointer of the top c entry frame.
136   Address c_entry_fp_;
137   // Try-blocks are chained through the stack.
138   Address handler_;
139   // C function that was called at c entry.
140   Address c_function_;
141 
142   // Simulator field is always present to get predictable layout.
143   Simulator* simulator_;
144 
145   // The stack pointer of the bottom JS entry frame.
146   Address js_entry_sp_;
147   // The external callback we're currently in.
148   ExternalCallbackScope* external_callback_scope_;
149   StateTag current_vm_state_;
150   EmbedderState* current_embedder_state_;
151 
152   // Call back function to report unsafe JS accesses.
153   v8::FailedAccessCheckCallback failed_access_check_callback_;
154 
155   // Address of the thread-local "thread in wasm" flag.
156   Address thread_in_wasm_flag_address_;
157 
158 #ifdef V8_ENABLE_CONSERVATIVE_STACK_SCANNING
159   ::heap::base::Stack stack_;
160 #endif
161 };
162 
163 }  // namespace internal
164 }  // namespace v8
165 
166 #endif  // V8_EXECUTION_THREAD_LOCAL_TOP_H_
167