Commit 6b389902 authored by ishell@chromium.org's avatar ishell@chromium.org

Revert "Polymorphic named calls optimized for the case of repetitive call...

Revert "Polymorphic named calls optimized for the case of repetitive call targets." for now because it prevents better results for checkmap elimination.

R=verwaest@chromium.org

Review URL: https://codereview.chromium.org/138453002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18597 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 975141b2
......@@ -6855,6 +6855,9 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return;
int argument_count = expr->arguments()->length() + 1; // Includes receiver.
HBasicBlock* join = NULL;
FunctionSorter order[kMaxCallPolymorphism];
int ordered_functions = 0;
Handle<Map> initial_string_map(
isolate()->native_context()->string_function()->initial_map());
......@@ -6868,121 +6871,72 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
bool handle_smi = false;
// A map from functions to a set of receivers' maps.
struct FuncMapEntry {
Handle<JSFunction> func;
SmallMapList maps;
};
FuncMapEntry func_map[kMaxCallPolymorphism];
FunctionSorter order[kMaxCallPolymorphism];
int func_count = 0;
int maps_count = 0;
for (int i = 0;
i < types->length() && func_count < kMaxCallPolymorphism;
i < types->length() && ordered_functions < kMaxCallPolymorphism;
++i) {
Handle<Map> map = types->at(i);
if (expr->ComputeTarget(map, name)) {
if (map.is_identical_to(number_marker_map)) handle_smi = true;
// Try to find the target function among known targets.
int func_index = 0;
for (; func_index < func_count; ++func_index) {
if (*func_map[func_index].func == *expr->target()) {
break;
}
}
FuncMapEntry* entry = &func_map[func_index];
if (func_index == func_count) {
// Entry not found, "allocate" it.
entry->func = expr->target();
entry->maps.Reserve(types->length() - maps_count, zone());
order[func_index] =
FunctionSorter(func_index,
entry->func->shared()->profiler_ticks(),
InliningAstSize(entry->func),
entry->func->shared()->SourceSize());
++func_count;
}
entry->maps.Add(map, zone());
++maps_count;
order[ordered_functions++] =
FunctionSorter(i,
expr->target()->shared()->profiler_ticks(),
InliningAstSize(expr->target()),
expr->target()->shared()->SourceSize());
}
}
std::sort(order, order + func_count);
std::sort(order, order + ordered_functions);
HBasicBlock* number_block = NULL;
HBasicBlock* join = NULL;
if (func_count > 0) {
// Only needed once.
join = graph()->CreateBasicBlock();
if (handle_smi) {
HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
number_block = graph()->CreateBasicBlock();
FinishCurrentBlock(
New<HIsSmiAndBranch>(receiver, empty_smi_block, not_smi_block));
Goto(empty_smi_block, number_block);
set_current_block(not_smi_block);
} else {
BuildCheckHeapObject(receiver);
}
}
for (int fn = 0; fn < func_count; ++fn) {
for (int fn = 0; fn < ordered_functions; ++fn) {
int i = order[fn].index();
FuncMapEntry* func_map_entry = &func_map[i];
HBasicBlock* call_block = graph()->CreateBasicBlock();
HBasicBlock* if_false = NULL;
int maps_count = func_map_entry->maps.length();
for (int m = 0; m < maps_count; ++m) {
Handle<Map> map = func_map_entry->maps.at(m);
HBasicBlock* if_true = graph()->CreateBasicBlock();
if_false = graph()->CreateBasicBlock();
HUnaryControlInstruction* compare;
if (handle_smi && map.is_identical_to(number_marker_map)) {
compare =
New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
map = initial_number_map;
expr->set_number_check(
Handle<JSObject>(JSObject::cast(map->prototype())));
} else if (map.is_identical_to(string_marker_map)) {
compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
map = initial_string_map;
expr->set_string_check(
Handle<JSObject>(JSObject::cast(map->prototype())));
Handle<Map> map = types->at(i);
if (fn == 0) {
// Only needed once.
join = graph()->CreateBasicBlock();
if (handle_smi) {
HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
number_block = graph()->CreateBasicBlock();
FinishCurrentBlock(New<HIsSmiAndBranch>(
receiver, empty_smi_block, not_smi_block));
Goto(empty_smi_block, number_block);
set_current_block(not_smi_block);
} else {
compare = New<HCompareMap>(receiver, map, if_true, if_false);
expr->set_map_check();
}
FinishCurrentBlock(compare);
if (expr->check_type() == NUMBER_CHECK) {
Goto(if_true, number_block);
if_true = number_block;
number_block->SetJoinId(expr->id());
BuildCheckHeapObject(receiver);
}
set_current_block(if_true);
expr->ComputeTarget(map, name);
ASSERT(*expr->target() == *func_map_entry->func);
AddCheckPrototypeMaps(expr->holder(), map);
}
HBasicBlock* if_true = graph()->CreateBasicBlock();
HBasicBlock* if_false = graph()->CreateBasicBlock();
HUnaryControlInstruction* compare;
if (handle_smi && map.is_identical_to(number_marker_map)) {
compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
map = initial_number_map;
expr->set_number_check(
Handle<JSObject>(JSObject::cast(map->prototype())));
} else if (map.is_identical_to(string_marker_map)) {
compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
map = initial_string_map;
expr->set_string_check(
Handle<JSObject>(JSObject::cast(map->prototype())));
} else {
compare = New<HCompareMap>(receiver, map, if_true, if_false);
expr->set_map_check();
}
Goto(if_true, call_block);
FinishCurrentBlock(compare);
set_current_block(if_false);
if (expr->check_type() == NUMBER_CHECK) {
Goto(if_true, number_block);
if_true = number_block;
number_block->SetJoinId(expr->id());
}
set_current_block(if_true);
// Generate call once for all corresponding maps.
call_block->SetJoinId(expr->id());
set_current_block(call_block);
expr->ComputeTarget(map, name);
AddCheckPrototypeMaps(expr->holder(), map);
if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
Handle<JSFunction> caller = current_info()->closure();
SmartArrayPointer<char> caller_name =
......@@ -7002,15 +6956,15 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
AddInstruction(call);
if (!ast_context()->IsEffect()) Push(call);
}
if (current_block() != NULL) Goto(join);
if (current_block() != NULL) Goto(join);
set_current_block(if_false);
}
// Finish up. Unconditionally deoptimize if we've handled all the maps we
// know about and do not want to handle ones we've never seen. Otherwise
// use a generic IC.
if (maps_count == types->length() && FLAG_deoptimize_uncommon_cases) {
if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
// Because the deopt may be the only path in the polymorphic call, make sure
// that the environment stack matches the depth on deopt that it otherwise
// would have had after a successful call.
......
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