From: hpayer@chromium.org Date: Wed, 28 Aug 2013 08:39:43 +0000 (+0000) Subject: Clear next map word when folding allocations into js arrays. X-Git-Tag: upstream/4.7.83~12785 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4d7375ca989dad16a924676993d7259cc9318191;p=platform%2Fupstream%2Fv8.git Clear next map word when folding allocations into js arrays. BUG= R=mstarzinger@chromium.org, mvstanton@chromium.org Review URL: https://codereview.chromium.org/22915007 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16381 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/heap.cc b/src/heap.cc index ad352bc..b1096b3 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -4971,7 +4971,7 @@ MaybeObject* Heap::CopyJSObjectWithAllocationSite( int object_size = map->instance_size(); Object* clone; - ASSERT(map->CanTrackAllocationSite()); + ASSERT(AllocationSite::CanTrack(map->instance_type())); ASSERT(map->instance_type() == JS_ARRAY_TYPE); WriteBarrierMode wb_mode = UPDATE_WRITE_BARRIER; diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index 7701b9e..0bd7b79 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -3283,8 +3283,9 @@ void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, // First update the size of the dominator allocate instruction. dominator_size = dominator_allocate->size(); - int32_t dominator_size_constant = + int32_t original_object_size = HConstant::cast(dominator_size)->GetInteger32Constant(); + int32_t dominator_size_constant = original_object_size; int32_t current_size_constant = HConstant::cast(current_size)->GetInteger32Constant(); int32_t new_dominator_size = dominator_size_constant + current_size_constant; @@ -3319,9 +3320,19 @@ void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, #ifdef VERIFY_HEAP if (FLAG_verify_heap && dominator_allocate->IsNewSpaceAllocation()) { dominator_allocate->MakePrefillWithFiller(); + } else { + // TODO(hpayer): This is a short-term hack to make allocation mementos + // work again in new space. + ClearNextMapWord(original_object_size); } +#else + // TODO(hpayer): This is a short-term hack to make allocation mementos + // work again in new space. + ClearNextMapWord(original_object_size); #endif + dominator_allocate->clear_next_map_word_ = clear_next_map_word_; + // After that replace the dominated allocate instruction. HInstruction* dominated_allocate_instr = HInnerAllocatedObject::New(zone, @@ -3457,6 +3468,19 @@ void HAllocate::CreateFreeSpaceFiller(int32_t free_space_size) { } +void HAllocate::ClearNextMapWord(int offset) { + if (clear_next_map_word_) { + Zone* zone = block()->zone(); + HObjectAccess access = HObjectAccess::ForJSObjectOffset(offset); + HStoreNamedField* clear_next_map = + HStoreNamedField::New(zone, context(), this, access, + block()->graph()->GetConstantNull()); + clear_next_map->ClearAllSideEffects(); + clear_next_map->InsertAfter(this); + } +} + + void HAllocate::PrintDataTo(StringStream* stream) { size()->PrintNameTo(stream); stream->Add(" ("); diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 59db99c..8f79edf 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -5166,7 +5166,8 @@ class HAllocate V8_FINAL : public HTemplateInstruction<2> { InstanceType instance_type) : HTemplateInstruction<2>(type), dominating_allocate_(NULL), - filler_free_space_size_(NULL) { + filler_free_space_size_(NULL), + clear_next_map_word_(false) { SetOperandAt(0, context); SetOperandAt(1, size); set_representation(Representation::Tagged()); @@ -5188,6 +5189,8 @@ class HAllocate V8_FINAL : public HTemplateInstruction<2> { if (!FLAG_use_gvn || !FLAG_use_allocation_folding) { flags_ = static_cast(flags_ | PREFILL_WITH_FILLER); } + clear_next_map_word_ = pretenure_flag == NOT_TENURED && + AllocationSite::CanTrack(instance_type); } void UpdateSize(HValue* size) { @@ -5207,10 +5210,13 @@ class HAllocate V8_FINAL : public HTemplateInstruction<2> { allocate->IsOldPointerSpaceAllocation()); } + void ClearNextMapWord(int offset); + Flags flags_; Handle known_initial_map_; HAllocate* dominating_allocate_; HStoreNamedField* filler_free_space_size_; + bool clear_next_map_word_; }; diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 83f91de..4847f1a 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -8329,7 +8329,7 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy( int* data_offset, AllocationSiteMode mode) { bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && - boilerplate_object->map()->CanTrackAllocationSite(); + AllocationSite::CanTrack(boilerplate_object->map()->instance_type()); // If using allocation sites, then the payload on the site should already // be filled in as a valid (boilerplate) array. @@ -8385,7 +8385,7 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy( // Create allocation site info. if (mode == TRACK_ALLOCATION_SITE && - boilerplate_object->map()->CanTrackAllocationSite()) { + AllocationSite::CanTrack(boilerplate_object->map()->instance_type())) { elements_offset += AllocationMemento::kSize; *offset += AllocationMemento::kSize; BuildCreateAllocationMemento(target, JSArray::kSize, allocation_site); diff --git a/src/objects-inl.h b/src/objects-inl.h index 13ae603..b165ad4 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -1312,7 +1312,7 @@ void JSObject::ValidateElements() { bool JSObject::ShouldTrackAllocationInfo() { - if (map()->CanTrackAllocationSite()) { + if (AllocationSite::CanTrack(map()->instance_type())) { if (!IsJSArray()) { return true; } @@ -1349,6 +1349,11 @@ AllocationSiteMode AllocationSite::GetMode(ElementsKind from, } +inline bool AllocationSite::CanTrack(InstanceType type) { + return type == JS_ARRAY_TYPE; +} + + MaybeObject* JSObject::EnsureCanContainHeapObjectElements() { ValidateElements(); ElementsKind elements_kind = map()->elements_kind(); @@ -3593,11 +3598,6 @@ Code::Flags Code::flags() { } -inline bool Map::CanTrackAllocationSite() { - return instance_type() == JS_ARRAY_TYPE; -} - - void Map::set_owns_descriptors(bool is_shared) { set_bit_field3(OwnsDescriptors::update(bit_field3(), is_shared)); } diff --git a/src/objects.h b/src/objects.h index 4685dc7..988f1ab 100644 --- a/src/objects.h +++ b/src/objects.h @@ -5776,7 +5776,6 @@ class Map: public HeapObject { set_bit_field3(EnumLengthBits::update(bit_field3(), length)); } - inline bool CanTrackAllocationSite(); inline bool owns_descriptors(); inline void set_owns_descriptors(bool is_shared); inline bool is_observed(); @@ -7845,6 +7844,7 @@ class AllocationSite: public Struct { static inline AllocationSiteMode GetMode( ElementsKind boilerplate_elements_kind); static inline AllocationSiteMode GetMode(ElementsKind from, ElementsKind to); + static inline bool CanTrack(InstanceType type); static const int kTransitionInfoOffset = HeapObject::kHeaderSize; static const int kWeakNextOffset = kTransitionInfoOffset + kPointerSize; diff --git a/test/mjsunit/allocation-folding.js b/test/mjsunit/allocation-folding.js index fe5fa6d..ec07392 100644 --- a/test/mjsunit/allocation-folding.js +++ b/test/mjsunit/allocation-folding.js @@ -56,7 +56,7 @@ function doubles() { doubles(); doubles(); doubles(); %OptimizeFunctionOnNextCall(doubles); -var result = doubles(); +result = doubles(); gc(); @@ -72,8 +72,31 @@ function doubles_int() { doubles_int(); doubles_int(); doubles_int(); %OptimizeFunctionOnNextCall(doubles_int); -var result = doubles_int(); +result = doubles_int(); gc(); assertEquals(result[1], 3.1); + +// Test allocation folding over a branch. + +function branch_int(left) { + var elem1 = [1, 2]; + var elem2; + if (left) { + elem2 = [3, 4]; + } else { + elem2 = [5, 6]; + } + return elem2; +} + +branch_int(1); branch_int(1); branch_int(1); +%OptimizeFunctionOnNextCall(branch_int); +result = branch_int(1); +var result2 = branch_int(0); + +gc(); + +assertEquals(result[1], 4); +assertEquals(result2[1], 6);