LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
bool is_in_object = instr->access().IsInobject();
bool needs_write_barrier = instr->NeedsWriteBarrier();
- bool needs_write_barrier_for_map = instr->has_transition() &&
- instr->NeedsWriteBarrierForMap();
LOperand* obj;
if (needs_write_barrier) {
? UseRegister(instr->object())
: UseTempRegister(instr->object());
} else {
- obj = needs_write_barrier_for_map
- ? UseRegister(instr->object())
- : UseRegisterAtStart(instr->object());
+ obj = UseRegisterAtStart(instr->object());
}
LOperand* val;
val = UseRegister(instr->value());
}
- // We need a temporary register for write barrier of the map field.
- LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
-
- LInstruction* result = new(zone()) LStoreNamedField(obj, val, temp);
+ LInstruction* result = new(zone()) LStoreNamedField(obj, val);
if (!instr->access().IsExternalMemory() &&
instr->field_representation().IsHeapObject() &&
!instr->value()->type().IsHeapObject()) {
};
-class LStoreNamedField V8_FINAL : public LTemplateInstruction<0, 2, 1> {
+class LStoreNamedField V8_FINAL : public LTemplateInstruction<0, 2, 0> {
public:
- LStoreNamedField(LOperand* object, LOperand* value, LOperand* temp) {
+ LStoreNamedField(LOperand* object, LOperand* value) {
inputs_[0] = object;
inputs_[1] = value;
- temps_[0] = temp;
}
LOperand* object() { return inputs_[0]; }
LOperand* value() { return inputs_[1]; }
- LOperand* temp() { return temps_[0]; }
DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
}
} else if (representation.IsDouble()) {
ASSERT(access.IsInobject());
- ASSERT(!instr->hydrogen()->has_transition());
ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
DwVfpRegister value = ToDoubleRegister(instr->value());
__ vstr(value, FieldMemOperand(object, offset));
return;
}
- if (instr->hydrogen()->has_transition()) {
- Handle<Map> transition = instr->hydrogen()->transition_map();
- AddDeprecationDependency(transition);
- __ mov(scratch, Operand(transition));
- __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
- if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
- Register temp = ToRegister(instr->temp());
- // Update the write barrier for the map field.
- __ RecordWriteField(object,
- HeapObject::kMapOffset,
- scratch,
- temp,
- GetLinkRegisterState(),
- kSaveFPRegs,
- OMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- }
- }
-
// Do the store.
Register value = ToRegister(instr->value());
if (access.IsInobject()) {
value = UseRegisterAndClobber(instr->value());
temp0 = TempRegister();
temp1 = TempRegister();
- } else if (instr->NeedsWriteBarrierForMap()) {
- value = UseRegister(instr->value());
- temp0 = TempRegister();
- temp1 = TempRegister();
} else {
value = UseRegister(instr->value());
temp0 = TempRegister();
int offset = access.offset();
if (access.IsExternalMemory()) {
- ASSERT(!instr->hydrogen()->has_transition());
ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
Register value = ToRegister(instr->value());
__ Store(value, MemOperand(object, offset), representation);
return;
} else if (representation.IsDouble()) {
ASSERT(access.IsInobject());
- ASSERT(!instr->hydrogen()->has_transition());
ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
FPRegister value = ToDoubleRegister(instr->value());
__ Str(value, FieldMemOperand(object, offset));
check_needed = OMIT_SMI_CHECK;
}
- if (instr->hydrogen()->has_transition()) {
- Handle<Map> transition = instr->hydrogen()->transition_map();
- AddDeprecationDependency(transition);
- // Store the new map value.
- Register new_map_value = ToRegister(instr->temp0());
- __ Mov(new_map_value, Operand(transition));
- __ Str(new_map_value, FieldMemOperand(object, HeapObject::kMapOffset));
- if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
- // Update the write barrier for the map field.
- __ RecordWriteField(object,
- HeapObject::kMapOffset,
- new_map_value,
- ToRegister(instr->temp1()),
- GetLinkRegisterState(),
- kSaveFPRegs,
- OMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- }
- }
-
// Do the store.
Register destination;
if (access.IsInobject()) {
void ReduceStoreNamedField(HStoreNamedField* instr) {
HValue* object = instr->object()->ActualValue();
- if (instr->has_transition()) {
- // This store transitions the object to a new map.
- Kill(object);
- HConstant* c_transition = HConstant::cast(instr->transition());
- HCheckTableEntry::State state = c_transition->HasStableMapValue()
- ? HCheckTableEntry::CHECKED_STABLE
- : HCheckTableEntry::CHECKED;
- Insert(object, NULL, c_transition->MapValue(), state);
- } else if (instr->access().IsMap()) {
+ if (instr->access().IsMap()) {
// This is a store directly to the map field of the object.
Kill(object);
if (!instr->value()->IsConstant()) return;
switch (instr->opcode()) {
case HValue::kStoreNamedField: {
HStoreNamedField* store = HStoreNamedField::cast(instr);
- if (store->access().IsMap() || store->has_transition()) {
+ if (store->access().IsMap()) {
objects_.Add(store->object(), zone);
}
break;
ASSERT(store->access().IsInobject());
state = NewStateCopy(store->previous(), state);
state->SetOperandAt(index, store->value());
- if (store->has_transition()) {
- state->SetOperandAt(0, store->transition());
- }
if (store->HasObservableSideEffects()) {
state->ReuseSideEffectsFromStore(store);
}
store->DeleteAndReplaceWith(store->ActualValue());
if (FLAG_trace_escape_analysis) {
- PrintF("Replacing store #%d%s\n", instr->id(),
- store->has_transition() ? " (with transition)" : "");
+ PrintF("Replacing store #%d\n", instr->id());
}
break;
}
if (NeedsWriteBarrier()) {
stream->Add(" (write-barrier)");
}
- if (has_transition()) {
- stream->Add(" (transition map %p)", *transition_map());
- }
}
};
-class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
+class HStoreNamedField V8_FINAL : public HTemplateInstruction<2> {
public:
DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
HObjectAccess, HValue*);
HValue* object() const { return OperandAt(0); }
HValue* value() const { return OperandAt(1); }
- HValue* transition() const { return OperandAt(2); }
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()) {
- return Handle<Map>::cast(
- HConstant::cast(transition())->handle(Isolate::Current()));
- } else {
- return Handle<Map>();
- }
- }
-
- void SetTransition(HConstant* transition) {
- ASSERT(!has_transition()); // Only set once.
- SetOperandAt(2, transition);
- has_transition_ = true;
- }
-
bool NeedsWriteBarrier() {
- ASSERT(!field_representation().IsDouble() || !has_transition());
if (IsSkipWriteBarrier()) return false;
if (field_representation().IsDouble()) return false;
if (field_representation().IsSmi()) return false;
new_space_dominator());
}
- bool NeedsWriteBarrierForMap() {
- if (IsSkipWriteBarrier()) return false;
- return ReceiverObjectNeedsWriteBarrier(object(), transition(),
- new_space_dominator());
- }
-
Representation field_representation() const {
return access_.representation();
}
: access_(access),
new_space_dominator_(NULL),
write_barrier_mode_(UPDATE_WRITE_BARRIER),
- has_transition_(false),
store_mode_(store_mode) {
// Stores to a non existing in-object property are allowed only to the
// newly allocated objects (via HAllocate or HInnerAllocatedObject).
obj->IsAllocate() || obj->IsInnerAllocatedObject());
SetOperandAt(0, obj);
SetOperandAt(1, val);
- SetOperandAt(2, obj);
access.SetGVNFlags(this, STORE);
}
HObjectAccess access_;
HValue* new_space_dominator_;
WriteBarrierMode write_barrier_mode_ : 1;
- bool has_transition_ : 1;
StoreFieldOrKeyedMode store_mode_ : 1;
};
HValue* object = instr->object()->ActualValue();
HValue* value = instr->value();
- if (instr->has_transition()) {
- // A transition introduces a new field and alters the map of the object.
- // Since the field in the object is new, it cannot alias existing entries.
- // TODO(titzer): introduce a constant for the new map and remember it.
- KillFieldInternal(object, FieldOf(JSObject::kMapOffset), NULL);
- } else {
+ if (instr->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
// Kill non-equivalent may-alias entries.
KillFieldInternal(object, field, value);
}
while (i < unobserved_.length()) {
HStoreNamedField* prev = unobserved_.at(i);
if (aliasing_->MustAlias(object, prev->object()->ActualValue()) &&
- store->access().Equals(prev->access())) {
+ store->access().Equals(prev->access()) &&
+ (!SmiValuesAre32Bits() ||
+ !store->field_representation().IsSmi() ||
+ store->store_mode() == STORE_TO_INITIALIZED_ENTRY ||
+ prev->store_mode() == INITIALIZING_STORE)) {
// This store is guaranteed to overwrite the previous store.
prev->DeleteAndReplaceWith(NULL);
TRACE(("++ Unobserved store S%d overwritten by S%d\n",
i++;
}
}
- // Only non-transitioning stores are removable.
- if (!store->has_transition()) {
- TRACE(("-- Might remove store S%d\n", store->id()));
- unobserved_.Add(store, zone());
- }
+ TRACE(("-- Might remove store S%d\n", store->id()));
+ unobserved_.Add(store, zone());
}
if (transition_to_field) {
Handle<Map> transition(info->transition());
ASSERT(!transition->is_deprecated());
- instr->SetTransition(Add<HConstant>(transition));
+ if (transition->CanBeDeprecated()) {
+ Map::AddDependentCompilationInfo(
+ transition, DependentCode::kTransitionGroup, top_info());
+ }
+ Add<HStoreNamedField>(checked_object->ActualValue(),
+ HObjectAccess::ForMap(),
+ Add<HConstant>(transition),
+ STORE_TO_INITIALIZED_ENTRY);
}
return instr;
}
}
} else if (representation.IsDouble()) {
ASSERT(access.IsInobject());
- ASSERT(!instr->hydrogen()->has_transition());
ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
XMMRegister value = ToDoubleRegister(instr->value());
__ movsd(FieldOperand(object, offset), value);
return;
}
- if (instr->hydrogen()->has_transition()) {
- Handle<Map> transition = instr->hydrogen()->transition_map();
- AddDeprecationDependency(transition);
- if (!instr->hydrogen()->NeedsWriteBarrierForMap()) {
- __ mov(FieldOperand(object, HeapObject::kMapOffset), transition);
- } else {
- Register temp = ToRegister(instr->temp());
- Register temp_map = ToRegister(instr->temp_map());
- __ mov(temp_map, transition);
- __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map);
- // Update the write barrier for the map field.
- __ RecordWriteField(object,
- HeapObject::kMapOffset,
- temp_map,
- temp,
- kSaveFPRegs,
- OMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- }
- }
-
// Do the store.
Register write_register = object;
if (!access.IsInobject()) {
bool is_external_location = instr->access().IsExternalMemory() &&
instr->access().offset() == 0;
bool needs_write_barrier = instr->NeedsWriteBarrier();
- bool needs_write_barrier_for_map = instr->has_transition() &&
- instr->NeedsWriteBarrierForMap();
LOperand* obj;
if (needs_write_barrier) {
} else if (is_external_location) {
ASSERT(!is_in_object);
ASSERT(!needs_write_barrier);
- ASSERT(!needs_write_barrier_for_map);
obj = UseRegisterOrConstant(instr->object());
} else {
- obj = needs_write_barrier_for_map
- ? UseRegister(instr->object())
- : UseRegisterAtStart(instr->object());
+ obj = UseRegisterAtStart(instr->object());
}
bool can_be_constant = instr->value()->IsConstant() &&
// We only need a scratch register if we have a write barrier or we
// have a store into the properties array (not in-object-property).
- LOperand* temp = (!is_in_object || needs_write_barrier ||
- needs_write_barrier_for_map) ? TempRegister() : NULL;
-
- // We need a temporary register for write barrier of the map field.
- LOperand* temp_map = needs_write_barrier_for_map ? TempRegister() : NULL;
+ LOperand* temp = (!is_in_object || needs_write_barrier)
+ ? TempRegister() : NULL;
LInstruction* result =
- new(zone()) LStoreNamedField(obj, val, temp, temp_map);
+ new(zone()) LStoreNamedField(obj, val, temp);
if (!instr->access().IsExternalMemory() &&
instr->field_representation().IsHeapObject() &&
(val->IsConstantOperand()
};
-class LStoreNamedField V8_FINAL : public LTemplateInstruction<0, 2, 2> {
+class LStoreNamedField V8_FINAL : public LTemplateInstruction<0, 2, 1> {
public:
LStoreNamedField(LOperand* obj,
LOperand* val,
- LOperand* temp,
- LOperand* temp_map) {
+ LOperand* temp) {
inputs_[0] = obj;
inputs_[1] = val;
temps_[0] = temp;
- temps_[1] = temp_map;
}
LOperand* object() { return inputs_[0]; }
LOperand* value() { return inputs_[1]; }
LOperand* temp() { return temps_[0]; }
- LOperand* temp_map() { return temps_[1]; }
DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
}
-void LCodeGenBase::AddDeprecationDependency(Handle<Map> map) {
- if (map->is_deprecated()) return Abort(kMapBecameDeprecated);
- chunk_->AddDeprecationDependency(map);
-}
-
-
void LCodeGenBase::AddStabilityDependency(Handle<Map> map) {
if (!map->is_stable()) return Abort(kMapBecameUnstable);
chunk_->AddStabilityDependency(map);
void Abort(BailoutReason reason);
// Methods for code dependencies.
- void AddDeprecationDependency(Handle<Map> map);
void AddStabilityDependency(Handle<Map> map);
};
instructions_(32, graph->zone()),
pointer_maps_(8, graph->zone()),
inlined_closures_(1, graph->zone()),
- deprecation_dependencies_(MapLess(), MapAllocator(graph->zone())),
stability_dependencies_(MapLess(), MapAllocator(graph->zone())) {
}
void LChunk::CommitDependencies(Handle<Code> code) const {
- for (MapSet::const_iterator it = deprecation_dependencies_.begin(),
- iend = deprecation_dependencies_.end(); it != iend; ++it) {
- Handle<Map> map = *it;
- ASSERT(!map->is_deprecated());
- ASSERT(map->CanBeDeprecated());
- Map::AddDependentCode(map, DependentCode::kTransitionGroup, code);
- }
-
for (MapSet::const_iterator it = stability_dependencies_.begin(),
iend = stability_dependencies_.end(); it != iend; ++it) {
Handle<Map> map = *it;
inlined_closures_.Add(closure, zone());
}
- void AddDeprecationDependency(Handle<Map> map) {
- ASSERT(!map->is_deprecated());
- if (!map->CanBeDeprecated()) return;
- ASSERT(!info_->IsStub());
- deprecation_dependencies_.insert(map);
- }
-
void AddStabilityDependency(Handle<Map> map) {
ASSERT(map->is_stable());
if (!map->CanTransition()) return;
ZoneList<LInstruction*> instructions_;
ZoneList<LPointerMap*> pointer_maps_;
ZoneList<Handle<JSFunction> > inlined_closures_;
- MapSet deprecation_dependencies_;
MapSet stability_dependencies_;
};
}
} else if (representation.IsDouble()) {
ASSERT(access.IsInobject());
- ASSERT(!hinstr->has_transition());
ASSERT(!hinstr->NeedsWriteBarrier());
XMMRegister value = ToDoubleRegister(instr->value());
__ movsd(FieldOperand(object, offset), value);
return;
}
- if (hinstr->has_transition()) {
- Handle<Map> transition = hinstr->transition_map();
- AddDeprecationDependency(transition);
- if (!hinstr->NeedsWriteBarrierForMap()) {
- __ Move(FieldOperand(object, HeapObject::kMapOffset), transition);
- } else {
- Register temp = ToRegister(instr->temp());
- __ Move(kScratchRegister, transition);
- __ movp(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister);
- // Update the write barrier for the map field.
- __ RecordWriteField(object,
- HeapObject::kMapOffset,
- kScratchRegister,
- temp,
- kSaveFPRegs,
- OMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- }
- }
-
// Do the store.
Register write_register = object;
if (!access.IsInobject()) {
bool is_external_location = instr->access().IsExternalMemory() &&
instr->access().offset() == 0;
bool needs_write_barrier = instr->NeedsWriteBarrier();
- bool needs_write_barrier_for_map = instr->has_transition() &&
- instr->NeedsWriteBarrierForMap();
LOperand* obj;
if (needs_write_barrier) {
} else if (is_external_location) {
ASSERT(!is_in_object);
ASSERT(!needs_write_barrier);
- ASSERT(!needs_write_barrier_for_map);
obj = UseRegisterOrConstant(instr->object());
} else {
- obj = needs_write_barrier_for_map
- ? UseRegister(instr->object())
- : UseRegisterAtStart(instr->object());
+ obj = UseRegisterAtStart(instr->object());
}
bool can_be_constant = instr->value()->IsConstant() &&
// We only need a scratch register if we have a write barrier or we
// have a store into the properties array (not in-object-property).
- LOperand* temp = (!is_in_object || needs_write_barrier ||
- needs_write_barrier_for_map) ? TempRegister() : NULL;
+ LOperand* temp = (!is_in_object || needs_write_barrier)
+ ? TempRegister() : NULL;
LInstruction* result = new(zone()) LStoreNamedField(obj, val, temp);
if (!instr->access().IsExternalMemory() &&