Commit 4f945599 authored by Dominik Inführ's avatar Dominik Inführ Committed by Commit Bot

Add Visitor for EphemeronHashTable

JSWeakCollection does not have any weak references anymore. Special
handling of Ephemerons can now be implemented in
VisitEphemeronHashTable.

Bug: chromium:844008
Change-Id: I9f4d8ad6a32cc7a55b715803f6a83ff8d2743ce8
Reviewed-on: https://chromium-review.googlesource.com/1090274
Commit-Queue: Dominik Inführ <dinfuehr@google.com>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53584}
parent 3896cdc2
......@@ -357,6 +357,11 @@ class ConcurrentMarkingVisitor final
return 0;
}
int VisitEphemeronHashTable(Map* map, EphemeronHashTable* object) {
bailout_.Push(object);
return 0;
}
void MarkObject(HeapObject* object) {
#ifdef THREAD_SANITIZER
// Perform a dummy acquire load to tell TSAN that there is no data race
......
......@@ -96,24 +96,20 @@ int MarkingVisitor<fixed_array_mode, retaining_path_mode, MarkingState>::
heap_->set_encountered_weak_collections(weak_collection);
}
// Skip visiting the backing hash table containing the mappings and the
// pointer to the other enqueued weak collections, both are post-processed.
int size = JSWeakCollection::BodyDescriptorWeak::SizeOf(map, weak_collection);
JSWeakCollection::BodyDescriptorWeak::IterateBody(map, weak_collection, size,
this);
// Partially initialized weak collection is enqueued, but table is ignored.
if (!weak_collection->table()->IsEphemeronHashTable()) return size;
// Mark the backing hash table without pushing it on the marking stack.
Object** slot =
HeapObject::RawField(weak_collection, JSWeakCollection::kTableOffset);
HeapObject* obj = HeapObject::cast(*slot);
collector_->RecordSlot(weak_collection, slot, obj);
MarkObjectWithoutPush(weak_collection, obj);
int size = JSWeakCollection::BodyDescriptor::SizeOf(map, weak_collection);
JSWeakCollection::BodyDescriptor::IterateBody(map, weak_collection, size,
this);
return size;
}
template <FixedArrayVisitationMode fixed_array_mode,
TraceRetainingPathMode retaining_path_mode, typename MarkingState>
int MarkingVisitor<fixed_array_mode, retaining_path_mode, MarkingState>::
VisitEphemeronHashTable(Map* map, EphemeronHashTable* table) {
// TODO(dinfuehr): Account size of the backing store.
return 0;
}
template <FixedArrayVisitationMode fixed_array_mode,
TraceRetainingPathMode retaining_path_mode, typename MarkingState>
int MarkingVisitor<fixed_array_mode, retaining_path_mode,
......
......@@ -822,6 +822,7 @@ class MarkingVisitor final
V8_INLINE int VisitAllocationSite(Map* map, AllocationSite* object);
V8_INLINE int VisitBytecodeArray(Map* map, BytecodeArray* object);
V8_INLINE int VisitCodeDataContainer(Map* map, CodeDataContainer* object);
V8_INLINE int VisitEphemeronHashTable(Map* map, EphemeronHashTable* object);
V8_INLINE int VisitFixedArray(Map* map, FixedArray* object);
V8_INLINE int VisitJSApiObject(Map* map, JSObject* object);
V8_INLINE int VisitJSFunction(Map* map, JSFunction* object);
......
......@@ -9,6 +9,7 @@
#include "src/layout-descriptor.h"
#include "src/objects-body-descriptors.h"
#include "src/objects.h"
#include "src/objects/hash-table.h"
#include "src/objects/ordered-hash-table.h"
#include "src/objects/string.h"
#include "src/visitors.h"
......@@ -33,6 +34,7 @@ class JSWeakCollection;
V(CodeDataContainer) \
V(ConsString) \
V(DataHandler) \
V(EphemeronHashTable) \
V(FeedbackCell) \
V(FeedbackVector) \
V(FixedArray) \
......
......@@ -364,7 +364,6 @@ class PrototypeInfo::BodyDescriptor final : public BodyDescriptorBase {
}
};
template <JSWeakCollection::BodyVisitingPolicy body_visiting_policy>
class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
public:
STATIC_ASSERT(kTableOffset + kPointerSize == kNextOffset);
......@@ -377,12 +376,7 @@ class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
template <typename ObjectVisitor>
static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
ObjectVisitor* v) {
if (body_visiting_policy == kIgnoreWeakness) {
IterateBodyImpl(map, obj, kPropertiesOrHashOffset, object_size, v);
} else {
IteratePointers(obj, kPropertiesOrHashOffset, kTableOffset, v);
IterateBodyImpl(map, obj, kSize, object_size, v);
}
IterateBodyImpl(map, obj, kPropertiesOrHashOffset, object_size, v);
}
static inline int SizeOf(Map* map, HeapObject* object) {
......
......@@ -2979,7 +2979,6 @@ VisitorId Map::GetVisitorId(Map* map) {
case FIXED_ARRAY_TYPE:
case BOILERPLATE_DESCRIPTION_TYPE:
case HASH_TABLE_TYPE:
case EPHEMERON_HASH_TABLE_TYPE:
case SCOPE_INFO_TYPE:
case BLOCK_CONTEXT_TYPE:
case CATCH_CONTEXT_TYPE:
......@@ -2992,6 +2991,9 @@ VisitorId Map::GetVisitorId(Map* map) {
case WITH_CONTEXT_TYPE:
return kVisitFixedArray;
case EPHEMERON_HASH_TABLE_TYPE:
return kVisitEphemeronHashTable;
case WEAK_FIXED_ARRAY_TYPE:
case WEAK_ARRAY_LIST_TYPE:
case DESCRIPTOR_ARRAY_TYPE:
......
......@@ -110,19 +110,14 @@ class JSWeakCollection : public JSObject {
static const int kNextOffset = kTableOffset + kPointerSize;
static const int kSize = kNextOffset + kPointerSize;
// Visiting policy defines whether the table and next collection fields
// should be visited or not.
enum BodyVisitingPolicy { kIgnoreWeakness, kRespectWeakness };
// Iterates the function object according to the visiting policy.
template <BodyVisitingPolicy>
class BodyDescriptorImpl;
// Visit the whole object.
typedef BodyDescriptorImpl<kIgnoreWeakness> BodyDescriptor;
typedef BodyDescriptorImpl BodyDescriptor;
// Don't visit table and next collection fields.
typedef BodyDescriptorImpl<kRespectWeakness> BodyDescriptorWeak;
// No weak fields.
typedef BodyDescriptor BodyDescriptorWeak;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakCollection);
......
......@@ -27,6 +27,7 @@ namespace internal {
V(ConsString) \
V(DataHandler) \
V(DataObject) \
V(EphemeronHashTable) \
V(FeedbackCell) \
V(FeedbackVector) \
V(FixedArray) \
......
......@@ -841,7 +841,8 @@ class IndexedReferencesExtractor : public ObjectVisitor {
bool V8HeapExplorer::ExtractReferencesPass1(int entry, HeapObject* obj) {
if (obj->IsFixedArray()) return false; // FixedArrays are processed on pass 2
if (obj->IsFixedArray() || obj->IsEphemeronHashTable())
return false; // FixedArrays & EphemeronHashTables are processed on pass 2
if (obj->IsJSGlobalProxy()) {
ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj));
......@@ -900,10 +901,12 @@ bool V8HeapExplorer::ExtractReferencesPass1(int entry, HeapObject* obj) {
bool V8HeapExplorer::ExtractReferencesPass2(int entry, HeapObject* obj) {
if (!obj->IsFixedArray()) return false;
if (!obj->IsFixedArray() && !obj->IsEphemeronHashTable()) return false;
if (obj->IsContext()) {
ExtractContextReferences(entry, Context::cast(obj));
} else if (obj->IsEphemeronHashTable()) {
ExtractEphemeronHashTableReferences(entry, EphemeronHashTable::cast(obj));
} else {
ExtractFixedArrayReferences(entry, FixedArray::cast(obj));
}
......@@ -1037,14 +1040,34 @@ void V8HeapExplorer::ExtractJSCollectionReferences(int entry,
void V8HeapExplorer::ExtractJSWeakCollectionReferences(int entry,
JSWeakCollection* obj) {
if (obj->table()->IsEphemeronHashTable()) {
EphemeronHashTable* table = EphemeronHashTable::cast(obj->table());
TagFixedArraySubType(table, JS_WEAK_COLLECTION_SUB_TYPE);
}
SetInternalReference(obj, entry, "table", obj->table(),
JSWeakCollection::kTableOffset);
}
void V8HeapExplorer::ExtractEphemeronHashTableReferences(
int entry, EphemeronHashTable* table) {
for (int i = 0, capacity = table->Capacity(); i < capacity; ++i) {
int key_index = EphemeronHashTable::EntryToIndex(i) +
EphemeronHashTable::kEntryKeyIndex;
int value_index = EphemeronHashTable::EntryToValueIndex(i);
Object* key = table->get(key_index);
Object* value = table->get(value_index);
SetWeakReference(table, entry, key_index, key,
table->OffsetOfElementAt(key_index));
SetInternalReference(table, entry, value_index, value,
table->OffsetOfElementAt(value_index));
HeapEntry* key_entry = GetEntry(key);
int key_entry_index = key_entry->index();
HeapEntry* value_entry = GetEntry(value);
if (key_entry && value_entry) {
const char* edge_name =
names_->GetFormatted("key %s in WeakMap", key_entry->name());
filler_->SetNamedAutoIndexReference(
HeapGraphEdge::kInternal, key_entry_index, edge_name, value_entry);
}
}
}
void V8HeapExplorer::ExtractContextReferences(int entry, Context* context) {
if (!context->IsNativeContext() && context->is_declaration_context()) {
ScopeInfo* scope_info = context->scope_info();
......@@ -1350,50 +1373,10 @@ void V8HeapExplorer::ExtractJSPromiseReferences(int entry, JSPromise* promise) {
}
void V8HeapExplorer::ExtractFixedArrayReferences(int entry, FixedArray* array) {
auto it = array_types_.find(array);
if (it == array_types_.end()) {
for (int i = 0, l = array->length(); i < l; ++i) {
DCHECK(!HasWeakHeapObjectTag(array->get(i)));
SetInternalReference(array, entry, i, array->get(i),
array->OffsetOfElementAt(i));
}
return;
}
switch (it->second) {
case JS_WEAK_COLLECTION_SUB_TYPE: {
EphemeronHashTable* table = EphemeronHashTable::cast(array);
for (int i = 0, capacity = table->Capacity(); i < capacity; ++i) {
int key_index = EphemeronHashTable::EntryToIndex(i) +
EphemeronHashTable::kEntryKeyIndex;
int value_index = EphemeronHashTable::EntryToValueIndex(i);
Object* key = table->get(key_index);
Object* value = table->get(value_index);
SetWeakReference(table, entry, key_index, key,
table->OffsetOfElementAt(key_index));
SetInternalReference(table, entry, value_index, value,
table->OffsetOfElementAt(value_index));
HeapEntry* key_entry = GetEntry(key);
int key_entry_index = key_entry->index();
HeapEntry* value_entry = GetEntry(value);
if (key_entry && value_entry) {
const char* edge_name =
names_->GetFormatted("key %s in WeakMap", key_entry->name());
filler_->SetNamedAutoIndexReference(HeapGraphEdge::kInternal,
key_entry_index, edge_name,
value_entry);
}
}
break;
}
// TODO(alph): Add special processing for other types of FixedArrays.
default:
for (int i = 0, l = array->length(); i < l; ++i) {
SetInternalReference(array, entry, i, array->get(i),
array->OffsetOfElementAt(i));
}
break;
for (int i = 0, l = array->length(); i < l; ++i) {
DCHECK(!HasWeakHeapObjectTag(array->get(i)));
SetInternalReference(array, entry, i, array->get(i),
array->OffsetOfElementAt(i));
}
}
......
......@@ -13,6 +13,7 @@
#include "src/base/platform/time.h"
#include "src/objects.h"
#include "src/objects/fixed-array.h"
#include "src/objects/hash-table.h"
#include "src/profiler/strings-storage.h"
#include "src/string-hasher.h"
#include "src/visitors.h"
......@@ -378,6 +379,8 @@ class V8HeapExplorer : public HeapEntriesAllocator {
void ExtractJSCollectionReferences(int entry, JSCollection* collection);
void ExtractJSWeakCollectionReferences(int entry,
JSWeakCollection* collection);
void ExtractEphemeronHashTableReferences(int entry,
EphemeronHashTable* table);
void ExtractContextReferences(int entry, Context* context);
void ExtractMapReferences(int entry, Map* map);
void ExtractSharedFunctionInfoReferences(int entry,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment