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 17 namespace v8 { 18 19 namespace bigint { 20 class Processor; 21 } 22 23 namespace internal { 24 25 class Isolate; 26 class LocalLogger; 27 class RuntimeCallStats; 28 29 // HiddenLocalFactory parallels Isolate's HiddenFactory 30 class V8_EXPORT_PRIVATE HiddenLocalFactory : private LocalFactory { 31 public: 32 // Forward constructors. 33 using LocalFactory::LocalFactory; 34 }; 35 36 // And Isolate-like class that can be passed in to templated methods that need 37 // an isolate syntactically, but are usable off-thread. 38 // 39 // This class holds an LocalFactory, but is otherwise effectively a stub 40 // implementation of an Isolate. In particular, it doesn't allow throwing 41 // exceptions, and hard crashes if you try. 42 class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory { 43 public: 44 using HandleScopeType = LocalHandleScope; 45 46 explicit LocalIsolate(Isolate* isolate, ThreadKind kind, 47 RuntimeCallStats* runtime_call_stats = nullptr); 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 } 70 factory()71 v8::internal::LocalFactory* factory() { 72 // Upcast to the privately inherited base-class using c-style casts to avoid 73 // undefined behavior (as static_cast cannot cast across private bases). 74 return (v8::internal::LocalFactory*)this; 75 } 76 has_pending_exception()77 bool has_pending_exception() const { return false; } 78 79 void RegisterDeserializerStarted(); 80 void RegisterDeserializerFinished(); 81 82 template <typename T> Throw(Handle<Object> exception)83 Handle<T> Throw(Handle<Object> exception) { 84 UNREACHABLE(); 85 } FatalProcessOutOfHeapMemory(const char * location)86 [[noreturn]] void FatalProcessOutOfHeapMemory(const char* location) { 87 UNREACHABLE(); 88 } 89 90 int GetNextScriptId(); 91 #if V8_SFI_HAS_UNIQUE_ID 92 int GetNextUniqueSharedFunctionInfoId(); 93 #endif // V8_SFI_HAS_UNIQUE_ID 94 95 bool is_collecting_type_profile() const; 96 logger()97 LocalLogger* logger() const { return logger_.get(); } thread_id()98 ThreadId thread_id() const { return thread_id_; } stack_limit()99 Address stack_limit() const { return stack_limit_; } runtime_call_stats()100 RuntimeCallStats* runtime_call_stats() const { return runtime_call_stats_; } bigint_processor()101 bigint::Processor* bigint_processor() { 102 if (!bigint_processor_) InitializeBigIntProcessor(); 103 return bigint_processor_; 104 } 105 is_main_thread()106 bool is_main_thread() const { return heap_.is_main_thread(); } 107 108 // AsIsolate is only allowed on the main-thread. AsIsolate()109 Isolate* AsIsolate() { 110 DCHECK(is_main_thread()); 111 DCHECK_EQ(ThreadId::Current(), isolate_->thread_id()); 112 return isolate_; 113 } AsLocalIsolate()114 LocalIsolate* AsLocalIsolate() { return this; } 115 pending_message_address()116 Object* pending_message_address() { 117 return isolate_->pending_message_address(); 118 } 119 120 private: 121 friend class v8::internal::LocalFactory; 122 123 void InitializeBigIntProcessor(); 124 125 LocalHeap heap_; 126 127 // TODO(leszeks): Extract out the fields of the Isolate we want and store 128 // those instead of the whole thing. 129 Isolate* const isolate_; 130 131 std::unique_ptr<LocalLogger> logger_; 132 ThreadId const thread_id_; 133 Address const stack_limit_; 134 135 RuntimeCallStats* runtime_call_stats_; 136 bigint::Processor* bigint_processor_{nullptr}; 137 }; 138 139 template <base::MutexSharedType kIsShared> 140 class V8_NODISCARD SharedMutexGuardIfOffThread<LocalIsolate, kIsShared> final { 141 public: SharedMutexGuardIfOffThread(base::SharedMutex * mutex,LocalIsolate * isolate)142 SharedMutexGuardIfOffThread(base::SharedMutex* mutex, LocalIsolate* isolate) { 143 DCHECK_NOT_NULL(mutex); 144 DCHECK_NOT_NULL(isolate); 145 if (!isolate->is_main_thread()) mutex_guard_.emplace(mutex); 146 } 147 148 SharedMutexGuardIfOffThread(const SharedMutexGuardIfOffThread&) = delete; 149 SharedMutexGuardIfOffThread& operator=(const SharedMutexGuardIfOffThread&) = 150 delete; 151 152 private: 153 base::Optional<base::SharedMutexGuard<kIsShared>> mutex_guard_; 154 }; 155 156 } // namespace internal 157 } // namespace v8 158 159 #endif // V8_EXECUTION_LOCAL_ISOLATE_H_ 160