Object's body descriptors refactoring.
1) Body descriptors moved to their own header files. 2) Missing body descriptors added. 3) Template versions of HeapObject::Iterate*() methods added. 4) Body descriptors support new kind of queries: IsValidSlot(offset) which can be used for invalid slots filtering. This is a first step towards virtual and static visitors unification and support in-object properties in built-in (sub-)classes. Review URL: https://codereview.chromium.org/1440243002 Cr-Commit-Position: refs/heads/master@{#31980}
This commit is contained in:
parent
55c07a8b2f
commit
138eb324ea
2
BUILD.gn
2
BUILD.gn
@ -1127,6 +1127,8 @@ source_set("v8_base") {
|
||||
"src/modules.cc",
|
||||
"src/modules.h",
|
||||
"src/msan.h",
|
||||
"src/objects-body-descriptors-inl.h",
|
||||
"src/objects-body-descriptors.h",
|
||||
"src/objects-debug.cc",
|
||||
"src/objects-inl.h",
|
||||
"src/objects-printer.cc",
|
||||
|
@ -1813,7 +1813,7 @@ void MarkCompactCollector::ProcessTopOptimizedFrame(ObjectVisitor* visitor) {
|
||||
if (it.frame()->type() == StackFrame::OPTIMIZED) {
|
||||
Code* code = it.frame()->LookupCode();
|
||||
if (!code->CanDeoptAt(it.frame()->pc())) {
|
||||
code->CodeIterateBody(visitor);
|
||||
Code::BodyDescriptor::IterateBody(code, visitor);
|
||||
}
|
||||
ProcessMarkingDeque();
|
||||
return;
|
||||
@ -2723,8 +2723,7 @@ void MarkCompactCollector::MigrateObjectMixed(
|
||||
heap()->MoveBlock(dst->address(), src->address(), size);
|
||||
|
||||
// Visit inherited JSObject properties and byte length of ArrayBuffer
|
||||
Address regular_slot =
|
||||
dst->address() + JSArrayBuffer::BodyDescriptor::kStartOffset;
|
||||
Address regular_slot = dst->address() + JSArrayBuffer::kPropertiesOffset;
|
||||
Address regular_slots_end =
|
||||
dst->address() + JSArrayBuffer::kByteLengthOffset + kPointerSize;
|
||||
while (regular_slot < regular_slots_end) {
|
||||
@ -2793,7 +2792,7 @@ static inline void UpdateSlot(Isolate* isolate, ObjectVisitor* v,
|
||||
}
|
||||
case SlotsBuffer::RELOCATED_CODE_OBJECT: {
|
||||
HeapObject* obj = HeapObject::FromAddress(addr);
|
||||
Code::cast(obj)->CodeIterateBody(v);
|
||||
Code::BodyDescriptor::IterateBody(obj, v);
|
||||
break;
|
||||
}
|
||||
case SlotsBuffer::DEBUG_TARGET_SLOT: {
|
||||
@ -3140,7 +3139,7 @@ bool MarkCompactCollector::IsSlotInLiveObject(Address slot) {
|
||||
BytecodeArray::kConstantPoolOffset;
|
||||
} else if (object->IsJSArrayBuffer()) {
|
||||
int off = static_cast<int>(slot - object->address());
|
||||
return (off >= JSArrayBuffer::BodyDescriptor::kStartOffset &&
|
||||
return (off >= JSArrayBuffer::kPropertiesOffset &&
|
||||
off <= JSArrayBuffer::kByteLengthOffset) ||
|
||||
(off >= JSArrayBuffer::kSize &&
|
||||
off < JSArrayBuffer::kSizeWithInternalFields);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "src/heap/objects-visiting.h"
|
||||
#include "src/ic/ic-state.h"
|
||||
#include "src/macro-assembler.h"
|
||||
#include "src/objects-body-descriptors-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -94,14 +95,14 @@ void StaticNewSpaceVisitor<StaticVisitor>::Initialize() {
|
||||
template <typename StaticVisitor>
|
||||
int StaticNewSpaceVisitor<StaticVisitor>::VisitJSArrayBuffer(
|
||||
Map* map, HeapObject* object) {
|
||||
Heap* heap = map->GetHeap();
|
||||
typedef FlexibleBodyVisitor<StaticVisitor, JSArrayBuffer::BodyDescriptor, int>
|
||||
JSArrayBufferBodyVisitor;
|
||||
|
||||
JSArrayBuffer::JSArrayBufferIterateBody<
|
||||
StaticNewSpaceVisitor<StaticVisitor> >(heap, object);
|
||||
if (!JSArrayBuffer::cast(object)->is_external()) {
|
||||
Heap* heap = map->GetHeap();
|
||||
heap->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(object));
|
||||
}
|
||||
return JSArrayBuffer::kSizeWithInternalFields;
|
||||
return JSArrayBufferBodyVisitor::Visit(map, object);
|
||||
}
|
||||
|
||||
|
||||
@ -427,6 +428,8 @@ void StaticMarkingVisitor<StaticVisitor>::VisitWeakCollection(
|
||||
template <typename StaticVisitor>
|
||||
void StaticMarkingVisitor<StaticVisitor>::VisitCode(Map* map,
|
||||
HeapObject* object) {
|
||||
typedef FlexibleBodyVisitor<StaticVisitor, Code::BodyDescriptor, void>
|
||||
CodeBodyVisitor;
|
||||
Heap* heap = map->GetHeap();
|
||||
Code* code = Code::cast(object);
|
||||
if (FLAG_age_code && !heap->isolate()->serializer_enabled()) {
|
||||
@ -439,7 +442,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitCode(Map* map,
|
||||
MarkInlinedFunctionsCode(heap, code);
|
||||
}
|
||||
}
|
||||
code->CodeIterateBody<StaticVisitor>(heap);
|
||||
CodeBodyVisitor::Visit(map, object);
|
||||
}
|
||||
|
||||
|
||||
@ -525,12 +528,9 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSFunction(Map* map,
|
||||
template <typename StaticVisitor>
|
||||
void StaticMarkingVisitor<StaticVisitor>::VisitJSRegExp(Map* map,
|
||||
HeapObject* object) {
|
||||
int last_property_offset =
|
||||
JSRegExp::kSize + kPointerSize * map->GetInObjectProperties();
|
||||
StaticVisitor::VisitPointers(
|
||||
map->GetHeap(), object,
|
||||
HeapObject::RawField(object, JSRegExp::kPropertiesOffset),
|
||||
HeapObject::RawField(object, last_property_offset));
|
||||
typedef FlexibleBodyVisitor<StaticVisitor, JSRegExp::BodyDescriptor, void>
|
||||
JSRegExpBodyVisitor;
|
||||
JSRegExpBodyVisitor::Visit(map, object);
|
||||
}
|
||||
|
||||
|
||||
@ -539,7 +539,11 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSArrayBuffer(
|
||||
Map* map, HeapObject* object) {
|
||||
Heap* heap = map->GetHeap();
|
||||
|
||||
JSArrayBuffer::JSArrayBufferIterateBody<StaticVisitor>(heap, object);
|
||||
typedef FlexibleBodyVisitor<StaticVisitor, JSArrayBuffer::BodyDescriptor,
|
||||
void> JSArrayBufferBodyVisitor;
|
||||
|
||||
JSArrayBufferBodyVisitor::Visit(map, object);
|
||||
|
||||
if (!JSArrayBuffer::cast(object)->is_external() &&
|
||||
!heap->InNewSpace(object)) {
|
||||
heap->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(object));
|
||||
@ -550,20 +554,18 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSArrayBuffer(
|
||||
template <typename StaticVisitor>
|
||||
void StaticMarkingVisitor<StaticVisitor>::VisitJSTypedArray(
|
||||
Map* map, HeapObject* object) {
|
||||
StaticVisitor::VisitPointers(
|
||||
map->GetHeap(), object,
|
||||
HeapObject::RawField(object, JSTypedArray::BodyDescriptor::kStartOffset),
|
||||
HeapObject::RawField(object, JSTypedArray::kSizeWithInternalFields));
|
||||
typedef FlexibleBodyVisitor<StaticVisitor, JSTypedArray::BodyDescriptor, void>
|
||||
JSTypedArrayBodyVisitor;
|
||||
JSTypedArrayBodyVisitor::Visit(map, object);
|
||||
}
|
||||
|
||||
|
||||
template <typename StaticVisitor>
|
||||
void StaticMarkingVisitor<StaticVisitor>::VisitJSDataView(Map* map,
|
||||
HeapObject* object) {
|
||||
StaticVisitor::VisitPointers(
|
||||
map->GetHeap(), object,
|
||||
HeapObject::RawField(object, JSDataView::BodyDescriptor::kStartOffset),
|
||||
HeapObject::RawField(object, JSDataView::kSizeWithInternalFields));
|
||||
typedef FlexibleBodyVisitor<StaticVisitor, JSDataView::BodyDescriptor, void>
|
||||
JSDataViewBodyVisitor;
|
||||
JSDataViewBodyVisitor::Visit(map, object);
|
||||
}
|
||||
|
||||
|
||||
@ -822,66 +824,6 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSFunctionWeakCode(
|
||||
}
|
||||
|
||||
|
||||
void Code::CodeIterateBody(ObjectVisitor* v) {
|
||||
int mode_mask = RelocInfo::kCodeTargetMask |
|
||||
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
|
||||
RelocInfo::ModeMask(RelocInfo::CELL) |
|
||||
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
|
||||
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
|
||||
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
|
||||
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
|
||||
RelocInfo::kDebugBreakSlotMask;
|
||||
|
||||
// There are two places where we iterate code bodies: here and the
|
||||
// templated CodeIterateBody (below). They should be kept in sync.
|
||||
IteratePointer(v, kRelocationInfoOffset);
|
||||
IteratePointer(v, kHandlerTableOffset);
|
||||
IteratePointer(v, kDeoptimizationDataOffset);
|
||||
IteratePointer(v, kTypeFeedbackInfoOffset);
|
||||
IterateNextCodeLink(v, kNextCodeLinkOffset);
|
||||
|
||||
RelocIterator it(this, mode_mask);
|
||||
Isolate* isolate = this->GetIsolate();
|
||||
for (; !it.done(); it.next()) {
|
||||
it.rinfo()->Visit(isolate, v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename StaticVisitor>
|
||||
void Code::CodeIterateBody(Heap* heap) {
|
||||
int mode_mask = RelocInfo::kCodeTargetMask |
|
||||
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
|
||||
RelocInfo::ModeMask(RelocInfo::CELL) |
|
||||
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
|
||||
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
|
||||
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
|
||||
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
|
||||
RelocInfo::kDebugBreakSlotMask;
|
||||
|
||||
// There are two places where we iterate code bodies: here and the non-
|
||||
// templated CodeIterateBody (above). They should be kept in sync.
|
||||
StaticVisitor::VisitPointer(
|
||||
heap, this,
|
||||
reinterpret_cast<Object**>(this->address() + kRelocationInfoOffset));
|
||||
StaticVisitor::VisitPointer(
|
||||
heap, this,
|
||||
reinterpret_cast<Object**>(this->address() + kHandlerTableOffset));
|
||||
StaticVisitor::VisitPointer(
|
||||
heap, this,
|
||||
reinterpret_cast<Object**>(this->address() + kDeoptimizationDataOffset));
|
||||
StaticVisitor::VisitPointer(
|
||||
heap, this,
|
||||
reinterpret_cast<Object**>(this->address() + kTypeFeedbackInfoOffset));
|
||||
StaticVisitor::VisitNextCodeLink(
|
||||
heap, reinterpret_cast<Object**>(this->address() + kNextCodeLinkOffset));
|
||||
|
||||
|
||||
RelocIterator it(this, mode_mask);
|
||||
for (; !it.done(); it.next()) {
|
||||
it.rinfo()->template Visit<StaticVisitor>(heap);
|
||||
}
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -179,138 +179,6 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
|
||||
}
|
||||
|
||||
|
||||
void HeapObject::IterateBody(InstanceType type, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
// Avoiding <Type>::cast(this) because it accesses the map pointer field.
|
||||
// During GC, the map pointer field is encoded.
|
||||
if (type < FIRST_NONSTRING_TYPE) {
|
||||
switch (type & kStringRepresentationMask) {
|
||||
case kSeqStringTag:
|
||||
break;
|
||||
case kConsStringTag:
|
||||
ConsString::BodyDescriptor::IterateBody(this, v);
|
||||
break;
|
||||
case kSlicedStringTag:
|
||||
SlicedString::BodyDescriptor::IterateBody(this, v);
|
||||
break;
|
||||
case kExternalStringTag:
|
||||
if ((type & kStringEncodingMask) == kOneByteStringTag) {
|
||||
reinterpret_cast<ExternalOneByteString*>(this)
|
||||
->ExternalOneByteStringIterateBody(v);
|
||||
} else {
|
||||
reinterpret_cast<ExternalTwoByteString*>(this)
|
||||
->ExternalTwoByteStringIterateBody(v);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case FIXED_ARRAY_TYPE:
|
||||
FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
|
||||
break;
|
||||
case FIXED_DOUBLE_ARRAY_TYPE:
|
||||
break;
|
||||
case JS_OBJECT_TYPE:
|
||||
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
|
||||
case JS_GENERATOR_OBJECT_TYPE:
|
||||
case JS_MODULE_TYPE:
|
||||
case JS_VALUE_TYPE:
|
||||
case JS_DATE_TYPE:
|
||||
case JS_ARRAY_TYPE:
|
||||
case JS_TYPED_ARRAY_TYPE:
|
||||
case JS_DATA_VIEW_TYPE:
|
||||
case JS_SET_TYPE:
|
||||
case JS_MAP_TYPE:
|
||||
case JS_SET_ITERATOR_TYPE:
|
||||
case JS_MAP_ITERATOR_TYPE:
|
||||
case JS_ITERATOR_RESULT_TYPE:
|
||||
case JS_WEAK_MAP_TYPE:
|
||||
case JS_WEAK_SET_TYPE:
|
||||
case JS_REGEXP_TYPE:
|
||||
case JS_GLOBAL_PROXY_TYPE:
|
||||
case JS_GLOBAL_OBJECT_TYPE:
|
||||
case JS_MESSAGE_OBJECT_TYPE:
|
||||
JSObject::BodyDescriptor::IterateBody(this, object_size, v);
|
||||
break;
|
||||
case JS_ARRAY_BUFFER_TYPE:
|
||||
JSArrayBuffer::JSArrayBufferIterateBody(this, v);
|
||||
break;
|
||||
case JS_FUNCTION_TYPE:
|
||||
JSFunction::BodyDescriptor::IterateBody(this, object_size, v);
|
||||
break;
|
||||
case ODDBALL_TYPE:
|
||||
Oddball::BodyDescriptor::IterateBody(this, v);
|
||||
break;
|
||||
case JS_PROXY_TYPE:
|
||||
JSProxy::BodyDescriptor::IterateBody(this, v);
|
||||
break;
|
||||
case JS_FUNCTION_PROXY_TYPE:
|
||||
JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
|
||||
break;
|
||||
case FOREIGN_TYPE:
|
||||
reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
|
||||
break;
|
||||
case MAP_TYPE:
|
||||
Map::BodyDescriptor::IterateBody(this, v);
|
||||
break;
|
||||
case CODE_TYPE:
|
||||
reinterpret_cast<Code*>(this)->CodeIterateBody(v);
|
||||
break;
|
||||
case CELL_TYPE:
|
||||
Cell::BodyDescriptor::IterateBody(this, v);
|
||||
break;
|
||||
case PROPERTY_CELL_TYPE:
|
||||
PropertyCell::BodyDescriptor::IterateBody(this, v);
|
||||
break;
|
||||
case WEAK_CELL_TYPE:
|
||||
WeakCell::BodyDescriptor::IterateBody(this, v);
|
||||
break;
|
||||
case SYMBOL_TYPE:
|
||||
Symbol::BodyDescriptor::IterateBody(this, v);
|
||||
break;
|
||||
case BYTECODE_ARRAY_TYPE:
|
||||
reinterpret_cast<BytecodeArray*>(this)->BytecodeArrayIterateBody(v);
|
||||
break;
|
||||
|
||||
case HEAP_NUMBER_TYPE:
|
||||
case MUTABLE_HEAP_NUMBER_TYPE:
|
||||
case SIMD128_VALUE_TYPE:
|
||||
case FILLER_TYPE:
|
||||
case BYTE_ARRAY_TYPE:
|
||||
case FREE_SPACE_TYPE:
|
||||
break;
|
||||
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
||||
case FIXED_##TYPE##_ARRAY_TYPE: \
|
||||
reinterpret_cast<FixedTypedArrayBase*>(this) \
|
||||
->FixedTypedArrayBaseIterateBody(v); \
|
||||
break;
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
||||
#undef TYPED_ARRAY_CASE
|
||||
|
||||
case SHARED_FUNCTION_INFO_TYPE: {
|
||||
SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
|
||||
break;
|
||||
}
|
||||
|
||||
#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
|
||||
STRUCT_LIST(MAKE_STRUCT_CASE)
|
||||
#undef MAKE_STRUCT_CASE
|
||||
if (type == ALLOCATION_SITE_TYPE) {
|
||||
AllocationSite::BodyDescriptor::IterateBody(this, v);
|
||||
} else {
|
||||
StructBodyDescriptor::IterateBody(this, object_size, v);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PrintF("Unknown type: %d\n", type);
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We don't record weak slots during marking or scavenges. Instead we do it
|
||||
// once when we complete mark-compact cycle. Note that write barrier has no
|
||||
// effect if we are already in the middle of compacting mark-sweep cycle and we
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "src/heap/heap.h"
|
||||
#include "src/heap/spaces.h"
|
||||
#include "src/layout-descriptor.h"
|
||||
#include "src/objects-body-descriptors.h"
|
||||
|
||||
// This file provides base classes and auxiliary methods for defining
|
||||
// static object visitors used during GC.
|
||||
|
@ -266,7 +266,8 @@ class ScavengingVisitor : public StaticVisitorBase {
|
||||
|
||||
static inline void EvacuateFixedArray(Map* map, HeapObject** slot,
|
||||
HeapObject* object) {
|
||||
int object_size = FixedArray::BodyDescriptor::SizeOf(map, object);
|
||||
int length = reinterpret_cast<FixedArray*>(object)->synchronized_length();
|
||||
int object_size = FixedArray::SizeFor(length);
|
||||
EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object,
|
||||
object_size);
|
||||
}
|
||||
|
@ -502,8 +502,7 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) {
|
||||
slot_callback);
|
||||
} else if (heap_object->IsJSArrayBuffer()) {
|
||||
FindPointersToNewSpaceInRegion(
|
||||
obj_address +
|
||||
JSArrayBuffer::BodyDescriptor::kStartOffset,
|
||||
obj_address + JSArrayBuffer::kPropertiesOffset,
|
||||
obj_address + JSArrayBuffer::kByteLengthOffset +
|
||||
kPointerSize,
|
||||
slot_callback);
|
||||
|
584
src/objects-body-descriptors-inl.h
Normal file
584
src/objects-body-descriptors-inl.h
Normal file
@ -0,0 +1,584 @@
|
||||
// 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/objects-body-descriptors.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
template <int start_offset>
|
||||
int FlexibleBodyDescriptor<start_offset>::SizeOf(Map* map, HeapObject* object) {
|
||||
return object->SizeFromMap(map);
|
||||
}
|
||||
|
||||
|
||||
bool BodyDescriptorBase::IsValidSlotImpl(HeapObject* obj, int offset) {
|
||||
if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
|
||||
return true;
|
||||
} else {
|
||||
DCHECK(FLAG_unbox_double_fields);
|
||||
DCHECK(IsAligned(offset, kPointerSize));
|
||||
|
||||
LayoutDescriptorHelper helper(obj->map());
|
||||
DCHECK(!helper.all_fields_tagged());
|
||||
return helper.IsTagged(offset);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
void BodyDescriptorBase::IterateBodyImpl(HeapObject* obj, int start_offset,
|
||||
int end_offset, ObjectVisitor* v) {
|
||||
if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
|
||||
IteratePointers(obj, start_offset, end_offset, v);
|
||||
} else {
|
||||
DCHECK(FLAG_unbox_double_fields);
|
||||
DCHECK(IsAligned(start_offset, kPointerSize) &&
|
||||
IsAligned(end_offset, kPointerSize));
|
||||
|
||||
LayoutDescriptorHelper helper(obj->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 StaticVisitor>
|
||||
void BodyDescriptorBase::IterateBodyImpl(Heap* heap, HeapObject* obj,
|
||||
int start_offset, int end_offset) {
|
||||
if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
|
||||
IteratePointers<StaticVisitor>(heap, obj, start_offset, end_offset);
|
||||
} else {
|
||||
DCHECK(FLAG_unbox_double_fields);
|
||||
DCHECK(IsAligned(start_offset, kPointerSize) &&
|
||||
IsAligned(end_offset, kPointerSize));
|
||||
|
||||
LayoutDescriptorHelper helper(obj->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<StaticVisitor>(heap, obj, offset, end_of_region_offset);
|
||||
}
|
||||
offset = end_of_region_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
void BodyDescriptorBase::IteratePointers(HeapObject* obj, int start_offset,
|
||||
int end_offset, ObjectVisitor* v) {
|
||||
v->VisitPointers(HeapObject::RawField(obj, start_offset),
|
||||
HeapObject::RawField(obj, end_offset));
|
||||
}
|
||||
|
||||
|
||||
template <typename StaticVisitor>
|
||||
void BodyDescriptorBase::IteratePointers(Heap* heap, HeapObject* obj,
|
||||
int start_offset, int end_offset) {
|
||||
StaticVisitor::VisitPointers(heap, 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(HeapObject::RawField(obj, offset));
|
||||
}
|
||||
|
||||
|
||||
template <typename StaticVisitor>
|
||||
void BodyDescriptorBase::IteratePointer(Heap* heap, HeapObject* obj,
|
||||
int offset) {
|
||||
StaticVisitor::VisitPointer(heap, obj, HeapObject::RawField(obj, offset));
|
||||
}
|
||||
|
||||
|
||||
// Iterates the function object according to the visiting policy.
|
||||
template <JSFunction::BodyVisitingPolicy body_visiting_policy>
|
||||
class JSFunction::BodyDescriptorImpl final : public BodyDescriptorBase {
|
||||
public:
|
||||
STATIC_ASSERT(kNonWeakFieldsEndOffset == kCodeEntryOffset);
|
||||
STATIC_ASSERT(kCodeEntryOffset + kPointerSize == kNextFunctionLinkOffset);
|
||||
STATIC_ASSERT(kNextFunctionLinkOffset + kPointerSize == kSize);
|
||||
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) {
|
||||
if (offset < kSize) return true;
|
||||
// TODO(ishell): v8:4531, fix when JFunctions are allowed to have
|
||||
// in-object properties
|
||||
// return IsValidSlotImpl(obj, offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IteratePointers(obj, kPropertiesOffset, kNonWeakFieldsEndOffset, v);
|
||||
|
||||
if (body_visiting_policy & kVisitCodeEntry) {
|
||||
v->VisitCodeEntry(obj->address() + kCodeEntryOffset);
|
||||
}
|
||||
|
||||
if (body_visiting_policy & kVisitNextFunction) {
|
||||
IteratePointers(obj, kNextFunctionLinkOffset, kSize, v);
|
||||
}
|
||||
|
||||
// TODO(ishell): v8:4531, fix when JFunctions are allowed to have in-object
|
||||
// properties
|
||||
// IterateBodyImpl(obj, kSize, object_size, v);
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
Heap* heap = obj->GetHeap();
|
||||
IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
|
||||
kNonWeakFieldsEndOffset);
|
||||
|
||||
if (body_visiting_policy & kVisitCodeEntry) {
|
||||
StaticVisitor::VisitCodeEntry(heap, obj,
|
||||
obj->address() + kCodeEntryOffset);
|
||||
}
|
||||
|
||||
if (body_visiting_policy & kVisitNextFunction) {
|
||||
IteratePointers<StaticVisitor>(heap, obj, kNextFunctionLinkOffset, kSize);
|
||||
}
|
||||
|
||||
// TODO(ishell): v8:4531, fix when JFunctions are allowed to have in-object
|
||||
// properties
|
||||
// IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object) {
|
||||
// TODO(ishell): v8:4531, fix when JFunctions are allowed to have in-object
|
||||
// properties
|
||||
return JSFunction::kSize;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
STATIC_ASSERT(kByteLengthOffset + kPointerSize == kBackingStoreOffset);
|
||||
STATIC_ASSERT(kBackingStoreOffset + kPointerSize == kBitFieldSlot);
|
||||
STATIC_ASSERT(kBitFieldSlot + kPointerSize == kSize);
|
||||
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) {
|
||||
if (offset < kBackingStoreOffset) return true;
|
||||
if (offset < kSize) return false;
|
||||
if (offset < kSizeWithInternalFields) return true;
|
||||
// TODO(ishell): v8:4531, fix when JSArrayBuffers are allowed to have
|
||||
// in-object properties
|
||||
// return IsValidSlotImpl(obj, offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IteratePointers(obj, kPropertiesOffset, kBackingStoreOffset, v);
|
||||
IteratePointers(obj, kSize, kSizeWithInternalFields, v);
|
||||
|
||||
// TODO(ishell): v8:4531, fix when JSArrayBuffers are allowed to have
|
||||
// in-object properties
|
||||
// IterateBodyImpl(obj, kSize, object_size, v);
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
Heap* heap = obj->GetHeap();
|
||||
IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
|
||||
kBackingStoreOffset);
|
||||
IteratePointers<StaticVisitor>(heap, obj, kSize, kSizeWithInternalFields);
|
||||
|
||||
// TODO(ishell): v8:4531, fix when JSArrayBuffers are allowed to have
|
||||
// in-object properties
|
||||
// IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object) {
|
||||
// TODO(ishell): v8:4531, fix when JSArrayBuffers are allowed to have
|
||||
// in-object properties
|
||||
// return map->instance_size();
|
||||
return kSizeWithInternalFields;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class BytecodeArray::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) {
|
||||
return offset == kConstantPoolOffset;
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IteratePointer(obj, kConstantPoolOffset, v);
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
Heap* heap = obj->GetHeap();
|
||||
IteratePointer<StaticVisitor>(heap, obj, kConstantPoolOffset);
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object) {
|
||||
return SizeFor(
|
||||
reinterpret_cast<FixedArray*>(object)->synchronized_length());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) {
|
||||
return offset == kBasePointerOffset;
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IteratePointer(obj, kBasePointerOffset, v);
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
Heap* heap = obj->GetHeap();
|
||||
IteratePointer<StaticVisitor>(heap, obj, kBasePointerOffset);
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object) {
|
||||
return reinterpret_cast<FixedTypedArrayBase*>(object)->size();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class JSWeakCollection::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) {
|
||||
// TODO(ishell): v8:4531, fix when JSWeakCollections are allowed to have
|
||||
// in-object properties
|
||||
// return IsValidSlotImpl(obj, offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IteratePointers(obj, kPropertiesOffset, kSize, v);
|
||||
|
||||
// TODO(ishell): v8:4531, fix when JSWeakCollections are allowed to have
|
||||
// in-object properties
|
||||
// IterateBodyImpl(obj, kSize, object_size, v);
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
Heap* heap = obj->GetHeap();
|
||||
IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset, kSize);
|
||||
|
||||
// TODO(ishell): v8:4531, fix when JSWeakCollections are allowed to have
|
||||
// in-object properties
|
||||
// IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
|
||||
};
|
||||
|
||||
|
||||
class Foreign::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
v->VisitExternalReference(reinterpret_cast<Address*>(
|
||||
HeapObject::RawField(obj, kForeignAddressOffset)));
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
StaticVisitor::VisitExternalReference(reinterpret_cast<Address*>(
|
||||
HeapObject::RawField(obj, kForeignAddressOffset)));
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
|
||||
};
|
||||
|
||||
|
||||
class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
typedef v8::String::ExternalOneByteStringResource Resource;
|
||||
v->VisitExternalOneByteString(reinterpret_cast<Resource**>(
|
||||
HeapObject::RawField(obj, kResourceOffset)));
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
typedef v8::String::ExternalOneByteStringResource Resource;
|
||||
StaticVisitor::VisitExternalOneByteString(reinterpret_cast<Resource**>(
|
||||
HeapObject::RawField(obj, kResourceOffset)));
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
|
||||
};
|
||||
|
||||
|
||||
class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
typedef v8::String::ExternalStringResource Resource;
|
||||
v->VisitExternalTwoByteString(reinterpret_cast<Resource**>(
|
||||
HeapObject::RawField(obj, kResourceOffset)));
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
typedef v8::String::ExternalStringResource Resource;
|
||||
StaticVisitor::VisitExternalTwoByteString(reinterpret_cast<Resource**>(
|
||||
HeapObject::RawField(obj, kResourceOffset)));
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
|
||||
};
|
||||
|
||||
|
||||
class Code::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
STATIC_ASSERT(kRelocationInfoOffset + kPointerSize == kHandlerTableOffset);
|
||||
STATIC_ASSERT(kHandlerTableOffset + kPointerSize ==
|
||||
kDeoptimizationDataOffset);
|
||||
STATIC_ASSERT(kDeoptimizationDataOffset + kPointerSize ==
|
||||
kTypeFeedbackInfoOffset);
|
||||
STATIC_ASSERT(kTypeFeedbackInfoOffset + kPointerSize == kNextCodeLinkOffset);
|
||||
|
||||
static bool IsValidSlot(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(HeapObject* obj, ObjectVisitor* v) {
|
||||
int mode_mask = RelocInfo::kCodeTargetMask |
|
||||
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
|
||||
RelocInfo::ModeMask(RelocInfo::CELL) |
|
||||
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
|
||||
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
|
||||
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
|
||||
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
|
||||
RelocInfo::kDebugBreakSlotMask;
|
||||
|
||||
IteratePointers(obj, kRelocationInfoOffset, kNextCodeLinkOffset, v);
|
||||
v->VisitNextCodeLink(HeapObject::RawField(obj, kNextCodeLinkOffset));
|
||||
|
||||
RelocIterator it(reinterpret_cast<Code*>(obj), mode_mask);
|
||||
Isolate* isolate = obj->GetIsolate();
|
||||
for (; !it.done(); it.next()) {
|
||||
it.rinfo()->Visit(isolate, v);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IterateBody(obj, v);
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj) {
|
||||
int mode_mask = RelocInfo::kCodeTargetMask |
|
||||
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
|
||||
RelocInfo::ModeMask(RelocInfo::CELL) |
|
||||
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
|
||||
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
|
||||
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
|
||||
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
|
||||
RelocInfo::kDebugBreakSlotMask;
|
||||
|
||||
Heap* heap = obj->GetHeap();
|
||||
IteratePointers<StaticVisitor>(heap, obj, kRelocationInfoOffset,
|
||||
kNextCodeLinkOffset);
|
||||
StaticVisitor::VisitNextCodeLink(
|
||||
heap, HeapObject::RawField(obj, kNextCodeLinkOffset));
|
||||
|
||||
RelocIterator it(reinterpret_cast<Code*>(obj), mode_mask);
|
||||
for (; !it.done(); it.next()) {
|
||||
it.rinfo()->template Visit<StaticVisitor>(heap);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
IterateBody<StaticVisitor>(obj);
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object) {
|
||||
return reinterpret_cast<Code*>(object)->CodeSize();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Op, typename ReturnType, typename T1, typename T2,
|
||||
typename T3>
|
||||
ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3) {
|
||||
if (type < FIRST_NONSTRING_TYPE) {
|
||||
switch (type & kStringRepresentationMask) {
|
||||
case kSeqStringTag:
|
||||
return ReturnType();
|
||||
case kConsStringTag:
|
||||
return Op::template apply<ConsString::BodyDescriptor>(p1, p2, p3);
|
||||
case kSlicedStringTag:
|
||||
return Op::template apply<SlicedString::BodyDescriptor>(p1, p2, p3);
|
||||
case kExternalStringTag:
|
||||
if ((type & kStringEncodingMask) == kOneByteStringTag) {
|
||||
return Op::template apply<ExternalOneByteString::BodyDescriptor>(
|
||||
p1, p2, p3);
|
||||
} else {
|
||||
return Op::template apply<ExternalTwoByteString::BodyDescriptor>(
|
||||
p1, p2, p3);
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
return ReturnType();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case FIXED_ARRAY_TYPE:
|
||||
return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3);
|
||||
case FIXED_DOUBLE_ARRAY_TYPE:
|
||||
return ReturnType();
|
||||
case JS_OBJECT_TYPE:
|
||||
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
|
||||
case JS_GENERATOR_OBJECT_TYPE:
|
||||
case JS_MODULE_TYPE:
|
||||
case JS_VALUE_TYPE:
|
||||
case JS_DATE_TYPE:
|
||||
case JS_ARRAY_TYPE:
|
||||
case JS_TYPED_ARRAY_TYPE:
|
||||
case JS_DATA_VIEW_TYPE:
|
||||
case JS_SET_TYPE:
|
||||
case JS_MAP_TYPE:
|
||||
case JS_SET_ITERATOR_TYPE:
|
||||
case JS_MAP_ITERATOR_TYPE:
|
||||
case JS_ITERATOR_RESULT_TYPE:
|
||||
case JS_REGEXP_TYPE:
|
||||
case JS_GLOBAL_PROXY_TYPE:
|
||||
case JS_GLOBAL_OBJECT_TYPE:
|
||||
case JS_MESSAGE_OBJECT_TYPE:
|
||||
return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3);
|
||||
case JS_WEAK_MAP_TYPE:
|
||||
case JS_WEAK_SET_TYPE:
|
||||
return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3);
|
||||
case JS_ARRAY_BUFFER_TYPE:
|
||||
return Op::template apply<JSArrayBuffer::BodyDescriptor>(p1, p2, p3);
|
||||
case JS_FUNCTION_TYPE:
|
||||
return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3);
|
||||
case ODDBALL_TYPE:
|
||||
return Op::template apply<Oddball::BodyDescriptor>(p1, p2, p3);
|
||||
case JS_PROXY_TYPE:
|
||||
return Op::template apply<JSProxy::BodyDescriptor>(p1, p2, p3);
|
||||
case JS_FUNCTION_PROXY_TYPE:
|
||||
return Op::template apply<JSFunctionProxy::BodyDescriptor>(p1, p2, p3);
|
||||
case FOREIGN_TYPE:
|
||||
return Op::template apply<Foreign::BodyDescriptor>(p1, p2, p3);
|
||||
case MAP_TYPE:
|
||||
return Op::template apply<Map::BodyDescriptor>(p1, p2, p3);
|
||||
case CODE_TYPE:
|
||||
return Op::template apply<Code::BodyDescriptor>(p1, p2, p3);
|
||||
case CELL_TYPE:
|
||||
return Op::template apply<Cell::BodyDescriptor>(p1, p2, p3);
|
||||
case PROPERTY_CELL_TYPE:
|
||||
return Op::template apply<PropertyCell::BodyDescriptor>(p1, p2, p3);
|
||||
case WEAK_CELL_TYPE:
|
||||
return Op::template apply<WeakCell::BodyDescriptor>(p1, p2, p3);
|
||||
case SYMBOL_TYPE:
|
||||
return Op::template apply<Symbol::BodyDescriptor>(p1, p2, p3);
|
||||
case BYTECODE_ARRAY_TYPE:
|
||||
return Op::template apply<BytecodeArray::BodyDescriptor>(p1, p2, p3);
|
||||
|
||||
case HEAP_NUMBER_TYPE:
|
||||
case MUTABLE_HEAP_NUMBER_TYPE:
|
||||
case SIMD128_VALUE_TYPE:
|
||||
case FILLER_TYPE:
|
||||
case BYTE_ARRAY_TYPE:
|
||||
case FREE_SPACE_TYPE:
|
||||
return ReturnType();
|
||||
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
||||
case FIXED_##TYPE##_ARRAY_TYPE: \
|
||||
return Op::template apply<FixedTypedArrayBase::BodyDescriptor>(p1, p2, p3);
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
||||
#undef TYPED_ARRAY_CASE
|
||||
|
||||
case SHARED_FUNCTION_INFO_TYPE: {
|
||||
return Op::template apply<SharedFunctionInfo::BodyDescriptor>(p1, p2, p3);
|
||||
}
|
||||
|
||||
#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
|
||||
STRUCT_LIST(MAKE_STRUCT_CASE)
|
||||
#undef MAKE_STRUCT_CASE
|
||||
if (type == ALLOCATION_SITE_TYPE) {
|
||||
return Op::template apply<AllocationSite::BodyDescriptor>(p1, p2, p3);
|
||||
} else {
|
||||
return Op::template apply<StructBodyDescriptor>(p1, p2, p3);
|
||||
}
|
||||
default:
|
||||
PrintF("Unknown type: %d\n", type);
|
||||
UNREACHABLE();
|
||||
return ReturnType();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
void HeapObject::IterateFast(ObjectVisitor* v) {
|
||||
BodyDescriptorBase::IteratePointer(this, kMapOffset, v);
|
||||
IterateBody(v);
|
||||
}
|
||||
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
void HeapObject::IterateBodyFast(ObjectVisitor* v) {
|
||||
Map* m = map();
|
||||
IterateBody(m->instance_type(), SizeFromMap(m), v);
|
||||
}
|
||||
|
||||
|
||||
struct CallIterateBody {
|
||||
template <typename BodyDescriptor, typename ObjectVisitor>
|
||||
static void apply(HeapObject* obj, int object_size, ObjectVisitor* v) {
|
||||
BodyDescriptor::IterateBody(obj, object_size, v);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
void HeapObject::IterateBodyFast(InstanceType type, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
BodyDescriptorApply<CallIterateBody, void>(type, this, object_size, v);
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_OBJECTS_BODY_DESCRIPTORS_INL_H_
|
139
src/objects-body-descriptors.h
Normal file
139
src/objects-body-descriptors.h
Normal file
@ -0,0 +1,139 @@
|
||||
// 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_H_
|
||||
#define V8_OBJECTS_BODY_DESCRIPTORS_H_
|
||||
|
||||
#include "src/objects.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// This is the base class for object's body descriptors.
|
||||
//
|
||||
// Each BodyDescriptor subclass must provide the following methods:
|
||||
//
|
||||
// 1) Returns true if the object contains a tagged value at given offset.
|
||||
// It is used for invalid slots filtering. If the offset points outside
|
||||
// of the object or to the map word, the result is UNDEFINED (!!!).
|
||||
//
|
||||
// static bool IsValidSlot(HeapObject* obj, int offset);
|
||||
//
|
||||
//
|
||||
// 2) Iterate object's body using stateful object visitor.
|
||||
//
|
||||
// template <typename ObjectVisitor>
|
||||
// static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
// ObjectVisitor* v);
|
||||
//
|
||||
//
|
||||
// 3) Iterate object's body using stateless object visitor.
|
||||
//
|
||||
// template <typename StaticVisitor>
|
||||
// static inline void IterateBody(HeapObject* obj, int object_size);
|
||||
//
|
||||
class BodyDescriptorBase BASE_EMBEDDED {
|
||||
public:
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IteratePointers(HeapObject* obj, int start_offset,
|
||||
int end_offset, ObjectVisitor* v);
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IteratePointers(Heap* heap, HeapObject* obj,
|
||||
int start_offset, int end_offset);
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IteratePointer(HeapObject* obj, int offset,
|
||||
ObjectVisitor* v);
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IteratePointer(Heap* heap, HeapObject* obj, int offset);
|
||||
|
||||
protected:
|
||||
// Returns true for all header fields.
|
||||
static inline bool IsValidSlotImpl(HeapObject* obj, int offset);
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBodyImpl(HeapObject* obj, int start_offset,
|
||||
int end_offset, ObjectVisitor* v);
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBodyImpl(Heap* heap, HeapObject* obj,
|
||||
int start_offset, int end_offset);
|
||||
};
|
||||
|
||||
|
||||
// This class describes a body of an object of a fixed size
|
||||
// in which all pointer fields are located in the [start_offset, end_offset)
|
||||
// interval.
|
||||
template <int start_offset, int end_offset, int size>
|
||||
class FixedBodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static const int kStartOffset = start_offset;
|
||||
static const int kEndOffset = end_offset;
|
||||
static const int kSize = size;
|
||||
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) {
|
||||
return offset >= kStartOffset && offset < kEndOffset;
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, ObjectVisitor* v) {
|
||||
IterateBodyImpl(obj, start_offset, end_offset, v);
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IterateBody(obj, v);
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj) {
|
||||
Heap* heap = obj->GetHeap();
|
||||
IterateBodyImpl<StaticVisitor>(heap, obj, start_offset, end_offset);
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
IterateBody(obj);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// This class describes a body of an object of a variable size
|
||||
// in which all pointer fields are located in the [start_offset, object_size)
|
||||
// interval.
|
||||
template <int start_offset>
|
||||
class FlexibleBodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static const int kStartOffset = start_offset;
|
||||
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) {
|
||||
if (offset < kStartOffset) return false;
|
||||
return IsValidSlotImpl(obj, offset);
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IterateBodyImpl(obj, start_offset, object_size, v);
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
Heap* heap = obj->GetHeap();
|
||||
IterateBodyImpl<StaticVisitor>(heap, obj, start_offset, object_size);
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object);
|
||||
};
|
||||
|
||||
|
||||
typedef FlexibleBodyDescriptor<HeapObject::kHeaderSize> StructBodyDescriptor;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_OBJECTS_BODY_DESCRIPTORS_H_
|
@ -1530,22 +1530,6 @@ HeapObjectContents HeapObject::ContentType() {
|
||||
}
|
||||
|
||||
|
||||
void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
|
||||
v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
|
||||
reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
|
||||
}
|
||||
|
||||
|
||||
void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
|
||||
v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
|
||||
}
|
||||
|
||||
|
||||
void HeapObject::IterateNextCodeLink(ObjectVisitor* v, int offset) {
|
||||
v->VisitNextCodeLink(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
|
||||
}
|
||||
|
||||
|
||||
double HeapNumber::value() const {
|
||||
return READ_DOUBLE_FIELD(this, kValueOffset);
|
||||
}
|
||||
@ -4173,11 +4157,6 @@ Address ByteArray::GetDataStartAddress() {
|
||||
}
|
||||
|
||||
|
||||
void BytecodeArray::BytecodeArrayIterateBody(ObjectVisitor* v) {
|
||||
IteratePointer(v, kConstantPoolOffset);
|
||||
}
|
||||
|
||||
|
||||
byte BytecodeArray::get(int index) {
|
||||
DCHECK(index >= 0 && index < this->length());
|
||||
return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
|
||||
@ -4538,7 +4517,8 @@ int HeapObject::SizeFromMap(Map* map) {
|
||||
// Only inline the most frequent cases.
|
||||
InstanceType instance_type = map->instance_type();
|
||||
if (instance_type == FIXED_ARRAY_TYPE) {
|
||||
return FixedArray::BodyDescriptor::SizeOf(map, this);
|
||||
return FixedArray::SizeFor(
|
||||
reinterpret_cast<FixedArray*>(this)->synchronized_length());
|
||||
}
|
||||
if (instance_type == ONE_BYTE_STRING_TYPE ||
|
||||
instance_type == ONE_BYTE_INTERNALIZED_STRING_TYPE) {
|
||||
@ -6677,32 +6657,6 @@ void JSArrayBuffer::set_is_shared(bool value) {
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
template <typename StaticVisitor>
|
||||
void JSArrayBuffer::JSArrayBufferIterateBody(Heap* heap, HeapObject* obj) {
|
||||
StaticVisitor::VisitPointers(
|
||||
heap, obj,
|
||||
HeapObject::RawField(obj, JSArrayBuffer::BodyDescriptor::kStartOffset),
|
||||
HeapObject::RawField(obj,
|
||||
JSArrayBuffer::kByteLengthOffset + kPointerSize));
|
||||
StaticVisitor::VisitPointers(
|
||||
heap, obj, HeapObject::RawField(obj, JSArrayBuffer::kSize),
|
||||
HeapObject::RawField(obj, JSArrayBuffer::kSizeWithInternalFields));
|
||||
}
|
||||
|
||||
|
||||
void JSArrayBuffer::JSArrayBufferIterateBody(HeapObject* obj,
|
||||
ObjectVisitor* v) {
|
||||
v->VisitPointers(
|
||||
HeapObject::RawField(obj, JSArrayBuffer::BodyDescriptor::kStartOffset),
|
||||
HeapObject::RawField(obj,
|
||||
JSArrayBuffer::kByteLengthOffset + kPointerSize));
|
||||
v->VisitPointers(
|
||||
HeapObject::RawField(obj, JSArrayBuffer::kSize),
|
||||
HeapObject::RawField(obj, JSArrayBuffer::kSizeWithInternalFields));
|
||||
}
|
||||
|
||||
|
||||
Object* JSArrayBufferView::byte_offset() const {
|
||||
if (WasNeutered()) return Smi::FromInt(0);
|
||||
return Object::cast(READ_FIELD(this, kByteOffsetOffset));
|
||||
@ -7835,189 +7789,6 @@ Relocatable::~Relocatable() {
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
template <int start_offset>
|
||||
int FlexibleBodyDescriptor<start_offset>::SizeOf(Map* map, HeapObject* object) {
|
||||
return map->instance_size();
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
int FixedArray::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
|
||||
return SizeFor(reinterpret_cast<FixedArray*>(object)->synchronized_length());
|
||||
}
|
||||
|
||||
|
||||
void Foreign::ForeignIterateBody(ObjectVisitor* v) {
|
||||
v->VisitExternalReference(
|
||||
reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
|
||||
}
|
||||
|
||||
|
||||
template<typename StaticVisitor>
|
||||
void Foreign::ForeignIterateBody() {
|
||||
StaticVisitor::VisitExternalReference(
|
||||
reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
|
||||
}
|
||||
|
||||
|
||||
void FixedTypedArrayBase::FixedTypedArrayBaseIterateBody(ObjectVisitor* v) {
|
||||
v->VisitPointer(
|
||||
reinterpret_cast<Object**>(FIELD_ADDR(this, kBasePointerOffset)));
|
||||
}
|
||||
|
||||
|
||||
template <typename StaticVisitor>
|
||||
void FixedTypedArrayBase::FixedTypedArrayBaseIterateBody() {
|
||||
StaticVisitor::VisitPointer(
|
||||
reinterpret_cast<Object**>(FIELD_ADDR(this, kBasePointerOffset)));
|
||||
}
|
||||
|
||||
|
||||
void ExternalOneByteString::ExternalOneByteStringIterateBody(ObjectVisitor* v) {
|
||||
typedef v8::String::ExternalOneByteStringResource Resource;
|
||||
v->VisitExternalOneByteString(
|
||||
reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
|
||||
}
|
||||
|
||||
|
||||
template <typename StaticVisitor>
|
||||
void ExternalOneByteString::ExternalOneByteStringIterateBody() {
|
||||
typedef v8::String::ExternalOneByteStringResource Resource;
|
||||
StaticVisitor::VisitExternalOneByteString(
|
||||
reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
|
||||
}
|
||||
|
||||
|
||||
void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
|
||||
typedef v8::String::ExternalStringResource Resource;
|
||||
v->VisitExternalTwoByteString(
|
||||
reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
|
||||
}
|
||||
|
||||
|
||||
template<typename StaticVisitor>
|
||||
void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
|
||||
typedef v8::String::ExternalStringResource Resource;
|
||||
StaticVisitor::VisitExternalTwoByteString(
|
||||
reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
|
||||
}
|
||||
|
||||
|
||||
void BodyDescriptorBase::IterateBodyImpl(HeapObject* obj, int start_offset,
|
||||
int end_offset, ObjectVisitor* v) {
|
||||
if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
|
||||
IteratePointers(obj, start_offset, end_offset, v);
|
||||
} else {
|
||||
DCHECK(FLAG_unbox_double_fields);
|
||||
DCHECK(IsAligned(start_offset, kPointerSize) &&
|
||||
IsAligned(end_offset, kPointerSize));
|
||||
|
||||
LayoutDescriptorHelper helper(obj->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 StaticVisitor>
|
||||
void BodyDescriptorBase::IterateBodyImpl(Heap* heap, HeapObject* obj,
|
||||
int start_offset, int end_offset) {
|
||||
if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
|
||||
IteratePointers<StaticVisitor>(heap, obj, start_offset, end_offset);
|
||||
} else {
|
||||
DCHECK(FLAG_unbox_double_fields);
|
||||
DCHECK(IsAligned(start_offset, kPointerSize) &&
|
||||
IsAligned(end_offset, kPointerSize));
|
||||
|
||||
LayoutDescriptorHelper helper(obj->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<StaticVisitor>(heap, obj, offset, end_of_region_offset);
|
||||
}
|
||||
offset = end_of_region_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BodyDescriptorBase::IteratePointers(HeapObject* obj, int start_offset,
|
||||
int end_offset, ObjectVisitor* v) {
|
||||
v->VisitPointers(HeapObject::RawField(obj, start_offset),
|
||||
HeapObject::RawField(obj, end_offset));
|
||||
}
|
||||
|
||||
|
||||
template <typename StaticVisitor>
|
||||
void BodyDescriptorBase::IteratePointers(Heap* heap, HeapObject* obj,
|
||||
int start_offset, int end_offset) {
|
||||
StaticVisitor::VisitPointers(heap, obj,
|
||||
HeapObject::RawField(obj, start_offset),
|
||||
HeapObject::RawField(obj, end_offset));
|
||||
}
|
||||
|
||||
|
||||
// Iterates the function object according to the visiting policy.
|
||||
template <JSFunction::BodyVisitingPolicy body_visiting_policy>
|
||||
class JSFunction::BodyDescriptorImpl : public BodyDescriptorBase {
|
||||
public:
|
||||
STATIC_ASSERT(kNonWeakFieldsEndOffset == kCodeEntryOffset);
|
||||
STATIC_ASSERT(kCodeEntryOffset + kPointerSize == kNextFunctionLinkOffset);
|
||||
STATIC_ASSERT(kNextFunctionLinkOffset + kPointerSize == kSize);
|
||||
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IteratePointers(obj, kPropertiesOffset, kNonWeakFieldsEndOffset, v);
|
||||
|
||||
if (body_visiting_policy & kVisitCodeEntry) {
|
||||
v->VisitCodeEntry(obj->address() + kCodeEntryOffset);
|
||||
}
|
||||
|
||||
if (body_visiting_policy & kVisitNextFunction) {
|
||||
IteratePointers(obj, kNextFunctionLinkOffset, kSize, v);
|
||||
}
|
||||
|
||||
// TODO(ishell): v8:4531, fix when JFunctions are allowed to have in-object
|
||||
// properties
|
||||
// IterateBodyImpl(obj, kSize, object_size, v);
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
Heap* heap = obj->GetHeap();
|
||||
IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
|
||||
kNonWeakFieldsEndOffset);
|
||||
|
||||
if (body_visiting_policy & kVisitCodeEntry) {
|
||||
StaticVisitor::VisitCodeEntry(heap, obj,
|
||||
obj->address() + kCodeEntryOffset);
|
||||
}
|
||||
|
||||
if (body_visiting_policy & kVisitNextFunction) {
|
||||
IteratePointers<StaticVisitor>(heap, obj, kNextFunctionLinkOffset, kSize);
|
||||
}
|
||||
|
||||
// TODO(ishell): v8:4531, fix when JFunctions are allowed to have in-object
|
||||
// properties
|
||||
// IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object) {
|
||||
// TODO(ishell): v8:4531, fix when JFunctions are allowed to have in-object
|
||||
// properties
|
||||
return JSFunction::kSize;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class Derived, class TableType>
|
||||
Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() {
|
||||
TableType* table(TableType::cast(this->table()));
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "src/macro-assembler.h"
|
||||
#include "src/messages.h"
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/objects-body-descriptors-inl.h"
|
||||
#include "src/profiler/cpu-profiler.h"
|
||||
#include "src/property-descriptor.h"
|
||||
#include "src/prototype.h"
|
||||
@ -1999,12 +2000,33 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
|
||||
}
|
||||
|
||||
|
||||
void HeapObject::Iterate(ObjectVisitor* v) {
|
||||
// Handle header
|
||||
IteratePointer(v, kMapOffset);
|
||||
// Handle object body
|
||||
void HeapObject::Iterate(ObjectVisitor* v) { IterateFast<ObjectVisitor>(v); }
|
||||
|
||||
|
||||
void HeapObject::IterateBody(ObjectVisitor* v) {
|
||||
Map* m = map();
|
||||
IterateBody(m->instance_type(), SizeFromMap(m), v);
|
||||
IterateBodyFast<ObjectVisitor>(m->instance_type(), SizeFromMap(m), v);
|
||||
}
|
||||
|
||||
|
||||
void HeapObject::IterateBody(InstanceType type, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IterateBodyFast<ObjectVisitor>(type, object_size, v);
|
||||
}
|
||||
|
||||
|
||||
struct CallIsValidSlot {
|
||||
template <typename BodyDescriptor>
|
||||
static bool apply(HeapObject* obj, int offset, int) {
|
||||
return BodyDescriptor::IsValidSlot(obj, offset);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
bool HeapObject::IsValidSlot(int offset) {
|
||||
DCHECK_NE(0, offset);
|
||||
return BodyDescriptorApply<CallIsValidSlot, bool>(map()->instance_type(),
|
||||
this, offset, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -15249,15 +15271,14 @@ class InternalizedStringKey : public HashTableKey {
|
||||
|
||||
template<typename Derived, typename Shape, typename Key>
|
||||
void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
|
||||
IteratePointers(v, 0, kElementsStartOffset);
|
||||
BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v);
|
||||
}
|
||||
|
||||
|
||||
template<typename Derived, typename Shape, typename Key>
|
||||
void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
|
||||
IteratePointers(v,
|
||||
kElementsStartOffset,
|
||||
kHeaderSize + length() * kPointerSize);
|
||||
BodyDescriptorBase::IteratePointers(this, kElementsStartOffset,
|
||||
kHeaderSize + length() * kPointerSize, v);
|
||||
}
|
||||
|
||||
|
||||
|
158
src/objects.h
158
src/objects.h
@ -1555,15 +1555,35 @@ class HeapObject: public Object {
|
||||
return reinterpret_cast<Address>(this) - kHeapObjectTag;
|
||||
}
|
||||
|
||||
// Iterates over pointers contained in the object (including the Map)
|
||||
// Iterates over pointers contained in the object (including the Map).
|
||||
// If it's not performance critical iteration use the non-templatized
|
||||
// version.
|
||||
void Iterate(ObjectVisitor* v);
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
inline void IterateFast(ObjectVisitor* v);
|
||||
|
||||
// Iterates over all pointers contained in the object except the
|
||||
// first map pointer. The object type is given in the first
|
||||
// parameter. This function does not access the map pointer in the
|
||||
// object, and so is safe to call while the map pointer is modified.
|
||||
// If it's not performance critical iteration use the non-templatized
|
||||
// version.
|
||||
void IterateBody(ObjectVisitor* v);
|
||||
void IterateBody(InstanceType type, int object_size, ObjectVisitor* v);
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
inline void IterateBodyFast(ObjectVisitor* v);
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
inline void IterateBodyFast(InstanceType type, int object_size,
|
||||
ObjectVisitor* v);
|
||||
|
||||
// Returns true if the object contains a tagged value at given offset.
|
||||
// It is used for invalid slots filtering. If the offset points outside
|
||||
// of the object or to the map word, the result is UNDEFINED (!!!).
|
||||
bool IsValidSlot(int offset);
|
||||
|
||||
// Returns the heap object's size in bytes
|
||||
inline int Size();
|
||||
|
||||
@ -1623,90 +1643,17 @@ class HeapObject: public Object {
|
||||
|
||||
STATIC_ASSERT(kMapOffset == Internals::kHeapObjectMapOffset);
|
||||
|
||||
protected:
|
||||
// helpers for calling an ObjectVisitor to iterate over pointers in the
|
||||
// half-open range [start, end) specified as integer offsets
|
||||
inline void IteratePointers(ObjectVisitor* v, int start, int end);
|
||||
// as above, for the single element at "offset"
|
||||
inline void IteratePointer(ObjectVisitor* v, int offset);
|
||||
// as above, for the next code link of a code object.
|
||||
inline void IterateNextCodeLink(ObjectVisitor* v, int offset);
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
|
||||
};
|
||||
|
||||
|
||||
// This is the base class for object's body descriptors.
|
||||
class BodyDescriptorBase {
|
||||
protected:
|
||||
static inline void IterateBodyImpl(HeapObject* obj, int start_offset,
|
||||
int end_offset, ObjectVisitor* v);
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBodyImpl(Heap* heap, HeapObject* obj,
|
||||
int start_offset, int end_offset);
|
||||
|
||||
static inline void IteratePointers(HeapObject* obj, int start_offset,
|
||||
int end_offset, ObjectVisitor* v);
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IteratePointers(Heap* heap, HeapObject* obj,
|
||||
int start_offset, int end_offset);
|
||||
};
|
||||
|
||||
|
||||
// This class describes a body of an object of a fixed size
|
||||
// in which all pointer fields are located in the [start_offset, end_offset)
|
||||
// interval.
|
||||
template <int start_offset, int end_offset, int size>
|
||||
class FixedBodyDescriptor : public BodyDescriptorBase {
|
||||
public:
|
||||
static const int kStartOffset = start_offset;
|
||||
static const int kEndOffset = end_offset;
|
||||
static const int kSize = size;
|
||||
|
||||
static inline void IterateBody(HeapObject* obj, ObjectVisitor* v) {
|
||||
IterateBodyImpl(obj, start_offset, end_offset, v);
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj) {
|
||||
Heap* heap = obj->GetHeap();
|
||||
IterateBodyImpl<StaticVisitor>(heap, obj, start_offset, end_offset);
|
||||
}
|
||||
};
|
||||
class FixedBodyDescriptor;
|
||||
|
||||
|
||||
// This base class describes a body of an object of a variable size
|
||||
// in which all pointer fields are located in the [start_offset, object_size)
|
||||
// interval.
|
||||
template <int start_offset>
|
||||
class FlexibleBodyDescriptorBase : public BodyDescriptorBase {
|
||||
public:
|
||||
static const int kStartOffset = start_offset;
|
||||
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IterateBodyImpl(obj, start_offset, object_size, v);
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
Heap* heap = obj->GetHeap();
|
||||
IterateBodyImpl<StaticVisitor>(heap, obj, start_offset, object_size);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// This class describes a body of an object of a variable size
|
||||
// in which all pointer fields are located in the [start_offset, object_size)
|
||||
// interval. The size of the object is taken from the map.
|
||||
template <int start_offset>
|
||||
class FlexibleBodyDescriptor : public FlexibleBodyDescriptorBase<start_offset> {
|
||||
public:
|
||||
static inline int SizeOf(Map* map, HeapObject* object);
|
||||
};
|
||||
class FlexibleBodyDescriptor;
|
||||
|
||||
|
||||
// The HeapNumber class describes heap allocated numbers that cannot be
|
||||
@ -2688,10 +2635,7 @@ class FixedArray: public FixedArrayBase {
|
||||
// object, the prefix of this array is sorted.
|
||||
void SortPairs(FixedArray* numbers, uint32_t len);
|
||||
|
||||
class BodyDescriptor : public FlexibleBodyDescriptorBase<kHeaderSize> {
|
||||
public:
|
||||
static inline int SizeOf(Map* map, HeapObject* object);
|
||||
};
|
||||
typedef FlexibleBodyDescriptor<kHeaderSize> BodyDescriptor;
|
||||
|
||||
protected:
|
||||
// Set operation on FixedArray without using write barriers. Can
|
||||
@ -4423,7 +4367,6 @@ class BytecodeArray : public FixedArrayBase {
|
||||
|
||||
// Dispatched behavior.
|
||||
inline int BytecodeArraySize();
|
||||
inline void BytecodeArrayIterateBody(ObjectVisitor* v);
|
||||
|
||||
DECLARE_PRINTER(BytecodeArray)
|
||||
DECLARE_VERIFIER(BytecodeArray)
|
||||
@ -4443,6 +4386,8 @@ class BytecodeArray : public FixedArrayBase {
|
||||
// Maximal length of a single BytecodeArray.
|
||||
static const int kMaxLength = kMaxSize - kHeaderSize;
|
||||
|
||||
class BodyDescriptor;
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(BytecodeArray);
|
||||
};
|
||||
@ -4508,11 +4453,6 @@ class FixedTypedArrayBase: public FixedArrayBase {
|
||||
DECL_ACCESSORS(external_pointer, void)
|
||||
|
||||
// Dispatched behavior.
|
||||
inline void FixedTypedArrayBaseIterateBody(ObjectVisitor* v);
|
||||
|
||||
template <typename StaticVisitor>
|
||||
inline void FixedTypedArrayBaseIterateBody();
|
||||
|
||||
DECLARE_CAST(FixedTypedArrayBase)
|
||||
|
||||
static const int kBasePointerOffset = FixedArrayBase::kHeaderSize;
|
||||
@ -4522,6 +4462,8 @@ class FixedTypedArrayBase: public FixedArrayBase {
|
||||
|
||||
static const int kDataOffset = kHeaderSize;
|
||||
|
||||
class BodyDescriptor;
|
||||
|
||||
inline int size();
|
||||
|
||||
static inline int TypedArraySize(InstanceType type, int length);
|
||||
@ -5192,10 +5134,6 @@ class Code: public HeapObject {
|
||||
|
||||
// Dispatched behavior.
|
||||
inline int CodeSize();
|
||||
inline void CodeIterateBody(ObjectVisitor* v);
|
||||
|
||||
template<typename StaticVisitor>
|
||||
inline void CodeIterateBody(Heap* heap);
|
||||
|
||||
DECLARE_PRINTER(Code)
|
||||
DECLARE_VERIFIER(Code)
|
||||
@ -5294,6 +5232,8 @@ class Code: public HeapObject {
|
||||
static const int kHeaderSize =
|
||||
(kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask;
|
||||
|
||||
class BodyDescriptor;
|
||||
|
||||
// Byte offsets within kKindSpecificFlags1Offset.
|
||||
static const int kFullCodeFlags = kKindSpecificFlags1Offset;
|
||||
class FullCodeFlagsHasDeoptimizationSupportField:
|
||||
@ -9204,11 +9144,7 @@ class ExternalOneByteString : public ExternalString {
|
||||
|
||||
DECLARE_CAST(ExternalOneByteString)
|
||||
|
||||
// Garbage collection support.
|
||||
inline void ExternalOneByteStringIterateBody(ObjectVisitor* v);
|
||||
|
||||
template <typename StaticVisitor>
|
||||
inline void ExternalOneByteStringIterateBody();
|
||||
class BodyDescriptor;
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalOneByteString);
|
||||
@ -9243,11 +9179,7 @@ class ExternalTwoByteString: public ExternalString {
|
||||
|
||||
DECLARE_CAST(ExternalTwoByteString)
|
||||
|
||||
// Garbage collection support.
|
||||
inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
|
||||
|
||||
template<typename StaticVisitor>
|
||||
inline void ExternalTwoByteStringIterateBody();
|
||||
class BodyDescriptor;
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString);
|
||||
@ -9868,6 +9800,8 @@ class JSWeakCollection: public JSObject {
|
||||
static const int kNextOffset = kTableOffset + kPointerSize;
|
||||
static const int kSize = kNextOffset + kPointerSize;
|
||||
|
||||
class BodyDescriptor;
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakCollection);
|
||||
};
|
||||
@ -9946,11 +9880,6 @@ class JSArrayBuffer: public JSObject {
|
||||
DECLARE_VERIFIER(JSArrayBuffer)
|
||||
|
||||
static const int kByteLengthOffset = JSObject::kHeaderSize;
|
||||
|
||||
// NOTE: GC will visit objects fields:
|
||||
// 1. From JSObject::BodyDescriptor::kStartOffset to kByteLengthOffset +
|
||||
// kPointerSize
|
||||
// 2. From start of the internal fields and up to the end of them
|
||||
static const int kBackingStoreOffset = kByteLengthOffset + kPointerSize;
|
||||
static const int kBitFieldSlot = kBackingStoreOffset + kPointerSize;
|
||||
#if V8_TARGET_LITTLE_ENDIAN || !V8_HOST_ARCH_64_BIT
|
||||
@ -9963,11 +9892,9 @@ class JSArrayBuffer: public JSObject {
|
||||
static const int kSizeWithInternalFields =
|
||||
kSize + v8::ArrayBuffer::kInternalFieldCount * kPointerSize;
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void JSArrayBufferIterateBody(Heap* heap, HeapObject* obj);
|
||||
|
||||
static inline void JSArrayBufferIterateBody(HeapObject* obj,
|
||||
ObjectVisitor* v);
|
||||
// Iterates all fields in the object including internal ones except
|
||||
// kBackingStoreOffset and kBitFieldSlot.
|
||||
class BodyDescriptor;
|
||||
|
||||
class IsExternal : public BitField<bool, 1, 1> {};
|
||||
class IsNeuterable : public BitField<bool, 2, 1> {};
|
||||
@ -10072,12 +9999,6 @@ class Foreign: public HeapObject {
|
||||
|
||||
DECLARE_CAST(Foreign)
|
||||
|
||||
// Dispatched behavior.
|
||||
inline void ForeignIterateBody(ObjectVisitor* v);
|
||||
|
||||
template<typename StaticVisitor>
|
||||
inline void ForeignIterateBody();
|
||||
|
||||
// Dispatched behavior.
|
||||
DECLARE_PRINTER(Foreign)
|
||||
DECLARE_VERIFIER(Foreign)
|
||||
@ -10089,6 +10010,8 @@ class Foreign: public HeapObject {
|
||||
|
||||
STATIC_ASSERT(kForeignAddressOffset == Internals::kForeignAddressOffset);
|
||||
|
||||
class BodyDescriptor;
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(Foreign);
|
||||
};
|
||||
@ -10752,9 +10675,6 @@ class ObjectVisitor BASE_EMBEDDED {
|
||||
};
|
||||
|
||||
|
||||
typedef FlexibleBodyDescriptor<HeapObject::kHeaderSize> StructBodyDescriptor;
|
||||
|
||||
|
||||
// BooleanBit is a helper class for setting and getting a bit in an integer.
|
||||
class BooleanBit : public AllStatic {
|
||||
public:
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "src/code-stubs.h"
|
||||
#include "src/conversions.h"
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/objects-body-descriptors.h"
|
||||
#include "src/profiler/allocation-tracker.h"
|
||||
#include "src/profiler/heap-profiler.h"
|
||||
#include "src/profiler/heap-snapshot-generator-inl.h"
|
||||
@ -1542,7 +1543,7 @@ void V8HeapExplorer::ExtractAllocationSiteReferences(int entry,
|
||||
// Do not visit weak_next as it is not visited by the StaticVisitor,
|
||||
// and we're not very interested in weak_next field here.
|
||||
STATIC_ASSERT(AllocationSite::kWeakNextOffset >=
|
||||
AllocationSite::BodyDescriptor::kEndOffset);
|
||||
AllocationSite::BodyDescriptor::kEndOffset);
|
||||
}
|
||||
|
||||
|
||||
|
@ -867,6 +867,8 @@
|
||||
'../../src/modules.cc',
|
||||
'../../src/modules.h',
|
||||
'../../src/msan.h',
|
||||
'../../src/objects-body-descriptors-inl.h',
|
||||
'../../src/objects-body-descriptors.h',
|
||||
'../../src/objects-debug.cc',
|
||||
'../../src/objects-inl.h',
|
||||
'../../src/objects-printer.cc',
|
||||
|
Loading…
Reference in New Issue
Block a user