Chromium Code Reviews| 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 |