| 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 |