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
This commit is contained in:
ishell@chromium.org 2013-12-18 17:53:50 +00:00
parent c8583b59dc
commit 8c159ed4ec
5 changed files with 78 additions and 37 deletions

View File

@ -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<Map> 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;
};

View File

@ -5206,9 +5206,9 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
}
} else {
// This is a normal store.
instr = New<HStoreNamedField>(checked_object->ActualValue(),
field_access,
value);
instr = New<HStoreNamedField>(
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<HStoreNamedField>(object, access, result);
} else {
Representation representation = details.representation();
HInstruction* value_instruction = Add<HConstant>(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<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(),
value_instruction);
Add<HConstant>(value));
value_instruction = double_box;
} else if (representation.IsSmi() && value->IsUninitialized()) {
value_instruction = graph()->GetConstant0();
} else {
value_instruction = Add<HConstant>(value);
}
Add<HStoreNamedField>(object, access, value_instruction);

View File

@ -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()) {

View File

@ -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<Object> 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<Object> 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.

View File

@ -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());