53b9e1ed26
We plan to store additional information that is not related to scopes. The new name will reflect this fact better. Change-Id: I4ddb1017bc255e6ad271e4448848ed630f367d5b Reviewed-on: https://chromium-review.googlesource.com/c/1388538 Commit-Queue: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Cr-Commit-Position: refs/heads/master@{#58591}
1077 lines
40 KiB
C++
1077 lines
40 KiB
C++
// Copyright 2015 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_OBJECTS_BODY_DESCRIPTORS_INL_H_
|
|
#define V8_OBJECTS_BODY_DESCRIPTORS_INL_H_
|
|
|
|
#include "src/feedback-vector.h"
|
|
#include "src/objects-body-descriptors.h"
|
|
#include "src/objects/cell.h"
|
|
#include "src/objects/foreign-inl.h"
|
|
#include "src/objects/hash-table.h"
|
|
#include "src/objects/js-collection.h"
|
|
#include "src/objects/js-weak-refs.h"
|
|
#include "src/objects/oddball.h"
|
|
#include "src/objects/slots.h"
|
|
#include "src/reloc-info.h"
|
|
#include "src/transitions.h"
|
|
#include "src/wasm/wasm-objects-inl.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
template <int start_offset>
|
|
int FlexibleBodyDescriptor<start_offset>::SizeOf(Map map, HeapObject object) {
|
|
return object->SizeFromMap(map);
|
|
}
|
|
|
|
template <int start_offset>
|
|
int FlexibleWeakBodyDescriptor<start_offset>::SizeOf(Map map,
|
|
HeapObject object) {
|
|
return object->SizeFromMap(map);
|
|
}
|
|
|
|
bool BodyDescriptorBase::IsValidJSObjectSlotImpl(Map map, HeapObject obj,
|
|
int offset) {
|
|
#ifdef V8_COMPRESS_POINTERS
|
|
STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize);
|
|
int embedder_fields_offset = JSObject::GetEmbedderFieldsStartOffset(map);
|
|
int inobject_fields_offset = map->GetInObjectPropertyOffset(0);
|
|
// |embedder_fields_offset| may be greater than |inobject_fields_offset| if
|
|
// the object does not have embedder fields but the check handles this
|
|
// case properly.
|
|
if (embedder_fields_offset <= offset && offset < inobject_fields_offset) {
|
|
// offset points to embedder fields area:
|
|
// [embedder_fields_offset, inobject_fields_offset).
|
|
STATIC_ASSERT(base::bits::IsPowerOfTwo(kEmbedderDataSlotSize));
|
|
return ((offset - embedder_fields_offset) & (kEmbedderDataSlotSize - 1)) ==
|
|
EmbedderDataSlot::kTaggedPayloadOffset;
|
|
}
|
|
#else
|
|
// We store raw aligned pointers as Smis, so it's safe to treat the whole
|
|
// embedder field area as tagged slots.
|
|
STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize);
|
|
#endif
|
|
if (!FLAG_unbox_double_fields || map->HasFastPointerLayout()) {
|
|
return true;
|
|
} else {
|
|
DCHECK(FLAG_unbox_double_fields);
|
|
DCHECK(IsAligned(offset, kSystemPointerSize));
|
|
|
|
LayoutDescriptorHelper helper(map);
|
|
DCHECK(!helper.all_fields_tagged());
|
|
return helper.IsTagged(offset);
|
|
}
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
void BodyDescriptorBase::IterateJSObjectBodyImpl(Map map, HeapObject obj,
|
|
int start_offset,
|
|
int end_offset,
|
|
ObjectVisitor* v) {
|
|
#ifdef V8_COMPRESS_POINTERS
|
|
STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize);
|
|
int header_size = JSObject::GetHeaderSize(map);
|
|
int inobject_fields_offset = map->GetInObjectPropertyOffset(0);
|
|
// We are always requested to process header and embedder fields.
|
|
DCHECK_LE(inobject_fields_offset, end_offset);
|
|
// Embedder fields are located between header rouned up to the system pointer
|
|
// size and inobject properties.
|
|
if (header_size < inobject_fields_offset) {
|
|
// There are embedder fields.
|
|
IteratePointers(obj, start_offset, header_size, v);
|
|
// Iterate only tagged payload of the embedder slots and skip raw payload.
|
|
int embedder_fields_offset = RoundUp(header_size, kSystemPointerSize);
|
|
DCHECK_EQ(embedder_fields_offset,
|
|
JSObject::GetEmbedderFieldsStartOffset(map));
|
|
for (int offset =
|
|
embedder_fields_offset + EmbedderDataSlot::kTaggedPayloadOffset;
|
|
offset < inobject_fields_offset; offset += kEmbedderDataSlotSize) {
|
|
IteratePointer(obj, offset, v);
|
|
}
|
|
// Proceed processing inobject properties.
|
|
start_offset = inobject_fields_offset;
|
|
}
|
|
#else
|
|
// We store raw aligned pointers as Smis, so it's safe to iterate the whole
|
|
// embedder field area as tagged slots.
|
|
STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize);
|
|
#endif
|
|
if (!FLAG_unbox_double_fields || map->HasFastPointerLayout()) {
|
|
IteratePointers(obj, start_offset, end_offset, v);
|
|
} else {
|
|
DCHECK(FLAG_unbox_double_fields);
|
|
DCHECK(IsAligned(start_offset, kSystemPointerSize) &&
|
|
IsAligned(end_offset, kSystemPointerSize));
|
|
|
|
LayoutDescriptorHelper helper(map);
|
|
DCHECK(!helper.all_fields_tagged());
|
|
for (int offset = start_offset; offset < end_offset;) {
|
|
int end_of_region_offset;
|
|
if (helper.IsTagged(offset, end_offset, &end_of_region_offset)) {
|
|
IteratePointers(obj, offset, end_of_region_offset, v);
|
|
}
|
|
offset = end_of_region_offset;
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
DISABLE_CFI_PERF void BodyDescriptorBase::IteratePointers(HeapObject obj,
|
|
int start_offset,
|
|
int end_offset,
|
|
ObjectVisitor* v) {
|
|
v->VisitPointers(obj, HeapObject::RawField(obj, start_offset),
|
|
HeapObject::RawField(obj, end_offset));
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
void BodyDescriptorBase::IteratePointer(HeapObject obj, int offset,
|
|
ObjectVisitor* v) {
|
|
v->VisitPointer(obj, HeapObject::RawField(obj, offset));
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
DISABLE_CFI_PERF void BodyDescriptorBase::IterateMaybeWeakPointers(
|
|
HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v) {
|
|
v->VisitPointers(obj, HeapObject::RawMaybeWeakField(obj, start_offset),
|
|
HeapObject::RawMaybeWeakField(obj, end_offset));
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
void BodyDescriptorBase::IterateMaybeWeakPointer(HeapObject obj, int offset,
|
|
ObjectVisitor* v) {
|
|
v->VisitPointer(obj, HeapObject::RawMaybeWeakField(obj, offset));
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
DISABLE_CFI_PERF void BodyDescriptorBase::IterateCustomWeakPointers(
|
|
HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v) {
|
|
v->VisitCustomWeakPointers(obj, HeapObject::RawField(obj, start_offset),
|
|
HeapObject::RawField(obj, end_offset));
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
void BodyDescriptorBase::IterateCustomWeakPointer(HeapObject obj, int offset,
|
|
ObjectVisitor* v) {
|
|
v->VisitCustomWeakPointer(obj, HeapObject::RawField(obj, offset));
|
|
}
|
|
|
|
class JSObject::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset;
|
|
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
if (offset < kStartOffset) return false;
|
|
return IsValidJSObjectSlotImpl(map, obj, offset);
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IterateJSObjectBodyImpl(map, obj, kStartOffset, object_size, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return map->instance_size();
|
|
}
|
|
};
|
|
|
|
class JSObject::FastBodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset;
|
|
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return offset >= kStartOffset;
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IteratePointers(obj, kStartOffset, object_size, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return map->instance_size();
|
|
}
|
|
};
|
|
|
|
class JSFunction::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
if (offset < kSizeWithoutPrototype) return true;
|
|
if (offset < kSizeWithPrototype && map->has_prototype_slot()) {
|
|
return true;
|
|
}
|
|
return IsValidJSObjectSlotImpl(map, obj, offset);
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
int header_size = JSFunction::GetHeaderSize(map->has_prototype_slot());
|
|
DCHECK_EQ(header_size, JSObject::GetHeaderSize(map));
|
|
IteratePointers(obj, kPropertiesOrHashOffset, header_size, v);
|
|
IterateJSObjectBodyImpl(map, obj, header_size, object_size, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return map->instance_size();
|
|
}
|
|
};
|
|
|
|
class JSWeakCell::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return JSObject::BodyDescriptor::IsValidSlot(map, obj, offset);
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IteratePointers(obj, JSReceiver::kPropertiesOrHashOffset, kTargetOffset, v);
|
|
IterateCustomWeakPointer(obj, kTargetOffset, v);
|
|
IteratePointers(obj, kTargetOffset + kPointerSize, object_size, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return map->instance_size();
|
|
}
|
|
};
|
|
|
|
class JSWeakRef::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return JSObject::BodyDescriptor::IsValidSlot(map, obj, offset);
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IteratePointers(obj, JSReceiver::kPropertiesOrHashOffset, kTargetOffset, v);
|
|
IterateCustomWeakPointer(obj, kTargetOffset, v);
|
|
IteratePointers(obj, kTargetOffset + kPointerSize, object_size, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return map->instance_size();
|
|
}
|
|
};
|
|
|
|
class SharedFunctionInfo::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return FixedBodyDescriptor<kStartOfPointerFieldsOffset,
|
|
kEndOfTaggedFieldsOffset,
|
|
kAlignedSize>::IsValidSlot(map, obj, offset);
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IterateCustomWeakPointer(obj, kFunctionDataOffset, v);
|
|
IteratePointers(obj,
|
|
SharedFunctionInfo::kStartOfAlwaysStrongPointerFieldsOffset,
|
|
SharedFunctionInfo::kEndOfTaggedFieldsOffset, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return map->instance_size();
|
|
}
|
|
};
|
|
|
|
class AllocationSite::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
STATIC_ASSERT(AllocationSite::kCommonPointerFieldEndOffset ==
|
|
AllocationSite::kPretenureDataOffset);
|
|
STATIC_ASSERT(AllocationSite::kPretenureDataOffset + kInt32Size ==
|
|
AllocationSite::kPretenureCreateCountOffset);
|
|
STATIC_ASSERT(AllocationSite::kPretenureCreateCountOffset + kInt32Size ==
|
|
AllocationSite::kWeakNextOffset);
|
|
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
if (offset >= AllocationSite::kStartOffset &&
|
|
offset < AllocationSite::kCommonPointerFieldEndOffset) {
|
|
return true;
|
|
}
|
|
// check for weak_next offset
|
|
if (map->instance_size() == AllocationSite::kSizeWithWeakNext &&
|
|
offset == AllocationSite::kWeakNextOffset) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
// Iterate over all the common pointer fields
|
|
IteratePointers(obj, AllocationSite::kStartOffset,
|
|
AllocationSite::kCommonPointerFieldEndOffset, v);
|
|
// Skip PretenureDataOffset and PretenureCreateCount which are Int32 fields.
|
|
// Visit weak_next only if it has weak_next field.
|
|
if (object_size == AllocationSite::kSizeWithWeakNext) {
|
|
IterateCustomWeakPointers(obj, AllocationSite::kWeakNextOffset,
|
|
AllocationSite::kSizeWithWeakNext, v);
|
|
}
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return map->instance_size();
|
|
}
|
|
};
|
|
|
|
class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
if (offset < kEndOfTaggedFieldsOffset) return true;
|
|
if (offset < kHeaderSize) return false;
|
|
return IsValidJSObjectSlotImpl(map, obj, offset);
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
// JSArrayBuffer instances contain raw data that the GC does not know about.
|
|
IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
|
|
IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return map->instance_size();
|
|
}
|
|
};
|
|
|
|
class JSArrayBufferView::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
if (offset < kEndOfTaggedFieldsOffset) return true;
|
|
if (offset < kHeaderSize) return false;
|
|
return IsValidJSObjectSlotImpl(map, obj, offset);
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
// JSArrayBufferView contains raw data that the GC does not know about.
|
|
IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
|
|
IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return map->instance_size();
|
|
}
|
|
};
|
|
|
|
template <typename Derived>
|
|
class SmallOrderedHashTable<Derived>::BodyDescriptor final
|
|
: public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
Derived table = Derived::cast(obj);
|
|
// Only data table part contains tagged values.
|
|
return (offset >= DataTableStartOffset()) &&
|
|
(offset < table->GetBucketsStartOffset());
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
Derived table = Derived::cast(obj);
|
|
int start_offset = DataTableStartOffset();
|
|
int end_offset = table->GetBucketsStartOffset();
|
|
IteratePointers(obj, start_offset, end_offset, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject obj) {
|
|
Derived table = Derived::cast(obj);
|
|
return table->SizeFor(table->Capacity());
|
|
}
|
|
};
|
|
|
|
class ByteArray::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {}
|
|
|
|
static inline int SizeOf(Map map, HeapObject obj) {
|
|
return ByteArray::SizeFor(ByteArray::cast(obj)->synchronized_length());
|
|
}
|
|
};
|
|
|
|
class BytecodeArray::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return offset >= kConstantPoolOffset &&
|
|
offset <= kSourcePositionTableOffset;
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IteratePointer(obj, kConstantPoolOffset, v);
|
|
IteratePointer(obj, kHandlerTableOffset, v);
|
|
IteratePointer(obj, kSourcePositionTableOffset, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject obj) {
|
|
return BytecodeArray::SizeFor(
|
|
BytecodeArray::cast(obj)->synchronized_length());
|
|
}
|
|
};
|
|
|
|
class BigInt::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {}
|
|
|
|
static inline int SizeOf(Map map, HeapObject obj) {
|
|
return BigInt::SizeFor(BigInt::cast(obj)->synchronized_length());
|
|
}
|
|
};
|
|
|
|
class FixedDoubleArray::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {}
|
|
|
|
static inline int SizeOf(Map map, HeapObject obj) {
|
|
return FixedDoubleArray::SizeFor(
|
|
FixedDoubleArray::cast(obj)->synchronized_length());
|
|
}
|
|
};
|
|
|
|
class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return offset == kBasePointerOffset;
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IteratePointer(obj, kBasePointerOffset, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return FixedTypedArrayBase::cast(object)->size();
|
|
}
|
|
};
|
|
|
|
class FeedbackMetadata::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {}
|
|
|
|
static inline int SizeOf(Map map, HeapObject obj) {
|
|
return FeedbackMetadata::SizeFor(
|
|
FeedbackMetadata::cast(obj)->synchronized_slot_count());
|
|
}
|
|
};
|
|
|
|
class FeedbackVector::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return offset == kSharedFunctionInfoOffset ||
|
|
offset == kOptimizedCodeOffset || offset >= kFeedbackSlotsOffset;
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IteratePointer(obj, kSharedFunctionInfoOffset, v);
|
|
IterateMaybeWeakPointer(obj, kOptimizedCodeOffset, v);
|
|
IterateMaybeWeakPointers(obj, kFeedbackSlotsOffset, object_size, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject obj) {
|
|
return FeedbackVector::SizeFor(FeedbackVector::cast(obj)->length());
|
|
}
|
|
};
|
|
|
|
class PreparseData::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return offset == kScopeDataOffset || offset >= kChildDataStartOffset;
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IteratePointer(obj, kScopeDataOffset, v);
|
|
IteratePointers(obj, kChildDataStartOffset, object_size, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject obj) {
|
|
return PreparseData::SizeFor(PreparseData::cast(obj)->length());
|
|
}
|
|
};
|
|
|
|
class PrototypeInfo::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return offset >= HeapObject::kHeaderSize;
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IteratePointers(obj, HeapObject::kHeaderSize, kObjectCreateMapOffset, v);
|
|
IterateMaybeWeakPointer(obj, kObjectCreateMapOffset, v);
|
|
IteratePointers(obj, kObjectCreateMapOffset + kPointerSize, object_size, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject obj) {
|
|
return obj->SizeFromMap(map);
|
|
}
|
|
};
|
|
|
|
class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
|
|
public:
|
|
STATIC_ASSERT(kTableOffset + kPointerSize == kSize);
|
|
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return IsValidJSObjectSlotImpl(map, obj, offset);
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IterateJSObjectBodyImpl(map, obj, kPropertiesOrHashOffset, object_size, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return map->instance_size();
|
|
}
|
|
};
|
|
|
|
class Foreign::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
v->VisitExternalReference(
|
|
Foreign::cast(obj),
|
|
reinterpret_cast<Address*>(
|
|
HeapObject::RawField(obj, kForeignAddressOffset).address()));
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) { return kSize; }
|
|
};
|
|
|
|
class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) { return kSize; }
|
|
};
|
|
|
|
class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) { return kSize; }
|
|
};
|
|
|
|
class Code::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
STATIC_ASSERT(kRelocationInfoOffset + kPointerSize ==
|
|
kDeoptimizationDataOffset);
|
|
STATIC_ASSERT(kDeoptimizationDataOffset + kPointerSize ==
|
|
kSourcePositionTableOffset);
|
|
STATIC_ASSERT(kSourcePositionTableOffset + kPointerSize ==
|
|
kCodeDataContainerOffset);
|
|
STATIC_ASSERT(kCodeDataContainerOffset + kPointerSize == kDataStart);
|
|
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
// Slots in code can't be invalid because we never trim code objects.
|
|
return true;
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, ObjectVisitor* v) {
|
|
int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
|
|
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
|
|
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
|
|
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
|
|
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
|
|
RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) |
|
|
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
|
|
|
|
// GC does not visit data/code in the header and in the body directly.
|
|
IteratePointers(obj, kRelocationInfoOffset, kDataStart, v);
|
|
|
|
RelocIterator it(Code::cast(obj), mode_mask);
|
|
v->VisitRelocInfo(&it);
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IterateBody(map, obj, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return Code::unchecked_cast(object)->CodeSize();
|
|
}
|
|
};
|
|
|
|
class SeqOneByteString::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {}
|
|
|
|
static inline int SizeOf(Map map, HeapObject obj) {
|
|
SeqOneByteString string = SeqOneByteString::cast(obj);
|
|
return string->SizeFor(string->synchronized_length());
|
|
}
|
|
};
|
|
|
|
class SeqTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {}
|
|
|
|
static inline int SizeOf(Map map, HeapObject obj) {
|
|
SeqTwoByteString string = SeqTwoByteString::cast(obj);
|
|
return string->SizeFor(string->synchronized_length());
|
|
}
|
|
};
|
|
|
|
class WasmInstanceObject::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
if (offset < kMemoryStartOffset) return true;
|
|
if (offset < kModuleObjectOffset) return false;
|
|
return IsValidJSObjectSlotImpl(map, obj, offset);
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
|
|
IterateJSObjectBodyImpl(map, obj, kSize, object_size, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return map->instance_size();
|
|
}
|
|
};
|
|
|
|
class Map::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return offset >= Map::kPointerFieldsBeginOffset &&
|
|
offset < Map::kPointerFieldsEndOffset;
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IteratePointers(obj, Map::kPointerFieldsBeginOffset,
|
|
Map::kTransitionsOrPrototypeInfoOffset, v);
|
|
IterateMaybeWeakPointer(obj, kTransitionsOrPrototypeInfoOffset, v);
|
|
IteratePointers(obj, Map::kTransitionsOrPrototypeInfoOffset + kPointerSize,
|
|
Map::kPointerFieldsEndOffset, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject obj) { return Map::kSize; }
|
|
};
|
|
|
|
class DataHandler::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return offset >= HeapObject::kHeaderSize;
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
static_assert(kSmiHandlerOffset < kData1Offset,
|
|
"Field order must be in sync with this iteration code");
|
|
static_assert(kData1Offset < kSizeWithData1,
|
|
"Field order must be in sync with this iteration code");
|
|
IteratePointers(obj, kSmiHandlerOffset, kData1Offset, v);
|
|
IterateMaybeWeakPointers(obj, kData1Offset, object_size, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return object->SizeFromMap(map);
|
|
}
|
|
};
|
|
|
|
class NativeContext::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return offset < NativeContext::kEndOfTaggedFieldsOffset;
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IteratePointers(obj, NativeContext::kStartOfStrongFieldsOffset,
|
|
NativeContext::kEndOfStrongFieldsOffset, v);
|
|
IterateCustomWeakPointers(obj, NativeContext::kStartOfWeakFieldsOffset,
|
|
NativeContext::kEndOfWeakFieldsOffset, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return NativeContext::kSize;
|
|
}
|
|
};
|
|
|
|
class CodeDataContainer::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
return offset >= CodeDataContainer::kHeaderSize &&
|
|
offset < CodeDataContainer::kSize;
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
IteratePointers(obj, CodeDataContainer::kHeaderSize,
|
|
CodeDataContainer::kPointerFieldsStrongEndOffset, v);
|
|
IterateCustomWeakPointers(
|
|
obj, CodeDataContainer::kPointerFieldsStrongEndOffset,
|
|
CodeDataContainer::kPointerFieldsWeakEndOffset, v);
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return CodeDataContainer::kSize;
|
|
}
|
|
};
|
|
|
|
class EmbedderDataArray::BodyDescriptor final : public BodyDescriptorBase {
|
|
public:
|
|
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
|
#ifdef V8_COMPRESS_POINTERS
|
|
STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kSystemPointerSize);
|
|
STATIC_ASSERT(base::bits::IsPowerOfTwo(kEmbedderDataSlotSize));
|
|
return (offset < EmbedderDataArray::kHeaderSize) ||
|
|
(((offset - EmbedderDataArray::kHeaderSize) &
|
|
(kEmbedderDataSlotSize - 1)) ==
|
|
EmbedderDataSlot::kTaggedPayloadOffset);
|
|
#else
|
|
STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize);
|
|
// We store raw aligned pointers as Smis, so it's safe to iterate the whole
|
|
// array.
|
|
return true;
|
|
#endif
|
|
}
|
|
|
|
template <typename ObjectVisitor>
|
|
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
#ifdef V8_COMPRESS_POINTERS
|
|
STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kSystemPointerSize);
|
|
// Iterate only tagged payload of the embedder slots and skip raw payload.
|
|
for (int offset = EmbedderDataArray::OffsetOfElementAt(0) +
|
|
EmbedderDataSlot::kTaggedPayloadOffset;
|
|
offset < object_size; offset += kEmbedderDataSlotSize) {
|
|
IteratePointer(obj, offset, v);
|
|
}
|
|
#else
|
|
// We store raw aligned pointers as Smis, so it's safe to iterate the whole
|
|
// array.
|
|
STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize);
|
|
IteratePointers(obj, EmbedderDataArray::kHeaderSize, object_size, v);
|
|
#endif
|
|
}
|
|
|
|
static inline int SizeOf(Map map, HeapObject object) {
|
|
return object->SizeFromMap(map);
|
|
}
|
|
};
|
|
|
|
template <typename Op, typename ReturnType, typename T1, typename T2,
|
|
typename T3, typename T4>
|
|
ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
|
|
if (type < FIRST_NONSTRING_TYPE) {
|
|
switch (type & kStringRepresentationMask) {
|
|
case kSeqStringTag:
|
|
return ReturnType();
|
|
case kConsStringTag:
|
|
return Op::template apply<ConsString::BodyDescriptor>(p1, p2, p3, p4);
|
|
case kThinStringTag:
|
|
return Op::template apply<ThinString::BodyDescriptor>(p1, p2, p3, p4);
|
|
case kSlicedStringTag:
|
|
return Op::template apply<SlicedString::BodyDescriptor>(p1, p2, p3, p4);
|
|
case kExternalStringTag:
|
|
if ((type & kStringEncodingMask) == kOneByteStringTag) {
|
|
return Op::template apply<ExternalOneByteString::BodyDescriptor>(
|
|
p1, p2, p3, p4);
|
|
} else {
|
|
return Op::template apply<ExternalTwoByteString::BodyDescriptor>(
|
|
p1, p2, p3, p4);
|
|
}
|
|
}
|
|
UNREACHABLE();
|
|
}
|
|
|
|
switch (type) {
|
|
case EMBEDDER_DATA_ARRAY_TYPE:
|
|
return Op::template apply<EmbedderDataArray::BodyDescriptor>(p1, p2, p3,
|
|
p4);
|
|
case FIXED_ARRAY_TYPE:
|
|
case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
|
|
case HASH_TABLE_TYPE:
|
|
case ORDERED_HASH_MAP_TYPE:
|
|
case ORDERED_HASH_SET_TYPE:
|
|
case ORDERED_NAME_DICTIONARY_TYPE:
|
|
case NAME_DICTIONARY_TYPE:
|
|
case GLOBAL_DICTIONARY_TYPE:
|
|
case NUMBER_DICTIONARY_TYPE:
|
|
case SIMPLE_NUMBER_DICTIONARY_TYPE:
|
|
case STRING_TABLE_TYPE:
|
|
case EPHEMERON_HASH_TABLE_TYPE:
|
|
case SCOPE_INFO_TYPE:
|
|
case SCRIPT_CONTEXT_TABLE_TYPE:
|
|
return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3, p4);
|
|
case AWAIT_CONTEXT_TYPE:
|
|
case BLOCK_CONTEXT_TYPE:
|
|
case CATCH_CONTEXT_TYPE:
|
|
case DEBUG_EVALUATE_CONTEXT_TYPE:
|
|
case EVAL_CONTEXT_TYPE:
|
|
case FUNCTION_CONTEXT_TYPE:
|
|
case MODULE_CONTEXT_TYPE:
|
|
case SCRIPT_CONTEXT_TYPE:
|
|
case WITH_CONTEXT_TYPE:
|
|
return Op::template apply<Context::BodyDescriptor>(p1, p2, p3, p4);
|
|
case NATIVE_CONTEXT_TYPE:
|
|
return Op::template apply<NativeContext::BodyDescriptor>(p1, p2, p3, p4);
|
|
case WEAK_FIXED_ARRAY_TYPE:
|
|
return Op::template apply<WeakFixedArray::BodyDescriptor>(p1, p2, p3, p4);
|
|
case WEAK_ARRAY_LIST_TYPE:
|
|
return Op::template apply<WeakArrayList::BodyDescriptor>(p1, p2, p3, p4);
|
|
case FIXED_DOUBLE_ARRAY_TYPE:
|
|
return ReturnType();
|
|
case FEEDBACK_METADATA_TYPE:
|
|
return Op::template apply<FeedbackMetadata::BodyDescriptor>(p1, p2, p3,
|
|
p4);
|
|
case PROPERTY_ARRAY_TYPE:
|
|
return Op::template apply<PropertyArray::BodyDescriptor>(p1, p2, p3, p4);
|
|
case DESCRIPTOR_ARRAY_TYPE:
|
|
return Op::template apply<DescriptorArray::BodyDescriptor>(p1, p2, p3,
|
|
p4);
|
|
case TRANSITION_ARRAY_TYPE:
|
|
return Op::template apply<TransitionArray::BodyDescriptor>(p1, p2, p3,
|
|
p4);
|
|
case FEEDBACK_CELL_TYPE:
|
|
return Op::template apply<FeedbackCell::BodyDescriptor>(p1, p2, p3, p4);
|
|
case FEEDBACK_VECTOR_TYPE:
|
|
return Op::template apply<FeedbackVector::BodyDescriptor>(p1, p2, p3, p4);
|
|
case JS_OBJECT_TYPE:
|
|
case JS_ERROR_TYPE:
|
|
case JS_ARGUMENTS_TYPE:
|
|
case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
|
|
case JS_PROMISE_TYPE:
|
|
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
|
|
case JS_GENERATOR_OBJECT_TYPE:
|
|
case JS_ASYNC_FUNCTION_OBJECT_TYPE:
|
|
case JS_ASYNC_GENERATOR_OBJECT_TYPE:
|
|
case JS_VALUE_TYPE:
|
|
case JS_DATE_TYPE:
|
|
case JS_ARRAY_TYPE:
|
|
case JS_ARRAY_ITERATOR_TYPE:
|
|
case JS_MODULE_NAMESPACE_TYPE:
|
|
case JS_SET_TYPE:
|
|
case JS_MAP_TYPE:
|
|
case JS_SET_KEY_VALUE_ITERATOR_TYPE:
|
|
case JS_SET_VALUE_ITERATOR_TYPE:
|
|
case JS_MAP_KEY_ITERATOR_TYPE:
|
|
case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
|
|
case JS_MAP_VALUE_ITERATOR_TYPE:
|
|
case JS_STRING_ITERATOR_TYPE:
|
|
case JS_REGEXP_STRING_ITERATOR_TYPE:
|
|
case JS_REGEXP_TYPE:
|
|
case JS_GLOBAL_PROXY_TYPE:
|
|
case JS_GLOBAL_OBJECT_TYPE:
|
|
case JS_API_OBJECT_TYPE:
|
|
case JS_SPECIAL_API_OBJECT_TYPE:
|
|
case JS_MESSAGE_OBJECT_TYPE:
|
|
case JS_BOUND_FUNCTION_TYPE:
|
|
case JS_WEAK_FACTORY_CLEANUP_ITERATOR_TYPE:
|
|
case JS_WEAK_FACTORY_TYPE:
|
|
#ifdef V8_INTL_SUPPORT
|
|
case JS_INTL_V8_BREAK_ITERATOR_TYPE:
|
|
case JS_INTL_COLLATOR_TYPE:
|
|
case JS_INTL_DATE_TIME_FORMAT_TYPE:
|
|
case JS_INTL_LIST_FORMAT_TYPE:
|
|
case JS_INTL_LOCALE_TYPE:
|
|
case JS_INTL_NUMBER_FORMAT_TYPE:
|
|
case JS_INTL_PLURAL_RULES_TYPE:
|
|
case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
|
|
case JS_INTL_SEGMENT_ITERATOR_TYPE:
|
|
case JS_INTL_SEGMENTER_TYPE:
|
|
#endif // V8_INTL_SUPPORT
|
|
case WASM_EXCEPTION_TYPE:
|
|
case WASM_GLOBAL_TYPE:
|
|
case WASM_MEMORY_TYPE:
|
|
case WASM_MODULE_TYPE:
|
|
case WASM_TABLE_TYPE:
|
|
return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3, p4);
|
|
case WASM_INSTANCE_TYPE:
|
|
return Op::template apply<WasmInstanceObject::BodyDescriptor>(p1, p2, p3,
|
|
p4);
|
|
case JS_WEAK_MAP_TYPE:
|
|
case JS_WEAK_SET_TYPE:
|
|
return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3,
|
|
p4);
|
|
case JS_ARRAY_BUFFER_TYPE:
|
|
return Op::template apply<JSArrayBuffer::BodyDescriptor>(p1, p2, p3, p4);
|
|
case JS_DATA_VIEW_TYPE:
|
|
return Op::template apply<JSDataView::BodyDescriptor>(p1, p2, p3, p4);
|
|
case JS_TYPED_ARRAY_TYPE:
|
|
return Op::template apply<JSTypedArray::BodyDescriptor>(p1, p2, p3, p4);
|
|
case JS_FUNCTION_TYPE:
|
|
return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3, p4);
|
|
case JS_WEAK_CELL_TYPE:
|
|
return Op::template apply<JSWeakCell::BodyDescriptor>(p1, p2, p3, p4);
|
|
case JS_WEAK_REF_TYPE:
|
|
return Op::template apply<JSWeakRef::BodyDescriptor>(p1, p2, p3, p4);
|
|
case ODDBALL_TYPE:
|
|
return Op::template apply<Oddball::BodyDescriptor>(p1, p2, p3, p4);
|
|
case JS_PROXY_TYPE:
|
|
return Op::template apply<JSProxy::BodyDescriptor>(p1, p2, p3, p4);
|
|
case FOREIGN_TYPE:
|
|
return Op::template apply<Foreign::BodyDescriptor>(p1, p2, p3, p4);
|
|
case MAP_TYPE:
|
|
return Op::template apply<Map::BodyDescriptor>(p1, p2, p3, p4);
|
|
case CODE_TYPE:
|
|
return Op::template apply<Code::BodyDescriptor>(p1, p2, p3, p4);
|
|
case CELL_TYPE:
|
|
return Op::template apply<Cell::BodyDescriptor>(p1, p2, p3, p4);
|
|
case PROPERTY_CELL_TYPE:
|
|
return Op::template apply<PropertyCell::BodyDescriptor>(p1, p2, p3, p4);
|
|
case SYMBOL_TYPE:
|
|
return Op::template apply<Symbol::BodyDescriptor>(p1, p2, p3, p4);
|
|
case BYTECODE_ARRAY_TYPE:
|
|
return Op::template apply<BytecodeArray::BodyDescriptor>(p1, p2, p3, p4);
|
|
case SMALL_ORDERED_HASH_SET_TYPE:
|
|
return Op::template apply<
|
|
SmallOrderedHashTable<SmallOrderedHashSet>::BodyDescriptor>(p1, p2,
|
|
p3, p4);
|
|
case SMALL_ORDERED_HASH_MAP_TYPE:
|
|
return Op::template apply<
|
|
SmallOrderedHashTable<SmallOrderedHashMap>::BodyDescriptor>(p1, p2,
|
|
p3, p4);
|
|
case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
|
|
return Op::template apply<
|
|
SmallOrderedHashTable<SmallOrderedNameDictionary>::BodyDescriptor>(
|
|
p1, p2, p3, p4);
|
|
case CODE_DATA_CONTAINER_TYPE:
|
|
return Op::template apply<CodeDataContainer::BodyDescriptor>(p1, p2, p3,
|
|
p4);
|
|
case PRE_PARSED_SCOPE_DATA_TYPE:
|
|
return Op::template apply<PreparseData::BodyDescriptor>(p1, p2, p3, p4);
|
|
case UNCOMPILED_DATA_WITHOUT_PRE_PARSED_SCOPE_TYPE:
|
|
return Op::template apply<
|
|
UncompiledDataWithoutPreparseData::BodyDescriptor>(p1, p2, p3, p4);
|
|
case UNCOMPILED_DATA_WITH_PRE_PARSED_SCOPE_TYPE:
|
|
return Op::template apply<UncompiledDataWithPreparseData::BodyDescriptor>(
|
|
p1, p2, p3, p4);
|
|
case HEAP_NUMBER_TYPE:
|
|
case MUTABLE_HEAP_NUMBER_TYPE:
|
|
case FILLER_TYPE:
|
|
case BYTE_ARRAY_TYPE:
|
|
case FREE_SPACE_TYPE:
|
|
case BIGINT_TYPE:
|
|
return ReturnType();
|
|
|
|
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
|
|
case FIXED_##TYPE##_ARRAY_TYPE: \
|
|
return Op::template apply<FixedTypedArrayBase::BodyDescriptor>(p1, p2, p3, \
|
|
p4);
|
|
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
|
#undef TYPED_ARRAY_CASE
|
|
|
|
case SHARED_FUNCTION_INFO_TYPE: {
|
|
return Op::template apply<SharedFunctionInfo::BodyDescriptor>(p1, p2, p3,
|
|
p4);
|
|
}
|
|
case ALLOCATION_SITE_TYPE:
|
|
return Op::template apply<AllocationSite::BodyDescriptor>(p1, p2, p3, p4);
|
|
|
|
#define MAKE_STRUCT_CASE(TYPE, Name, name) case TYPE:
|
|
STRUCT_LIST(MAKE_STRUCT_CASE)
|
|
#undef MAKE_STRUCT_CASE
|
|
if (type == PROTOTYPE_INFO_TYPE) {
|
|
return Op::template apply<PrototypeInfo::BodyDescriptor>(p1, p2, p3,
|
|
p4);
|
|
} else {
|
|
return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
|
|
}
|
|
case CALL_HANDLER_INFO_TYPE:
|
|
return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
|
|
case LOAD_HANDLER_TYPE:
|
|
case STORE_HANDLER_TYPE:
|
|
return Op::template apply<DataHandler::BodyDescriptor>(p1, p2, p3, p4);
|
|
default:
|
|
PrintF("Unknown type: %d\n", type);
|
|
UNREACHABLE();
|
|
}
|
|
}
|
|
|
|
|
|
template <typename ObjectVisitor>
|
|
void HeapObject::IterateFast(ObjectVisitor* v) {
|
|
BodyDescriptorBase::IteratePointer(*this, kMapOffset, v);
|
|
IterateBodyFast(v);
|
|
}
|
|
|
|
|
|
template <typename ObjectVisitor>
|
|
void HeapObject::IterateBodyFast(ObjectVisitor* v) {
|
|
Map m = map();
|
|
IterateBodyFast(m, SizeFromMap(m), v);
|
|
}
|
|
|
|
|
|
struct CallIterateBody {
|
|
template <typename BodyDescriptor, typename ObjectVisitor>
|
|
static void apply(Map map, HeapObject obj, int object_size,
|
|
ObjectVisitor* v) {
|
|
BodyDescriptor::IterateBody(map, obj, object_size, v);
|
|
}
|
|
};
|
|
|
|
template <typename ObjectVisitor>
|
|
void HeapObject::IterateBodyFast(Map map, int object_size, ObjectVisitor* v) {
|
|
BodyDescriptorApply<CallIterateBody, void>(map->instance_type(), map, *this,
|
|
object_size, v);
|
|
}
|
|
} // namespace internal
|
|
} // namespace v8
|
|
|
|
#endif // V8_OBJECTS_BODY_DESCRIPTORS_INL_H_
|