Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(288)

Side by Side Diff: runtime/vm/aot_optimizer.cc

Issue 2856543002: Use off-heap data for class check instructions (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698