Commit a3fed0af authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

Fix constructors for HLoadNamedField.

Also try to determine an appropriate HType for tracked fields,
instead of (incorrectly) using HType::NonPrimitive() everywhere.

R=svenpanne@chromium.org

Review URL: https://codereview.chromium.org/269353003

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21186 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 24696e1d
...@@ -340,8 +340,10 @@ class HCheckTable : public ZoneObject { ...@@ -340,8 +340,10 @@ class HCheckTable : public ZoneObject {
// Reduce a load of the map field when it is known to be a constant. // Reduce a load of the map field when it is known to be a constant.
if (!instr->access().IsMap()) { if (!instr->access().IsMap()) {
// Check if we introduce field maps here. // Check if we introduce field maps here.
if (instr->maps()->size() != 0) { MapSet maps = instr->maps();
Insert(instr, instr, instr->maps()); if (maps != NULL) {
ASSERT_NE(0, maps->size());
Insert(instr, NULL, maps);
} }
return; return;
} }
......
...@@ -3418,7 +3418,7 @@ void HLoadNamedField::PrintDataTo(StringStream* stream) { ...@@ -3418,7 +3418,7 @@ void HLoadNamedField::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream); object()->PrintNameTo(stream);
access_.PrintTo(stream); access_.PrintTo(stream);
if (maps()->size() != 0) { if (maps() != NULL) {
stream->Add(" [%p", *maps()->at(0).handle()); stream->Add(" [%p", *maps()->at(0).handle());
for (int i = 1; i < maps()->size(); ++i) { for (int i = 1; i < maps()->size(); ++i) {
stream->Add(",%p", *maps()->at(i).handle()); stream->Add(",%p", *maps()->at(i).handle());
......
...@@ -6212,28 +6212,10 @@ class HObjectAccess V8_FINAL { ...@@ -6212,28 +6212,10 @@ class HObjectAccess V8_FINAL {
class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> { class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
public: public:
static HLoadNamedField* New(Zone* zone, HValue* context, DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*,
HValue* object, HValue* dependency, HValue*, HObjectAccess);
HObjectAccess access) { DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue*, HValue*,
return new(zone) HLoadNamedField( HObjectAccess, const UniqueSet<Map>*, HType);
object, dependency, access, new(zone) UniqueSet<Map>());
}
static HLoadNamedField* New(Zone* zone, HValue* context,
HValue* object, HValue* dependency,
HObjectAccess access, SmallMapList* map_list,
CompilationInfo* info) {
UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
for (int i = 0; i < map_list->length(); ++i) {
Handle<Map> map = map_list->at(i);
maps->Add(Unique<Map>::CreateImmovable(map), zone);
// TODO(bmeurer): Get rid of this shit!
if (map->CanTransition()) {
Map::AddDependentCompilationInfo(
map, DependentCode::kPrototypeCheckGroup, info);
}
}
return new(zone) HLoadNamedField(object, dependency, access, maps);
}
HValue* object() { return OperandAt(0); } HValue* object() { return OperandAt(0); }
HValue* dependency() { HValue* dependency() {
...@@ -6262,23 +6244,36 @@ class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> { ...@@ -6262,23 +6244,36 @@ class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
virtual Range* InferRange(Zone* zone) V8_OVERRIDE; virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
bool CanBeReplacedWith(HValue* other) const {
if (!type().Equals(other->type())) return false;
if (!representation().Equals(other->representation())) return false;
if (!other->IsLoadNamedField()) return true;
HLoadNamedField* that = HLoadNamedField::cast(other);
if (this->maps_ == that->maps_) return true;
if (this->maps_ == NULL || that->maps_ == NULL) return false;
return this->maps_->IsSubset(that->maps_);
}
DECLARE_CONCRETE_INSTRUCTION(LoadNamedField) DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
protected: protected:
virtual bool DataEquals(HValue* other) V8_OVERRIDE { virtual bool DataEquals(HValue* other) V8_OVERRIDE {
HLoadNamedField* b = HLoadNamedField::cast(other); HLoadNamedField* that = HLoadNamedField::cast(other);
return access_.Equals(b->access_) && this->maps()->Equals(b->maps()); if (!this->access_.Equals(that->access_)) return false;
if (this->maps_ == that->maps_) return true;
return (this->maps_ != NULL &&
that->maps_ != NULL &&
this->maps_->Equals(that->maps_));
} }
private: private:
HLoadNamedField(HValue* object, HLoadNamedField(HValue* object,
HValue* dependency, HValue* dependency,
HObjectAccess access, HObjectAccess access)
const UniqueSet<Map>* maps) : access_(access), maps_(NULL) {
: access_(access), maps_(maps) { ASSERT_NOT_NULL(object);
ASSERT(object != NULL);
SetOperandAt(0, object); SetOperandAt(0, object);
SetOperandAt(1, dependency != NULL ? dependency : object); SetOperandAt(1, dependency ? dependency : object);
Representation representation = access.representation(); Representation representation = access.representation();
if (representation.IsInteger8() || if (representation.IsInteger8() ||
...@@ -6298,6 +6293,8 @@ class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> { ...@@ -6298,6 +6293,8 @@ class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
representation.IsInteger32()) { representation.IsInteger32()) {
set_representation(representation); set_representation(representation);
} else if (representation.IsHeapObject()) { } else if (representation.IsHeapObject()) {
// TODO(bmeurer): This is probably broken. What we actually want to to
// instead is set_representation(Representation::HeapObject()).
set_type(HType::NonPrimitive()); set_type(HType::NonPrimitive());
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
} else { } else {
...@@ -6306,6 +6303,28 @@ class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> { ...@@ -6306,6 +6303,28 @@ class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
access.SetGVNFlags(this, LOAD); access.SetGVNFlags(this, LOAD);
} }
HLoadNamedField(HValue* object,
HValue* dependency,
HObjectAccess access,
const UniqueSet<Map>* maps,
HType type)
: HTemplateInstruction<2>(type), access_(access), maps_(maps) {
ASSERT_NOT_NULL(maps);
ASSERT_NE(0, maps->size());
ASSERT_NOT_NULL(object);
SetOperandAt(0, object);
SetOperandAt(1, dependency ? dependency : object);
ASSERT(access.representation().IsHeapObject());
// TODO(bmeurer): This is probably broken. What we actually want to to
// instead is set_representation(Representation::HeapObject()).
if (!type.IsHeapObject()) set_type(HType::NonPrimitive());
set_representation(Representation::Tagged());
access.SetGVNFlags(this, LOAD);
}
virtual bool IsDeletable() const V8_OVERRIDE { return true; } virtual bool IsDeletable() const V8_OVERRIDE { return true; }
HObjectAccess access_; HObjectAccess access_;
......
...@@ -53,12 +53,7 @@ class HLoadEliminationTable : public ZoneObject { ...@@ -53,12 +53,7 @@ class HLoadEliminationTable : public ZoneObject {
FieldOf(l->access()), FieldOf(l->access()),
l->object()->ActualValue()->id())); l->object()->ActualValue()->id()));
HValue* result = load(l); HValue* result = load(l);
if (result != instr && if (result != instr && l->CanBeReplacedWith(result)) {
result->type().Equals(instr->type()) &&
result->representation().Equals(instr->representation()) &&
(!result->IsLoadNamedField() ||
HLoadNamedField::cast(instr)->maps()->IsSubset(
HLoadNamedField::cast(result)->maps()))) {
// The load can be replaced with a previous load or a value. // The load can be replaced with a previous load or a value.
TRACE((" replace L%d -> v%d\n", instr->id(), result->id())); TRACE((" replace L%d -> v%d\n", instr->id(), result->id()));
instr->DeleteAndReplaceWith(result); instr->DeleteAndReplaceWith(result);
......
...@@ -5348,8 +5348,24 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField( ...@@ -5348,8 +5348,24 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
// Load the double value from it. // Load the double value from it.
access = HObjectAccess::ForHeapNumberValue(); access = HObjectAccess::ForHeapNumberValue();
} }
SmallMapList* map_list = info->field_maps();
if (map_list->length() == 0) {
return New<HLoadNamedField>(checked_object, checked_object, access);
}
UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(map_list->length(), zone());
for (int i = 0; i < map_list->length(); ++i) {
Handle<Map> map = map_list->at(i);
maps->Add(Unique<Map>::CreateImmovable(map), zone());
// TODO(bmeurer): Get rid of this shit!
if (map->CanTransition()) {
Map::AddDependentCompilationInfo(
map, DependentCode::kPrototypeCheckGroup, top_info());
}
}
return New<HLoadNamedField>( return New<HLoadNamedField>(
checked_object, checked_object, access, info->field_maps(), top_info()); checked_object, checked_object, access, maps, info->field_type());
} }
...@@ -5488,6 +5504,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible( ...@@ -5488,6 +5504,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
} }
} }
info->GeneralizeRepresentation(r); info->GeneralizeRepresentation(r);
info->field_type_ = info->field_type_.Combine(field_type_);
return true; return true;
} }
...@@ -5539,8 +5556,9 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { ...@@ -5539,8 +5556,9 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps( void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
Handle<Map> map) { Handle<Map> map) {
// Clear any previously collected field maps. // Clear any previously collected field maps/type.
field_maps_.Clear(); field_maps_.Clear();
field_type_ = HType::Tagged();
// Figure out the field type from the accessor map. // Figure out the field type from the accessor map.
Handle<HeapType> field_type(lookup_.GetFieldTypeFromMap(*map), isolate()); Handle<HeapType> field_type(lookup_.GetFieldTypeFromMap(*map), isolate());
...@@ -5563,6 +5581,22 @@ void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps( ...@@ -5563,6 +5581,22 @@ void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
field_maps_.Sort(); field_maps_.Sort();
ASSERT_EQ(num_field_maps, field_maps_.length()); ASSERT_EQ(num_field_maps, field_maps_.length());
// Determine field HType from field HeapType.
if (field_type->Is(HeapType::Number())) {
field_type_ = HType::HeapNumber();
} else if (field_type->Is(HeapType::String())) {
field_type_ = HType::String();
} else if (field_type->Is(HeapType::Boolean())) {
field_type_ = HType::Boolean();
} else if (field_type->Is(HeapType::Array())) {
field_type_ = HType::JSArray();
} else if (field_type->Is(HeapType::Object())) {
field_type_ = HType::JSObject();
} else if (field_type->Is(HeapType::Null()) ||
field_type->Is(HeapType::Undefined())) {
field_type_ = HType::NonPrimitive();
}
// Add dependency on the map that introduced the field. // Add dependency on the map that introduced the field.
Map::AddDependentCompilationInfo( Map::AddDependentCompilationInfo(
handle(lookup_.GetFieldOwnerFromMap(*map), isolate()), handle(lookup_.GetFieldOwnerFromMap(*map), isolate()),
......
...@@ -2326,6 +2326,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { ...@@ -2326,6 +2326,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
access_type_(access_type), access_type_(access_type),
type_(type), type_(type),
name_(name), name_(name),
field_type_(HType::Tagged()),
access_(HObjectAccess::ForMap()) { } access_(HObjectAccess::ForMap()) { }
// Checkes whether this PropertyAccessInfo can be handled as a monomorphic // Checkes whether this PropertyAccessInfo can be handled as a monomorphic
...@@ -2392,6 +2393,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { ...@@ -2392,6 +2393,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
Handle<Object> constant() { return constant_; } Handle<Object> constant() { return constant_; }
Handle<Map> transition() { return handle(lookup_.GetTransitionTarget()); } Handle<Map> transition() { return handle(lookup_.GetTransitionTarget()); }
SmallMapList* field_maps() { return &field_maps_; } SmallMapList* field_maps() { return &field_maps_; }
HType field_type() const { return field_type_; }
HObjectAccess access() { return access_; } HObjectAccess access() { return access_; }
private: private:
...@@ -2422,6 +2424,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { ...@@ -2422,6 +2424,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
Handle<JSObject> api_holder_; Handle<JSObject> api_holder_;
Handle<Object> constant_; Handle<Object> constant_;
SmallMapList field_maps_; SmallMapList field_maps_;
HType field_type_;
HObjectAccess access_; HObjectAccess access_;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment