[isolate] Move HandleScopeImplementer to IsolateData
To allow faster access from hot generated code, this commit moves the HandleScopeImplementer directly into IsolateData, enabling access via the root register. To support this migration, the following changes were made: * Extracted HandleScopeImplementer from api.cc and api.h into its own dedicated files in src/handles/. * Replaced std::optional for last_handle_before_persistent_block_ with a raw pointer and a sentinel value to optimize the structure. * Updated builtins and assembler code to access the implementer via IsolateFieldId rather than relying on an external reference. Change-Id: I3a5d8997363e02d94f3b4628423624951b93bd8e Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7881490 Commit-Queue: Andreas Haas <ahaas@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/main@{#107761}
This commit is contained in:
1 parent
be01443eed
commit
5127e5f8d5
53 files changed
+561
-418
No files matched your search
@@ -1754,6 +1754,9 @@ filegroup(
|
||||
"src/handles/global-handles.cc",
|
||||
"src/handles/global-handles.h",
|
||||
"src/handles/global-handles-inl.h",
|
||||
"src/handles/handle-scope-implementer.cc",
|
||||
"src/handles/handle-scope-implementer.h",
|
||||
"src/handles/handle-scope-implementer-inl.h",
|
||||
"src/handles/handles.cc",
|
||||
"src/handles/handles.h",
|
||||
"src/handles/handles-inl.h",
|
||||
|
||||
@@ -4075,6 +4075,8 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/flags/save-flags.h",
|
||||
"src/handles/global-handles-inl.h",
|
||||
"src/handles/global-handles.h",
|
||||
"src/handles/handle-scope-implementer-inl.h",
|
||||
"src/handles/handle-scope-implementer.h",
|
||||
"src/handles/handles-inl.h",
|
||||
"src/handles/handles.h",
|
||||
"src/handles/local-handles-inl.h",
|
||||
@@ -5997,6 +5999,7 @@ v8_cluster_source_set("v8_base_without_compiler") {
|
||||
"src/flags/flags.cc",
|
||||
"src/flags/save-flags.cc",
|
||||
"src/handles/global-handles.cc",
|
||||
"src/handles/handle-scope-implementer.cc",
|
||||
"src/handles/handles.cc",
|
||||
"src/handles/local-handles.cc",
|
||||
"src/handles/persistent-handles.cc",
|
||||
|
||||
@@ -1045,6 +1045,8 @@ class Internals {
|
||||
static const int kThreadLocalTopSize = 30 * kApiSystemPointerSize;
|
||||
static const int kHandleScopeDataSize =
|
||||
2 * kApiSystemPointerSize + 2 * kApiInt32Size;
|
||||
static const int kHandleScopeImplementerSize =
|
||||
11 * kApiSystemPointerSize + kHandleScopeDataSize;
|
||||
|
||||
// ExternalPointerTable and TrustedPointerTable layout guarantees.
|
||||
static const int kExternalEntityTableBasePointerOffset = 0;
|
||||
@@ -1089,8 +1091,10 @@ class Internals {
|
||||
kIsolateLongTaskStatsCounterOffset + kApiSizetSize;
|
||||
static const int kIsolateHandleScopeDataOffset =
|
||||
kIsolateThreadLocalTopOffset + kThreadLocalTopSize;
|
||||
static const int kIsolateEmbedderDataOffset =
|
||||
static const int kIsolateHandleScopeImplementerOffset =
|
||||
kIsolateHandleScopeDataOffset + kHandleScopeDataSize;
|
||||
static const int kIsolateEmbedderDataOffset =
|
||||
kIsolateHandleScopeImplementerOffset + kHandleScopeImplementerSize;
|
||||
#ifdef V8_COMPRESS_POINTERS
|
||||
static const int kIsolateExternalPointerTableOffset =
|
||||
kIsolateEmbedderDataOffset + kNumIsolateDataSlots * kApiSystemPointerSize;
|
||||
|
||||
@@ -501,20 +501,6 @@ inline bool V8_EXPORT TryToCopyAndConvertArrayToCppBuffer(Local<Array> src,
|
||||
uint32_t max_length) {
|
||||
return CopyAndConvertArrayToCppBuffer<type_info_id, T>(src, dst, max_length);
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
void HandleScopeImplementer::EnterContext(Tagged<NativeContext> context) {
|
||||
entered_contexts_.push_back(context);
|
||||
isolate_->set_last_entered_context(context);
|
||||
}
|
||||
|
||||
DirectHandle<NativeContext> HandleScopeImplementer::LastEnteredContext() {
|
||||
if (entered_contexts_.empty()) return {};
|
||||
return direct_handle(entered_contexts_.back(), isolate_);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_API_API_INL_H_
|
||||
+1
-132
@@ -68,6 +68,7 @@
|
||||
#include "src/execution/v8threads.h"
|
||||
#include "src/execution/vm-state-inl.h"
|
||||
#include "src/handles/global-handles.h"
|
||||
#include "src/handles/handle-scope-implementer-inl.h"
|
||||
#include "src/handles/persistent-handles.h"
|
||||
#include "src/handles/shared-object-conveyor-handles.h"
|
||||
#include "src/handles/traced-handles-inl.h"
|
||||
@@ -12165,138 +12166,6 @@ std::shared_ptr<WasmStreaming> WasmStreaming::Unpack(Isolate* v8_isolate,
|
||||
|
||||
namespace internal {
|
||||
|
||||
const size_t HandleScopeImplementer::kEnteredContextsOffset =
|
||||
offsetof(HandleScopeImplementer, entered_contexts_);
|
||||
|
||||
void HandleScopeImplementer::FreeThreadResources() { Free(); }
|
||||
|
||||
char* HandleScopeImplementer::ArchiveThread(char* storage) {
|
||||
HandleScopeData* current = isolate_->handle_scope_data();
|
||||
handle_scope_data_ = *current;
|
||||
MemCopy(storage, this, sizeof(*this));
|
||||
|
||||
ResetAfterArchive();
|
||||
current->Initialize();
|
||||
|
||||
return storage + ArchiveSpacePerThread();
|
||||
}
|
||||
|
||||
int HandleScopeImplementer::ArchiveSpacePerThread() {
|
||||
return sizeof(HandleScopeImplementer);
|
||||
}
|
||||
|
||||
char* HandleScopeImplementer::RestoreThread(char* storage) {
|
||||
MemCopy(this, storage, sizeof(*this));
|
||||
*isolate_->handle_scope_data() = handle_scope_data_;
|
||||
isolate_->set_last_entered_context(entered_contexts_.empty()
|
||||
? Tagged<NativeContext>()
|
||||
: entered_contexts_.back());
|
||||
return storage + ArchiveSpacePerThread();
|
||||
}
|
||||
|
||||
void HandleScopeImplementer::IterateThis(RootVisitor* v) {
|
||||
#ifdef DEBUG
|
||||
bool found_block_before_persistent = false;
|
||||
#endif
|
||||
// Iterate over all handles in the blocks except for the last.
|
||||
for (int i = static_cast<int>(blocks()->size()) - 2; i >= 0; --i) {
|
||||
Address* block = blocks()->at(i);
|
||||
// Cast possibly-unrelated pointers to plain Address before comparing them
|
||||
// to avoid undefined behavior.
|
||||
if (HasPersistentScope() &&
|
||||
(reinterpret_cast<Address>(
|
||||
last_handle_before_persistent_block_.value()) <=
|
||||
reinterpret_cast<Address>(&block[kHandleBlockSize])) &&
|
||||
(reinterpret_cast<Address>(
|
||||
last_handle_before_persistent_block_.value()) >=
|
||||
reinterpret_cast<Address>(block))) {
|
||||
v->VisitRootPointers(
|
||||
Root::kHandleScope, nullptr, FullObjectSlot(block),
|
||||
FullObjectSlot(last_handle_before_persistent_block_.value()));
|
||||
DCHECK(!found_block_before_persistent);
|
||||
#ifdef DEBUG
|
||||
found_block_before_persistent = true;
|
||||
#endif
|
||||
} else {
|
||||
v->VisitRootPointers(Root::kHandleScope, nullptr, FullObjectSlot(block),
|
||||
FullObjectSlot(&block[kHandleBlockSize]));
|
||||
}
|
||||
}
|
||||
|
||||
DCHECK_EQ(HasPersistentScope() &&
|
||||
last_handle_before_persistent_block_.value() != nullptr,
|
||||
found_block_before_persistent);
|
||||
|
||||
// Iterate over live handles in the last block (if any).
|
||||
if (!blocks()->empty()) {
|
||||
v->VisitRootPointers(Root::kHandleScope, nullptr,
|
||||
FullObjectSlot(blocks()->back()),
|
||||
FullObjectSlot(handle_scope_data_.next));
|
||||
}
|
||||
|
||||
v->VisitRootPointer(Root::kHandleScope, nullptr,
|
||||
FullObjectSlot(isolate_->last_entered_context_address()));
|
||||
|
||||
saved_contexts_.shrink_to_fit();
|
||||
if (!saved_contexts_.empty()) {
|
||||
FullObjectSlot start(&saved_contexts_.front());
|
||||
v->VisitRootPointers(Root::kHandleScope, nullptr, start,
|
||||
start + static_cast<int>(saved_contexts_.size()));
|
||||
}
|
||||
entered_contexts_.shrink_to_fit();
|
||||
if (!entered_contexts_.empty()) {
|
||||
FullObjectSlot start(&entered_contexts_.front());
|
||||
v->VisitRootPointers(Root::kHandleScope, nullptr, start,
|
||||
start + static_cast<int>(entered_contexts_.size()));
|
||||
}
|
||||
}
|
||||
|
||||
void HandleScopeImplementer::Iterate(RootVisitor* v) {
|
||||
HandleScopeData* current = isolate_->handle_scope_data();
|
||||
handle_scope_data_ = *current;
|
||||
IterateThis(v);
|
||||
}
|
||||
|
||||
char* HandleScopeImplementer::Iterate(RootVisitor* v, char* storage) {
|
||||
HandleScopeImplementer* scope_implementer =
|
||||
reinterpret_cast<HandleScopeImplementer*>(storage);
|
||||
scope_implementer->IterateThis(v);
|
||||
return storage + ArchiveSpacePerThread();
|
||||
}
|
||||
|
||||
std::unique_ptr<PersistentHandles> HandleScopeImplementer::DetachPersistent(
|
||||
Address* first_block) {
|
||||
std::unique_ptr<PersistentHandles> ph(new PersistentHandles(isolate()));
|
||||
DCHECK(HasPersistentScope());
|
||||
DCHECK_NOT_NULL(first_block);
|
||||
|
||||
Address* block_start;
|
||||
do {
|
||||
block_start = blocks_.back();
|
||||
ph->blocks_.push_back(blocks_.back());
|
||||
#if DEBUG
|
||||
ph->ordered_blocks_.insert(blocks_.back());
|
||||
#endif
|
||||
blocks_.pop_back();
|
||||
} while (block_start != first_block);
|
||||
|
||||
// ph->blocks_ now contains the blocks installed on the HandleScope stack
|
||||
// since BeginPersistentScope was called, but in reverse order.
|
||||
|
||||
// Switch first and last blocks, such that the last block is the one
|
||||
// that is potentially half full.
|
||||
DCHECK(!ph->blocks_.empty());
|
||||
std::swap(ph->blocks_.front(), ph->blocks_.back());
|
||||
|
||||
ph->block_next_ = isolate()->handle_scope_data()->next;
|
||||
block_start = ph->blocks_.back();
|
||||
ph->block_limit_ = block_start + kHandleBlockSize;
|
||||
|
||||
DCHECK_EQ(blocks_.empty(),
|
||||
last_handle_before_persistent_block_.value() == nullptr);
|
||||
last_handle_before_persistent_block_.reset();
|
||||
return ph;
|
||||
}
|
||||
|
||||
void InvokeAccessorGetterCallback(
|
||||
v8::Local<v8::Name> property,
|
||||
|
||||
+1
-197
@@ -15,7 +15,6 @@
|
||||
#include "include/v8-typed-array.h"
|
||||
#include "include/v8-wasm.h"
|
||||
#include "src/base/contextual.h"
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/objects/bigint.h"
|
||||
#include "src/objects/contexts.h"
|
||||
#include "src/objects/js-array-buffer.h"
|
||||
@@ -38,6 +37,7 @@ class Template;
|
||||
enum class Intercepted : uint32_t;
|
||||
|
||||
namespace internal {
|
||||
class Isolate;
|
||||
class JSArrayBufferView;
|
||||
class JSFinalizationRegistry;
|
||||
} // namespace internal
|
||||
@@ -318,202 +318,6 @@ namespace internal {
|
||||
|
||||
class PersistentHandles;
|
||||
|
||||
// This class is here in order to be able to declare it a friend of
|
||||
// HandleScope. Moving these methods to be members of HandleScope would be
|
||||
// neat in some ways, but it would expose internal implementation details in
|
||||
// our public header file, which is undesirable.
|
||||
//
|
||||
// An isolate has a single instance of this class to hold the current thread's
|
||||
// data. In multithreaded V8 programs this data is copied in and out of storage
|
||||
// so that the currently executing thread always has its own copy of this
|
||||
// data.
|
||||
class HandleScopeImplementer {
|
||||
public:
|
||||
class V8_NODISCARD EnteredContextRewindScope {
|
||||
public:
|
||||
explicit EnteredContextRewindScope(HandleScopeImplementer* hsi)
|
||||
: hsi_(hsi), saved_entered_context_count_(hsi->EnteredContextCount()) {}
|
||||
|
||||
~EnteredContextRewindScope() {
|
||||
DCHECK_LE(saved_entered_context_count_, hsi_->EnteredContextCount());
|
||||
while (saved_entered_context_count_ < hsi_->EnteredContextCount()) {
|
||||
hsi_->LeaveContext();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
HandleScopeImplementer* hsi_;
|
||||
size_t saved_entered_context_count_;
|
||||
};
|
||||
|
||||
explicit HandleScopeImplementer(Isolate* isolate)
|
||||
: isolate_(isolate), spare_(nullptr) {}
|
||||
|
||||
~HandleScopeImplementer() { DeleteArray(spare_); }
|
||||
|
||||
HandleScopeImplementer(const HandleScopeImplementer&) = delete;
|
||||
HandleScopeImplementer& operator=(const HandleScopeImplementer&) = delete;
|
||||
|
||||
// Threading support for handle data.
|
||||
static int ArchiveSpacePerThread();
|
||||
char* RestoreThread(char* from);
|
||||
char* ArchiveThread(char* to);
|
||||
void FreeThreadResources();
|
||||
|
||||
// Garbage collection support.
|
||||
V8_EXPORT_PRIVATE void Iterate(i::RootVisitor* v);
|
||||
V8_EXPORT_PRIVATE static char* Iterate(i::RootVisitor* v, char* data);
|
||||
|
||||
inline internal::Address* GetSpareOrNewBlock();
|
||||
inline void DeleteExtensions(internal::Address* prev_limit);
|
||||
|
||||
inline void EnterContext(Tagged<NativeContext> context);
|
||||
inline void LeaveContext();
|
||||
inline bool LastEnteredContextWas(Tagged<NativeContext> context);
|
||||
inline size_t EnteredContextCount() const { return entered_contexts_.size(); }
|
||||
|
||||
// Returns the last entered context or an empty handle if no
|
||||
// contexts have been entered.
|
||||
inline DirectHandle<NativeContext> LastEnteredContext();
|
||||
|
||||
inline void SaveContext(Tagged<Context> context);
|
||||
inline Tagged<Context> RestoreContext();
|
||||
inline bool HasSavedContexts();
|
||||
|
||||
inline DetachableVector<Address*>* blocks() { return &blocks_; }
|
||||
Isolate* isolate() const { return isolate_; }
|
||||
|
||||
void ReturnBlock(Address* block) {
|
||||
DCHECK_NOT_NULL(block);
|
||||
if (spare_ != nullptr) DeleteArray(spare_);
|
||||
spare_ = block;
|
||||
}
|
||||
|
||||
static const size_t kEnteredContextsOffset;
|
||||
|
||||
private:
|
||||
void ResetAfterArchive() {
|
||||
blocks_.detach();
|
||||
entered_contexts_.detach();
|
||||
saved_contexts_.detach();
|
||||
spare_ = nullptr;
|
||||
last_handle_before_persistent_block_.reset();
|
||||
isolate_->set_last_entered_context(Tagged<NativeContext>());
|
||||
}
|
||||
|
||||
void Free() {
|
||||
DCHECK(blocks_.empty());
|
||||
DCHECK(entered_contexts_.empty());
|
||||
DCHECK(saved_contexts_.empty());
|
||||
|
||||
blocks_.free();
|
||||
entered_contexts_.free();
|
||||
saved_contexts_.free();
|
||||
if (spare_ != nullptr) {
|
||||
DeleteArray(spare_);
|
||||
spare_ = nullptr;
|
||||
}
|
||||
DCHECK(isolate_->thread_local_top()->CallDepthIsZero());
|
||||
}
|
||||
|
||||
void BeginPersistentScope() {
|
||||
DCHECK(!last_handle_before_persistent_block_.has_value());
|
||||
last_handle_before_persistent_block_ = isolate()->handle_scope_data()->next;
|
||||
}
|
||||
bool HasPersistentScope() const {
|
||||
return last_handle_before_persistent_block_.has_value();
|
||||
}
|
||||
std::unique_ptr<PersistentHandles> DetachPersistent(Address* first_block);
|
||||
|
||||
Isolate* isolate_;
|
||||
DetachableVector<Address*> blocks_;
|
||||
|
||||
// Used as a stack to keep track of entered contexts.
|
||||
DetachableVector<Tagged<NativeContext>> entered_contexts_;
|
||||
|
||||
// Used as a stack to keep track of saved contexts.
|
||||
DetachableVector<Tagged<Context>> saved_contexts_;
|
||||
Address* spare_;
|
||||
std::optional<Address*> last_handle_before_persistent_block_;
|
||||
// This is only used for threading support.
|
||||
HandleScopeData handle_scope_data_;
|
||||
|
||||
void IterateThis(RootVisitor* v);
|
||||
char* RestoreThreadHelper(char* from);
|
||||
char* ArchiveThreadHelper(char* to);
|
||||
|
||||
friend class HandleScopeImplementerOffsets;
|
||||
friend class PersistentHandlesScope;
|
||||
};
|
||||
|
||||
const int kHandleBlockSize = i::KB - 2; // fit in one page
|
||||
|
||||
void HandleScopeImplementer::SaveContext(Tagged<Context> context) {
|
||||
saved_contexts_.push_back(context);
|
||||
}
|
||||
|
||||
Tagged<Context> HandleScopeImplementer::RestoreContext() {
|
||||
Tagged<Context> last_context = saved_contexts_.back();
|
||||
saved_contexts_.pop_back();
|
||||
return last_context;
|
||||
}
|
||||
|
||||
bool HandleScopeImplementer::HasSavedContexts() {
|
||||
return !saved_contexts_.empty();
|
||||
}
|
||||
|
||||
void HandleScopeImplementer::LeaveContext() {
|
||||
DCHECK(!entered_contexts_.empty());
|
||||
entered_contexts_.pop_back();
|
||||
isolate_->set_last_entered_context(entered_contexts_.empty()
|
||||
? Tagged<NativeContext>()
|
||||
: entered_contexts_.back());
|
||||
}
|
||||
|
||||
bool HandleScopeImplementer::LastEnteredContextWas(
|
||||
Tagged<NativeContext> context) {
|
||||
return !entered_contexts_.empty() && entered_contexts_.back() == context;
|
||||
}
|
||||
|
||||
// If there's a spare block, use it for growing the current scope.
|
||||
internal::Address* HandleScopeImplementer::GetSpareOrNewBlock() {
|
||||
internal::Address* block =
|
||||
(spare_ != nullptr) ? spare_
|
||||
: NewArray<internal::Address>(kHandleBlockSize);
|
||||
spare_ = nullptr;
|
||||
return block;
|
||||
}
|
||||
|
||||
void HandleScopeImplementer::DeleteExtensions(internal::Address* prev_limit) {
|
||||
while (!blocks_.empty()) {
|
||||
internal::Address* block_start = blocks_.back();
|
||||
internal::Address* block_limit = block_start + kHandleBlockSize;
|
||||
|
||||
// SealHandleScope may make the prev_limit to point inside the block.
|
||||
// Cast possibly-unrelated pointers to plain Address before comparing them
|
||||
// to avoid undefined behavior.
|
||||
if (reinterpret_cast<Address>(block_start) <
|
||||
reinterpret_cast<Address>(prev_limit) &&
|
||||
reinterpret_cast<Address>(prev_limit) <=
|
||||
reinterpret_cast<Address>(block_limit)) {
|
||||
#ifdef ENABLE_LOCAL_HANDLE_ZAPPING
|
||||
internal::HandleScope::ZapRange(prev_limit, block_limit);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
blocks_.pop_back();
|
||||
#ifdef ENABLE_LOCAL_HANDLE_ZAPPING
|
||||
internal::HandleScope::ZapRange(block_start, block_limit);
|
||||
#endif
|
||||
if (spare_ != nullptr) {
|
||||
DeleteArray(spare_);
|
||||
}
|
||||
spare_ = block_start;
|
||||
}
|
||||
DCHECK((blocks_.empty() && prev_limit == nullptr) ||
|
||||
(!blocks_.empty() && prev_limit != nullptr));
|
||||
}
|
||||
|
||||
// This is a wrapper function called from CallApiGetter builtin when profiling
|
||||
// or side-effect checking is enabled. It's supposed to set up the runtime
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/api/api-inl.h"
|
||||
#include "src/builtins/builtins-utils-inl.h"
|
||||
#include "src/builtins/builtins.h"
|
||||
#include "src/codegen/code-factory.h"
|
||||
#include "src/codegen/compiler.h"
|
||||
#include "src/handles/handle-scope-implementer-inl.h"
|
||||
#include "src/logging/counters.h"
|
||||
#include "src/numbers/conversions.h"
|
||||
#include "src/objects/api-callbacks.h"
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/api/api.h"
|
||||
#include "src/builtins/builtins-utils-gen.h"
|
||||
#include "src/codegen/code-stub-assembler-inl.h"
|
||||
#include "src/execution/microtask-queue.h"
|
||||
#include "src/handles/handle-scope-implementer.h"
|
||||
#include "src/objects/js-generator-inl.h"
|
||||
#include "src/objects/js-weak-refs.h"
|
||||
#include "src/objects/microtask-inl.h"
|
||||
@@ -150,18 +150,11 @@ void MicrotaskQueueBuiltinsAssembler::PrepareForContext(
|
||||
if (DEBUG_BOOL) {
|
||||
// Postcondition: entered_contexts_.back() == native_context, i.e. the
|
||||
// context the microtask is about to run in is visible to API callers.
|
||||
using ContextStack = DetachableVector<Context>;
|
||||
TNode<IntPtrT> size_offset =
|
||||
IntPtrConstant(HandleScopeImplementer::kEnteredContextsOffset +
|
||||
ContextStack::kSizeOffset);
|
||||
TNode<IntPtrT> data_offset =
|
||||
IntPtrConstant(HandleScopeImplementer::kEnteredContextsOffset +
|
||||
ContextStack::kDataOffset);
|
||||
auto ref = ExternalReference::handle_scope_implementer_address(isolate());
|
||||
TNode<RawPtrT> hsi = Load<RawPtrT>(ExternalConstant(ref));
|
||||
TNode<IntPtrT> size = Load<IntPtrT>(hsi, size_offset);
|
||||
TNode<IntPtrT> size =
|
||||
Load<IntPtrT>(IsolateField(IsolateFieldId::kEnteredContextCount));
|
||||
CSA_CHECK(this, IntPtrGreaterThan(size, IntPtrConstant(0)));
|
||||
TNode<RawPtrT> data = Load<RawPtrT>(hsi, data_offset);
|
||||
TNode<RawPtrT> data =
|
||||
Load<RawPtrT>(IsolateField(IsolateFieldId::kEnteredContextData));
|
||||
TNode<Object> back = LoadFullTagged(
|
||||
data, TimesSystemPointerSize(IntPtrSub(size, IntPtrConstant(1))));
|
||||
CSA_CHECK(this, TaggedEqual(back, native_context));
|
||||
@@ -581,42 +574,32 @@ void MicrotaskQueueBuiltinsAssembler::SetCurrentContext(
|
||||
}
|
||||
|
||||
TNode<IntPtrT> MicrotaskQueueBuiltinsAssembler::GetEnteredContextCount() {
|
||||
auto ref = ExternalReference::handle_scope_implementer_address(isolate());
|
||||
TNode<RawPtrT> hsi = Load<RawPtrT>(ExternalConstant(ref));
|
||||
|
||||
using ContextStack = DetachableVector<Context>;
|
||||
TNode<IntPtrT> size_offset =
|
||||
IntPtrConstant(HandleScopeImplementer::kEnteredContextsOffset +
|
||||
ContextStack::kSizeOffset);
|
||||
return Load<IntPtrT>(hsi, size_offset);
|
||||
return Load<IntPtrT>(IsolateField(IsolateFieldId::kEnteredContextCount));
|
||||
}
|
||||
|
||||
void MicrotaskQueueBuiltinsAssembler::EnterContext(
|
||||
TNode<Context> native_context) {
|
||||
CSA_DCHECK(this, IsNativeContext(native_context));
|
||||
|
||||
auto ref = ExternalReference::handle_scope_implementer_address(isolate());
|
||||
TNode<RawPtrT> hsi = Load<RawPtrT>(ExternalConstant(ref));
|
||||
TNode<RawPtrT> hsi = ReinterpretCast<RawPtrT>(
|
||||
IsolateField(IsolateFieldId::kHandleScopeImplementer));
|
||||
|
||||
using ContextStack = DetachableVector<Context>;
|
||||
TNode<IntPtrT> capacity_offset =
|
||||
IntPtrConstant(HandleScopeImplementer::kEnteredContextsOffset +
|
||||
ContextStack::kCapacityOffset);
|
||||
TNode<IntPtrT> size_offset =
|
||||
IntPtrConstant(HandleScopeImplementer::kEnteredContextsOffset +
|
||||
ContextStack::kSizeOffset);
|
||||
|
||||
TNode<IntPtrT> capacity = Load<IntPtrT>(hsi, capacity_offset);
|
||||
TNode<IntPtrT> size = Load<IntPtrT>(hsi, size_offset);
|
||||
TNode<IntPtrT> capacity =
|
||||
Load<IntPtrT>(IsolateField(IsolateFieldId::kEnteredContextCapacity));
|
||||
TNode<IntPtrT> size =
|
||||
Load<IntPtrT>(IsolateField(IsolateFieldId::kEnteredContextCount));
|
||||
|
||||
Label if_append(this), if_grow(this, Label::kDeferred), done(this);
|
||||
Branch(WordEqual(size, capacity), &if_grow, &if_append);
|
||||
BIND(&if_append);
|
||||
{
|
||||
TNode<IntPtrT> data_offset =
|
||||
IntPtrConstant(HandleScopeImplementer::kEnteredContextsOffset +
|
||||
ContextStack::kDataOffset);
|
||||
TNode<RawPtrT> data = Load<RawPtrT>(hsi, data_offset);
|
||||
TNode<RawPtrT> data =
|
||||
Load<RawPtrT>(IsolateField(IsolateFieldId::kEnteredContextData));
|
||||
StoreFullTaggedNoWriteBarrier(data, TimesSystemPointerSize(size),
|
||||
native_context);
|
||||
|
||||
@@ -645,8 +628,8 @@ void MicrotaskQueueBuiltinsAssembler::EnterContext(
|
||||
|
||||
void MicrotaskQueueBuiltinsAssembler::RewindEnteredContext(
|
||||
TNode<IntPtrT> saved_entered_context_count) {
|
||||
auto ref = ExternalReference::handle_scope_implementer_address(isolate());
|
||||
TNode<RawPtrT> hsi = Load<RawPtrT>(ExternalConstant(ref));
|
||||
TNode<RawPtrT> hsi = ReinterpretCast<RawPtrT>(
|
||||
IsolateField(IsolateFieldId::kHandleScopeImplementer));
|
||||
|
||||
using ContextStack = DetachableVector<Context>;
|
||||
TNode<IntPtrT> size_offset =
|
||||
@@ -654,7 +637,8 @@ void MicrotaskQueueBuiltinsAssembler::RewindEnteredContext(
|
||||
ContextStack::kSizeOffset);
|
||||
|
||||
if (DEBUG_BOOL) {
|
||||
TNode<IntPtrT> size = Load<IntPtrT>(hsi, size_offset);
|
||||
TNode<IntPtrT> size =
|
||||
Load<IntPtrT>(IsolateField(IsolateFieldId::kEnteredContextCount));
|
||||
CSA_CHECK(this, IntPtrLessThanOrEqual(saved_entered_context_count, size));
|
||||
}
|
||||
|
||||
@@ -672,10 +656,8 @@ void MicrotaskQueueBuiltinsAssembler::RewindEnteredContext(
|
||||
}
|
||||
BIND(&if_not_empty);
|
||||
{
|
||||
TNode<IntPtrT> data_offset =
|
||||
IntPtrConstant(HandleScopeImplementer::kEnteredContextsOffset +
|
||||
ContextStack::kDataOffset);
|
||||
TNode<RawPtrT> data = Load<RawPtrT>(hsi, data_offset);
|
||||
TNode<RawPtrT> data =
|
||||
Load<RawPtrT>(IsolateField(IsolateFieldId::kEnteredContextData));
|
||||
TNode<IntPtrT> index =
|
||||
IntPtrSub(saved_entered_context_count, IntPtrConstant(1));
|
||||
TNode<Object> last_context =
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "src/builtins/builtins.h"
|
||||
|
||||
#include "src/api/api-inl.h"
|
||||
#include "src/base/logging.h"
|
||||
#include "src/builtins/builtins-descriptors.h"
|
||||
#include "src/builtins/builtins-inl.h"
|
||||
@@ -15,6 +14,7 @@
|
||||
#include "src/codegen/macro-assembler.h"
|
||||
#include "src/diagnostics/code-tracer.h"
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/handles/handle-scope-implementer-inl.h"
|
||||
#include "src/heap/combined-heap.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
#include "src/logging/code-events.h" // For CodeCreateEvent.
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "src/objects/heap-number.h"
|
||||
#include "src/objects/heap-object.h"
|
||||
#include "src/objects/hole.h"
|
||||
#include "src/objects/js-collection.h"
|
||||
#include "src/objects/js-function.h"
|
||||
#include "src/objects/js-objects.h"
|
||||
#include "src/objects/js-promise.h"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include "include/cppgc/allocation.h"
|
||||
#include "include/v8-fast-api-calls.h"
|
||||
#include "src/api/api-inl.h"
|
||||
#include "src/api/api.h"
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/ieee754.h"
|
||||
#include "src/base/logging.h"
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/execution/microtask-queue.h"
|
||||
#include "src/execution/simulator.h"
|
||||
#include "src/handles/handle-scope-implementer-inl.h"
|
||||
#include "src/heap/heap-inl.h"
|
||||
#include "src/heap/heap.h"
|
||||
#include "src/ic/stub-cache.h"
|
||||
@@ -281,11 +282,6 @@ ExternalReference ExternalReference::isolate_address() {
|
||||
return ExternalReference(IsolateFieldId::kIsolateAddress);
|
||||
}
|
||||
|
||||
ExternalReference ExternalReference::handle_scope_implementer_address(
|
||||
Isolate* isolate) {
|
||||
return ExternalReference(isolate->handle_scope_implementer_address());
|
||||
}
|
||||
|
||||
#ifdef V8_ENABLE_SANDBOX
|
||||
ExternalReference ExternalReference::sandbox_base_address() {
|
||||
return ExternalReference(Sandbox::current()->base_address());
|
||||
|
||||
@@ -28,8 +28,6 @@ enum class IsolateFieldId : uint8_t;
|
||||
// TODO(ishell): Remove entries accessible via IsolateFieldId.
|
||||
#define EXTERNAL_REFERENCE_LIST_WITH_ISOLATE(V) \
|
||||
V(isolate_address, "isolate") \
|
||||
V(handle_scope_implementer_address, \
|
||||
"Isolate::handle_scope_implementer_address") \
|
||||
V(address_of_interpreter_entry_trampoline_instruction_start, \
|
||||
"Address of the InterpreterEntryTrampoline instruction start") \
|
||||
V(interpreter_dispatch_table_address, "Interpreter::dispatch_table_address") \
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "src/compiler/js-operator.h"
|
||||
#include "src/compiler/simplified-operator.h"
|
||||
#include "src/compiler/write-barrier-kind.h"
|
||||
#include "src/objects/bigint.h"
|
||||
#include "src/objects/elements-kind.h"
|
||||
#include "src/objects/js-objects.h"
|
||||
#include "src/objects/property-details.h"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "src/objects/instance-type.h"
|
||||
#include "src/objects/object-list-macros.h"
|
||||
#include "src/objects/property-details.h"
|
||||
#include "src/objects/shared-function-info.h"
|
||||
#include "src/utils/boxed-float.h"
|
||||
#include "src/zone/zone-compact-set.h"
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
|
||||
#include "src/api/api.h"
|
||||
#include "src/base/container-utils.h"
|
||||
#include "src/base/small-vector.h"
|
||||
#include "src/builtins/builtins-promise.h"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "src/api/api.h"
|
||||
#include "src/base/iterator.h"
|
||||
#include "src/base/logging.h"
|
||||
#include "src/builtins/accessors.h"
|
||||
|
||||
@@ -15,11 +15,22 @@
|
||||
#include "src/codegen/tnode.h"
|
||||
#include "src/compiler/turboshaft/fast-hash.h"
|
||||
#include "src/compiler/turboshaft/representations.h"
|
||||
#include "src/objects/bigint.h"
|
||||
#include "src/objects/contexts.h"
|
||||
#include "src/objects/heap-number.h"
|
||||
#include "src/objects/js-array-buffer.h"
|
||||
#include "src/objects/js-collection.h"
|
||||
#include "src/objects/js-function.h"
|
||||
#include "src/objects/js-generator.h"
|
||||
#include "src/objects/js-promise.h"
|
||||
#include "src/objects/js-proxy.h"
|
||||
#include "src/objects/objects.h"
|
||||
#include "src/objects/oddball.h"
|
||||
#include "src/objects/shared-function-info.h"
|
||||
#include "src/objects/source-text-module.h"
|
||||
#include "src/objects/string.h"
|
||||
#include "src/objects/tagged.h"
|
||||
#include "src/objects/templates.h"
|
||||
|
||||
#define TURBOSHAFT_ALLOW_IMPLICIT_OPINDEX_INITIALIZATION_FOR_V 1
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
#include "src/api/api.h"
|
||||
#include "src/base/logging.h"
|
||||
#include "src/base/macros.h"
|
||||
#include "src/base/small-vector.h"
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "include/v8-container.h"
|
||||
#include "include/v8-template.h"
|
||||
#include "src/api/api.h"
|
||||
|
||||
namespace v8 {
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/api/api.h"
|
||||
#include "src/base/platform/platform-win32.h"
|
||||
#include "src/base/platform/platform.h"
|
||||
#include "src/d8/d8.h"
|
||||
|
||||
@@ -63,6 +63,8 @@ static constexpr int kFastCCallAlignmentPaddingCount = 1;
|
||||
V(LongTaskStatsCounter, kSizetSize, long_task_stats_counter) \
|
||||
V(ThreadLocalTop, ThreadLocalTop::kSizeInBytes, thread_local_top) \
|
||||
V(HandleScopeData, HandleScopeData::kSizeInBytes, handle_scope_data) \
|
||||
V(HandleScopeImplementer, HandleScopeImplementer::kSizeInBytes, \
|
||||
handle_scope_implementer) \
|
||||
V(EmbedderData, Internals::kNumIsolateDataSlots* kSystemPointerSize, \
|
||||
embedder_data) \
|
||||
ISOLATE_DATA_FIELDS_POINTER_COMPRESSION(V) \
|
||||
@@ -172,6 +174,18 @@ static constexpr int kFastCCallAlignmentPaddingCount = 1;
|
||||
V(HandleScopeLimit, handle_scope_limit, handle_scope_data, \
|
||||
offsetof(HandleScopeData, limit)) \
|
||||
\
|
||||
/* HandleScopeImplementer fields. */ \
|
||||
V(EnteredContextCount, entered_context_count, handle_scope_implementer, \
|
||||
static_cast<int>(HandleScopeImplementer::kEnteredContextsOffset + \
|
||||
DetachableVectorBase::kSizeOffset)) \
|
||||
V(EnteredContextCapacity, entered_context_capacity, \
|
||||
handle_scope_implementer, \
|
||||
static_cast<int>(HandleScopeImplementer::kEnteredContextsOffset + \
|
||||
DetachableVectorBase::kCapacityOffset)) \
|
||||
V(EnteredContextData, entered_context_data, handle_scope_implementer, \
|
||||
static_cast<int>(HandleScopeImplementer::kEnteredContextsOffset + \
|
||||
DetachableVectorBase::kDataOffset)) \
|
||||
\
|
||||
/* NewAllocationInfo fields. */ \
|
||||
V(NewAllocationInfoStart, new_allocation_info_start, new_allocation_info, \
|
||||
LinearAllocationArea::StartOffset()) \
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "src/execution/isolate-data-fields.h"
|
||||
#include "src/execution/stack-guard.h"
|
||||
#include "src/execution/thread-local-top.h"
|
||||
#include "src/handles/handle-scope-implementer.h"
|
||||
#include "src/heap/linear-allocation-area.h"
|
||||
#include "src/init/isolate-group.h"
|
||||
#include "src/roots/roots.h"
|
||||
@@ -93,7 +94,8 @@ class IsolateData final {
|
||||
#ifdef V8_COMPRESS_POINTERS
|
||||
cage_base_(group->GetPtrComprCageBase()),
|
||||
#endif
|
||||
stack_guard_(isolate)
|
||||
stack_guard_(isolate),
|
||||
handle_scope_implementer_()
|
||||
#ifdef V8_ENABLE_SANDBOX
|
||||
,
|
||||
trusted_cage_base_(group->GetTrustedPtrComprCageBase())
|
||||
@@ -200,6 +202,12 @@ class IsolateData final {
|
||||
}
|
||||
ThreadLocalTop& thread_local_top() { return thread_local_top_; }
|
||||
ThreadLocalTop const& thread_local_top() const { return thread_local_top_; }
|
||||
HandleScopeImplementer* handle_scope_implementer() {
|
||||
return &handle_scope_implementer_;
|
||||
}
|
||||
const HandleScopeImplementer* handle_scope_implementer() const {
|
||||
return &handle_scope_implementer_;
|
||||
}
|
||||
Address* builtin_entry_table() { return builtin_entry_table_; }
|
||||
Address* builtin_table() { return builtin_table_; }
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
@@ -379,6 +387,7 @@ class IsolateData final {
|
||||
|
||||
ThreadLocalTop thread_local_top_;
|
||||
HandleScopeData handle_scope_data_;
|
||||
HandleScopeImplementer handle_scope_implementer_;
|
||||
|
||||
// These fields are accessed through the API, offsets must be kept in sync
|
||||
// with v8::internal::Internals (in include/v8-internal.h) constants. The
|
||||
@@ -471,6 +480,7 @@ class IsolateData final {
|
||||
|
||||
V8_INLINE static void AssertPredictableLayout();
|
||||
|
||||
friend class HandleScopeImplementer;
|
||||
friend class Isolate;
|
||||
friend class Heap;
|
||||
FRIEND_TEST(HeapTest, ExternalLimitDefault);
|
||||
|
||||
@@ -682,6 +682,8 @@ void Isolate::Iterate(RootVisitor* v, ThreadLocalTop* thread) {
|
||||
FullObjectSlot(&thread->pending_message_));
|
||||
v->VisitRootPointer(Root::kStackRoots, nullptr,
|
||||
FullObjectSlot(&thread->context_));
|
||||
v->VisitRootPointer(Root::kStackRoots, nullptr,
|
||||
FullObjectSlot(&thread->last_entered_context_));
|
||||
|
||||
for (v8::TryCatch* block = thread->try_catch_handler_; block != nullptr;
|
||||
block = block->next_) {
|
||||
@@ -4857,6 +4859,9 @@ void Isolate::CheckIsolateLayout() {
|
||||
static_assert(
|
||||
static_cast<int>(OFFSET_OF(Isolate, isolate_data_.handle_scope_data_)) ==
|
||||
Internals::kIsolateHandleScopeDataOffset);
|
||||
static_assert(static_cast<int>(OFFSET_OF(
|
||||
Isolate, isolate_data_.handle_scope_implementer_)) ==
|
||||
Internals::kIsolateHandleScopeImplementerOffset);
|
||||
static_assert(
|
||||
static_cast<int>(OFFSET_OF(Isolate, isolate_data_.embedder_data_)) ==
|
||||
Internals::kIsolateEmbedderDataOffset);
|
||||
@@ -5317,9 +5322,6 @@ Isolate::~Isolate() {
|
||||
delete v8_file_logger_;
|
||||
v8_file_logger_ = nullptr;
|
||||
|
||||
delete handle_scope_implementer_;
|
||||
handle_scope_implementer_ = nullptr;
|
||||
|
||||
delete code_tracer();
|
||||
set_code_tracer(nullptr);
|
||||
|
||||
@@ -6118,7 +6120,6 @@ bool Isolate::Init(SnapshotData* startup_snapshot_data,
|
||||
global_handles_ = new GlobalHandles(this);
|
||||
eternal_handles_ = new EternalHandles();
|
||||
bootstrapper_ = new Bootstrapper(this);
|
||||
handle_scope_implementer_ = new HandleScopeImplementer(this);
|
||||
load_stub_cache_ = new StubCache(this);
|
||||
store_stub_cache_ = new StubCache(this);
|
||||
define_own_stub_cache_ = new StubCache(this);
|
||||
|
||||
+13
-8
@@ -1216,7 +1216,17 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
|
||||
OFFSET_OF(Isolate, heap_));
|
||||
}
|
||||
|
||||
static Isolate* FromHandleScopeImplementer(
|
||||
const HandleScopeImplementer* handle_scope_implementer) {
|
||||
Address hsi_addr = reinterpret_cast<Address>(handle_scope_implementer);
|
||||
Address isolate_addr = hsi_addr -
|
||||
IsolateData::kHandleScopeImplementerOffset -
|
||||
OFFSET_OF(Isolate, isolate_data_);
|
||||
return reinterpret_cast<Isolate*>(isolate_addr);
|
||||
}
|
||||
|
||||
const IsolateData* isolate_data() const { return &isolate_data_; }
|
||||
|
||||
IsolateData* isolate_data() { return &isolate_data_; }
|
||||
|
||||
// When pointer compression is on, this is the base address of the pointer
|
||||
@@ -1399,9 +1409,8 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
|
||||
return &isolate_data_.handle_scope_data_;
|
||||
}
|
||||
|
||||
HandleScopeImplementer* handle_scope_implementer() const {
|
||||
DCHECK(handle_scope_implementer_);
|
||||
return handle_scope_implementer_;
|
||||
HandleScopeImplementer* handle_scope_implementer() {
|
||||
return isolate_data_.handle_scope_implementer();
|
||||
}
|
||||
|
||||
UnicodeCache* unicode_cache() const { return unicode_cache_; }
|
||||
@@ -1901,10 +1910,6 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
|
||||
javascript_execution_counter_++;
|
||||
}
|
||||
|
||||
Address handle_scope_implementer_address() {
|
||||
return reinterpret_cast<Address>(&handle_scope_implementer_);
|
||||
}
|
||||
|
||||
void SetReleaseCppHeapCallback(v8::Isolate::ReleaseCppHeapCallback callback);
|
||||
|
||||
void RunReleaseCppHeapCallback(std::unique_ptr<v8::CppHeap> cpp_heap);
|
||||
@@ -2652,7 +2657,6 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
|
||||
StackTrace::StackTraceOptions stack_trace_for_uncaught_exceptions_options_ =
|
||||
StackTrace::kOverview;
|
||||
DescriptorLookupCache* descriptor_lookup_cache_ = nullptr;
|
||||
HandleScopeImplementer* handle_scope_implementer_ = nullptr;
|
||||
UnicodeCache* unicode_cache_ = nullptr;
|
||||
AccountingAllocator* allocator_ = nullptr;
|
||||
InnerPointerToCodeCache* inner_pointer_to_code_cache_ = nullptr;
|
||||
@@ -3016,6 +3020,7 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
|
||||
|
||||
bool is_frozen_ = false;
|
||||
|
||||
friend class HandleScopeImplementer;
|
||||
friend class GlobalSafepoint;
|
||||
friend class heap::HeapTester;
|
||||
friend class IsolateForPointerCompression;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "src/api/api-inl.h"
|
||||
#include "src/base/logging.h"
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/handles/handle-scope-implementer-inl.h"
|
||||
#include "src/handles/handles-inl.h"
|
||||
#include "src/objects/microtask-inl.h"
|
||||
#include "src/objects/visitors.h"
|
||||
|
||||
@@ -21,6 +21,7 @@ void ThreadLocalTop::Clear() {
|
||||
c_entry_fp_ = kNullAddress;
|
||||
c_function_ = kNullAddress;
|
||||
context_ = {};
|
||||
last_entered_context_ = {};
|
||||
topmost_script_having_context_ = {};
|
||||
thread_id_ = ThreadId();
|
||||
pending_handler_entrypoint_ = kNullAddress;
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
#include "src/execution/v8threads.h"
|
||||
|
||||
#include "include/v8-locker.h"
|
||||
#include "src/api/api.h"
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/execution/execution.h"
|
||||
#include "src/execution/isolate-inl.h"
|
||||
#include "src/execution/stack-guard.h"
|
||||
#include "src/handles/handle-scope-implementer.h"
|
||||
#include "src/init/bootstrapper.h"
|
||||
#include "src/objects/visitors.h"
|
||||
#include "src/regexp/regexp-stack.h"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "src/extensions/statistics-extension.h"
|
||||
|
||||
#include "include/v8-template.h"
|
||||
#include "src/api/api.h"
|
||||
#include "src/common/assert-scope.h"
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/heap/heap-inl.h" // crbug.com/v8/8499
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
// Copyright 2026 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_HANDLES_HANDLE_SCOPE_IMPLEMENTER_INL_H_
|
||||
#define V8_HANDLES_HANDLE_SCOPE_IMPLEMENTER_INL_H_
|
||||
|
||||
#include "src/handles/handle-scope-implementer.h"
|
||||
#include "src/handles/handles-inl.h"
|
||||
#include "src/heap/heap-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
void HandleScopeImplementer::SaveContext(Tagged<Context> context) {
|
||||
saved_contexts_.push_back(context);
|
||||
}
|
||||
|
||||
Tagged<Context> HandleScopeImplementer::RestoreContext() {
|
||||
Tagged<Context> last_context = saved_contexts_.back();
|
||||
saved_contexts_.pop_back();
|
||||
return last_context;
|
||||
}
|
||||
|
||||
bool HandleScopeImplementer::HasSavedContexts() {
|
||||
return !saved_contexts_.empty();
|
||||
}
|
||||
|
||||
void HandleScopeImplementer::LeaveContext() {
|
||||
DCHECK(!entered_contexts_.empty());
|
||||
entered_contexts_.pop_back();
|
||||
Isolate::FromHandleScopeImplementer(this)->set_last_entered_context(
|
||||
entered_contexts_.empty() ? Tagged<NativeContext>()
|
||||
: entered_contexts_.back());
|
||||
}
|
||||
|
||||
HandleScopeImplementer::EnteredContextRewindScope::EnteredContextRewindScope(
|
||||
HandleScopeImplementer* hsi)
|
||||
: hsi_(hsi), saved_entered_context_count_(hsi->EnteredContextCount()) {}
|
||||
|
||||
HandleScopeImplementer::EnteredContextRewindScope::
|
||||
~EnteredContextRewindScope() {
|
||||
DCHECK_LE(saved_entered_context_count_, hsi_->EnteredContextCount());
|
||||
while (saved_entered_context_count_ < hsi_->EnteredContextCount()) {
|
||||
hsi_->LeaveContext();
|
||||
}
|
||||
}
|
||||
|
||||
bool HandleScopeImplementer::LastEnteredContextWas(
|
||||
Tagged<NativeContext> context) {
|
||||
return !entered_contexts_.empty() && entered_contexts_.back() == context;
|
||||
}
|
||||
|
||||
// If there's a spare block, use it for growing the current scope.
|
||||
internal::Address* HandleScopeImplementer::GetSpareOrNewBlock() {
|
||||
internal::Address* block =
|
||||
(spare_ != nullptr) ? spare_
|
||||
: NewArray<internal::Address>(kHandleBlockSize);
|
||||
spare_ = nullptr;
|
||||
return block;
|
||||
}
|
||||
|
||||
void HandleScopeImplementer::DeleteExtensions(internal::Address* prev_limit) {
|
||||
while (!blocks_.empty()) {
|
||||
internal::Address* block_start = blocks_.back();
|
||||
internal::Address* block_limit = block_start + kHandleBlockSize;
|
||||
|
||||
// SealHandleScope may make the prev_limit to point inside the block.
|
||||
// Cast possibly-unrelated pointers to plain Address before comparing them
|
||||
// to avoid undefined behavior.
|
||||
if (reinterpret_cast<Address>(block_start) <
|
||||
reinterpret_cast<Address>(prev_limit) &&
|
||||
reinterpret_cast<Address>(prev_limit) <=
|
||||
reinterpret_cast<Address>(block_limit)) {
|
||||
#ifdef ENABLE_LOCAL_HANDLE_ZAPPING
|
||||
internal::HandleScope::ZapRange(prev_limit, block_limit);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
blocks_.pop_back();
|
||||
#ifdef ENABLE_LOCAL_HANDLE_ZAPPING
|
||||
internal::HandleScope::ZapRange(block_start, block_limit);
|
||||
#endif
|
||||
if (spare_ != nullptr) {
|
||||
DeleteArray(spare_);
|
||||
}
|
||||
spare_ = block_start;
|
||||
}
|
||||
DCHECK((blocks_.empty() && prev_limit == nullptr) ||
|
||||
(!blocks_.empty() && prev_limit != nullptr));
|
||||
}
|
||||
|
||||
void HandleScopeImplementer::EnterContext(Tagged<NativeContext> context) {
|
||||
entered_contexts_.push_back(context);
|
||||
Isolate::FromHandleScopeImplementer(this)->set_last_entered_context(context);
|
||||
}
|
||||
|
||||
DirectHandle<NativeContext> HandleScopeImplementer::LastEnteredContext() {
|
||||
if (entered_contexts_.empty()) return {};
|
||||
return direct_handle(entered_contexts_.back(),
|
||||
Isolate::FromHandleScopeImplementer(this));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_HANDLES_HANDLE_SCOPE_IMPLEMENTER_INL_H_
|
||||
@@ -0,0 +1,178 @@
|
||||
// Copyright 2026 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.
|
||||
|
||||
#include "src/handles/handle-scope-implementer.h"
|
||||
|
||||
#include "src/execution/isolate-data.h"
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/handles/handle-scope-implementer-inl.h"
|
||||
#include "src/handles/persistent-handles.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
void HandleScopeImplementer::ResetAfterArchive() {
|
||||
blocks_.detach();
|
||||
entered_contexts_.detach();
|
||||
saved_contexts_.detach();
|
||||
spare_ = nullptr;
|
||||
last_handle_before_persistent_block_ = kInvalidLastHandle;
|
||||
Isolate::FromHandleScopeImplementer(this)->set_last_entered_context(
|
||||
Tagged<NativeContext>());
|
||||
}
|
||||
|
||||
void HandleScopeImplementer::Free() {
|
||||
DCHECK(blocks_.empty());
|
||||
DCHECK(entered_contexts_.empty());
|
||||
DCHECK(saved_contexts_.empty());
|
||||
|
||||
blocks_.free();
|
||||
entered_contexts_.free();
|
||||
saved_contexts_.free();
|
||||
if (spare_ != nullptr) {
|
||||
DeleteArray(spare_);
|
||||
spare_ = nullptr;
|
||||
}
|
||||
DCHECK(Isolate::FromHandleScopeImplementer(this)
|
||||
->thread_local_top()
|
||||
->CallDepthIsZero());
|
||||
}
|
||||
|
||||
void HandleScopeImplementer::BeginPersistentScope() {
|
||||
DCHECK_EQ(last_handle_before_persistent_block_, kInvalidLastHandle);
|
||||
last_handle_before_persistent_block_ =
|
||||
Isolate::FromHandleScopeImplementer(this)->handle_scope_data()->next;
|
||||
}
|
||||
|
||||
void HandleScopeImplementer::FreeThreadResources() { Free(); }
|
||||
|
||||
char* HandleScopeImplementer::ArchiveThread(char* storage) {
|
||||
HandleScopeData* current =
|
||||
Isolate::FromHandleScopeImplementer(this)->handle_scope_data();
|
||||
handle_scope_data_ = *current;
|
||||
MemCopy(storage, this, sizeof(*this));
|
||||
|
||||
ResetAfterArchive();
|
||||
current->Initialize();
|
||||
|
||||
return storage + ArchiveSpacePerThread();
|
||||
}
|
||||
|
||||
int HandleScopeImplementer::ArchiveSpacePerThread() {
|
||||
return sizeof(HandleScopeImplementer);
|
||||
}
|
||||
|
||||
char* HandleScopeImplementer::RestoreThread(char* storage) {
|
||||
MemCopy(this, storage, sizeof(*this));
|
||||
*Isolate::FromHandleScopeImplementer(this)->handle_scope_data() =
|
||||
handle_scope_data_;
|
||||
Isolate::FromHandleScopeImplementer(this)->set_last_entered_context(
|
||||
entered_contexts_.empty() ? Tagged<NativeContext>()
|
||||
: entered_contexts_.back());
|
||||
return storage + ArchiveSpacePerThread();
|
||||
}
|
||||
|
||||
void HandleScopeImplementer::IterateThis(RootVisitor* v) {
|
||||
#ifdef DEBUG
|
||||
bool found_block_before_persistent = false;
|
||||
#endif
|
||||
// Iterate over all handles in the blocks except for the last.
|
||||
for (int i = static_cast<int>(blocks()->size()) - 2; i >= 0; --i) {
|
||||
Address* block = blocks()->at(i);
|
||||
// Cast possibly-unrelated pointers to plain Address before comparing them
|
||||
// to avoid undefined behavior.
|
||||
if (HasPersistentScope() &&
|
||||
(reinterpret_cast<Address>(last_handle_before_persistent_block_) <=
|
||||
reinterpret_cast<Address>(&block[kHandleBlockSize])) &&
|
||||
(reinterpret_cast<Address>(last_handle_before_persistent_block_) >=
|
||||
reinterpret_cast<Address>(block))) {
|
||||
v->VisitRootPointers(
|
||||
Root::kHandleScope, nullptr, FullObjectSlot(block),
|
||||
FullObjectSlot(last_handle_before_persistent_block_));
|
||||
DCHECK(!found_block_before_persistent);
|
||||
#ifdef DEBUG
|
||||
found_block_before_persistent = true;
|
||||
#endif
|
||||
} else {
|
||||
v->VisitRootPointers(Root::kHandleScope, nullptr, FullObjectSlot(block),
|
||||
FullObjectSlot(&block[kHandleBlockSize]));
|
||||
}
|
||||
}
|
||||
|
||||
DCHECK_EQ(
|
||||
HasPersistentScope() && last_handle_before_persistent_block_ != nullptr,
|
||||
found_block_before_persistent);
|
||||
|
||||
// Iterate over live handles in the last block (if any).
|
||||
if (!blocks()->empty()) {
|
||||
v->VisitRootPointers(Root::kHandleScope, nullptr,
|
||||
FullObjectSlot(blocks()->back()),
|
||||
FullObjectSlot(handle_scope_data_.next));
|
||||
}
|
||||
|
||||
saved_contexts_.shrink_to_fit();
|
||||
if (!saved_contexts_.empty()) {
|
||||
FullObjectSlot start(&saved_contexts_.front());
|
||||
v->VisitRootPointers(Root::kHandleScope, nullptr, start,
|
||||
start + static_cast<int>(saved_contexts_.size()));
|
||||
}
|
||||
entered_contexts_.shrink_to_fit();
|
||||
if (!entered_contexts_.empty()) {
|
||||
FullObjectSlot start(&entered_contexts_.front());
|
||||
v->VisitRootPointers(Root::kHandleScope, nullptr, start,
|
||||
start + static_cast<int>(entered_contexts_.size()));
|
||||
}
|
||||
}
|
||||
|
||||
void HandleScopeImplementer::Iterate(RootVisitor* v) {
|
||||
HandleScopeData* current =
|
||||
Isolate::FromHandleScopeImplementer(this)->handle_scope_data();
|
||||
handle_scope_data_ = *current;
|
||||
IterateThis(v);
|
||||
}
|
||||
|
||||
char* HandleScopeImplementer::Iterate(RootVisitor* v, char* storage) {
|
||||
HandleScopeImplementer* scope_implementer =
|
||||
reinterpret_cast<HandleScopeImplementer*>(storage);
|
||||
scope_implementer->IterateThis(v);
|
||||
return storage + ArchiveSpacePerThread();
|
||||
}
|
||||
|
||||
std::unique_ptr<PersistentHandles> HandleScopeImplementer::DetachPersistent(
|
||||
Address* first_block) {
|
||||
std::unique_ptr<PersistentHandles> ph(
|
||||
new PersistentHandles(Isolate::FromHandleScopeImplementer(this)));
|
||||
DCHECK(HasPersistentScope());
|
||||
DCHECK_NOT_NULL(first_block);
|
||||
|
||||
Address* block_start;
|
||||
do {
|
||||
block_start = blocks_.back();
|
||||
ph->blocks_.push_back(blocks_.back());
|
||||
#if DEBUG
|
||||
ph->ordered_blocks_.insert(blocks_.back());
|
||||
#endif
|
||||
blocks_.pop_back();
|
||||
} while (block_start != first_block);
|
||||
|
||||
// ph->blocks_ now contains the blocks installed on the HandleScope stack
|
||||
// since BeginPersistentScope was called, but in reverse order.
|
||||
|
||||
// Switch first and last blocks, such that the last block is the one
|
||||
// that is potentially half full.
|
||||
DCHECK(!ph->blocks_.empty());
|
||||
std::swap(ph->blocks_.front(), ph->blocks_.back());
|
||||
|
||||
ph->block_next_ =
|
||||
Isolate::FromHandleScopeImplementer(this)->handle_scope_data()->next;
|
||||
block_start = ph->blocks_.back();
|
||||
ph->block_limit_ = block_start + kHandleBlockSize;
|
||||
|
||||
DCHECK_EQ(blocks_.empty(), last_handle_before_persistent_block_ == nullptr);
|
||||
last_handle_before_persistent_block_ = kInvalidLastHandle;
|
||||
return ph;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
@@ -0,0 +1,133 @@
|
||||
// Copyright 2026 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_HANDLES_HANDLE_SCOPE_IMPLEMENTER_H_
|
||||
#define V8_HANDLES_HANDLE_SCOPE_IMPLEMENTER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "include/v8-internal.h"
|
||||
#include "src/base/macros.h"
|
||||
#include "src/objects/contexts.h"
|
||||
#include "src/utils/detachable-vector.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class Isolate;
|
||||
class PersistentHandles;
|
||||
|
||||
// This class is here in order to be able to declare it a friend of
|
||||
// HandleScope. Moving these methods to be members of HandleScope would be
|
||||
// neat in some ways, but it would expose internal implementation details in
|
||||
// our public header file, which is undesirable.
|
||||
//
|
||||
// An isolate has a single instance of this class to hold the current thread's
|
||||
// data. In multithreaded V8 programs this data is copied in and out of storage
|
||||
// so that the currently executing thread always has its own copy of this
|
||||
// data.
|
||||
class HandleScopeImplementer {
|
||||
public:
|
||||
static constexpr int kSizeInBytes =
|
||||
11 * kSystemPointerSize + HandleScopeData::kSizeInBytes;
|
||||
|
||||
class V8_NODISCARD EnteredContextRewindScope {
|
||||
public:
|
||||
explicit inline EnteredContextRewindScope(HandleScopeImplementer* hsi);
|
||||
inline ~EnteredContextRewindScope();
|
||||
|
||||
private:
|
||||
HandleScopeImplementer* hsi_;
|
||||
size_t saved_entered_context_count_;
|
||||
};
|
||||
|
||||
HandleScopeImplementer() : spare_(nullptr) {}
|
||||
|
||||
~HandleScopeImplementer() { DeleteArray(spare_); }
|
||||
|
||||
HandleScopeImplementer(const HandleScopeImplementer&) = delete;
|
||||
HandleScopeImplementer& operator=(const HandleScopeImplementer&) = delete;
|
||||
|
||||
// Threading support for handle data.
|
||||
static int ArchiveSpacePerThread();
|
||||
char* RestoreThread(char* from);
|
||||
char* ArchiveThread(char* to);
|
||||
void FreeThreadResources();
|
||||
|
||||
// Garbage collection support.
|
||||
V8_EXPORT_PRIVATE void Iterate(RootVisitor* v);
|
||||
V8_EXPORT_PRIVATE static char* Iterate(RootVisitor* v, char* data);
|
||||
|
||||
inline internal::Address* GetSpareOrNewBlock();
|
||||
inline void DeleteExtensions(internal::Address* prev_limit);
|
||||
|
||||
inline void EnterContext(Tagged<NativeContext> context);
|
||||
inline void LeaveContext();
|
||||
inline bool LastEnteredContextWas(Tagged<NativeContext> context);
|
||||
inline size_t EnteredContextCount() const { return entered_contexts_.size(); }
|
||||
|
||||
// Returns the last entered context or an empty handle if no
|
||||
// contexts have been entered.
|
||||
inline DirectHandle<NativeContext> LastEnteredContext();
|
||||
|
||||
inline void SaveContext(Tagged<Context> context);
|
||||
inline Tagged<Context> RestoreContext();
|
||||
inline bool HasSavedContexts();
|
||||
|
||||
inline DetachableVector<Address*>* blocks() { return &blocks_; }
|
||||
|
||||
void ReturnBlock(Address* block) {
|
||||
DCHECK_NOT_NULL(block);
|
||||
if (spare_ != nullptr) DeleteArray(spare_);
|
||||
spare_ = block;
|
||||
}
|
||||
|
||||
static const size_t kEnteredContextsOffset;
|
||||
|
||||
private:
|
||||
static constexpr Address kSentinel = kNullAddress;
|
||||
static constexpr Address* kInvalidLastHandle =
|
||||
const_cast<Address*>(&kSentinel);
|
||||
|
||||
void ResetAfterArchive();
|
||||
|
||||
void Free();
|
||||
void BeginPersistentScope();
|
||||
bool HasPersistentScope() const {
|
||||
return last_handle_before_persistent_block_ != kInvalidLastHandle;
|
||||
}
|
||||
std::unique_ptr<PersistentHandles> DetachPersistent(Address* first_block);
|
||||
|
||||
DetachableVector<Address*> blocks_;
|
||||
|
||||
// Used as a stack to keep track of entered contexts.
|
||||
DetachableVector<Tagged<NativeContext>> entered_contexts_;
|
||||
|
||||
// Used as a stack to keep track of saved contexts.
|
||||
DetachableVector<Tagged<Context>> saved_contexts_;
|
||||
Address* spare_;
|
||||
Address* last_handle_before_persistent_block_ = kInvalidLastHandle;
|
||||
// This is only used for threading support.
|
||||
HandleScopeData handle_scope_data_;
|
||||
|
||||
void IterateThis(RootVisitor* v);
|
||||
char* RestoreThreadHelper(char* from);
|
||||
char* ArchiveThreadHelper(char* to);
|
||||
|
||||
friend class HandleScopeImplementerOffsets;
|
||||
friend class PersistentHandlesScope;
|
||||
};
|
||||
|
||||
inline constexpr size_t HandleScopeImplementer::kEnteredContextsOffset =
|
||||
offsetof(HandleScopeImplementer, entered_contexts_);
|
||||
|
||||
static_assert(HandleScopeImplementer::kSizeInBytes ==
|
||||
sizeof(HandleScopeImplementer));
|
||||
|
||||
const int kHandleBlockSize = KB - 2; // fit in one page
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_HANDLES_HANDLE_SCOPE_IMPLEMENTER_H_
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "src/codegen/optimized-compilation-info.h"
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/execution/thread-id.h"
|
||||
#include "src/handles/handle-scope-implementer-inl.h"
|
||||
#include "src/handles/maybe-handles.h"
|
||||
#include "src/heap/base/stack.h"
|
||||
#include "src/heap/heap-layout-inl.h"
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
#include "src/handles/local-handles.h"
|
||||
|
||||
#include "src/api/api.h"
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/handles/handle-scope-implementer.h"
|
||||
#include "src/handles/handles-inl.h"
|
||||
#include "src/handles/handles.h"
|
||||
#include "src/heap/heap-inl.h"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "src/handles/persistent-handles.h"
|
||||
|
||||
#include "src/api/api.h"
|
||||
#include "src/handles/handle-scope-implementer-inl.h"
|
||||
#include "src/heap/heap-inl.h"
|
||||
#include "src/heap/safepoint.h"
|
||||
#include "src/utils/allocation.h"
|
||||
@@ -139,7 +139,8 @@ void PersistentHandlesList::Iterate(RootVisitor* visitor, Isolate* isolate) {
|
||||
PersistentHandlesScope::PersistentHandlesScope(Isolate* isolate)
|
||||
: impl_(isolate->handle_scope_implementer()) {
|
||||
impl_->BeginPersistentScope();
|
||||
HandleScopeData* data = impl_->isolate()->handle_scope_data();
|
||||
HandleScopeData* data =
|
||||
Isolate::FromHandleScopeImplementer(impl_)->handle_scope_data();
|
||||
Address* new_next = impl_->GetSpareOrNewBlock();
|
||||
Address* new_limit = &new_next[kHandleBlockSize];
|
||||
impl_->blocks()->push_back(new_next);
|
||||
@@ -157,13 +158,16 @@ PersistentHandlesScope::PersistentHandlesScope(Isolate* isolate)
|
||||
|
||||
PersistentHandlesScope::~PersistentHandlesScope() {
|
||||
DCHECK(handles_detached_);
|
||||
impl_->isolate()->handle_scope_data()->level--;
|
||||
DCHECK_EQ(impl_->isolate()->handle_scope_data()->level, prev_level_);
|
||||
Isolate::FromHandleScopeImplementer(impl_)->handle_scope_data()->level--;
|
||||
DCHECK_EQ(
|
||||
Isolate::FromHandleScopeImplementer(impl_)->handle_scope_data()->level,
|
||||
prev_level_);
|
||||
}
|
||||
|
||||
std::unique_ptr<PersistentHandles> PersistentHandlesScope::Detach() {
|
||||
std::unique_ptr<PersistentHandles> ph = impl_->DetachPersistent(first_block_);
|
||||
HandleScopeData* data = impl_->isolate()->handle_scope_data();
|
||||
HandleScopeData* data =
|
||||
Isolate::FromHandleScopeImplementer(impl_)->handle_scope_data();
|
||||
data->next = prev_next_;
|
||||
data->limit = prev_limit_;
|
||||
#ifdef DEBUG
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
#include <vector>
|
||||
|
||||
#include "include/v8-internal.h"
|
||||
#include "src/api/api.h"
|
||||
#include "src/base/macros.h"
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/handles/handle-scope-implementer.h"
|
||||
#include "src/objects/visitors.h"
|
||||
#include "testing/gtest/include/gtest/gtest_prod.h" // nogncheck
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "src/objects/map-word-inl.h"
|
||||
#include "src/objects/object-predicates-inl.h"
|
||||
#include "src/objects/slots-inl.h"
|
||||
#include "src/objects/templates.h"
|
||||
#include "src/objects/visitors-inl.h"
|
||||
#include "src/roots/static-roots.h"
|
||||
#include "src/utils/allocation.h"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
|
||||
#include "src/api/api.h"
|
||||
#include "src/base/bounds.h"
|
||||
#include "src/base/logging.h"
|
||||
#include "src/base/macros.h"
|
||||
|
||||
@@ -45,6 +45,11 @@
|
||||
#include "src/maglev/maglev-regalloc-node-info.h"
|
||||
#include "src/objects/arguments.h"
|
||||
#include "src/objects/heap-number.h"
|
||||
#include "src/objects/js-array-buffer.h"
|
||||
#include "src/objects/js-collection.h"
|
||||
#include "src/objects/js-generator.h"
|
||||
#include "src/objects/js-promise.h"
|
||||
#include "src/objects/js-proxy.h"
|
||||
#include "src/objects/property-details.h"
|
||||
#include "src/objects/smi.h"
|
||||
#include "src/objects/tagged-index.h"
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
// Include the non-inl header before the rest of the headers.
|
||||
|
||||
#include "src/heap/heap-write-barrier-inl.h"
|
||||
// The include of `biging.h` is needed because BigInt is part of JSAny.
|
||||
#include "src/objects/bigint.h"
|
||||
#include "src/objects/smi-inl.h"
|
||||
#include "src/objects/tagged-field-inl.h"
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "src/objects/module.h"
|
||||
// Include the non-inl header before the rest of the headers.
|
||||
|
||||
#include "src/objects/js-promise-inl.h"
|
||||
#include "src/objects/scope-info.h"
|
||||
#include "src/objects/source-text-module.h"
|
||||
#include "src/objects/string-inl.h"
|
||||
|
||||
@@ -8,8 +8,11 @@
|
||||
#include "src/objects/source-text-module.h"
|
||||
// Include the non-inl header before the rest of the headers.
|
||||
|
||||
#include "src/objects/js-function-inl.h"
|
||||
#include "src/objects/js-generator-inl.h"
|
||||
#include "src/objects/module-inl.h"
|
||||
#include "src/objects/objects-inl.h"
|
||||
#include "src/objects/shared-function-info-inl.h"
|
||||
|
||||
// Has to be the last include (doesn't have include guards):
|
||||
#include "src/objects/object-macros.h"
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/execution/local-isolate.h"
|
||||
#include "src/heap/factory.h"
|
||||
#include "src/objects/objects.h"
|
||||
#include "src/objects/string.h"
|
||||
#include "src/utils/memcopy.h"
|
||||
|
||||
namespace v8 {
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "src/api/api-inl.h"
|
||||
#include "src/api/api.h"
|
||||
#include "src/builtins/builtins-utils.h"
|
||||
#include "src/builtins/builtins.h"
|
||||
#include "src/builtins/superspread.h"
|
||||
@@ -15,6 +13,7 @@
|
||||
#include "src/execution/messages.h"
|
||||
#include "src/execution/protectors-inl.h"
|
||||
#include "src/execution/tiering-manager.h"
|
||||
#include "src/handles/handle-scope-implementer-inl.h"
|
||||
#include "src/handles/maybe-handles.h"
|
||||
#include "src/logging/counters.h"
|
||||
#include "src/numbers/conversions.h"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <cstring>
|
||||
|
||||
#include "include/v8-wasm.h"
|
||||
#include "src/api/api.h"
|
||||
#include "src/base/memory.h"
|
||||
#include "src/base/platform/mutex.h"
|
||||
#include "src/builtins/builtins-inl.h"
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "src/api/api-inl.h"
|
||||
#include "src/asmjs/asm-js.h"
|
||||
#include "src/codegen/compiler.h"
|
||||
#include "src/compiler/fast-api-calls.h"
|
||||
#include "src/compiler/wasm-compiler.h"
|
||||
#include "src/handles/handle-scope-implementer-inl.h"
|
||||
#include "src/logging/counters-scopes.h"
|
||||
#include "src/logging/metrics.h"
|
||||
#include "src/numbers/conversions-inl.h"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// source code is governed by a BSD-style license that can be found in the
|
||||
// LICENSE file.
|
||||
|
||||
#include "src/api/api.h"
|
||||
#include "src/base/memory.h"
|
||||
#include "src/codegen/external-reference.h"
|
||||
#include "test/cctest/cctest.h"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
|
||||
#include "src/api/api.h"
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/ieee754.h"
|
||||
#include "src/base/numerics/safe_conversions.h"
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "test/cctest/profiler-extension.h"
|
||||
|
||||
#include "include/v8-template.h"
|
||||
#include "src/api/api.h"
|
||||
#include "test/cctest/cctest.h"
|
||||
|
||||
namespace v8 {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "include/v8-function-callback.h"
|
||||
#include "include/v8-function.h"
|
||||
#include "src/api/api.h"
|
||||
#include "src/base/strings.h"
|
||||
#include "test/cctest/cctest.h"
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "include/v8-extension.h"
|
||||
#include "include/v8-function.h"
|
||||
#include "include/v8-locker.h"
|
||||
#include "src/api/api.h"
|
||||
#include "src/base/platform/platform.h"
|
||||
#include "src/objects/objects-inl.h"
|
||||
#include "src/sandbox/sandboxable-thread.h"
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "include/v8-local-handle.h"
|
||||
#include "include/v8-template.h"
|
||||
#include "include/v8-unwinder.h"
|
||||
#include "src/api/api.h"
|
||||
#include "src/flags/flags.h"
|
||||
#include "test/cctest/cctest.h"
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "include/v8-profiler.h"
|
||||
#include "include/v8-template.h"
|
||||
#include "src/api/api.h"
|
||||
#include "src/execution/vm-state-inl.h"
|
||||
#include "src/objects/smi.h"
|
||||
#include "src/profiler/tick-sample.h"
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// Copyright 2019 the V8 project authors. All rights reserved.
|
||||
// Copyright 2019 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.
|
||||
|
||||
@@ -687,7 +687,7 @@ function print_handles_data(print_handles = false) {
|
||||
|
||||
let iso = cast(isolate_address, "v8::internal::Isolate");
|
||||
let hsd = iso.handle_scope_data_;
|
||||
let hsimpl = iso.handle_scope_implementer_;
|
||||
let hsimpl = iso.isolate_data_.handle_scope_implementer_;
|
||||
|
||||
// depth level
|
||||
print(`Nested depth level: ${hsd.level}`);
|
||||
|
||||
Reference in new issue
Block a user