| 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 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 __ Bind(&is_false); | 545 __ Bind(&is_false); |
| 546 __ LoadObject(result, compiler->bool_false()); | 546 __ LoadObject(result, compiler->bool_false()); |
| 547 __ jmp(&done); | 547 __ jmp(&done); |
| 548 __ Bind(&is_true); | 548 __ Bind(&is_true); |
| 549 __ LoadObject(result, compiler->bool_true()); | 549 __ LoadObject(result, compiler->bool_true()); |
| 550 __ Bind(&done); | 550 __ Bind(&done); |
| 551 } | 551 } |
| 552 } | 552 } |
| 553 | 553 |
| 554 | 554 |
| 555 | |
| 556 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 555 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 557 if (operands_class_id() == kSmi) { | 556 if (operands_class_id() == kSmi) { |
| 558 EmitSmiRelationalOp(compiler, this); | 557 EmitSmiRelationalOp(compiler, this); |
| 559 return; | 558 return; |
| 560 } | 559 } |
| 561 if (operands_class_id() == kDouble) { | 560 if (operands_class_id() == kDouble) { |
| 562 EmitDoubleRelationalOp(compiler, this); | 561 EmitDoubleRelationalOp(compiler, this); |
| 563 return; | 562 return; |
| 564 } | 563 } |
| 565 const String& function_name = | 564 const String& function_name = |
| (...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1370 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1369 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
| 1371 const intptr_t kNumInputs = 2; | 1370 const intptr_t kNumInputs = 2; |
| 1372 | 1371 |
| 1373 if (operands_type() == kDoubleOperands) { | 1372 if (operands_type() == kDoubleOperands) { |
| 1374 return MakeCallSummary(); // Calls into a stub for allocation. | 1373 return MakeCallSummary(); // Calls into a stub for allocation. |
| 1375 } | 1374 } |
| 1376 | 1375 |
| 1377 if (operands_type() == kMintOperands) { | 1376 if (operands_type() == kMintOperands) { |
| 1378 ASSERT(op_kind() == Token::kBIT_AND); | 1377 ASSERT(op_kind() == Token::kBIT_AND); |
| 1379 const intptr_t kNumTemps = 1; | 1378 const intptr_t kNumTemps = 1; |
| 1380 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 1379 LocationSummary* summary = |
| 1381 summary->set_in(0, Location::RequiresRegister()); | 1380 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1381 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 1382 summary->set_in(1, Location::RequiresRegister()); | 1382 summary->set_in(1, Location::RequiresRegister()); |
| 1383 summary->set_out(Location::SameAsFirstInput()); | 1383 summary->set_out(Location::SameAsFirstInput()); |
| 1384 summary->set_temp(0, Location::RequiresRegister()); | 1384 summary->set_temp(0, Location::RequiresRegister()); |
| 1385 return summary; | 1385 return summary; |
| 1386 } | 1386 } |
| 1387 | 1387 |
| 1388 ASSERT(operands_type() == kSmiOperands); | 1388 ASSERT(operands_type() == kSmiOperands); |
| 1389 | 1389 |
| 1390 if (op_kind() == Token::kTRUNCDIV) { | 1390 if (op_kind() == Token::kTRUNCDIV) { |
| 1391 const intptr_t kNumTemps = 3; | 1391 const intptr_t kNumTemps = 3; |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1556 } | 1556 } |
| 1557 default: | 1557 default: |
| 1558 UNREACHABLE(); | 1558 UNREACHABLE(); |
| 1559 break; | 1559 break; |
| 1560 } | 1560 } |
| 1561 } | 1561 } |
| 1562 | 1562 |
| 1563 | 1563 |
| 1564 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1564 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
| 1565 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1565 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
| 1566 // receiver and a Smi argument. | 1566 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1567 // both receiver and argument are Mint or if one of them is Mint and the other |
| 1568 // is a negative Smi. |
| 1567 Register left = comp->locs()->in(0).reg(); | 1569 Register left = comp->locs()->in(0).reg(); |
| 1568 Register right = comp->locs()->in(1).reg(); | 1570 Register right = comp->locs()->in(1).reg(); |
| 1569 Register result = comp->locs()->out().reg(); | 1571 Register result = comp->locs()->out().reg(); |
| 1570 Register temp = comp->locs()->temp(0).reg(); | 1572 Register temp = comp->locs()->temp(0).reg(); |
| 1571 ASSERT(left == result); | 1573 ASSERT(left == result); |
| 1574 ASSERT(comp->op_kind() == Token::kBIT_AND); |
| 1572 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1575 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
| 1573 comp->instance_call()->token_index(), | 1576 comp->instance_call()->token_index(), |
| 1574 comp->instance_call()->try_index(), | 1577 comp->instance_call()->try_index(), |
| 1575 kDeoptMintBinaryOp, | 1578 kDeoptMintBinaryOp, |
| 1576 temp, | 1579 left, |
| 1577 right); | 1580 right); |
| 1578 __ testl(right, Immediate(kSmiTagMask)); // Argument must be Smi. | 1581 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1579 __ j(NOT_ZERO, deopt); | 1582 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1580 __ testl(left, Immediate(kSmiTagMask)); // Receiver can be Smi. | 1583 __ j(NOT_ZERO, &non_smi); |
| 1581 Label two_smi; | 1584 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1582 __ j(ZERO, &two_smi); | 1585 __ j(ZERO, &smi_smi); |
| 1583 __ CompareClassId(left, kMint, temp); // Receiver must be Mint. | 1586 __ CompareClassId(right, kMint, temp); // Is argument Mint? |
| 1584 __ j(NOT_EQUAL, deopt); | 1587 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. |
| 1588 __ cmpl(left, Immediate(0)); |
| 1589 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. |
| 1585 | 1590 |
| 1586 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1591 // Positive Smi receiver, Mint argument. |
| 1592 // Load lower argument Mint word, convert to Smi. It is OK to loose bits. |
| 1593 __ movl(right, FieldAddress(right, Mint::value_offset())); |
| 1594 __ SmiTag(right); |
| 1595 __ andl(result, right); |
| 1596 __ jmp(&done); |
| 1587 | 1597 |
| 1588 // Load lower Mint word, convert to Smi. It is OK to loose bits. | 1598 __ Bind(&non_smi); // Receiver is non-Smi. |
| 1589 ASSERT(result == left); | 1599 __ CompareClassId(left, kMint, temp); // Is receiver Mint? |
| 1600 __ j(NOT_EQUAL, deopt); // Receiver neither Smi nor Mint. |
| 1601 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1602 __ j(NOT_ZERO, &mint_static_call); // Mint receiver, non-Smi argument. |
| 1603 __ cmpl(right, Immediate(0)); |
| 1604 __ j(LESS, &mint_static_call); // Mint receiver, negative Smi argument. |
| 1605 |
| 1606 // Mint receiver, positive Smi argument. |
| 1607 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. |
| 1590 __ movl(result, FieldAddress(left, Mint::value_offset())); | 1608 __ movl(result, FieldAddress(left, Mint::value_offset())); |
| 1591 __ SmiTag(result); | 1609 __ SmiTag(result); |
| 1592 __ Bind(&two_smi); | 1610 __ Bind(&smi_smi); |
| 1593 __ andl(result, right); | 1611 __ andl(result, right); |
| 1612 __ jmp(&done); |
| 1613 |
| 1614 __ Bind(&smi_static_call); |
| 1615 { |
| 1616 Function& target = Function::ZoneHandle( |
| 1617 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
| 1618 if (target.IsNull()) { |
| 1619 __ jmp(deopt); |
| 1620 } else { |
| 1621 __ pushl(left); |
| 1622 __ pushl(right); |
| 1623 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| 1624 comp->instance_call()->token_index(), |
| 1625 comp->instance_call()->try_index(), |
| 1626 target, |
| 1627 comp->instance_call()->ArgumentCount(), |
| 1628 comp->instance_call()->argument_names()); |
| 1629 ASSERT(result == EAX); |
| 1630 __ jmp(&done); |
| 1631 } |
| 1632 } |
| 1633 |
| 1634 __ Bind(&mint_static_call); |
| 1635 { |
| 1636 Function& target = Function::ZoneHandle( |
| 1637 comp->ic_data()->GetTargetForReceiverClassId(kMint)); |
| 1638 if (target.IsNull()) { |
| 1639 __ jmp(deopt); |
| 1640 } else { |
| 1641 __ pushl(left); |
| 1642 __ pushl(right); |
| 1643 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| 1644 comp->instance_call()->token_index(), |
| 1645 comp->instance_call()->try_index(), |
| 1646 target, |
| 1647 comp->instance_call()->ArgumentCount(), |
| 1648 comp->instance_call()->argument_names()); |
| 1649 ASSERT(result == EAX); |
| 1650 } |
| 1651 } |
| 1652 __ Bind(&done); |
| 1594 } | 1653 } |
| 1595 | 1654 |
| 1596 | 1655 |
| 1597 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, | 1656 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, |
| 1598 BinaryOpComp* comp) { | 1657 BinaryOpComp* comp) { |
| 1599 Register left = EBX; | 1658 Register left = EBX; |
| 1600 Register right = ECX; | 1659 Register right = ECX; |
| 1601 Register temp = EDX; | 1660 Register temp = EDX; |
| 1602 Register result = comp->locs()->out().reg(); | 1661 Register result = comp->locs()->out().reg(); |
| 1603 | 1662 |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1871 compiler->GenerateStaticCall(instance_call()->cid(), | 1930 compiler->GenerateStaticCall(instance_call()->cid(), |
| 1872 instance_call()->token_index(), | 1931 instance_call()->token_index(), |
| 1873 instance_call()->try_index(), | 1932 instance_call()->try_index(), |
| 1874 target, | 1933 target, |
| 1875 instance_call()->ArgumentCount(), | 1934 instance_call()->ArgumentCount(), |
| 1876 instance_call()->argument_names()); | 1935 instance_call()->argument_names()); |
| 1877 } | 1936 } |
| 1878 __ Bind(&done); | 1937 __ Bind(&done); |
| 1879 } | 1938 } |
| 1880 | 1939 |
| 1881 | |
| 1882 } // namespace dart | 1940 } // namespace dart |
| 1883 | 1941 |
| 1884 #undef __ | 1942 #undef __ |
| 1885 | 1943 |
| 1886 #endif // defined TARGET_ARCH_X64 | 1944 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |