Change the translation of polymorphic stores.

They do not use subgraphs or subgraph scopes.  Instead of computing a list
of single-block subgraphs and then adding all the edges afterward, build
both the blocks and edges directly.

Review URL: http://codereview.chromium.org/6615014

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7058 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f6a366a8
...@@ -3147,65 +3147,70 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, ...@@ -3147,65 +3147,70 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
HValue* value, HValue* value,
ZoneMapList* types, ZoneMapList* types,
Handle<String> name) { Handle<String> name) {
int number_of_types = Min(types->length(), kMaxStorePolymorphism); int count = 0;
ZoneMapList maps(number_of_types); HBasicBlock* join = NULL;
ZoneList<HSubgraph*> subgraphs(number_of_types); for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
bool needs_generic = (types->length() > kMaxStorePolymorphism);
// Build subgraphs for each of the specific maps.
//
// 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.
for (int i = 0; i < number_of_types; ++i) {
Handle<Map> map = types->at(i); Handle<Map> map = types->at(i);
LookupResult lookup; LookupResult lookup;
if (ComputeStoredField(map, name, &lookup)) { if (ComputeStoredField(map, name, &lookup)) {
HSubgraph* subgraph = CreateBranchSubgraph(environment()); ++count;
SubgraphScope scope(this, subgraph); if (join == NULL) {
AddInstruction(new HCheckNonSmi(object)); // Only needed once.
join = graph()->CreateBasicBlock();
}
HBasicBlock* if_true = graph()->CreateBasicBlock();
HBasicBlock* if_false = graph()->CreateBasicBlock();
HCompareMap* compare = new HCompareMap(object, map, if_true, if_false);
current_block()->Finish(compare);
set_current_block(if_true);
HInstruction* instr = HInstruction* instr =
BuildStoreNamedField(object, name, value, map, &lookup, false); BuildStoreNamedField(object, name, value, map, &lookup, false);
Push(value);
instr->set_position(expr->position()); instr->set_position(expr->position());
// Goto will add the HSimulate for the store.
AddInstruction(instr); AddInstruction(instr);
maps.Add(map); if (!ast_context()->IsEffect()) Push(value);
subgraphs.Add(subgraph); current_block()->Goto(join);
} else {
needs_generic = true; set_current_block(if_false);
} }
} }
// If none of the properties were named fields we generate a // Finish up. We need a generic IC if there were types we couldn't
// generic store. // resolve statically or if we want to handle maps we've never seen.
if (maps.length() == 0) { if (count < types->length() || !FLAG_deoptimize_uncommon_cases) {
HInstruction* instr = BuildStoreNamedGeneric(object, name, value); HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
Push(value);
instr->set_position(expr->position()); instr->set_position(expr->position());
AddInstruction(instr); AddInstruction(instr);
if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
ast_context()->ReturnValue(Pop()); if (join == NULL) {
} else { // The HSimulate for the store should not see the stored value in
// Build subgraph for generic store through IC. // effect contexts (it is not materialized at expr->id() in the
HSubgraph* default_graph = CreateBranchSubgraph(environment()); // unoptimized code).
{ SubgraphScope scope(this, default_graph); if (instr->HasSideEffects()) {
if (!needs_generic && FLAG_deoptimize_uncommon_cases) { if (ast_context()->IsEffect()) {
default_graph->exit_block()->FinishExit(new HDeoptimize()); AddSimulate(expr->id());
default_graph->set_exit_block(NULL);
} else { } else {
HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
Push(value); Push(value);
instr->set_position(expr->position()); AddSimulate(expr->id());
AddInstruction(instr); Drop(1);
} }
} }
ast_context()->ReturnValue(value);
} else {
if (!ast_context()->IsEffect()) Push(value);
current_block()->Goto(join);
join->SetJoinId(expr->id());
set_current_block(join);
if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
}
HBasicBlock* new_exit_block = } else {
BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id()); current_block()->FinishExit(new HDeoptimize);
set_current_block(new_exit_block); set_current_block(join);
// In an effect context, we did not materialized the value in the if (join != NULL) {
// predecessor environments so there's no need to handle it here. join->SetJoinId(expr->id());
if (current_block() != NULL && !ast_context()->IsEffect()) { if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
ast_context()->ReturnValue(Pop());
} }
} }
} }
......
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