Turn polymorphic stores monomorphic if store sequence matches.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14589 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
verwaest@chromium.org 2013-05-08 09:39:26 +00:00
parent f5ad8e4469
commit e5feaf31fa
2 changed files with 52 additions and 0 deletions

View File

@ -7218,6 +7218,54 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
HValue* value, HValue* value,
SmallMapList* types, SmallMapList* types,
Handle<String> name) { Handle<String> name) {
// Use monomorphic store if property lookup results in the same field index
// and compatible representation for all maps. Requires special map check on
// the set of all handled maps.
if (types->length() <= kMaxStorePolymorphism) {
int previous_field_offset = 0;
bool previous_field_is_in_object = false;
Representation previous_representation = Representation::None();
Handle<Map> map;
LookupResult lookup(isolate());
int count;
for (count = 0; count < types->length(); ++count) {
map = types->at(count);
if (!ComputeLoadStoreField(map, name, &lookup, false) ||
lookup.IsTransition()) {
break;
}
Representation representation = lookup.representation();
int index = ComputeLoadStoreFieldIndex(map, &lookup);
bool is_in_object = index < 0;
int offset = index * kPointerSize;
if (index < 0) {
offset += map->instance_size();
} else {
offset += FixedArray::kHeaderSize;
}
if (count == 0) {
previous_field_offset = offset;
previous_field_is_in_object = is_in_object;
previous_representation = representation;
} else if (offset != previous_field_offset ||
is_in_object != previous_field_is_in_object ||
!representation.IsCompatibleForStore(
previous_representation)) {
break;
}
}
if (types->length() == count) {
AddInstruction(new(zone()) HCheckNonSmi(object));
AddInstruction(HCheckMaps::New(object, types, zone()));
HInstruction* instr = BuildStoreNamedField(
object, name, value, map, &lookup);
instr->set_position(expr->position());
return ast_context()->ReturnInstruction(instr, expr->id());
}
}
// TODO(ager): We should recognize when the prototype chains for different // TODO(ager): We should recognize when the prototype chains for different
// maps are identical. In that case we can avoid repeatedly generating the // maps are identical. In that case we can avoid repeatedly generating the
// same prototype map checks. // same prototype map checks.

View File

@ -108,6 +108,10 @@ class Representation {
(!IsDouble() && !other.IsDouble()); (!IsDouble() && !other.IsDouble());
} }
bool IsCompatibleForStore(const Representation& other) const {
return Equals(other);
}
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);