blob: 2cddb1567e06bb3343c533cb495b0742f4bf857e [file] [log] [blame]
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_EXECUTION_LOCAL_ISOLATE_H_
#define V8_EXECUTION_LOCAL_ISOLATE_H_
#include "src/base/macros.h"
#include "src/execution/shared-mutex-guard-if-off-thread.h"
#include "src/execution/thread-id.h"
#include "src/handles/handles.h"
#include "src/handles/local-handles.h"
#include "src/handles/maybe-handles.h"
#include "src/heap/local-factory.h"
#include "src/heap/local-heap.h"
#include "src/logging/runtime-call-stats.h"
namespace v8 {
namespace bigint {
class Processor;
}
namespace internal {
class Isolate;
class LocalLogger;
class RuntimeCallStats;
// HiddenLocalFactory parallels Isolate's HiddenFactory
class V8_EXPORT_PRIVATE HiddenLocalFactory : private LocalFactory {
public:
// Forward constructors.
using LocalFactory::LocalFactory;
};
// And Isolate-like class that can be passed in to templated methods that need
// an isolate syntactically, but are usable off-thread.
//
// This class holds an LocalFactory, but is otherwise effectively a stub
// implementation of an Isolate. In particular, it doesn't allow throwing
// exceptions, and hard crashes if you try.
class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
public:
using HandleScopeType = LocalHandleScope;
explicit LocalIsolate(Isolate* isolate, ThreadKind kind);
~LocalIsolate();
// Kinda sketchy.
static LocalIsolate* FromHeap(LocalHeap* heap) {
return reinterpret_cast<LocalIsolate*>(reinterpret_cast<Address>(heap) -
OFFSET_OF(LocalIsolate, heap_));
}
bool is_main_thread() { return heap()->is_main_thread(); }
LocalHeap* heap() { return &heap_; }
inline Address cage_base() const;
inline Address code_cage_base() const;
inline ReadOnlyHeap* read_only_heap() const;
inline Object root(RootIndex index) const;
inline Handle<Object> root_handle(RootIndex index) const;
StringTable* string_table() const { return isolate_->string_table(); }
base::SharedMutex* internalized_string_access() {
return isolate_->internalized_string_access();
}
base::SharedMutex* shared_function_info_access() {
return isolate_->shared_function_info_access();
}
const AstStringConstants* ast_string_constants() {
return isolate_->ast_string_constants();
}
LazyCompileDispatcher* lazy_compile_dispatcher() {
return isolate_->lazy_compile_dispatcher();
}
V8FileLogger* main_thread_logger() {
// TODO(leszeks): This is needed for logging in ParseInfo. Figure out a way
// to use the LocalLogger for this instead.
return isolate_->v8_file_logger();
}
bool is_precise_binary_code_coverage() const {
return isolate_->is_precise_binary_code_coverage();
}
v8::internal::LocalFactory* factory() {
// Upcast to the privately inherited base-class using c-style casts to avoid
// undefined behavior (as static_cast cannot cast across private bases).
return (v8::internal::LocalFactory*)this;
}
AccountingAllocator* allocator() { return isolate_->allocator(); }
bool has_pending_exception() const { return false; }
void RegisterDeserializerStarted();
void RegisterDeserializerFinished();
bool has_active_deserializer() const;
template <typename T>
Handle<T> Throw(Handle<Object> exception) {
UNREACHABLE();
}
[[noreturn]] void FatalProcessOutOfHeapMemory(const char* location) {
UNREACHABLE();
}
int GetNextScriptId();
#if V8_SFI_HAS_UNIQUE_ID
int GetNextUniqueSharedFunctionInfoId();
#endif // V8_SFI_HAS_UNIQUE_ID
// TODO(cbruni): rename this back to logger() once the V8FileLogger
// refactoring is completed.
LocalLogger* v8_file_logger() const { return logger_.get(); }
ThreadId thread_id() const { return thread_id_; }
Address stack_limit() const { return stack_limit_; }
#ifdef V8_RUNTIME_CALL_STATS
RuntimeCallStats* runtime_call_stats() const { return runtime_call_stats_; }
#else
RuntimeCallStats* runtime_call_stats() const { return nullptr; }
#endif
bigint::Processor* bigint_processor() {
if (!bigint_processor_) InitializeBigIntProcessor();
return bigint_processor_;
}
bool is_main_thread() const { return heap_.is_main_thread(); }
// AsIsolate is only allowed on the main-thread.
Isolate* AsIsolate() {
DCHECK(is_main_thread());
DCHECK_EQ(ThreadId::Current(), isolate_->thread_id());
return isolate_;
}
LocalIsolate* AsLocalIsolate() { return this; }
// TODO(victorgomes): Remove this when/if MacroAssembler supports LocalIsolate
// only constructor.
Isolate* GetMainThreadIsolateUnsafe() const { return isolate_; }
Object* pending_message_address() {
return isolate_->pending_message_address();
}
#ifdef V8_INTL_SUPPORT
// WARNING: This might be out-of-sync with the main-thread.
const std::string& DefaultLocale();
#endif
private:
friend class v8::internal::LocalFactory;
friend class LocalIsolateFactory;
void InitializeBigIntProcessor();
LocalHeap heap_;
// TODO(leszeks): Extract out the fields of the Isolate we want and store
// those instead of the whole thing.
Isolate* const isolate_;
std::unique_ptr<LocalLogger> logger_;
ThreadId const thread_id_;
Address const stack_limit_;
bigint::Processor* bigint_processor_{nullptr};
#ifdef V8_RUNTIME_CALL_STATS
base::Optional<WorkerThreadRuntimeCallStatsScope> rcs_scope_;
RuntimeCallStats* runtime_call_stats_;
#endif
#ifdef V8_INTL_SUPPORT
std::string default_locale_;
#endif
};
template <base::MutexSharedType kIsShared>
class V8_NODISCARD SharedMutexGuardIfOffThread<LocalIsolate, kIsShared> final {
public:
SharedMutexGuardIfOffThread(base::SharedMutex* mutex, LocalIsolate* isolate) {
DCHECK_NOT_NULL(mutex);
DCHECK_NOT_NULL(isolate);
if (!isolate->is_main_thread()) mutex_guard_.emplace(mutex);
}
SharedMutexGuardIfOffThread(const SharedMutexGuardIfOffThread&) = delete;
SharedMutexGuardIfOffThread& operator=(const SharedMutexGuardIfOffThread&) =
delete;
private:
base::Optional<base::SharedMutexGuard<kIsShared>> mutex_guard_;
};
} // namespace internal
} // namespace v8
#endif // V8_EXECUTION_LOCAL_ISOLATE_H_