| Index: src/heap.cc
|
| diff --git a/src/heap.cc b/src/heap.cc
|
| index c5c2c67cfdb2ee200d7a1b4c6247b59563640191..ac2504f9b571f6e5cca8fb1878b2219f4a25119b 100644
|
| --- a/src/heap.cc
|
| +++ b/src/heap.cc
|
| @@ -105,6 +105,7 @@ Heap::Heap()
|
| code_space_(NULL),
|
| map_space_(NULL),
|
| cell_space_(NULL),
|
| + property_cell_space_(NULL),
|
| lo_space_(NULL),
|
| gc_state_(NOT_IN_GC),
|
| gc_post_processing_depth_(0),
|
| @@ -151,7 +152,6 @@ Heap::Heap()
|
| last_idle_notification_gc_count_(0),
|
| last_idle_notification_gc_count_init_(false),
|
| mark_sweeps_since_idle_round_started_(0),
|
| - ms_count_at_last_idle_notification_(0),
|
| gc_count_at_last_idle_gc_(0),
|
| scavenges_since_last_idle_round_(kIdleScavengeThreshold),
|
| gcs_since_last_deopt_(0),
|
| @@ -199,7 +199,8 @@ intptr_t Heap::Capacity() {
|
| old_data_space_->Capacity() +
|
| code_space_->Capacity() +
|
| map_space_->Capacity() +
|
| - cell_space_->Capacity();
|
| + cell_space_->Capacity() +
|
| + property_cell_space_->Capacity();
|
| }
|
|
|
|
|
| @@ -212,6 +213,7 @@ intptr_t Heap::CommittedMemory() {
|
| code_space_->CommittedMemory() +
|
| map_space_->CommittedMemory() +
|
| cell_space_->CommittedMemory() +
|
| + property_cell_space_->CommittedMemory() +
|
| lo_space_->Size();
|
| }
|
|
|
| @@ -225,6 +227,7 @@ size_t Heap::CommittedPhysicalMemory() {
|
| code_space_->CommittedPhysicalMemory() +
|
| map_space_->CommittedPhysicalMemory() +
|
| cell_space_->CommittedPhysicalMemory() +
|
| + property_cell_space_->CommittedPhysicalMemory() +
|
| lo_space_->CommittedPhysicalMemory();
|
| }
|
|
|
| @@ -244,7 +247,8 @@ intptr_t Heap::Available() {
|
| old_data_space_->Available() +
|
| code_space_->Available() +
|
| map_space_->Available() +
|
| - cell_space_->Available();
|
| + cell_space_->Available() +
|
| + property_cell_space_->Available();
|
| }
|
|
|
|
|
| @@ -254,6 +258,7 @@ bool Heap::HasBeenSetUp() {
|
| code_space_ != NULL &&
|
| map_space_ != NULL &&
|
| cell_space_ != NULL &&
|
| + property_cell_space_ != NULL &&
|
| lo_space_ != NULL;
|
| }
|
|
|
| @@ -383,6 +388,12 @@ void Heap::PrintShortHeapStatistics() {
|
| cell_space_->SizeOfObjects() / KB,
|
| cell_space_->Available() / KB,
|
| cell_space_->CommittedMemory() / KB);
|
| + PrintPID("PropertyCell space, used: %6" V8_PTR_PREFIX "d KB"
|
| + ", available: %6" V8_PTR_PREFIX "d KB"
|
| + ", committed: %6" V8_PTR_PREFIX "d KB\n",
|
| + property_cell_space_->SizeOfObjects() / KB,
|
| + property_cell_space_->Available() / KB,
|
| + property_cell_space_->CommittedMemory() / KB);
|
| PrintPID("Large object space, used: %6" V8_PTR_PREFIX "d KB"
|
| ", available: %6" V8_PTR_PREFIX "d KB"
|
| ", committed: %6" V8_PTR_PREFIX "d KB\n",
|
| @@ -395,6 +406,8 @@ void Heap::PrintShortHeapStatistics() {
|
| this->SizeOfObjects() / KB,
|
| this->Available() / KB,
|
| this->CommittedMemory() / KB);
|
| + PrintPID("External memory reported: %6" V8_PTR_PREFIX "d KB\n",
|
| + amount_of_external_allocated_memory_ / KB);
|
| PrintPID("Total time spent in GC : %.1f ms\n", total_gc_time_ms_);
|
| }
|
|
|
| @@ -514,6 +527,10 @@ void Heap::GarbageCollectionEpilogue() {
|
| isolate_->counters()->heap_fraction_cell_space()->AddSample(
|
| static_cast<int>(
|
| (cell_space()->CommittedMemory() * 100.0) / CommittedMemory()));
|
| + isolate_->counters()->heap_fraction_property_cell_space()->
|
| + AddSample(static_cast<int>(
|
| + (property_cell_space()->CommittedMemory() * 100.0) /
|
| + CommittedMemory()));
|
|
|
| isolate_->counters()->heap_sample_total_committed()->AddSample(
|
| static_cast<int>(CommittedMemory() / KB));
|
| @@ -523,6 +540,10 @@ void Heap::GarbageCollectionEpilogue() {
|
| static_cast<int>(map_space()->CommittedMemory() / KB));
|
| isolate_->counters()->heap_sample_cell_space_committed()->AddSample(
|
| static_cast<int>(cell_space()->CommittedMemory() / KB));
|
| + isolate_->counters()->
|
| + heap_sample_property_cell_space_committed()->
|
| + AddSample(static_cast<int>(
|
| + property_cell_space()->CommittedMemory() / KB));
|
| }
|
|
|
| #define UPDATE_COUNTERS_FOR_SPACE(space) \
|
| @@ -548,6 +569,7 @@ void Heap::GarbageCollectionEpilogue() {
|
| UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(code_space)
|
| UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(map_space)
|
| UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(cell_space)
|
| + UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(property_cell_space)
|
| UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(lo_space)
|
| #undef UPDATE_COUNTERS_FOR_SPACE
|
| #undef UPDATE_FRAGMENTATION_FOR_SPACE
|
| @@ -1212,7 +1234,7 @@ void StoreBufferRebuilder::Callback(MemoryChunk* page, StoreBufferEvent event) {
|
| // Store Buffer overflowed while scanning promoted objects. These are not
|
| // in any particular page, though they are likely to be clustered by the
|
| // allocation routines.
|
| - store_buffer_->EnsureSpace(StoreBuffer::kStoreBufferSize);
|
| + store_buffer_->EnsureSpace(StoreBuffer::kStoreBufferSize / 2);
|
| } else {
|
| // Store Buffer overflowed while scanning a particular old space page for
|
| // pointers to new space.
|
| @@ -1353,15 +1375,31 @@ void Heap::Scavenge() {
|
| store_buffer()->IteratePointersToNewSpace(&ScavengeObject);
|
| }
|
|
|
| - // Copy objects reachable from cells by scavenging cell values directly.
|
| + // Copy objects reachable from simple cells by scavenging cell values
|
| + // directly.
|
| HeapObjectIterator cell_iterator(cell_space_);
|
| for (HeapObject* heap_object = cell_iterator.Next();
|
| heap_object != NULL;
|
| heap_object = cell_iterator.Next()) {
|
| - if (heap_object->IsJSGlobalPropertyCell()) {
|
| - JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(heap_object);
|
| + if (heap_object->IsCell()) {
|
| + Cell* cell = Cell::cast(heap_object);
|
| + Address value_address = cell->ValueAddress();
|
| + scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
|
| + }
|
| + }
|
| +
|
| + // Copy objects reachable from global property cells by scavenging global
|
| + // property cell values directly.
|
| + HeapObjectIterator js_global_property_cell_iterator(property_cell_space_);
|
| + for (HeapObject* heap_object = js_global_property_cell_iterator.Next();
|
| + heap_object != NULL;
|
| + heap_object = js_global_property_cell_iterator.Next()) {
|
| + if (heap_object->IsPropertyCell()) {
|
| + PropertyCell* cell = PropertyCell::cast(heap_object);
|
| Address value_address = cell->ValueAddress();
|
| scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
|
| + Address type_address = cell->TypeAddress();
|
| + scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(type_address));
|
| }
|
| }
|
|
|
| @@ -2634,8 +2672,13 @@ bool Heap::CreateInitialMaps() {
|
| }
|
| set_code_map(Map::cast(obj));
|
|
|
| - { MaybeObject* maybe_obj = AllocateMap(JS_GLOBAL_PROPERTY_CELL_TYPE,
|
| - JSGlobalPropertyCell::kSize);
|
| + { MaybeObject* maybe_obj = AllocateMap(CELL_TYPE, Cell::kSize);
|
| + if (!maybe_obj->ToObject(&obj)) return false;
|
| + }
|
| + set_cell_map(Map::cast(obj));
|
| +
|
| + { MaybeObject* maybe_obj = AllocateMap(PROPERTY_CELL_TYPE,
|
| + PropertyCell::kSize);
|
| if (!maybe_obj->ToObject(&obj)) return false;
|
| }
|
| set_global_property_cell_map(Map::cast(obj));
|
| @@ -2769,14 +2812,26 @@ MaybeObject* Heap::AllocateHeapNumber(double value) {
|
| }
|
|
|
|
|
| -MaybeObject* Heap::AllocateJSGlobalPropertyCell(Object* value) {
|
| +MaybeObject* Heap::AllocateCell(Object* value) {
|
| Object* result;
|
| { MaybeObject* maybe_result = AllocateRawCell();
|
| if (!maybe_result->ToObject(&result)) return maybe_result;
|
| }
|
| + HeapObject::cast(result)->set_map_no_write_barrier(cell_map());
|
| + Cell::cast(result)->set_value(value);
|
| + return result;
|
| +}
|
| +
|
| +
|
| +MaybeObject* Heap::AllocatePropertyCell(Object* value) {
|
| + Object* result;
|
| + { MaybeObject* maybe_result = AllocateRawPropertyCell();
|
| + if (!maybe_result->ToObject(&result)) return maybe_result;
|
| + }
|
| HeapObject::cast(result)->set_map_no_write_barrier(
|
| global_property_cell_map());
|
| - JSGlobalPropertyCell::cast(result)->set_value(value);
|
| + PropertyCell::cast(result)->set_value(value);
|
| + PropertyCell::cast(result)->set_type(Type::None());
|
| return result;
|
| }
|
|
|
| @@ -4445,8 +4500,7 @@ MaybeObject* Heap::AllocateJSObjectWithAllocationSite(JSFunction* constructor,
|
| // advice
|
| Map* initial_map = constructor->initial_map();
|
|
|
| - JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(
|
| - *allocation_site_info_payload);
|
| + Cell* cell = Cell::cast(*allocation_site_info_payload);
|
| Smi* smi = Smi::cast(cell->value());
|
| ElementsKind to_kind = static_cast<ElementsKind>(smi->value());
|
| AllocationSiteMode mode = TRACK_ALLOCATION_SITE;
|
| @@ -4675,7 +4729,7 @@ MaybeObject* Heap::AllocateGlobalObject(JSFunction* constructor) {
|
|
|
| // Make sure no field properties are described in the initial map.
|
| // This guarantees us that normalizing the properties does not
|
| - // require us to change property values to JSGlobalPropertyCells.
|
| + // require us to change property values to PropertyCells.
|
| ASSERT(map->NextFreePropertyIndex() == 0);
|
|
|
| // Make sure we don't have a ton of pre-allocated slots in the
|
| @@ -4704,7 +4758,7 @@ MaybeObject* Heap::AllocateGlobalObject(JSFunction* constructor) {
|
| ASSERT(details.type() == CALLBACKS); // Only accessors are expected.
|
| PropertyDetails d = PropertyDetails(details.attributes(), CALLBACKS, i + 1);
|
| Object* value = descs->GetCallbacksObject(i);
|
| - MaybeObject* maybe_value = AllocateJSGlobalPropertyCell(value);
|
| + MaybeObject* maybe_value = AllocatePropertyCell(value);
|
| if (!maybe_value->ToObject(&value)) return maybe_value;
|
|
|
| MaybeObject* maybe_added = dictionary->Add(descs->GetKey(i), value, d);
|
| @@ -5809,6 +5863,7 @@ void Heap::AdvanceIdleIncrementalMarking(intptr_t step_size) {
|
| uncommit = true;
|
| }
|
| CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental");
|
| + mark_sweeps_since_idle_round_started_++;
|
| gc_count_at_last_idle_gc_ = gc_count_;
|
| if (uncommit) {
|
| new_space_.Shrink();
|
| @@ -5822,6 +5877,7 @@ bool Heap::IdleNotification(int hint) {
|
| // Hints greater than this value indicate that
|
| // the embedder is requesting a lot of GC work.
|
| const int kMaxHint = 1000;
|
| + const int kMinHintForIncrementalMarking = 10;
|
| // Minimal hint that allows to do full GC.
|
| const int kMinHintForFullGC = 100;
|
| intptr_t size_factor = Min(Max(hint, 20), kMaxHint) / 4;
|
| @@ -5884,18 +5940,9 @@ bool Heap::IdleNotification(int hint) {
|
| }
|
| }
|
|
|
| - int new_mark_sweeps = ms_count_ - ms_count_at_last_idle_notification_;
|
| - mark_sweeps_since_idle_round_started_ += new_mark_sweeps;
|
| - ms_count_at_last_idle_notification_ = ms_count_;
|
| -
|
| int remaining_mark_sweeps = kMaxMarkSweepsInIdleRound -
|
| mark_sweeps_since_idle_round_started_;
|
|
|
| - if (remaining_mark_sweeps <= 0) {
|
| - FinishIdleRound();
|
| - return true;
|
| - }
|
| -
|
| if (incremental_marking()->IsStopped()) {
|
| // If there are no more than two GCs left in this idle round and we are
|
| // allowed to do a full GC, then make those GCs full in order to compact
|
| @@ -5905,13 +5952,21 @@ bool Heap::IdleNotification(int hint) {
|
| if (remaining_mark_sweeps <= 2 && hint >= kMinHintForFullGC) {
|
| CollectAllGarbage(kReduceMemoryFootprintMask,
|
| "idle notification: finalize idle round");
|
| - } else {
|
| + mark_sweeps_since_idle_round_started_++;
|
| + } else if (hint > kMinHintForIncrementalMarking) {
|
| incremental_marking()->Start();
|
| }
|
| }
|
| - if (!incremental_marking()->IsStopped()) {
|
| + if (!incremental_marking()->IsStopped() &&
|
| + hint > kMinHintForIncrementalMarking) {
|
| AdvanceIdleIncrementalMarking(step_size);
|
| }
|
| +
|
| + if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) {
|
| + FinishIdleRound();
|
| + return true;
|
| + }
|
| +
|
| return false;
|
| }
|
|
|
| @@ -6028,6 +6083,8 @@ void Heap::ReportHeapStatistics(const char* title) {
|
| map_space_->ReportStatistics();
|
| PrintF("Cell space : ");
|
| cell_space_->ReportStatistics();
|
| + PrintF("PropertyCell space : ");
|
| + property_cell_space_->ReportStatistics();
|
| PrintF("Large object space : ");
|
| lo_space_->ReportStatistics();
|
| PrintF(">>>>>> ========================================= >>>>>>\n");
|
| @@ -6049,6 +6106,7 @@ bool Heap::Contains(Address addr) {
|
| code_space_->Contains(addr) ||
|
| map_space_->Contains(addr) ||
|
| cell_space_->Contains(addr) ||
|
| + property_cell_space_->Contains(addr) ||
|
| lo_space_->SlowContains(addr));
|
| }
|
|
|
| @@ -6075,6 +6133,8 @@ bool Heap::InSpace(Address addr, AllocationSpace space) {
|
| return map_space_->Contains(addr);
|
| case CELL_SPACE:
|
| return cell_space_->Contains(addr);
|
| + case PROPERTY_CELL_SPACE:
|
| + return property_cell_space_->Contains(addr);
|
| case LO_SPACE:
|
| return lo_space_->SlowContains(addr);
|
| }
|
| @@ -6101,6 +6161,7 @@ void Heap::Verify() {
|
| old_data_space_->Verify(&no_dirty_regions_visitor);
|
| code_space_->Verify(&no_dirty_regions_visitor);
|
| cell_space_->Verify(&no_dirty_regions_visitor);
|
| + property_cell_space_->Verify(&no_dirty_regions_visitor);
|
|
|
| lo_space_->Verify();
|
| }
|
| @@ -6600,6 +6661,8 @@ void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
|
| *stats->map_space_capacity = map_space_->Capacity();
|
| *stats->cell_space_size = cell_space_->SizeOfObjects();
|
| *stats->cell_space_capacity = cell_space_->Capacity();
|
| + *stats->property_cell_space_size = property_cell_space_->SizeOfObjects();
|
| + *stats->property_cell_space_capacity = property_cell_space_->Capacity();
|
| *stats->lo_space_size = lo_space_->Size();
|
| isolate_->global_handles()->RecordStats(stats);
|
| *stats->memory_allocator_size = isolate()->memory_allocator()->Size();
|
| @@ -6628,6 +6691,7 @@ intptr_t Heap::PromotedSpaceSizeOfObjects() {
|
| + code_space_->SizeOfObjects()
|
| + map_space_->SizeOfObjects()
|
| + cell_space_->SizeOfObjects()
|
| + + property_cell_space_->SizeOfObjects()
|
| + lo_space_->SizeOfObjects();
|
| }
|
|
|
| @@ -6716,11 +6780,17 @@ bool Heap::SetUp() {
|
| if (map_space_ == NULL) return false;
|
| if (!map_space_->SetUp()) return false;
|
|
|
| - // Initialize global property cell space.
|
| + // Initialize simple cell space.
|
| cell_space_ = new CellSpace(this, max_old_generation_size_, CELL_SPACE);
|
| if (cell_space_ == NULL) return false;
|
| if (!cell_space_->SetUp()) return false;
|
|
|
| + // Initialize global property cell space.
|
| + property_cell_space_ = new PropertyCellSpace(this, max_old_generation_size_,
|
| + PROPERTY_CELL_SPACE);
|
| + if (property_cell_space_ == NULL) return false;
|
| + if (!property_cell_space_->SetUp()) return false;
|
| +
|
| // The large object code space may contain code or data. We set the memory
|
| // to be non-executable here for safety, but this means we need to enable it
|
| // explicitly when allocating large code objects.
|
| @@ -6842,6 +6912,12 @@ void Heap::TearDown() {
|
| cell_space_ = NULL;
|
| }
|
|
|
| + if (property_cell_space_ != NULL) {
|
| + property_cell_space_->TearDown();
|
| + delete property_cell_space_;
|
| + property_cell_space_ = NULL;
|
| + }
|
| +
|
| if (lo_space_ != NULL) {
|
| lo_space_->TearDown();
|
| delete lo_space_;
|
| @@ -6932,6 +7008,8 @@ Space* AllSpaces::next() {
|
| return heap_->map_space();
|
| case CELL_SPACE:
|
| return heap_->cell_space();
|
| + case PROPERTY_CELL_SPACE:
|
| + return heap_->property_cell_space();
|
| case LO_SPACE:
|
| return heap_->lo_space();
|
| default:
|
| @@ -6952,6 +7030,8 @@ PagedSpace* PagedSpaces::next() {
|
| return heap_->map_space();
|
| case CELL_SPACE:
|
| return heap_->cell_space();
|
| + case PROPERTY_CELL_SPACE:
|
| + return heap_->property_cell_space();
|
| default:
|
| return NULL;
|
| }
|
| @@ -7041,6 +7121,10 @@ ObjectIterator* SpaceIterator::CreateIterator() {
|
| case CELL_SPACE:
|
| iterator_ = new HeapObjectIterator(heap_->cell_space(), size_func_);
|
| break;
|
| + case PROPERTY_CELL_SPACE:
|
| + iterator_ = new HeapObjectIterator(heap_->property_cell_space(),
|
| + size_func_);
|
| + break;
|
| case LO_SPACE:
|
| iterator_ = new LargeObjectIterator(heap_->lo_space(), size_func_);
|
| break;
|
|
|