| Index: src/hydrogen.cc | 
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc | 
| index 7841e1f92f8fe7d93cac3fe86fe40120a88596b1..deb113bb54e36885768c26fc42f188c4dd6f8f22 100644 | 
| --- a/src/hydrogen.cc | 
| +++ b/src/hydrogen.cc | 
| @@ -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. | 
|  |