| Index: src/heap.cc
|
| diff --git a/src/heap.cc b/src/heap.cc
|
| index f28c9260b9d8ebc211381ed971db3bbfaad88977..b9e1a2b323a36664d1e53e84e7c7e899f2f9817e 100644
|
| --- a/src/heap.cc
|
| +++ b/src/heap.cc
|
| @@ -87,7 +87,6 @@ Heap::Heap()
|
| contexts_disposed_(0),
|
| global_ic_age_(0),
|
| flush_monomorphic_ics_(false),
|
| - allocation_mementos_found_(0),
|
| scan_on_scavenge_pages_(0),
|
| new_space_(this),
|
| old_pointer_space_(NULL),
|
| @@ -506,6 +505,40 @@ void Heap::RepairFreeListsAfterBoot() {
|
|
|
|
|
| void Heap::GarbageCollectionEpilogue() {
|
| + if (FLAG_allocation_site_pretenuring) {
|
| + int tenure_decisions = 0;
|
| + int dont_tenure_decisions = 0;
|
| + int allocation_mementos_found = 0;
|
| +
|
| + Object* cur = allocation_sites_list();
|
| + while (cur->IsAllocationSite()) {
|
| + AllocationSite* casted = AllocationSite::cast(cur);
|
| + allocation_mementos_found += casted->memento_found_count()->value();
|
| + if (casted->DigestPretenuringFeedback()) {
|
| + if (casted->GetPretenureMode() == TENURED) {
|
| + tenure_decisions++;
|
| + } else {
|
| + dont_tenure_decisions++;
|
| + }
|
| + }
|
| + cur = casted->weak_next();
|
| + }
|
| +
|
| + // TODO(mvstanton): Pretenure decisions are only made once for an allocation
|
| + // site. Find a sane way to decide about revisiting the decision later.
|
| +
|
| + if (FLAG_trace_track_allocation_sites &&
|
| + (allocation_mementos_found > 0 ||
|
| + tenure_decisions > 0 ||
|
| + dont_tenure_decisions > 0)) {
|
| + PrintF("GC: (#mementos, #tenure decisions, #donttenure decisions) "
|
| + "(%d, %d, %d)\n",
|
| + allocation_mementos_found,
|
| + tenure_decisions,
|
| + dont_tenure_decisions);
|
| + }
|
| + }
|
| +
|
| store_buffer()->GCEpilogue();
|
|
|
| // In release mode, we only zap the from space under heap verification.
|
| @@ -1393,8 +1426,6 @@ class ScavengeWeakObjectRetainer : public WeakObjectRetainer {
|
| void Heap::Scavenge() {
|
| RelocationLock relocation_lock(this);
|
|
|
| - allocation_mementos_found_ = 0;
|
| -
|
| #ifdef VERIFY_HEAP
|
| if (FLAG_verify_heap) VerifyNonPointerSpacePointers(this);
|
| #endif
|
| @@ -1517,9 +1548,6 @@ void Heap::Scavenge() {
|
|
|
| promotion_queue_.Destroy();
|
|
|
| - if (!FLAG_watch_ic_patching) {
|
| - isolate()->runtime_profiler()->UpdateSamplesAfterScavenge();
|
| - }
|
| incremental_marking()->UpdateMarkingDequeAfterScavenge();
|
|
|
| ScavengeWeakObjectRetainer weak_object_retainer(this);
|
| @@ -1542,11 +1570,6 @@ void Heap::Scavenge() {
|
| gc_state_ = NOT_IN_GC;
|
|
|
| scavenges_since_last_idle_round_++;
|
| -
|
| - if (FLAG_trace_track_allocation_sites && allocation_mementos_found_ > 0) {
|
| - PrintF("AllocationMementos found during scavenge = %d\n",
|
| - allocation_mementos_found_);
|
| - }
|
| }
|
|
|
|
|
| @@ -1915,12 +1938,7 @@ void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer,
|
|
|
| void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
|
| DisallowHeapAllocation no_allocation;
|
| -
|
| - // Both the external string table and the string table may contain
|
| - // external strings, but neither lists them exhaustively, nor is the
|
| - // intersection set empty. Therefore we iterate over the external string
|
| - // table first, ignoring internalized strings, and then over the
|
| - // internalized string table.
|
| + // All external strings are listed in the external string table.
|
|
|
| class ExternalStringTableVisitorAdapter : public ObjectVisitor {
|
| public:
|
| @@ -1928,13 +1946,9 @@ void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
|
| v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {}
|
| virtual void VisitPointers(Object** start, Object** end) {
|
| for (Object** p = start; p < end; p++) {
|
| - // Visit non-internalized external strings,
|
| - // since internalized strings are listed in the string table.
|
| - if (!(*p)->IsInternalizedString()) {
|
| - ASSERT((*p)->IsExternalString());
|
| - visitor_->VisitExternalString(Utils::ToLocal(
|
| - Handle<String>(String::cast(*p))));
|
| - }
|
| + ASSERT((*p)->IsExternalString());
|
| + visitor_->VisitExternalString(Utils::ToLocal(
|
| + Handle<String>(String::cast(*p))));
|
| }
|
| }
|
| private:
|
| @@ -1942,25 +1956,6 @@ void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
|
| } external_string_table_visitor(visitor);
|
|
|
| external_string_table_.Iterate(&external_string_table_visitor);
|
| -
|
| - class StringTableVisitorAdapter : public ObjectVisitor {
|
| - public:
|
| - explicit StringTableVisitorAdapter(
|
| - v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {}
|
| - virtual void VisitPointers(Object** start, Object** end) {
|
| - for (Object** p = start; p < end; p++) {
|
| - if ((*p)->IsExternalString()) {
|
| - ASSERT((*p)->IsInternalizedString());
|
| - visitor_->VisitExternalString(Utils::ToLocal(
|
| - Handle<String>(String::cast(*p))));
|
| - }
|
| - }
|
| - }
|
| - private:
|
| - v8::ExternalResourceVisitor* visitor_;
|
| - } string_table_visitor(visitor);
|
| -
|
| - string_table()->IterateElements(&string_table_visitor);
|
| }
|
|
|
|
|
| @@ -2170,7 +2165,7 @@ class ScavengingVisitor : public StaticVisitorBase {
|
| RecordCopiedObject(heap, target);
|
| Isolate* isolate = heap->isolate();
|
| HeapProfiler* heap_profiler = isolate->heap_profiler();
|
| - if (heap_profiler->is_profiling()) {
|
| + if (heap_profiler->is_tracking_object_moves()) {
|
| heap_profiler->ObjectMoveEvent(source->address(), target->address(),
|
| size);
|
| }
|
| @@ -2421,7 +2416,7 @@ void Heap::SelectScavengingVisitorsTable() {
|
| isolate()->logger()->is_logging() ||
|
| isolate()->cpu_profiler()->is_profiling() ||
|
| (isolate()->heap_profiler() != NULL &&
|
| - isolate()->heap_profiler()->is_profiling());
|
| + isolate()->heap_profiler()->is_tracking_object_moves());
|
|
|
| if (!incremental_marking()->IsMarking()) {
|
| if (!logging_and_profiling) {
|
| @@ -3968,7 +3963,12 @@ MaybeObject* Heap::AllocateSubString(String* buffer,
|
| int length = end - start;
|
| if (length <= 0) {
|
| return empty_string();
|
| - } else if (length == 1) {
|
| + }
|
| +
|
| + // Make an attempt to flatten the buffer to reduce access time.
|
| + buffer = buffer->TryFlattenGetString();
|
| +
|
| + if (length == 1) {
|
| return LookupSingleCharacterStringFromCode(buffer->Get(start));
|
| } else if (length == 2) {
|
| // Optimization for 2-byte strings often used as keys in a decompression
|
| @@ -3979,9 +3979,6 @@ MaybeObject* Heap::AllocateSubString(String* buffer,
|
| return MakeOrFindTwoCharacterString(this, c1, c2);
|
| }
|
|
|
| - // Make an attempt to flatten the buffer to reduce access time.
|
| - buffer = buffer->TryFlattenGetString();
|
| -
|
| if (!FLAG_string_slices ||
|
| !buffer->IsFlat() ||
|
| length < SlicedString::kMinLength ||
|
| @@ -4357,6 +4354,17 @@ MaybeObject* Heap::CopyCode(Code* code, Vector<byte> reloc_info) {
|
| }
|
|
|
|
|
| +void Heap::InitializeAllocationMemento(AllocationMemento* memento,
|
| + AllocationSite* allocation_site) {
|
| + memento->set_map_no_write_barrier(allocation_memento_map());
|
| + ASSERT(allocation_site->map() == allocation_site_map());
|
| + memento->set_allocation_site(allocation_site, SKIP_WRITE_BARRIER);
|
| + if (FLAG_allocation_site_pretenuring) {
|
| + allocation_site->IncrementMementoCreateCount();
|
| + }
|
| +}
|
| +
|
| +
|
| MaybeObject* Heap::AllocateWithAllocationSite(Map* map, AllocationSpace space,
|
| Handle<AllocationSite> allocation_site) {
|
| ASSERT(gc_state_ == NOT_IN_GC);
|
| @@ -4373,9 +4381,7 @@ MaybeObject* Heap::AllocateWithAllocationSite(Map* map, AllocationSpace space,
|
| HeapObject::cast(result)->set_map_no_write_barrier(map);
|
| AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>(
|
| reinterpret_cast<Address>(result) + map->instance_size());
|
| - alloc_memento->set_map_no_write_barrier(allocation_memento_map());
|
| - ASSERT(allocation_site->map() == allocation_site_map());
|
| - alloc_memento->set_allocation_site(*allocation_site, SKIP_WRITE_BARRIER);
|
| + InitializeAllocationMemento(alloc_memento, *allocation_site);
|
| return result;
|
| }
|
|
|
| @@ -4808,8 +4814,7 @@ MaybeObject* Heap::CopyJSObject(JSObject* source, AllocationSite* site) {
|
| int object_size = map->instance_size();
|
| Object* clone;
|
|
|
| - ASSERT(site == NULL || (AllocationSite::CanTrack(map->instance_type()) &&
|
| - map->instance_type() == JS_ARRAY_TYPE));
|
| + ASSERT(site == NULL || AllocationSite::CanTrack(map->instance_type()));
|
|
|
| WriteBarrierMode wb_mode = UPDATE_WRITE_BARRIER;
|
|
|
| @@ -4848,16 +4853,7 @@ MaybeObject* Heap::CopyJSObject(JSObject* source, AllocationSite* site) {
|
| if (site != NULL) {
|
| AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>(
|
| reinterpret_cast<Address>(clone) + object_size);
|
| - alloc_memento->set_map_no_write_barrier(allocation_memento_map());
|
| - ASSERT(site->map() == allocation_site_map());
|
| - alloc_memento->set_allocation_site(site, SKIP_WRITE_BARRIER);
|
| - HeapProfiler* profiler = isolate()->heap_profiler();
|
| - if (profiler->is_tracking_allocations()) {
|
| - profiler->UpdateObjectSizeEvent(HeapObject::cast(clone)->address(),
|
| - object_size);
|
| - profiler->NewObjectEvent(alloc_memento->address(),
|
| - AllocationMemento::kSize);
|
| - }
|
| + InitializeAllocationMemento(alloc_memento, site);
|
| }
|
| }
|
|
|
| @@ -4981,7 +4977,7 @@ MaybeObject* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor,
|
|
|
|
|
| MaybeObject* Heap::AllocateStringFromOneByte(Vector<const uint8_t> string,
|
| - PretenureFlag pretenure) {
|
| + PretenureFlag pretenure) {
|
| int length = string.length();
|
| if (length == 1) {
|
| return Heap::LookupSingleCharacterStringFromCode(string[0]);
|
|
|