Try convert polymorphic stores into a single monomorphic store.

R=jkummerow@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15158 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
verwaest@chromium.org 2013-06-14 14:16:03 +00:00
parent af599c835d
commit 773c08c58f
3 changed files with 86 additions and 7 deletions

View File

@ -3794,6 +3794,13 @@ void TestContext::BuildBranch(HValue* value) {
} while (false)
#define CHECK_ALIVE_OR_RETURN(call, value) \
do { \
call; \
if (HasStackOverflow() || current_block() == NULL) return value; \
} while (false)
void HOptimizedGraphBuilder::Bailout(const char* reason) {
current_info()->set_bailout_reason(reason);
SetStackOverflow();
@ -6300,13 +6307,13 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
Handle<String> name) {
// 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.
if (types->length() > kMaxLoadPolymorphism) return NULL;
LookupResult lookup(isolate());
int count;
Representation representation = Representation::None();
HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
for (count = 0;
count < types->length() && count < kMaxLoadPolymorphism;
++count) {
for (count = 0; count < types->length(); ++count) {
Handle<Map> map = types->at(count);
if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
@ -6317,7 +6324,6 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
if (count == 0) {
// First time through the loop; set access and representation.
access = new_access;
representation = new_representation;
} else if (!representation.IsCompatibleForLoad(new_representation)) {
// Representations did not match.
break;
@ -6328,6 +6334,7 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
// In-objectness did not match.
break;
}
representation = representation.generalize(new_representation);
}
if (count != types->length()) return NULL;
@ -6359,12 +6366,75 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
}
bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
Assignment* expr,
HValue* object,
HValue* value,
SmallMapList* types,
Handle<String> name) {
// Use monomorphic store if property lookup results in the same field index
// for all maps. Requires special map check on the set of all handled maps.
if (types->length() > kMaxStorePolymorphism) return false;
// TODO(verwaest): Merge the checking logic with the code in
// TryLoadPolymorphicAsMonomorphic.
LookupResult lookup(isolate());
int count;
Representation representation = Representation::None();
HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
for (count = 0; count < types->length(); ++count) {
Handle<Map> map = types->at(count);
// Pass false to ignore transitions.
if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name);
Representation new_representation =
ComputeLoadStoreRepresentation(map, &lookup);
if (count == 0) {
// First time through the loop; set access and representation.
access = new_access;
representation = new_representation;
} else if (!representation.IsCompatibleForStore(new_representation)) {
// Representations did not match.
break;
} else if (access.offset() != new_access.offset()) {
// Offsets did not match.
break;
} else if (access.IsInobject() != new_access.IsInobject()) {
// In-objectness did not match.
break;
}
}
if (count != types->length()) return false;
// Everything matched; can use monomorphic store.
BuildCheckNonSmi(object);
AddInstruction(HCheckMaps::New(object, types, zone()));
HInstruction* store;
CHECK_ALIVE_OR_RETURN(
store = BuildStoreNamedField(object, name, value, types->at(0), &lookup),
true);
Push(value);
store->set_position(expr->position());
AddInstruction(store);
AddSimulate(expr->AssignmentId());
ast_context()->ReturnValue(Pop());
return true;
}
void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
Assignment* expr,
HValue* object,
HValue* value,
SmallMapList* types,
Handle<String> name) {
if (TryStorePolymorphicAsMonomorphic(expr, object, value, types, name)) {
return;
}
// 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.
@ -6387,8 +6457,8 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
set_current_block(if_true);
HInstruction* instr;
CHECK_ALIVE(instr =
BuildStoreNamedField(object, name, value, map, &lookup));
CHECK_ALIVE(
instr = BuildStoreNamedField(object, name, value, map, &lookup));
instr->set_position(expr->position());
// Goto will add the HSimulate for the store.
AddInstruction(instr);
@ -6432,7 +6502,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
ASSERT(join != NULL);
join->SetJoinId(expr->id());
set_current_block(join);
if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
}

View File

@ -1707,6 +1707,11 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
HValue* value,
SmallMapList* types,
Handle<String> name);
bool TryStorePolymorphicAsMonomorphic(Assignment* expr,
HValue* object,
HValue* value,
SmallMapList* types,
Handle<String> name);
void HandlePolymorphicCallNamed(Call* expr,
HValue* receiver,
SmallMapList* types,

View File

@ -110,6 +110,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);