OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 if (instr->IsCall()) { | 277 if (instr->IsCall()) { |
278 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 278 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
279 } | 279 } |
280 if (!instr->IsLazyBailout() && !instr->IsGap()) { | 280 if (!instr->IsLazyBailout() && !instr->IsGap()) { |
281 safepoints_.BumpLastLazySafepointIndex(); | 281 safepoints_.BumpLastLazySafepointIndex(); |
282 } | 282 } |
283 } | 283 } |
284 | 284 |
285 | 285 |
286 void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) { | 286 void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) { |
| 287 if (FLAG_debug_code && FLAG_enable_slow_asserts && instr->HasResult() && |
| 288 instr->hydrogen_value()->representation().IsInteger32() && |
| 289 instr->result()->IsRegister()) { |
| 290 __ AssertZeroExtended(ToRegister(instr->result())); |
| 291 } |
| 292 |
287 if (instr->HasResult() && instr->MustSignExtendResult(chunk())) { | 293 if (instr->HasResult() && instr->MustSignExtendResult(chunk())) { |
288 if (instr->result()->IsRegister()) { | 294 if (instr->result()->IsRegister()) { |
289 Register result_reg = ToRegister(instr->result()); | 295 Register result_reg = ToRegister(instr->result()); |
290 __ movsxlq(result_reg, result_reg); | 296 __ movsxlq(result_reg, result_reg); |
291 } else { | 297 } else { |
292 // Sign extend the 32bit result in the stack slots. | 298 // Sign extend the 32bit result in the stack slots. |
293 ASSERT(instr->result()->IsStackSlot()); | 299 ASSERT(instr->result()->IsStackSlot()); |
294 Operand src = ToOperand(instr->result()); | 300 Operand src = ToOperand(instr->result()); |
295 __ movsxlq(kScratchRegister, src); | 301 __ movsxlq(kScratchRegister, src); |
296 __ movq(src, kScratchRegister); | 302 __ movq(src, kScratchRegister); |
(...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1131 // If the divisor is positive, things are easy: There can be no deopts and we | 1137 // If the divisor is positive, things are easy: There can be no deopts and we |
1132 // can simply do an arithmetic right shift. | 1138 // can simply do an arithmetic right shift. |
1133 if (divisor == 1) return; | 1139 if (divisor == 1) return; |
1134 int32_t shift = WhichPowerOf2Abs(divisor); | 1140 int32_t shift = WhichPowerOf2Abs(divisor); |
1135 if (divisor > 1) { | 1141 if (divisor > 1) { |
1136 __ sarl(dividend, Immediate(shift)); | 1142 __ sarl(dividend, Immediate(shift)); |
1137 return; | 1143 return; |
1138 } | 1144 } |
1139 | 1145 |
1140 // If the divisor is negative, we have to negate and handle edge cases. | 1146 // If the divisor is negative, we have to negate and handle edge cases. |
1141 Label not_kmin_int, done; | |
1142 __ negl(dividend); | 1147 __ negl(dividend); |
1143 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1148 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1144 DeoptimizeIf(zero, instr->environment()); | 1149 DeoptimizeIf(zero, instr->environment()); |
1145 } | 1150 } |
1146 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1151 |
1147 // Note that we could emit branch-free code, but that would need one more | 1152 // If the negation could not overflow, simply shifting is OK. |
1148 // register. | 1153 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
1149 __ j(no_overflow, ¬_kmin_int, Label::kNear); | 1154 __ sarl(dividend, Immediate(shift)); |
1150 if (divisor == -1) { | 1155 return; |
1151 DeoptimizeIf(no_condition, instr->environment()); | |
1152 } else { | |
1153 __ movl(dividend, Immediate(kMinInt / divisor)); | |
1154 __ jmp(&done, Label::kNear); | |
1155 } | |
1156 } | 1156 } |
| 1157 |
| 1158 // Note that we could emit branch-free code, but that would need one more |
| 1159 // register. |
| 1160 if (divisor == -1) { |
| 1161 DeoptimizeIf(overflow, instr->environment()); |
| 1162 return; |
| 1163 } |
| 1164 |
| 1165 Label not_kmin_int, done; |
| 1166 __ j(no_overflow, ¬_kmin_int, Label::kNear); |
| 1167 __ movl(dividend, Immediate(kMinInt / divisor)); |
| 1168 __ jmp(&done, Label::kNear); |
1157 __ bind(¬_kmin_int); | 1169 __ bind(¬_kmin_int); |
1158 __ sarl(dividend, Immediate(shift)); | 1170 __ sarl(dividend, Immediate(shift)); |
1159 __ bind(&done); | 1171 __ bind(&done); |
1160 } | 1172 } |
1161 | 1173 |
1162 | 1174 |
1163 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { | 1175 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
1164 Register dividend = ToRegister(instr->dividend()); | 1176 Register dividend = ToRegister(instr->dividend()); |
1165 int32_t divisor = instr->divisor(); | 1177 int32_t divisor = instr->divisor(); |
1166 ASSERT(ToRegister(instr->result()).is(rdx)); | 1178 ASSERT(ToRegister(instr->result()).is(rdx)); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1254 } | 1266 } |
1255 | 1267 |
1256 // Check for (0 / -x) that will produce negative zero. | 1268 // Check for (0 / -x) that will produce negative zero. |
1257 HDiv* hdiv = instr->hydrogen(); | 1269 HDiv* hdiv = instr->hydrogen(); |
1258 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1270 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1259 __ testl(dividend, dividend); | 1271 __ testl(dividend, dividend); |
1260 DeoptimizeIf(zero, instr->environment()); | 1272 DeoptimizeIf(zero, instr->environment()); |
1261 } | 1273 } |
1262 | 1274 |
1263 __ TruncatingDiv(dividend, Abs(divisor)); | 1275 __ TruncatingDiv(dividend, Abs(divisor)); |
1264 if (divisor < 0) __ negp(rdx); | 1276 if (divisor < 0) __ negl(rdx); |
1265 | 1277 |
1266 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1278 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
1267 __ movl(rax, rdx); | 1279 __ movl(rax, rdx); |
1268 __ imull(rax, rax, Immediate(divisor)); | 1280 __ imull(rax, rax, Immediate(divisor)); |
1269 __ subl(rax, dividend); | 1281 __ subl(rax, dividend); |
1270 DeoptimizeIf(not_equal, instr->environment()); | 1282 DeoptimizeIf(not_equal, instr->environment()); |
1271 } | 1283 } |
1272 } | 1284 } |
1273 | 1285 |
1274 | 1286 |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1466 __ xorl(ToRegister(left), Immediate(right_operand)); | 1478 __ xorl(ToRegister(left), Immediate(right_operand)); |
1467 } | 1479 } |
1468 break; | 1480 break; |
1469 default: | 1481 default: |
1470 UNREACHABLE(); | 1482 UNREACHABLE(); |
1471 break; | 1483 break; |
1472 } | 1484 } |
1473 } else if (right->IsStackSlot()) { | 1485 } else if (right->IsStackSlot()) { |
1474 switch (instr->op()) { | 1486 switch (instr->op()) { |
1475 case Token::BIT_AND: | 1487 case Token::BIT_AND: |
1476 __ andp(ToRegister(left), ToOperand(right)); | 1488 if (instr->IsInteger32()) { |
| 1489 __ andl(ToRegister(left), ToOperand(right)); |
| 1490 } else { |
| 1491 __ andp(ToRegister(left), ToOperand(right)); |
| 1492 } |
1477 break; | 1493 break; |
1478 case Token::BIT_OR: | 1494 case Token::BIT_OR: |
1479 __ orp(ToRegister(left), ToOperand(right)); | 1495 if (instr->IsInteger32()) { |
| 1496 __ orl(ToRegister(left), ToOperand(right)); |
| 1497 } else { |
| 1498 __ orp(ToRegister(left), ToOperand(right)); |
| 1499 } |
1480 break; | 1500 break; |
1481 case Token::BIT_XOR: | 1501 case Token::BIT_XOR: |
1482 __ xorp(ToRegister(left), ToOperand(right)); | 1502 if (instr->IsInteger32()) { |
| 1503 __ xorl(ToRegister(left), ToOperand(right)); |
| 1504 } else { |
| 1505 __ xorp(ToRegister(left), ToOperand(right)); |
| 1506 } |
1483 break; | 1507 break; |
1484 default: | 1508 default: |
1485 UNREACHABLE(); | 1509 UNREACHABLE(); |
1486 break; | 1510 break; |
1487 } | 1511 } |
1488 } else { | 1512 } else { |
1489 ASSERT(right->IsRegister()); | 1513 ASSERT(right->IsRegister()); |
1490 switch (instr->op()) { | 1514 switch (instr->op()) { |
1491 case Token::BIT_AND: | 1515 case Token::BIT_AND: |
1492 __ andp(ToRegister(left), ToRegister(right)); | 1516 if (instr->IsInteger32()) { |
| 1517 __ andl(ToRegister(left), ToRegister(right)); |
| 1518 } else { |
| 1519 __ andp(ToRegister(left), ToRegister(right)); |
| 1520 } |
1493 break; | 1521 break; |
1494 case Token::BIT_OR: | 1522 case Token::BIT_OR: |
1495 __ orp(ToRegister(left), ToRegister(right)); | 1523 if (instr->IsInteger32()) { |
| 1524 __ orl(ToRegister(left), ToRegister(right)); |
| 1525 } else { |
| 1526 __ orp(ToRegister(left), ToRegister(right)); |
| 1527 } |
1496 break; | 1528 break; |
1497 case Token::BIT_XOR: | 1529 case Token::BIT_XOR: |
1498 __ xorp(ToRegister(left), ToRegister(right)); | 1530 if (instr->IsInteger32()) { |
| 1531 __ xorl(ToRegister(left), ToRegister(right)); |
| 1532 } else { |
| 1533 __ xorp(ToRegister(left), ToRegister(right)); |
| 1534 } |
1499 break; | 1535 break; |
1500 default: | 1536 default: |
1501 UNREACHABLE(); | 1537 UNREACHABLE(); |
1502 break; | 1538 break; |
1503 } | 1539 } |
1504 } | 1540 } |
1505 } | 1541 } |
1506 | 1542 |
1507 | 1543 |
1508 void LCodeGen::DoShiftI(LShiftI* instr) { | 1544 void LCodeGen::DoShiftI(LShiftI* instr) { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1595 } | 1631 } |
1596 } | 1632 } |
1597 | 1633 |
1598 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1634 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1599 DeoptimizeIf(overflow, instr->environment()); | 1635 DeoptimizeIf(overflow, instr->environment()); |
1600 } | 1636 } |
1601 } | 1637 } |
1602 | 1638 |
1603 | 1639 |
1604 void LCodeGen::DoConstantI(LConstantI* instr) { | 1640 void LCodeGen::DoConstantI(LConstantI* instr) { |
1605 __ Set(ToRegister(instr->result()), instr->value()); | 1641 Register dst = ToRegister(instr->result()); |
| 1642 if (instr->value() == 0) { |
| 1643 __ xorl(dst, dst); |
| 1644 } else { |
| 1645 __ movl(dst, Immediate(instr->value())); |
| 1646 } |
1606 } | 1647 } |
1607 | 1648 |
1608 | 1649 |
1609 void LCodeGen::DoConstantS(LConstantS* instr) { | 1650 void LCodeGen::DoConstantS(LConstantS* instr) { |
1610 __ Move(ToRegister(instr->result()), instr->value()); | 1651 __ Move(ToRegister(instr->result()), instr->value()); |
1611 } | 1652 } |
1612 | 1653 |
1613 | 1654 |
1614 void LCodeGen::DoConstantD(LConstantD* instr) { | 1655 void LCodeGen::DoConstantD(LConstantD* instr) { |
1615 ASSERT(instr->result()->IsDoubleRegister()); | 1656 ASSERT(instr->result()->IsDoubleRegister()); |
(...skipping 1358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2974 __ movss(result, operand); | 3015 __ movss(result, operand); |
2975 __ cvtss2sd(result, result); | 3016 __ cvtss2sd(result, result); |
2976 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || | 3017 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
2977 elements_kind == FLOAT64_ELEMENTS) { | 3018 elements_kind == FLOAT64_ELEMENTS) { |
2978 __ movsd(ToDoubleRegister(instr->result()), operand); | 3019 __ movsd(ToDoubleRegister(instr->result()), operand); |
2979 } else { | 3020 } else { |
2980 Register result(ToRegister(instr->result())); | 3021 Register result(ToRegister(instr->result())); |
2981 switch (elements_kind) { | 3022 switch (elements_kind) { |
2982 case EXTERNAL_INT8_ELEMENTS: | 3023 case EXTERNAL_INT8_ELEMENTS: |
2983 case INT8_ELEMENTS: | 3024 case INT8_ELEMENTS: |
2984 __ movsxbq(result, operand); | 3025 __ movsxbl(result, operand); |
2985 break; | 3026 break; |
2986 case EXTERNAL_UINT8_ELEMENTS: | 3027 case EXTERNAL_UINT8_ELEMENTS: |
2987 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: | 3028 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: |
2988 case UINT8_ELEMENTS: | 3029 case UINT8_ELEMENTS: |
2989 case UINT8_CLAMPED_ELEMENTS: | 3030 case UINT8_CLAMPED_ELEMENTS: |
2990 __ movzxbp(result, operand); | 3031 __ movzxbl(result, operand); |
2991 break; | 3032 break; |
2992 case EXTERNAL_INT16_ELEMENTS: | 3033 case EXTERNAL_INT16_ELEMENTS: |
2993 case INT16_ELEMENTS: | 3034 case INT16_ELEMENTS: |
2994 __ movsxwq(result, operand); | 3035 __ movsxwl(result, operand); |
2995 break; | 3036 break; |
2996 case EXTERNAL_UINT16_ELEMENTS: | 3037 case EXTERNAL_UINT16_ELEMENTS: |
2997 case UINT16_ELEMENTS: | 3038 case UINT16_ELEMENTS: |
2998 __ movzxwp(result, operand); | 3039 __ movzxwl(result, operand); |
2999 break; | 3040 break; |
3000 case EXTERNAL_INT32_ELEMENTS: | 3041 case EXTERNAL_INT32_ELEMENTS: |
3001 case INT32_ELEMENTS: | 3042 case INT32_ELEMENTS: |
3002 __ movsxlq(result, operand); | 3043 __ movl(result, operand); |
3003 break; | 3044 break; |
3004 case EXTERNAL_UINT32_ELEMENTS: | 3045 case EXTERNAL_UINT32_ELEMENTS: |
3005 case UINT32_ELEMENTS: | 3046 case UINT32_ELEMENTS: |
3006 __ movl(result, operand); | 3047 __ movl(result, operand); |
3007 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 3048 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
3008 __ testl(result, result); | 3049 __ testl(result, result); |
3009 DeoptimizeIf(negative, instr->environment()); | 3050 DeoptimizeIf(negative, instr->environment()); |
3010 } | 3051 } |
3011 break; | 3052 break; |
3012 case EXTERNAL_FLOAT32_ELEMENTS: | 3053 case EXTERNAL_FLOAT32_ELEMENTS: |
(...skipping 2578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5591 FixedArray::kHeaderSize - kPointerSize)); | 5632 FixedArray::kHeaderSize - kPointerSize)); |
5592 __ bind(&done); | 5633 __ bind(&done); |
5593 } | 5634 } |
5594 | 5635 |
5595 | 5636 |
5596 #undef __ | 5637 #undef __ |
5597 | 5638 |
5598 } } // namespace v8::internal | 5639 } } // namespace v8::internal |
5599 | 5640 |
5600 #endif // V8_TARGET_ARCH_X64 | 5641 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |