%PDF- %PDF-
| Direktori : /home2/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/heap/ |
| Current File : //home2/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/heap/objects-visiting-inl.h |
// Copyright 2012 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_HEAP_OBJECTS_VISITING_INL_H_
#define V8_HEAP_OBJECTS_VISITING_INL_H_
#include "src/base/logging.h"
#include "src/heap/mark-compact.h"
#include "src/heap/object-lock.h"
#include "src/heap/objects-visiting.h"
#include "src/objects/arguments.h"
#include "src/objects/data-handler-inl.h"
#include "src/objects/free-space-inl.h"
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/js-weak-refs-inl.h"
#include "src/objects/module-inl.h"
#include "src/objects/objects-body-descriptors-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/oddball.h"
#include "src/objects/ordered-hash-table.h"
#include "src/objects/shared-function-info.h"
#include "src/objects/synthetic-module-inl.h"
#include "src/objects/torque-defined-classes.h"
#include "src/objects/visitors.h"
#if V8_ENABLE_WEBASSEMBLY
#include "src/wasm/wasm-objects.h"
#endif // V8_ENABLE_WEBASSEMBLY
namespace v8 {
namespace internal {
template <VisitorId visitor_id>
inline bool ContainsReadOnlyMap(PtrComprCageBase, Tagged<HeapObject>) {
return false;
}
// List of visitor ids that can only appear in read-only maps. Unfortunately,
// these are generally contained in all other lists. Adding an instance type
// here optimizes handling in visitors that do not need to Map objects with such
// visitor ids.
#define READ_ONLY_MAPS_VISITOR_ID_LIST(V) \
V(AccessorInfo) \
V(AllocationSite) \
V(BigInt) \
V(BytecodeArray) \
V(ByteArray) \
V(CallHandlerInfo) \
V(Cell) \
V(Code) \
V(DataHandler) \
V(DataObject) \
V(DescriptorArray) \
V(EmbedderDataArray) \
V(ExternalString) \
V(FeedbackCell) \
V(FeedbackMetadata) \
V(FeedbackVector) \
V(FixedArray) \
V(FixedDoubleArray) \
V(InstructionStream) \
V(PreparseData) \
V(PropertyArray) \
V(PropertyCell) \
V(PrototypeInfo) \
V(ScopeInfo) \
V(SeqOneByteString) \
V(SeqTwoByteString) \
V(SharedFunctionInfo) \
V(ShortcutCandidate) \
V(SlicedString) \
V(SloppyArgumentsElements) \
V(Symbol) \
V(ThinString) \
V(TransitionArray) \
V(UncompiledDataWithoutPreparseData) \
V(UncompiledDataWithPreparseData) \
V(WeakArrayList) \
V(WeakFixedArray)
#define DEFINE_READ_ONLY_MAP_SPECIALIZATION(VisitorIdType) \
template <> \
inline bool ContainsReadOnlyMap<VisitorId::kVisit##VisitorIdType>( \
PtrComprCageBase cage_base, Tagged<HeapObject> object) { \
/* If you see this DCHECK fail we encountered a Map with a VisitorId that \
* should have only ever appeared in read-only space. */ \
DCHECK(object->map(cage_base).InReadOnlySpace()); \
return true; \
}
READ_ONLY_MAPS_VISITOR_ID_LIST(DEFINE_READ_ONLY_MAP_SPECIALIZATION)
#undef DEFINE_READ_ONLY_MAP_SPECIALIZATION
#undef READ_ONLY_MAPS_VISITOR_ID_LIST
template <typename ResultType, typename ConcreteVisitor>
HeapVisitor<ResultType, ConcreteVisitor>::HeapVisitor(
PtrComprCageBase cage_base, PtrComprCageBase code_cage_base)
: ObjectVisitorWithCageBases(cage_base, code_cage_base) {}
template <typename ResultType, typename ConcreteVisitor>
HeapVisitor<ResultType, ConcreteVisitor>::HeapVisitor(Isolate* isolate)
: ObjectVisitorWithCageBases(isolate) {}
template <typename ResultType, typename ConcreteVisitor>
HeapVisitor<ResultType, ConcreteVisitor>::HeapVisitor(Heap* heap)
: ObjectVisitorWithCageBases(heap) {}
template <typename ResultType, typename ConcreteVisitor>
template <typename T>
Tagged<T> HeapVisitor<ResultType, ConcreteVisitor>::Cast(
Tagged<HeapObject> object) {
return T::cast(object);
}
template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(
Tagged<HeapObject> object) {
return Visit(object->map(cage_base()), object);
}
template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(
Tagged<Map> map, Tagged<HeapObject> object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
switch (map->visitor_id()) {
#define CASE(TypeName) \
case kVisit##TypeName: \
return visitor->Visit##TypeName( \
map, ConcreteVisitor::template Cast<TypeName>(object));
TYPED_VISITOR_ID_LIST(CASE)
TORQUE_VISITOR_ID_LIST(CASE)
#undef CASE
case kVisitShortcutCandidate:
return visitor->VisitShortcutCandidate(
map, ConcreteVisitor::template Cast<ConsString>(object));
case kVisitDataObject:
return visitor->VisitDataObject(map, object);
case kVisitJSObjectFast:
return visitor->VisitJSObjectFast(
map, ConcreteVisitor::template Cast<JSObject>(object));
case kVisitJSApiObject:
return visitor->VisitJSApiObject(
map, ConcreteVisitor::template Cast<JSObject>(object));
case kVisitStruct:
return visitor->VisitStruct(map, object);
case kVisitFreeSpace:
return visitor->VisitFreeSpace(map, FreeSpace::cast(object));
case kDataOnlyVisitorIdCount:
case kVisitorIdCount:
UNREACHABLE();
}
UNREACHABLE();
// Make the compiler happy.
return ResultType();
}
template <typename ResultType, typename ConcreteVisitor>
template <VisitorId visitor_id>
void HeapVisitor<ResultType, ConcreteVisitor>::VisitMapPointerIfNeeded(
Tagged<HeapObject> host) {
DCHECK(!host->map_word(cage_base(), kRelaxedLoad).IsForwardingAddress());
if constexpr (!ConcreteVisitor::ShouldVisitMapPointer()) {
return;
}
if constexpr (!ConcreteVisitor::ShouldVisitReadOnlyMapPointer()) {
if (ContainsReadOnlyMap<visitor_id>(cage_base(), host)) {
return;
}
}
static_cast<ConcreteVisitor*>(this)->VisitMapPointer(host);
}
#define VISIT(TypeName) \
template <typename ResultType, typename ConcreteVisitor> \
ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit##TypeName( \
Tagged<Map> map, Tagged<TypeName> object) { \
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this); \
/* If you see the following DCHECK fail, then the size computation of \
* BodyDescriptor doesn't match the size return via obj.Size(). This is \
* problematic as the GC requires those sizes to match for accounting \
* reasons. The fix likely involves adding a padding field in the object \
* defintions. */ \
DCHECK_EQ(object->SizeFromMap(map), \
TypeName::BodyDescriptor::SizeOf(map, object)); \
visitor->template VisitMapPointerIfNeeded<VisitorId::kVisit##TypeName>( \
object); \
const int size = TypeName::BodyDescriptor::SizeOf(map, object); \
TypeName::BodyDescriptor::IterateBody(map, object, size, visitor); \
return static_cast<ResultType>(size); \
}
TYPED_VISITOR_ID_LIST(VISIT)
TORQUE_VISITOR_ID_LIST(VISIT)
#undef VISIT
template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitShortcutCandidate(
Tagged<Map> map, Tagged<ConsString> object) {
return static_cast<ConcreteVisitor*>(this)->VisitConsString(map, object);
}
template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitDataObject(
Tagged<Map> map, Tagged<HeapObject> object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
int size = map->instance_size();
visitor->template VisitMapPointerIfNeeded<VisitorId::kVisitDataObject>(
object);
#ifdef V8_ENABLE_SANDBOX
// The following types have external pointers, which must be visited.
// TODO(v8:10391) Consider adding custom visitor IDs for these and making
// this block not depend on V8_ENABLE_SANDBOX.
if (IsForeign(object, cage_base())) {
Foreign::BodyDescriptor::IterateBody(map, object, size, visitor);
}
#endif // V8_ENABLE_SANDBOX
return static_cast<ResultType>(size);
}
template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSObjectFast(
Tagged<Map> map, Tagged<JSObject> object) {
return VisitJSObjectSubclass<JSObject, JSObject::FastBodyDescriptor>(map,
object);
}
template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSApiObject(
Tagged<Map> map, Tagged<JSObject> object) {
return VisitJSObjectSubclass<JSObject, JSObject::BodyDescriptor>(map, object);
}
template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitStruct(
Tagged<Map> map, Tagged<HeapObject> object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
int size = map->instance_size();
visitor->template VisitMapPointerIfNeeded<VisitorId::kVisitStruct>(object);
StructBodyDescriptor::IterateBody(map, object, size, visitor);
return static_cast<ResultType>(size);
}
template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitFreeSpace(
Tagged<Map> map, Tagged<FreeSpace> object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
visitor->template VisitMapPointerIfNeeded<VisitorId::kVisitFreeSpace>(object);
return static_cast<ResultType>(object->size(kRelaxedLoad));
}
template <typename ResultType, typename ConcreteVisitor>
template <typename T, typename TBodyDescriptor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSObjectSubclass(
Tagged<Map> map, Tagged<T> object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
visitor->template VisitMapPointerIfNeeded<VisitorId::kVisitJSObject>(object);
const int size = TBodyDescriptor::SizeOf(map, object);
const int used_size = map->UsedInstanceSize();
DCHECK_LE(used_size, size);
DCHECK_GE(used_size, JSObject::GetHeaderSize(map));
// It is important to visit only the used field and ignore the slack fields
// because the slack fields may be trimmed concurrently. For non-concurrent
// visitors this merely is an optimization in that we only visit the actually
// used fields.
TBodyDescriptor::IterateBody(map, object, used_size, visitor);
return size;
}
template <typename ResultType, typename ConcreteVisitor>
ConcurrentHeapVisitor<ResultType, ConcreteVisitor>::ConcurrentHeapVisitor(
Isolate* isolate)
: HeapVisitor<ResultType, ConcreteVisitor>(isolate) {}
template <typename T>
struct ConcurrentVisitorCastHelper {
static V8_INLINE Tagged<T> Cast(Tagged<HeapObject> object) {
return T::cast(object);
}
};
#define UNCHECKED_CAST(VisitorId, TypeName) \
template <> \
V8_INLINE Tagged<TypeName> ConcurrentVisitorCastHelper<TypeName>::Cast( \
Tagged<HeapObject> object) { \
return TypeName::unchecked_cast(object); \
}
SAFE_STRING_TRANSITION_SOURCES(UNCHECKED_CAST)
// Casts are also needed for unsafe ones for the initial dispatch in
// HeapVisitor.
UNSAFE_STRING_TRANSITION_SOURCES(UNCHECKED_CAST)
#undef UNCHECKED_CAST
template <typename ResultType, typename ConcreteVisitor>
template <typename T>
Tagged<T> ConcurrentHeapVisitor<ResultType, ConcreteVisitor>::Cast(
Tagged<HeapObject> object) {
if constexpr (ConcreteVisitor::EnableConcurrentVisitation()) {
return ConcurrentVisitorCastHelper<T>::Cast(object);
}
return T::cast(object);
}
#define VISIT_AS_LOCKED_STRING(VisitorId, TypeName) \
template <typename ResultType, typename ConcreteVisitor> \
ResultType \
ConcurrentHeapVisitor<ResultType, ConcreteVisitor>::Visit##TypeName( \
Tagged<Map> map, Tagged<TypeName> object) { \
if constexpr (ConcreteVisitor::EnableConcurrentVisitation()) { \
return VisitStringLocked(object); \
} \
return HeapVisitor<ResultType, ConcreteVisitor>::Visit##TypeName(map, \
object); \
}
UNSAFE_STRING_TRANSITION_SOURCES(VISIT_AS_LOCKED_STRING)
#undef VISIT_AS_LOCKED_STRING
template <typename ResultType, typename ConcreteVisitor>
template <typename T>
ResultType
ConcurrentHeapVisitor<ResultType, ConcreteVisitor>::VisitStringLocked(
Tagged<T> object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
SharedObjectLockGuard guard(object);
// The object has been locked. At this point shared read access is
// guaranteed but we must re-read the map and check whether the string has
// transitioned.
Tagged<Map> map = object->map(visitor->cage_base());
int size;
switch (map->visitor_id()) {
#define UNSAFE_STRING_TRANSITION_TARGET_CASE(VisitorIdType, TypeName) \
case kVisit##VisitorIdType: \
visitor \
->template VisitMapPointerIfNeeded<VisitorId::kVisit##VisitorIdType>( \
object); \
size = TypeName::BodyDescriptor::SizeOf(map, object); \
TypeName::BodyDescriptor::IterateBody( \
map, TypeName::unchecked_cast(object), size, visitor); \
break;
UNSAFE_STRING_TRANSITION_TARGETS(UNSAFE_STRING_TRANSITION_TARGET_CASE)
#undef UNSAFE_STRING_TRANSITION_TARGET_CASE
default:
UNREACHABLE();
}
return static_cast<ResultType>(size);
;
}
template <typename ConcreteVisitor>
NewSpaceVisitor<ConcreteVisitor>::NewSpaceVisitor(Isolate* isolate)
: ConcurrentHeapVisitor<int, ConcreteVisitor>(isolate) {}
} // namespace internal
} // namespace v8
#endif // V8_HEAP_OBJECTS_VISITING_INL_H_