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 1408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1419 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1419 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1420 summary->set_in(0, Location::RegisterLocation(EAX)); | 1420 summary->set_in(0, Location::RegisterLocation(EAX)); |
1421 summary->set_in(1, Location::RegisterLocation(ECX)); | 1421 summary->set_in(1, Location::RegisterLocation(ECX)); |
1422 summary->set_out(Location::SameAsFirstInput()); | 1422 summary->set_out(Location::SameAsFirstInput()); |
1423 summary->set_temp(0, Location::RegisterLocation(EBX)); | 1423 summary->set_temp(0, Location::RegisterLocation(EBX)); |
1424 // Will be used for for sign extension. | 1424 // Will be used for for sign extension. |
1425 summary->set_temp(1, Location::RegisterLocation(EDX)); | 1425 summary->set_temp(1, Location::RegisterLocation(EDX)); |
1426 summary->set_temp(2, Location::RequiresRegister()); | 1426 summary->set_temp(2, Location::RequiresRegister()); |
1427 return summary; | 1427 return summary; |
1428 } else if (op_kind() == Token::kSHR) { | 1428 } else if (op_kind() == Token::kSHR) { |
1429 const intptr_t kNumTemps = 1; | 1429 const intptr_t kNumTemps = 0; |
1430 LocationSummary* summary = | 1430 LocationSummary* summary = |
1431 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1431 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1432 summary->set_in(0, Location::RequiresRegister()); | 1432 summary->set_in(0, Location::RequiresRegister()); |
1433 summary->set_in(1, Location::RegisterLocation(ECX)); | 1433 summary->set_in(1, Location::RegisterLocation(ECX)); |
1434 summary->set_out(Location::SameAsFirstInput()); | 1434 summary->set_out(Location::SameAsFirstInput()); |
1435 summary->set_temp(0, Location::RequiresRegister()); | |
1436 return summary; | 1435 return summary; |
1437 } else if (op_kind() == Token::kSHL) { | 1436 } else if (op_kind() == Token::kSHL) { |
1438 // Two Smi operands can easily overflow into Mint. | 1437 // Two Smi operands can easily overflow into Mint. |
1439 const intptr_t kNumTemps = 2; | 1438 const intptr_t kNumTemps = 2; |
1440 LocationSummary* summary = | 1439 LocationSummary* summary = |
1441 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1440 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
1442 summary->set_in(0, Location::RegisterLocation(EAX)); | 1441 summary->set_in(0, Location::RegisterLocation(EAX)); |
1443 summary->set_in(1, Location::RegisterLocation(EDX)); | 1442 summary->set_in(1, Location::RegisterLocation(EDX)); |
1444 summary->set_temp(0, Location::RegisterLocation(EBX)); | 1443 summary->set_temp(0, Location::RegisterLocation(EBX)); |
1445 summary->set_temp(1, Location::RegisterLocation(ECX)); | 1444 summary->set_temp(1, Location::RegisterLocation(ECX)); |
1446 summary->set_out(Location::RegisterLocation(EAX)); | 1445 summary->set_out(Location::RegisterLocation(EAX)); |
1447 return summary; | 1446 return summary; |
1448 } else { | 1447 } else { |
1449 const intptr_t kNumTemps = 1; | 1448 const intptr_t kNumTemps = 0; |
1450 LocationSummary* summary = | 1449 LocationSummary* summary = |
1451 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1450 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1452 summary->set_in(0, Location::RequiresRegister()); | 1451 summary->set_in(0, Location::RequiresRegister()); |
1453 summary->set_in(1, Location::RequiresRegister()); | 1452 summary->set_in(1, Location::RequiresRegister()); |
1454 summary->set_out(Location::SameAsFirstInput()); | 1453 summary->set_out(Location::SameAsFirstInput()); |
1455 summary->set_temp(0, Location::RequiresRegister()); | |
1456 return summary; | 1454 return summary; |
1457 } | 1455 } |
1458 } | 1456 } |
1459 | 1457 |
1460 | 1458 |
1461 void BinarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1459 void BinarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1462 Register left = locs()->in(0).reg(); | 1460 Register left = locs()->in(0).reg(); |
1463 Register right = locs()->in(1).reg(); | 1461 Register right = locs()->in(1).reg(); |
1464 Register result = locs()->out().reg(); | 1462 Register result = locs()->out().reg(); |
1465 Register temp = locs()->temp(0).reg(); | |
1466 ASSERT(left == result); | 1463 ASSERT(left == result); |
1467 const bool left_is_smi = this->left()->ResultCid() == kSmiCid; | 1464 Label* deopt = NULL; |
1468 const bool right_is_smi = this->right()->ResultCid() == kSmiCid; | |
1469 bool can_deopt; | |
1470 switch (op_kind()) { | 1465 switch (op_kind()) { |
1471 case Token::kBIT_AND: | 1466 case Token::kBIT_AND: |
1472 case Token::kBIT_OR: | 1467 case Token::kBIT_OR: |
1473 case Token::kBIT_XOR: | 1468 case Token::kBIT_XOR: |
1474 can_deopt = !(right_is_smi && left_is_smi); | 1469 // Can't deoptimize. Arguments are already checked for smi. |
1475 break; | 1470 break; |
1476 default: | 1471 default: |
1477 can_deopt = true; | 1472 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1473 instance_call()->try_index(), |
| 1474 kDeoptBinarySmiOp); |
1478 } | 1475 } |
1479 Label* deopt = NULL; | 1476 |
1480 if (can_deopt) { | |
1481 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | |
1482 instance_call()->try_index(), | |
1483 kDeoptBinarySmiOp); | |
1484 } | |
1485 if (!left_is_smi || !right_is_smi) { | |
1486 __ movl(temp, left); | |
1487 __ orl(temp, right); | |
1488 __ testl(temp, Immediate(kSmiTagMask)); | |
1489 __ j(NOT_ZERO, deopt); | |
1490 } | |
1491 switch (op_kind()) { | 1477 switch (op_kind()) { |
1492 case Token::kADD: { | 1478 case Token::kADD: { |
1493 __ addl(left, right); | 1479 __ addl(left, right); |
1494 __ j(OVERFLOW, deopt); | 1480 __ j(OVERFLOW, deopt); |
1495 break; | 1481 break; |
1496 } | 1482 } |
1497 case Token::kSUB: { | 1483 case Token::kSUB: { |
1498 __ subl(left, right); | 1484 __ subl(left, right); |
1499 __ j(OVERFLOW, deopt); | 1485 __ j(OVERFLOW, deopt); |
1500 break; | 1486 break; |
(...skipping 13 matching lines...) Expand all Loading... |
1514 // No overflow check. | 1500 // No overflow check. |
1515 __ orl(left, right); | 1501 __ orl(left, right); |
1516 break; | 1502 break; |
1517 } | 1503 } |
1518 case Token::kBIT_XOR: { | 1504 case Token::kBIT_XOR: { |
1519 // No overflow check. | 1505 // No overflow check. |
1520 __ xorl(left, right); | 1506 __ xorl(left, right); |
1521 break; | 1507 break; |
1522 } | 1508 } |
1523 case Token::kTRUNCDIV: { | 1509 case Token::kTRUNCDIV: { |
| 1510 Register temp = locs()->temp(0).reg(); |
1524 // Handle divide by zero in runtime. | 1511 // Handle divide by zero in runtime. |
1525 // Deoptimization requires that temp and right are preserved. | 1512 // Deoptimization requires that temp and right are preserved. |
1526 __ testl(right, right); | 1513 __ testl(right, right); |
1527 __ j(ZERO, deopt); | 1514 __ j(ZERO, deopt); |
1528 ASSERT(left == EAX); | 1515 ASSERT(left == EAX); |
1529 ASSERT((right != EDX) && (right != EAX)); | 1516 ASSERT((right != EDX) && (right != EAX)); |
1530 ASSERT((temp != EDX) && (temp != EAX)); | 1517 ASSERT((temp != EDX) && (temp != EAX)); |
1531 ASSERT(locs()->temp(1).reg() == EDX); | 1518 ASSERT(locs()->temp(1).reg() == EDX); |
1532 ASSERT(result == EAX); | 1519 ASSERT(result == EAX); |
1533 Register right_temp = locs()->temp(2).reg(); | 1520 Register right_temp = locs()->temp(2).reg(); |
(...skipping 20 matching lines...) Expand all Loading... |
1554 __ j(LESS, &count_ok, Assembler::kNearJump); | 1541 __ j(LESS, &count_ok, Assembler::kNearJump); |
1555 __ movl(right, kCountLimit); | 1542 __ movl(right, kCountLimit); |
1556 __ Bind(&count_ok); | 1543 __ Bind(&count_ok); |
1557 ASSERT(right == ECX); // Count must be in ECX | 1544 ASSERT(right == ECX); // Count must be in ECX |
1558 __ SmiUntag(left); | 1545 __ SmiUntag(left); |
1559 __ sarl(left, right); | 1546 __ sarl(left, right); |
1560 __ SmiTag(left); | 1547 __ SmiTag(left); |
1561 break; | 1548 break; |
1562 } | 1549 } |
1563 case Token::kSHL: { | 1550 case Token::kSHL: { |
| 1551 Register temp = locs()->temp(0).reg(); |
1564 Label call_method, done; | 1552 Label call_method, done; |
1565 // Check if count too large for handling it inlined. | 1553 // Check if count too large for handling it inlined. |
1566 __ movl(temp, left); | 1554 __ movl(temp, left); |
1567 __ cmpl(right, | 1555 __ cmpl(right, |
1568 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); | 1556 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); |
1569 __ j(ABOVE_EQUAL, &call_method, Assembler::kNearJump); | 1557 __ j(ABOVE_EQUAL, &call_method, Assembler::kNearJump); |
1570 Register right_temp = locs()->temp(1).reg(); | 1558 Register right_temp = locs()->temp(1).reg(); |
1571 ASSERT(right_temp == ECX); // Count must be in ECX | 1559 ASSERT(right_temp == ECX); // Count must be in ECX |
1572 __ movl(right_temp, right); | 1560 __ movl(right_temp, right); |
1573 __ SmiUntag(right_temp); | 1561 __ SmiUntag(right_temp); |
(...skipping 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2185 if (use_near_jump) { | 2173 if (use_near_jump) { |
2186 __ j(EQUAL, &is_ok, Assembler::kNearJump); | 2174 __ j(EQUAL, &is_ok, Assembler::kNearJump); |
2187 } else { | 2175 } else { |
2188 __ j(EQUAL, &is_ok); | 2176 __ j(EQUAL, &is_ok); |
2189 } | 2177 } |
2190 } | 2178 } |
2191 } | 2179 } |
2192 __ Bind(&is_ok); | 2180 __ Bind(&is_ok); |
2193 } | 2181 } |
2194 | 2182 |
| 2183 |
| 2184 LocationSummary* CheckSmiComp::MakeLocationSummary() const { |
| 2185 const intptr_t kNumInputs = 1; |
| 2186 const intptr_t kNumTemps = 0; |
| 2187 LocationSummary* summary = |
| 2188 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2189 summary->set_in(0, Location::RequiresRegister()); |
| 2190 return summary; |
| 2191 } |
| 2192 |
| 2193 |
| 2194 void CheckSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2195 Register value = locs()->in(0).reg(); |
| 2196 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2197 try_index(), |
| 2198 kDeoptCheckSmi); |
| 2199 __ testl(value, Immediate(kSmiTagMask)); |
| 2200 __ j(NOT_ZERO, deopt); |
| 2201 } |
| 2202 |
| 2203 |
2195 } // namespace dart | 2204 } // namespace dart |
2196 | 2205 |
2197 #undef __ | 2206 #undef __ |
2198 | 2207 |
2199 #endif // defined TARGET_ARCH_X64 | 2208 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |