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 CallTargets& targets, |
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_->GetCheckClass(to_check, targets, deopt_id, |
471 insert_before->token_pos()); | 458 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::AddReceiverCheck(InstanceCallInstr* call) { |
477 AddCheckClass(call->ArgumentAt(0), | 464 AddCheckClass(call->ArgumentAt(0), |
478 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()), | 465 *CallTargets::Create(Z, *call->ic_data(), 0), call->deopt_id(), |
Vyacheslav Egorov (Google)
2017/05/01 12:21:24
please add a comment to the numeric argument here
erikcorry
2017/05/05 15:15:51
Done.
| |
479 call->deopt_id(), call->env(), call); | 466 call->env(), call); |
480 } | 467 } |
481 | 468 |
482 | 469 |
483 static bool ArgIsAlways(intptr_t cid, | 470 static bool ArgIsAlways(intptr_t cid, |
484 const ICData& ic_data, | 471 const ICData& ic_data, |
485 intptr_t arg_number) { | 472 intptr_t arg_number) { |
486 ASSERT(ic_data.NumArgsTested() > arg_number); | 473 ASSERT(ic_data.NumArgsTested() > arg_number); |
487 if (ic_data.NumberOfUsedChecks() == 0) { | 474 if (ic_data.NumberOfUsedChecks() == 0) { |
488 return false; | 475 return false; |
489 } | 476 } |
490 const intptr_t num_checks = ic_data.NumberOfChecks(); | 477 const intptr_t num_checks = ic_data.NumberOfChecks(); |
491 for (intptr_t i = 0; i < num_checks; i++) { | 478 for (intptr_t i = 0; i < num_checks; i++) { |
492 if (ic_data.IsUsedAt(i) && ic_data.GetClassIdAt(i, arg_number) != cid) { | 479 if (ic_data.IsUsedAt(i) && ic_data.GetClassIdAt(i, arg_number) != cid) { |
493 return false; | 480 return false; |
494 } | 481 } |
495 } | 482 } |
496 return true; | 483 return true; |
497 } | 484 } |
498 | 485 |
499 | 486 |
500 bool AotOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) { | 487 bool AotOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) { |
501 // Check for monomorphic IC data. | 488 // Check for monomorphic IC data. |
502 if (!call->HasICData()) return false; | 489 if (!call->HasICData()) return false; |
503 const ICData& ic_data = | 490 if (!call->ic_data()->NumberOfChecksIs(1)) { |
Vyacheslav Egorov (Google)
2017/05/01 12:21:24
these are not equivalent - as unary checks collaps
erikcorry
2017/05/05 15:15:51
Good catch, it does matter.
| |
504 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks()); | |
505 if (!ic_data.NumberOfChecksIs(1)) { | |
506 return false; | 491 return false; |
507 } | 492 } |
508 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | 493 return FlowGraphInliner::TryReplaceInstanceCallWithInline( |
509 flow_graph_, current_iterator(), call); | 494 flow_graph_, current_iterator(), call); |
510 } | 495 } |
511 | 496 |
512 | 497 |
513 // Return true if d is a string of length one (a constant or result from | 498 // Return true if d is a string of length one (a constant or result from |
514 // from string-from-char-code instruction. | 499 // from string-from-char-code instruction. |
515 static bool IsLengthOneString(Definition* d) { | 500 static bool IsLengthOneString(Definition* d) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
568 | 553 |
569 Definition* to_remove_right = NULL; | 554 Definition* to_remove_right = NULL; |
570 Value* right_val = NULL; | 555 Value* right_val = NULL; |
571 if (right->IsOneByteStringFromCharCode()) { | 556 if (right->IsOneByteStringFromCharCode()) { |
572 // Skip string-from-char-code, and use its input as right value. | 557 // Skip string-from-char-code, and use its input as right value. |
573 OneByteStringFromCharCodeInstr* right_instr = | 558 OneByteStringFromCharCodeInstr* right_instr = |
574 right->AsOneByteStringFromCharCode(); | 559 right->AsOneByteStringFromCharCode(); |
575 right_val = new (Z) Value(right_instr->char_code()->definition()); | 560 right_val = new (Z) Value(right_instr->char_code()->definition()); |
576 to_remove_right = right_instr; | 561 to_remove_right = right_instr; |
577 } else { | 562 } else { |
578 const ICData& unary_checks_1 = | 563 const CallTargets* targets_1 = |
579 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)); | 564 CallTargets::Create(Z, *call->ic_data(), 1); |
580 AddCheckClass(right, unary_checks_1, call->deopt_id(), call->env(), call); | 565 AddCheckClass(right, *targets_1, call->deopt_id(), call->env(), call); |
Vyacheslav Egorov (Google)
2017/05/01 12:21:24
This code is repeated, so it could be a helper:
A
erikcorry
2017/05/05 15:15:51
Done.
| |
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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after 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 const CallTargets* targets_0 = |
717 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 702 CallTargets::Create(Z, *call->ic_data(), 0); |
718 AddCheckClass(left, unary_checks_0, call->deopt_id(), call->env(), call); | 703 AddCheckClass(left, *targets_0, call->deopt_id(), call->env(), call); |
719 | 704 |
720 const ICData& unary_checks_1 = | 705 const CallTargets* targets_1 = |
721 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)); | 706 CallTargets::Create(Z, *call->ic_data(), 1); |
722 AddCheckClass(right, unary_checks_1, call->deopt_id(), call->env(), call); | 707 AddCheckClass(right, *targets_1, call->deopt_id(), call->env(), call); |
708 | |
723 cid = kSmiCid; | 709 cid = kSmiCid; |
724 } else { | 710 } else { |
725 // Shortcut for equality with null. | 711 // Shortcut for equality with null. |
726 // TODO(vegorov): this optimization is not speculative and should | 712 // TODO(vegorov): this optimization is not speculative and should |
727 // be hoisted out of this function. | 713 // be hoisted out of this function. |
728 ConstantInstr* right_const = right->AsConstant(); | 714 ConstantInstr* right_const = right->AsConstant(); |
729 ConstantInstr* left_const = left->AsConstant(); | 715 ConstantInstr* left_const = left->AsConstant(); |
730 if ((right_const != NULL && right_const->value().IsNull()) || | 716 if ((right_const != NULL && right_const->value().IsNull()) || |
731 (left_const != NULL && left_const->value().IsNull())) { | 717 (left_const != NULL && left_const->value().IsNull())) { |
732 StrictCompareInstr* comp = new (Z) | 718 StrictCompareInstr* comp = new (Z) |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1073 | 1059 |
1074 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, | 1060 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, |
1075 Token::Kind op_kind) { | 1061 Token::Kind op_kind) { |
1076 if (!ShouldInlineSimd()) { | 1062 if (!ShouldInlineSimd()) { |
1077 return false; | 1063 return false; |
1078 } | 1064 } |
1079 ASSERT(call->ArgumentCount() == 2); | 1065 ASSERT(call->ArgumentCount() == 2); |
1080 Definition* left = call->ArgumentAt(0); | 1066 Definition* left = call->ArgumentAt(0); |
1081 Definition* right = call->ArgumentAt(1); | 1067 Definition* right = call->ArgumentAt(1); |
1082 // Type check left. | 1068 // Type check left. |
1083 AddCheckClass(left, ICData::ZoneHandle( | 1069 AddCheckClass(left, *CallTargets::Create(Z, *call->ic_data(), 0), |
1084 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
1085 call->deopt_id(), call->env(), call); | 1070 call->deopt_id(), call->env(), call); |
1086 // Type check right. | 1071 // Type check right. |
1087 AddCheckClass(right, ICData::ZoneHandle( | 1072 AddCheckClass(right, *CallTargets::Create(Z, *call->ic_data(), 1), |
1088 Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)), | |
1089 call->deopt_id(), call->env(), call); | 1073 call->deopt_id(), call->env(), call); |
1090 // Replace call. | 1074 // Replace call. |
1091 BinaryFloat32x4OpInstr* float32x4_bin_op = new (Z) BinaryFloat32x4OpInstr( | 1075 BinaryFloat32x4OpInstr* float32x4_bin_op = new (Z) BinaryFloat32x4OpInstr( |
1092 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); | 1076 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); |
1093 ReplaceCall(call, float32x4_bin_op); | 1077 ReplaceCall(call, float32x4_bin_op); |
1094 | 1078 |
1095 return true; | 1079 return true; |
1096 } | 1080 } |
1097 | 1081 |
1098 | 1082 |
1099 bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, | 1083 bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, |
1100 Token::Kind op_kind) { | 1084 Token::Kind op_kind) { |
1101 if (!ShouldInlineSimd()) { | 1085 if (!ShouldInlineSimd()) { |
1102 return false; | 1086 return false; |
1103 } | 1087 } |
1104 ASSERT(call->ArgumentCount() == 2); | 1088 ASSERT(call->ArgumentCount() == 2); |
1105 Definition* left = call->ArgumentAt(0); | 1089 Definition* left = call->ArgumentAt(0); |
1106 Definition* right = call->ArgumentAt(1); | 1090 Definition* right = call->ArgumentAt(1); |
1107 // Type check left. | 1091 // Type check left. |
1108 AddCheckClass(left, ICData::ZoneHandle( | 1092 AddCheckClass(left, *CallTargets::Create(Z, *call->ic_data(), 0), |
1109 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
1110 call->deopt_id(), call->env(), call); | 1093 call->deopt_id(), call->env(), call); |
1111 // Type check right. | 1094 // Type check right. |
1112 AddCheckClass(right, ICData::ZoneHandle( | 1095 AddCheckClass(right, *CallTargets::Create(Z, *call->ic_data(), 1), |
1113 Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)), | |
1114 call->deopt_id(), call->env(), call); | 1096 call->deopt_id(), call->env(), call); |
1115 // Replace call. | 1097 // Replace call. |
1116 BinaryInt32x4OpInstr* int32x4_bin_op = new (Z) BinaryInt32x4OpInstr( | 1098 BinaryInt32x4OpInstr* int32x4_bin_op = new (Z) BinaryInt32x4OpInstr( |
1117 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); | 1099 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); |
1118 ReplaceCall(call, int32x4_bin_op); | 1100 ReplaceCall(call, int32x4_bin_op); |
1119 return true; | 1101 return true; |
1120 } | 1102 } |
1121 | 1103 |
1122 | 1104 |
1123 bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, | 1105 bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, |
1124 Token::Kind op_kind) { | 1106 Token::Kind op_kind) { |
1125 if (!ShouldInlineSimd()) { | 1107 if (!ShouldInlineSimd()) { |
1126 return false; | 1108 return false; |
1127 } | 1109 } |
1128 ASSERT(call->ArgumentCount() == 2); | 1110 ASSERT(call->ArgumentCount() == 2); |
1129 Definition* left = call->ArgumentAt(0); | 1111 Definition* left = call->ArgumentAt(0); |
1130 Definition* right = call->ArgumentAt(1); | 1112 Definition* right = call->ArgumentAt(1); |
1131 // Type check left. | 1113 // Type check left. |
1132 AddCheckClass( | 1114 AddCheckClass(left, *CallTargets::Create(Z, *call->ic_data(), 0), |
1133 left, ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 1115 call->deopt_id(), call->env(), call); |
1134 call->deopt_id(), call->env(), call); | |
1135 // Type check right. | 1116 // Type check right. |
1136 AddCheckClass( | 1117 AddCheckClass(right, *CallTargets::Create(Z, *call->ic_data(), 1), |
1137 right, ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(1)), | 1118 call->deopt_id(), call->env(), call); |
1138 call->deopt_id(), call->env(), call); | |
1139 // Replace call. | 1119 // Replace call. |
1140 BinaryFloat64x2OpInstr* float64x2_bin_op = new (Z) BinaryFloat64x2OpInstr( | 1120 BinaryFloat64x2OpInstr* float64x2_bin_op = new (Z) BinaryFloat64x2OpInstr( |
1141 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); | 1121 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); |
1142 ReplaceCall(call, float64x2_bin_op); | 1122 ReplaceCall(call, float64x2_bin_op); |
1143 return true; | 1123 return true; |
1144 } | 1124 } |
1145 | 1125 |
1146 | 1126 |
1147 // Only unique implicit instance getters can be currently handled. | 1127 // Only unique implicit instance getters can be currently handled. |
1148 bool AotOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { | 1128 bool AotOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { |
(...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1835 // we don't have one target. | 1815 // we don't have one target. |
1836 const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0)); | 1816 const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0)); |
1837 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); | 1817 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); |
1838 has_one_target = !polymorphic_target; | 1818 has_one_target = !polymorphic_target; |
1839 } | 1819 } |
1840 | 1820 |
1841 if (has_one_target) { | 1821 if (has_one_target) { |
1842 RawFunction::Kind function_kind = | 1822 RawFunction::Kind function_kind = |
1843 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); | 1823 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); |
1844 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) { | 1824 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) { |
1845 CallTargets* targets = CallTargets::Create(Z, unary_checks); | 1825 CallTargets* targets = CallTargets::Create(Z, unary_checks, 0); |
1846 PolymorphicInstanceCallInstr* call = | 1826 PolymorphicInstanceCallInstr* call = |
1847 new (Z) PolymorphicInstanceCallInstr(instr, *targets, | 1827 new (Z) PolymorphicInstanceCallInstr(instr, *targets, |
1848 /* with_checks = */ false, | 1828 /* with_checks = */ false, |
1849 /* complete = */ true); | 1829 /* complete = */ true); |
1850 instr->ReplaceWith(call, current_iterator()); | 1830 instr->ReplaceWith(call, current_iterator()); |
1851 return; | 1831 return; |
1852 } | 1832 } |
1853 } | 1833 } |
1854 switch (instr->token_kind()) { | 1834 switch (instr->token_kind()) { |
1855 case Token::kEQ: | 1835 case Token::kEQ: |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2030 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) { | 2010 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) { |
2031 args->Add(instr->PushArgumentAt(i)); | 2011 args->Add(instr->PushArgumentAt(i)); |
2032 } | 2012 } |
2033 StaticCallInstr* call = new (Z) StaticCallInstr( | 2013 StaticCallInstr* call = new (Z) StaticCallInstr( |
2034 instr->token_pos(), Function::ZoneHandle(Z, single_target.raw()), | 2014 instr->token_pos(), Function::ZoneHandle(Z, single_target.raw()), |
2035 instr->argument_names(), args, instr->deopt_id()); | 2015 instr->argument_names(), args, instr->deopt_id()); |
2036 instr->ReplaceWith(call, current_iterator()); | 2016 instr->ReplaceWith(call, current_iterator()); |
2037 return; | 2017 return; |
2038 } else if ((ic_data.raw() != ICData::null()) && | 2018 } else if ((ic_data.raw() != ICData::null()) && |
2039 !ic_data.NumberOfChecksIs(0)) { | 2019 !ic_data.NumberOfChecksIs(0)) { |
2040 CallTargets* targets = CallTargets::Create(Z, ic_data); | 2020 CallTargets* targets = CallTargets::Create(Z, ic_data, 0); |
2041 PolymorphicInstanceCallInstr* call = | 2021 PolymorphicInstanceCallInstr* call = |
2042 new (Z) PolymorphicInstanceCallInstr(instr, *targets, | 2022 new (Z) PolymorphicInstanceCallInstr(instr, *targets, |
2043 /* with_checks = */ true, | 2023 /* with_checks = */ true, |
2044 /* complete = */ true); | 2024 /* complete = */ true); |
2045 instr->ReplaceWith(call, current_iterator()); | 2025 instr->ReplaceWith(call, current_iterator()); |
2046 return; | 2026 return; |
2047 } | 2027 } |
2048 } | 2028 } |
2049 } | 2029 } |
2050 | 2030 |
2051 // More than one target. Generate generic polymorphic call without | 2031 // More than one target. Generate generic polymorphic call without |
2052 // deoptimization. | 2032 // deoptimization. |
2053 if (instr->ic_data()->NumberOfUsedChecks() > 0) { | 2033 if (instr->ic_data()->NumberOfUsedChecks() > 0) { |
2054 ASSERT(!FLAG_polymorphic_with_deopt); | 2034 ASSERT(!FLAG_polymorphic_with_deopt); |
2055 // OK to use checks with PolymorphicInstanceCallInstr since no | 2035 // OK to use checks with PolymorphicInstanceCallInstr since no |
2056 // deoptimization is allowed. | 2036 // deoptimization is allowed. |
2057 CallTargets* targets = CallTargets::Create(Z, *instr->ic_data()); | 2037 CallTargets* targets = CallTargets::Create(Z, *instr->ic_data(), 0); |
2058 PolymorphicInstanceCallInstr* call = | 2038 PolymorphicInstanceCallInstr* call = |
2059 new (Z) PolymorphicInstanceCallInstr(instr, *targets, | 2039 new (Z) PolymorphicInstanceCallInstr(instr, *targets, |
2060 /* with_checks = */ true, | 2040 /* with_checks = */ true, |
2061 /* complete = */ false); | 2041 /* complete = */ false); |
2062 instr->ReplaceWith(call, current_iterator()); | 2042 instr->ReplaceWith(call, current_iterator()); |
2063 return; | 2043 return; |
2064 } | 2044 } |
2065 } | 2045 } |
2066 | 2046 |
2067 | 2047 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2134 kDoubleCid)) { | 2114 kDoubleCid)) { |
2135 result_cid = kDoubleCid; | 2115 result_cid = kDoubleCid; |
2136 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, | 2116 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, |
2137 kSmiCid)) { | 2117 kSmiCid)) { |
2138 result_cid = kSmiCid; | 2118 result_cid = kSmiCid; |
2139 } | 2119 } |
2140 if (result_cid != kIllegalCid) { | 2120 if (result_cid != kIllegalCid) { |
2141 MathMinMaxInstr* min_max = new (Z) MathMinMaxInstr( | 2121 MathMinMaxInstr* min_max = new (Z) MathMinMaxInstr( |
2142 recognized_kind, new (Z) Value(call->ArgumentAt(0)), | 2122 recognized_kind, new (Z) Value(call->ArgumentAt(0)), |
2143 new (Z) Value(call->ArgumentAt(1)), call->deopt_id(), result_cid); | 2123 new (Z) Value(call->ArgumentAt(1)), call->deopt_id(), result_cid); |
2144 const ICData& unary_checks = | 2124 const CallTargets* targets = CallTargets::Create(Z, ic_data, 0); |
2145 ICData::ZoneHandle(Z, ic_data.AsUnaryClassChecks()); | 2125 AddCheckClass(min_max->left()->definition(), *targets, |
2146 AddCheckClass(min_max->left()->definition(), unary_checks, | |
2147 call->deopt_id(), call->env(), call); | 2126 call->deopt_id(), call->env(), call); |
2148 AddCheckClass(min_max->right()->definition(), unary_checks, | 2127 AddCheckClass(min_max->right()->definition(), *targets, |
2149 call->deopt_id(), call->env(), call); | 2128 call->deopt_id(), call->env(), call); |
2150 ReplaceCall(call, min_max); | 2129 ReplaceCall(call, min_max); |
2151 } | 2130 } |
2152 } | 2131 } |
2153 break; | 2132 break; |
2154 } | 2133 } |
2155 case MethodRecognizer::kDoubleFromInteger: { | 2134 case MethodRecognizer::kDoubleFromInteger: { |
2156 if (call->HasICData() && call->ic_data()->NumberOfChecksIs(1)) { | 2135 if (call->HasICData() && call->ic_data()->NumberOfChecksIs(1)) { |
2157 const ICData& ic_data = *call->ic_data(); | 2136 const ICData& ic_data = *call->ic_data(); |
2158 if (CanUnboxDouble()) { | 2137 if (CanUnboxDouble()) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2255 FlowGraph::kEffect); | 2234 FlowGraph::kEffect); |
2256 current_iterator()->RemoveCurrentFromGraph(); | 2235 current_iterator()->RemoveCurrentFromGraph(); |
2257 } | 2236 } |
2258 } | 2237 } |
2259 } | 2238 } |
2260 } | 2239 } |
2261 | 2240 |
2262 #endif // DART_PRECOMPILER | 2241 #endif // DART_PRECOMPILER |
2263 | 2242 |
2264 } // namespace dart | 2243 } // namespace dart |
OLD | NEW |