Commit 46d39cab authored by verwaest@chromium.org's avatar verwaest@chromium.org

Fix polymorphic to monomorphic load to take representation into account.

Review URL: https://chromiumcodereview.appspot.com/14966005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14565 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 169283de
...@@ -413,7 +413,7 @@ Handle<Code> KeyedLoadFastElementStub::GenerateCode() { ...@@ -413,7 +413,7 @@ Handle<Code> KeyedLoadFastElementStub::GenerateCode() {
template<> template<>
HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() { HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() {
Representation representation = casted_stub()->representation(); Representation representation = casted_stub()->representation();
HInstruction* load = AddInstruction(new(zone()) HLoadNamedField( HInstruction* load = AddInstruction(DoBuildLoadNamedField(
GetParameter(0), casted_stub()->is_inobject(), GetParameter(0), casted_stub()->is_inobject(),
representation, casted_stub()->offset())); representation, casted_stub()->offset()));
return load; return load;
...@@ -428,7 +428,7 @@ Handle<Code> LoadFieldStub::GenerateCode() { ...@@ -428,7 +428,7 @@ Handle<Code> LoadFieldStub::GenerateCode() {
template<> template<>
HValue* CodeStubGraphBuilder<KeyedLoadFieldStub>::BuildCodeStub() { HValue* CodeStubGraphBuilder<KeyedLoadFieldStub>::BuildCodeStub() {
Representation representation = casted_stub()->representation(); Representation representation = casted_stub()->representation();
HInstruction* load = AddInstruction(new(zone()) HLoadNamedField( HInstruction* load = AddInstruction(DoBuildLoadNamedField(
GetParameter(0), casted_stub()->is_inobject(), GetParameter(0), casted_stub()->is_inobject(),
representation, casted_stub()->offset())); representation, casted_stub()->offset()));
return load; return load;
......
...@@ -7131,22 +7131,31 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, ...@@ -7131,22 +7131,31 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
HValue* object, HValue* object,
SmallMapList* types, SmallMapList* types,
Handle<String> name) { Handle<String> name) {
int count = 0;
int previous_field_offset = 0;
bool previous_field_is_in_object = false;
bool is_monomorphic_field = true;
if (HandlePolymorphicArrayLengthLoad(expr, object, types, name)) if (HandlePolymorphicArrayLengthLoad(expr, object, types, name))
return; return;
Handle<Map> map; AddInstruction(new(zone()) HCheckNonSmi(object));
// Use monomorphic load if property lookup results in the same field index
// for all maps. Requires special map check on the set of all handled maps.
HInstruction* instr = NULL;
if (types->length() > 0 && types->length() <= kMaxLoadPolymorphism) {
LookupResult lookup(isolate()); LookupResult lookup(isolate());
for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { int previous_field_offset = 0;
map = types->at(i); bool previous_field_is_in_object = false;
if (ComputeLoadStoreField(map, name, &lookup, false)) { Representation representation = Representation::None();
int count;
for (count = 0; count < types->length(); ++count) {
Handle<Map> map = types->at(count);
if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
int index = ComputeLoadStoreFieldIndex(map, &lookup); int index = ComputeLoadStoreFieldIndex(map, &lookup);
Representation new_representation =
ComputeLoadStoreRepresentation(map, &lookup);
bool is_in_object = index < 0; bool is_in_object = index < 0;
int offset = index * kPointerSize; int offset = index * kPointerSize;
if (index < 0) { if (index < 0) {
// Negative property indices are in-object properties, indexed // Negative property indices are in-object properties, indexed
// from the end of the fixed part of the object. // from the end of the fixed part of the object.
...@@ -7154,31 +7163,33 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, ...@@ -7154,31 +7163,33 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
} else { } else {
offset += FixedArray::kHeaderSize; offset += FixedArray::kHeaderSize;
} }
if (count == 0) { if (count == 0) {
previous_field_offset = offset; previous_field_offset = offset;
previous_field_is_in_object = is_in_object; previous_field_is_in_object = is_in_object;
} else if (is_monomorphic_field) { representation = new_representation;
is_monomorphic_field = (offset == previous_field_offset) && } else if (offset != previous_field_offset ||
(is_in_object == previous_field_is_in_object); is_in_object != previous_field_is_in_object ||
} (FLAG_track_fields &&
++count; !representation.IsCompatibleForLoad(new_representation))) {
break;
} }
representation = representation.generalize(new_representation);
} }
// Use monomorphic load if property lookup results in the same field index if (count == types->length()) {
// for all maps. Requires special map check on the set of all handled maps.
AddInstruction(new(zone()) HCheckNonSmi(object));
HInstruction* instr;
if (count == types->length() && is_monomorphic_field) {
AddInstruction(HCheckMaps::New(object, types, zone())); AddInstruction(HCheckMaps::New(object, types, zone()));
instr = BuildLoadNamedField(object, map, &lookup); instr = DoBuildLoadNamedField(
} else { object, previous_field_is_in_object,
representation, previous_field_offset);
}
}
if (instr == NULL) {
HValue* context = environment()->LookupContext(); HValue* context = environment()->LookupContext();
instr = new(zone()) HLoadNamedFieldPolymorphic(context, instr = new(zone()) HLoadNamedFieldPolymorphic(
object, context, object, types, name, zone());
types,
name,
zone());
} }
instr->set_position(expr->position()); instr->set_position(expr->position());
...@@ -7735,18 +7746,25 @@ HLoadNamedField* HOptimizedGraphBuilder::BuildLoadNamedField( ...@@ -7735,18 +7746,25 @@ HLoadNamedField* HOptimizedGraphBuilder::BuildLoadNamedField(
HValue* object, HValue* object,
Handle<Map> map, Handle<Map> map,
LookupResult* lookup) { LookupResult* lookup) {
Representation representation = lookup->representation();
int index = lookup->GetLocalFieldIndexFromMap(*map); int index = lookup->GetLocalFieldIndexFromMap(*map);
if (index < 0) { // Negative property indices are in-object properties, indexed from the end of
// Negative property indices are in-object properties, indexed // the fixed part of the object. Non-negative property indices are in the
// from the end of the fixed part of the object. // properties array.
int offset = (index * kPointerSize) + map->instance_size(); int inobject = index < 0;
return new(zone()) HLoadNamedField(object, true, representation, offset); Representation representation = lookup->representation();
} else { int offset = inobject
// Non-negative property indices are in the properties array. ? index * kPointerSize + map->instance_size()
int offset = (index * kPointerSize) + FixedArray::kHeaderSize; : index * kPointerSize + FixedArray::kHeaderSize;
return new(zone()) HLoadNamedField(object, false, representation, offset); return DoBuildLoadNamedField(object, inobject, representation, offset);
} }
HLoadNamedField* HGraphBuilder::DoBuildLoadNamedField(
HValue* object,
bool inobject,
Representation representation,
int offset) {
return new(zone()) HLoadNamedField(object, inobject, representation, offset);
} }
......
...@@ -982,6 +982,11 @@ class HGraphBuilder { ...@@ -982,6 +982,11 @@ class HGraphBuilder {
HValue* BuildCheckMap(HValue* obj, Handle<Map> map); HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
// Building common constructs // Building common constructs
HLoadNamedField* DoBuildLoadNamedField(HValue* object,
bool inobject,
Representation representation,
int offset);
HInstruction* BuildExternalArrayElementAccess( HInstruction* BuildExternalArrayElementAccess(
HValue* external_elements, HValue* external_elements,
HValue* checked_key, HValue* checked_key,
......
...@@ -103,6 +103,11 @@ class Representation { ...@@ -103,6 +103,11 @@ class Representation {
return kind_ == other.kind_; return kind_ == other.kind_;
} }
bool IsCompatibleForLoad(const Representation& other) const {
return (IsDouble() && other.IsDouble()) ||
(!IsDouble() && !other.IsDouble());
}
bool is_more_general_than(const Representation& other) const { bool is_more_general_than(const Representation& other) const {
ASSERT(kind_ != kExternal); ASSERT(kind_ != kExternal);
ASSERT(other.kind_ != kExternal); ASSERT(other.kind_ != kExternal);
......
...@@ -99,3 +99,22 @@ assertFalse(%HaveSameMap(o6, o7)); ...@@ -99,3 +99,22 @@ assertFalse(%HaveSameMap(o6, o7));
// Smi, double, object. // Smi, double, object.
o6.c = {}; o6.c = {};
assertTrue(%HaveSameMap(o6, o7)); assertTrue(%HaveSameMap(o6, o7));
function poly_load(o, b) {
var v = o.field;
if (b) {
return v + 10;
}
return o;
}
var of1 = {a:0};
of1.field = {};
var of2 = {b:0};
of2.field = 10;
poly_load(of1, false);
poly_load(of1, false);
poly_load(of2, true);
%OptimizeFunctionOnNextCall(poly_load);
assertEquals("[object Object]10", poly_load(of1, true));
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