[base] Store AllocationPolicy object in TemplateHashMapImpl instance

... this will avoid the need to pass AllocationPolicy to every method
that can allocate/deallocate and allows to make deallocation method
implementation stateful.

The latter will also allow implementing accounting of deallocated zone
memory.

Adding one more field is generally fine because usually these hashmap
objects are allocated on the stack or inside other rarely-allocated
long-lived objects.
The only exception is Scope class. The Scope objects are created very
often during parsing and each of them has a VariableMap field.
The Scope object size issue will be addressed in a follow-up CL.

Bug: v8:10572
Change-Id: I63fbd41246cf2e568c8ba80c213d3e9caffc2c87
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2284992
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68877}
This commit is contained in:
Igor Sheludko 2020-07-14 19:24:24 +02:00 committed by Commit Bot
parent ebcc39d59a
commit 41a8d9c352
13 changed files with 62 additions and 81 deletions

View File

@ -335,10 +335,9 @@ void ObjectLiteral::CalculateEmitStore(Zone* zone) {
const auto GETTER = ObjectLiteral::Property::GETTER;
const auto SETTER = ObjectLiteral::Property::SETTER;
ZoneAllocationPolicy allocator(zone);
CustomMatcherZoneHashMap table(
Literal::Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
CustomMatcherZoneHashMap table(Literal::Match,
ZoneHashMap::kDefaultHashMapCapacity,
ZoneAllocationPolicy(zone));
for (int i = properties()->length() - 1; i >= 0; i--) {
ObjectLiteral::Property* property = properties()->at(i);
if (property->is_computed_name()) continue;
@ -347,7 +346,7 @@ void ObjectLiteral::CalculateEmitStore(Zone* zone) {
DCHECK(!literal->IsNullLiteral());
uint32_t hash = literal->Hash();
ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash, allocator);
ZoneHashMap::Entry* entry = table.LookupOrInsert(literal, hash);
if (entry->value == nullptr) {
entry->value = property;
} else {

View File

@ -46,9 +46,8 @@ Variable* VariableMap::Declare(Zone* zone, Scope* scope,
// AstRawStrings are unambiguous, i.e., the same string is always represented
// by the same AstRawString*.
// FIXME(marja): fix the type of Lookup.
Entry* p =
ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
ZoneAllocationPolicy(zone));
Entry* p = ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name),
name->Hash());
*was_added = p->value == nullptr;
if (*was_added) {
// The variable has not been declared yet -> insert it.
@ -66,11 +65,10 @@ void VariableMap::Remove(Variable* var) {
ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->Hash());
}
void VariableMap::Add(Zone* zone, Variable* var) {
void VariableMap::Add(Variable* var) {
const AstRawString* name = var->raw_name();
Entry* p =
ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
ZoneAllocationPolicy(zone));
Entry* p = ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name),
name->Hash());
DCHECK_NULL(p->value);
DCHECK_EQ(name, p->key);
p->value = var;
@ -682,7 +680,7 @@ Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name,
if (sloppy_eval_can_extend_vars()) {
cache->NonLocal(name, VariableMode::kDynamic);
} else {
cache->variables_.Add(zone(), function_);
cache->variables_.Add(function_);
}
return function_;
}

View File

@ -50,7 +50,7 @@ class VariableMap : public ZoneHashMap {
V8_EXPORT_PRIVATE Variable* Lookup(const AstRawString* name);
void Remove(Variable* var);
void Add(Zone* zone, Variable* var);
void Add(Variable* var);
};
class Scope;

View File

@ -54,18 +54,15 @@ class TemplateHashMapImpl {
// If an entry with matching key is found, returns that entry.
// If no matching entry is found, a new entry is inserted with
// corresponding key, key hash, and default initialized value.
Entry* LookupOrInsert(const Key& key, uint32_t hash,
AllocationPolicy allocator = AllocationPolicy());
Entry* LookupOrInsert(const Key& key, uint32_t hash);
// If an entry with matching key is found, returns that entry.
// If no matching entry is found, a new entry is inserted with
// corresponding key, key hash, and value created by func.
template <typename Func>
Entry* LookupOrInsert(const Key& key, uint32_t hash, const Func& value_func,
AllocationPolicy allocator = AllocationPolicy());
Entry* LookupOrInsert(const Key& key, uint32_t hash, const Func& value_func);
Entry* InsertNew(const Key& key, uint32_t hash,
AllocationPolicy allocator = AllocationPolicy());
Entry* InsertNew(const Key& key, uint32_t hash);
// Removes the entry with matching key.
// It returns the value of the deleted entry
@ -103,12 +100,12 @@ class TemplateHashMapImpl {
Entry* Next(Entry* entry) const;
void Reset(AllocationPolicy allocator) {
Initialize(capacity_, allocator);
Initialize(capacity_);
occupancy_ = 0;
}
protected:
void Initialize(uint32_t capacity, AllocationPolicy allocator);
void Initialize(uint32_t capacity);
private:
Entry* map_;
@ -117,13 +114,14 @@ class TemplateHashMapImpl {
// TODO(leszeks): This takes up space even if it has no state, maybe replace
// with something that does the empty base optimisation e.g. std::tuple
MatchFun match_;
// TODO(ishell): same here.
AllocationPolicy allocator_;
Entry* map_end() const { return map_ + capacity_; }
Entry* Probe(const Key& key, uint32_t hash) const;
Entry* FillEmptyEntry(Entry* entry, const Key& key, const Value& value,
uint32_t hash,
AllocationPolicy allocator = AllocationPolicy());
void Resize(AllocationPolicy allocator);
uint32_t hash);
void Resize();
DISALLOW_COPY_AND_ASSIGN(TemplateHashMapImpl);
};
@ -132,8 +130,8 @@ template <typename Key, typename Value, typename MatchFun,
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::
TemplateHashMapImpl(uint32_t initial_capacity, MatchFun match,
AllocationPolicy allocator)
: match_(match) {
Initialize(initial_capacity, allocator);
: match_(match), allocator_(allocator) {
Initialize(initial_capacity);
}
template <typename Key, typename Value, typename MatchFun,
@ -144,8 +142,9 @@ TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::
AllocationPolicy allocator)
: capacity_(original->capacity_),
occupancy_(original->occupancy_),
match_(original->match_) {
map_ = reinterpret_cast<Entry*>(allocator.New(capacity_ * sizeof(Entry)));
match_(original->match_),
allocator_(allocator) {
map_ = reinterpret_cast<Entry*>(allocator_.New(capacity_ * sizeof(Entry)));
memcpy(map_, original->map_, capacity_ * sizeof(Entry));
}
@ -169,8 +168,8 @@ template <typename Key, typename Value, typename MatchFun,
class AllocationPolicy>
typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry*
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::LookupOrInsert(
const Key& key, uint32_t hash, AllocationPolicy allocator) {
return LookupOrInsert(key, hash, []() { return Value(); }, allocator);
const Key& key, uint32_t hash) {
return LookupOrInsert(key, hash, []() { return Value(); });
}
template <typename Key, typename Value, typename MatchFun,
@ -178,24 +177,23 @@ template <typename Key, typename Value, typename MatchFun,
template <typename Func>
typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry*
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::LookupOrInsert(
const Key& key, uint32_t hash, const Func& value_func,
AllocationPolicy allocator) {
const Key& key, uint32_t hash, const Func& value_func) {
// Find a matching entry.
Entry* entry = Probe(key, hash);
if (entry->exists()) {
return entry;
}
return FillEmptyEntry(entry, key, value_func(), hash, allocator);
return FillEmptyEntry(entry, key, value_func(), hash);
}
template <typename Key, typename Value, typename MatchFun,
class AllocationPolicy>
typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry*
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::InsertNew(
const Key& key, uint32_t hash, AllocationPolicy allocator) {
const Key& key, uint32_t hash) {
Entry* entry = Probe(key, hash);
return FillEmptyEntry(entry, key, Value(), hash, allocator);
return FillEmptyEntry(entry, key, Value(), hash);
}
template <typename Key, typename Value, typename MatchFun,
@ -313,8 +311,7 @@ template <typename Key, typename Value, typename MatchFun,
class AllocationPolicy>
typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry*
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::FillEmptyEntry(
Entry* entry, const Key& key, const Value& value, uint32_t hash,
AllocationPolicy allocator) {
Entry* entry, const Key& key, const Value& value, uint32_t hash) {
DCHECK(!entry->exists());
new (entry) Entry(key, value, hash);
@ -322,7 +319,7 @@ TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::FillEmptyEntry(
// Grow the map if we reached >= 80% occupancy.
if (occupancy_ + occupancy_ / 4 >= capacity_) {
Resize(allocator);
Resize();
entry = Probe(key, hash);
}
@ -332,9 +329,9 @@ TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::FillEmptyEntry(
template <typename Key, typename Value, typename MatchFun,
class AllocationPolicy>
void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Initialize(
uint32_t capacity, AllocationPolicy allocator) {
uint32_t capacity) {
DCHECK(base::bits::IsPowerOfTwo(capacity));
map_ = reinterpret_cast<Entry*>(allocator.New(capacity * sizeof(Entry)));
map_ = reinterpret_cast<Entry*>(allocator_.New(capacity * sizeof(Entry)));
if (map_ == nullptr) {
FATAL("Out of memory: HashMap::Initialize");
return;
@ -345,20 +342,19 @@ void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Initialize(
template <typename Key, typename Value, typename MatchFun,
class AllocationPolicy>
void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Resize(
AllocationPolicy allocator) {
void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Resize() {
Entry* map = map_;
uint32_t n = occupancy_;
// Allocate larger map.
Initialize(capacity_ * 2, allocator);
Initialize(capacity_ * 2);
// Rehash all current entries.
for (Entry* entry = map; n > 0; entry++) {
if (entry->exists()) {
Entry* new_entry = Probe(entry->key, entry->hash);
new_entry = FillEmptyEntry(new_entry, entry->key, entry->value,
entry->hash, allocator);
new_entry =
FillEmptyEntry(new_entry, entry->key, entry->value, entry->hash);
n--;
}
}
@ -484,10 +480,9 @@ class TemplateHashMap
Iterator begin() const { return Iterator(this, this->Start()); }
Iterator end() const { return Iterator(this, nullptr); }
Iterator find(Key* key, bool insert = false,
AllocationPolicy allocator = AllocationPolicy()) {
Iterator find(Key* key, bool insert = false) {
if (insert) {
return Iterator(this, this->LookupOrInsert(key, key->Hash(), allocator));
return Iterator(this, this->LookupOrInsert(key, key->Hash()));
}
return Iterator(this, this->Lookup(key, key->Hash()));
}

View File

@ -24,8 +24,7 @@ BytecodeLiveness& BytecodeLivenessMap::InitializeLiveness(int offset,
Zone* zone) {
return liveness_map_
.LookupOrInsert(offset, OffsetHash(offset),
[&]() { return BytecodeLiveness(register_count, zone); },
ZoneAllocationPolicy(zone))
[&]() { return BytecodeLiveness(register_count, zone); })
->value;
}

View File

@ -2707,7 +2707,7 @@ void JSHeapBroker::InitializeAndStartSerializing(
// clang-format off
ObjectData* JSHeapBroker::GetOrCreateData(Handle<Object> object) {
RefsMap::Entry* entry = refs_->LookupOrInsert(object.address(), zone());
RefsMap::Entry* entry = refs_->LookupOrInsert(object.address());
ObjectData** data_storage = &(entry->value);
if (*data_storage == nullptr) {
// TODO(neis): Remove these Allow* once we serialize everything upfront.
@ -3987,8 +3987,7 @@ ObjectRef::ObjectRef(JSHeapBroker* broker, Handle<Object> object,
data_ = broker->GetOrCreateData(object);
break;
case JSHeapBroker::kDisabled: {
RefsMap::Entry* entry =
broker->refs_->LookupOrInsert(object.address(), broker->zone());
RefsMap::Entry* entry = broker->refs_->LookupOrInsert(object.address());
ObjectData** storage = &(entry->value);
if (*storage == nullptr) {
AllowHandleDereferenceIf allow_handle_dereference(

View File

@ -22,10 +22,9 @@ RefsMap::Entry* RefsMap::Lookup(const Address& key) const {
return UnderlyingMap::Lookup(key, Hash(key));
}
RefsMap::Entry* RefsMap::LookupOrInsert(const Address& key, Zone* zone) {
RefsMap::Entry* RefsMap::LookupOrInsert(const Address& key) {
return UnderlyingMap::LookupOrInsert(key, RefsMap::Hash(key),
[]() { return nullptr; },
ZoneAllocationPolicy(zone));
[]() { return nullptr; });
}
uint32_t RefsMap::Hash(Address addr) { return static_cast<uint32_t>(addr); }

View File

@ -41,7 +41,7 @@ class RefsMap
// Wrappers around methods from UnderlyingMap
Entry* Lookup(const Address& key) const;
Entry* LookupOrInsert(const Address& key, Zone* zone);
Entry* LookupOrInsert(const Address& key);
private:
static uint32_t Hash(Address addr);

View File

@ -119,8 +119,7 @@ Node* StateValuesCache::GetValuesNodeFromCache(Node** nodes, size_t count,
SparseInputMask mask) {
StateValuesKey key(count, mask, nodes);
int hash = StateValuesHashKey(nodes, count);
ZoneHashMap::Entry* lookup =
hash_map_.LookupOrInsert(&key, hash, ZoneAllocationPolicy(zone()));
ZoneHashMap::Entry* lookup = hash_map_.LookupOrInsert(&key, hash);
DCHECK_NOT_NULL(lookup);
Node* node;
if (lookup->value == nullptr) {

View File

@ -1005,7 +1005,7 @@ class AccessorTable
zone_(zone) {}
Accessors<PropertyT>* LookupOrInsert(Literal* key) {
auto it = this->find(key, true, ZoneAllocationPolicy(zone_));
auto it = this->find(key, true);
if (it->second == nullptr) {
it->second = zone_->New<Accessors<PropertyT>>();
ordered_accessors_.push_back({key, it->second});

View File

@ -134,11 +134,7 @@ ConstantArrayBuilder::ConstantArrayBuilder(Zone* zone)
ZoneAllocationPolicy(zone)),
smi_map_(zone),
smi_pairs_(zone),
heap_number_map_(zone),
#define INIT_SINGLETON_ENTRY_FIELD(NAME, LOWER_NAME) LOWER_NAME##_(-1),
SINGLETON_CONSTANT_ENTRY_TYPES(INIT_SINGLETON_ENTRY_FIELD)
#undef INIT_SINGLETON_ENTRY_FIELD
zone_(zone) {
heap_number_map_(zone) {
idx_slice_[0] =
zone->New<ConstantArraySlice>(zone, 0, k8BitCapacity, OperandSize::kByte);
idx_slice_[1] = zone->New<ConstantArraySlice>(
@ -247,8 +243,7 @@ size_t ConstantArrayBuilder::Insert(const AstRawString* raw_string) {
return constants_map_
.LookupOrInsert(reinterpret_cast<intptr_t>(raw_string),
raw_string->Hash(),
[&]() { return AllocateIndex(Entry(raw_string)); },
ZoneAllocationPolicy(zone_))
[&]() { return AllocateIndex(Entry(raw_string)); })
->value;
}
@ -256,8 +251,7 @@ size_t ConstantArrayBuilder::Insert(AstBigInt bigint) {
return constants_map_
.LookupOrInsert(reinterpret_cast<intptr_t>(bigint.c_str()),
static_cast<uint32_t>(base::hash_value(bigint.c_str())),
[&]() { return AllocateIndex(Entry(bigint)); },
ZoneAllocationPolicy(zone_))
[&]() { return AllocateIndex(Entry(bigint)); })
->value;
}
@ -265,8 +259,7 @@ size_t ConstantArrayBuilder::Insert(const Scope* scope) {
return constants_map_
.LookupOrInsert(reinterpret_cast<intptr_t>(scope),
static_cast<uint32_t>(base::hash_value(scope)),
[&]() { return AllocateIndex(Entry(scope)); },
ZoneAllocationPolicy(zone_))
[&]() { return AllocateIndex(Entry(scope)); })
->value;
}

View File

@ -239,11 +239,9 @@ class V8_EXPORT_PRIVATE ConstantArrayBuilder final {
ZoneVector<std::pair<Smi, index_t>> smi_pairs_;
ZoneMap<double, index_t> heap_number_map_;
#define SINGLETON_ENTRY_FIELD(NAME, LOWER_NAME) int LOWER_NAME##_;
#define SINGLETON_ENTRY_FIELD(NAME, LOWER_NAME) int LOWER_NAME##_ = -1;
SINGLETON_CONSTANT_ENTRY_TYPES(SINGLETON_ENTRY_FIELD)
#undef SINGLETON_ENTRY_FIELD
Zone* zone_;
};
} // namespace interpreter

View File

@ -1068,17 +1068,19 @@ Maybe<bool> KeyAccumulator::CollectOwnJSProxyKeys(Handle<JSReceiver> receiver,
// exception. Combine with step 18
// 18. Let uncheckedResultKeys be a new List which is a copy of trapResult.
Zone set_zone(isolate_->allocator(), ZONE_NAME);
ZoneAllocationPolicy alloc(&set_zone);
const int kPresent = 1;
const int kGone = 0;
base::TemplateHashMapImpl<Handle<Name>, int, NameComparator,
ZoneAllocationPolicy>
unchecked_result_keys(ZoneHashMap::kDefaultHashMapCapacity,
NameComparator(isolate_), alloc);
using ZoneHashMapImpl =
base::TemplateHashMapImpl<Handle<Name>, int, NameComparator,
ZoneAllocationPolicy>;
ZoneHashMapImpl unchecked_result_keys(
ZoneHashMapImpl::kDefaultHashMapCapacity, NameComparator(isolate_),
ZoneAllocationPolicy(&set_zone));
int unchecked_result_keys_size = 0;
for (int i = 0; i < trap_result->length(); ++i) {
Handle<Name> key(Name::cast(trap_result->get(i)), isolate_);
auto entry = unchecked_result_keys.LookupOrInsert(key, key->Hash(), alloc);
auto entry = unchecked_result_keys.LookupOrInsert(key, key->Hash());
if (entry->value != kPresent) {
entry->value = kPresent;
unchecked_result_keys_size++;