| 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 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 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 __ Bind(&is_false); | 544 __ Bind(&is_false); |
| 545 __ LoadObject(result, compiler->bool_false()); | 545 __ LoadObject(result, compiler->bool_false()); |
| 546 __ jmp(&done); | 546 __ jmp(&done); |
| 547 __ Bind(&is_true); | 547 __ Bind(&is_true); |
| 548 __ LoadObject(result, compiler->bool_true()); | 548 __ LoadObject(result, compiler->bool_true()); |
| 549 __ Bind(&done); | 549 __ Bind(&done); |
| 550 } | 550 } |
| 551 } | 551 } |
| 552 | 552 |
| 553 | 553 |
| 554 | |
| 555 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 554 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 556 if (operands_class_id() == kSmi) { | 555 if (operands_class_id() == kSmi) { |
| 557 EmitSmiRelationalOp(compiler, this); | 556 EmitSmiRelationalOp(compiler, this); |
| 558 return; | 557 return; |
| 559 } | 558 } |
| 560 if (operands_class_id() == kDouble) { | 559 if (operands_class_id() == kDouble) { |
| 561 EmitDoubleRelationalOp(compiler, this); | 560 EmitDoubleRelationalOp(compiler, this); |
| 562 return; | 561 return; |
| 563 } | 562 } |
| 564 const String& function_name = | 563 const String& function_name = |
| (...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1479 UNREACHABLE(); | 1478 UNREACHABLE(); |
| 1480 break; | 1479 break; |
| 1481 } | 1480 } |
| 1482 default: | 1481 default: |
| 1483 UNREACHABLE(); | 1482 UNREACHABLE(); |
| 1484 break; | 1483 break; |
| 1485 } | 1484 } |
| 1486 } | 1485 } |
| 1487 | 1486 |
| 1488 | 1487 |
| 1488 static RawFunction* GetTargetForReceiverClassId(const ICData& ic_data, |
| 1489 intptr_t receiver_class_id) { |
| 1490 Function& target = Function::Handle(); |
| 1491 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 1492 GrowableArray<intptr_t> class_ids; |
| 1493 ic_data.GetCheckAt(i, &class_ids, &target); |
| 1494 if (class_ids[0] == receiver_class_id) { |
| 1495 return target.raw(); |
| 1496 } |
| 1497 } |
| 1498 UNREACHABLE(); |
| 1499 return Function::null(); |
| 1500 } |
| 1501 |
| 1502 |
| 1489 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1503 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
| 1490 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1504 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
| 1491 // receiver and a Smi argument. | 1505 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1506 // both receiver and argument are Mint or if one of them is Mint and the other |
| 1507 // is a negative Smi. |
| 1492 Register left = comp->locs()->in(0).reg(); | 1508 Register left = comp->locs()->in(0).reg(); |
| 1493 Register right = comp->locs()->in(1).reg(); | 1509 Register right = comp->locs()->in(1).reg(); |
| 1494 Register result = comp->locs()->out().reg(); | 1510 Register result = comp->locs()->out().reg(); |
| 1495 Register temp = comp->locs()->temp(0).reg(); | 1511 Register temp = comp->locs()->temp(0).reg(); |
| 1496 ASSERT(left == result); | 1512 ASSERT(left == result); |
| 1513 ASSERT(comp->op_kind() == Token::kBIT_AND); |
| 1497 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1514 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
| 1498 comp->instance_call()->token_index(), | 1515 comp->instance_call()->token_index(), |
| 1499 comp->instance_call()->try_index(), | 1516 comp->instance_call()->try_index(), |
| 1500 kDeoptMintBinaryOp, | 1517 kDeoptMintBinaryOp, |
| 1501 temp, | 1518 temp, |
| 1502 right); | 1519 right); |
| 1503 __ testl(right, Immediate(kSmiTagMask)); // Argument must be Smi. | 1520 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1504 __ j(NOT_ZERO, deopt); | 1521 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1505 __ testl(left, Immediate(kSmiTagMask)); // Receiver can be Smi. | 1522 __ j(NOT_ZERO, &non_smi); |
| 1506 Label two_smi; | 1523 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1507 __ j(ZERO, &two_smi); | 1524 __ j(ZERO, &smi_smi); |
| 1508 __ CompareClassId(left, kMint, temp); // Receiver must be Mint. | 1525 __ CompareClassId(right, kMint, temp); // Is argument Mint? |
| 1509 __ j(NOT_EQUAL, deopt); | 1526 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. |
| 1527 __ cmpl(left, Immediate(0)); |
| 1528 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. |
| 1510 | 1529 |
| 1511 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1530 // Positive Smi receiver, Mint argument. |
| 1531 // Load lower argument Mint word, convert to Smi. It is OK to loose bits. |
| 1532 __ movl(right, FieldAddress(right, Mint::value_offset())); |
| 1533 __ SmiTag(right); |
| 1534 __ andl(result, right); |
| 1535 __ jmp(&done); |
| 1512 | 1536 |
| 1513 // Load lower Mint word, convert to Smi. It is OK to loose bits. | 1537 __ Bind(&non_smi); // Receiver is non-Smi. |
| 1514 ASSERT(result == left); | 1538 __ CompareClassId(left, kMint, temp); // Is receiver Mint? |
| 1539 __ j(NOT_EQUAL, deopt); // Receiver neither Smi nor Mint. |
| 1540 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1541 __ j(NOT_ZERO, &mint_static_call); // Mint receiver, non-Smi argument. |
| 1542 __ cmpl(right, Immediate(0)); |
| 1543 __ j(LESS, &mint_static_call); // Mint receiver, negative Smi argument. |
| 1544 |
| 1545 // Mint receiver, positive Smi argument. |
| 1546 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. |
| 1515 __ movl(result, FieldAddress(left, Mint::value_offset())); | 1547 __ movl(result, FieldAddress(left, Mint::value_offset())); |
| 1516 __ SmiTag(result); | 1548 __ SmiTag(result); |
| 1517 __ Bind(&two_smi); | 1549 __ Bind(&smi_smi); |
| 1518 __ andl(result, right); | 1550 __ andl(result, right); |
| 1551 __ jmp(&done); |
| 1552 |
| 1553 __ Bind(&smi_static_call); |
| 1554 { |
| 1555 Function& target = Function::ZoneHandle( |
| 1556 GetTargetForReceiverClassId(*comp->ic_data(), kSmi)); |
| 1557 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| 1558 comp->instance_call()->token_index(), |
| 1559 comp->instance_call()->try_index(), |
| 1560 target, |
| 1561 comp->instance_call()->ArgumentCount(), |
| 1562 comp->instance_call()->argument_names()); |
| 1563 } |
| 1564 __ jmp(&done); |
| 1565 |
| 1566 __ Bind(&mint_static_call); |
| 1567 { |
| 1568 Function& target = Function::ZoneHandle( |
| 1569 GetTargetForReceiverClassId(*comp->ic_data(), kMint)); |
| 1570 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| 1571 comp->instance_call()->token_index(), |
| 1572 comp->instance_call()->try_index(), |
| 1573 target, |
| 1574 comp->instance_call()->ArgumentCount(), |
| 1575 comp->instance_call()->argument_names()); |
| 1576 } |
| 1577 __ Bind(&done); |
| 1519 } | 1578 } |
| 1520 | 1579 |
| 1521 | 1580 |
| 1522 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, | 1581 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, |
| 1523 BinaryOpComp* comp) { | 1582 BinaryOpComp* comp) { |
| 1524 Register left = EBX; | 1583 Register left = EBX; |
| 1525 Register right = ECX; | 1584 Register right = ECX; |
| 1526 Register temp = EDX; | 1585 Register temp = EDX; |
| 1527 Register result = comp->locs()->out().reg(); | 1586 Register result = comp->locs()->out().reg(); |
| 1528 | 1587 |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1799 compiler->GenerateStaticCall(instance_call()->cid(), | 1858 compiler->GenerateStaticCall(instance_call()->cid(), |
| 1800 instance_call()->token_index(), | 1859 instance_call()->token_index(), |
| 1801 instance_call()->try_index(), | 1860 instance_call()->try_index(), |
| 1802 target, | 1861 target, |
| 1803 instance_call()->ArgumentCount(), | 1862 instance_call()->ArgumentCount(), |
| 1804 instance_call()->argument_names()); | 1863 instance_call()->argument_names()); |
| 1805 } | 1864 } |
| 1806 __ Bind(&done); | 1865 __ Bind(&done); |
| 1807 } | 1866 } |
| 1808 | 1867 |
| 1809 | |
| 1810 } // namespace dart | 1868 } // namespace dart |
| 1811 | 1869 |
| 1812 #undef __ | 1870 #undef __ |
| 1813 | 1871 |
| 1814 #endif // defined TARGET_ARCH_X64 | 1872 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |