Commit eaaf0c2c authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[zone-stats] Extend AllocationPolicy interface

1) turn static methods to instance ones.
2) change New/Delete to NewArray/DeleteArray getting array length as
   argument instead of raw size.
3) propagate type tags through allocate/delete methods of existing
   AllocationPolicy classes.

This will allow implementing accounting of deallocated zone memory.

Bug: v8:10572
Change-Id: Ib41c646044814ac6d75d50b2847bbb8964ce25d3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2300489Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68904}
parent 26df3fdc
...@@ -20,8 +20,14 @@ namespace base { ...@@ -20,8 +20,14 @@ namespace base {
class DefaultAllocationPolicy { class DefaultAllocationPolicy {
public: public:
V8_INLINE void* New(size_t size) { return malloc(size); } template <typename T, typename TypeTag = T[]>
V8_INLINE static void Delete(void* p) { free(p); } V8_INLINE T* NewArray(size_t length) {
return static_cast<T*>(malloc(length * sizeof(T)));
}
template <typename T, typename TypeTag = T[]>
V8_INLINE void DeleteArray(T* p, size_t length) {
free(p);
}
}; };
template <typename Key, typename Value, class MatchFun, class AllocationPolicy> template <typename Key, typename Value, class MatchFun, class AllocationPolicy>
...@@ -78,7 +84,8 @@ class TemplateHashMapImpl { ...@@ -78,7 +84,8 @@ class TemplateHashMapImpl {
// Empties the map and makes it unusable for allocation. // Empties the map and makes it unusable for allocation.
void Invalidate() { void Invalidate() {
AllocationPolicy::Delete(impl_.map_); DCHECK_NOT_NULL(impl_.map_);
impl_.allocator().DeleteArray(impl_.map_, capacity());
impl_ = Impl(impl_.match(), AllocationPolicy()); impl_ = Impl(impl_.match(), AllocationPolicy());
} }
...@@ -173,8 +180,7 @@ TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>:: ...@@ -173,8 +180,7 @@ TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::
: impl_(original->impl_.match(), std::move(allocator)) { : impl_(original->impl_.match(), std::move(allocator)) {
impl_.capacity_ = original->capacity(); impl_.capacity_ = original->capacity();
impl_.occupancy_ = original->occupancy(); impl_.occupancy_ = original->occupancy();
impl_.map_ = reinterpret_cast<Entry*>( impl_.map_ = impl_.allocator().template NewArray<Entry>(capacity());
impl_.allocator().New(capacity() * sizeof(Entry)));
memcpy(impl_.map_, original->impl_.map_, capacity() * sizeof(Entry)); memcpy(impl_.map_, original->impl_.map_, capacity() * sizeof(Entry));
} }
...@@ -182,7 +188,7 @@ template <typename Key, typename Value, typename MatchFun, ...@@ -182,7 +188,7 @@ template <typename Key, typename Value, typename MatchFun,
class AllocationPolicy> class AllocationPolicy>
TemplateHashMapImpl<Key, Value, MatchFun, TemplateHashMapImpl<Key, Value, MatchFun,
AllocationPolicy>::~TemplateHashMapImpl() { AllocationPolicy>::~TemplateHashMapImpl() {
AllocationPolicy::Delete(impl_.map_); if (impl_.map_) impl_.allocator().DeleteArray(impl_.map_, capacity());
} }
template <typename Key, typename Value, typename MatchFun, template <typename Key, typename Value, typename MatchFun,
...@@ -363,8 +369,7 @@ template <typename Key, typename Value, typename MatchFun, ...@@ -363,8 +369,7 @@ template <typename Key, typename Value, typename MatchFun,
void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Initialize( void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Initialize(
uint32_t capacity) { uint32_t capacity) {
DCHECK(base::bits::IsPowerOfTwo(capacity)); DCHECK(base::bits::IsPowerOfTwo(capacity));
impl_.map_ = impl_.map_ = impl_.allocator().template NewArray<Entry>(capacity);
reinterpret_cast<Entry*>(allocator().New(capacity * sizeof(Entry)));
if (impl_.map_ == nullptr) { if (impl_.map_ == nullptr) {
FATAL("Out of memory: HashMap::Initialize"); FATAL("Out of memory: HashMap::Initialize");
return; return;
...@@ -376,14 +381,15 @@ void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Initialize( ...@@ -376,14 +381,15 @@ void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Initialize(
template <typename Key, typename Value, typename MatchFun, template <typename Key, typename Value, typename MatchFun,
class AllocationPolicy> class AllocationPolicy>
void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Resize() { void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Resize() {
Entry* map = impl_.map_; Entry* old_map = impl_.map_;
uint32_t old_capacity = capacity();
uint32_t n = occupancy(); uint32_t n = occupancy();
// Allocate larger map. // Allocate larger map.
Initialize(capacity() * 2); Initialize(capacity() * 2);
// Rehash all current entries. // Rehash all current entries.
for (Entry* entry = map; n > 0; entry++) { for (Entry* entry = old_map; n > 0; entry++) {
if (entry->exists()) { if (entry->exists()) {
Entry* new_entry = Probe(entry->key, entry->hash); Entry* new_entry = Probe(entry->key, entry->hash);
new_entry = new_entry =
...@@ -393,7 +399,7 @@ void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Resize() { ...@@ -393,7 +399,7 @@ void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Resize() {
} }
// Delete old map. // Delete old map.
AllocationPolicy::Delete(map); impl_.allocator().DeleteArray(old_map, old_capacity);
} }
// Match function which compares hashes before executing a (potentially // Match function which compares hashes before executing a (potentially
......
...@@ -67,8 +67,14 @@ char* StrNDup(const char* str, int n); ...@@ -67,8 +67,14 @@ char* StrNDup(const char* str, int n);
// and free. Used as the default policy for lists. // and free. Used as the default policy for lists.
class FreeStoreAllocationPolicy { class FreeStoreAllocationPolicy {
public: public:
V8_INLINE void* New(size_t size) { return Malloced::operator new(size); } template <typename T, typename TypeTag = T[]>
V8_INLINE static void Delete(void* p) { Malloced::operator delete(p); } V8_INLINE T* NewArray(size_t length) {
return static_cast<T*>(Malloced::operator new(length * sizeof(T)));
}
template <typename T, typename TypeTag = T[]>
V8_INLINE void DeleteArray(T* p, size_t length) {
Malloced::operator delete(p);
}
}; };
// Performs a malloc, with retry logic on failure. Returns nullptr on failure. // Performs a malloc, with retry logic on failure. Returns nullptr on failure.
......
...@@ -24,8 +24,8 @@ void IdentityMapBase::Clear() { ...@@ -24,8 +24,8 @@ void IdentityMapBase::Clear() {
if (keys_) { if (keys_) {
DCHECK(!is_iterable()); DCHECK(!is_iterable());
heap_->UnregisterStrongRoots(FullObjectSlot(keys_)); heap_->UnregisterStrongRoots(FullObjectSlot(keys_));
DeleteArray(keys_); DeletePointerArray(reinterpret_cast<void**>(keys_), capacity_);
DeleteArray(values_); DeletePointerArray(values_, capacity_);
keys_ = nullptr; keys_ = nullptr;
values_ = nullptr; values_ = nullptr;
size_ = 0; size_ = 0;
...@@ -289,8 +289,8 @@ void IdentityMapBase::Resize(int new_capacity) { ...@@ -289,8 +289,8 @@ void IdentityMapBase::Resize(int new_capacity) {
FullObjectSlot(keys_ + capacity_)); FullObjectSlot(keys_ + capacity_));
// Delete old storage; // Delete old storage;
DeleteArray(old_keys); DeletePointerArray(reinterpret_cast<void**>(old_keys), old_capacity);
DeleteArray(old_values); DeletePointerArray(old_values, old_capacity);
} }
} // namespace internal } // namespace internal
......
...@@ -56,7 +56,7 @@ class V8_EXPORT_PRIVATE IdentityMapBase { ...@@ -56,7 +56,7 @@ class V8_EXPORT_PRIVATE IdentityMapBase {
void DisableIteration(); void DisableIteration();
virtual void** NewPointerArray(size_t length) = 0; virtual void** NewPointerArray(size_t length) = 0;
virtual void DeleteArray(void* array) = 0; virtual void DeletePointerArray(void** array, size_t length) = 0;
private: private:
// Internal implementation should not be called directly by subclasses. // Internal implementation should not be called directly by subclasses.
...@@ -180,10 +180,18 @@ class IdentityMap : public IdentityMapBase { ...@@ -180,10 +180,18 @@ class IdentityMap : public IdentityMapBase {
}; };
protected: protected:
// This struct is just a type tag for Zone::NewArray<T>(size_t) call.
struct Buffer {};
// TODO(ishell): consider removing virtual methods in favor of combining
// IdentityMapBase and IdentityMap into one class. This would also save
// space when sizeof(V) is less than sizeof(void*).
void** NewPointerArray(size_t length) override { void** NewPointerArray(size_t length) override {
return static_cast<void**>(allocator_.New(sizeof(void*) * length)); return allocator_.template NewArray<void*, Buffer>(length);
}
void DeletePointerArray(void** array, size_t length) override {
allocator_.template DeleteArray<void*, Buffer>(array, length);
} }
void DeleteArray(void* array) override { allocator_.Delete(array); }
private: private:
AllocationPolicy allocator_; AllocationPolicy allocator_;
......
...@@ -62,6 +62,18 @@ class V8_EXPORT_PRIVATE Zone final { ...@@ -62,6 +62,18 @@ class V8_EXPORT_PRIVATE Zone final {
#endif #endif
} }
template <typename TypeTag = void>
void Delete(void* pointer, size_t size) {
DCHECK_NOT_NULL(pointer);
DCHECK_NE(size, 0);
// TODO(v8:10572): implement accounting for reusable zone memory
#ifdef DEBUG
size = RoundUp(size, kAlignmentInBytes);
static const unsigned char kZapDeadByte = 0xcd;
memset(pointer, kZapDeadByte, size);
#endif
}
// Allocates memory for T instance and constructs object by calling respective // Allocates memory for T instance and constructs object by calling respective
// Args... constructor. // Args... constructor.
// TODO(v8:10689): account allocated bytes with the T type. // TODO(v8:10689): account allocated bytes with the T type.
...@@ -82,16 +94,9 @@ class V8_EXPORT_PRIVATE Zone final { ...@@ -82,16 +94,9 @@ class V8_EXPORT_PRIVATE Zone final {
return static_cast<T*>(Allocate<TypeTag>(length * sizeof(T))); return static_cast<T*>(Allocate<TypeTag>(length * sizeof(T)));
} }
template <typename T> template <typename T, typename TypeTag = T[]>
void DeleteArray(T* pointer, size_t length) { void DeleteArray(T* pointer, size_t length) {
DCHECK_NOT_NULL(pointer); Delete<TypeTag>(pointer, length * sizeof(T));
DCHECK_NE(length, 0);
// TODO(v8:10572): implement accounting for reusable zone memory
#ifdef DEBUG
size_t size = RoundUp(length * sizeof(T), kAlignmentInBytes);
static const unsigned char kZapDeadByte = 0xcd;
memset(pointer, kZapDeadByte, size);
#endif
} }
// Seals the zone to prevent any further allocation. // Seals the zone to prevent any further allocation.
...@@ -197,8 +202,16 @@ class ZoneAllocationPolicy { ...@@ -197,8 +202,16 @@ class ZoneAllocationPolicy {
// Creates unusable allocation policy. // Creates unusable allocation policy.
ZoneAllocationPolicy() : zone_(nullptr) {} ZoneAllocationPolicy() : zone_(nullptr) {}
explicit ZoneAllocationPolicy(Zone* zone) : zone_(zone) {} explicit ZoneAllocationPolicy(Zone* zone) : zone_(zone) {}
void* New(size_t size) { return zone()->New(size); }
static void Delete(void* pointer) {} template <typename T, typename TypeTag = T[]>
V8_INLINE T* NewArray(size_t length) {
return zone()->NewArray<T, TypeTag>(length);
}
template <typename T, typename TypeTag = T[]>
V8_INLINE void DeleteArray(T* p, size_t length) {
zone()->DeleteArray<T, TypeTag>(p, length);
}
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
private: private:
......
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