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