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 {
class DefaultAllocationPolicy {
public:
V8_INLINE void* New(size_t size) { return malloc(size); }
V8_INLINE static void Delete(void* p) { free(p); }
template <typename T, typename TypeTag = T[]>
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>
......@@ -78,7 +84,8 @@ class TemplateHashMapImpl {
// Empties the map and makes it unusable for allocation.
void Invalidate() {
AllocationPolicy::Delete(impl_.map_);
DCHECK_NOT_NULL(impl_.map_);
impl_.allocator().DeleteArray(impl_.map_, capacity());
impl_ = Impl(impl_.match(), AllocationPolicy());
}
......@@ -173,8 +180,7 @@ TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::
: impl_(original->impl_.match(), std::move(allocator)) {
impl_.capacity_ = original->capacity();
impl_.occupancy_ = original->occupancy();
impl_.map_ = reinterpret_cast<Entry*>(
impl_.allocator().New(capacity() * sizeof(Entry)));
impl_.map_ = impl_.allocator().template NewArray<Entry>(capacity());
memcpy(impl_.map_, original->impl_.map_, capacity() * sizeof(Entry));
}
......@@ -182,7 +188,7 @@ template <typename Key, typename Value, typename MatchFun,
class AllocationPolicy>
TemplateHashMapImpl<Key, Value, MatchFun,
AllocationPolicy>::~TemplateHashMapImpl() {
AllocationPolicy::Delete(impl_.map_);
if (impl_.map_) impl_.allocator().DeleteArray(impl_.map_, capacity());
}
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(
uint32_t capacity) {
DCHECK(base::bits::IsPowerOfTwo(capacity));
impl_.map_ =
reinterpret_cast<Entry*>(allocator().New(capacity * sizeof(Entry)));
impl_.map_ = impl_.allocator().template NewArray<Entry>(capacity);
if (impl_.map_ == nullptr) {
FATAL("Out of memory: HashMap::Initialize");
return;
......@@ -376,14 +381,15 @@ void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Initialize(
template <typename Key, typename Value, typename MatchFun,
class AllocationPolicy>
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();
// Allocate larger map.
Initialize(capacity() * 2);
// Rehash all current entries.
for (Entry* entry = map; n > 0; entry++) {
for (Entry* entry = old_map; n > 0; entry++) {
if (entry->exists()) {
Entry* new_entry = Probe(entry->key, entry->hash);
new_entry =
......@@ -393,7 +399,7 @@ void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Resize() {
}
// Delete old map.
AllocationPolicy::Delete(map);
impl_.allocator().DeleteArray(old_map, old_capacity);
}
// Match function which compares hashes before executing a (potentially
......
......@@ -67,8 +67,14 @@ char* StrNDup(const char* str, int n);
// and free. Used as the default policy for lists.
class FreeStoreAllocationPolicy {
public:
V8_INLINE void* New(size_t size) { return Malloced::operator new(size); }
V8_INLINE static void Delete(void* p) { Malloced::operator delete(p); }
template <typename T, typename TypeTag = T[]>
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.
......
......@@ -24,8 +24,8 @@ void IdentityMapBase::Clear() {
if (keys_) {
DCHECK(!is_iterable());
heap_->UnregisterStrongRoots(FullObjectSlot(keys_));
DeleteArray(keys_);
DeleteArray(values_);
DeletePointerArray(reinterpret_cast<void**>(keys_), capacity_);
DeletePointerArray(values_, capacity_);
keys_ = nullptr;
values_ = nullptr;
size_ = 0;
......@@ -289,8 +289,8 @@ void IdentityMapBase::Resize(int new_capacity) {
FullObjectSlot(keys_ + capacity_));
// Delete old storage;
DeleteArray(old_keys);
DeleteArray(old_values);
DeletePointerArray(reinterpret_cast<void**>(old_keys), old_capacity);
DeletePointerArray(old_values, old_capacity);
}
} // namespace internal
......
......@@ -56,7 +56,7 @@ class V8_EXPORT_PRIVATE IdentityMapBase {
void DisableIteration();
virtual void** NewPointerArray(size_t length) = 0;
virtual void DeleteArray(void* array) = 0;
virtual void DeletePointerArray(void** array, size_t length) = 0;
private:
// Internal implementation should not be called directly by subclasses.
......@@ -180,10 +180,18 @@ class IdentityMap : public IdentityMapBase {
};
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 {
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:
AllocationPolicy allocator_;
......
......@@ -62,6 +62,18 @@ class V8_EXPORT_PRIVATE Zone final {
#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
// Args... constructor.
// TODO(v8:10689): account allocated bytes with the T type.
......@@ -82,16 +94,9 @@ class V8_EXPORT_PRIVATE Zone final {
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) {
DCHECK_NOT_NULL(pointer);
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
Delete<TypeTag>(pointer, length * sizeof(T));
}
// Seals the zone to prevent any further allocation.
......@@ -197,8 +202,16 @@ class ZoneAllocationPolicy {
// Creates unusable allocation policy.
ZoneAllocationPolicy() : zone_(nullptr) {}
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_; }
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