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}
This commit is contained in:
bmeurer 2015-01-28 23:41:35 -08:00 committed by Commit bot
parent 1f2e5973eb
commit d0f3e5302c
17 changed files with 107 additions and 163 deletions

View File

@ -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",

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -9,7 +9,6 @@
#include "src/allocation.h"
#include "src/macro-assembler.h"
#include "src/zone-inl.h"
namespace v8 {

View File

@ -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 {

View File

@ -7,7 +7,6 @@
#include "src/allocation.h"
#include "src/assembler.h"
#include "src/zone-inl.h"
namespace v8 {
namespace internal {

View File

@ -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 {

View File

@ -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 {

View File

@ -7,7 +7,6 @@
#include "src/allocation.h"
#include "src/variables.h"
#include "src/zone-inl.h"
namespace v8 {
namespace internal {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 <sanitizer/asan_interface.h>
#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 <typename Config>
ZoneSplayTree<Config>::~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<Config, ZoneAllocationPolicy>::ResetRoot();
}
void* ZoneObject::operator new(size_t size, Zone* zone) {
return zone->New(static_cast<int>(size));
}
inline void* ZoneAllocationPolicy::New(size_t size) {
DCHECK(zone_);
return zone_->New(static_cast<int>(size));
}
template <typename T>
void* ZoneList<T>::operator new(size_t size, Zone* zone) {
return zone->New(static_cast<int>(size));
}
template <typename T>
void* ZoneSplayTree<T>::operator new(size_t size, Zone* zone) {
return zone->New(static_cast<int>(size));
}
} } // namespace v8::internal
#endif // V8_ZONE_INL_H_

View File

@ -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 <string.h>
#include "src/zone.h"
#include "src/v8.h"
#include "src/zone-inl.h"
#include <cstring>
#ifdef V8_USE_ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#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<Segment*>(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_t>(size) ||
new_size < static_cast<size_t>(kSegmentOverhead)) {
V8::FatalProcessOutOfMemory("Zone");
return NULL;
FatalProcessOutOfMemory("Zone");
return nullptr;
}
if (new_size < static_cast<size_t>(kMinimumSegmentSize)) {
new_size = kMinimumSegmentSize;
@ -229,13 +250,13 @@ Address Zone::NewExpand(int size) {
new_size = Max(min_new_size, static_cast<size_t>(kMaximumSegmentSize));
}
if (new_size > INT_MAX) {
V8::FatalProcessOutOfMemory("Zone");
return NULL;
FatalProcessOutOfMemory("Zone");
return nullptr;
}
Segment* segment = NewSegment(static_cast<int>(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<uintptr_t>(position_)
< reinterpret_cast<uintptr_t>(result)) {
V8::FatalProcessOutOfMemory("Zone");
return NULL;
}
DCHECK_GE(reinterpret_cast<uintptr_t>(position_),
reinterpret_cast<uintptr_t>(result));
limit_ = segment->end();
DCHECK(position_ <= limit_);
return result;
}
} } // namespace v8::internal
} // namespace internal
} // namespace v8

View File

@ -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 <typename T>
T* NewArray(int length) {
CHECK(std::numeric_limits<int>::max() / static_cast<int>(sizeof(T)) >
length);
DCHECK(std::numeric_limits<int>::max() / static_cast<int>(sizeof(T)) >
length);
return static_cast<T*>(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<int>(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<int>(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<typename T>
class ZoneList: public List<T, ZoneAllocationPolicy> {
template <typename T>
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.
ZoneList(int capacity, Zone* zone)
: List<T, ZoneAllocationPolicy>(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<int>(size));
}
// Construct a new ZoneList by copying the elements of the given ZoneList.
ZoneList(const ZoneList<T>& other, Zone* zone)
@ -192,27 +194,27 @@ class ZoneList: public List<T, ZoneAllocationPolicy> {
// 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<T, ZoneAllocationPolicy>::Add(element, ZoneAllocationPolicy(zone));
}
INLINE(void AddAll(const List<T, ZoneAllocationPolicy>& other, Zone* zone)) {
void AddAll(const List<T, ZoneAllocationPolicy>& other, Zone* zone) {
List<T, ZoneAllocationPolicy>::AddAll(other, ZoneAllocationPolicy(zone));
}
INLINE(void AddAll(const Vector<T>& other, Zone* zone)) {
void AddAll(const Vector<T>& other, Zone* zone) {
List<T, ZoneAllocationPolicy>::AddAll(other, ZoneAllocationPolicy(zone));
}
INLINE(void InsertAt(int index, const T& element, Zone* zone)) {
void InsertAt(int index, const T& element, Zone* zone) {
List<T, ZoneAllocationPolicy>::InsertAt(index, element,
ZoneAllocationPolicy(zone));
}
INLINE(Vector<T> AddBlock(T value, int count, Zone* zone)) {
Vector<T> AddBlock(T value, int count, Zone* zone) {
return List<T, ZoneAllocationPolicy>::AddBlock(value, count,
ZoneAllocationPolicy(zone));
}
INLINE(void Allocate(int length, Zone* zone)) {
void Allocate(int length, Zone* zone) {
List<T, ZoneAllocationPolicy>::Allocate(length, ZoneAllocationPolicy(zone));
}
INLINE(void Initialize(int capacity, Zone* zone)) {
void Initialize(int capacity, Zone* zone) {
List<T, ZoneAllocationPolicy>::Initialize(capacity,
ZoneAllocationPolicy(zone));
}
@ -226,13 +228,20 @@ class ZoneList: public List<T, ZoneAllocationPolicy> {
// different configurations of a concrete splay tree (see splay-tree.h).
// The tree itself and all its elements are allocated in the Zone.
template <typename Config>
class ZoneSplayTree: public SplayTree<Config, ZoneAllocationPolicy> {
class ZoneSplayTree FINAL : public SplayTree<Config, ZoneAllocationPolicy> {
public:
explicit ZoneSplayTree(Zone* zone)
: SplayTree<Config, ZoneAllocationPolicy>(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<Config, ZoneAllocationPolicy>::ResetRoot();
}
INLINE(void* operator new(size_t size, Zone* zone));
void* operator new(size_t size, Zone* zone) {
return zone->New(static_cast<int>(size));
}
void operator delete(void* pointer) { UNREACHABLE(); }
void operator delete(void* pointer, Zone* zone) { UNREACHABLE(); }
@ -241,6 +250,7 @@ class ZoneSplayTree: public SplayTree<Config, ZoneAllocationPolicy> {
typedef TemplateHashMapImpl<ZoneAllocationPolicy> ZoneHashMap;
} } // namespace v8::internal
} // namespace internal
} // namespace v8
#endif // V8_ZONE_H_

View File

@ -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

View File

@ -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',