From e5feaf31faaefe20cdbb71d426bc47849c398e38 Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Wed, 8 May 2013 09:39:26 +0000 Subject: [PATCH] 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 --- src/hydrogen.cc | 48 ++++++++++++++++++++++++++++++++++++++++++ src/property-details.h | 4 ++++ 2 files changed, 52 insertions(+) diff --git a/src/hydrogen.cc b/src/hydrogen.cc index f50a2d5796..aeeff34045 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -7218,6 +7218,54 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( HValue* value, SmallMapList* types, Handle 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; + 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 // maps are identical. In that case we can avoid repeatedly generating the // same prototype map checks. diff --git a/src/property-details.h b/src/property-details.h index 62140fe962..dc8c9f2350 100644 --- a/src/property-details.h +++ b/src/property-details.h @@ -108,6 +108,10 @@ class Representation { (!IsDouble() && !other.IsDouble()); } + bool IsCompatibleForStore(const Representation& other) const { + return Equals(other); + } + bool is_more_general_than(const Representation& other) const { ASSERT(kind_ != kExternal); ASSERT(other.kind_ != kExternal);