From b9f0c06ab2324950c5cb878d7f77e9bba6750156 Mon Sep 17 00:00:00 2001 From: "mvstanton@chromium.org" Date: Wed, 17 Jul 2013 11:50:24 +0000 Subject: [PATCH] The gc should be able to traverse all AllocationSites for decision making. The sites are threaded into a weak list. Special problems include: * Allocations of AllocationSites occur in generated code, so generated code needs to be able to add to the list. For now I have a special hydrogen instruction, though it would be nice to use general purpose instructions. * The snapshot contains AllocationSites, and these need to be re-threaded into the list on deserialization. Something nice is that the AllocationSites are only created in old space, so a special new space visitor isn't required. BUG= R=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/18173013 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15715 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-arm.cc | 25 +++++++++++++++++++++++ src/arm/lithium-arm.h | 18 +++++++++++++++++ src/arm/lithium-codegen-arm.cc | 13 ++++++++++++ src/assembler.cc | 6 ++++++ src/assembler.h | 3 +++ src/code-stubs-hydrogen.cc | 8 ++++++-- src/heap.cc | 43 +++++++++++++++++++++++++++++++++++++++- src/heap.h | 9 ++++++++- src/hydrogen-instructions.cc | 6 ++++++ src/hydrogen-instructions.h | 37 ++++++++++++++++++++++++++++++++++ src/ia32/lithium-codegen-ia32.cc | 14 +++++++++++++ src/ia32/lithium-ia32.cc | 26 ++++++++++++++++++++++++ src/ia32/lithium-ia32.h | 20 +++++++++++++++++++ src/objects-inl.h | 1 + src/objects-printer.cc | 4 ++++ src/objects-visiting-inl.h | 5 +++++ src/objects-visiting.cc | 4 ++++ src/objects-visiting.h | 1 + src/objects.cc | 6 +++++- src/objects.h | 11 ++++++++-- src/serialize.cc | 36 ++++++++++++++++++++++++++++++--- src/serialize.h | 4 ++++ src/x64/lithium-codegen-x64.cc | 10 ++++++++++ src/x64/lithium-x64.cc | 25 +++++++++++++++++++++++ src/x64/lithium-x64.h | 18 +++++++++++++++++ 25 files changed, 343 insertions(+), 10 deletions(-) diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index d614bd0..b68d22f 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -272,6 +272,24 @@ void LCallConstantFunction::PrintDataTo(StringStream* stream) { } +ExternalReference LLinkObjectInList::GetReference(Isolate* isolate) { + switch (hydrogen()->known_list()) { + case HLinkObjectInList::ALLOCATION_SITE_LIST: + return ExternalReference::allocation_sites_list_address(isolate); + } + + UNREACHABLE(); + // Return a dummy value + return ExternalReference::isolate_address(isolate); +} + + +void LLinkObjectInList::PrintDataTo(StringStream* stream) { + object()->PrintTo(stream); + stream->Add(" offset %d", hydrogen()->store_field().offset()); +} + + void LLoadContextSlot::PrintDataTo(StringStream* stream) { context()->PrintTo(stream); stream->Add("[%d]", slot_index()); @@ -2113,6 +2131,13 @@ LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) { } +LInstruction* LChunkBuilder::DoLinkObjectInList(HLinkObjectInList* instr) { + LOperand* object = UseRegister(instr->value()); + LLinkObjectInList* result = new(zone()) LLinkObjectInList(object); + return result; +} + + LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { LOperand* context = UseRegisterAtStart(instr->value()); LInstruction* result = diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h index a628d5a..5165f1b 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h @@ -120,6 +120,7 @@ class LCodeGen; V(IsUndetectableAndBranch) \ V(Label) \ V(LazyBailout) \ + V(LinkObjectInList) \ V(LoadContextSlot) \ V(LoadExternalArrayPointer) \ V(LoadFunctionPrototype) \ @@ -1683,6 +1684,23 @@ class LStoreGlobalGeneric: public LTemplateInstruction<0, 2, 0> { }; +class LLinkObjectInList: public LTemplateInstruction<0, 1, 0> { + public: + explicit LLinkObjectInList(LOperand* object) { + inputs_[0] = object; + } + + LOperand* object() { return inputs_[0]; } + + ExternalReference GetReference(Isolate* isolate); + + DECLARE_CONCRETE_INSTRUCTION(LinkObjectInList, "link-object-in-list") + DECLARE_HYDROGEN_ACCESSOR(LinkObjectInList) + + virtual void PrintDataTo(StringStream* stream); +}; + + class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> { public: explicit LLoadContextSlot(LOperand* context) { diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index e21a1bb..9900a1e 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -2928,6 +2928,19 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { } +void LCodeGen::DoLinkObjectInList(LLinkObjectInList* instr) { + Register object = ToRegister(instr->object()); + ExternalReference sites_list_address = instr->GetReference(isolate()); + + __ mov(ip, Operand(sites_list_address)); + __ ldr(ip, MemOperand(ip)); + __ str(ip, FieldMemOperand(object, + instr->hydrogen()->store_field().offset())); + __ mov(ip, Operand(sites_list_address)); + __ str(object, MemOperand(ip)); +} + + void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { Register context = ToRegister(instr->context()); Register result = ToRegister(instr->result()); diff --git a/src/assembler.cc b/src/assembler.cc index 16a73a7..82c3c83 100644 --- a/src/assembler.cc +++ b/src/assembler.cc @@ -1125,6 +1125,12 @@ ExternalReference ExternalReference::roots_array_start(Isolate* isolate) { } +ExternalReference ExternalReference::allocation_sites_list_address( + Isolate* isolate) { + return ExternalReference(isolate->heap()->allocation_sites_list_address()); +} + + ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) { return ExternalReference(isolate->stack_guard()->address_of_jslimit()); } diff --git a/src/assembler.h b/src/assembler.h index 95853e8..5cdddeb 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -747,6 +747,9 @@ class ExternalReference BASE_EMBEDDED { // Static variable Heap::roots_array_start() static ExternalReference roots_array_start(Isolate* isolate); + // Static variable Heap::allocation_sites_list_address() + static ExternalReference allocation_sites_list_address(Isolate* isolate); + // Static variable StackGuard::address_of_jslimit() static ExternalReference address_of_stack_limit(Isolate* isolate); diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc index 25715cb..531c25c 100644 --- a/src/code-stubs-hydrogen.cc +++ b/src/code-stubs-hydrogen.cc @@ -445,8 +445,12 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { // Store the payload (smi elements kind) HValue* initial_elements_kind = AddInstruction(new(zone) HConstant( GetInitialFastElementsKind())); - AddInstruction(new(zone) HStoreNamedField(object, - HObjectAccess::ForAllocationSiteTransitionInfo(), initial_elements_kind)); + Add(object, + HObjectAccess::ForAllocationSiteTransitionInfo(), + initial_elements_kind); + + Add(object, HObjectAccess::ForAllocationSiteWeakNext(), + HLinkObjectInList::ALLOCATION_SITE_LIST); // We use a hammer (SkipWriteBarrier()) to indicate that we know the input // cell is really a Cell, and so no write barrier is needed. diff --git a/src/heap.cc b/src/heap.cc index 792178e..97c1d41 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -182,6 +182,7 @@ Heap::Heap() memset(roots_, 0, sizeof(roots_[0]) * kRootListLength); native_contexts_list_ = NULL; array_buffers_list_ = Smi::FromInt(0); + allocation_sites_list_ = Smi::FromInt(0); mark_compact_collector_.heap_ = this; external_string_table_.heap_ = this; // Put a dummy entry in the remembered pages so we can find the list the @@ -1664,6 +1665,7 @@ void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) { mark_compact_collector()->is_compacting(); ProcessArrayBuffers(retainer, record_slots); ProcessNativeContexts(retainer, record_slots); + ProcessAllocationSites(retainer, record_slots); } void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer, @@ -1757,6 +1759,39 @@ void Heap::TearDownArrayBuffers() { } +template<> +struct WeakListVisitor { + static void SetWeakNext(AllocationSite* obj, Object* next) { + obj->set_weak_next(next); + } + + static Object* WeakNext(AllocationSite* obj) { + return obj->weak_next(); + } + + static void VisitLiveObject(Heap* heap, + AllocationSite* array_buffer, + WeakObjectRetainer* retainer, + bool record_slots) {} + + static void VisitPhantomObject(Heap* heap, AllocationSite* phantom) {} + + static int WeakNextOffset() { + return AllocationSite::kWeakNextOffset; + } +}; + + +void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer, + bool record_slots) { + Object* allocation_site_obj = + VisitWeakList(this, + allocation_sites_list(), + retainer, record_slots); + set_allocation_sites_list(allocation_site_obj); +} + + void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) { DisallowHeapAllocation no_allocation; @@ -2887,7 +2922,12 @@ MaybeObject* Heap::AllocateAllocationSite() { MaybeObject* maybe_result = Allocate(allocation_site_map(), OLD_POINTER_SPACE); if (!maybe_result->ToObject(&result)) return maybe_result; - AllocationSite::cast(result)->Initialize(); + AllocationSite* site = AllocationSite::cast(result); + site->Initialize(); + + // Link the site + site->set_weak_next(allocation_sites_list()); + set_allocation_sites_list(site); return result; } @@ -6889,6 +6929,7 @@ bool Heap::CreateHeapObjects() { native_contexts_list_ = undefined_value(); array_buffers_list_ = undefined_value(); + allocation_sites_list_ = undefined_value(); return true; } diff --git a/src/heap.h b/src/heap.h index 2c97faf..6d12208 100644 --- a/src/heap.h +++ b/src/heap.h @@ -1376,6 +1376,11 @@ class Heap { } Object* array_buffers_list() { return array_buffers_list_; } + void set_allocation_sites_list(Object* object) { + allocation_sites_list_ = object; + } + Object* allocation_sites_list() { return allocation_sites_list_; } + Object** allocation_sites_list_address() { return &allocation_sites_list_; } // Number of mark-sweeps. unsigned int ms_count() { return ms_count_; } @@ -2045,9 +2050,10 @@ class Heap { // last GC. bool old_gen_exhausted_; + // Weak list heads, threaded through the objects. Object* native_contexts_list_; - Object* array_buffers_list_; + Object* allocation_sites_list_; StoreBufferRebuilder store_buffer_rebuilder_; @@ -2197,6 +2203,7 @@ class Heap { void ProcessNativeContexts(WeakObjectRetainer* retainer, bool record_slots); void ProcessArrayBuffers(WeakObjectRetainer* retainer, bool record_slots); + void ProcessAllocationSites(WeakObjectRetainer* retainer, bool record_slots); // Called on heap tear-down. void TearDownArrayBuffers(); diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index e99f909..16f502d 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -3059,6 +3059,12 @@ void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) { } +void HLinkObjectInList::PrintDataTo(StringStream* stream) { + value()->PrintNameTo(stream); + stream->Add(" offset %d", store_field_.offset()); +} + + void HLoadContextSlot::PrintDataTo(StringStream* stream) { value()->PrintNameTo(stream); stream->Add("[%d]", slot_index()); diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 2fb18fd..a006c44 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -131,6 +131,7 @@ class LChunkBuilder; V(IsSmiAndBranch) \ V(IsUndetectableAndBranch) \ V(LeaveInlined) \ + V(LinkObjectInList) \ V(LoadContextSlot) \ V(LoadExternalArrayPointer) \ V(LoadFunctionPrototype) \ @@ -5332,6 +5333,10 @@ class HObjectAccess { return HObjectAccess(kInobject, AllocationSite::kTransitionInfoOffset); } + static HObjectAccess ForAllocationSiteWeakNext() { + return HObjectAccess(kInobject, AllocationSite::kWeakNextOffset); + } + static HObjectAccess ForFixedArrayLength() { return HObjectAccess(kArrayLengths, FixedArray::kLengthOffset); } @@ -5422,6 +5427,38 @@ class HObjectAccess { }; +class HLinkObjectInList: public HUnaryOperation { + public: + // There needs to be a mapping from every KnownList to an external reference + enum KnownList { + ALLOCATION_SITE_LIST + }; + + HLinkObjectInList(HValue* object, HObjectAccess store_field, + KnownList known_list) + : HUnaryOperation(object), + store_field_(store_field), + known_list_(known_list) { + set_representation(Representation::Tagged()); + } + + HObjectAccess store_field() const { return store_field_; } + KnownList known_list() const { return known_list_; } + + virtual Representation RequiredInputRepresentation(int index) { + return Representation::Tagged(); + } + + virtual void PrintDataTo(StringStream* stream); + + DECLARE_CONCRETE_INSTRUCTION(LinkObjectInList) + + private: + HObjectAccess store_field_; + KnownList known_list_; +}; + + class HLoadNamedField: public HTemplateInstruction<2> { public: HLoadNamedField(HValue* object, diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 770cecb..8b7a494 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -2992,6 +2992,20 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { } +void LCodeGen::DoLinkObjectInList(LLinkObjectInList* instr) { + Register object = ToRegister(instr->object()); + Register temp = ToRegister(instr->temp()); + ExternalReference sites_list_address = instr->GetReference(isolate()); + + __ mov(temp, Immediate(sites_list_address)); + __ mov(temp, Operand(temp, 0)); + __ mov(FieldOperand(object, instr->hydrogen()->store_field().offset()), + temp); + __ mov(temp, Immediate(sites_list_address)); + __ mov(Operand(temp, 0), object); +} + + void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { Register context = ToRegister(instr->context()); Register result = ToRegister(instr->result()); diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index 24ee7bf..aebe26b 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -302,6 +302,24 @@ void LCallConstantFunction::PrintDataTo(StringStream* stream) { } +ExternalReference LLinkObjectInList::GetReference(Isolate* isolate) { + switch (hydrogen()->known_list()) { + case HLinkObjectInList::ALLOCATION_SITE_LIST: + return ExternalReference::allocation_sites_list_address(isolate); + } + + UNREACHABLE(); + // Return a dummy value + return ExternalReference::isolate_address(isolate); +} + + +void LLinkObjectInList::PrintDataTo(StringStream* stream) { + object()->PrintTo(stream); + stream->Add(" offset %d", hydrogen()->store_field().offset()); +} + + void LLoadContextSlot::PrintDataTo(StringStream* stream) { context()->PrintTo(stream); stream->Add("[%d]", slot_index()); @@ -2162,6 +2180,14 @@ LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) { } +LInstruction* LChunkBuilder::DoLinkObjectInList(HLinkObjectInList* instr) { + LOperand* object = UseRegister(instr->value()); + LOperand* temp = TempRegister(); + LLinkObjectInList* result = new(zone()) LLinkObjectInList(object, temp); + return result; +} + + LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { LOperand* context = UseRegisterAtStart(instr->value()); LInstruction* result = diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h index 4dcc95a..a938ee5 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h @@ -115,6 +115,7 @@ class LCodeGen; V(IsUndetectableAndBranch) \ V(Label) \ V(LazyBailout) \ + V(LinkObjectInList) \ V(LoadContextSlot) \ V(LoadExternalArrayPointer) \ V(LoadFunctionPrototype) \ @@ -1706,6 +1707,25 @@ class LStoreGlobalGeneric: public LTemplateInstruction<0, 3, 0> { }; +class LLinkObjectInList: public LTemplateInstruction<0, 1, 1> { + public: + explicit LLinkObjectInList(LOperand* object, LOperand* temp) { + inputs_[0] = object; + temps_[0] = temp; + } + + LOperand* object() { return inputs_[0]; } + LOperand* temp() { return temps_[0]; } + + ExternalReference GetReference(Isolate* isolate); + + DECLARE_CONCRETE_INSTRUCTION(LinkObjectInList, "link-object-in-list") + DECLARE_HYDROGEN_ACCESSOR(LinkObjectInList) + + virtual void PrintDataTo(StringStream* stream); +}; + + class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> { public: explicit LLoadContextSlot(LOperand* context) { diff --git a/src/objects-inl.h b/src/objects-inl.h index 091a0eb..ca3486f 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -4450,6 +4450,7 @@ ACCESSORS(SignatureInfo, args, Object, kArgsOffset) ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset) ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset) +ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset) ACCESSORS(AllocationSiteInfo, allocation_site, Object, kAllocationSiteOffset) ACCESSORS(Script, source, Object, kSourceOffset) diff --git a/src/objects-printer.cc b/src/objects-printer.cc index db324d0..0ed737b 100644 --- a/src/objects-printer.cc +++ b/src/objects-printer.cc @@ -1119,6 +1119,10 @@ void TypeSwitchInfo::TypeSwitchInfoPrint(FILE* out) { void AllocationSite::AllocationSitePrint(FILE* out) { HeapObject::PrintHeader(out, "AllocationSite"); + PrintF(out, " - weak_next: "); + weak_next()->ShortPrint(out); + PrintF(out, "\n"); + PrintF(out, " - transition_info: "); if (transition_info()->IsCell()) { Cell* cell = Cell::cast(transition_info()); diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h index 612f937..29abbe2 100644 --- a/src/objects-visiting-inl.h +++ b/src/objects-visiting-inl.h @@ -185,6 +185,11 @@ void StaticMarkingVisitor::Initialize() { table_.Register(kVisitNativeContext, &VisitNativeContext); + table_.Register(kVisitAllocationSite, + &FixedBodyVisitor::Visit); + table_.Register(kVisitByteArray, &DataObjectVisitor::Visit); table_.Register(kVisitFreeSpace, &DataObjectVisitor::Visit); diff --git a/src/objects-visiting.cc b/src/objects-visiting.cc index 6502209..484bb88 100644 --- a/src/objects-visiting.cc +++ b/src/objects-visiting.cc @@ -182,6 +182,10 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId( case NAME##_TYPE: STRUCT_LIST(MAKE_STRUCT_CASE) #undef MAKE_STRUCT_CASE + if (instance_type == ALLOCATION_SITE_TYPE) { + return kVisitAllocationSite; + } + return GetVisitorIdForSize(kVisitStruct, kVisitStructGeneric, instance_size); diff --git a/src/objects-visiting.h b/src/objects-visiting.h index c2ab45d..de5ad82 100644 --- a/src/objects-visiting.h +++ b/src/objects-visiting.h @@ -55,6 +55,7 @@ class StaticVisitorBase : public AllStatic { V(FixedArray) \ V(FixedDoubleArray) \ V(NativeContext) \ + V(AllocationSite) \ V(DataObject2) \ V(DataObject3) \ V(DataObject4) \ diff --git a/src/objects.cc b/src/objects.cc index 0c31df3..241da74 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1706,7 +1706,11 @@ void HeapObject::IterateBody(InstanceType type, int object_size, case NAME##_TYPE: STRUCT_LIST(MAKE_STRUCT_CASE) #undef MAKE_STRUCT_CASE - StructBodyDescriptor::IterateBody(this, object_size, v); + if (type == ALLOCATION_SITE_TYPE) { + AllocationSite::BodyDescriptor::IterateBody(this, v); + } else { + StructBodyDescriptor::IterateBody(this, object_size, v); + } break; default: PrintF("Unknown type: %d\n", type); diff --git a/src/objects.h b/src/objects.h index 2cc232c..9530e4d 100644 --- a/src/objects.h +++ b/src/objects.h @@ -7474,11 +7474,10 @@ enum AllocationSiteMode { class AllocationSite: public Struct { public: - static const int kTransitionInfoOffset = HeapObject::kHeaderSize; - static const int kSize = kTransitionInfoOffset + kPointerSize; static const uint32_t kMaximumArrayBytesToPretransition = 8 * 1024; DECL_ACCESSORS(transition_info, Object) + DECL_ACCESSORS(weak_next, Object) void Initialize() { SetElementsKind(GetInitialFastElementsKind()); @@ -7508,6 +7507,14 @@ class AllocationSite: public Struct { ElementsKind boilerplate_elements_kind); static inline AllocationSiteMode GetMode(ElementsKind from, ElementsKind to); + static const int kTransitionInfoOffset = HeapObject::kHeaderSize; + static const int kWeakNextOffset = kTransitionInfoOffset + kPointerSize; + static const int kSize = kWeakNextOffset + kPointerSize; + + typedef FixedBodyDescriptor BodyDescriptor; + private: DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationSite); }; diff --git a/src/serialize.cc b/src/serialize.cc index 4e51cd3..ad56d36 100644 --- a/src/serialize.cc +++ b/src/serialize.cc @@ -577,6 +577,10 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) { UNCLASSIFIED, 62, "Heap::NewSpaceAllocationLimitAddress"); + Add(ExternalReference::allocation_sites_list_address(isolate).address(), + UNCLASSIFIED, + 63, + "Heap::allocation_sites_list_address()"); // Add a small set of deopt entry addresses to encoder without generating the // deopt table code, which isn't possible at deserialization time. @@ -587,7 +591,7 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) { entry, Deoptimizer::LAZY, Deoptimizer::CALCULATE_ENTRY_ADDRESS); - Add(address, LAZY_DEOPTIMIZATION, 63 + entry, "lazy_deopt"); + Add(address, LAZY_DEOPTIMIZATION, 64 + entry, "lazy_deopt"); } } @@ -690,6 +694,13 @@ void Deserializer::Deserialize() { isolate_->heap()->set_array_buffers_list( isolate_->heap()->undefined_value()); + // The allocation site list is build during root iteration, but if no sites + // were encountered then it needs to be initialized to undefined. + if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { + isolate_->heap()->set_allocation_sites_list( + isolate_->heap()->undefined_value()); + } + // Update data pointers to the external strings containing natives sources. for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { Object* source = isolate_->heap()->natives_source_cache()->get(i); @@ -745,6 +756,16 @@ void Deserializer::VisitPointers(Object** start, Object** end) { } +void Deserializer::RelinkAllocationSite(AllocationSite* site) { + if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { + site->set_weak_next(isolate_->heap()->undefined_value()); + } else { + site->set_weak_next(isolate_->heap()->allocation_sites_list()); + } + isolate_->heap()->set_allocation_sites_list(site); +} + + // This routine writes the new object into the pointer provided and then // returns true if the new object was in young space and false otherwise. // The reason for this strange interface is that otherwise the object is @@ -754,16 +775,25 @@ void Deserializer::ReadObject(int space_number, Object** write_back) { int size = source_->GetInt() << kObjectAlignmentBits; Address address = Allocate(space_number, size); - *write_back = HeapObject::FromAddress(address); + HeapObject* obj = HeapObject::FromAddress(address); + *write_back = obj; Object** current = reinterpret_cast(address); Object** limit = current + (size >> kPointerSizeLog2); if (FLAG_log_snapshot_positions) { LOG(isolate_, SnapshotPositionEvent(address, source_->position())); } ReadChunk(current, limit, space_number, address); + + // TODO(mvstanton): consider treating the heap()->allocation_sites_list() + // as a (weak) root. If this root is relocated correctly, + // RelinkAllocationSite() isn't necessary. + if (obj->IsAllocationSite()) { + RelinkAllocationSite(AllocationSite::cast(obj)); + } + #ifdef DEBUG bool is_codespace = (space_number == CODE_SPACE); - ASSERT(HeapObject::FromAddress(address)->IsCode() == is_codespace); + ASSERT(obj->IsCode() == is_codespace); #endif } diff --git a/src/serialize.h b/src/serialize.h index a6099af..283c1b7 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -347,6 +347,10 @@ class Deserializer: public SerializerDeserializer { UNREACHABLE(); } + // Allocation sites are present in the snapshot, and must be linked into + // a list at deserialization time. + void RelinkAllocationSite(AllocationSite* site); + // Fills in some heap data in an area from start to end (non-inclusive). The // space id is used for the write barrier. The object_address is the address // of the object we are writing into, or NULL if we are not writing into an diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index ab51b91..e52dfff 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -2603,6 +2603,16 @@ void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { } +void LCodeGen::DoLinkObjectInList(LLinkObjectInList* instr) { + Register object = ToRegister(instr->object()); + ExternalReference sites_list_address = instr->GetReference(isolate()); + __ Load(kScratchRegister, sites_list_address); + __ movq(FieldOperand(object, instr->hydrogen()->store_field().offset()), + kScratchRegister); + __ Store(sites_list_address, object); +} + + void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { Register context = ToRegister(instr->context()); Register result = ToRegister(instr->result()); diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 945d002..2cec68b 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -275,6 +275,24 @@ void LCallConstantFunction::PrintDataTo(StringStream* stream) { } +ExternalReference LLinkObjectInList::GetReference(Isolate* isolate) { + switch (hydrogen()->known_list()) { + case HLinkObjectInList::ALLOCATION_SITE_LIST: + return ExternalReference::allocation_sites_list_address(isolate); + } + + UNREACHABLE(); + // Return a dummy value + return ExternalReference::isolate_address(isolate); +} + + +void LLinkObjectInList::PrintDataTo(StringStream* stream) { + object()->PrintTo(stream); + stream->Add(" offset %d", hydrogen()->store_field().offset()); +} + + void LLoadContextSlot::PrintDataTo(StringStream* stream) { context()->PrintTo(stream); stream->Add("[%d]", slot_index()); @@ -2028,6 +2046,13 @@ LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) { } +LInstruction* LChunkBuilder::DoLinkObjectInList(HLinkObjectInList* instr) { + LOperand* object = UseRegister(instr->value()); + LLinkObjectInList* result = new(zone()) LLinkObjectInList(object); + return result; +} + + LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { LOperand* context = UseRegisterAtStart(instr->value()); LInstruction* result = diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h index 62f65ae..32ee0b9 100644 --- a/src/x64/lithium-x64.h +++ b/src/x64/lithium-x64.h @@ -121,6 +121,7 @@ class LCodeGen; V(IsUndetectableAndBranch) \ V(Label) \ V(LazyBailout) \ + V(LinkObjectInList) \ V(LoadContextSlot) \ V(LoadExternalArrayPointer) \ V(LoadFunctionPrototype) \ @@ -1620,6 +1621,23 @@ class LStoreGlobalGeneric: public LTemplateInstruction<0, 2, 0> { }; +class LLinkObjectInList: public LTemplateInstruction<0, 1, 0> { + public: + explicit LLinkObjectInList(LOperand* object) { + inputs_[0] = object; + } + + LOperand* object() { return inputs_[0]; } + + ExternalReference GetReference(Isolate* isolate); + + DECLARE_CONCRETE_INSTRUCTION(LinkObjectInList, "link-object-in-list") + DECLARE_HYDROGEN_ACCESSOR(LinkObjectInList) + + virtual void PrintDataTo(StringStream* stream); +}; + + class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> { public: explicit LLoadContextSlot(LOperand* context) { -- 2.7.4