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:
parent
c8583b59dc
commit
8c159ed4ec
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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()) {
|
||||
|
@ -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.
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user