[heap] Internalize kExternalAllocationLimit

Base the fast-path in AdjustAmountOfExternalMemory on a value + limit. To
preserve the behavior the limit is just set using kExternalAllocationLimit.

Redo naming of related members.

R=jochen@chromium.org
BUG=chromium:621829
LOG=N

Review-Url: https://codereview.chromium.org/2085893002
Cr-Commit-Position: refs/heads/master@{#37131}
This commit is contained in:
mlippautz 2016-06-21 02:25:08 -07:00 committed by Commit bot
parent f0dc0dbf21
commit 706b3f2730
11 changed files with 59 additions and 78 deletions

View File

@ -7493,13 +7493,12 @@ class Internals {
static const int kExternalOneByteRepresentationTag = 0x06;
static const int kIsolateEmbedderDataOffset = 0 * kApiPointerSize;
static const int kAmountOfExternalAllocatedMemoryOffset =
4 * kApiPointerSize;
static const int kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset =
kAmountOfExternalAllocatedMemoryOffset + kApiInt64Size;
static const int kIsolateRootsOffset =
kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset + kApiInt64Size +
kApiPointerSize + kApiPointerSize;
static const int kExternalMemoryOffset = 4 * kApiPointerSize;
static const int kExternalMemoryLimitOffset =
kExternalMemoryOffset + kApiInt64Size;
static const int kIsolateRootsOffset = kExternalMemoryLimitOffset +
kApiInt64Size + kApiInt64Size +
kApiPointerSize + kApiPointerSize;
static const int kUndefinedValueRootIndex = 4;
static const int kTheHoleValueRootIndex = 5;
static const int kNullValueRootIndex = 6;
@ -7507,10 +7506,6 @@ class Internals {
static const int kFalseValueRootIndex = 8;
static const int kEmptyStringRootIndex = 9;
// The external allocation limit should be below 256 MB on all architectures
// to avoid that resource-constrained embedders run low on memory.
static const int kExternalAllocationLimit = 192 * 1024 * 1024;
static const int kNodeClassIdOffset = 1 * kApiPointerSize;
static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
static const int kNodeStateMask = 0x7;
@ -8705,21 +8700,16 @@ uint32_t Isolate::GetNumberOfDataSlots() {
int64_t Isolate::AdjustAmountOfExternalAllocatedMemory(
int64_t change_in_bytes) {
typedef internal::Internals I;
int64_t* amount_of_external_allocated_memory =
reinterpret_cast<int64_t*>(reinterpret_cast<uint8_t*>(this) +
I::kAmountOfExternalAllocatedMemoryOffset);
int64_t* amount_of_external_allocated_memory_at_last_global_gc =
reinterpret_cast<int64_t*>(
reinterpret_cast<uint8_t*>(this) +
I::kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset);
int64_t amount = *amount_of_external_allocated_memory + change_in_bytes;
if (change_in_bytes > 0 &&
amount - *amount_of_external_allocated_memory_at_last_global_gc >
I::kExternalAllocationLimit) {
int64_t* external_memory = reinterpret_cast<int64_t*>(
reinterpret_cast<uint8_t*>(this) + I::kExternalMemoryOffset);
const int64_t external_memory_limit = *reinterpret_cast<int64_t*>(
reinterpret_cast<uint8_t*>(this) + I::kExternalMemoryLimitOffset);
const int64_t amount = *external_memory + change_in_bytes;
*external_memory = amount;
if (change_in_bytes > 0 && amount > external_memory_limit) {
ReportExternalAllocationLimitReached();
}
*amount_of_external_allocated_memory = amount;
return *amount_of_external_allocated_memory;
return *external_memory;
}

View File

@ -135,8 +135,7 @@ void StatisticsExtension::GetCounters(
AddNumber(args.GetIsolate(), result, numbers[i].number, numbers[i].name);
}
AddNumber64(args.GetIsolate(), result,
heap->amount_of_external_allocated_memory(),
AddNumber64(args.GetIsolate(), result, heap->external_memory(),
"amount_of_external_allocated_memory");
args.GetReturnValue().Set(result);
}

View File

@ -182,6 +182,10 @@ const size_t kCodeRangeAreaAlignment = 4 * KB; // OS page.
#endif
#endif
// The external allocation limit should be below 256 MB on all architectures
// to avoid that resource-constrained embedders run low on memory.
const int kExternalAllocationLimit = 192 * 1024 * 1024;
STATIC_ASSERT(kPointerSize == (1 << kPointerSizeLog2));
const int kBitsPerByte = 8;

View File

@ -44,8 +44,7 @@ void ArrayBufferTracker::Unregister(Heap* heap, JSArrayBuffer* buffer) {
DCHECK_NOT_NULL(tracker);
length = tracker->Remove(buffer).second;
}
heap->update_amount_of_external_allocated_memory(
-static_cast<intptr_t>(length));
heap->update_external_memory(-static_cast<intptr_t>(length));
}
void LocalArrayBufferTracker::Add(Key key, const Value& value) {

View File

@ -29,7 +29,7 @@ void LocalArrayBufferTracker::Free() {
}
}
if (freed_memory > 0) {
heap_->update_amount_of_external_allocated_freed_memory(
heap_->update_external_memory_concurrently_freed(
static_cast<intptr_t>(freed_memory));
}
}
@ -68,7 +68,7 @@ void LocalArrayBufferTracker::Process(Callback callback) {
}
}
if (freed_memory > 0) {
heap_->update_amount_of_external_allocated_freed_memory(
heap_->update_external_memory_concurrently_freed(
static_cast<intptr_t>(freed_memory));
}
}
@ -82,7 +82,7 @@ void ArrayBufferTracker::FreeDeadInNewSpace(Heap* heap) {
bool empty = ProcessBuffers(page, kUpdateForwardedRemoveOthers);
CHECK(empty);
}
heap->account_amount_of_external_allocated_freed_memory();
heap->account_external_memory_concurrently_freed();
}
void ArrayBufferTracker::FreeDead(Page* page) {

View File

@ -68,8 +68,9 @@ class IdleScavengeObserver : public AllocationObserver {
};
Heap::Heap()
: amount_of_external_allocated_memory_(0),
amount_of_external_allocated_memory_at_last_global_gc_(0),
: external_memory_(0),
external_memory_limit_(kExternalAllocationLimit),
external_memory_at_last_mark_compact_(0),
isolate_(nullptr),
code_range_size_(0),
// semispace_size_ should be a power of 2 and old_generation_size_ should
@ -383,9 +384,8 @@ void Heap::PrintShortHeapStatistics() {
", committed: %6" V8PRIdPTR " KB\n",
this->SizeOfObjects() / KB, this->Available() / KB,
this->CommittedMemory() / KB);
PrintIsolate(
isolate_, "External memory reported: %6" V8PRIdPTR " KB\n",
static_cast<intptr_t>(amount_of_external_allocated_memory_ / KB));
PrintIsolate(isolate_, "External memory reported: %6" V8PRIdPTR " KB\n",
static_cast<intptr_t>(external_memory_ / KB));
PrintIsolate(isolate_, "Total time spent in GC : %.1f ms\n",
total_gc_time_ms_);
}
@ -1339,8 +1339,8 @@ bool Heap::PerformGarbageCollection(
intptr_t old_gen_size = PromotedSpaceSizeOfObjects();
if (collector == MARK_COMPACTOR) {
// Register the amount of external allocated memory.
amount_of_external_allocated_memory_at_last_global_gc_ =
amount_of_external_allocated_memory_;
external_memory_at_last_mark_compact_ = external_memory_;
external_memory_limit_ = external_memory_ + kExternalAllocationLimit;
SetOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed);
} else if (HasLowYoungGenerationAllocationRate() &&
old_generation_size_configured_) {
@ -4425,8 +4425,8 @@ void Heap::CollectGarbageOnMemoryPressure(const char* source) {
double end = MonotonicallyIncreasingTimeInMs();
// Estimate how much memory we can free.
int64_t potential_garbage = (CommittedMemory() - SizeOfObjects()) +
amount_of_external_allocated_memory_;
int64_t potential_garbage =
(CommittedMemory() - SizeOfObjects()) + external_memory_;
// If we can potentially free large amount of memory, then start GC right
// away instead of waiting for memory reducer.
if (potential_garbage >= kGarbageThresholdInBytes &&
@ -5048,11 +5048,8 @@ intptr_t Heap::PromotedSpaceSizeOfObjects() {
int64_t Heap::PromotedExternalMemorySize() {
if (amount_of_external_allocated_memory_ <=
amount_of_external_allocated_memory_at_last_global_gc_)
return 0;
return amount_of_external_allocated_memory_ -
amount_of_external_allocated_memory_at_last_global_gc_;
if (external_memory_ <= external_memory_at_last_mark_compact_) return 0;
return external_memory_ - external_memory_at_last_mark_compact_;
}

View File

@ -821,22 +821,16 @@ class Heap {
global_ic_age_ = (global_ic_age_ + 1) & SharedFunctionInfo::ICAgeBits::kMax;
}
int64_t amount_of_external_allocated_memory() {
return amount_of_external_allocated_memory_;
int64_t external_memory() { return external_memory_; }
void update_external_memory(int64_t delta) { external_memory_ += delta; }
void update_external_memory_concurrently_freed(intptr_t freed) {
external_memory_concurrently_freed_.Increment(freed);
}
void update_amount_of_external_allocated_memory(int64_t delta) {
amount_of_external_allocated_memory_ += delta;
}
void update_amount_of_external_allocated_freed_memory(intptr_t freed) {
amount_of_external_allocated_memory_freed_.Increment(freed);
}
void account_amount_of_external_allocated_freed_memory() {
amount_of_external_allocated_memory_ -=
amount_of_external_allocated_memory_freed_.Value();
amount_of_external_allocated_memory_freed_.SetValue(0);
void account_external_memory_concurrently_freed() {
external_memory_ -= external_memory_concurrently_freed_.Value();
external_memory_concurrently_freed_.SetValue(0);
}
void DeoptMarkedAllocationSites();
@ -1997,14 +1991,17 @@ class Heap {
void set_force_oom(bool value) { force_oom_ = value; }
// The amount of external memory registered through the API kept alive
// by global handles
int64_t amount_of_external_allocated_memory_;
// The amount of external memory registered through the API.
int64_t external_memory_;
// Caches the amount of external memory registered at the last global gc.
int64_t amount_of_external_allocated_memory_at_last_global_gc_;
// The limit when to trigger memory pressure from the API.
int64_t external_memory_limit_;
base::AtomicNumber<intptr_t> amount_of_external_allocated_memory_freed_;
// Caches the amount of external memory registered at the last MC.
int64_t external_memory_at_last_mark_compact_;
// The amount of memory that has been freed concurrently.
base::AtomicNumber<intptr_t> external_memory_concurrently_freed_;
// This can be calculated directly from a pointer to the heap; however, it is
// more expedient to get at the isolate directly from within Heap methods.

View File

@ -898,7 +898,7 @@ void MarkCompactCollector::Prepare() {
space = spaces.next()) {
space->PrepareForMarkCompact();
}
heap()->account_amount_of_external_allocated_freed_memory();
heap()->account_external_memory_concurrently_freed();
#ifdef VERIFY_HEAP
if (!was_marked_incrementally_ && FLAG_verify_heap) {

View File

@ -2312,13 +2312,10 @@ bool Isolate::Init(Deserializer* des) {
Internals::kIsolateEmbedderDataOffset);
CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.roots_)),
Internals::kIsolateRootsOffset);
CHECK_EQ(static_cast<int>(
OFFSET_OF(Isolate, heap_.amount_of_external_allocated_memory_)),
Internals::kAmountOfExternalAllocatedMemoryOffset);
CHECK_EQ(static_cast<int>(OFFSET_OF(
Isolate,
heap_.amount_of_external_allocated_memory_at_last_global_gc_)),
Internals::kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset);
CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.external_memory_)),
Internals::kExternalMemoryOffset);
CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.external_memory_limit_)),
Internals::kExternalMemoryLimitOffset);
time_millis_at_init_ = heap_.MonotonicallyIncreasingTimeInMs();

View File

@ -6717,7 +6717,7 @@ TEST(Regress618958) {
v8::HandleScope scope(CcTest::isolate());
Heap* heap = CcTest::heap();
bool isolate_is_locked = true;
heap->update_amount_of_external_allocated_memory(100 * MB);
heap->update_external_memory(100 * MB);
int mark_sweep_count_before = heap->ms_count();
heap->MemoryPressureNotification(MemoryPressureLevel::kCritical,
isolate_is_locked);

View File

@ -14853,8 +14853,7 @@ THREADED_TEST(ExternalAllocatedMemory) {
isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
CHECK_EQ(baseline,
isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
const int64_t kTriggerGCSize =
v8::internal::Internals::kExternalAllocationLimit + 1;
const int64_t kTriggerGCSize = i::kExternalAllocationLimit + 1;
CHECK_EQ(baseline + kTriggerGCSize,
isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
CHECK_EQ(baseline,
@ -14866,8 +14865,7 @@ TEST(Regress51719) {
i::FLAG_incremental_marking = false;
CcTest::InitializeVM();
const int64_t kTriggerGCSize =
v8::internal::Internals::kExternalAllocationLimit + 1;
const int64_t kTriggerGCSize = i::kExternalAllocationLimit + 1;
v8::Isolate* isolate = CcTest::isolate();
isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
}