From 8c159ed4ec6eeeb4bd675e7643cf66c70ab6b013 Mon Sep 17 00:00:00 2001 From: "ishell@chromium.org" Date: Wed, 18 Dec 2013 17:53:50 +0000 Subject: [PATCH] HStoreNamedField for Smis optimized for x64 R=verwaest@chromium.org Review URL: https://codereview.chromium.org/108413003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18360 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/hydrogen-instructions.h | 26 +++++++++++-- src/hydrogen.cc | 14 ++++--- src/objects-inl.h | 3 ++ src/x64/lithium-codegen-x64.cc | 70 +++++++++++++++++++++------------- src/x64/lithium-x64.cc | 2 +- 5 files changed, 78 insertions(+), 37 deletions(-) diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 6d595adb23..f82789f703 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -6503,10 +6503,20 @@ class HLoadKeyedGeneric V8_FINAL : public HTemplateInstruction<3> { }; +// Indicates whether the store is a store to an entry that was previously +// initialized or not. +enum StoreFieldOrKeyedMode { + INITIALIZING_STORE, + STORE_TO_INITIALIZED_ENTRY +}; + + class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> { public: DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*, HObjectAccess, HValue*); + DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*, + HObjectAccess, HValue*, StoreFieldOrKeyedMode); DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) @@ -6527,8 +6537,12 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> { field_representation().IsUInteger16() || field_representation().IsInteger32()) { return Representation::Integer32(); - } else if (field_representation().IsDouble() || - field_representation().IsSmi()) { + } else if (field_representation().IsDouble()) { + return field_representation(); + } else if (field_representation().IsSmi()) { + if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) { + return Representation::Integer32(); + } return field_representation(); } else if (field_representation().IsExternal()) { return Representation::External(); @@ -6555,6 +6569,7 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> { HObjectAccess access() const { return access_; } HValue* new_space_dominator() const { return new_space_dominator_; } bool has_transition() const { return has_transition_; } + StoreFieldOrKeyedMode store_mode() const { return store_mode_; } Handle transition_map() const { if (has_transition()) { @@ -6605,11 +6620,13 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> { private: HStoreNamedField(HValue* obj, HObjectAccess access, - HValue* val) + HValue* val, + StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE) : access_(access), new_space_dominator_(NULL), write_barrier_mode_(UPDATE_WRITE_BARRIER), - has_transition_(false) { + has_transition_(false), + store_mode_(store_mode) { SetOperandAt(0, obj); SetOperandAt(1, val); SetOperandAt(2, obj); @@ -6620,6 +6637,7 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> { HValue* new_space_dominator_; WriteBarrierMode write_barrier_mode_ : 1; bool has_transition_ : 1; + StoreFieldOrKeyedMode store_mode_ : 1; }; diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 339a623ead..4adaba30ae 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -5206,9 +5206,9 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( } } else { // This is a normal store. - instr = New(checked_object->ActualValue(), - field_access, - value); + instr = New( + checked_object->ActualValue(), field_access, value, + transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY); } if (transition_to_field) { @@ -9441,7 +9441,7 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( Add(object, access, result); } else { Representation representation = details.representation(); - HInstruction* value_instruction = Add(value); + HInstruction* value_instruction; if (representation.IsDouble()) { // Allocate a HeapNumber box and store the value into it. @@ -9456,8 +9456,12 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map()); Add(double_box, HObjectAccess::ForHeapNumberValue(), - value_instruction); + Add(value)); value_instruction = double_box; + } else if (representation.IsSmi() && value->IsUninitialized()) { + value_instruction = graph()->GetConstant0(); + } else { + value_instruction = Add(value); } Add(object, access, value_instruction); diff --git a/src/objects-inl.h b/src/objects-inl.h index d488fc05e8..994c991e28 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -267,6 +267,9 @@ bool Object::HasValidElements() { MaybeObject* Object::AllocateNewStorageFor(Heap* heap, Representation representation) { + if (FLAG_track_fields && representation.IsSmi() && IsUninitialized()) { + return Smi::FromInt(0); + } if (!FLAG_track_double_fields) return this; if (!representation.IsDouble()) return this; if (IsUninitialized()) { diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 560c4db190..31b2f217c6 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -3938,13 +3938,14 @@ void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { + HStoreNamedField* hinstr = instr->hydrogen(); Representation representation = instr->representation(); - HObjectAccess access = instr->hydrogen()->access(); + HObjectAccess access = hinstr->access(); int offset = access.offset(); if (access.IsExternalMemory()) { - ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); + ASSERT(!hinstr->NeedsWriteBarrier()); Register value = ToRegister(instr->value()); if (instr->object()->IsConstantOperand()) { ASSERT(value.is(rax)); @@ -3964,7 +3965,8 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { if (FLAG_track_fields && representation.IsSmi()) { if (instr->value()->IsConstantOperand()) { LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); - if (!IsSmiConstant(operand_value)) { + if (!IsInteger32Constant(operand_value) && + !IsSmiConstant(operand_value)) { DeoptimizeIf(no_condition, instr->environment()); } } @@ -3975,7 +3977,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { DeoptimizeIf(no_condition, instr->environment()); } } else { - if (!instr->hydrogen()->value()->type().IsHeapObject()) { + if (!hinstr->value()->type().IsHeapObject()) { Register value = ToRegister(instr->value()); Condition cc = masm()->CheckSmi(value); DeoptimizeIf(cc, instr->environment()); @@ -3984,14 +3986,14 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { } else if (FLAG_track_double_fields && representation.IsDouble()) { ASSERT(transition.is_null()); ASSERT(access.IsInobject()); - ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); + ASSERT(!hinstr->NeedsWriteBarrier()); XMMRegister value = ToDoubleRegister(instr->value()); __ movsd(FieldOperand(object, offset), value); return; } if (!transition.is_null()) { - if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { + if (!hinstr->NeedsWriteBarrierForMap()) { __ Move(FieldOperand(object, HeapObject::kMapOffset), transition); } else { Register temp = ToRegister(instr->temp()); @@ -4009,9 +4011,8 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { } // Do the store. - SmiCheck check_needed = - instr->hydrogen()->value()->IsHeapObject() - ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + SmiCheck check_needed = hinstr->value()->IsHeapObject() + ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; Register write_register = object; if (!access.IsInobject()) { @@ -4019,26 +4020,41 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { __ movq(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); } - if (instr->value()->IsConstantOperand()) { - LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); - if (operand_value->IsRegister()) { - Register value = ToRegister(operand_value); - __ Store(FieldOperand(write_register, offset), value, representation); - } else if (representation.IsInteger32()) { - int32_t value = ToInteger32(operand_value); - ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); - __ movl(FieldOperand(write_register, offset), Immediate(value)); - } else { - Handle handle_value = ToHandle(operand_value); - ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); - __ Move(FieldOperand(write_register, offset), handle_value); - } - } else { - Register value = ToRegister(instr->value()); - __ Store(FieldOperand(write_register, offset), value, representation); + if (representation.IsSmi() && + hinstr->value()->representation().IsInteger32()) { + ASSERT(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); + // Store int value directly to upper half of the smi. + STATIC_ASSERT(kSmiTag == 0); + STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); + offset += kPointerSize / 2; + representation = Representation::Integer32(); } - if (instr->hydrogen()->NeedsWriteBarrier()) { + Operand operand = FieldOperand(write_register, offset); + + if (instr->value()->IsRegister()) { + Register value = ToRegister(instr->value()); + __ Store(operand, value, representation); + } else { + LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); + if (IsInteger32Constant(operand_value)) { + ASSERT(!hinstr->NeedsWriteBarrier()); + int32_t value = ToInteger32(operand_value); + if (representation.IsSmi()) { + __ Move(operand, Smi::FromInt(value)); + + } else { + __ movl(operand, Immediate(value)); + } + + } else { + Handle handle_value = ToHandle(operand_value); + ASSERT(!hinstr->NeedsWriteBarrier()); + __ Move(operand, handle_value); + } + } + + if (hinstr->NeedsWriteBarrier()) { Register value = ToRegister(instr->value()); Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object; // Update the write barrier for the object for in-object properties. diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 480adf8650..41a331a07d 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -2296,7 +2296,7 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { } else if (can_be_constant) { val = UseRegisterOrConstant(instr->value()); } else if (FLAG_track_fields && instr->field_representation().IsSmi()) { - val = UseTempRegister(instr->value()); + val = UseRegister(instr->value()); } else if (FLAG_track_double_fields && instr->field_representation().IsDouble()) { val = UseRegisterAtStart(instr->value());