From d0f3e5302c8d89fee4995b86a2b83c9ecf5d1e7a Mon Sep 17 00:00:00 2001 From: bmeurer Date: Wed, 28 Jan 2015 23:41:35 -0800 Subject: [PATCH] Minor refactoring for Zone class and friends. R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/885813002 Cr-Commit-Position: refs/heads/master@{#26315} --- BUILD.gn | 1 - src/ast.h | 1 - src/bit-vector.h | 1 - src/compiler/machine-operator.cc | 2 - src/deoptimizer.h | 1 - src/interface.h | 1 - src/jsregexp.h | 1 - src/profile-generator.cc | 1 - src/safepoint-table.cc | 1 - src/scopeinfo.h | 1 - src/type-info.h | 2 +- src/v8.h | 1 - src/zone-inl.h | 70 ---------------------- src/zone.cc | 100 ++++++++++++++++++------------- src/zone.h | 84 ++++++++++++++------------ test/cctest/test-regexp.cc | 1 - tools/gyp/v8.gyp | 1 - 17 files changed, 107 insertions(+), 163 deletions(-) delete mode 100644 src/zone-inl.h diff --git a/BUILD.gn b/BUILD.gn index d765369f39..155d2c3019 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -986,7 +986,6 @@ source_set("v8_base") { "src/version.h", "src/vm-state-inl.h", "src/vm-state.h", - "src/zone-inl.h", "src/zone.cc", "src/zone.h", "src/third_party/fdlibm/fdlibm.cc", diff --git a/src/ast.h b/src/ast.h index 4b5f0bda41..02f7df64b0 100644 --- a/src/ast.h +++ b/src/ast.h @@ -22,7 +22,6 @@ #include "src/types.h" #include "src/utils.h" #include "src/variables.h" -#include "src/zone-inl.h" namespace v8 { namespace internal { diff --git a/src/bit-vector.h b/src/bit-vector.h index 9fc747d06f..29c6b438a9 100644 --- a/src/bit-vector.h +++ b/src/bit-vector.h @@ -10,7 +10,6 @@ #include "src/allocation.h" #include "src/ast.h" #include "src/compiler.h" -#include "src/zone-inl.h" namespace v8 { namespace internal { diff --git a/src/compiler/machine-operator.cc b/src/compiler/machine-operator.cc index eb034e92e3..2522a8e15d 100644 --- a/src/compiler/machine-operator.cc +++ b/src/compiler/machine-operator.cc @@ -7,8 +7,6 @@ #include "src/base/lazy-instance.h" #include "src/compiler/opcodes.h" #include "src/compiler/operator.h" -#include "src/v8.h" -#include "src/zone-inl.h" namespace v8 { namespace internal { diff --git a/src/deoptimizer.h b/src/deoptimizer.h index 612d5f6ecf..b14c369741 100644 --- a/src/deoptimizer.h +++ b/src/deoptimizer.h @@ -9,7 +9,6 @@ #include "src/allocation.h" #include "src/macro-assembler.h" -#include "src/zone-inl.h" namespace v8 { diff --git a/src/interface.h b/src/interface.h index 1843f47846..3336021d82 100644 --- a/src/interface.h +++ b/src/interface.h @@ -6,7 +6,6 @@ #define V8_INTERFACE_H_ #include "src/ast-value-factory.h" -#include "src/zone-inl.h" // For operator new. namespace v8 { namespace internal { diff --git a/src/jsregexp.h b/src/jsregexp.h index 419fd7b8cc..d74b3bcbbe 100644 --- a/src/jsregexp.h +++ b/src/jsregexp.h @@ -7,7 +7,6 @@ #include "src/allocation.h" #include "src/assembler.h" -#include "src/zone-inl.h" namespace v8 { namespace internal { diff --git a/src/profile-generator.cc b/src/profile-generator.cc index 7ad491021b..ac3df176ca 100644 --- a/src/profile-generator.cc +++ b/src/profile-generator.cc @@ -12,7 +12,6 @@ #include "src/sampler.h" #include "src/scopeinfo.h" #include "src/unicode.h" -#include "src/zone-inl.h" namespace v8 { namespace internal { diff --git a/src/safepoint-table.cc b/src/safepoint-table.cc index aaa32b9e14..a0ae5b2ced 100644 --- a/src/safepoint-table.cc +++ b/src/safepoint-table.cc @@ -10,7 +10,6 @@ #include "src/disasm.h" #include "src/macro-assembler.h" #include "src/ostreams.h" -#include "src/zone-inl.h" namespace v8 { namespace internal { diff --git a/src/scopeinfo.h b/src/scopeinfo.h index 1d9f06fde8..8462548d9d 100644 --- a/src/scopeinfo.h +++ b/src/scopeinfo.h @@ -7,7 +7,6 @@ #include "src/allocation.h" #include "src/variables.h" -#include "src/zone-inl.h" namespace v8 { namespace internal { diff --git a/src/type-info.h b/src/type-info.h index e9653d5833..65af76865e 100644 --- a/src/type-info.h +++ b/src/type-info.h @@ -8,7 +8,7 @@ #include "src/allocation.h" #include "src/globals.h" #include "src/types.h" -#include "src/zone-inl.h" +#include "src/zone.h" namespace v8 { namespace internal { diff --git a/src/v8.h b/src/v8.h index 4267434e4b..4922a4db1e 100644 --- a/src/v8.h +++ b/src/v8.h @@ -44,7 +44,6 @@ #include "src/log-inl.h" // NOLINT #include "src/handles-inl.h" // NOLINT #include "src/types-inl.h" // NOLINT -#include "src/zone-inl.h" // NOLINT namespace v8 { namespace internal { diff --git a/src/zone-inl.h b/src/zone-inl.h deleted file mode 100644 index 63efe16818..0000000000 --- a/src/zone-inl.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2012 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef V8_ZONE_INL_H_ -#define V8_ZONE_INL_H_ - -#include "src/zone.h" - -#ifdef V8_USE_ADDRESS_SANITIZER - #include -#else - #define ASAN_UNPOISON_MEMORY_REGION(start, size) ((void) 0) -#endif - -#include "src/counters.h" -#include "src/isolate.h" -#include "src/utils.h" - -namespace v8 { -namespace internal { - - -static const int kASanRedzoneBytes = 24; // Must be a multiple of 8. - - -bool Zone::excess_allocation() { - return segment_bytes_allocated_ > kExcessLimit; -} - - -void Zone::adjust_segment_bytes_allocated(int delta) { - segment_bytes_allocated_ += delta; -} - - -template -ZoneSplayTree::~ZoneSplayTree() { - // Reset the root to avoid unneeded iteration over all tree nodes - // in the destructor. For a zone-allocated tree, nodes will be - // freed by the Zone. - SplayTree::ResetRoot(); -} - - -void* ZoneObject::operator new(size_t size, Zone* zone) { - return zone->New(static_cast(size)); -} - -inline void* ZoneAllocationPolicy::New(size_t size) { - DCHECK(zone_); - return zone_->New(static_cast(size)); -} - - -template -void* ZoneList::operator new(size_t size, Zone* zone) { - return zone->New(static_cast(size)); -} - - -template -void* ZoneSplayTree::operator new(size_t size, Zone* zone) { - return zone->New(static_cast(size)); -} - - -} } // namespace v8::internal - -#endif // V8_ZONE_INL_H_ diff --git a/src/zone.cc b/src/zone.cc index e52523dd96..41eff83590 100644 --- a/src/zone.cc +++ b/src/zone.cc @@ -2,14 +2,43 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include +#include "src/zone.h" -#include "src/v8.h" -#include "src/zone-inl.h" +#include + +#ifdef V8_USE_ADDRESS_SANITIZER +#include +#endif // V8_USE_ADDRESS_SANITIZER namespace v8 { namespace internal { +namespace { + +#if V8_USE_ADDRESS_SANITIZER + +const int kASanRedzoneBytes = 24; // Must be a multiple of 8. + +#else + +#define ASAN_POISON_MEMORY_REGION(start, size) \ + do { \ + USE(start); \ + USE(size); \ + } while (false) + +#define ASAN_UNPOISON_MEMORY_REGION(start, size) \ + do { \ + USE(start); \ + USE(size); \ + } while (false) + +const int kASanRedzoneBytes = 0; + +#endif // V8_USE_ADDRESS_SANITIZER + +} // namespace + // Segments represent chunks of memory: They have starting address // (encoded in the this pointer) and a size in bytes. Segments are @@ -25,7 +54,7 @@ class Segment { } Segment* next() const { return next_; } - void clear_next() { next_ = NULL; } + void clear_next() { next_ = nullptr; } int size() const { return size_; } int capacity() const { return size_ - sizeof(Segment); } @@ -49,7 +78,7 @@ Zone::Zone() segment_bytes_allocated_(0), position_(0), limit_(0), - segment_head_(NULL) {} + segment_head_(nullptr) {} Zone::~Zone() { @@ -75,24 +104,16 @@ void* Zone::New(int size) { // Check if the requested size is available without expanding. Address result = position_; - int size_with_redzone = -#ifdef V8_USE_ADDRESS_SANITIZER - size + kASanRedzoneBytes; -#else - size; -#endif - + const int size_with_redzone = size + kASanRedzoneBytes; if (size_with_redzone > limit_ - position_) { - result = NewExpand(size_with_redzone); + result = NewExpand(size_with_redzone); } else { - position_ += size_with_redzone; + position_ += size_with_redzone; } -#ifdef V8_USE_ADDRESS_SANITIZER Address redzone_position = result + size; DCHECK(redzone_position + kASanRedzoneBytes == position_); ASAN_POISON_MEMORY_REGION(redzone_position, kASanRedzoneBytes); -#endif // Check that the result has the proper alignment and return it. DCHECK(IsAddressAligned(result, kAlignment, 0)); @@ -108,12 +129,12 @@ void Zone::DeleteAll() { #endif // Find a segment with a suitable size to keep around. - Segment* keep = NULL; + Segment* keep = nullptr; // Traverse the chained list of segments, zapping (in debug mode) // and freeing every segment except the one we wish to keep. - for (Segment* current = segment_head_; current != NULL; ) { + for (Segment* current = segment_head_; current;) { Segment* next = current->next(); - if (keep == NULL && current->size() <= kMaximumKeptSegmentSize) { + if (!keep && current->size() <= kMaximumKeptSegmentSize) { // Unlink the segment we wish to keep from the list. keep = current; keep->clear_next(); @@ -134,7 +155,7 @@ void Zone::DeleteAll() { // variables 'position' and 'limit' to prepare for future allocate // attempts. Otherwise, we must clear the position and limit to // force a new segment to be allocated on demand. - if (keep != NULL) { + if (keep) { Address start = keep->start(); position_ = RoundUp(start, kAlignment); limit_ = keep->end(); @@ -160,8 +181,8 @@ void Zone::DeleteKeptSegment() { static const unsigned char kZapDeadByte = 0xcd; #endif - DCHECK(segment_head_ == NULL || segment_head_->next() == NULL); - if (segment_head_ != NULL) { + DCHECK(segment_head_ == nullptr || segment_head_->next() == nullptr); + if (segment_head_ != nullptr) { int size = segment_head_->size(); #ifdef DEBUG // Un-poison first so the zapping doesn't trigger ASan complaints. @@ -170,7 +191,7 @@ void Zone::DeleteKeptSegment() { memset(segment_head_, kZapDeadByte, size); #endif DeleteSegment(segment_head_, size); - segment_head_ = NULL; + segment_head_ = nullptr; } DCHECK(segment_bytes_allocated_ == 0); @@ -181,8 +202,8 @@ void Zone::DeleteKeptSegment() { // of the segment chain. Returns the new segment. Segment* Zone::NewSegment(int size) { Segment* result = reinterpret_cast(Malloced::New(size)); - adjust_segment_bytes_allocated(size); - if (result != NULL) { + segment_bytes_allocated_ += size; + if (result != nullptr) { result->Initialize(segment_head_, size); segment_head_ = result; } @@ -192,7 +213,7 @@ Segment* Zone::NewSegment(int size) { // Deletes the given segment. Does not touch the segment chain. void Zone::DeleteSegment(Segment* segment, int size) { - adjust_segment_bytes_allocated(-size); + segment_bytes_allocated_ -= size; Malloced::Delete(segment); } @@ -208,7 +229,7 @@ Address Zone::NewExpand(int size) { // except that we employ a maximum segment size when we delete. This // is to avoid excessive malloc() and free() overhead. Segment* head = segment_head_; - const size_t old_size = (head == NULL) ? 0 : head->size(); + const size_t old_size = (head == nullptr) ? 0 : head->size(); static const size_t kSegmentOverhead = sizeof(Segment) + kAlignment; const size_t new_size_no_overhead = size + (old_size << 1); size_t new_size = kSegmentOverhead + new_size_no_overhead; @@ -216,8 +237,8 @@ Address Zone::NewExpand(int size) { // Guard against integer overflow. if (new_size_no_overhead < static_cast(size) || new_size < static_cast(kSegmentOverhead)) { - V8::FatalProcessOutOfMemory("Zone"); - return NULL; + FatalProcessOutOfMemory("Zone"); + return nullptr; } if (new_size < static_cast(kMinimumSegmentSize)) { new_size = kMinimumSegmentSize; @@ -229,13 +250,13 @@ Address Zone::NewExpand(int size) { new_size = Max(min_new_size, static_cast(kMaximumSegmentSize)); } if (new_size > INT_MAX) { - V8::FatalProcessOutOfMemory("Zone"); - return NULL; + FatalProcessOutOfMemory("Zone"); + return nullptr; } Segment* segment = NewSegment(static_cast(new_size)); - if (segment == NULL) { - V8::FatalProcessOutOfMemory("Zone"); - return NULL; + if (segment == nullptr) { + FatalProcessOutOfMemory("Zone"); + return nullptr; } // Recompute 'top' and 'limit' based on the new segment. @@ -244,15 +265,12 @@ Address Zone::NewExpand(int size) { // Check for address overflow. // (Should not happen since the segment is guaranteed to accomodate // size bytes + header and alignment padding) - if (reinterpret_cast(position_) - < reinterpret_cast(result)) { - V8::FatalProcessOutOfMemory("Zone"); - return NULL; - } + DCHECK_GE(reinterpret_cast(position_), + reinterpret_cast(result)); limit_ = segment->end(); DCHECK(position_ <= limit_); return result; } - -} } // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/src/zone.h b/src/zone.h index 2a730f9ee0..da657155fe 100644 --- a/src/zone.h +++ b/src/zone.h @@ -17,35 +17,35 @@ namespace v8 { namespace internal { - +// Forward declarations. class Segment; -class Isolate; + // The Zone supports very fast allocation of small chunks of // memory. The chunks cannot be deallocated individually, but instead // the Zone supports deallocating all chunks in one fast // operation. The Zone is used to hold temporary data structures like // the abstract syntax tree, which is deallocated after compilation. - +// // Note: There is no need to initialize the Zone; the first time an // allocation is attempted, a segment of memory will be requested // through a call to malloc(). - +// // Note: The implementation is inherently not thread safe. Do not use // from multi-threaded code. - -class Zone { +class Zone FINAL { public: Zone(); ~Zone(); + // Allocate 'size' bytes of memory in the Zone; expands the Zone by // allocating new segments of memory on demand using malloc(). void* New(int size); template T* NewArray(int length) { - CHECK(std::numeric_limits::max() / static_cast(sizeof(T)) > - length); + DCHECK(std::numeric_limits::max() / static_cast(sizeof(T)) > + length); return static_cast(New(length * sizeof(T))); } @@ -59,15 +59,13 @@ class Zone { // Returns true if more memory has been allocated in zones than // the limit allows. - inline bool excess_allocation(); + bool excess_allocation() const { + return segment_bytes_allocated_ > kExcessLimit; + } - inline void adjust_segment_bytes_allocated(int delta); - - inline unsigned allocation_size() const { return allocation_size_; } + unsigned allocation_size() const { return allocation_size_; } private: - friend class Isolate; - // 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. @@ -106,10 +104,10 @@ class Zone { // Creates a new segment, sets it size, and pushes it to the front // of the segment chain. Returns the new segment. - INLINE(Segment* NewSegment(int size)); + inline Segment* NewSegment(int size); // Deletes the given segment. Does not touch the segment chain. - INLINE(void DeleteSegment(Segment* segment, int size)); + inline void DeleteSegment(Segment* segment, int size); // The free region in the current (front) segment is represented as // the half-open interval [position, limit). The 'position' variable @@ -126,7 +124,9 @@ class Zone { class ZoneObject { public: // Allocate a new ZoneObject of 'size' bytes in the Zone. - INLINE(void* operator new(size_t size, Zone* zone)); + void* operator new(size_t size, Zone* zone) { + return zone->New(static_cast(size)); + } // Ideally, the delete operator should be private instead of // public, but unfortunately the compiler sometimes synthesizes @@ -143,12 +143,12 @@ class ZoneObject { // The ZoneScope is used to automatically call DeleteAll() on a // Zone when the ZoneScope is destroyed (i.e. goes out of scope) -struct ZoneScope { +class ZoneScope FINAL { public: explicit ZoneScope(Zone* zone) : zone_(zone) { } ~ZoneScope() { zone_->DeleteAll(); } - Zone* zone() { return zone_; } + Zone* zone() const { return zone_; } private: Zone* zone_; @@ -157,12 +157,12 @@ struct ZoneScope { // The ZoneAllocationPolicy is used to specialize generic data // structures to allocate themselves and their elements in the Zone. -struct ZoneAllocationPolicy { +class ZoneAllocationPolicy FINAL { public: explicit ZoneAllocationPolicy(Zone* zone) : zone_(zone) { } - INLINE(void* New(size_t size)); - INLINE(static void Delete(void *pointer)) { } - Zone* zone() { return zone_; } + void* New(size_t size) { return zone()->New(static_cast(size)); } + static void Delete(void* pointer) {} + Zone* zone() const { return zone_; } private: Zone* zone_; @@ -173,15 +173,17 @@ struct ZoneAllocationPolicy { // elements. The list itself and all its elements are allocated in the // Zone. ZoneLists cannot be deleted individually; you can delete all // objects in the Zone by calling Zone::DeleteAll(). -template -class ZoneList: public List { +template +class ZoneList FINAL : public List { public: // Construct a new ZoneList with the given capacity; the length is // always zero. The capacity must be non-negative. ZoneList(int capacity, Zone* zone) : List(capacity, ZoneAllocationPolicy(zone)) { } - INLINE(void* operator new(size_t size, Zone* zone)); + void* operator new(size_t size, Zone* zone) { + return zone->New(static_cast(size)); + } // Construct a new ZoneList by copying the elements of the given ZoneList. ZoneList(const ZoneList& other, Zone* zone) @@ -192,27 +194,27 @@ class ZoneList: public List { // We add some convenience wrappers so that we can pass in a Zone // instead of a (less convenient) ZoneAllocationPolicy. - INLINE(void Add(const T& element, Zone* zone)) { + void Add(const T& element, Zone* zone) { List::Add(element, ZoneAllocationPolicy(zone)); } - INLINE(void AddAll(const List& other, Zone* zone)) { + void AddAll(const List& other, Zone* zone) { List::AddAll(other, ZoneAllocationPolicy(zone)); } - INLINE(void AddAll(const Vector& other, Zone* zone)) { + void AddAll(const Vector& other, Zone* zone) { List::AddAll(other, ZoneAllocationPolicy(zone)); } - INLINE(void InsertAt(int index, const T& element, Zone* zone)) { + void InsertAt(int index, const T& element, Zone* zone) { List::InsertAt(index, element, ZoneAllocationPolicy(zone)); } - INLINE(Vector AddBlock(T value, int count, Zone* zone)) { + Vector AddBlock(T value, int count, Zone* zone) { return List::AddBlock(value, count, ZoneAllocationPolicy(zone)); } - INLINE(void Allocate(int length, Zone* zone)) { + void Allocate(int length, Zone* zone) { List::Allocate(length, ZoneAllocationPolicy(zone)); } - INLINE(void Initialize(int capacity, Zone* zone)) { + void Initialize(int capacity, Zone* zone) { List::Initialize(capacity, ZoneAllocationPolicy(zone)); } @@ -226,13 +228,20 @@ class ZoneList: public List { // different configurations of a concrete splay tree (see splay-tree.h). // The tree itself and all its elements are allocated in the Zone. template -class ZoneSplayTree: public SplayTree { +class ZoneSplayTree FINAL : public SplayTree { public: explicit ZoneSplayTree(Zone* zone) : SplayTree(ZoneAllocationPolicy(zone)) {} - ~ZoneSplayTree(); + ~ZoneSplayTree() { + // Reset the root to avoid unneeded iteration over all tree nodes + // in the destructor. For a zone-allocated tree, nodes will be + // freed by the Zone. + SplayTree::ResetRoot(); + } - INLINE(void* operator new(size_t size, Zone* zone)); + void* operator new(size_t size, Zone* zone) { + return zone->New(static_cast(size)); + } void operator delete(void* pointer) { UNREACHABLE(); } void operator delete(void* pointer, Zone* zone) { UNREACHABLE(); } @@ -241,6 +250,7 @@ class ZoneSplayTree: public SplayTree { typedef TemplateHashMapImpl ZoneHashMap; -} } // namespace v8::internal +} // namespace internal +} // namespace v8 #endif // V8_ZONE_H_ diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc index 2fe46d53ea..db624e9787 100644 --- a/test/cctest/test-regexp.cc +++ b/test/cctest/test-regexp.cc @@ -38,7 +38,6 @@ #include "src/regexp-macro-assembler.h" #include "src/regexp-macro-assembler-irregexp.h" #include "src/string-stream.h" -#include "src/zone-inl.h" #ifdef V8_INTERPRETED_REGEXP #include "src/interpreter-irregexp.h" #else // V8_INTERPRETED_REGEXP diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index 2a28db5475..67f95597f1 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp @@ -895,7 +895,6 @@ '../../src/version.h', '../../src/vm-state-inl.h', '../../src/vm-state.h', - '../../src/zone-inl.h', '../../src/zone.cc', '../../src/zone.h', '../../src/third_party/fdlibm/fdlibm.cc',