[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 kExternalOneByteRepresentationTag = 0x06;
static const int kIsolateEmbedderDataOffset = 0 * kApiPointerSize; static const int kIsolateEmbedderDataOffset = 0 * kApiPointerSize;
static const int kAmountOfExternalAllocatedMemoryOffset = static const int kExternalMemoryOffset = 4 * kApiPointerSize;
4 * kApiPointerSize; static const int kExternalMemoryLimitOffset =
static const int kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset = kExternalMemoryOffset + kApiInt64Size;
kAmountOfExternalAllocatedMemoryOffset + kApiInt64Size; static const int kIsolateRootsOffset = kExternalMemoryLimitOffset +
static const int kIsolateRootsOffset = kApiInt64Size + kApiInt64Size +
kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset + kApiInt64Size + kApiPointerSize + kApiPointerSize;
kApiPointerSize + kApiPointerSize;
static const int kUndefinedValueRootIndex = 4; static const int kUndefinedValueRootIndex = 4;
static const int kTheHoleValueRootIndex = 5; static const int kTheHoleValueRootIndex = 5;
static const int kNullValueRootIndex = 6; static const int kNullValueRootIndex = 6;
@ -7507,10 +7506,6 @@ class Internals {
static const int kFalseValueRootIndex = 8; static const int kFalseValueRootIndex = 8;
static const int kEmptyStringRootIndex = 9; 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 kNodeClassIdOffset = 1 * kApiPointerSize;
static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3; static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
static const int kNodeStateMask = 0x7; static const int kNodeStateMask = 0x7;
@ -8705,21 +8700,16 @@ uint32_t Isolate::GetNumberOfDataSlots() {
int64_t Isolate::AdjustAmountOfExternalAllocatedMemory( int64_t Isolate::AdjustAmountOfExternalAllocatedMemory(
int64_t change_in_bytes) { int64_t change_in_bytes) {
typedef internal::Internals I; typedef internal::Internals I;
int64_t* amount_of_external_allocated_memory = int64_t* external_memory = reinterpret_cast<int64_t*>(
reinterpret_cast<int64_t*>(reinterpret_cast<uint8_t*>(this) + reinterpret_cast<uint8_t*>(this) + I::kExternalMemoryOffset);
I::kAmountOfExternalAllocatedMemoryOffset); const int64_t external_memory_limit = *reinterpret_cast<int64_t*>(
int64_t* amount_of_external_allocated_memory_at_last_global_gc = reinterpret_cast<uint8_t*>(this) + I::kExternalMemoryLimitOffset);
reinterpret_cast<int64_t*>( const int64_t amount = *external_memory + change_in_bytes;
reinterpret_cast<uint8_t*>(this) + *external_memory = amount;
I::kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset); if (change_in_bytes > 0 && amount > external_memory_limit) {
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) {
ReportExternalAllocationLimitReached(); ReportExternalAllocationLimitReached();
} }
*amount_of_external_allocated_memory = amount; return *external_memory;
return *amount_of_external_allocated_memory;
} }

View File

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

View File

@ -182,6 +182,10 @@ const size_t kCodeRangeAreaAlignment = 4 * KB; // OS page.
#endif #endif
#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)); STATIC_ASSERT(kPointerSize == (1 << kPointerSizeLog2));
const int kBitsPerByte = 8; const int kBitsPerByte = 8;

View File

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

View File

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

View File

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

View File

@ -821,22 +821,16 @@ class Heap {
global_ic_age_ = (global_ic_age_ + 1) & SharedFunctionInfo::ICAgeBits::kMax; global_ic_age_ = (global_ic_age_ + 1) & SharedFunctionInfo::ICAgeBits::kMax;
} }
int64_t amount_of_external_allocated_memory() { int64_t external_memory() { return external_memory_; }
return amount_of_external_allocated_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) { void account_external_memory_concurrently_freed() {
amount_of_external_allocated_memory_ += delta; external_memory_ -= external_memory_concurrently_freed_.Value();
} external_memory_concurrently_freed_.SetValue(0);
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 DeoptMarkedAllocationSites(); void DeoptMarkedAllocationSites();
@ -1997,14 +1991,17 @@ class Heap {
void set_force_oom(bool value) { force_oom_ = value; } void set_force_oom(bool value) { force_oom_ = value; }
// The amount of external memory registered through the API kept alive // The amount of external memory registered through the API.
// by global handles int64_t external_memory_;
int64_t amount_of_external_allocated_memory_;
// Caches the amount of external memory registered at the last global gc. // The limit when to trigger memory pressure from the API.
int64_t amount_of_external_allocated_memory_at_last_global_gc_; 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 // 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. // 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 = spaces.next()) {
space->PrepareForMarkCompact(); space->PrepareForMarkCompact();
} }
heap()->account_amount_of_external_allocated_freed_memory(); heap()->account_external_memory_concurrently_freed();
#ifdef VERIFY_HEAP #ifdef VERIFY_HEAP
if (!was_marked_incrementally_ && FLAG_verify_heap) { if (!was_marked_incrementally_ && FLAG_verify_heap) {

View File

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

View File

@ -6717,7 +6717,7 @@ TEST(Regress618958) {
v8::HandleScope scope(CcTest::isolate()); v8::HandleScope scope(CcTest::isolate());
Heap* heap = CcTest::heap(); Heap* heap = CcTest::heap();
bool isolate_is_locked = true; 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(); int mark_sweep_count_before = heap->ms_count();
heap->MemoryPressureNotification(MemoryPressureLevel::kCritical, heap->MemoryPressureNotification(MemoryPressureLevel::kCritical,
isolate_is_locked); isolate_is_locked);

View File

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