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:
ishell 2015-11-13 04:32:08 -08:00 committed by Commit bot
parent 55c07a8b2f
commit 138eb324ea
14 changed files with 830 additions and 580 deletions

View File

@ -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",

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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);
}

View File

@ -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);

View 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_

View 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_

View File

@ -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()));

View File

@ -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);
}

View File

@ -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:

View File

@ -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);
}

View File

@ -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',