From d7975dfdab626bd6eec3e9f6e43ccaab316bfbd5 Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Tue, 4 Jun 2013 08:28:33 +0000 Subject: [PATCH] Deprecate HAllocateObject in favor of HAllocate. This models the instantiation of an implicit receiver for CallNew nodes in hydrogen using HAllocate together with generic stores instead of one specialized HAllocateObject instruction, hence creating a single choking point for inlined allocation in optimized code. R=hpayer@chromium.org Review URL: https://codereview.chromium.org/15714005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14930 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-arm.cc | 8 ---- src/arm/lithium-arm.h | 16 -------- src/arm/lithium-codegen-arm.cc | 74 --------------------------------- src/arm/lithium-codegen-arm.h | 1 - src/heap.cc | 10 +---- src/hydrogen-instructions.cc | 5 --- src/hydrogen-instructions.h | 56 ++++++------------------- src/hydrogen.cc | 76 ++++++++++++++++++++++++++++++---- src/hydrogen.h | 1 - src/ia32/lithium-codegen-ia32.cc | 89 ---------------------------------------- src/ia32/lithium-codegen-ia32.h | 1 - src/ia32/lithium-ia32.cc | 9 ---- src/ia32/lithium-ia32.h | 16 -------- src/mips/lithium-codegen-mips.cc | 74 --------------------------------- src/mips/lithium-codegen-mips.h | 1 - src/mips/lithium-mips.cc | 8 ---- src/mips/lithium-mips.h | 16 -------- src/objects.h | 7 ++++ src/x64/lithium-codegen-x64.cc | 88 --------------------------------------- src/x64/lithium-codegen-x64.h | 1 - src/x64/lithium-x64.cc | 7 ---- src/x64/lithium-x64.h | 14 ------- 22 files changed, 88 insertions(+), 490 deletions(-) diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index c1f24c9..3fc0fd8 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -2388,14 +2388,6 @@ LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) { } -LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) { - info()->MarkAsDeferredCalling(); - LAllocateObject* result = - new(zone()) LAllocateObject(TempRegister(), TempRegister()); - return AssignPointerMap(DefineAsRegister(result)); -} - - LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { info()->MarkAsDeferredCalling(); LOperand* size = instr->size()->IsConstant() diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h index 6ae65e8..bec0463 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h @@ -49,7 +49,6 @@ class LCodeGen; #define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \ V(AccessArgumentsAt) \ V(AddI) \ - V(AllocateObject) \ V(Allocate) \ V(ApplyArguments) \ V(ArgumentsElements) \ @@ -2457,21 +2456,6 @@ class LClampTToUint8: public LTemplateInstruction<1, 1, 1> { }; -class LAllocateObject: public LTemplateInstruction<1, 1, 2> { - public: - LAllocateObject(LOperand* temp, LOperand* temp2) { - temps_[0] = temp; - temps_[1] = temp2; - } - - LOperand* temp() { return temps_[0]; } - LOperand* temp2() { return temps_[1]; } - - DECLARE_CONCRETE_INSTRUCTION(AllocateObject, "allocate-object") - DECLARE_HYDROGEN_ACCESSOR(AllocateObject) -}; - - class LAllocate: public LTemplateInstruction<1, 2, 2> { public: LAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) { diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 2ef6951..d2b2c26 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -5410,80 +5410,6 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { } -void LCodeGen::DoAllocateObject(LAllocateObject* instr) { - class DeferredAllocateObject: public LDeferredCode { - public: - DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr) - : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } - virtual LInstruction* instr() { return instr_; } - private: - LAllocateObject* instr_; - }; - - DeferredAllocateObject* deferred = - new(zone()) DeferredAllocateObject(this, instr); - - Register result = ToRegister(instr->result()); - Register scratch = ToRegister(instr->temp()); - Register scratch2 = ToRegister(instr->temp2()); - Handle constructor = instr->hydrogen()->constructor(); - Handle initial_map = instr->hydrogen()->constructor_initial_map(); - int instance_size = initial_map->instance_size(); - ASSERT(initial_map->pre_allocated_property_fields() + - initial_map->unused_property_fields() - - initial_map->inobject_properties() == 0); - - __ Allocate(instance_size, result, scratch, scratch2, deferred->entry(), - TAG_OBJECT); - - __ bind(deferred->exit()); - if (FLAG_debug_code) { - Label is_in_new_space; - __ JumpIfInNewSpace(result, scratch, &is_in_new_space); - __ Abort("Allocated object is not in new-space"); - __ bind(&is_in_new_space); - } - - // Load the initial map. - Register map = scratch; - __ LoadHeapObject(map, constructor); - __ ldr(map, FieldMemOperand(map, JSFunction::kPrototypeOrInitialMapOffset)); - - // Initialize map and fields of the newly allocated object. - ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); - __ str(map, FieldMemOperand(result, JSObject::kMapOffset)); - __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex); - __ str(scratch, FieldMemOperand(result, JSObject::kElementsOffset)); - __ str(scratch, FieldMemOperand(result, JSObject::kPropertiesOffset)); - if (initial_map->inobject_properties() != 0) { - __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); - for (int i = 0; i < initial_map->inobject_properties(); i++) { - int property_offset = JSObject::kHeaderSize + i * kPointerSize; - __ str(scratch, FieldMemOperand(result, property_offset)); - } - } -} - - -void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { - Register result = ToRegister(instr->result()); - Handle initial_map = instr->hydrogen()->constructor_initial_map(); - int instance_size = initial_map->instance_size(); - - // TODO(3095996): Get rid of this. For now, we need to make the - // result register contain a valid pointer because it is already - // contained in the register pointer map. - __ mov(result, Operand::Zero()); - - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); - __ mov(r0, Operand(Smi::FromInt(instance_size))); - __ push(r0); - CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); - __ StoreToSafepointRegisterSlot(r0, result); -} - - void LCodeGen::DoAllocate(LAllocate* instr) { class DeferredAllocate: public LDeferredCode { public: diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h index f282847..c7ccdfb 100644 --- a/src/arm/lithium-codegen-arm.h +++ b/src/arm/lithium-codegen-arm.h @@ -157,7 +157,6 @@ class LCodeGen BASE_EMBEDDED { void DoDeferredRandom(LRandom* instr); void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); void DoDeferredStringCharFromCode(LStringCharFromCode* instr); - void DoDeferredAllocateObject(LAllocateObject* instr); void DoDeferredAllocate(LAllocate* instr); void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, Label* map_check); diff --git a/src/heap.cc b/src/heap.cc index 9bfca64..5783a85 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -4302,10 +4302,7 @@ MaybeObject* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) { ASSERT(map->instance_type() != JS_BUILTINS_OBJECT_TYPE); // Allocate the backing storage for the properties. - int prop_size = - map->pre_allocated_property_fields() + - map->unused_property_fields() - - map->inobject_properties(); + int prop_size = map->InitialPropertiesLength(); ASSERT(prop_size >= 0); Object* properties; { MaybeObject* maybe_properties = AllocateFixedArray(prop_size, pretenure); @@ -4342,10 +4339,7 @@ MaybeObject* Heap::AllocateJSObjectFromMapWithAllocationSite(Map* map, ASSERT(map->instance_type() != JS_BUILTINS_OBJECT_TYPE); // Allocate the backing storage for the properties. - int prop_size = - map->pre_allocated_property_fields() + - map->unused_property_fields() - - map->inobject_properties(); + int prop_size = map->InitialPropertiesLength(); ASSERT(prop_size >= 0); Object* properties; { MaybeObject* maybe_properties = AllocateFixedArray(prop_size); diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index 8b3cd52..b8fb175 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -3029,11 +3029,6 @@ HType HStringCharFromCode::CalculateInferredType() { } -HType HAllocateObject::CalculateInferredType() { - return HType::JSObject(); -} - - HType HAllocate::CalculateInferredType() { return type_; } diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index f79d995..c232184 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -65,7 +65,6 @@ class LChunkBuilder; V(AccessArgumentsAt) \ V(Add) \ V(Allocate) \ - V(AllocateObject) \ V(ApplyArguments) \ V(ArgumentsElements) \ V(ArgumentsLength) \ @@ -4808,48 +4807,6 @@ class HLoadGlobalGeneric: public HTemplateInstruction<2> { }; -class HAllocateObject: public HTemplateInstruction<1> { - public: - HAllocateObject(HValue* context, Handle constructor) - : constructor_(constructor) { - SetOperandAt(0, context); - set_representation(Representation::Tagged()); - SetGVNFlag(kChangesNewSpacePromotion); - constructor_initial_map_ = constructor->has_initial_map() - ? Handle(constructor->initial_map()) - : Handle::null(); - // If slack tracking finished, the instance size and property counts - // remain unchanged so that we can allocate memory for the object. - ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress()); - } - - // Maximum instance size for which allocations will be inlined. - static const int kMaxSize = 64 * kPointerSize; - - HValue* context() { return OperandAt(0); } - Handle constructor() { return constructor_; } - Handle constructor_initial_map() { return constructor_initial_map_; } - - virtual Representation RequiredInputRepresentation(int index) { - return Representation::Tagged(); - } - virtual Handle GetMonomorphicJSObjectMap() { - ASSERT(!constructor_initial_map_.is_null()); - return constructor_initial_map_; - } - virtual HType CalculateInferredType(); - - DECLARE_CONCRETE_INSTRUCTION(AllocateObject) - - private: - // TODO(svenpanne) Might be safe, but leave it out until we know for sure. - // virtual bool IsDeletable() const { return true; } - - Handle constructor_; - Handle constructor_initial_map_; -}; - - class HAllocate: public HTemplateInstruction<2> { public: enum Flags { @@ -4868,6 +4825,9 @@ class HAllocate: public HTemplateInstruction<2> { SetGVNFlag(kChangesNewSpacePromotion); } + // Maximum instance size for which allocations will be inlined. + static const int kMaxInlineSize = 64 * kPointerSize; + static Flags DefaultFlags() { return CAN_ALLOCATE_IN_NEW_SPACE; } @@ -4892,6 +4852,14 @@ class HAllocate: public HTemplateInstruction<2> { } } + virtual Handle GetMonomorphicJSObjectMap() { + return known_initial_map_; + } + + void set_known_initial_map(Handle known_initial_map) { + known_initial_map_ = known_initial_map; + } + virtual HType CalculateInferredType(); bool CanAllocateInNewSpace() const { @@ -4926,6 +4894,7 @@ class HAllocate: public HTemplateInstruction<2> { private: HType type_; Flags flags_; + Handle known_initial_map_; }; @@ -4969,7 +4938,6 @@ inline bool ReceiverObjectNeedsWriteBarrier(HValue* object, new_space_dominator); } if (object != new_space_dominator) return true; - if (object->IsAllocateObject()) return false; if (object->IsAllocate()) { return !HAllocate::cast(object)->GuaranteedInNewSpace(); } diff --git a/src/hydrogen.cc b/src/hydrogen.cc index bfe7cbc..1cf6d83 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -8741,7 +8741,8 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) { static bool IsAllocationInlineable(Handle constructor) { return constructor->has_initial_map() && constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && - constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; + constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && + constructor->initial_map()->InitialPropertiesLength() == 0; } @@ -8751,6 +8752,7 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { ASSERT(current_block()->HasPredecessor()); int argument_count = expr->arguments()->length() + 1; // Plus constructor. HValue* context = environment()->LookupContext(); + Factory* factory = isolate()->factory(); if (FLAG_inline_construct && expr->IsMonomorphic() && @@ -8770,20 +8772,76 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { constructor->shared()->CompleteInobjectSlackTracking(); } - // Replace the constructor function with a newly allocated receiver. - HInstruction* receiver = new(zone()) HAllocateObject(context, constructor); - // Index of the receiver from the top of the expression stack. + // Calculate instance size from initial map of constructor. + ASSERT(constructor->has_initial_map()); + Handle initial_map(constructor->initial_map()); + int instance_size = initial_map->instance_size(); + ASSERT(initial_map->InitialPropertiesLength() == 0); + + // Allocate an instance of the implicit receiver object. + HValue* size_in_bytes = + AddInstruction(new(zone()) HConstant(instance_size, + Representation::Integer32())); + HInstruction* receiver = + AddInstruction(new(zone()) HAllocate(context, + size_in_bytes, + HType::JSObject(), + HAllocate::DefaultFlags())); + HAllocate::cast(receiver)->set_known_initial_map(initial_map); + + // Load the initial map from the constructor. + HValue* constructor_value = + AddInstruction(new(zone()) HConstant(constructor, + Representation::Tagged())); + HValue* initial_map_value = + AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset( + JSFunction::kPrototypeOrInitialMapOffset)); + + // Initialize map and fields of the newly allocated object. + { NoObservableSideEffectsScope no_effects(this); + ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); + AddStore(receiver, + HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), + initial_map_value); + HValue* empty_fixed_array = + AddInstruction(new(zone()) HConstant(factory->empty_fixed_array(), + Representation::Tagged())); + AddStore(receiver, + HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), + empty_fixed_array); + AddStore(receiver, + HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), + empty_fixed_array); + if (initial_map->inobject_properties() != 0) { + HConstant* undefined = graph()->GetConstantUndefined(); + for (int i = 0; i < initial_map->inobject_properties(); i++) { + int property_offset = JSObject::kHeaderSize + i * kPointerSize; + AddStore(receiver, + HObjectAccess::ForJSObjectOffset(property_offset), + undefined); + } + } + } + + // Replace the constructor function with a newly allocated receiver using + // the index of the receiver from the top of the expression stack. const int receiver_index = argument_count - 1; - AddInstruction(receiver); ASSERT(environment()->ExpressionStackAt(receiver_index) == function); environment()->SetExpressionStackAt(receiver_index, receiver); if (TryInlineConstruct(expr, receiver)) return; - // TODO(mstarzinger): For now we remove the previous HAllocateObject and - // add HPushArgument for the arguments in case inlining failed. What we - // actually should do is emit HInvokeFunction on the constructor instead - // of using HCallNew as a fallback. + // TODO(mstarzinger): For now we remove the previous HAllocate and all + // corresponding instructions and instead add HPushArgument for the + // arguments in case inlining failed. What we actually should do is for + // inlining to try to build a subgraph without mutating the parent graph. + HInstruction* instr = current_block()->last(); + while (instr != initial_map_value) { + HInstruction* prev_instr = instr->previous(); + instr->DeleteAndReplaceWith(NULL); + instr = prev_instr; + } + initial_map_value->DeleteAndReplaceWith(NULL); receiver->DeleteAndReplaceWith(NULL); check->DeleteAndReplaceWith(NULL); environment()->SetExpressionStackAt(receiver_index, function); diff --git a/src/hydrogen.h b/src/hydrogen.h index 7a57448..6163e1e 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -66,7 +66,6 @@ class HBasicBlock: public ZoneObject { HInstruction* first() const { return first_; } HInstruction* last() const { return last_; } void set_last(HInstruction* instr) { last_ = instr; } - HInstruction* GetLastInstruction(); HControlInstruction* end() const { return end_; } HLoopInformation* loop_information() const { return loop_information_; } const ZoneList* predecessors() const { return &predecessors_; } diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 911a64c..9472722 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -5998,95 +5998,6 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { } -void LCodeGen::DoAllocateObject(LAllocateObject* instr) { - class DeferredAllocateObject: public LDeferredCode { - public: - DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr) - : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } - virtual LInstruction* instr() { return instr_; } - private: - LAllocateObject* instr_; - }; - - DeferredAllocateObject* deferred = - new(zone()) DeferredAllocateObject(this, instr); - - Register result = ToRegister(instr->result()); - Register scratch = ToRegister(instr->temp()); - Handle constructor = instr->hydrogen()->constructor(); - Handle initial_map = instr->hydrogen()->constructor_initial_map(); - int instance_size = initial_map->instance_size(); - ASSERT(initial_map->pre_allocated_property_fields() + - initial_map->unused_property_fields() - - initial_map->inobject_properties() == 0); - - __ Allocate(instance_size, result, no_reg, scratch, deferred->entry(), - TAG_OBJECT); - - __ bind(deferred->exit()); - if (FLAG_debug_code) { - Label is_in_new_space; - __ JumpIfInNewSpace(result, scratch, &is_in_new_space); - __ Abort("Allocated object is not in new-space"); - __ bind(&is_in_new_space); - } - - // Load the initial map. - Register map = scratch; - __ LoadHeapObject(scratch, constructor); - __ mov(map, FieldOperand(scratch, JSFunction::kPrototypeOrInitialMapOffset)); - - if (FLAG_debug_code) { - __ AssertNotSmi(map); - __ cmpb(FieldOperand(map, Map::kInstanceSizeOffset), - instance_size >> kPointerSizeLog2); - __ Assert(equal, "Unexpected instance size"); - __ cmpb(FieldOperand(map, Map::kPreAllocatedPropertyFieldsOffset), - initial_map->pre_allocated_property_fields()); - __ Assert(equal, "Unexpected pre-allocated property fields count"); - __ cmpb(FieldOperand(map, Map::kUnusedPropertyFieldsOffset), - initial_map->unused_property_fields()); - __ Assert(equal, "Unexpected unused property fields count"); - __ cmpb(FieldOperand(map, Map::kInObjectPropertiesOffset), - initial_map->inobject_properties()); - __ Assert(equal, "Unexpected in-object property fields count"); - } - - // Initialize map and fields of the newly allocated object. - ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); - __ mov(FieldOperand(result, JSObject::kMapOffset), map); - __ mov(scratch, factory()->empty_fixed_array()); - __ mov(FieldOperand(result, JSObject::kElementsOffset), scratch); - __ mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch); - if (initial_map->inobject_properties() != 0) { - __ mov(scratch, factory()->undefined_value()); - for (int i = 0; i < initial_map->inobject_properties(); i++) { - int property_offset = JSObject::kHeaderSize + i * kPointerSize; - __ mov(FieldOperand(result, property_offset), scratch); - } - } -} - - -void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { - Register result = ToRegister(instr->result()); - Handle initial_map = instr->hydrogen()->constructor_initial_map(); - int instance_size = initial_map->instance_size(); - - // TODO(3095996): Get rid of this. For now, we need to make the - // result register contain a valid pointer because it is already - // contained in the register pointer map. - __ Set(result, Immediate(0)); - - PushSafepointRegistersScope scope(this); - __ push(Immediate(Smi::FromInt(instance_size))); - CallRuntimeFromDeferred( - Runtime::kAllocateInNewSpace, 1, instr, instr->context()); - __ StoreToSafepointRegisterSlot(result, eax); -} - - void LCodeGen::DoAllocate(LAllocate* instr) { class DeferredAllocate: public LDeferredCode { public: diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h index dec768b..647dd0e 100644 --- a/src/ia32/lithium-codegen-ia32.h +++ b/src/ia32/lithium-codegen-ia32.h @@ -159,7 +159,6 @@ class LCodeGen BASE_EMBEDDED { void DoDeferredRandom(LRandom* instr); void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); void DoDeferredStringCharFromCode(LStringCharFromCode* instr); - void DoDeferredAllocateObject(LAllocateObject* instr); void DoDeferredAllocate(LAllocate* instr); void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, Label* map_check); diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index 28c4d2c..9a39c85 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -2519,15 +2519,6 @@ LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) { } -LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) { - info()->MarkAsDeferredCalling(); - LOperand* context = UseAny(instr->context()); - LOperand* temp = TempRegister(); - LAllocateObject* result = new(zone()) LAllocateObject(context, temp); - return AssignPointerMap(DefineAsRegister(result)); -} - - LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { info()->MarkAsDeferredCalling(); LOperand* context = UseAny(instr->context()); diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h index 568ef87..e43672c 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h @@ -44,7 +44,6 @@ class LCodeGen; V(AccessArgumentsAt) \ V(AddI) \ V(Allocate) \ - V(AllocateObject) \ V(ApplyArguments) \ V(ArgumentsElements) \ V(ArgumentsLength) \ @@ -2552,21 +2551,6 @@ class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> { }; -class LAllocateObject: public LTemplateInstruction<1, 1, 1> { - public: - LAllocateObject(LOperand* context, LOperand* temp) { - inputs_[0] = context; - temps_[0] = temp; - } - - LOperand* context() { return inputs_[0]; } - LOperand* temp() { return temps_[0]; } - - DECLARE_CONCRETE_INSTRUCTION(AllocateObject, "allocate-object") - DECLARE_HYDROGEN_ACCESSOR(AllocateObject) -}; - - class LAllocate: public LTemplateInstruction<1, 2, 1> { public: LAllocate(LOperand* context, LOperand* size, LOperand* temp) { diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 677d600..bcb6f1a 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -5138,80 +5138,6 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { } -void LCodeGen::DoAllocateObject(LAllocateObject* instr) { - class DeferredAllocateObject: public LDeferredCode { - public: - DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr) - : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } - virtual LInstruction* instr() { return instr_; } - private: - LAllocateObject* instr_; - }; - - DeferredAllocateObject* deferred = - new(zone()) DeferredAllocateObject(this, instr); - - Register result = ToRegister(instr->result()); - Register scratch = ToRegister(instr->temp()); - Register scratch2 = ToRegister(instr->temp2()); - Handle constructor = instr->hydrogen()->constructor(); - Handle initial_map = instr->hydrogen()->constructor_initial_map(); - int instance_size = initial_map->instance_size(); - ASSERT(initial_map->pre_allocated_property_fields() + - initial_map->unused_property_fields() - - initial_map->inobject_properties() == 0); - - __ Allocate(instance_size, result, scratch, scratch2, deferred->entry(), - TAG_OBJECT); - - __ bind(deferred->exit()); - if (FLAG_debug_code) { - Label is_in_new_space; - __ JumpIfInNewSpace(result, scratch, &is_in_new_space); - __ Abort("Allocated object is not in new-space"); - __ bind(&is_in_new_space); - } - - // Load the initial map. - Register map = scratch; - __ LoadHeapObject(map, constructor); - __ lw(map, FieldMemOperand(map, JSFunction::kPrototypeOrInitialMapOffset)); - - // Initialize map and fields of the newly allocated object. - ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); - __ sw(map, FieldMemOperand(result, JSObject::kMapOffset)); - __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex); - __ sw(scratch, FieldMemOperand(result, JSObject::kElementsOffset)); - __ sw(scratch, FieldMemOperand(result, JSObject::kPropertiesOffset)); - if (initial_map->inobject_properties() != 0) { - __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); - for (int i = 0; i < initial_map->inobject_properties(); i++) { - int property_offset = JSObject::kHeaderSize + i * kPointerSize; - __ sw(scratch, FieldMemOperand(result, property_offset)); - } - } -} - - -void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { - Register result = ToRegister(instr->result()); - Handle initial_map = instr->hydrogen()->constructor_initial_map(); - int instance_size = initial_map->instance_size(); - - // TODO(3095996): Get rid of this. For now, we need to make the - // result register contain a valid pointer because it is already - // contained in the register pointer map. - __ mov(result, zero_reg); - - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); - __ li(a0, Operand(Smi::FromInt(instance_size))); - __ push(a0); - CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); - __ StoreToSafepointRegisterSlot(v0, result); -} - - void LCodeGen::DoAllocate(LAllocate* instr) { class DeferredAllocate: public LDeferredCode { public: diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h index 2f4e140..a208c40 100644 --- a/src/mips/lithium-codegen-mips.h +++ b/src/mips/lithium-codegen-mips.h @@ -151,7 +151,6 @@ class LCodeGen BASE_EMBEDDED { void DoDeferredRandom(LRandom* instr); void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); void DoDeferredStringCharFromCode(LStringCharFromCode* instr); - void DoDeferredAllocateObject(LAllocateObject* instr); void DoDeferredAllocate(LAllocate* instr); void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, Label* map_check); diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index 2325064..795f58f 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -2263,14 +2263,6 @@ LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) { } -LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) { - info()->MarkAsDeferredCalling(); - LAllocateObject* result = - new(zone()) LAllocateObject(TempRegister(), TempRegister()); - return AssignPointerMap(DefineAsRegister(result)); -} - - LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { info()->MarkAsDeferredCalling(); LOperand* size = instr->size()->IsConstant() diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h index 01dd6c2..50feee0 100644 --- a/src/mips/lithium-mips.h +++ b/src/mips/lithium-mips.h @@ -49,7 +49,6 @@ class LCodeGen; #define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \ V(AccessArgumentsAt) \ V(AddI) \ - V(AllocateObject) \ V(Allocate) \ V(ApplyArguments) \ V(ArgumentsElements) \ @@ -2398,21 +2397,6 @@ class LClampTToUint8: public LTemplateInstruction<1, 1, 1> { }; -class LAllocateObject: public LTemplateInstruction<1, 1, 2> { - public: - LAllocateObject(LOperand* temp, LOperand* temp2) { - temps_[0] = temp; - temps_[1] = temp2; - } - - LOperand* temp() { return temps_[0]; } - LOperand* temp2() { return temps_[1]; } - - DECLARE_CONCRETE_INSTRUCTION(AllocateObject, "allocate-object") - DECLARE_HYDROGEN_ACCESSOR(AllocateObject) -}; - - class LAllocate: public LTemplateInstruction<1, 2, 2> { public: LAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) { diff --git a/src/objects.h b/src/objects.h index ac748ee..11b231f 100644 --- a/src/objects.h +++ b/src/objects.h @@ -5443,6 +5443,13 @@ class Map: public HeapObject { int NumberOfDescribedProperties(DescriptorFlag which = OWN_DESCRIPTORS, PropertyAttributes filter = NONE); + // Returns the number of slots allocated for the initial properties + // backing storage for instances of this map. + int InitialPropertiesLength() { + return pre_allocated_property_fields() + unused_property_fields() - + inobject_properties(); + } + // Casting. static inline Map* cast(Object* obj); diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index cb3cd44..8d86675 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -5088,94 +5088,6 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { } -void LCodeGen::DoAllocateObject(LAllocateObject* instr) { - class DeferredAllocateObject: public LDeferredCode { - public: - DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr) - : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } - virtual LInstruction* instr() { return instr_; } - private: - LAllocateObject* instr_; - }; - - DeferredAllocateObject* deferred = - new(zone()) DeferredAllocateObject(this, instr); - - Register result = ToRegister(instr->result()); - Register scratch = ToRegister(instr->temp()); - Handle constructor = instr->hydrogen()->constructor(); - Handle initial_map = instr->hydrogen()->constructor_initial_map(); - int instance_size = initial_map->instance_size(); - ASSERT(initial_map->pre_allocated_property_fields() + - initial_map->unused_property_fields() - - initial_map->inobject_properties() == 0); - - __ Allocate(instance_size, result, no_reg, scratch, deferred->entry(), - TAG_OBJECT); - - __ bind(deferred->exit()); - if (FLAG_debug_code) { - Label is_in_new_space; - __ JumpIfInNewSpace(result, scratch, &is_in_new_space); - __ Abort("Allocated object is not in new-space"); - __ bind(&is_in_new_space); - } - - // Load the initial map. - Register map = scratch; - __ LoadHeapObject(scratch, constructor); - __ movq(map, FieldOperand(scratch, JSFunction::kPrototypeOrInitialMapOffset)); - - if (FLAG_debug_code) { - __ AssertNotSmi(map); - __ cmpb(FieldOperand(map, Map::kInstanceSizeOffset), - Immediate(instance_size >> kPointerSizeLog2)); - __ Assert(equal, "Unexpected instance size"); - __ cmpb(FieldOperand(map, Map::kPreAllocatedPropertyFieldsOffset), - Immediate(initial_map->pre_allocated_property_fields())); - __ Assert(equal, "Unexpected pre-allocated property fields count"); - __ cmpb(FieldOperand(map, Map::kUnusedPropertyFieldsOffset), - Immediate(initial_map->unused_property_fields())); - __ Assert(equal, "Unexpected unused property fields count"); - __ cmpb(FieldOperand(map, Map::kInObjectPropertiesOffset), - Immediate(initial_map->inobject_properties())); - __ Assert(equal, "Unexpected in-object property fields count"); - } - - // Initialize map and fields of the newly allocated object. - ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); - __ movq(FieldOperand(result, JSObject::kMapOffset), map); - __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex); - __ movq(FieldOperand(result, JSObject::kElementsOffset), scratch); - __ movq(FieldOperand(result, JSObject::kPropertiesOffset), scratch); - if (initial_map->inobject_properties() != 0) { - __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); - for (int i = 0; i < initial_map->inobject_properties(); i++) { - int property_offset = JSObject::kHeaderSize + i * kPointerSize; - __ movq(FieldOperand(result, property_offset), scratch); - } - } -} - - -void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { - Register result = ToRegister(instr->result()); - Handle initial_map = instr->hydrogen()->constructor_initial_map(); - int instance_size = initial_map->instance_size(); - - // TODO(3095996): Get rid of this. For now, we need to make the - // result register contain a valid pointer because it is already - // contained in the register pointer map. - __ Set(result, 0); - - PushSafepointRegistersScope scope(this); - __ Push(Smi::FromInt(instance_size)); - CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); - __ StoreToSafepointRegisterSlot(result, rax); -} - - void LCodeGen::DoAllocate(LAllocate* instr) { class DeferredAllocate: public LDeferredCode { public: diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h index 9890649..07a948c 100644 --- a/src/x64/lithium-codegen-x64.h +++ b/src/x64/lithium-codegen-x64.h @@ -130,7 +130,6 @@ class LCodeGen BASE_EMBEDDED { void DoDeferredRandom(LRandom* instr); void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); void DoDeferredStringCharFromCode(LStringCharFromCode* instr); - void DoDeferredAllocateObject(LAllocateObject* instr); void DoDeferredAllocate(LAllocate* instr); void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, Label* map_check); diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index fe23709..44102a0 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -2328,13 +2328,6 @@ LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) { } -LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) { - info()->MarkAsDeferredCalling(); - LAllocateObject* result = new(zone()) LAllocateObject(TempRegister()); - return AssignPointerMap(DefineAsRegister(result)); -} - - LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { info()->MarkAsDeferredCalling(); LOperand* size = instr->size()->IsConstant() diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h index 36b080f..1121af5 100644 --- a/src/x64/lithium-x64.h +++ b/src/x64/lithium-x64.h @@ -50,7 +50,6 @@ class LCodeGen; V(AccessArgumentsAt) \ V(AddI) \ V(Allocate) \ - V(AllocateObject) \ V(ApplyArguments) \ V(ArgumentsElements) \ V(ArgumentsLength) \ @@ -2363,19 +2362,6 @@ class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> { }; -class LAllocateObject: public LTemplateInstruction<1, 0, 1> { - public: - explicit LAllocateObject(LOperand* temp) { - temps_[0] = temp; - } - - LOperand* temp() { return temps_[0]; } - - DECLARE_CONCRETE_INSTRUCTION(AllocateObject, "allocate-object") - DECLARE_HYDROGEN_ACCESSOR(AllocateObject) -}; - - class LAllocate: public LTemplateInstruction<1, 1, 1> { public: LAllocate(LOperand* size, LOperand* temp) { -- 2.7.4