OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1362 void MacroAssembler::SmiMul(Register dst, | 1362 void MacroAssembler::SmiMul(Register dst, |
1363 Register src1, | 1363 Register src1, |
1364 Register src2, | 1364 Register src2, |
1365 LabelType* on_not_smi_result) { | 1365 LabelType* on_not_smi_result) { |
1366 ASSERT(!dst.is(src2)); | 1366 ASSERT(!dst.is(src2)); |
1367 ASSERT(!dst.is(kScratchRegister)); | 1367 ASSERT(!dst.is(kScratchRegister)); |
1368 ASSERT(!src1.is(kScratchRegister)); | 1368 ASSERT(!src1.is(kScratchRegister)); |
1369 ASSERT(!src2.is(kScratchRegister)); | 1369 ASSERT(!src2.is(kScratchRegister)); |
1370 | 1370 |
1371 if (dst.is(src1)) { | 1371 if (dst.is(src1)) { |
1372 NearLabel failure, zero_correct_result; | 1372 Label failure, zero_correct_result; |
1373 movq(kScratchRegister, src1); // Create backup for later testing. | 1373 movq(kScratchRegister, src1); // Create backup for later testing. |
1374 SmiToInteger64(dst, src1); | 1374 SmiToInteger64(dst, src1); |
1375 imul(dst, src2); | 1375 imul(dst, src2); |
1376 j(overflow, &failure); | 1376 j(overflow, &failure, Label::kNear); |
1377 | 1377 |
1378 // Check for negative zero result. If product is zero, and one | 1378 // Check for negative zero result. If product is zero, and one |
1379 // argument is negative, go to slow case. | 1379 // argument is negative, go to slow case. |
1380 NearLabel correct_result; | 1380 Label correct_result; |
1381 testq(dst, dst); | 1381 testq(dst, dst); |
1382 j(not_zero, &correct_result); | 1382 j(not_zero, &correct_result, Label::kNear); |
1383 | 1383 |
1384 movq(dst, kScratchRegister); | 1384 movq(dst, kScratchRegister); |
1385 xor_(dst, src2); | 1385 xor_(dst, src2); |
1386 j(positive, &zero_correct_result); // Result was positive zero. | 1386 // Result was positive zero. |
| 1387 j(positive, &zero_correct_result, Label::kNear); |
1387 | 1388 |
1388 bind(&failure); // Reused failure exit, restores src1. | 1389 bind(&failure); // Reused failure exit, restores src1. |
1389 movq(src1, kScratchRegister); | 1390 movq(src1, kScratchRegister); |
1390 jmp(on_not_smi_result); | 1391 jmp(on_not_smi_result); |
1391 | 1392 |
1392 bind(&zero_correct_result); | 1393 bind(&zero_correct_result); |
1393 Set(dst, 0); | 1394 Set(dst, 0); |
1394 | 1395 |
1395 bind(&correct_result); | 1396 bind(&correct_result); |
1396 } else { | 1397 } else { |
1397 SmiToInteger64(dst, src1); | 1398 SmiToInteger64(dst, src1); |
1398 imul(dst, src2); | 1399 imul(dst, src2); |
1399 j(overflow, on_not_smi_result); | 1400 j(overflow, on_not_smi_result); |
1400 // Check for negative zero result. If product is zero, and one | 1401 // Check for negative zero result. If product is zero, and one |
1401 // argument is negative, go to slow case. | 1402 // argument is negative, go to slow case. |
1402 NearLabel correct_result; | 1403 Label correct_result; |
1403 testq(dst, dst); | 1404 testq(dst, dst); |
1404 j(not_zero, &correct_result); | 1405 j(not_zero, &correct_result, Label::kNear); |
1405 // One of src1 and src2 is zero, the check whether the other is | 1406 // One of src1 and src2 is zero, the check whether the other is |
1406 // negative. | 1407 // negative. |
1407 movq(kScratchRegister, src1); | 1408 movq(kScratchRegister, src1); |
1408 xor_(kScratchRegister, src2); | 1409 xor_(kScratchRegister, src2); |
1409 j(negative, on_not_smi_result); | 1410 j(negative, on_not_smi_result); |
1410 bind(&correct_result); | 1411 bind(&correct_result); |
1411 } | 1412 } |
1412 } | 1413 } |
1413 | 1414 |
1414 | 1415 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1509 Register src2, | 1510 Register src2, |
1510 LabelType* on_not_smi_result) { | 1511 LabelType* on_not_smi_result) { |
1511 ASSERT(!src1.is(kScratchRegister)); | 1512 ASSERT(!src1.is(kScratchRegister)); |
1512 ASSERT(!src2.is(kScratchRegister)); | 1513 ASSERT(!src2.is(kScratchRegister)); |
1513 ASSERT(!dst.is(kScratchRegister)); | 1514 ASSERT(!dst.is(kScratchRegister)); |
1514 ASSERT(!src2.is(rax)); | 1515 ASSERT(!src2.is(rax)); |
1515 ASSERT(!src2.is(rdx)); | 1516 ASSERT(!src2.is(rdx)); |
1516 ASSERT(!src1.is(rdx)); | 1517 ASSERT(!src1.is(rdx)); |
1517 | 1518 |
1518 // Check for 0 divisor (result is +/-Infinity). | 1519 // Check for 0 divisor (result is +/-Infinity). |
1519 NearLabel positive_divisor; | |
1520 testq(src2, src2); | 1520 testq(src2, src2); |
1521 j(zero, on_not_smi_result); | 1521 j(zero, on_not_smi_result); |
1522 | 1522 |
1523 if (src1.is(rax)) { | 1523 if (src1.is(rax)) { |
1524 movq(kScratchRegister, src1); | 1524 movq(kScratchRegister, src1); |
1525 } | 1525 } |
1526 SmiToInteger32(rax, src1); | 1526 SmiToInteger32(rax, src1); |
1527 // We need to rule out dividing Smi::kMinValue by -1, since that would | 1527 // We need to rule out dividing Smi::kMinValue by -1, since that would |
1528 // overflow in idiv and raise an exception. | 1528 // overflow in idiv and raise an exception. |
1529 // We combine this with negative zero test (negative zero only happens | 1529 // We combine this with negative zero test (negative zero only happens |
1530 // when dividing zero by a negative number). | 1530 // when dividing zero by a negative number). |
1531 | 1531 |
1532 // We overshoot a little and go to slow case if we divide min-value | 1532 // We overshoot a little and go to slow case if we divide min-value |
1533 // by any negative value, not just -1. | 1533 // by any negative value, not just -1. |
1534 NearLabel safe_div; | 1534 Label safe_div; |
1535 testl(rax, Immediate(0x7fffffff)); | 1535 testl(rax, Immediate(0x7fffffff)); |
1536 j(not_zero, &safe_div); | 1536 j(not_zero, &safe_div, Label::kNear); |
1537 testq(src2, src2); | 1537 testq(src2, src2); |
1538 if (src1.is(rax)) { | 1538 if (src1.is(rax)) { |
1539 j(positive, &safe_div); | 1539 j(positive, &safe_div, Label::kNear); |
1540 movq(src1, kScratchRegister); | 1540 movq(src1, kScratchRegister); |
1541 jmp(on_not_smi_result); | 1541 jmp(on_not_smi_result); |
1542 } else { | 1542 } else { |
1543 j(negative, on_not_smi_result); | 1543 j(negative, on_not_smi_result); |
1544 } | 1544 } |
1545 bind(&safe_div); | 1545 bind(&safe_div); |
1546 | 1546 |
1547 SmiToInteger32(src2, src2); | 1547 SmiToInteger32(src2, src2); |
1548 // Sign extend src1 into edx:eax. | 1548 // Sign extend src1 into edx:eax. |
1549 cdq(); | 1549 cdq(); |
1550 idivl(src2); | 1550 idivl(src2); |
1551 Integer32ToSmi(src2, src2); | 1551 Integer32ToSmi(src2, src2); |
1552 // Check that the remainder is zero. | 1552 // Check that the remainder is zero. |
1553 testl(rdx, rdx); | 1553 testl(rdx, rdx); |
1554 if (src1.is(rax)) { | 1554 if (src1.is(rax)) { |
1555 NearLabel smi_result; | 1555 Label smi_result; |
1556 j(zero, &smi_result); | 1556 j(zero, &smi_result, Label::kNear); |
1557 movq(src1, kScratchRegister); | 1557 movq(src1, kScratchRegister); |
1558 jmp(on_not_smi_result); | 1558 jmp(on_not_smi_result); |
1559 bind(&smi_result); | 1559 bind(&smi_result); |
1560 } else { | 1560 } else { |
1561 j(not_zero, on_not_smi_result); | 1561 j(not_zero, on_not_smi_result); |
1562 } | 1562 } |
1563 if (!dst.is(src1) && src1.is(rax)) { | 1563 if (!dst.is(src1) && src1.is(rax)) { |
1564 movq(src1, kScratchRegister); | 1564 movq(src1, kScratchRegister); |
1565 } | 1565 } |
1566 Integer32ToSmi(dst, rax); | 1566 Integer32ToSmi(dst, rax); |
(...skipping 16 matching lines...) Expand all Loading... |
1583 testq(src2, src2); | 1583 testq(src2, src2); |
1584 j(zero, on_not_smi_result); | 1584 j(zero, on_not_smi_result); |
1585 | 1585 |
1586 if (src1.is(rax)) { | 1586 if (src1.is(rax)) { |
1587 movq(kScratchRegister, src1); | 1587 movq(kScratchRegister, src1); |
1588 } | 1588 } |
1589 SmiToInteger32(rax, src1); | 1589 SmiToInteger32(rax, src1); |
1590 SmiToInteger32(src2, src2); | 1590 SmiToInteger32(src2, src2); |
1591 | 1591 |
1592 // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow). | 1592 // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow). |
1593 NearLabel safe_div; | 1593 Label safe_div; |
1594 cmpl(rax, Immediate(Smi::kMinValue)); | 1594 cmpl(rax, Immediate(Smi::kMinValue)); |
1595 j(not_equal, &safe_div); | 1595 j(not_equal, &safe_div, Label::kNear); |
1596 cmpl(src2, Immediate(-1)); | 1596 cmpl(src2, Immediate(-1)); |
1597 j(not_equal, &safe_div); | 1597 j(not_equal, &safe_div, Label::kNear); |
1598 // Retag inputs and go slow case. | 1598 // Retag inputs and go slow case. |
1599 Integer32ToSmi(src2, src2); | 1599 Integer32ToSmi(src2, src2); |
1600 if (src1.is(rax)) { | 1600 if (src1.is(rax)) { |
1601 movq(src1, kScratchRegister); | 1601 movq(src1, kScratchRegister); |
1602 } | 1602 } |
1603 jmp(on_not_smi_result); | 1603 jmp(on_not_smi_result); |
1604 bind(&safe_div); | 1604 bind(&safe_div); |
1605 | 1605 |
1606 // Sign extend eax into edx:eax. | 1606 // Sign extend eax into edx:eax. |
1607 cdq(); | 1607 cdq(); |
1608 idivl(src2); | 1608 idivl(src2); |
1609 // Restore smi tags on inputs. | 1609 // Restore smi tags on inputs. |
1610 Integer32ToSmi(src2, src2); | 1610 Integer32ToSmi(src2, src2); |
1611 if (src1.is(rax)) { | 1611 if (src1.is(rax)) { |
1612 movq(src1, kScratchRegister); | 1612 movq(src1, kScratchRegister); |
1613 } | 1613 } |
1614 // Check for a negative zero result. If the result is zero, and the | 1614 // Check for a negative zero result. If the result is zero, and the |
1615 // dividend is negative, go slow to return a floating point negative zero. | 1615 // dividend is negative, go slow to return a floating point negative zero. |
1616 NearLabel smi_result; | 1616 Label smi_result; |
1617 testl(rdx, rdx); | 1617 testl(rdx, rdx); |
1618 j(not_zero, &smi_result); | 1618 j(not_zero, &smi_result, Label::kNear); |
1619 testq(src1, src1); | 1619 testq(src1, src1); |
1620 j(negative, on_not_smi_result); | 1620 j(negative, on_not_smi_result); |
1621 bind(&smi_result); | 1621 bind(&smi_result); |
1622 Integer32ToSmi(dst, rdx); | 1622 Integer32ToSmi(dst, rdx); |
1623 } | 1623 } |
1624 | 1624 |
1625 | 1625 |
1626 template <typename LabelType> | 1626 template <typename LabelType> |
1627 void MacroAssembler::SmiShiftLogicalRightConstant( | 1627 void MacroAssembler::SmiShiftLogicalRightConstant( |
1628 Register dst, Register src, int shift_value, LabelType* on_not_smi_result) { | 1628 Register dst, Register src, int shift_value, LabelType* on_not_smi_result) { |
(...skipping 16 matching lines...) Expand all Loading... |
1645 void MacroAssembler::SmiShiftLogicalRight(Register dst, | 1645 void MacroAssembler::SmiShiftLogicalRight(Register dst, |
1646 Register src1, | 1646 Register src1, |
1647 Register src2, | 1647 Register src2, |
1648 LabelType* on_not_smi_result) { | 1648 LabelType* on_not_smi_result) { |
1649 ASSERT(!dst.is(kScratchRegister)); | 1649 ASSERT(!dst.is(kScratchRegister)); |
1650 ASSERT(!src1.is(kScratchRegister)); | 1650 ASSERT(!src1.is(kScratchRegister)); |
1651 ASSERT(!src2.is(kScratchRegister)); | 1651 ASSERT(!src2.is(kScratchRegister)); |
1652 ASSERT(!dst.is(rcx)); | 1652 ASSERT(!dst.is(rcx)); |
1653 // dst and src1 can be the same, because the one case that bails out | 1653 // dst and src1 can be the same, because the one case that bails out |
1654 // is a shift by 0, which leaves dst, and therefore src1, unchanged. | 1654 // is a shift by 0, which leaves dst, and therefore src1, unchanged. |
1655 NearLabel result_ok; | |
1656 if (src1.is(rcx) || src2.is(rcx)) { | 1655 if (src1.is(rcx) || src2.is(rcx)) { |
1657 movq(kScratchRegister, rcx); | 1656 movq(kScratchRegister, rcx); |
1658 } | 1657 } |
1659 if (!dst.is(src1)) { | 1658 if (!dst.is(src1)) { |
1660 movq(dst, src1); | 1659 movq(dst, src1); |
1661 } | 1660 } |
1662 SmiToInteger32(rcx, src2); | 1661 SmiToInteger32(rcx, src2); |
1663 orl(rcx, Immediate(kSmiShift)); | 1662 orl(rcx, Immediate(kSmiShift)); |
1664 shr_cl(dst); // Shift is rcx modulo 0x1f + 32. | 1663 shr_cl(dst); // Shift is rcx modulo 0x1f + 32. |
1665 shl(dst, Immediate(kSmiShift)); | 1664 shl(dst, Immediate(kSmiShift)); |
1666 testq(dst, dst); | 1665 testq(dst, dst); |
1667 if (src1.is(rcx) || src2.is(rcx)) { | 1666 if (src1.is(rcx) || src2.is(rcx)) { |
1668 NearLabel positive_result; | 1667 Label positive_result; |
1669 j(positive, &positive_result); | 1668 j(positive, &positive_result, Label::kNear); |
1670 if (src1.is(rcx)) { | 1669 if (src1.is(rcx)) { |
1671 movq(src1, kScratchRegister); | 1670 movq(src1, kScratchRegister); |
1672 } else { | 1671 } else { |
1673 movq(src2, kScratchRegister); | 1672 movq(src2, kScratchRegister); |
1674 } | 1673 } |
1675 jmp(on_not_smi_result); | 1674 jmp(on_not_smi_result); |
1676 bind(&positive_result); | 1675 bind(&positive_result); |
1677 } else { | 1676 } else { |
1678 j(negative, on_not_smi_result); // src2 was zero and src1 negative. | 1677 j(negative, on_not_smi_result); // src2 was zero and src1 negative. |
1679 } | 1678 } |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1931 | 1930 |
1932 template <typename LabelType> | 1931 template <typename LabelType> |
1933 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 1932 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
1934 const ParameterCount& actual, | 1933 const ParameterCount& actual, |
1935 Handle<Code> code_constant, | 1934 Handle<Code> code_constant, |
1936 Register code_register, | 1935 Register code_register, |
1937 LabelType* done, | 1936 LabelType* done, |
1938 InvokeFlag flag, | 1937 InvokeFlag flag, |
1939 const CallWrapper& call_wrapper) { | 1938 const CallWrapper& call_wrapper) { |
1940 bool definitely_matches = false; | 1939 bool definitely_matches = false; |
1941 NearLabel invoke; | 1940 Label invoke; |
1942 if (expected.is_immediate()) { | 1941 if (expected.is_immediate()) { |
1943 ASSERT(actual.is_immediate()); | 1942 ASSERT(actual.is_immediate()); |
1944 if (expected.immediate() == actual.immediate()) { | 1943 if (expected.immediate() == actual.immediate()) { |
1945 definitely_matches = true; | 1944 definitely_matches = true; |
1946 } else { | 1945 } else { |
1947 Set(rax, actual.immediate()); | 1946 Set(rax, actual.immediate()); |
1948 if (expected.immediate() == | 1947 if (expected.immediate() == |
1949 SharedFunctionInfo::kDontAdaptArgumentsSentinel) { | 1948 SharedFunctionInfo::kDontAdaptArgumentsSentinel) { |
1950 // Don't worry about adapting arguments for built-ins that | 1949 // Don't worry about adapting arguments for built-ins that |
1951 // don't want that done. Skip adaption code by making it look | 1950 // don't want that done. Skip adaption code by making it look |
1952 // like we have a match between expected and actual number of | 1951 // like we have a match between expected and actual number of |
1953 // arguments. | 1952 // arguments. |
1954 definitely_matches = true; | 1953 definitely_matches = true; |
1955 } else { | 1954 } else { |
1956 Set(rbx, expected.immediate()); | 1955 Set(rbx, expected.immediate()); |
1957 } | 1956 } |
1958 } | 1957 } |
1959 } else { | 1958 } else { |
1960 if (actual.is_immediate()) { | 1959 if (actual.is_immediate()) { |
1961 // Expected is in register, actual is immediate. This is the | 1960 // Expected is in register, actual is immediate. This is the |
1962 // case when we invoke function values without going through the | 1961 // case when we invoke function values without going through the |
1963 // IC mechanism. | 1962 // IC mechanism. |
1964 cmpq(expected.reg(), Immediate(actual.immediate())); | 1963 cmpq(expected.reg(), Immediate(actual.immediate())); |
1965 j(equal, &invoke); | 1964 j(equal, &invoke, Label::kNear); |
1966 ASSERT(expected.reg().is(rbx)); | 1965 ASSERT(expected.reg().is(rbx)); |
1967 Set(rax, actual.immediate()); | 1966 Set(rax, actual.immediate()); |
1968 } else if (!expected.reg().is(actual.reg())) { | 1967 } else if (!expected.reg().is(actual.reg())) { |
1969 // Both expected and actual are in (different) registers. This | 1968 // Both expected and actual are in (different) registers. This |
1970 // is the case when we invoke functions using call and apply. | 1969 // is the case when we invoke functions using call and apply. |
1971 cmpq(expected.reg(), actual.reg()); | 1970 cmpq(expected.reg(), actual.reg()); |
1972 j(equal, &invoke); | 1971 j(equal, &invoke, Label::kNear); |
1973 ASSERT(actual.reg().is(rax)); | 1972 ASSERT(actual.reg().is(rax)); |
1974 ASSERT(expected.reg().is(rbx)); | 1973 ASSERT(expected.reg().is(rbx)); |
1975 } | 1974 } |
1976 } | 1975 } |
1977 | 1976 |
1978 if (!definitely_matches) { | 1977 if (!definitely_matches) { |
1979 Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 1978 Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
1980 if (!code_constant.is_null()) { | 1979 if (!code_constant.is_null()) { |
1981 movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); | 1980 movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); |
1982 addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 1981 addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
(...skipping 10 matching lines...) Expand all Loading... |
1993 Jump(adaptor, RelocInfo::CODE_TARGET); | 1992 Jump(adaptor, RelocInfo::CODE_TARGET); |
1994 } | 1993 } |
1995 bind(&invoke); | 1994 bind(&invoke); |
1996 } | 1995 } |
1997 } | 1996 } |
1998 | 1997 |
1999 | 1998 |
2000 } } // namespace v8::internal | 1999 } } // namespace v8::internal |
2001 | 2000 |
2002 #endif // V8_X64_MACRO_ASSEMBLER_X64_H_ | 2001 #endif // V8_X64_MACRO_ASSEMBLER_X64_H_ |
OLD | NEW |