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 1424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1435 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1435 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1436 summary->set_in(0, Location::RegisterLocation(RAX)); | 1436 summary->set_in(0, Location::RegisterLocation(RAX)); |
1437 summary->set_in(1, Location::RegisterLocation(RCX)); | 1437 summary->set_in(1, Location::RegisterLocation(RCX)); |
1438 summary->set_out(Location::SameAsFirstInput()); | 1438 summary->set_out(Location::SameAsFirstInput()); |
1439 summary->set_temp(0, Location::RegisterLocation(RBX)); | 1439 summary->set_temp(0, Location::RegisterLocation(RBX)); |
1440 // Will be used for for sign extension. | 1440 // Will be used for for sign extension. |
1441 summary->set_temp(1, Location::RegisterLocation(RDX)); | 1441 summary->set_temp(1, Location::RegisterLocation(RDX)); |
1442 summary->set_temp(2, Location::RequiresRegister()); | 1442 summary->set_temp(2, Location::RequiresRegister()); |
1443 return summary; | 1443 return summary; |
1444 } else if (op_kind() == Token::kSHR) { | 1444 } else if (op_kind() == Token::kSHR) { |
1445 const intptr_t kNumTemps = 1; | 1445 const intptr_t kNumTemps = 0; |
1446 LocationSummary* summary = | 1446 LocationSummary* summary = |
1447 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1447 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1448 summary->set_in(0, Location::RequiresRegister()); | 1448 summary->set_in(0, Location::RequiresRegister()); |
1449 summary->set_in(1, Location::RegisterLocation(RCX)); | 1449 summary->set_in(1, Location::RegisterLocation(RCX)); |
1450 summary->set_out(Location::SameAsFirstInput()); | 1450 summary->set_out(Location::SameAsFirstInput()); |
1451 summary->set_temp(0, Location::RequiresRegister()); | |
1452 return summary; | 1451 return summary; |
1453 } else if (op_kind() == Token::kSHL) { | 1452 } else if (op_kind() == Token::kSHL) { |
1454 // Two Smi operands can easily overflow into Mint. | 1453 // Two Smi operands can easily overflow into Mint. |
1455 const intptr_t kNumTemps = 2; | 1454 const intptr_t kNumTemps = 2; |
1456 LocationSummary* summary = | 1455 LocationSummary* summary = |
1457 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1456 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
1458 summary->set_in(0, Location::RegisterLocation(RAX)); | 1457 summary->set_in(0, Location::RegisterLocation(RAX)); |
1459 summary->set_in(1, Location::RegisterLocation(RDX)); | 1458 summary->set_in(1, Location::RegisterLocation(RDX)); |
1460 summary->set_out(Location::RegisterLocation(RAX)); | 1459 summary->set_out(Location::RegisterLocation(RAX)); |
1461 summary->set_temp(0, Location::RegisterLocation(RBX)); | 1460 summary->set_temp(0, Location::RegisterLocation(RBX)); |
1462 summary->set_temp(1, Location::RegisterLocation(RCX)); | 1461 summary->set_temp(1, Location::RegisterLocation(RCX)); |
1463 return summary; | 1462 return summary; |
1464 } else { | 1463 } else { |
1465 const intptr_t kNumTemps = 1; | 1464 const intptr_t kNumTemps = 0; |
1466 LocationSummary* summary = | 1465 LocationSummary* summary = |
1467 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1466 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1468 summary->set_in(0, Location::RequiresRegister()); | 1467 summary->set_in(0, Location::RequiresRegister()); |
1469 summary->set_in(1, Location::RequiresRegister()); | 1468 summary->set_in(1, Location::RequiresRegister()); |
1470 summary->set_out(Location::SameAsFirstInput()); | 1469 summary->set_out(Location::SameAsFirstInput()); |
1471 summary->set_temp(0, Location::RequiresRegister()); | |
1472 return summary; | 1470 return summary; |
1473 } | 1471 } |
1474 } | 1472 } |
1475 | 1473 |
1476 | 1474 |
1477 void BinarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1475 void BinarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1478 Register left = locs()->in(0).reg(); | 1476 Register left = locs()->in(0).reg(); |
1479 Register right = locs()->in(1).reg(); | 1477 Register right = locs()->in(1).reg(); |
1480 Register result = locs()->out().reg(); | 1478 Register result = locs()->out().reg(); |
1481 Register temp = locs()->temp(0).reg(); | |
1482 ASSERT(left == result); | 1479 ASSERT(left == result); |
1483 const bool left_is_smi = this->left()->ResultCid() == kSmiCid; | 1480 Label* deopt = NULL; |
1484 const bool right_is_smi = this->right()->ResultCid() == kSmiCid; | |
1485 bool can_deopt; | |
1486 switch (op_kind()) { | 1481 switch (op_kind()) { |
1487 case Token::kBIT_AND: | 1482 case Token::kBIT_AND: |
1488 case Token::kBIT_OR: | 1483 case Token::kBIT_OR: |
1489 case Token::kBIT_XOR: | 1484 case Token::kBIT_XOR: |
1490 can_deopt = !(right_is_smi && left_is_smi); | 1485 // Can't deoptimize. Arguments are already checked for smi. |
1491 break; | 1486 break; |
1492 default: | 1487 default: |
1493 can_deopt = true; | 1488 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1494 } | 1489 instance_call()->try_index(), |
1495 Label* deopt = NULL; | 1490 kDeoptBinarySmiOp); |
1496 if (can_deopt) { | |
1497 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | |
1498 instance_call()->try_index(), | |
1499 kDeoptBinarySmiOp); | |
1500 } | |
1501 if (!left_is_smi || !right_is_smi) { | |
1502 __ movq(temp, left); | |
1503 __ orq(temp, right); | |
1504 __ testq(temp, Immediate(kSmiTagMask)); | |
1505 __ j(NOT_ZERO, deopt); | |
1506 } | 1491 } |
1507 switch (op_kind()) { | 1492 switch (op_kind()) { |
1508 case Token::kADD: { | 1493 case Token::kADD: { |
1509 __ addq(left, right); | 1494 __ addq(left, right); |
1510 __ j(OVERFLOW, deopt); | 1495 __ j(OVERFLOW, deopt); |
1511 break; | 1496 break; |
1512 } | 1497 } |
1513 case Token::kSUB: { | 1498 case Token::kSUB: { |
1514 __ subq(left, right); | 1499 __ subq(left, right); |
1515 __ j(OVERFLOW, deopt); | 1500 __ j(OVERFLOW, deopt); |
(...skipping 14 matching lines...) Expand all Loading... |
1530 // No overflow check. | 1515 // No overflow check. |
1531 __ orq(left, right); | 1516 __ orq(left, right); |
1532 break; | 1517 break; |
1533 } | 1518 } |
1534 case Token::kBIT_XOR: { | 1519 case Token::kBIT_XOR: { |
1535 // No overflow check. | 1520 // No overflow check. |
1536 __ xorq(left, right); | 1521 __ xorq(left, right); |
1537 break; | 1522 break; |
1538 } | 1523 } |
1539 case Token::kTRUNCDIV: { | 1524 case Token::kTRUNCDIV: { |
| 1525 Register temp = locs()->temp(0).reg(); |
1540 // Handle divide by zero in runtime. | 1526 // Handle divide by zero in runtime. |
1541 // Deoptimization requires that temp and right are preserved. | 1527 // Deoptimization requires that temp and right are preserved. |
1542 __ testq(right, right); | 1528 __ testq(right, right); |
1543 __ j(ZERO, deopt); | 1529 __ j(ZERO, deopt); |
1544 ASSERT(left == RAX); | 1530 ASSERT(left == RAX); |
1545 ASSERT((right != RDX) && (right != RAX)); | 1531 ASSERT((right != RDX) && (right != RAX)); |
1546 ASSERT((temp != RDX) && (temp != RAX)); | 1532 ASSERT((temp != RDX) && (temp != RAX)); |
1547 ASSERT(locs()->temp(1).reg() == RDX); | 1533 ASSERT(locs()->temp(1).reg() == RDX); |
1548 ASSERT(result == RAX); | 1534 ASSERT(result == RAX); |
1549 Register right_temp = locs()->temp(2).reg(); | 1535 Register right_temp = locs()->temp(2).reg(); |
(...skipping 20 matching lines...) Expand all Loading... |
1570 __ j(LESS, &count_ok, Assembler::kNearJump); | 1556 __ j(LESS, &count_ok, Assembler::kNearJump); |
1571 __ movq(right, kCountLimit); | 1557 __ movq(right, kCountLimit); |
1572 __ Bind(&count_ok); | 1558 __ Bind(&count_ok); |
1573 ASSERT(right == RCX); // Count must be in RCX | 1559 ASSERT(right == RCX); // Count must be in RCX |
1574 __ SmiUntag(left); | 1560 __ SmiUntag(left); |
1575 __ sarq(left, right); | 1561 __ sarq(left, right); |
1576 __ SmiTag(left); | 1562 __ SmiTag(left); |
1577 break; | 1563 break; |
1578 } | 1564 } |
1579 case Token::kSHL: { | 1565 case Token::kSHL: { |
| 1566 Register temp = locs()->temp(0).reg(); |
1580 Label call_method, done; | 1567 Label call_method, done; |
1581 // Check if count too large for handling it inlined. | 1568 // Check if count too large for handling it inlined. |
1582 __ movq(temp, left); | 1569 __ movq(temp, left); |
1583 __ cmpq(right, | 1570 __ cmpq(right, |
1584 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); | 1571 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); |
1585 __ j(ABOVE_EQUAL, &call_method, Assembler::kNearJump); | 1572 __ j(ABOVE_EQUAL, &call_method, Assembler::kNearJump); |
1586 Register right_temp = locs()->temp(1).reg(); | 1573 Register right_temp = locs()->temp(1).reg(); |
1587 ASSERT(right_temp == RCX); // Count must be in RCX | 1574 ASSERT(right_temp == RCX); // Count must be in RCX |
1588 __ movq(right_temp, right); | 1575 __ movq(right_temp, right); |
1589 __ SmiUntag(right_temp); | 1576 __ SmiUntag(right_temp); |
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2198 if (use_near_jump) { | 2185 if (use_near_jump) { |
2199 __ j(EQUAL, &is_ok, Assembler::kNearJump); | 2186 __ j(EQUAL, &is_ok, Assembler::kNearJump); |
2200 } else { | 2187 } else { |
2201 __ j(EQUAL, &is_ok); | 2188 __ j(EQUAL, &is_ok); |
2202 } | 2189 } |
2203 } | 2190 } |
2204 } | 2191 } |
2205 __ Bind(&is_ok); | 2192 __ Bind(&is_ok); |
2206 } | 2193 } |
2207 | 2194 |
| 2195 |
| 2196 LocationSummary* CheckSmiComp::MakeLocationSummary() const { |
| 2197 const intptr_t kNumInputs = 1; |
| 2198 const intptr_t kNumTemps = 0; |
| 2199 LocationSummary* summary = |
| 2200 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2201 summary->set_in(0, Location::RequiresRegister()); |
| 2202 return summary; |
| 2203 } |
| 2204 |
| 2205 |
| 2206 void CheckSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2207 Register value = locs()->in(0).reg(); |
| 2208 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2209 try_index(), |
| 2210 kDeoptCheckSmi); |
| 2211 __ testq(value, Immediate(kSmiTagMask)); |
| 2212 __ j(NOT_ZERO, deopt); |
| 2213 } |
| 2214 |
| 2215 |
2208 } // namespace dart | 2216 } // namespace dart |
2209 | 2217 |
2210 #undef __ | 2218 #undef __ |
2211 | 2219 |
2212 #endif // defined TARGET_ARCH_X64 | 2220 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |