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