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 #ifndef DART_PRECOMPILED_RUNTIME | 4 #ifndef DART_PRECOMPILED_RUNTIME |
5 #include "vm/jit_optimizer.h" | 5 #include "vm/jit_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 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 Instruction* insert_before) { | 382 Instruction* insert_before) { |
383 if (to_check->Type()->ToCid() != kSmiCid) { | 383 if (to_check->Type()->ToCid() != kSmiCid) { |
384 InsertBefore(insert_before, | 384 InsertBefore(insert_before, |
385 new (Z) CheckSmiInstr(new (Z) Value(to_check), deopt_id, | 385 new (Z) CheckSmiInstr(new (Z) Value(to_check), deopt_id, |
386 insert_before->token_pos()), | 386 insert_before->token_pos()), |
387 deopt_environment, FlowGraph::kEffect); | 387 deopt_environment, FlowGraph::kEffect); |
388 } | 388 } |
389 } | 389 } |
390 | 390 |
391 | 391 |
392 Instruction* JitOptimizer::GetCheckClass(Definition* to_check, | |
393 const ICData& unary_checks, | |
394 intptr_t deopt_id, | |
395 TokenPosition token_pos) { | |
396 if ((unary_checks.NumberOfUsedChecks() == 1) && | |
397 unary_checks.HasReceiverClassId(kSmiCid)) { | |
398 return new (Z) CheckSmiInstr(new (Z) Value(to_check), deopt_id, token_pos); | |
399 } | |
400 return new (Z) CheckClassInstr(new (Z) Value(to_check), deopt_id, | |
401 unary_checks, token_pos); | |
402 } | |
403 | |
404 | |
405 void JitOptimizer::AddCheckClass(Definition* to_check, | 392 void JitOptimizer::AddCheckClass(Definition* to_check, |
406 const ICData& unary_checks, | 393 const CallTargets& targets, |
407 intptr_t deopt_id, | 394 intptr_t deopt_id, |
408 Environment* deopt_environment, | 395 Environment* deopt_environment, |
409 Instruction* insert_before) { | 396 Instruction* insert_before) { |
410 // Type propagation has not run yet, we cannot eliminate the check. | 397 // Type propagation has not run yet, we cannot eliminate the check. |
411 Instruction* check = GetCheckClass(to_check, unary_checks, deopt_id, | 398 Instruction* check = flow_graph_->GetCheckClass(to_check, targets, deopt_id, |
412 insert_before->token_pos()); | 399 insert_before->token_pos()); |
413 InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect); | 400 InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect); |
414 } | 401 } |
415 | 402 |
416 | 403 |
417 void JitOptimizer::AddReceiverCheck(InstanceCallInstr* call) { | 404 void JitOptimizer::AddReceiverCheck(InstanceCallInstr* call) { |
418 AddCheckClass(call->ArgumentAt(0), | 405 AddCheckClass( |
419 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()), | 406 call->ArgumentAt(0), |
420 call->deopt_id(), call->env(), call); | 407 *CallTargets::Create(Z, *call->ic_data(), /* argument_number = */ 0), |
| 408 call->deopt_id(), call->env(), call); |
421 } | 409 } |
422 | 410 |
423 | 411 |
424 static bool ArgIsAlways(intptr_t cid, | 412 static bool ArgIsAlways(intptr_t cid, |
425 const ICData& ic_data, | 413 const ICData& ic_data, |
426 intptr_t arg_number) { | 414 intptr_t arg_number) { |
427 ASSERT(ic_data.NumArgsTested() > arg_number); | 415 ASSERT(ic_data.NumArgsTested() > arg_number); |
428 if (ic_data.NumberOfUsedChecks() == 0) { | 416 if (ic_data.NumberOfUsedChecks() == 0) { |
429 return false; | 417 return false; |
430 } | 418 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 | 497 |
510 Definition* to_remove_right = NULL; | 498 Definition* to_remove_right = NULL; |
511 Value* right_val = NULL; | 499 Value* right_val = NULL; |
512 if (right->IsOneByteStringFromCharCode()) { | 500 if (right->IsOneByteStringFromCharCode()) { |
513 // Skip string-from-char-code, and use its input as right value. | 501 // Skip string-from-char-code, and use its input as right value. |
514 OneByteStringFromCharCodeInstr* right_instr = | 502 OneByteStringFromCharCodeInstr* right_instr = |
515 right->AsOneByteStringFromCharCode(); | 503 right->AsOneByteStringFromCharCode(); |
516 right_val = new (Z) Value(right_instr->char_code()->definition()); | 504 right_val = new (Z) Value(right_instr->char_code()->definition()); |
517 to_remove_right = right_instr; | 505 to_remove_right = right_instr; |
518 } else { | 506 } else { |
519 const ICData& unary_checks_1 = | 507 const CallTargets* targets_1 = |
520 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)); | 508 CallTargets::Create(Z, *call->ic_data(), 1); |
521 AddCheckClass(right, unary_checks_1, call->deopt_id(), call->env(), call); | 509 AddCheckClass(right, *targets_1, call->deopt_id(), call->env(), call); |
522 // String-to-char-code instructions returns -1 (illegal charcode) if | 510 // String-to-char-code instructions returns -1 (illegal charcode) if |
523 // string is not of length one. | 511 // string is not of length one. |
524 StringToCharCodeInstr* char_code_right = new (Z) | 512 StringToCharCodeInstr* char_code_right = new (Z) |
525 StringToCharCodeInstr(new (Z) Value(right), kOneByteStringCid); | 513 StringToCharCodeInstr(new (Z) Value(right), kOneByteStringCid); |
526 InsertBefore(call, char_code_right, call->env(), FlowGraph::kValue); | 514 InsertBefore(call, char_code_right, call->env(), FlowGraph::kValue); |
527 right_val = new (Z) Value(char_code_right); | 515 right_val = new (Z) Value(char_code_right); |
528 } | 516 } |
529 | 517 |
530 // Comparing char-codes instead of strings. | 518 // Comparing char-codes instead of strings. |
531 EqualityCompareInstr* comp = | 519 EqualityCompareInstr* comp = |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 } | 590 } |
603 } else { | 591 } else { |
604 // Check if ICDData contains checks with Smi/Null combinations. In that case | 592 // Check if ICDData contains checks with Smi/Null combinations. In that case |
605 // we can still emit the optimized Smi equality operation but need to add | 593 // we can still emit the optimized Smi equality operation but need to add |
606 // checks for null or Smi. | 594 // checks for null or Smi. |
607 GrowableArray<intptr_t> smi_or_null(2); | 595 GrowableArray<intptr_t> smi_or_null(2); |
608 smi_or_null.Add(kSmiCid); | 596 smi_or_null.Add(kSmiCid); |
609 smi_or_null.Add(kNullCid); | 597 smi_or_null.Add(kNullCid); |
610 if (ICDataHasOnlyReceiverArgumentClassIds(ic_data, smi_or_null, | 598 if (ICDataHasOnlyReceiverArgumentClassIds(ic_data, smi_or_null, |
611 smi_or_null)) { | 599 smi_or_null)) { |
612 const ICData& unary_checks_0 = | 600 const CallTargets* targets_0 = |
613 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 601 CallTargets::Create(Z, *call->ic_data(), 0); |
614 AddCheckClass(left, unary_checks_0, call->deopt_id(), call->env(), call); | 602 AddCheckClass(left, *targets_0, call->deopt_id(), call->env(), call); |
615 | 603 |
616 const ICData& unary_checks_1 = | 604 const CallTargets* targets_1 = |
617 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)); | 605 CallTargets::Create(Z, *call->ic_data(), 1); |
618 AddCheckClass(right, unary_checks_1, call->deopt_id(), call->env(), call); | 606 AddCheckClass(right, *targets_1, call->deopt_id(), call->env(), call); |
619 cid = kSmiCid; | 607 cid = kSmiCid; |
620 } else { | 608 } else { |
621 // Shortcut for equality with null. | 609 // Shortcut for equality with null. |
622 ConstantInstr* right_const = right->AsConstant(); | 610 ConstantInstr* right_const = right->AsConstant(); |
623 ConstantInstr* left_const = left->AsConstant(); | 611 ConstantInstr* left_const = left->AsConstant(); |
624 if ((right_const != NULL && right_const->value().IsNull()) || | 612 if ((right_const != NULL && right_const->value().IsNull()) || |
625 (left_const != NULL && left_const->value().IsNull())) { | 613 (left_const != NULL && left_const->value().IsNull())) { |
626 StrictCompareInstr* comp = new (Z) | 614 StrictCompareInstr* comp = new (Z) |
627 StrictCompareInstr(call->token_pos(), Token::kEQ_STRICT, | 615 StrictCompareInstr(call->token_pos(), Token::kEQ_STRICT, |
628 new (Z) Value(left), new (Z) Value(right), | 616 new (Z) Value(left), new (Z) Value(right), |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
973 | 961 |
974 bool JitOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, | 962 bool JitOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, |
975 Token::Kind op_kind) { | 963 Token::Kind op_kind) { |
976 if (!ShouldInlineSimd()) { | 964 if (!ShouldInlineSimd()) { |
977 return false; | 965 return false; |
978 } | 966 } |
979 ASSERT(call->ArgumentCount() == 2); | 967 ASSERT(call->ArgumentCount() == 2); |
980 Definition* left = call->ArgumentAt(0); | 968 Definition* left = call->ArgumentAt(0); |
981 Definition* right = call->ArgumentAt(1); | 969 Definition* right = call->ArgumentAt(1); |
982 // Type check left. | 970 // Type check left. |
983 AddCheckClass(left, ICData::ZoneHandle( | 971 AddCheckClass(left, *CallTargets::Create(Z, *call->ic_data(), 0), |
984 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
985 call->deopt_id(), call->env(), call); | 972 call->deopt_id(), call->env(), call); |
986 // Type check right. | 973 // Type check right. |
987 AddCheckClass(right, ICData::ZoneHandle( | 974 AddCheckClass(right, *CallTargets::Create(Z, *call->ic_data(), 1), |
988 Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)), | |
989 call->deopt_id(), call->env(), call); | 975 call->deopt_id(), call->env(), call); |
990 // Replace call. | 976 // Replace call. |
991 BinaryFloat32x4OpInstr* float32x4_bin_op = new (Z) BinaryFloat32x4OpInstr( | 977 BinaryFloat32x4OpInstr* float32x4_bin_op = new (Z) BinaryFloat32x4OpInstr( |
992 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); | 978 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); |
993 ReplaceCall(call, float32x4_bin_op); | 979 ReplaceCall(call, float32x4_bin_op); |
994 | 980 |
995 return true; | 981 return true; |
996 } | 982 } |
997 | 983 |
998 | 984 |
999 bool JitOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, | 985 bool JitOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, |
1000 Token::Kind op_kind) { | 986 Token::Kind op_kind) { |
1001 if (!ShouldInlineSimd()) { | 987 if (!ShouldInlineSimd()) { |
1002 return false; | 988 return false; |
1003 } | 989 } |
1004 ASSERT(call->ArgumentCount() == 2); | 990 ASSERT(call->ArgumentCount() == 2); |
1005 Definition* left = call->ArgumentAt(0); | 991 Definition* left = call->ArgumentAt(0); |
1006 Definition* right = call->ArgumentAt(1); | 992 Definition* right = call->ArgumentAt(1); |
1007 // Type check left. | 993 // Type check left. |
1008 AddCheckClass(left, ICData::ZoneHandle( | 994 AddCheckClass(left, *CallTargets::Create(Z, *call->ic_data(), 0), |
1009 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
1010 call->deopt_id(), call->env(), call); | 995 call->deopt_id(), call->env(), call); |
1011 // Type check right. | 996 // Type check right. |
1012 AddCheckClass(right, ICData::ZoneHandle( | 997 AddCheckClass(right, *CallTargets::Create(Z, *call->ic_data(), 1), |
1013 Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)), | |
1014 call->deopt_id(), call->env(), call); | 998 call->deopt_id(), call->env(), call); |
1015 // Replace call. | 999 // Replace call. |
1016 BinaryInt32x4OpInstr* int32x4_bin_op = new (Z) BinaryInt32x4OpInstr( | 1000 BinaryInt32x4OpInstr* int32x4_bin_op = new (Z) BinaryInt32x4OpInstr( |
1017 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); | 1001 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); |
1018 ReplaceCall(call, int32x4_bin_op); | 1002 ReplaceCall(call, int32x4_bin_op); |
1019 return true; | 1003 return true; |
1020 } | 1004 } |
1021 | 1005 |
1022 | 1006 |
1023 bool JitOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, | 1007 bool JitOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, |
1024 Token::Kind op_kind) { | 1008 Token::Kind op_kind) { |
1025 if (!ShouldInlineSimd()) { | 1009 if (!ShouldInlineSimd()) { |
1026 return false; | 1010 return false; |
1027 } | 1011 } |
1028 ASSERT(call->ArgumentCount() == 2); | 1012 ASSERT(call->ArgumentCount() == 2); |
1029 Definition* left = call->ArgumentAt(0); | 1013 Definition* left = call->ArgumentAt(0); |
1030 Definition* right = call->ArgumentAt(1); | 1014 Definition* right = call->ArgumentAt(1); |
1031 // Type check left. | 1015 // Type check left. |
1032 AddCheckClass( | 1016 AddCheckClass(left, *CallTargets::Create(Z, *call->ic_data(), 0), |
1033 left, ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 1017 call->deopt_id(), call->env(), call); |
1034 call->deopt_id(), call->env(), call); | |
1035 // Type check right. | 1018 // Type check right. |
1036 AddCheckClass( | 1019 AddCheckClass(right, *CallTargets::Create(Z, *call->ic_data(), 1), |
1037 right, ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(1)), | 1020 call->deopt_id(), call->env(), call); |
1038 call->deopt_id(), call->env(), call); | |
1039 // Replace call. | 1021 // Replace call. |
1040 BinaryFloat64x2OpInstr* float64x2_bin_op = new (Z) BinaryFloat64x2OpInstr( | 1022 BinaryFloat64x2OpInstr* float64x2_bin_op = new (Z) BinaryFloat64x2OpInstr( |
1041 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); | 1023 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); |
1042 ReplaceCall(call, float64x2_bin_op); | 1024 ReplaceCall(call, float64x2_bin_op); |
1043 return true; | 1025 return true; |
1044 } | 1026 } |
1045 | 1027 |
1046 | 1028 |
1047 // Only unique implicit instance getters can be currently handled. | 1029 // Only unique implicit instance getters can be currently handled. |
1048 bool JitOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { | 1030 bool JitOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1502 return; | 1484 return; |
1503 } | 1485 } |
1504 if ((op_kind == Token::kSET) && | 1486 if ((op_kind == Token::kSET) && |
1505 TryInlineInstanceSetter(instr, unary_checks)) { | 1487 TryInlineInstanceSetter(instr, unary_checks)) { |
1506 return; | 1488 return; |
1507 } | 1489 } |
1508 if (TryInlineInstanceMethod(instr)) { | 1490 if (TryInlineInstanceMethod(instr)) { |
1509 return; | 1491 return; |
1510 } | 1492 } |
1511 | 1493 |
1512 CallTargets* targets = CallTargets::Create(Z, unary_checks); | 1494 const CallTargets& targets = *CallTargets::CreateAndExpand(Z, unary_checks); |
1513 | 1495 |
1514 bool has_one_target = targets->HasSingleTarget(); | 1496 bool has_one_target = targets.HasSingleTarget(); |
1515 | 1497 |
1516 if (has_one_target) { | 1498 if (has_one_target) { |
1517 // Check if the single target is a polymorphic target, if it is, | 1499 // Check if the single target is a polymorphic target, if it is, |
1518 // we don't have one target. | 1500 // we don't have one target. |
1519 const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0)); | 1501 const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0)); |
1520 if (target.recognized_kind() == MethodRecognizer::kObjectRuntimeType) { | 1502 if (target.recognized_kind() == MethodRecognizer::kObjectRuntimeType) { |
1521 has_one_target = PolymorphicInstanceCallInstr::ComputeRuntimeType( | 1503 has_one_target = PolymorphicInstanceCallInstr::ComputeRuntimeType( |
1522 *targets) != Type::null(); | 1504 targets) != Type::null(); |
1523 } else { | 1505 } else { |
1524 const bool polymorphic_target = | 1506 const bool polymorphic_target = |
1525 MethodRecognizer::PolymorphicTarget(target); | 1507 MethodRecognizer::PolymorphicTarget(target); |
1526 has_one_target = !polymorphic_target; | 1508 has_one_target = !polymorphic_target; |
1527 } | 1509 } |
1528 } | 1510 } |
1529 | 1511 |
1530 if (has_one_target) { | 1512 if (has_one_target) { |
1531 const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0)); | 1513 const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0)); |
1532 const RawFunction::Kind function_kind = target.kind(); | 1514 const RawFunction::Kind function_kind = target.kind(); |
1533 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) { | 1515 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) { |
1534 PolymorphicInstanceCallInstr* call = | 1516 PolymorphicInstanceCallInstr* call = |
1535 new (Z) PolymorphicInstanceCallInstr(instr, *targets, | 1517 new (Z) PolymorphicInstanceCallInstr(instr, targets, |
1536 /* call_with_checks = */ false, | 1518 /* call_with_checks = */ false, |
1537 /* complete = */ false); | 1519 /* complete = */ false); |
1538 instr->ReplaceWith(call, current_iterator()); | 1520 instr->ReplaceWith(call, current_iterator()); |
1539 return; | 1521 return; |
1540 } | 1522 } |
1541 } | 1523 } |
1542 | 1524 |
1543 // If there is only one target we can make this into a deopting class check, | 1525 // If there is only one target we can make this into a deopting class check, |
1544 // followed by a call instruction that does not check the class of the | 1526 // followed by a call instruction that does not check the class of the |
1545 // receiver. This enables a lot of optimizations because after the class | 1527 // receiver. This enables a lot of optimizations because after the class |
(...skipping 11 matching lines...) Expand all Loading... |
1557 // Type propagation has not run yet, we cannot eliminate the check. | 1539 // Type propagation has not run yet, we cannot eliminate the check. |
1558 // TODO(erikcorry): The receiver check should use the off-heap targets | 1540 // TODO(erikcorry): The receiver check should use the off-heap targets |
1559 // array, not the IC array. | 1541 // array, not the IC array. |
1560 AddReceiverCheck(instr); | 1542 AddReceiverCheck(instr); |
1561 // Call can still deoptimize, do not detach environment from instr. | 1543 // Call can still deoptimize, do not detach environment from instr. |
1562 call_with_checks = false; | 1544 call_with_checks = false; |
1563 } else { | 1545 } else { |
1564 call_with_checks = true; | 1546 call_with_checks = true; |
1565 } | 1547 } |
1566 PolymorphicInstanceCallInstr* call = | 1548 PolymorphicInstanceCallInstr* call = |
1567 new (Z) PolymorphicInstanceCallInstr(instr, *targets, call_with_checks, | 1549 new (Z) PolymorphicInstanceCallInstr(instr, targets, call_with_checks, |
1568 /* complete = */ false); | 1550 /* complete = */ false); |
1569 instr->ReplaceWith(call, current_iterator()); | 1551 instr->ReplaceWith(call, current_iterator()); |
1570 } | 1552 } |
1571 | 1553 |
1572 | 1554 |
1573 void JitOptimizer::VisitStaticCall(StaticCallInstr* call) { | 1555 void JitOptimizer::VisitStaticCall(StaticCallInstr* call) { |
1574 MethodRecognizer::Kind recognized_kind = | 1556 MethodRecognizer::Kind recognized_kind = |
1575 MethodRecognizer::RecognizeKind(call->function()); | 1557 MethodRecognizer::RecognizeKind(call->function()); |
1576 switch (recognized_kind) { | 1558 switch (recognized_kind) { |
1577 case MethodRecognizer::kObjectConstructor: | 1559 case MethodRecognizer::kObjectConstructor: |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1610 kDoubleCid)) { | 1592 kDoubleCid)) { |
1611 result_cid = kDoubleCid; | 1593 result_cid = kDoubleCid; |
1612 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, | 1594 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, |
1613 kSmiCid)) { | 1595 kSmiCid)) { |
1614 result_cid = kSmiCid; | 1596 result_cid = kSmiCid; |
1615 } | 1597 } |
1616 if (result_cid != kIllegalCid) { | 1598 if (result_cid != kIllegalCid) { |
1617 MathMinMaxInstr* min_max = new (Z) MathMinMaxInstr( | 1599 MathMinMaxInstr* min_max = new (Z) MathMinMaxInstr( |
1618 recognized_kind, new (Z) Value(call->ArgumentAt(0)), | 1600 recognized_kind, new (Z) Value(call->ArgumentAt(0)), |
1619 new (Z) Value(call->ArgumentAt(1)), call->deopt_id(), result_cid); | 1601 new (Z) Value(call->ArgumentAt(1)), call->deopt_id(), result_cid); |
1620 const ICData& unary_checks = | 1602 const CallTargets* targets = CallTargets::Create(Z, ic_data, 0); |
1621 ICData::ZoneHandle(Z, ic_data.AsUnaryClassChecks()); | 1603 AddCheckClass(min_max->left()->definition(), *targets, |
1622 AddCheckClass(min_max->left()->definition(), unary_checks, | |
1623 call->deopt_id(), call->env(), call); | 1604 call->deopt_id(), call->env(), call); |
1624 AddCheckClass(min_max->right()->definition(), unary_checks, | 1605 AddCheckClass(min_max->right()->definition(), *targets, |
1625 call->deopt_id(), call->env(), call); | 1606 call->deopt_id(), call->env(), call); |
1626 ReplaceCall(call, min_max); | 1607 ReplaceCall(call, min_max); |
1627 } | 1608 } |
1628 } | 1609 } |
1629 break; | 1610 break; |
1630 } | 1611 } |
1631 | 1612 |
1632 case MethodRecognizer::kDoubleFromInteger: { | 1613 case MethodRecognizer::kDoubleFromInteger: { |
1633 if (call->HasICData() && call->ic_data()->NumberOfChecksIs(1)) { | 1614 if (call->HasICData() && call->ic_data()->NumberOfChecksIs(1)) { |
1634 const ICData& ic_data = *call->ic_data(); | 1615 const ICData& ic_data = *call->ic_data(); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1813 // Discard the environment from the original instruction because the store | 1794 // Discard the environment from the original instruction because the store |
1814 // can't deoptimize. | 1795 // can't deoptimize. |
1815 instr->RemoveEnvironment(); | 1796 instr->RemoveEnvironment(); |
1816 ReplaceCall(instr, store); | 1797 ReplaceCall(instr, store); |
1817 return true; | 1798 return true; |
1818 } | 1799 } |
1819 | 1800 |
1820 | 1801 |
1821 } // namespace dart | 1802 } // namespace dart |
1822 #endif // DART_PRECOMPILED_RUNTIME | 1803 #endif // DART_PRECOMPILED_RUNTIME |
OLD | NEW |