OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/aot_optimizer.h" | 5 #include "vm/aot_optimizer.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/branch_optimizer.h" | 8 #include "vm/branch_optimizer.h" |
9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
441 Instruction* insert_before) { | 441 Instruction* insert_before) { |
442 if (to_check->Type()->ToCid() != kSmiCid) { | 442 if (to_check->Type()->ToCid() != kSmiCid) { |
443 InsertBefore(insert_before, | 443 InsertBefore(insert_before, |
444 new (Z) CheckSmiInstr(new (Z) Value(to_check), deopt_id, | 444 new (Z) CheckSmiInstr(new (Z) Value(to_check), deopt_id, |
445 insert_before->token_pos()), | 445 insert_before->token_pos()), |
446 deopt_environment, FlowGraph::kEffect); | 446 deopt_environment, FlowGraph::kEffect); |
447 } | 447 } |
448 } | 448 } |
449 | 449 |
450 | 450 |
451 Instruction* AotOptimizer::GetCheckClass(Definition* to_check, | |
452 const ICData& unary_checks, | |
453 intptr_t deopt_id, | |
454 TokenPosition token_pos) { | |
455 if ((unary_checks.NumberOfUsedChecks() == 1) && | |
456 unary_checks.HasReceiverClassId(kSmiCid)) { | |
457 return new (Z) CheckSmiInstr(new (Z) Value(to_check), deopt_id, token_pos); | |
458 } | |
459 return new (Z) CheckClassInstr(new (Z) Value(to_check), deopt_id, | |
460 unary_checks, token_pos); | |
461 } | |
462 | |
463 | |
464 void AotOptimizer::AddCheckClass(Definition* to_check, | 451 void AotOptimizer::AddCheckClass(Definition* to_check, |
465 const ICData& unary_checks, | 452 const Cids& cids, |
466 intptr_t deopt_id, | 453 intptr_t deopt_id, |
467 Environment* deopt_environment, | 454 Environment* deopt_environment, |
468 Instruction* insert_before) { | 455 Instruction* insert_before) { |
469 // Type propagation has not run yet, we cannot eliminate the check. | 456 // Type propagation has not run yet, we cannot eliminate the check. |
470 Instruction* check = GetCheckClass(to_check, unary_checks, deopt_id, | 457 Instruction* check = flow_graph_->CreateCheckClass( |
471 insert_before->token_pos()); | 458 to_check, cids, deopt_id, insert_before->token_pos()); |
472 InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect); | 459 InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect); |
473 } | 460 } |
474 | 461 |
475 | 462 |
476 void AotOptimizer::AddReceiverCheck(InstanceCallInstr* call) { | 463 void AotOptimizer::AddChecksToArgNr(InstanceCallInstr* call, |
477 AddCheckClass(call->ArgumentAt(0), | 464 Definition* instr, |
478 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()), | 465 int argument_number) { |
479 call->deopt_id(), call->env(), call); | 466 const Cids* cids = Cids::Create(Z, *call->ic_data(), argument_number); |
467 AddCheckClass(instr, *cids, call->deopt_id(), call->env(), call); | |
480 } | 468 } |
481 | 469 |
482 | 470 |
483 static bool ArgIsAlways(intptr_t cid, | 471 static bool ArgIsAlways(intptr_t cid, |
484 const ICData& ic_data, | 472 const ICData& ic_data, |
485 intptr_t arg_number) { | 473 intptr_t arg_number) { |
486 ASSERT(ic_data.NumArgsTested() > arg_number); | 474 ASSERT(ic_data.NumArgsTested() > arg_number); |
487 if (ic_data.NumberOfUsedChecks() == 0) { | 475 if (ic_data.NumberOfUsedChecks() == 0) { |
488 return false; | 476 return false; |
489 } | 477 } |
490 const intptr_t num_checks = ic_data.NumberOfChecks(); | 478 const intptr_t num_checks = ic_data.NumberOfChecks(); |
491 for (intptr_t i = 0; i < num_checks; i++) { | 479 for (intptr_t i = 0; i < num_checks; i++) { |
492 if (ic_data.IsUsedAt(i) && ic_data.GetClassIdAt(i, arg_number) != cid) { | 480 if (ic_data.IsUsedAt(i) && ic_data.GetClassIdAt(i, arg_number) != cid) { |
493 return false; | 481 return false; |
494 } | 482 } |
495 } | 483 } |
496 return true; | 484 return true; |
497 } | 485 } |
498 | 486 |
499 | 487 |
500 bool AotOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) { | 488 bool AotOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call, |
489 const ICData* unary_checks) { | |
501 // Check for monomorphic IC data. | 490 // Check for monomorphic IC data. |
502 if (!call->HasICData()) return false; | 491 ASSERT(unary_checks->NumberOfChecks() > 0); |
503 const ICData& ic_data = | 492 if (unary_checks->NumberOfChecksIs(1)) { |
504 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks()); | |
505 if (!ic_data.NumberOfChecksIs(1)) { | |
506 return false; | 493 return false; |
507 } | 494 } |
508 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | 495 return FlowGraphInliner::TryReplaceInstanceCallWithInline( |
509 flow_graph_, current_iterator(), call); | 496 flow_graph_, current_iterator(), call); |
510 } | 497 } |
511 | 498 |
512 | 499 |
513 // Return true if d is a string of length one (a constant or result from | 500 // Return true if d is a string of length one (a constant or result from |
514 // from string-from-char-code instruction. | 501 // from string-from-char-code instruction. |
515 static bool IsLengthOneString(Definition* d) { | 502 static bool IsLengthOneString(Definition* d) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
568 | 555 |
569 Definition* to_remove_right = NULL; | 556 Definition* to_remove_right = NULL; |
570 Value* right_val = NULL; | 557 Value* right_val = NULL; |
571 if (right->IsOneByteStringFromCharCode()) { | 558 if (right->IsOneByteStringFromCharCode()) { |
572 // Skip string-from-char-code, and use its input as right value. | 559 // Skip string-from-char-code, and use its input as right value. |
573 OneByteStringFromCharCodeInstr* right_instr = | 560 OneByteStringFromCharCodeInstr* right_instr = |
574 right->AsOneByteStringFromCharCode(); | 561 right->AsOneByteStringFromCharCode(); |
575 right_val = new (Z) Value(right_instr->char_code()->definition()); | 562 right_val = new (Z) Value(right_instr->char_code()->definition()); |
576 to_remove_right = right_instr; | 563 to_remove_right = right_instr; |
577 } else { | 564 } else { |
578 const ICData& unary_checks_1 = | 565 AddChecksToArgNr(call, right, /* arg_number = */ 1); |
579 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)); | |
580 AddCheckClass(right, unary_checks_1, call->deopt_id(), call->env(), call); | |
581 // String-to-char-code instructions returns -1 (illegal charcode) if | 566 // String-to-char-code instructions returns -1 (illegal charcode) if |
582 // string is not of length one. | 567 // string is not of length one. |
583 StringToCharCodeInstr* char_code_right = new (Z) | 568 StringToCharCodeInstr* char_code_right = new (Z) |
584 StringToCharCodeInstr(new (Z) Value(right), kOneByteStringCid); | 569 StringToCharCodeInstr(new (Z) Value(right), kOneByteStringCid); |
585 InsertBefore(call, char_code_right, call->env(), FlowGraph::kValue); | 570 InsertBefore(call, char_code_right, call->env(), FlowGraph::kValue); |
586 right_val = new (Z) Value(char_code_right); | 571 right_val = new (Z) Value(char_code_right); |
587 } | 572 } |
588 | 573 |
589 // Comparing char-codes instead of strings. | 574 // Comparing char-codes instead of strings. |
590 EqualityCompareInstr* comp = | 575 EqualityCompareInstr* comp = |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
661 return false; | 646 return false; |
662 } | 647 } |
663 | 648 |
664 | 649 |
665 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, | 650 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, |
666 Token::Kind op_kind) { | 651 Token::Kind op_kind) { |
667 const ICData& ic_data = *call->ic_data(); | 652 const ICData& ic_data = *call->ic_data(); |
668 ASSERT(ic_data.NumArgsTested() == 2); | 653 ASSERT(ic_data.NumArgsTested() == 2); |
669 | 654 |
670 ASSERT(call->ArgumentCount() == 2); | 655 ASSERT(call->ArgumentCount() == 2); |
671 Definition* left = call->ArgumentAt(0); | 656 Definition* const left = call->ArgumentAt(0); |
672 Definition* right = call->ArgumentAt(1); | 657 Definition* const right = call->ArgumentAt(1); |
673 | 658 |
674 intptr_t cid = kIllegalCid; | 659 intptr_t cid = kIllegalCid; |
675 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { | 660 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { |
676 return TryStringLengthOneEquality(call, op_kind); | 661 return TryStringLengthOneEquality(call, op_kind); |
677 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 662 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
678 InsertBefore(call, | 663 InsertBefore(call, |
679 new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(), | 664 new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(), |
680 call->token_pos()), | 665 call->token_pos()), |
681 call->env(), FlowGraph::kEffect); | 666 call->env(), FlowGraph::kEffect); |
682 InsertBefore(call, | 667 InsertBefore(call, |
(...skipping 23 matching lines...) Expand all Loading... | |
706 } | 691 } |
707 } else { | 692 } else { |
708 // Check if ICDData contains checks with Smi/Null combinations. In that case | 693 // Check if ICDData contains checks with Smi/Null combinations. In that case |
709 // we can still emit the optimized Smi equality operation but need to add | 694 // we can still emit the optimized Smi equality operation but need to add |
710 // checks for null or Smi. | 695 // checks for null or Smi. |
711 GrowableArray<intptr_t> smi_or_null(2); | 696 GrowableArray<intptr_t> smi_or_null(2); |
712 smi_or_null.Add(kSmiCid); | 697 smi_or_null.Add(kSmiCid); |
713 smi_or_null.Add(kNullCid); | 698 smi_or_null.Add(kNullCid); |
714 if (ICDataHasOnlyReceiverArgumentClassIds(ic_data, smi_or_null, | 699 if (ICDataHasOnlyReceiverArgumentClassIds(ic_data, smi_or_null, |
715 smi_or_null)) { | 700 smi_or_null)) { |
716 const ICData& unary_checks_0 = | 701 AddChecksToArgNr(call, left, /* arg_number = */ 0); |
717 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 702 AddChecksToArgNr(call, right, /* arg_number = */ 1); |
718 AddCheckClass(left, unary_checks_0, call->deopt_id(), call->env(), call); | |
719 | 703 |
720 const ICData& unary_checks_1 = | |
721 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)); | |
722 AddCheckClass(right, unary_checks_1, call->deopt_id(), call->env(), call); | |
723 cid = kSmiCid; | 704 cid = kSmiCid; |
724 } else { | 705 } else { |
725 // Shortcut for equality with null. | 706 // Shortcut for equality with null. |
726 // TODO(vegorov): this optimization is not speculative and should | 707 // TODO(vegorov): this optimization is not speculative and should |
727 // be hoisted out of this function. | 708 // be hoisted out of this function. |
728 ConstantInstr* right_const = right->AsConstant(); | 709 ConstantInstr* right_const = right->AsConstant(); |
729 ConstantInstr* left_const = left->AsConstant(); | 710 ConstantInstr* left_const = left->AsConstant(); |
730 if ((right_const != NULL && right_const->value().IsNull()) || | 711 if ((right_const != NULL && right_const->value().IsNull()) || |
731 (left_const != NULL && left_const->value().IsNull())) { | 712 (left_const != NULL && left_const->value().IsNull())) { |
732 StrictCompareInstr* comp = new (Z) | 713 StrictCompareInstr* comp = new (Z) |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1070 return true; | 1051 return true; |
1071 } | 1052 } |
1072 | 1053 |
1073 | 1054 |
1074 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, | 1055 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, |
1075 Token::Kind op_kind) { | 1056 Token::Kind op_kind) { |
1076 if (!ShouldInlineSimd()) { | 1057 if (!ShouldInlineSimd()) { |
1077 return false; | 1058 return false; |
1078 } | 1059 } |
1079 ASSERT(call->ArgumentCount() == 2); | 1060 ASSERT(call->ArgumentCount() == 2); |
1080 Definition* left = call->ArgumentAt(0); | 1061 Definition* const left = call->ArgumentAt(0); |
1081 Definition* right = call->ArgumentAt(1); | 1062 Definition* const right = call->ArgumentAt(1); |
1082 // Type check left. | 1063 // Type check left and right. |
1083 AddCheckClass(left, ICData::ZoneHandle( | 1064 AddChecksToArgNr(call, left, /* arg_number = */ 0); |
1084 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 1065 AddChecksToArgNr(call, right, /* arg_number = */ 1); |
1085 call->deopt_id(), call->env(), call); | |
1086 // Type check right. | |
1087 AddCheckClass(right, ICData::ZoneHandle( | |
1088 Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)), | |
1089 call->deopt_id(), call->env(), call); | |
1090 // Replace call. | 1066 // Replace call. |
1091 BinaryFloat32x4OpInstr* float32x4_bin_op = new (Z) BinaryFloat32x4OpInstr( | 1067 BinaryFloat32x4OpInstr* float32x4_bin_op = new (Z) BinaryFloat32x4OpInstr( |
1092 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); | 1068 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); |
1093 ReplaceCall(call, float32x4_bin_op); | 1069 ReplaceCall(call, float32x4_bin_op); |
1094 | 1070 |
1095 return true; | 1071 return true; |
1096 } | 1072 } |
1097 | 1073 |
1098 | 1074 |
1099 bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, | 1075 bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, |
1100 Token::Kind op_kind) { | 1076 Token::Kind op_kind) { |
1101 if (!ShouldInlineSimd()) { | 1077 if (!ShouldInlineSimd()) { |
1102 return false; | 1078 return false; |
1103 } | 1079 } |
1104 ASSERT(call->ArgumentCount() == 2); | 1080 ASSERT(call->ArgumentCount() == 2); |
1105 Definition* left = call->ArgumentAt(0); | 1081 Definition* const left = call->ArgumentAt(0); |
1106 Definition* right = call->ArgumentAt(1); | 1082 Definition* const right = call->ArgumentAt(1); |
1107 // Type check left. | 1083 // Type check left and right. |
1108 AddCheckClass(left, ICData::ZoneHandle( | 1084 AddChecksToArgNr(call, left, /* arg_number = */ 0); |
1109 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 1085 AddChecksToArgNr(call, right, /* arg_number = */ 1); |
1110 call->deopt_id(), call->env(), call); | |
1111 // Type check right. | |
1112 AddCheckClass(right, ICData::ZoneHandle( | |
1113 Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)), | |
1114 call->deopt_id(), call->env(), call); | |
1115 // Replace call. | 1086 // Replace call. |
1116 BinaryInt32x4OpInstr* int32x4_bin_op = new (Z) BinaryInt32x4OpInstr( | 1087 BinaryInt32x4OpInstr* int32x4_bin_op = new (Z) BinaryInt32x4OpInstr( |
1117 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); | 1088 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); |
1118 ReplaceCall(call, int32x4_bin_op); | 1089 ReplaceCall(call, int32x4_bin_op); |
1119 return true; | 1090 return true; |
1120 } | 1091 } |
1121 | 1092 |
1122 | 1093 |
1123 bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, | 1094 bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, |
1124 Token::Kind op_kind) { | 1095 Token::Kind op_kind) { |
1125 if (!ShouldInlineSimd()) { | 1096 if (!ShouldInlineSimd()) { |
1126 return false; | 1097 return false; |
1127 } | 1098 } |
1128 ASSERT(call->ArgumentCount() == 2); | 1099 ASSERT(call->ArgumentCount() == 2); |
1129 Definition* left = call->ArgumentAt(0); | 1100 Definition* const left = call->ArgumentAt(0); |
1130 Definition* right = call->ArgumentAt(1); | 1101 Definition* const right = call->ArgumentAt(1); |
1131 // Type check left. | 1102 // Type check left and right. |
1132 AddCheckClass( | 1103 AddChecksToArgNr(call, left, /* arg_number = */ 0); |
1133 left, ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 1104 AddChecksToArgNr(call, right, /* arg_number = */ 1); |
1134 call->deopt_id(), call->env(), call); | |
1135 // Type check right. | |
1136 AddCheckClass( | |
1137 right, ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(1)), | |
1138 call->deopt_id(), call->env(), call); | |
1139 // Replace call. | 1105 // Replace call. |
1140 BinaryFloat64x2OpInstr* float64x2_bin_op = new (Z) BinaryFloat64x2OpInstr( | 1106 BinaryFloat64x2OpInstr* float64x2_bin_op = new (Z) BinaryFloat64x2OpInstr( |
1141 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); | 1107 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); |
1142 ReplaceCall(call, float64x2_bin_op); | 1108 ReplaceCall(call, float64x2_bin_op); |
1143 return true; | 1109 return true; |
1144 } | 1110 } |
1145 | 1111 |
1146 | 1112 |
1147 // Only unique implicit instance getters can be currently handled. | 1113 // Only unique implicit instance getters can be currently handled. |
1148 bool AotOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { | 1114 bool AotOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { |
(...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1793 } | 1759 } |
1794 | 1760 |
1795 if ((op_kind == Token::kEQ) && TryReplaceWithHaveSameRuntimeType(instr)) { | 1761 if ((op_kind == Token::kEQ) && TryReplaceWithHaveSameRuntimeType(instr)) { |
1796 return; | 1762 return; |
1797 } | 1763 } |
1798 | 1764 |
1799 const ICData& unary_checks = | 1765 const ICData& unary_checks = |
1800 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); | 1766 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); |
1801 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); | 1767 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); |
1802 if (IsAllowedForInlining(instr->deopt_id()) && number_of_checks > 0) { | 1768 if (IsAllowedForInlining(instr->deopt_id()) && number_of_checks > 0) { |
1803 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) { | 1769 if ((op_kind == Token::kINDEX) && |
1770 TryReplaceWithIndexedOp(instr, &unary_checks)) { | |
1804 return; | 1771 return; |
1805 } | 1772 } |
1806 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) { | 1773 if ((op_kind == Token::kASSIGN_INDEX) && |
1774 TryReplaceWithIndexedOp(instr, &unary_checks)) { | |
1807 return; | 1775 return; |
1808 } | 1776 } |
1809 if ((op_kind == Token::kEQ) && TryReplaceWithEqualityOp(instr, op_kind)) { | 1777 if ((op_kind == Token::kEQ) && TryReplaceWithEqualityOp(instr, op_kind)) { |
1810 return; | 1778 return; |
1811 } | 1779 } |
1812 | 1780 |
1813 if (Token::IsRelationalOperator(op_kind) && | 1781 if (Token::IsRelationalOperator(op_kind) && |
1814 TryReplaceWithRelationalOp(instr, op_kind)) { | 1782 TryReplaceWithRelationalOp(instr, op_kind)) { |
1815 return; | 1783 return; |
1816 } | 1784 } |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1902 Class::Handle(Z, isolate()->class_table()->At(receiver_cid)); | 1870 Class::Handle(Z, isolate()->class_table()->At(receiver_cid)); |
1903 | 1871 |
1904 const Array& args_desc_array = | 1872 const Array& args_desc_array = |
1905 Array::Handle(Z, ArgumentsDescriptor::New(instr->ArgumentCount(), | 1873 Array::Handle(Z, ArgumentsDescriptor::New(instr->ArgumentCount(), |
1906 instr->argument_names())); | 1874 instr->argument_names())); |
1907 ArgumentsDescriptor args_desc(args_desc_array); | 1875 ArgumentsDescriptor args_desc(args_desc_array); |
1908 Function& function = Function::Handle( | 1876 Function& function = Function::Handle( |
1909 Z, Resolver::ResolveDynamicForReceiverClass( | 1877 Z, Resolver::ResolveDynamicForReceiverClass( |
1910 receiver_class, instr->function_name(), args_desc)); | 1878 receiver_class, instr->function_name(), args_desc)); |
1911 if (!function.IsNull()) { | 1879 if (!function.IsNull()) { |
1912 CallTargets* targets = new (Z) CallTargets(); | 1880 CallTargets* targets = new (Z) CallTargets(Z); |
1913 Function& target = Function::ZoneHandle(Z, function.raw()); | 1881 Function& target = Function::ZoneHandle(Z, function.raw()); |
1914 targets->Add(CidRangeTarget(receiver_class.id(), receiver_class.id(), | 1882 targets->Add(new (Z) TargetInfo(receiver_class.id(), receiver_class.id(), |
1915 &target, /*count = */ 1)); | 1883 &target, /*count = */ 1)); |
1916 PolymorphicInstanceCallInstr* call = | 1884 PolymorphicInstanceCallInstr* call = |
1917 new (Z) PolymorphicInstanceCallInstr(instr, *targets, | 1885 new (Z) PolymorphicInstanceCallInstr(instr, *targets, |
1918 /* with_checks = */ false, | 1886 /* with_checks = */ false, |
1919 /* complete = */ true); | 1887 /* complete = */ true); |
1920 instr->ReplaceWith(call, current_iterator()); | 1888 instr->ReplaceWith(call, current_iterator()); |
1921 return; | 1889 return; |
1922 } | 1890 } |
1923 } | 1891 } |
1924 | 1892 |
1925 Definition* callee_receiver = instr->ArgumentAt(0); | 1893 Definition* callee_receiver = instr->ArgumentAt(0); |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2134 kDoubleCid)) { | 2102 kDoubleCid)) { |
2135 result_cid = kDoubleCid; | 2103 result_cid = kDoubleCid; |
2136 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, | 2104 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, |
2137 kSmiCid)) { | 2105 kSmiCid)) { |
2138 result_cid = kSmiCid; | 2106 result_cid = kSmiCid; |
2139 } | 2107 } |
2140 if (result_cid != kIllegalCid) { | 2108 if (result_cid != kIllegalCid) { |
2141 MathMinMaxInstr* min_max = new (Z) MathMinMaxInstr( | 2109 MathMinMaxInstr* min_max = new (Z) MathMinMaxInstr( |
2142 recognized_kind, new (Z) Value(call->ArgumentAt(0)), | 2110 recognized_kind, new (Z) Value(call->ArgumentAt(0)), |
2143 new (Z) Value(call->ArgumentAt(1)), call->deopt_id(), result_cid); | 2111 new (Z) Value(call->ArgumentAt(1)), call->deopt_id(), result_cid); |
2144 const ICData& unary_checks = | 2112 const Cids* cids = Cids::Create(Z, ic_data, 0); |
Vyacheslav Egorov (Google)
2017/05/09 21:07:27
please add a comment here about what does 0 means.
erikcorry
2017/05/10 08:47:43
Done.
| |
2145 ICData::ZoneHandle(Z, ic_data.AsUnaryClassChecks()); | 2113 AddCheckClass(min_max->left()->definition(), *cids, call->deopt_id(), |
2146 AddCheckClass(min_max->left()->definition(), unary_checks, | 2114 call->env(), call); |
2147 call->deopt_id(), call->env(), call); | 2115 AddCheckClass(min_max->right()->definition(), *cids, call->deopt_id(), |
2148 AddCheckClass(min_max->right()->definition(), unary_checks, | 2116 call->env(), call); |
2149 call->deopt_id(), call->env(), call); | |
2150 ReplaceCall(call, min_max); | 2117 ReplaceCall(call, min_max); |
2151 } | 2118 } |
2152 } | 2119 } |
2153 break; | 2120 break; |
2154 } | 2121 } |
2155 case MethodRecognizer::kDoubleFromInteger: { | 2122 case MethodRecognizer::kDoubleFromInteger: { |
2156 if (call->HasICData() && call->ic_data()->NumberOfChecksIs(1)) { | 2123 if (call->HasICData() && call->ic_data()->NumberOfChecksIs(1)) { |
2157 const ICData& ic_data = *call->ic_data(); | 2124 const ICData& ic_data = *call->ic_data(); |
2158 if (CanUnboxDouble()) { | 2125 if (CanUnboxDouble()) { |
2159 if (ArgIsAlways(kSmiCid, ic_data, 1)) { | 2126 if (ArgIsAlways(kSmiCid, ic_data, 1)) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2255 FlowGraph::kEffect); | 2222 FlowGraph::kEffect); |
2256 current_iterator()->RemoveCurrentFromGraph(); | 2223 current_iterator()->RemoveCurrentFromGraph(); |
2257 } | 2224 } |
2258 } | 2225 } |
2259 } | 2226 } |
2260 } | 2227 } |
2261 | 2228 |
2262 #endif // DART_PRECOMPILER | 2229 #endif // DART_PRECOMPILER |
2263 | 2230 |
2264 } // namespace dart | 2231 } // namespace dart |
OLD | NEW |