#ifndef V8_EXECUTION_ISOLATE_INL_H_
#define V8_EXECUTION_ISOLATE_INL_H_
#include "src/execution/isolate.h"
#include "src/objects/contexts-inl.h"
#include "src/objects/js-function.h"
#include "src/objects/lookup-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/oddball.h"
#include "src/objects/property-cell.h"
#include "src/objects/regexp-match-info.h"
#include "src/objects/shared-function-info.h"
#include "src/objects/source-text-module-inl.h"
#ifdef DEBUG
#include "src/common/ptr-compr-inl.h"
#include "src/runtime/runtime-utils.h"
#endif
namespace v8::internal {
V8_INLINE Isolate::PerIsolateThreadData*
Isolate::CurrentPerIsolateThreadData() {
return g_current_per_isolate_thread_data_;
}
V8_INLINE Isolate* Isolate::Current() {
Isolate* isolate = TryGetCurrent();
DCHECK_NOT_NULL(isolate);
return isolate;
}
bool Isolate::IsCurrent() const { return this == TryGetCurrent(); }
void Isolate::set_context(Tagged<Context> context) {
DCHECK(context.is_null() || IsContext(context));
thread_local_top()->context_ = context;
}
Handle<NativeContext> Isolate::native_context() {
DCHECK(!context().is_null());
return handle(context()->native_context(), this);
}
Tagged<NativeContext> Isolate::raw_native_context() {
DCHECK(!context().is_null());
return context()->native_context();
}
void Isolate::set_topmost_script_having_context(Tagged<Context> context) {
DCHECK(context.is_null() || IsContext(context));
thread_local_top()->topmost_script_having_context_ = context;
}
void Isolate::clear_topmost_script_having_context() {
static_assert(Context::kNoContext == 0);
thread_local_top()->topmost_script_having_context_ = Context();
}
DirectHandle<NativeContext> Isolate::GetIncumbentContext() {
Tagged<Context> maybe_topmost_script_having_context =
topmost_script_having_context();
if (V8_LIKELY(!maybe_topmost_script_having_context.is_null())) {
DCHECK(current_vm_state() == EXTERNAL ||
current_vm_state() == JS);
Tagged<NativeContext> incumbent_context =
maybe_topmost_script_having_context->native_context();
DCHECK_EQ(incumbent_context, *GetIncumbentContextSlow());
return direct_handle(incumbent_context, this);
}
return GetIncumbentContextSlow();
}
void Isolate::set_pending_message(Tagged<Object> message_obj) {
DCHECK(IsTheHole(message_obj, this) || IsJSMessageObject(message_obj));
thread_local_top()->pending_message_ = message_obj;
}
Tagged<Object> Isolate::pending_message() {
return thread_local_top()->pending_message_;
}
void Isolate::clear_pending_message() {
set_pending_message(ReadOnlyRoots(this).the_hole_value());
}
bool Isolate::has_pending_message() {
return !IsTheHole(pending_message(), this);
}
Tagged<Object> Isolate::exception() {
CHECK(has_exception());
DCHECK(!IsExceptionHole(thread_local_top()->exception_, this));
return thread_local_top()->exception_;
}
void Isolate::set_exception(Tagged<Object> exception_obj) {
DCHECK(!IsExceptionHole(exception_obj, this));
thread_local_top()->exception_ = exception_obj;
}
void Isolate::clear_internal_exception() {
DCHECK(!IsExceptionHole(thread_local_top()->exception_, this));
thread_local_top()->exception_ = ReadOnlyRoots(this).the_hole_value();
}
void Isolate::clear_exception() {
clear_internal_exception();
if (try_catch_handler()) try_catch_handler()->Reset();
}
bool Isolate::has_exception() {
ThreadLocalTop* top = thread_local_top();
DCHECK(!IsExceptionHole(top->exception_, this));
return !IsTheHole(top->exception_, this);
}
bool Isolate::is_execution_terminating() {
return thread_local_top()->exception_ ==
i::ReadOnlyRoots(this).termination_exception();
}
#ifdef DEBUG
Tagged<Object> Isolate::VerifyBuiltinsResult(Tagged<Object> result) {
if (is_execution_terminating() && !v8_flags.strict_termination_checks) {
return ReadOnlyRoots(this).exception();
}
DCHECK_EQ(has_exception(),
result.SafeEquals(ReadOnlyRoots(this).exception()));
#ifdef V8_COMPRESS_POINTERS
Isolate* isolate;
if (!IsSmi(result) &&
GetIsolateFromHeapObject(Cast<HeapObject>(result), &isolate)) {
DCHECK(isolate == this || isolate == shared_space_isolate());
}
#endif
return result;
}
ObjectPair Isolate::VerifyBuiltinsResult(ObjectPair pair) {
#ifdef V8_HOST_ARCH_64_BIT
Tagged<Object> x(pair.x), y(pair.y);
DCHECK_EQ(has_exception(), x.SafeEquals(ReadOnlyRoots(this).exception()));
#ifdef V8_COMPRESS_POINTERS
Isolate* isolate;
if (!IsSmi(x) && GetIsolateFromHeapObject(Cast<HeapObject>(x), &isolate)) {
DCHECK(isolate == this || isolate == shared_space_isolate());
}
if (!IsSmi(y) && GetIsolateFromHeapObject(Cast<HeapObject>(y), &isolate)) {
DCHECK(isolate == this || isolate == shared_space_isolate());
}
#endif
#endif
return pair;
}
#endif
bool Isolate::is_catchable_by_javascript(Tagged<Object> exception) {
return exception != ReadOnlyRoots(heap()).termination_exception();
}
bool Isolate::is_catchable_by_wasm(Tagged<Object> exception) {
if (!is_catchable_by_javascript(exception)) return false;
if (!IsJSObject(exception)) return true;
return !LookupIterator::HasInternalMarkerProperty(
this, Cast<JSReceiver>(exception), factory()->wasm_uncatchable_symbol());
}
void Isolate::FireBeforeCallEnteredCallback() {
for (auto& callback : before_call_entered_callbacks_) {
callback(reinterpret_cast<v8::Isolate*>(this));
}
}
Handle<JSGlobalObject> Isolate::global_object() {
return handle(context()->global_object(), this);
}
Handle<JSGlobalProxy> Isolate::global_proxy() {
return handle(context()->global_proxy(), this);
}
Isolate::ExceptionScope::ExceptionScope(Isolate* isolate)
: isolate_(isolate), exception_(isolate_->exception(), isolate_) {
isolate_->clear_internal_exception();
}
Isolate::ExceptionScope::~ExceptionScope() {
isolate_->set_exception(*exception_);
}
bool Isolate::IsInitialArrayPrototype(Tagged<JSArray> array) {
DisallowGarbageCollection no_gc;
return IsInCreationContext(array, Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
}
#define NATIVE_CONTEXT_FIELD_ACCESSOR(index, type, name) \
Handle<UNPAREN(type)> Isolate::name() { \
DCHECK(!raw_native_context().is_null()); \
return Handle<UNPAREN(type)>(raw_native_context()->name(), this); \
} \
bool Isolate::is_##name(Tagged<UNPAREN(type)> value) { \
DCHECK(!raw_native_context().is_null()); \
return raw_native_context()->is_##name(value); \
}
NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSOR)
#undef NATIVE_CONTEXT_FIELD_ACCESSOR
SetCurrentIsolateScope::SetCurrentIsolateScope(Isolate* isolate)
: ptr_compr_cage_access_scope_(isolate),
previous_isolate_(Isolate::TryGetCurrent()) {
Isolate::SetCurrent(isolate);
}
SetCurrentIsolateScope::~SetCurrentIsolateScope() {
Isolate::SetCurrent(previous_isolate_);
}
}
#endif