| 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 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 | 167 |
| 168 | 168 |
| 169 LocationSummary* ConstantComp::MakeLocationSummary() const { | 169 LocationSummary* ConstantComp::MakeLocationSummary() const { |
| 170 return LocationSummary::Make(0, | 170 return LocationSummary::Make(0, |
| 171 Location::RequiresRegister(), | 171 Location::RequiresRegister(), |
| 172 LocationSummary::kNoCall); | 172 LocationSummary::kNoCall); |
| 173 } | 173 } |
| 174 | 174 |
| 175 | 175 |
| 176 void ConstantComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 176 void ConstantComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 177 Register result = locs()->out().reg(); | 177 // Register allocator drops constant definitions that have no uses. |
| 178 __ LoadObject(result, value()); | 178 if (!locs()->out().IsInvalid()) { |
| 179 Register result = locs()->out().reg(); |
| 180 __ LoadObject(result, value()); |
| 181 } |
| 179 } | 182 } |
| 180 | 183 |
| 181 | 184 |
| 182 LocationSummary* AssertAssignableComp::MakeLocationSummary() const { | 185 LocationSummary* AssertAssignableComp::MakeLocationSummary() const { |
| 183 const intptr_t kNumInputs = 3; | 186 const intptr_t kNumInputs = 3; |
| 184 const intptr_t kNumTemps = 0; | 187 const intptr_t kNumTemps = 0; |
| 185 LocationSummary* summary = | 188 LocationSummary* summary = |
| 186 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 189 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 187 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. | 190 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. |
| 188 summary->set_in(1, Location::RegisterLocation(RCX)); // Instantiator. | 191 summary->set_in(1, Location::RegisterLocation(RCX)); // Instantiator. |
| (...skipping 1253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1442 | 1445 |
| 1443 Register temp = locs()->temp(0).reg(); | 1446 Register temp = locs()->temp(0).reg(); |
| 1444 // Generate stack overflow check. | 1447 // Generate stack overflow check. |
| 1445 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); | 1448 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); |
| 1446 __ cmpq(RSP, Address(temp, 0)); | 1449 __ cmpq(RSP, Address(temp, 0)); |
| 1447 __ j(BELOW_EQUAL, slow_path->entry_label()); | 1450 __ j(BELOW_EQUAL, slow_path->entry_label()); |
| 1448 __ Bind(slow_path->exit_label()); | 1451 __ Bind(slow_path->exit_label()); |
| 1449 } | 1452 } |
| 1450 | 1453 |
| 1451 | 1454 |
| 1455 static bool CanBeImmediate(const Object& constant) { |
| 1456 return constant.IsSmi() && |
| 1457 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); |
| 1458 } |
| 1459 |
| 1452 LocationSummary* BinarySmiOpComp::MakeLocationSummary() const { | 1460 LocationSummary* BinarySmiOpComp::MakeLocationSummary() const { |
| 1453 const intptr_t kNumInputs = 2; | 1461 const intptr_t kNumInputs = 2; |
| 1462 |
| 1463 ConstantComp* right_constant = right()->definition()->AsConstant(); |
| 1464 if ((right_constant != NULL) && |
| 1465 (op_kind() != Token::kTRUNCDIV) && |
| 1466 (op_kind() != Token::kSHL) && |
| 1467 (op_kind() != Token::kMUL) && |
| 1468 CanBeImmediate(right_constant->value())) { |
| 1469 const intptr_t kNumTemps = 0; |
| 1470 LocationSummary* summary = |
| 1471 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1472 summary->set_in(0, Location::RequiresRegister()); |
| 1473 summary->set_in(1, Location::Constant(right_constant->value())); |
| 1474 summary->set_out(Location::SameAsFirstInput()); |
| 1475 return summary; |
| 1476 } |
| 1477 |
| 1454 if (op_kind() == Token::kTRUNCDIV) { | 1478 if (op_kind() == Token::kTRUNCDIV) { |
| 1455 const intptr_t kNumTemps = 3; | 1479 const intptr_t kNumTemps = 3; |
| 1456 LocationSummary* summary = | 1480 LocationSummary* summary = |
| 1457 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1481 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1458 summary->set_in(0, Location::RegisterLocation(RAX)); | 1482 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 1459 summary->set_in(1, Location::RegisterLocation(RCX)); | 1483 summary->set_in(1, Location::RegisterLocation(RCX)); |
| 1460 summary->set_out(Location::SameAsFirstInput()); | 1484 summary->set_out(Location::SameAsFirstInput()); |
| 1461 summary->set_temp(0, Location::RegisterLocation(RBX)); | 1485 summary->set_temp(0, Location::RegisterLocation(RBX)); |
| 1462 // Will be used for for sign extension. | 1486 // Will be used for for sign extension. |
| 1463 summary->set_temp(1, Location::RegisterLocation(RDX)); | 1487 summary->set_temp(1, Location::RegisterLocation(RDX)); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1489 summary->set_in(0, Location::RequiresRegister()); | 1513 summary->set_in(0, Location::RequiresRegister()); |
| 1490 summary->set_in(1, Location::RequiresRegister()); | 1514 summary->set_in(1, Location::RequiresRegister()); |
| 1491 summary->set_out(Location::SameAsFirstInput()); | 1515 summary->set_out(Location::SameAsFirstInput()); |
| 1492 return summary; | 1516 return summary; |
| 1493 } | 1517 } |
| 1494 } | 1518 } |
| 1495 | 1519 |
| 1496 | 1520 |
| 1497 void BinarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1521 void BinarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1498 Register left = locs()->in(0).reg(); | 1522 Register left = locs()->in(0).reg(); |
| 1499 Register right = locs()->in(1).reg(); | |
| 1500 Register result = locs()->out().reg(); | 1523 Register result = locs()->out().reg(); |
| 1501 ASSERT(left == result); | 1524 ASSERT(left == result); |
| 1502 Label* deopt = NULL; | 1525 Label* deopt = NULL; |
| 1503 switch (op_kind()) { | 1526 switch (op_kind()) { |
| 1504 case Token::kBIT_AND: | 1527 case Token::kBIT_AND: |
| 1505 case Token::kBIT_OR: | 1528 case Token::kBIT_OR: |
| 1506 case Token::kBIT_XOR: | 1529 case Token::kBIT_XOR: |
| 1507 // Can't deoptimize. Arguments are already checked for smi. | 1530 // Can't deoptimize. Arguments are already checked for smi. |
| 1508 break; | 1531 break; |
| 1509 default: | 1532 default: |
| 1510 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1533 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1511 kDeoptBinarySmiOp); | 1534 kDeoptBinarySmiOp); |
| 1512 } | 1535 } |
| 1536 |
| 1537 if (locs()->in(1).IsConstant()) { |
| 1538 const Object& constant = locs()->in(1).constant(); |
| 1539 ASSERT(constant.IsSmi()); |
| 1540 const int64_t imm = |
| 1541 reinterpret_cast<int64_t>(constant.raw()); |
| 1542 switch (op_kind()) { |
| 1543 case Token::kADD: { |
| 1544 __ addq(left, Immediate(imm)); |
| 1545 __ j(OVERFLOW, deopt); |
| 1546 break; |
| 1547 } |
| 1548 case Token::kSUB: { |
| 1549 __ subq(left, Immediate(imm)); |
| 1550 __ j(OVERFLOW, deopt); |
| 1551 break; |
| 1552 } |
| 1553 case Token::kBIT_AND: { |
| 1554 // No overflow check. |
| 1555 __ andq(left, Immediate(imm)); |
| 1556 break; |
| 1557 } |
| 1558 case Token::kBIT_OR: { |
| 1559 // No overflow check. |
| 1560 __ orq(left, Immediate(imm)); |
| 1561 break; |
| 1562 } |
| 1563 case Token::kBIT_XOR: { |
| 1564 // No overflow check. |
| 1565 __ xorq(left, Immediate(imm)); |
| 1566 break; |
| 1567 } |
| 1568 |
| 1569 case Token::kSHR: { |
| 1570 // sarq operation masks the count to 6 bits. |
| 1571 const intptr_t kCountLimit = 0x3F; |
| 1572 intptr_t value = Smi::Cast(constant).Value(); |
| 1573 |
| 1574 if (value == 0) { |
| 1575 // TODO(vegorov): should be handled outside. |
| 1576 break; |
| 1577 } else if (value < 0) { |
| 1578 // TODO(vegorov): should be handled outside. |
| 1579 __ jmp(deopt); |
| 1580 break; |
| 1581 } |
| 1582 |
| 1583 value = value + kSmiTagSize; |
| 1584 if (value >= kCountLimit) value = kCountLimit; |
| 1585 |
| 1586 __ sarq(left, Immediate(value)); |
| 1587 __ SmiTag(left); |
| 1588 break; |
| 1589 } |
| 1590 default: |
| 1591 UNREACHABLE(); |
| 1592 break; |
| 1593 } |
| 1594 return; |
| 1595 } |
| 1596 |
| 1597 Register right = locs()->in(1).reg(); |
| 1513 switch (op_kind()) { | 1598 switch (op_kind()) { |
| 1514 case Token::kADD: { | 1599 case Token::kADD: { |
| 1515 __ addq(left, right); | 1600 __ addq(left, right); |
| 1516 __ j(OVERFLOW, deopt); | 1601 __ j(OVERFLOW, deopt); |
| 1517 break; | 1602 break; |
| 1518 } | 1603 } |
| 1519 case Token::kSUB: { | 1604 case Token::kSUB: { |
| 1520 __ subq(left, right); | 1605 __ subq(left, right); |
| 1521 __ j(OVERFLOW, deopt); | 1606 __ j(OVERFLOW, deopt); |
| 1522 break; | 1607 break; |
| (...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2198 } | 2283 } |
| 2199 __ j(ABOVE_EQUAL, deopt); | 2284 __ j(ABOVE_EQUAL, deopt); |
| 2200 } | 2285 } |
| 2201 | 2286 |
| 2202 | 2287 |
| 2203 } // namespace dart | 2288 } // namespace dart |
| 2204 | 2289 |
| 2205 #undef __ | 2290 #undef __ |
| 2206 | 2291 |
| 2207 #endif // defined TARGET_ARCH_X64 | 2292 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |