• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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_LOCAL_ISOLATE_H_
6 #define V8_EXECUTION_LOCAL_ISOLATE_H_
7 
8 #include "src/base/macros.h"
9 #include "src/execution/shared-mutex-guard-if-off-thread.h"
10 #include "src/execution/thread-id.h"
11 #include "src/handles/handles.h"
12 #include "src/handles/local-handles.h"
13 #include "src/handles/maybe-handles.h"
14 #include "src/heap/local-factory.h"
15 #include "src/heap/local-heap.h"
16 #include "src/logging/runtime-call-stats.h"
17 
18 namespace v8 {
19 
20 namespace bigint {
21 class Processor;
22 }
23 
24 namespace internal {
25 
26 class Isolate;
27 class LocalLogger;
28 class RuntimeCallStats;
29 
30 // HiddenLocalFactory parallels Isolate's HiddenFactory
31 class V8_EXPORT_PRIVATE HiddenLocalFactory : private LocalFactory {
32  public:
33   // Forward constructors.
34   using LocalFactory::LocalFactory;
35 };
36 
37 // And Isolate-like class that can be passed in to templated methods that need
38 // an isolate syntactically, but are usable off-thread.
39 //
40 // This class holds an LocalFactory, but is otherwise effectively a stub
41 // implementation of an Isolate. In particular, it doesn't allow throwing
42 // exceptions, and hard crashes if you try.
43 class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
44  public:
45   using HandleScopeType = LocalHandleScope;
46 
47   explicit LocalIsolate(Isolate* isolate, ThreadKind kind);
48   ~LocalIsolate();
49 
50   // Kinda sketchy.
FromHeap(LocalHeap * heap)51   static LocalIsolate* FromHeap(LocalHeap* heap) {
52     return reinterpret_cast<LocalIsolate*>(reinterpret_cast<Address>(heap) -
53                                            OFFSET_OF(LocalIsolate, heap_));
54   }
55 
is_main_thread()56   bool is_main_thread() { return heap()->is_main_thread(); }
57 
heap()58   LocalHeap* heap() { return &heap_; }
59 
60   inline Address cage_base() const;
61   inline Address code_cage_base() const;
62   inline ReadOnlyHeap* read_only_heap() const;
63   inline Object root(RootIndex index) const;
64   inline Handle<Object> root_handle(RootIndex index) const;
65 
string_table()66   StringTable* string_table() const { return isolate_->string_table(); }
internalized_string_access()67   base::SharedMutex* internalized_string_access() {
68     return isolate_->internalized_string_access();
69   }
ast_string_constants()70   const AstStringConstants* ast_string_constants() {
71     return isolate_->ast_string_constants();
72   }
lazy_compile_dispatcher()73   LazyCompileDispatcher* lazy_compile_dispatcher() {
74     return isolate_->lazy_compile_dispatcher();
75   }
main_thread_logger()76   Logger* main_thread_logger() {
77     // TODO(leszeks): This is needed for logging in ParseInfo. Figure out a way
78     // to use the LocalLogger for this instead.
79     return isolate_->logger();
80   }
81 
factory()82   v8::internal::LocalFactory* factory() {
83     // Upcast to the privately inherited base-class using c-style casts to avoid
84     // undefined behavior (as static_cast cannot cast across private bases).
85     return (v8::internal::LocalFactory*)this;
86   }
87 
allocator()88   AccountingAllocator* allocator() { return isolate_->allocator(); }
89 
has_pending_exception()90   bool has_pending_exception() const { return false; }
91 
92   void RegisterDeserializerStarted();
93   void RegisterDeserializerFinished();
94 
95   template <typename T>
Throw(Handle<Object> exception)96   Handle<T> Throw(Handle<Object> exception) {
97     UNREACHABLE();
98   }
FatalProcessOutOfHeapMemory(const char * location)99   [[noreturn]] void FatalProcessOutOfHeapMemory(const char* location) {
100     UNREACHABLE();
101   }
102 
103   int GetNextScriptId();
104 #if V8_SFI_HAS_UNIQUE_ID
105   int GetNextUniqueSharedFunctionInfoId();
106 #endif  // V8_SFI_HAS_UNIQUE_ID
107 
108   bool is_collecting_type_profile() const;
109 
logger()110   LocalLogger* logger() const { return logger_.get(); }
thread_id()111   ThreadId thread_id() const { return thread_id_; }
stack_limit()112   Address stack_limit() const { return stack_limit_; }
113 #ifdef V8_RUNTIME_CALL_STATS
runtime_call_stats()114   RuntimeCallStats* runtime_call_stats() const { return runtime_call_stats_; }
115 #else
runtime_call_stats()116   RuntimeCallStats* runtime_call_stats() const { return nullptr; }
117 #endif
bigint_processor()118   bigint::Processor* bigint_processor() {
119     if (!bigint_processor_) InitializeBigIntProcessor();
120     return bigint_processor_;
121   }
122 
is_main_thread()123   bool is_main_thread() const { return heap_.is_main_thread(); }
124 
125   // AsIsolate is only allowed on the main-thread.
AsIsolate()126   Isolate* AsIsolate() {
127     DCHECK(is_main_thread());
128     DCHECK_EQ(ThreadId::Current(), isolate_->thread_id());
129     return isolate_;
130   }
AsLocalIsolate()131   LocalIsolate* AsLocalIsolate() { return this; }
132 
133   // TODO(victorgomes): Remove this when/if MacroAssembler supports LocalIsolate
134   // only constructor.
GetMainThreadIsolateUnsafe()135   Isolate* GetMainThreadIsolateUnsafe() const { return isolate_; }
136 
pending_message_address()137   Object* pending_message_address() {
138     return isolate_->pending_message_address();
139   }
140 
141 #ifdef V8_INTL_SUPPORT
142   // WARNING: This might be out-of-sync with the main-thread.
143   const std::string& DefaultLocale();
144 #endif
145 
146  private:
147   friend class v8::internal::LocalFactory;
148   friend class LocalIsolateFactory;
149 
150   void InitializeBigIntProcessor();
151 
152   LocalHeap heap_;
153 
154   // TODO(leszeks): Extract out the fields of the Isolate we want and store
155   // those instead of the whole thing.
156   Isolate* const isolate_;
157 
158   std::unique_ptr<LocalLogger> logger_;
159   ThreadId const thread_id_;
160   Address const stack_limit_;
161 
162   bigint::Processor* bigint_processor_{nullptr};
163 
164 #ifdef V8_RUNTIME_CALL_STATS
165   base::Optional<WorkerThreadRuntimeCallStatsScope> rcs_scope_;
166   RuntimeCallStats* runtime_call_stats_;
167 #endif
168 #ifdef V8_INTL_SUPPORT
169   std::string default_locale_;
170 #endif
171 };
172 
173 template <base::MutexSharedType kIsShared>
174 class V8_NODISCARD SharedMutexGuardIfOffThread<LocalIsolate, kIsShared> final {
175  public:
SharedMutexGuardIfOffThread(base::SharedMutex * mutex,LocalIsolate * isolate)176   SharedMutexGuardIfOffThread(base::SharedMutex* mutex, LocalIsolate* isolate) {
177     DCHECK_NOT_NULL(mutex);
178     DCHECK_NOT_NULL(isolate);
179     if (!isolate->is_main_thread()) mutex_guard_.emplace(mutex);
180   }
181 
182   SharedMutexGuardIfOffThread(const SharedMutexGuardIfOffThread&) = delete;
183   SharedMutexGuardIfOffThread& operator=(const SharedMutexGuardIfOffThread&) =
184       delete;
185 
186  private:
187   base::Optional<base::SharedMutexGuard<kIsShared>> mutex_guard_;
188 };
189 
190 }  // namespace internal
191 }  // namespace v8
192 
193 #endif  // V8_EXECUTION_LOCAL_ISOLATE_H_
194