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.cc",
|
||||||
"src/modules.h",
|
"src/modules.h",
|
||||||
"src/msan.h",
|
"src/msan.h",
|
||||||
|
"src/objects-body-descriptors-inl.h",
|
||||||
|
"src/objects-body-descriptors.h",
|
||||||
"src/objects-debug.cc",
|
"src/objects-debug.cc",
|
||||||
"src/objects-inl.h",
|
"src/objects-inl.h",
|
||||||
"src/objects-printer.cc",
|
"src/objects-printer.cc",
|
||||||
|
@ -1813,7 +1813,7 @@ void MarkCompactCollector::ProcessTopOptimizedFrame(ObjectVisitor* visitor) {
|
|||||||
if (it.frame()->type() == StackFrame::OPTIMIZED) {
|
if (it.frame()->type() == StackFrame::OPTIMIZED) {
|
||||||
Code* code = it.frame()->LookupCode();
|
Code* code = it.frame()->LookupCode();
|
||||||
if (!code->CanDeoptAt(it.frame()->pc())) {
|
if (!code->CanDeoptAt(it.frame()->pc())) {
|
||||||
code->CodeIterateBody(visitor);
|
Code::BodyDescriptor::IterateBody(code, visitor);
|
||||||
}
|
}
|
||||||
ProcessMarkingDeque();
|
ProcessMarkingDeque();
|
||||||
return;
|
return;
|
||||||
@ -2723,8 +2723,7 @@ void MarkCompactCollector::MigrateObjectMixed(
|
|||||||
heap()->MoveBlock(dst->address(), src->address(), size);
|
heap()->MoveBlock(dst->address(), src->address(), size);
|
||||||
|
|
||||||
// Visit inherited JSObject properties and byte length of ArrayBuffer
|
// Visit inherited JSObject properties and byte length of ArrayBuffer
|
||||||
Address regular_slot =
|
Address regular_slot = dst->address() + JSArrayBuffer::kPropertiesOffset;
|
||||||
dst->address() + JSArrayBuffer::BodyDescriptor::kStartOffset;
|
|
||||||
Address regular_slots_end =
|
Address regular_slots_end =
|
||||||
dst->address() + JSArrayBuffer::kByteLengthOffset + kPointerSize;
|
dst->address() + JSArrayBuffer::kByteLengthOffset + kPointerSize;
|
||||||
while (regular_slot < regular_slots_end) {
|
while (regular_slot < regular_slots_end) {
|
||||||
@ -2793,7 +2792,7 @@ static inline void UpdateSlot(Isolate* isolate, ObjectVisitor* v,
|
|||||||
}
|
}
|
||||||
case SlotsBuffer::RELOCATED_CODE_OBJECT: {
|
case SlotsBuffer::RELOCATED_CODE_OBJECT: {
|
||||||
HeapObject* obj = HeapObject::FromAddress(addr);
|
HeapObject* obj = HeapObject::FromAddress(addr);
|
||||||
Code::cast(obj)->CodeIterateBody(v);
|
Code::BodyDescriptor::IterateBody(obj, v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SlotsBuffer::DEBUG_TARGET_SLOT: {
|
case SlotsBuffer::DEBUG_TARGET_SLOT: {
|
||||||
@ -3140,7 +3139,7 @@ bool MarkCompactCollector::IsSlotInLiveObject(Address slot) {
|
|||||||
BytecodeArray::kConstantPoolOffset;
|
BytecodeArray::kConstantPoolOffset;
|
||||||
} else if (object->IsJSArrayBuffer()) {
|
} else if (object->IsJSArrayBuffer()) {
|
||||||
int off = static_cast<int>(slot - object->address());
|
int off = static_cast<int>(slot - object->address());
|
||||||
return (off >= JSArrayBuffer::BodyDescriptor::kStartOffset &&
|
return (off >= JSArrayBuffer::kPropertiesOffset &&
|
||||||
off <= JSArrayBuffer::kByteLengthOffset) ||
|
off <= JSArrayBuffer::kByteLengthOffset) ||
|
||||||
(off >= JSArrayBuffer::kSize &&
|
(off >= JSArrayBuffer::kSize &&
|
||||||
off < JSArrayBuffer::kSizeWithInternalFields);
|
off < JSArrayBuffer::kSizeWithInternalFields);
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "src/heap/objects-visiting.h"
|
#include "src/heap/objects-visiting.h"
|
||||||
#include "src/ic/ic-state.h"
|
#include "src/ic/ic-state.h"
|
||||||
#include "src/macro-assembler.h"
|
#include "src/macro-assembler.h"
|
||||||
|
#include "src/objects-body-descriptors-inl.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -94,14 +95,14 @@ void StaticNewSpaceVisitor<StaticVisitor>::Initialize() {
|
|||||||
template <typename StaticVisitor>
|
template <typename StaticVisitor>
|
||||||
int StaticNewSpaceVisitor<StaticVisitor>::VisitJSArrayBuffer(
|
int StaticNewSpaceVisitor<StaticVisitor>::VisitJSArrayBuffer(
|
||||||
Map* map, HeapObject* object) {
|
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()) {
|
if (!JSArrayBuffer::cast(object)->is_external()) {
|
||||||
|
Heap* heap = map->GetHeap();
|
||||||
heap->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(object));
|
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>
|
template <typename StaticVisitor>
|
||||||
void StaticMarkingVisitor<StaticVisitor>::VisitCode(Map* map,
|
void StaticMarkingVisitor<StaticVisitor>::VisitCode(Map* map,
|
||||||
HeapObject* object) {
|
HeapObject* object) {
|
||||||
|
typedef FlexibleBodyVisitor<StaticVisitor, Code::BodyDescriptor, void>
|
||||||
|
CodeBodyVisitor;
|
||||||
Heap* heap = map->GetHeap();
|
Heap* heap = map->GetHeap();
|
||||||
Code* code = Code::cast(object);
|
Code* code = Code::cast(object);
|
||||||
if (FLAG_age_code && !heap->isolate()->serializer_enabled()) {
|
if (FLAG_age_code && !heap->isolate()->serializer_enabled()) {
|
||||||
@ -439,7 +442,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitCode(Map* map,
|
|||||||
MarkInlinedFunctionsCode(heap, code);
|
MarkInlinedFunctionsCode(heap, code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
code->CodeIterateBody<StaticVisitor>(heap);
|
CodeBodyVisitor::Visit(map, object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -525,12 +528,9 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSFunction(Map* map,
|
|||||||
template <typename StaticVisitor>
|
template <typename StaticVisitor>
|
||||||
void StaticMarkingVisitor<StaticVisitor>::VisitJSRegExp(Map* map,
|
void StaticMarkingVisitor<StaticVisitor>::VisitJSRegExp(Map* map,
|
||||||
HeapObject* object) {
|
HeapObject* object) {
|
||||||
int last_property_offset =
|
typedef FlexibleBodyVisitor<StaticVisitor, JSRegExp::BodyDescriptor, void>
|
||||||
JSRegExp::kSize + kPointerSize * map->GetInObjectProperties();
|
JSRegExpBodyVisitor;
|
||||||
StaticVisitor::VisitPointers(
|
JSRegExpBodyVisitor::Visit(map, object);
|
||||||
map->GetHeap(), object,
|
|
||||||
HeapObject::RawField(object, JSRegExp::kPropertiesOffset),
|
|
||||||
HeapObject::RawField(object, last_property_offset));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -539,7 +539,11 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSArrayBuffer(
|
|||||||
Map* map, HeapObject* object) {
|
Map* map, HeapObject* object) {
|
||||||
Heap* heap = map->GetHeap();
|
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() &&
|
if (!JSArrayBuffer::cast(object)->is_external() &&
|
||||||
!heap->InNewSpace(object)) {
|
!heap->InNewSpace(object)) {
|
||||||
heap->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(object));
|
heap->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(object));
|
||||||
@ -550,20 +554,18 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSArrayBuffer(
|
|||||||
template <typename StaticVisitor>
|
template <typename StaticVisitor>
|
||||||
void StaticMarkingVisitor<StaticVisitor>::VisitJSTypedArray(
|
void StaticMarkingVisitor<StaticVisitor>::VisitJSTypedArray(
|
||||||
Map* map, HeapObject* object) {
|
Map* map, HeapObject* object) {
|
||||||
StaticVisitor::VisitPointers(
|
typedef FlexibleBodyVisitor<StaticVisitor, JSTypedArray::BodyDescriptor, void>
|
||||||
map->GetHeap(), object,
|
JSTypedArrayBodyVisitor;
|
||||||
HeapObject::RawField(object, JSTypedArray::BodyDescriptor::kStartOffset),
|
JSTypedArrayBodyVisitor::Visit(map, object);
|
||||||
HeapObject::RawField(object, JSTypedArray::kSizeWithInternalFields));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename StaticVisitor>
|
template <typename StaticVisitor>
|
||||||
void StaticMarkingVisitor<StaticVisitor>::VisitJSDataView(Map* map,
|
void StaticMarkingVisitor<StaticVisitor>::VisitJSDataView(Map* map,
|
||||||
HeapObject* object) {
|
HeapObject* object) {
|
||||||
StaticVisitor::VisitPointers(
|
typedef FlexibleBodyVisitor<StaticVisitor, JSDataView::BodyDescriptor, void>
|
||||||
map->GetHeap(), object,
|
JSDataViewBodyVisitor;
|
||||||
HeapObject::RawField(object, JSDataView::BodyDescriptor::kStartOffset),
|
JSDataViewBodyVisitor::Visit(map, object);
|
||||||
HeapObject::RawField(object, JSDataView::kSizeWithInternalFields));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -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 internal
|
||||||
} // namespace v8
|
} // 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
|
// 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
|
// 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
|
// 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/heap.h"
|
||||||
#include "src/heap/spaces.h"
|
#include "src/heap/spaces.h"
|
||||||
#include "src/layout-descriptor.h"
|
#include "src/layout-descriptor.h"
|
||||||
|
#include "src/objects-body-descriptors.h"
|
||||||
|
|
||||||
// This file provides base classes and auxiliary methods for defining
|
// This file provides base classes and auxiliary methods for defining
|
||||||
// static object visitors used during GC.
|
// static object visitors used during GC.
|
||||||
|
@ -266,7 +266,8 @@ class ScavengingVisitor : public StaticVisitorBase {
|
|||||||
|
|
||||||
static inline void EvacuateFixedArray(Map* map, HeapObject** slot,
|
static inline void EvacuateFixedArray(Map* map, HeapObject** slot,
|
||||||
HeapObject* object) {
|
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,
|
EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object,
|
||||||
object_size);
|
object_size);
|
||||||
}
|
}
|
||||||
|
@ -502,8 +502,7 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) {
|
|||||||
slot_callback);
|
slot_callback);
|
||||||
} else if (heap_object->IsJSArrayBuffer()) {
|
} else if (heap_object->IsJSArrayBuffer()) {
|
||||||
FindPointersToNewSpaceInRegion(
|
FindPointersToNewSpaceInRegion(
|
||||||
obj_address +
|
obj_address + JSArrayBuffer::kPropertiesOffset,
|
||||||
JSArrayBuffer::BodyDescriptor::kStartOffset,
|
|
||||||
obj_address + JSArrayBuffer::kByteLengthOffset +
|
obj_address + JSArrayBuffer::kByteLengthOffset +
|
||||||
kPointerSize,
|
kPointerSize,
|
||||||
slot_callback);
|
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 {
|
double HeapNumber::value() const {
|
||||||
return READ_DOUBLE_FIELD(this, kValueOffset);
|
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) {
|
byte BytecodeArray::get(int index) {
|
||||||
DCHECK(index >= 0 && index < this->length());
|
DCHECK(index >= 0 && index < this->length());
|
||||||
return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
|
return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
|
||||||
@ -4538,7 +4517,8 @@ int HeapObject::SizeFromMap(Map* map) {
|
|||||||
// Only inline the most frequent cases.
|
// Only inline the most frequent cases.
|
||||||
InstanceType instance_type = map->instance_type();
|
InstanceType instance_type = map->instance_type();
|
||||||
if (instance_type == FIXED_ARRAY_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 ||
|
if (instance_type == ONE_BYTE_STRING_TYPE ||
|
||||||
instance_type == ONE_BYTE_INTERNALIZED_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 {
|
Object* JSArrayBufferView::byte_offset() const {
|
||||||
if (WasNeutered()) return Smi::FromInt(0);
|
if (WasNeutered()) return Smi::FromInt(0);
|
||||||
return Object::cast(READ_FIELD(this, kByteOffsetOffset));
|
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>
|
template<class Derived, class TableType>
|
||||||
Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() {
|
Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() {
|
||||||
TableType* table(TableType::cast(this->table()));
|
TableType* table(TableType::cast(this->table()));
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "src/macro-assembler.h"
|
#include "src/macro-assembler.h"
|
||||||
#include "src/messages.h"
|
#include "src/messages.h"
|
||||||
#include "src/objects-inl.h"
|
#include "src/objects-inl.h"
|
||||||
|
#include "src/objects-body-descriptors-inl.h"
|
||||||
#include "src/profiler/cpu-profiler.h"
|
#include "src/profiler/cpu-profiler.h"
|
||||||
#include "src/property-descriptor.h"
|
#include "src/property-descriptor.h"
|
||||||
#include "src/prototype.h"
|
#include "src/prototype.h"
|
||||||
@ -1999,12 +2000,33 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HeapObject::Iterate(ObjectVisitor* v) {
|
void HeapObject::Iterate(ObjectVisitor* v) { IterateFast<ObjectVisitor>(v); }
|
||||||
// Handle header
|
|
||||||
IteratePointer(v, kMapOffset);
|
|
||||||
// Handle object body
|
void HeapObject::IterateBody(ObjectVisitor* v) {
|
||||||
Map* m = map();
|
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>
|
template<typename Derived, typename Shape, typename Key>
|
||||||
void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
|
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>
|
template<typename Derived, typename Shape, typename Key>
|
||||||
void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
|
void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
|
||||||
IteratePointers(v,
|
BodyDescriptorBase::IteratePointers(this, kElementsStartOffset,
|
||||||
kElementsStartOffset,
|
kHeaderSize + length() * kPointerSize, v);
|
||||||
kHeaderSize + length() * kPointerSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
158
src/objects.h
158
src/objects.h
@ -1555,15 +1555,35 @@ class HeapObject: public Object {
|
|||||||
return reinterpret_cast<Address>(this) - kHeapObjectTag;
|
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);
|
void Iterate(ObjectVisitor* v);
|
||||||
|
|
||||||
|
template <typename ObjectVisitor>
|
||||||
|
inline void IterateFast(ObjectVisitor* v);
|
||||||
|
|
||||||
// Iterates over all pointers contained in the object except the
|
// Iterates over all pointers contained in the object except the
|
||||||
// first map pointer. The object type is given in the first
|
// first map pointer. The object type is given in the first
|
||||||
// parameter. This function does not access the map pointer in the
|
// parameter. This function does not access the map pointer in the
|
||||||
// object, and so is safe to call while the map pointer is modified.
|
// 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);
|
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
|
// Returns the heap object's size in bytes
|
||||||
inline int Size();
|
inline int Size();
|
||||||
|
|
||||||
@ -1623,90 +1643,17 @@ class HeapObject: public Object {
|
|||||||
|
|
||||||
STATIC_ASSERT(kMapOffset == Internals::kHeapObjectMapOffset);
|
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:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
|
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>
|
template <int start_offset, int end_offset, int size>
|
||||||
class FixedBodyDescriptor : public BodyDescriptorBase {
|
class FixedBodyDescriptor;
|
||||||
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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// 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>
|
template <int start_offset>
|
||||||
class FlexibleBodyDescriptorBase : public BodyDescriptorBase {
|
class FlexibleBodyDescriptor;
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// The HeapNumber class describes heap allocated numbers that cannot be
|
// 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.
|
// object, the prefix of this array is sorted.
|
||||||
void SortPairs(FixedArray* numbers, uint32_t len);
|
void SortPairs(FixedArray* numbers, uint32_t len);
|
||||||
|
|
||||||
class BodyDescriptor : public FlexibleBodyDescriptorBase<kHeaderSize> {
|
typedef FlexibleBodyDescriptor<kHeaderSize> BodyDescriptor;
|
||||||
public:
|
|
||||||
static inline int SizeOf(Map* map, HeapObject* object);
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Set operation on FixedArray without using write barriers. Can
|
// Set operation on FixedArray without using write barriers. Can
|
||||||
@ -4423,7 +4367,6 @@ class BytecodeArray : public FixedArrayBase {
|
|||||||
|
|
||||||
// Dispatched behavior.
|
// Dispatched behavior.
|
||||||
inline int BytecodeArraySize();
|
inline int BytecodeArraySize();
|
||||||
inline void BytecodeArrayIterateBody(ObjectVisitor* v);
|
|
||||||
|
|
||||||
DECLARE_PRINTER(BytecodeArray)
|
DECLARE_PRINTER(BytecodeArray)
|
||||||
DECLARE_VERIFIER(BytecodeArray)
|
DECLARE_VERIFIER(BytecodeArray)
|
||||||
@ -4443,6 +4386,8 @@ class BytecodeArray : public FixedArrayBase {
|
|||||||
// Maximal length of a single BytecodeArray.
|
// Maximal length of a single BytecodeArray.
|
||||||
static const int kMaxLength = kMaxSize - kHeaderSize;
|
static const int kMaxLength = kMaxSize - kHeaderSize;
|
||||||
|
|
||||||
|
class BodyDescriptor;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(BytecodeArray);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(BytecodeArray);
|
||||||
};
|
};
|
||||||
@ -4508,11 +4453,6 @@ class FixedTypedArrayBase: public FixedArrayBase {
|
|||||||
DECL_ACCESSORS(external_pointer, void)
|
DECL_ACCESSORS(external_pointer, void)
|
||||||
|
|
||||||
// Dispatched behavior.
|
// Dispatched behavior.
|
||||||
inline void FixedTypedArrayBaseIterateBody(ObjectVisitor* v);
|
|
||||||
|
|
||||||
template <typename StaticVisitor>
|
|
||||||
inline void FixedTypedArrayBaseIterateBody();
|
|
||||||
|
|
||||||
DECLARE_CAST(FixedTypedArrayBase)
|
DECLARE_CAST(FixedTypedArrayBase)
|
||||||
|
|
||||||
static const int kBasePointerOffset = FixedArrayBase::kHeaderSize;
|
static const int kBasePointerOffset = FixedArrayBase::kHeaderSize;
|
||||||
@ -4522,6 +4462,8 @@ class FixedTypedArrayBase: public FixedArrayBase {
|
|||||||
|
|
||||||
static const int kDataOffset = kHeaderSize;
|
static const int kDataOffset = kHeaderSize;
|
||||||
|
|
||||||
|
class BodyDescriptor;
|
||||||
|
|
||||||
inline int size();
|
inline int size();
|
||||||
|
|
||||||
static inline int TypedArraySize(InstanceType type, int length);
|
static inline int TypedArraySize(InstanceType type, int length);
|
||||||
@ -5192,10 +5134,6 @@ class Code: public HeapObject {
|
|||||||
|
|
||||||
// Dispatched behavior.
|
// Dispatched behavior.
|
||||||
inline int CodeSize();
|
inline int CodeSize();
|
||||||
inline void CodeIterateBody(ObjectVisitor* v);
|
|
||||||
|
|
||||||
template<typename StaticVisitor>
|
|
||||||
inline void CodeIterateBody(Heap* heap);
|
|
||||||
|
|
||||||
DECLARE_PRINTER(Code)
|
DECLARE_PRINTER(Code)
|
||||||
DECLARE_VERIFIER(Code)
|
DECLARE_VERIFIER(Code)
|
||||||
@ -5294,6 +5232,8 @@ class Code: public HeapObject {
|
|||||||
static const int kHeaderSize =
|
static const int kHeaderSize =
|
||||||
(kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask;
|
(kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask;
|
||||||
|
|
||||||
|
class BodyDescriptor;
|
||||||
|
|
||||||
// Byte offsets within kKindSpecificFlags1Offset.
|
// Byte offsets within kKindSpecificFlags1Offset.
|
||||||
static const int kFullCodeFlags = kKindSpecificFlags1Offset;
|
static const int kFullCodeFlags = kKindSpecificFlags1Offset;
|
||||||
class FullCodeFlagsHasDeoptimizationSupportField:
|
class FullCodeFlagsHasDeoptimizationSupportField:
|
||||||
@ -9204,11 +9144,7 @@ class ExternalOneByteString : public ExternalString {
|
|||||||
|
|
||||||
DECLARE_CAST(ExternalOneByteString)
|
DECLARE_CAST(ExternalOneByteString)
|
||||||
|
|
||||||
// Garbage collection support.
|
class BodyDescriptor;
|
||||||
inline void ExternalOneByteStringIterateBody(ObjectVisitor* v);
|
|
||||||
|
|
||||||
template <typename StaticVisitor>
|
|
||||||
inline void ExternalOneByteStringIterateBody();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalOneByteString);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalOneByteString);
|
||||||
@ -9243,11 +9179,7 @@ class ExternalTwoByteString: public ExternalString {
|
|||||||
|
|
||||||
DECLARE_CAST(ExternalTwoByteString)
|
DECLARE_CAST(ExternalTwoByteString)
|
||||||
|
|
||||||
// Garbage collection support.
|
class BodyDescriptor;
|
||||||
inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
|
|
||||||
|
|
||||||
template<typename StaticVisitor>
|
|
||||||
inline void ExternalTwoByteStringIterateBody();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString);
|
||||||
@ -9868,6 +9800,8 @@ class JSWeakCollection: public JSObject {
|
|||||||
static const int kNextOffset = kTableOffset + kPointerSize;
|
static const int kNextOffset = kTableOffset + kPointerSize;
|
||||||
static const int kSize = kNextOffset + kPointerSize;
|
static const int kSize = kNextOffset + kPointerSize;
|
||||||
|
|
||||||
|
class BodyDescriptor;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakCollection);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakCollection);
|
||||||
};
|
};
|
||||||
@ -9946,11 +9880,6 @@ class JSArrayBuffer: public JSObject {
|
|||||||
DECLARE_VERIFIER(JSArrayBuffer)
|
DECLARE_VERIFIER(JSArrayBuffer)
|
||||||
|
|
||||||
static const int kByteLengthOffset = JSObject::kHeaderSize;
|
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 kBackingStoreOffset = kByteLengthOffset + kPointerSize;
|
||||||
static const int kBitFieldSlot = kBackingStoreOffset + kPointerSize;
|
static const int kBitFieldSlot = kBackingStoreOffset + kPointerSize;
|
||||||
#if V8_TARGET_LITTLE_ENDIAN || !V8_HOST_ARCH_64_BIT
|
#if V8_TARGET_LITTLE_ENDIAN || !V8_HOST_ARCH_64_BIT
|
||||||
@ -9963,11 +9892,9 @@ class JSArrayBuffer: public JSObject {
|
|||||||
static const int kSizeWithInternalFields =
|
static const int kSizeWithInternalFields =
|
||||||
kSize + v8::ArrayBuffer::kInternalFieldCount * kPointerSize;
|
kSize + v8::ArrayBuffer::kInternalFieldCount * kPointerSize;
|
||||||
|
|
||||||
template <typename StaticVisitor>
|
// Iterates all fields in the object including internal ones except
|
||||||
static inline void JSArrayBufferIterateBody(Heap* heap, HeapObject* obj);
|
// kBackingStoreOffset and kBitFieldSlot.
|
||||||
|
class BodyDescriptor;
|
||||||
static inline void JSArrayBufferIterateBody(HeapObject* obj,
|
|
||||||
ObjectVisitor* v);
|
|
||||||
|
|
||||||
class IsExternal : public BitField<bool, 1, 1> {};
|
class IsExternal : public BitField<bool, 1, 1> {};
|
||||||
class IsNeuterable : public BitField<bool, 2, 1> {};
|
class IsNeuterable : public BitField<bool, 2, 1> {};
|
||||||
@ -10072,12 +9999,6 @@ class Foreign: public HeapObject {
|
|||||||
|
|
||||||
DECLARE_CAST(Foreign)
|
DECLARE_CAST(Foreign)
|
||||||
|
|
||||||
// Dispatched behavior.
|
|
||||||
inline void ForeignIterateBody(ObjectVisitor* v);
|
|
||||||
|
|
||||||
template<typename StaticVisitor>
|
|
||||||
inline void ForeignIterateBody();
|
|
||||||
|
|
||||||
// Dispatched behavior.
|
// Dispatched behavior.
|
||||||
DECLARE_PRINTER(Foreign)
|
DECLARE_PRINTER(Foreign)
|
||||||
DECLARE_VERIFIER(Foreign)
|
DECLARE_VERIFIER(Foreign)
|
||||||
@ -10089,6 +10010,8 @@ class Foreign: public HeapObject {
|
|||||||
|
|
||||||
STATIC_ASSERT(kForeignAddressOffset == Internals::kForeignAddressOffset);
|
STATIC_ASSERT(kForeignAddressOffset == Internals::kForeignAddressOffset);
|
||||||
|
|
||||||
|
class BodyDescriptor;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(Foreign);
|
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.
|
// BooleanBit is a helper class for setting and getting a bit in an integer.
|
||||||
class BooleanBit : public AllStatic {
|
class BooleanBit : public AllStatic {
|
||||||
public:
|
public:
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "src/code-stubs.h"
|
#include "src/code-stubs.h"
|
||||||
#include "src/conversions.h"
|
#include "src/conversions.h"
|
||||||
#include "src/debug/debug.h"
|
#include "src/debug/debug.h"
|
||||||
|
#include "src/objects-body-descriptors.h"
|
||||||
#include "src/profiler/allocation-tracker.h"
|
#include "src/profiler/allocation-tracker.h"
|
||||||
#include "src/profiler/heap-profiler.h"
|
#include "src/profiler/heap-profiler.h"
|
||||||
#include "src/profiler/heap-snapshot-generator-inl.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,
|
// Do not visit weak_next as it is not visited by the StaticVisitor,
|
||||||
// and we're not very interested in weak_next field here.
|
// and we're not very interested in weak_next field here.
|
||||||
STATIC_ASSERT(AllocationSite::kWeakNextOffset >=
|
STATIC_ASSERT(AllocationSite::kWeakNextOffset >=
|
||||||
AllocationSite::BodyDescriptor::kEndOffset);
|
AllocationSite::BodyDescriptor::kEndOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -867,6 +867,8 @@
|
|||||||
'../../src/modules.cc',
|
'../../src/modules.cc',
|
||||||
'../../src/modules.h',
|
'../../src/modules.h',
|
||||||
'../../src/msan.h',
|
'../../src/msan.h',
|
||||||
|
'../../src/objects-body-descriptors-inl.h',
|
||||||
|
'../../src/objects-body-descriptors.h',
|
||||||
'../../src/objects-debug.cc',
|
'../../src/objects-debug.cc',
|
||||||
'../../src/objects-inl.h',
|
'../../src/objects-inl.h',
|
||||||
'../../src/objects-printer.cc',
|
'../../src/objects-printer.cc',
|
||||||
|
Loading…
Reference in New Issue
Block a user