| Index: src/zone.h
|
| diff --git a/src/zone.h b/src/zone.h
|
| index 29055cb70d053547d44091cdfaf420e0f6736e2d..0b5b41c80a9f5b4e54701a41b49226df4f0318fc 100644
|
| --- a/src/zone.h
|
| +++ b/src/zone.h
|
| @@ -10,6 +10,7 @@
|
| #include "src/base/accounting-allocator.h"
|
| #include "src/base/hashmap.h"
|
| #include "src/base/logging.h"
|
| +#include "src/base/platform/platform.h"
|
| #include "src/globals.h"
|
| #include "src/list.h"
|
| #include "src/splay-tree.h"
|
| @@ -66,7 +67,13 @@ class Zone final {
|
|
|
| base::AccountingAllocator* allocator() const { return allocator_; }
|
|
|
| + // Returns the zone the pointer belongs to. Only works in case the pointer
|
| + // actually lies within a zone segment.
|
| + static Zone* GetZoneFromPointer(const void* ptr);
|
| +
|
| private:
|
| + friend class ZoneObject;
|
| + friend class Segment;
|
| // All pointers returned from New() have this alignment. In addition, if the
|
| // object being allocated has a size that is divisible by 8 then its alignment
|
| // will be 8. ASan requires 8-byte alignment.
|
| @@ -83,12 +90,24 @@ class Zone final {
|
| // Never allocate segments larger than this size in bytes.
|
| static const size_t kMaximumSegmentSize = 1 * MB;
|
|
|
| + static const uint8_t kSegmentAlignmentBits = 20;
|
| +
|
| + // Always align new segments to this size.
|
| + static const size_t kSegmentAlignmentSize = 1 << kSegmentAlignmentBits;
|
| +
|
| + static const size_t kSegmentAlignmentMask =
|
| + ~((1 << kSegmentAlignmentBits) - 1);
|
| +
|
| + STATIC_ASSERT(kMaximumSegmentSize <= kSegmentAlignmentSize);
|
| +
|
| // Never keep segments larger than this size in bytes around.
|
| static const size_t kMaximumKeptSegmentSize = 64 * KB;
|
|
|
| // Report zone excess when allocation exceeds this limit.
|
| static const size_t kExcessLimit = 256 * MB;
|
|
|
| + static Segment* GetZoneSegmentFromPointer(const void* ptr);
|
| +
|
| // The number of bytes allocated in this zone so far.
|
| size_t allocation_size_;
|
|
|
| @@ -97,18 +116,19 @@ class Zone final {
|
| // the zone.
|
| size_t segment_bytes_allocated_;
|
|
|
| - // Expand the Zone to hold at least 'size' more bytes and allocate
|
| - // the bytes. Returns the address of the newly allocated chunk of
|
| - // memory in the Zone. Should only be called if there isn't enough
|
| - // room in the Zone already.
|
| - Address NewExpand(size_t size);
|
| + // Creates a new normal segment, that can be used to quickly allocate memory
|
| + // for lots of smaller objects.
|
| + Address NewNormalSegment(size_t size);
|
|
|
| - // Creates a new segment, sets it size, and pushes it to the front
|
| - // of the segment chain. Returns the new segment.
|
| - inline Segment* NewSegment(size_t size);
|
| + // Creates a large object segment, that is created to exactly fit one large
|
| + // object.
|
| + Address NewLargeObjectSegment(size_t size);
|
| +
|
| + size_t CalculateSegmentSize(const size_t requested);
|
|
|
| - // Deletes the given segment. Does not touch the segment chain.
|
| - inline void DeleteSegment(Segment* segment, size_t size);
|
| + // Creates a new segment of the requested size and initializes it. Returns the
|
| + // new segment.
|
| + inline Segment* NewSegment(size_t size);
|
|
|
| // The free region in the current (front) segment is represented as
|
| // the half-open interval [position, limit). The 'position' variable
|
| @@ -121,7 +141,6 @@ class Zone final {
|
| Segment* segment_head_;
|
| };
|
|
|
| -
|
| // ZoneObject is an abstraction that helps define classes of objects
|
| // allocated in the Zone. Use it as a base class; see ast.h.
|
| class ZoneObject {
|
| @@ -129,6 +148,8 @@ class ZoneObject {
|
| // Allocate a new ZoneObject of 'size' bytes in the Zone.
|
| void* operator new(size_t size, Zone* zone) { return zone->New(size); }
|
|
|
| + Zone* zone() const { return Zone::GetZoneFromPointer(this); }
|
| +
|
| // Ideally, the delete operator should be private instead of
|
| // public, but unfortunately the compiler sometimes synthesizes
|
| // (unused) destructors for classes derived from ZoneObject, which
|
| @@ -162,7 +183,9 @@ class ZoneAllocationPolicy final {
|
| public:
|
| explicit ZoneAllocationPolicy(Zone* zone) : zone_(zone) { }
|
| void* New(size_t size) { return zone()->New(size); }
|
| - static void Delete(void* pointer) {}
|
| + static void Delete(void* pointer) {
|
| + DCHECK_IMPLIES(pointer != nullptr, Zone::GetZoneFromPointer(pointer));
|
| + }
|
| Zone* zone() const { return zone_; }
|
|
|
| private:
|
| @@ -179,8 +202,9 @@ class ZoneList final : public List<T, ZoneAllocationPolicy> {
|
| public:
|
| // Construct a new ZoneList with the given capacity; the length is
|
| // always zero. The capacity must be non-negative.
|
| + // The lists storage will be placed in the given zone.
|
| ZoneList(int capacity, Zone* zone)
|
| - : List<T, ZoneAllocationPolicy>(capacity, ZoneAllocationPolicy(zone)) { }
|
| + : List<T, ZoneAllocationPolicy>(capacity, ZoneAllocationPolicy(zone)) {}
|
|
|
| void* operator new(size_t size, Zone* zone) { return zone->New(size); }
|
|
|
| @@ -191,33 +215,53 @@ class ZoneList final : public List<T, ZoneAllocationPolicy> {
|
| AddAll(other, zone);
|
| }
|
|
|
| - // We add some convenience wrappers so that we can pass in a Zone
|
| - // instead of a (less convenient) ZoneAllocationPolicy.
|
| void Add(const T& element, Zone* zone) {
|
| + DCHECK_IMPLIES(this->has_storage_zone(), this->storage_zone() == zone);
|
| List<T, ZoneAllocationPolicy>::Add(element, ZoneAllocationPolicy(zone));
|
| }
|
| +
|
| void AddAll(const List<T, ZoneAllocationPolicy>& other, Zone* zone) {
|
| + DCHECK_IMPLIES(this->has_storage_zone(), this->storage_zone() == zone);
|
| List<T, ZoneAllocationPolicy>::AddAll(other, ZoneAllocationPolicy(zone));
|
| }
|
| +
|
| void AddAll(const Vector<T>& other, Zone* zone) {
|
| + DCHECK_IMPLIES(this->has_storage_zone(), this->storage_zone() == zone);
|
| List<T, ZoneAllocationPolicy>::AddAll(other, ZoneAllocationPolicy(zone));
|
| }
|
| +
|
| void InsertAt(int index, const T& element, Zone* zone) {
|
| + DCHECK_IMPLIES(this->has_storage_zone(), this->storage_zone() == zone);
|
| List<T, ZoneAllocationPolicy>::InsertAt(index, element,
|
| ZoneAllocationPolicy(zone));
|
| }
|
| +
|
| Vector<T> AddBlock(T value, int count, Zone* zone) {
|
| + DCHECK_IMPLIES(this->has_storage_zone(), this->storage_zone() == zone);
|
| return List<T, ZoneAllocationPolicy>::AddBlock(value, count,
|
| ZoneAllocationPolicy(zone));
|
| }
|
| +
|
| void Allocate(int length, Zone* zone) {
|
| + DCHECK_IMPLIES(this->has_storage_zone(), this->storage_zone() == zone);
|
| List<T, ZoneAllocationPolicy>::Allocate(length, ZoneAllocationPolicy(zone));
|
| }
|
| +
|
| void Initialize(int capacity, Zone* zone) {
|
| + DCHECK_IMPLIES(this->has_storage_zone(), this->storage_zone() == zone);
|
| List<T, ZoneAllocationPolicy>::Initialize(capacity,
|
| ZoneAllocationPolicy(zone));
|
| }
|
|
|
| + bool has_storage_zone() const { return this->capacity() > 0; }
|
| +
|
| + // Returns the zone the storage is located in
|
| + Zone* storage_zone() const {
|
| + DCHECK(this->has_storage_zone());
|
| + // ZoneList storage lives in a zone, so this works.
|
| + return Zone::GetZoneFromPointer(this->data());
|
| + }
|
| +
|
| void operator delete(void* pointer) { UNREACHABLE(); }
|
| void operator delete(void* pointer, Zone* zone) { UNREACHABLE(); }
|
| };
|
|
|