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
This commit is contained in:
parent
24696e1d09
commit
a3fed0af84
@ -340,8 +340,10 @@ class HCheckTable : public ZoneObject {
|
||||
// Reduce a load of the map field when it is known to be a constant.
|
||||
if (!instr->access().IsMap()) {
|
||||
// Check if we introduce field maps here.
|
||||
if (instr->maps()->size() != 0) {
|
||||
Insert(instr, instr, instr->maps());
|
||||
MapSet maps = instr->maps();
|
||||
if (maps != NULL) {
|
||||
ASSERT_NE(0, maps->size());
|
||||
Insert(instr, NULL, maps);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -3418,7 +3418,7 @@ void HLoadNamedField::PrintDataTo(StringStream* stream) {
|
||||
object()->PrintNameTo(stream);
|
||||
access_.PrintTo(stream);
|
||||
|
||||
if (maps()->size() != 0) {
|
||||
if (maps() != NULL) {
|
||||
stream->Add(" [%p", *maps()->at(0).handle());
|
||||
for (int i = 1; i < maps()->size(); ++i) {
|
||||
stream->Add(",%p", *maps()->at(i).handle());
|
||||
|
@ -6212,28 +6212,10 @@ class HObjectAccess V8_FINAL {
|
||||
|
||||
class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
|
||||
public:
|
||||
static HLoadNamedField* New(Zone* zone, HValue* context,
|
||||
HValue* object, HValue* dependency,
|
||||
HObjectAccess access) {
|
||||
return new(zone) HLoadNamedField(
|
||||
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);
|
||||
}
|
||||
DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*,
|
||||
HValue*, HObjectAccess);
|
||||
DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue*, HValue*,
|
||||
HObjectAccess, const UniqueSet<Map>*, HType);
|
||||
|
||||
HValue* object() { return OperandAt(0); }
|
||||
HValue* dependency() {
|
||||
@ -6262,23 +6244,36 @@ class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
|
||||
virtual Range* InferRange(Zone* zone) 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)
|
||||
|
||||
protected:
|
||||
virtual bool DataEquals(HValue* other) V8_OVERRIDE {
|
||||
HLoadNamedField* b = HLoadNamedField::cast(other);
|
||||
return access_.Equals(b->access_) && this->maps()->Equals(b->maps());
|
||||
HLoadNamedField* that = HLoadNamedField::cast(other);
|
||||
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:
|
||||
HLoadNamedField(HValue* object,
|
||||
HValue* dependency,
|
||||
HObjectAccess access,
|
||||
const UniqueSet<Map>* maps)
|
||||
: access_(access), maps_(maps) {
|
||||
ASSERT(object != NULL);
|
||||
HObjectAccess access)
|
||||
: access_(access), maps_(NULL) {
|
||||
ASSERT_NOT_NULL(object);
|
||||
SetOperandAt(0, object);
|
||||
SetOperandAt(1, dependency != NULL ? dependency : object);
|
||||
SetOperandAt(1, dependency ? dependency : object);
|
||||
|
||||
Representation representation = access.representation();
|
||||
if (representation.IsInteger8() ||
|
||||
@ -6298,6 +6293,8 @@ class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
|
||||
representation.IsInteger32()) {
|
||||
set_representation(representation);
|
||||
} 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_representation(Representation::Tagged());
|
||||
} else {
|
||||
@ -6306,6 +6303,28 @@ class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
|
||||
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; }
|
||||
|
||||
HObjectAccess access_;
|
||||
|
@ -53,12 +53,7 @@ class HLoadEliminationTable : public ZoneObject {
|
||||
FieldOf(l->access()),
|
||||
l->object()->ActualValue()->id()));
|
||||
HValue* result = load(l);
|
||||
if (result != instr &&
|
||||
result->type().Equals(instr->type()) &&
|
||||
result->representation().Equals(instr->representation()) &&
|
||||
(!result->IsLoadNamedField() ||
|
||||
HLoadNamedField::cast(instr)->maps()->IsSubset(
|
||||
HLoadNamedField::cast(result)->maps()))) {
|
||||
if (result != instr && l->CanBeReplacedWith(result)) {
|
||||
// The load can be replaced with a previous load or a value.
|
||||
TRACE((" replace L%d -> v%d\n", instr->id(), result->id()));
|
||||
instr->DeleteAndReplaceWith(result);
|
||||
|
@ -5348,8 +5348,24 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
|
||||
// Load the double value from it.
|
||||
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>(
|
||||
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(
|
||||
}
|
||||
}
|
||||
info->GeneralizeRepresentation(r);
|
||||
info->field_type_ = info->field_type_.Combine(field_type_);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5539,8 +5556,9 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
|
||||
|
||||
void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
|
||||
Handle<Map> map) {
|
||||
// Clear any previously collected field maps.
|
||||
// Clear any previously collected field maps/type.
|
||||
field_maps_.Clear();
|
||||
field_type_ = HType::Tagged();
|
||||
|
||||
// Figure out the field type from the accessor map.
|
||||
Handle<HeapType> field_type(lookup_.GetFieldTypeFromMap(*map), isolate());
|
||||
@ -5563,6 +5581,22 @@ void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
|
||||
field_maps_.Sort();
|
||||
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.
|
||||
Map::AddDependentCompilationInfo(
|
||||
handle(lookup_.GetFieldOwnerFromMap(*map), isolate()),
|
||||
|
@ -2326,6 +2326,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
|
||||
access_type_(access_type),
|
||||
type_(type),
|
||||
name_(name),
|
||||
field_type_(HType::Tagged()),
|
||||
access_(HObjectAccess::ForMap()) { }
|
||||
|
||||
// Checkes whether this PropertyAccessInfo can be handled as a monomorphic
|
||||
@ -2392,6 +2393,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
|
||||
Handle<Object> constant() { return constant_; }
|
||||
Handle<Map> transition() { return handle(lookup_.GetTransitionTarget()); }
|
||||
SmallMapList* field_maps() { return &field_maps_; }
|
||||
HType field_type() const { return field_type_; }
|
||||
HObjectAccess access() { return access_; }
|
||||
|
||||
private:
|
||||
@ -2422,6 +2424,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
|
||||
Handle<JSObject> api_holder_;
|
||||
Handle<Object> constant_;
|
||||
SmallMapList field_maps_;
|
||||
HType field_type_;
|
||||
HObjectAccess access_;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user