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