Make JSFunction::BodyDescriptor the only single place that knows how to iterate JSFunction's body.
The body descriptor supports different visiting policies: it could visit or skip the code entry and it could visit or skip next function field. BUG=v8:4531 LOG=Y Review URL: https://codereview.chromium.org/1422773007 Cr-Commit-Position: refs/heads/master@{#31915}
This commit is contained in:
parent
1e2770123b
commit
8e09ee1dba
@ -63,7 +63,11 @@ void StaticNewSpaceVisitor<StaticVisitor>::Initialize() {
|
||||
|
||||
table_.Register(kVisitSeqTwoByteString, &VisitSeqTwoByteString);
|
||||
|
||||
table_.Register(kVisitJSFunction, &VisitJSFunction);
|
||||
// Don't visit code entry. We are using this visitor only during scavenges.
|
||||
table_.Register(
|
||||
kVisitJSFunction,
|
||||
&FlexibleBodyVisitor<StaticVisitor, JSFunction::BodyDescriptorWeakCode,
|
||||
int>::Visit);
|
||||
|
||||
table_.Register(kVisitJSArrayBuffer, &VisitJSArrayBuffer);
|
||||
|
||||
@ -507,14 +511,14 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSFunction(Map* map,
|
||||
VisitSharedFunctionInfoWeakCode(heap, shared);
|
||||
}
|
||||
// Treat the reference to the code object weakly.
|
||||
VisitJSFunctionWeakCode(heap, object);
|
||||
VisitJSFunctionWeakCode(map, object);
|
||||
return;
|
||||
} else {
|
||||
// Visit all unoptimized code objects to prevent flushing them.
|
||||
StaticVisitor::MarkObject(heap, function->shared()->code());
|
||||
}
|
||||
}
|
||||
VisitJSFunctionStrongCode(heap, object);
|
||||
VisitJSFunctionStrongCode(map, object);
|
||||
}
|
||||
|
||||
|
||||
@ -801,42 +805,20 @@ void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfoWeakCode(
|
||||
|
||||
template <typename StaticVisitor>
|
||||
void StaticMarkingVisitor<StaticVisitor>::VisitJSFunctionStrongCode(
|
||||
Heap* heap, HeapObject* object) {
|
||||
Object** start_slot =
|
||||
HeapObject::RawField(object, JSFunction::kPropertiesOffset);
|
||||
Object** end_slot =
|
||||
HeapObject::RawField(object, JSFunction::kCodeEntryOffset);
|
||||
StaticVisitor::VisitPointers(heap, object, start_slot, end_slot);
|
||||
|
||||
VisitCodeEntry(heap, object,
|
||||
object->address() + JSFunction::kCodeEntryOffset);
|
||||
STATIC_ASSERT(JSFunction::kCodeEntryOffset + kPointerSize ==
|
||||
JSFunction::kPrototypeOrInitialMapOffset);
|
||||
|
||||
start_slot =
|
||||
HeapObject::RawField(object, JSFunction::kPrototypeOrInitialMapOffset);
|
||||
end_slot = HeapObject::RawField(object, JSFunction::kNonWeakFieldsEndOffset);
|
||||
StaticVisitor::VisitPointers(heap, object, start_slot, end_slot);
|
||||
Map* map, HeapObject* object) {
|
||||
typedef FlexibleBodyVisitor<StaticVisitor,
|
||||
JSFunction::BodyDescriptorStrongCode,
|
||||
void> JSFunctionStrongCodeBodyVisitor;
|
||||
JSFunctionStrongCodeBodyVisitor::Visit(map, object);
|
||||
}
|
||||
|
||||
|
||||
template <typename StaticVisitor>
|
||||
void StaticMarkingVisitor<StaticVisitor>::VisitJSFunctionWeakCode(
|
||||
Heap* heap, HeapObject* object) {
|
||||
Object** start_slot =
|
||||
HeapObject::RawField(object, JSFunction::kPropertiesOffset);
|
||||
Object** end_slot =
|
||||
HeapObject::RawField(object, JSFunction::kCodeEntryOffset);
|
||||
StaticVisitor::VisitPointers(heap, object, start_slot, end_slot);
|
||||
|
||||
// Skip visiting kCodeEntryOffset as it is treated weakly here.
|
||||
STATIC_ASSERT(JSFunction::kCodeEntryOffset + kPointerSize ==
|
||||
JSFunction::kPrototypeOrInitialMapOffset);
|
||||
|
||||
start_slot =
|
||||
HeapObject::RawField(object, JSFunction::kPrototypeOrInitialMapOffset);
|
||||
end_slot = HeapObject::RawField(object, JSFunction::kNonWeakFieldsEndOffset);
|
||||
StaticVisitor::VisitPointers(heap, object, start_slot, end_slot);
|
||||
Map* map, HeapObject* object) {
|
||||
typedef FlexibleBodyVisitor<StaticVisitor, JSFunction::BodyDescriptorWeakCode,
|
||||
void> JSFunctionWeakCodeBodyVisitor;
|
||||
JSFunctionWeakCodeBodyVisitor::Visit(map, object);
|
||||
}
|
||||
|
||||
|
||||
|
@ -238,8 +238,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
|
||||
JSArrayBuffer::JSArrayBufferIterateBody(this, v);
|
||||
break;
|
||||
case JS_FUNCTION_TYPE:
|
||||
reinterpret_cast<JSFunction*>(this)
|
||||
->JSFunctionIterateBody(object_size, v);
|
||||
JSFunction::BodyDescriptor::IterateBody(this, object_size, v);
|
||||
break;
|
||||
case ODDBALL_TYPE:
|
||||
Oddball::BodyDescriptor::IterateBody(this, v);
|
||||
|
@ -251,22 +251,15 @@ class StaticNewSpaceVisitor : public StaticVisitorBase {
|
||||
for (Object** p = start; p < end; p++) StaticVisitor::VisitPointer(heap, p);
|
||||
}
|
||||
|
||||
private:
|
||||
INLINE(static int VisitJSFunction(Map* map, HeapObject* object)) {
|
||||
Heap* heap = map->GetHeap();
|
||||
VisitPointers(heap, object,
|
||||
HeapObject::RawField(object, JSFunction::kPropertiesOffset),
|
||||
HeapObject::RawField(object, JSFunction::kCodeEntryOffset));
|
||||
|
||||
// Don't visit code entry. We are using this visitor only during scavenges.
|
||||
|
||||
VisitPointers(
|
||||
heap, object, HeapObject::RawField(
|
||||
object, JSFunction::kCodeEntryOffset + kPointerSize),
|
||||
HeapObject::RawField(object, JSFunction::kNonWeakFieldsEndOffset));
|
||||
return JSFunction::kSize;
|
||||
// Although we are using the JSFunction body descriptor which does not
|
||||
// visit the code entry, compiler wants it to be accessible.
|
||||
// See JSFunction::BodyDescriptorImpl.
|
||||
INLINE(static void VisitCodeEntry(Heap* heap, HeapObject* object,
|
||||
Address entry_address)) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
private:
|
||||
INLINE(static int VisitByteArray(Map* map, HeapObject* object)) {
|
||||
return reinterpret_cast<ByteArray*>(object)->ByteArraySize();
|
||||
}
|
||||
@ -405,8 +398,8 @@ class StaticMarkingVisitor : public StaticVisitorBase {
|
||||
// references to code objects either strongly or weakly.
|
||||
static void VisitSharedFunctionInfoStrongCode(Heap* heap, HeapObject* object);
|
||||
static void VisitSharedFunctionInfoWeakCode(Heap* heap, HeapObject* object);
|
||||
static void VisitJSFunctionStrongCode(Heap* heap, HeapObject* object);
|
||||
static void VisitJSFunctionWeakCode(Heap* heap, HeapObject* object);
|
||||
static void VisitJSFunctionStrongCode(Map* map, HeapObject* object);
|
||||
static void VisitJSFunctionWeakCode(Map* map, HeapObject* object);
|
||||
|
||||
class DataObjectVisitor {
|
||||
public:
|
||||
|
@ -7914,8 +7914,7 @@ void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
|
||||
void BodyDescriptorBase::IterateBodyImpl(HeapObject* obj, int start_offset,
|
||||
int end_offset, ObjectVisitor* v) {
|
||||
if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
|
||||
v->VisitPointers(HeapObject::RawField(obj, start_offset),
|
||||
HeapObject::RawField(obj, end_offset));
|
||||
IteratePointers(obj, start_offset, end_offset, v);
|
||||
} else {
|
||||
DCHECK(FLAG_unbox_double_fields);
|
||||
DCHECK(IsAligned(start_offset, kPointerSize) &&
|
||||
@ -7926,8 +7925,7 @@ void BodyDescriptorBase::IterateBodyImpl(HeapObject* obj, int start_offset,
|
||||
for (int offset = start_offset; offset < end_offset;) {
|
||||
int end_of_region_offset;
|
||||
if (helper.IsTagged(offset, end_offset, &end_of_region_offset)) {
|
||||
v->VisitPointers(HeapObject::RawField(obj, offset),
|
||||
HeapObject::RawField(obj, end_of_region_offset));
|
||||
IteratePointers(obj, offset, end_of_region_offset, v);
|
||||
}
|
||||
offset = end_of_region_offset;
|
||||
}
|
||||
@ -7936,13 +7934,10 @@ void BodyDescriptorBase::IterateBodyImpl(HeapObject* obj, int start_offset,
|
||||
|
||||
|
||||
template <typename StaticVisitor>
|
||||
void BodyDescriptorBase::IterateBodyImpl(HeapObject* obj, int start_offset,
|
||||
int end_offset) {
|
||||
Heap* heap = obj->GetHeap();
|
||||
void BodyDescriptorBase::IterateBodyImpl(Heap* heap, HeapObject* obj,
|
||||
int start_offset, int end_offset) {
|
||||
if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
|
||||
StaticVisitor::VisitPointers(heap, obj,
|
||||
HeapObject::RawField(obj, start_offset),
|
||||
HeapObject::RawField(obj, end_offset));
|
||||
IteratePointers<StaticVisitor>(heap, obj, start_offset, end_offset);
|
||||
} else {
|
||||
DCHECK(FLAG_unbox_double_fields);
|
||||
DCHECK(IsAligned(start_offset, kPointerSize) &&
|
||||
@ -7953,9 +7948,7 @@ void BodyDescriptorBase::IterateBodyImpl(HeapObject* obj, int start_offset,
|
||||
for (int offset = start_offset; offset < end_offset;) {
|
||||
int end_of_region_offset;
|
||||
if (helper.IsTagged(offset, end_offset, &end_of_region_offset)) {
|
||||
StaticVisitor::VisitPointers(
|
||||
heap, obj, HeapObject::RawField(obj, offset),
|
||||
HeapObject::RawField(obj, end_of_region_offset));
|
||||
IteratePointers<StaticVisitor>(heap, obj, offset, end_of_region_offset);
|
||||
}
|
||||
offset = end_of_region_offset;
|
||||
}
|
||||
@ -7963,6 +7956,75 @@ void BodyDescriptorBase::IterateBodyImpl(HeapObject* obj, int start_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()));
|
||||
|
@ -10980,15 +10980,6 @@ bool Map::EquivalentToForNormalization(Map* other,
|
||||
}
|
||||
|
||||
|
||||
void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
|
||||
// Iterate over all fields in the body but take care in dealing with
|
||||
// the code entry.
|
||||
IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
|
||||
v->VisitCodeEntry(this->address() + kCodeEntryOffset);
|
||||
IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
|
||||
}
|
||||
|
||||
|
||||
bool JSFunction::Inlines(SharedFunctionInfo* candidate) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
if (shared() == candidate) return true;
|
||||
|
@ -1644,8 +1644,15 @@ class BodyDescriptorBase {
|
||||
int end_offset, ObjectVisitor* v);
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBodyImpl(HeapObject* obj, int start_offset,
|
||||
int end_offset);
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
@ -1665,7 +1672,8 @@ class FixedBodyDescriptor : public BodyDescriptorBase {
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj) {
|
||||
IterateBodyImpl<StaticVisitor>(obj, start_offset, end_offset);
|
||||
Heap* heap = obj->GetHeap();
|
||||
IterateBodyImpl<StaticVisitor>(heap, obj, start_offset, end_offset);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1685,7 +1693,8 @@ class FlexibleBodyDescriptorBase : public BodyDescriptorBase {
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
IterateBodyImpl<StaticVisitor>(obj, start_offset, object_size);
|
||||
Heap* heap = obj->GetHeap();
|
||||
IterateBodyImpl<StaticVisitor>(heap, obj, start_offset, object_size);
|
||||
}
|
||||
};
|
||||
|
||||
@ -7409,9 +7418,26 @@ class JSFunction: public JSObject {
|
||||
int* instance_size,
|
||||
int* in_object_properties);
|
||||
|
||||
// Iterates the objects, including code objects indirectly referenced
|
||||
// through pointers to the first instruction in the code object.
|
||||
void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
|
||||
// Visiting policy flags define whether the code entry or next function
|
||||
// should be visited or not.
|
||||
enum BodyVisitingPolicy {
|
||||
kVisitCodeEntry = 1 << 0,
|
||||
kVisitNextFunction = 1 << 1,
|
||||
|
||||
kSkipCodeEntryAndNextFunction = 0,
|
||||
kVisitCodeEntryAndNextFunction = kVisitCodeEntry | kVisitNextFunction
|
||||
};
|
||||
// Iterates the function object according to the visiting policy.
|
||||
template <BodyVisitingPolicy>
|
||||
class BodyDescriptorImpl;
|
||||
|
||||
// Visit the whole object.
|
||||
typedef BodyDescriptorImpl<kVisitCodeEntryAndNextFunction> BodyDescriptor;
|
||||
|
||||
// Don't visit next function.
|
||||
typedef BodyDescriptorImpl<kVisitCodeEntry> BodyDescriptorStrongCode;
|
||||
typedef BodyDescriptorImpl<kSkipCodeEntryAndNextFunction>
|
||||
BodyDescriptorWeakCode;
|
||||
|
||||
// Dispatched behavior.
|
||||
DECLARE_PRINTER(JSFunction)
|
||||
@ -7429,15 +7455,14 @@ class JSFunction: public JSObject {
|
||||
|
||||
// Layout descriptors. The last property (from kNonWeakFieldsEndOffset to
|
||||
// kSize) is weak and has special handling during garbage collection.
|
||||
static const int kCodeEntryOffset = JSObject::kHeaderSize;
|
||||
static const int kPrototypeOrInitialMapOffset =
|
||||
kCodeEntryOffset + kPointerSize;
|
||||
static const int kPrototypeOrInitialMapOffset = JSObject::kHeaderSize;
|
||||
static const int kSharedFunctionInfoOffset =
|
||||
kPrototypeOrInitialMapOffset + kPointerSize;
|
||||
static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
|
||||
static const int kLiteralsOffset = kContextOffset + kPointerSize;
|
||||
static const int kNonWeakFieldsEndOffset = kLiteralsOffset + kPointerSize;
|
||||
static const int kNextFunctionLinkOffset = kNonWeakFieldsEndOffset;
|
||||
static const int kCodeEntryOffset = kNonWeakFieldsEndOffset;
|
||||
static const int kNextFunctionLinkOffset = kCodeEntryOffset + kPointerSize;
|
||||
static const int kSize = kNextFunctionLinkOffset + kPointerSize;
|
||||
|
||||
private:
|
||||
|
@ -1158,8 +1158,11 @@ void V8HeapExplorer::ExtractJSObjectReferences(
|
||||
SetWeakReference(js_fun, entry,
|
||||
"next_function_link", js_fun->next_function_link(),
|
||||
JSFunction::kNextFunctionLinkOffset);
|
||||
STATIC_ASSERT(JSFunction::kNextFunctionLinkOffset
|
||||
== JSFunction::kNonWeakFieldsEndOffset);
|
||||
// Ensure no new weak references appeared in JSFunction.
|
||||
STATIC_ASSERT(JSFunction::kCodeEntryOffset ==
|
||||
JSFunction::kNonWeakFieldsEndOffset);
|
||||
STATIC_ASSERT(JSFunction::kCodeEntryOffset + kPointerSize ==
|
||||
JSFunction::kNextFunctionLinkOffset);
|
||||
STATIC_ASSERT(JSFunction::kNextFunctionLinkOffset + kPointerSize
|
||||
== JSFunction::kSize);
|
||||
} else if (obj->IsJSGlobalObject()) {
|
||||
|
Loading…
Reference in New Issue
Block a user