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