OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 7353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7364 HValue* receiver, | 7364 HValue* receiver, |
7365 SmallMapList* types, | 7365 SmallMapList* types, |
7366 Handle<String> name) { | 7366 Handle<String> name) { |
7367 // TODO(ager): We should recognize when the prototype chains for different | 7367 // TODO(ager): We should recognize when the prototype chains for different |
7368 // maps are identical. In that case we can avoid repeatedly generating the | 7368 // maps are identical. In that case we can avoid repeatedly generating the |
7369 // same prototype map checks. | 7369 // same prototype map checks. |
7370 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 7370 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
7371 HBasicBlock* join = NULL; | 7371 HBasicBlock* join = NULL; |
7372 FunctionSorter order[kMaxCallPolymorphism]; | 7372 FunctionSorter order[kMaxCallPolymorphism]; |
7373 int ordered_functions = 0; | 7373 int ordered_functions = 0; |
| 7374 |
| 7375 Handle<Map> initial_string_map( |
| 7376 isolate()->native_context()->string_function()->initial_map()); |
| 7377 Handle<Map> string_marker_map( |
| 7378 JSObject::cast(initial_string_map->prototype())->map()); |
| 7379 Handle<Map> initial_number_map( |
| 7380 isolate()->native_context()->number_function()->initial_map()); |
| 7381 Handle<Map> number_marker_map( |
| 7382 JSObject::cast(initial_number_map->prototype())->map()); |
| 7383 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); |
| 7384 |
| 7385 bool handle_smi = false; |
| 7386 |
7374 for (int i = 0; | 7387 for (int i = 0; |
7375 i < types->length() && ordered_functions < kMaxCallPolymorphism; | 7388 i < types->length() && ordered_functions < kMaxCallPolymorphism; |
7376 ++i) { | 7389 ++i) { |
7377 Handle<Map> map = types->at(i); | 7390 Handle<Map> map = types->at(i); |
| 7391 if (map.is_identical_to(number_marker_map)) handle_smi = true; |
7378 if (expr->ComputeTarget(map, name)) { | 7392 if (expr->ComputeTarget(map, name)) { |
7379 order[ordered_functions++] = | 7393 order[ordered_functions++] = |
7380 FunctionSorter(i, | 7394 FunctionSorter(i, |
7381 expr->target()->shared()->profiler_ticks(), | 7395 expr->target()->shared()->profiler_ticks(), |
7382 InliningAstSize(expr->target()), | 7396 InliningAstSize(expr->target()), |
7383 expr->target()->shared()->SourceSize()); | 7397 expr->target()->shared()->SourceSize()); |
7384 } | 7398 } |
7385 } | 7399 } |
7386 | 7400 |
7387 qsort(reinterpret_cast<void*>(&order[0]), | 7401 qsort(reinterpret_cast<void*>(&order[0]), |
7388 ordered_functions, | 7402 ordered_functions, |
7389 sizeof(order[0]), | 7403 sizeof(order[0]), |
7390 &CompareHotness); | 7404 &CompareHotness); |
7391 | 7405 |
| 7406 HBasicBlock* number_block = NULL; |
| 7407 |
7392 for (int fn = 0; fn < ordered_functions; ++fn) { | 7408 for (int fn = 0; fn < ordered_functions; ++fn) { |
7393 int i = order[fn].index(); | 7409 int i = order[fn].index(); |
7394 Handle<Map> map = types->at(i); | 7410 Handle<Map> map = types->at(i); |
7395 if (fn == 0) { | 7411 if (fn == 0) { |
7396 // Only needed once. | 7412 // Only needed once. |
7397 AddInstruction(new(zone()) HCheckNonSmi(receiver)); | |
7398 join = graph()->CreateBasicBlock(); | 7413 join = graph()->CreateBasicBlock(); |
| 7414 if (handle_smi) { |
| 7415 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); |
| 7416 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); |
| 7417 number_block = graph()->CreateBasicBlock(); |
| 7418 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(receiver); |
| 7419 smicheck->SetSuccessorAt(0, empty_smi_block); |
| 7420 smicheck->SetSuccessorAt(1, not_smi_block); |
| 7421 current_block()->Finish(smicheck); |
| 7422 empty_smi_block->Goto(number_block); |
| 7423 set_current_block(not_smi_block); |
| 7424 } else { |
| 7425 AddInstruction(new(zone()) HCheckNonSmi(receiver)); |
| 7426 } |
7399 } | 7427 } |
7400 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 7428 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
7401 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 7429 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
7402 HCompareMap* compare = | 7430 HUnaryControlInstruction* compare; |
7403 new(zone()) HCompareMap(receiver, map, if_true, if_false); | 7431 |
| 7432 if (handle_smi && map.is_identical_to(number_marker_map)) { |
| 7433 compare = new(zone()) HCompareMap( |
| 7434 receiver, heap_number_map, if_true, if_false); |
| 7435 map = initial_number_map; |
| 7436 expr->set_number_check( |
| 7437 Handle<JSObject>(JSObject::cast(map->prototype()))); |
| 7438 } else if (map.is_identical_to(string_marker_map)) { |
| 7439 compare = new(zone()) HIsStringAndBranch(receiver); |
| 7440 compare->SetSuccessorAt(0, if_true); |
| 7441 compare->SetSuccessorAt(1, if_false); |
| 7442 map = initial_string_map; |
| 7443 expr->set_string_check( |
| 7444 Handle<JSObject>(JSObject::cast(map->prototype()))); |
| 7445 } else { |
| 7446 compare = new(zone()) HCompareMap(receiver, map, if_true, if_false); |
| 7447 expr->set_map_check(); |
| 7448 } |
| 7449 |
7404 current_block()->Finish(compare); | 7450 current_block()->Finish(compare); |
7405 | 7451 |
| 7452 if (expr->check_type() == NUMBER_CHECK) { |
| 7453 if_true->Goto(number_block); |
| 7454 if_true = number_block; |
| 7455 number_block->SetJoinId(expr->id()); |
| 7456 } |
7406 set_current_block(if_true); | 7457 set_current_block(if_true); |
| 7458 |
7407 expr->ComputeTarget(map, name); | 7459 expr->ComputeTarget(map, name); |
7408 AddCheckPrototypeMaps(expr->holder(), map); | 7460 AddCheckPrototypeMaps(expr->holder(), map); |
7409 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 7461 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
7410 Handle<JSFunction> caller = info()->closure(); | 7462 Handle<JSFunction> caller = info()->closure(); |
7411 SmartArrayPointer<char> caller_name = | 7463 SmartArrayPointer<char> caller_name = |
7412 caller->shared()->DebugName()->ToCString(); | 7464 caller->shared()->DebugName()->ToCString(); |
7413 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 7465 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
7414 *name->ToCString(), | 7466 *name->ToCString(), |
7415 *caller_name); | 7467 *caller_name); |
7416 } | 7468 } |
(...skipping 3459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10876 } | 10928 } |
10877 } | 10929 } |
10878 | 10930 |
10879 #ifdef DEBUG | 10931 #ifdef DEBUG |
10880 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 10932 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
10881 if (allocator_ != NULL) allocator_->Verify(); | 10933 if (allocator_ != NULL) allocator_->Verify(); |
10882 #endif | 10934 #endif |
10883 } | 10935 } |
10884 | 10936 |
10885 } } // namespace v8::internal | 10937 } } // namespace v8::internal |
OLD | NEW |