Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 } | 375 } |
| 376 __ jmp(&done); | 376 __ jmp(&done); |
| 377 __ Bind(&next_test); | 377 __ Bind(&next_test); |
| 378 } | 378 } |
| 379 // Fall through leads to deoptimization | 379 // Fall through leads to deoptimization |
| 380 __ jmp(deopt); | 380 __ jmp(deopt); |
| 381 __ Bind(&done); | 381 __ Bind(&done); |
| 382 } | 382 } |
| 383 | 383 |
| 384 | 384 |
| 385 | |
| 386 // First test if receiver is NULL, in which case === is applied. | 385 // First test if receiver is NULL, in which case === is applied. |
| 387 // If type feedback was provided (lists of <class-id, target>), do a | 386 // If type feedback was provided (lists of <class-id, target>), do a |
| 388 // type by type check (either === or static call to the operator. | 387 // type by type check (either === or static call to the operator. |
| 389 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 388 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
| 390 EqualityCompareComp* comp) { | 389 EqualityCompareComp* comp) { |
| 391 const Immediate raw_null = | 390 const Immediate raw_null = |
| 392 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 391 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 393 Register left = comp->locs()->in(0).reg(); | 392 Register left = comp->locs()->in(0).reg(); |
| 394 Register right = comp->locs()->in(1).reg(); | 393 Register right = comp->locs()->in(1).reg(); |
| 395 Label done, non_null_compare; | 394 Label done, non_null_compare; |
| (...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1496 UNREACHABLE(); | 1495 UNREACHABLE(); |
| 1497 break; | 1496 break; |
| 1498 } | 1497 } |
| 1499 default: | 1498 default: |
| 1500 UNREACHABLE(); | 1499 UNREACHABLE(); |
| 1501 break; | 1500 break; |
| 1502 } | 1501 } |
| 1503 } | 1502 } |
| 1504 | 1503 |
| 1505 | 1504 |
| 1505 static RawFunction* GetTargetForReceiverClassId(const ICData& ic_data, | |
| 1506 intptr_t receiver_class_id) { | |
|
srdjan
2012/06/21 16:02:37
I could imagine that this could also live inside c
regis
2012/06/21 18:26:42
Good point. Done.
| |
| 1507 Function& target = Function::Handle(); | |
| 1508 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | |
| 1509 GrowableArray<intptr_t> class_ids; | |
| 1510 ic_data.GetCheckAt(i, &class_ids, &target); | |
| 1511 if (class_ids[0] == receiver_class_id) { | |
| 1512 return target.raw(); | |
| 1513 } | |
| 1514 } | |
| 1515 UNREACHABLE(); | |
| 1516 return Function::null(); | |
| 1517 } | |
| 1518 | |
| 1519 | |
| 1506 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1520 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
| 1507 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1521 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
| 1508 // receiver and a Smi argument. | 1522 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1523 // both receiver and argument are Mint or if one of them is Mint and the other | |
| 1524 // is a negative Smi. | |
| 1509 Register left = comp->locs()->in(0).reg(); | 1525 Register left = comp->locs()->in(0).reg(); |
| 1510 Register right = comp->locs()->in(1).reg(); | 1526 Register right = comp->locs()->in(1).reg(); |
| 1511 Register result = comp->locs()->out().reg(); | 1527 Register result = comp->locs()->out().reg(); |
| 1512 Register temp = comp->locs()->temp(0).reg(); | 1528 Register temp = comp->locs()->temp(0).reg(); |
| 1513 ASSERT(left == result); | 1529 ASSERT(left == result); |
| 1530 ASSERT(comp->op_kind() == Token::kBIT_AND); | |
| 1514 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1531 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
| 1515 comp->instance_call()->token_index(), | 1532 comp->instance_call()->token_index(), |
| 1516 comp->instance_call()->try_index(), | 1533 comp->instance_call()->try_index(), |
| 1517 kDeoptMintBinaryOp, | 1534 kDeoptMintBinaryOp, |
| 1518 temp, | 1535 temp, |
| 1519 right); | 1536 right); |
| 1520 __ testq(right, Immediate(kSmiTagMask)); // Argument must be Smi. | 1537 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1521 __ j(NOT_ZERO, deopt); | 1538 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1522 __ testq(left, Immediate(kSmiTagMask)); // Receiver can be Smi. | 1539 __ j(NOT_ZERO, &non_smi); |
| 1523 Label two_smi; | 1540 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1524 __ j(ZERO, &two_smi); | 1541 __ j(ZERO, &smi_smi); |
| 1525 __ CompareClassId(left, kMint); // Receiver must be Mint. | 1542 __ CompareClassId(right, kMint); // Is argument Mint? |
| 1526 __ j(NOT_EQUAL, deopt); | 1543 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. |
| 1544 __ cmpq(left, Immediate(0)); | |
| 1545 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. | |
| 1527 | 1546 |
| 1528 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1547 // Positive Smi receiver, Mint argument. |
| 1548 // Load lower argument Mint word, convert to Smi. It is OK to loose bits. | |
| 1549 __ movq(right, FieldAddress(right, Mint::value_offset())); | |
| 1550 __ SmiTag(right); | |
| 1551 __ andq(result, right); | |
| 1552 __ jmp(&done); | |
| 1529 | 1553 |
| 1530 // Load lower Mint word, convert to Smi. It is OK to loose bits. | 1554 __ Bind(&non_smi); // Receiver is non-Smi. |
| 1531 ASSERT(result == left); | 1555 __ CompareClassId(left, kMint); // Is receiver Mint? |
| 1556 __ j(NOT_EQUAL, deopt); // Receiver neither Smi nor Mint. | |
| 1557 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? | |
| 1558 __ j(NOT_ZERO, &mint_static_call); // Mint receiver, non-Smi argument. | |
| 1559 __ cmpq(right, Immediate(0)); | |
| 1560 __ j(LESS, &mint_static_call); // Mint receiver, negative Smi argument. | |
| 1561 | |
| 1562 // Mint receiver, positive Smi argument. | |
| 1563 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. | |
| 1532 __ movq(result, FieldAddress(left, Mint::value_offset())); | 1564 __ movq(result, FieldAddress(left, Mint::value_offset())); |
| 1533 __ SmiTag(result); | 1565 __ SmiTag(result); |
| 1534 __ Bind(&two_smi); | 1566 __ Bind(&smi_smi); |
| 1535 __ andq(result, right); | 1567 __ andq(result, right); |
| 1568 __ jmp(&done); | |
| 1569 | |
| 1570 __ Bind(&smi_static_call); | |
| 1571 { | |
| 1572 Function& target = Function::ZoneHandle( | |
| 1573 GetTargetForReceiverClassId(*comp->ic_data(), kSmi)); | |
| 1574 compiler->GenerateStaticCall(comp->instance_call()->cid(), | |
| 1575 comp->instance_call()->token_index(), | |
| 1576 comp->instance_call()->try_index(), | |
| 1577 target, | |
| 1578 comp->instance_call()->ArgumentCount(), | |
| 1579 comp->instance_call()->argument_names()); | |
| 1580 } | |
| 1581 __ jmp(&done); | |
| 1582 | |
| 1583 __ Bind(&mint_static_call); | |
| 1584 { | |
| 1585 Function& target = Function::ZoneHandle( | |
| 1586 GetTargetForReceiverClassId(*comp->ic_data(), kMint)); | |
| 1587 compiler->GenerateStaticCall(comp->instance_call()->cid(), | |
| 1588 comp->instance_call()->token_index(), | |
| 1589 comp->instance_call()->try_index(), | |
| 1590 target, | |
| 1591 comp->instance_call()->ArgumentCount(), | |
| 1592 comp->instance_call()->argument_names()); | |
| 1593 } | |
| 1594 __ Bind(&done); | |
| 1536 } | 1595 } |
| 1537 | 1596 |
| 1538 | 1597 |
| 1539 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, | 1598 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, |
| 1540 BinaryOpComp* comp) { | 1599 BinaryOpComp* comp) { |
| 1541 Register left = RBX; | 1600 Register left = RBX; |
| 1542 Register right = RCX; | 1601 Register right = RCX; |
| 1543 Register temp = RDX; | 1602 Register temp = RDX; |
| 1544 Register result = comp->locs()->out().reg(); | 1603 Register result = comp->locs()->out().reg(); |
| 1545 | 1604 |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1817 instance_call()->argument_names()); | 1876 instance_call()->argument_names()); |
| 1818 } | 1877 } |
| 1819 __ Bind(&done); | 1878 __ Bind(&done); |
| 1820 } | 1879 } |
| 1821 | 1880 |
| 1822 } // namespace dart | 1881 } // namespace dart |
| 1823 | 1882 |
| 1824 #undef __ | 1883 #undef __ |
| 1825 | 1884 |
| 1826 #endif // defined TARGET_ARCH_X64 | 1885 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |