| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 1598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1609 case Token::SHR: | 1609 case Token::SHR: |
| 1610 if (reversed) { | 1610 if (reversed) { |
| 1611 Result constant_operand(value); | 1611 Result constant_operand(value); |
| 1612 LikelySmiBinaryOperation(op, &constant_operand, operand, | 1612 LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 1613 overwrite_mode); | 1613 overwrite_mode); |
| 1614 } else { | 1614 } else { |
| 1615 // Only the least significant 5 bits of the shift value are used. | 1615 // Only the least significant 5 bits of the shift value are used. |
| 1616 // In the slow case, this masking is done inside the runtime call. | 1616 // In the slow case, this masking is done inside the runtime call. |
| 1617 int shift_value = int_value & 0x1f; | 1617 int shift_value = int_value & 0x1f; |
| 1618 operand->ToRegister(); | 1618 operand->ToRegister(); |
| 1619 Result answer = allocator()->Allocate(); | 1619 frame_->Spill(operand->reg()); |
| 1620 ASSERT(answer.is_valid()); | |
| 1621 DeferredInlineSmiOperation* deferred = | 1620 DeferredInlineSmiOperation* deferred = |
| 1622 new DeferredInlineSmiOperation(op, | 1621 new DeferredInlineSmiOperation(op, |
| 1623 answer.reg(), | 1622 operand->reg(), |
| 1624 operand->reg(), | 1623 operand->reg(), |
| 1625 smi_value, | 1624 smi_value, |
| 1626 overwrite_mode); | 1625 overwrite_mode); |
| 1627 __ test(operand->reg(), Immediate(kSmiTagMask)); | |
| 1628 deferred->Branch(not_zero); | |
| 1629 __ mov(answer.reg(), operand->reg()); | |
| 1630 __ sar(answer.reg(), kSmiTagSize); | |
| 1631 __ shr(answer.reg(), shift_value); | |
| 1632 // A negative Smi shifted right two is in the positive Smi range. | |
| 1633 if (shift_value < 2) { | 1626 if (shift_value < 2) { |
| 1634 __ test(answer.reg(), Immediate(0xc0000000)); | 1627 // A negative Smi shifted by 0 or 1 is too big to fit in the positive |
| 1628 // Smi range. Fold the test into the Smi tag test. |
| 1629 __ test(operand->reg(), Immediate(kSmiTagMask | 0x80000000)); |
| 1635 deferred->Branch(not_zero); | 1630 deferred->Branch(not_zero); |
| 1631 if (shift_value == 1) { |
| 1632 __ shr(operand->reg(), 1); |
| 1633 __ and_(operand->reg(), ~kSmiTagMask); |
| 1634 } |
| 1635 } else { |
| 1636 __ test(operand->reg(), Immediate(kSmiTagMask)); |
| 1637 deferred->Branch(not_zero); |
| 1638 __ sar(operand->reg(), 1); |
| 1639 __ shr(operand->reg(), shift_value - 1); |
| 1640 __ and_(operand->reg(), ~kSmiTagMask); |
| 1636 } | 1641 } |
| 1637 operand->Unuse(); | 1642 ASSERT(kSmiTag == 0); // adjust code if not the case |
| 1638 ASSERT(kSmiTagSize == times_2); // Adjust the code if not true. | 1643 ASSERT(kSmiTagSize == 1); // Adjust the code if not true. |
| 1639 __ lea(answer.reg(), | |
| 1640 Operand(answer.reg(), answer.reg(), times_1, kSmiTag)); | |
| 1641 deferred->BindExit(); | 1644 deferred->BindExit(); |
| 1642 frame_->Push(&answer); | 1645 frame_->Push(operand); |
| 1643 } | 1646 } |
| 1644 break; | 1647 break; |
| 1645 | 1648 |
| 1646 case Token::SHL: | 1649 case Token::SHL: |
| 1647 if (reversed) { | 1650 if (reversed) { |
| 1648 Result constant_operand(value); | 1651 Result constant_operand(value); |
| 1649 LikelySmiBinaryOperation(op, &constant_operand, operand, | 1652 LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 1650 overwrite_mode); | 1653 overwrite_mode); |
| 1651 } else { | 1654 } else { |
| 1652 // Only the least significant 5 bits of the shift value are used. | 1655 // Only the least significant 5 bits of the shift value are used. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1726 ASSERT(op == Token::BIT_OR); | 1729 ASSERT(op == Token::BIT_OR); |
| 1727 if (int_value != 0) { | 1730 if (int_value != 0) { |
| 1728 __ or_(Operand(operand->reg()), Immediate(value)); | 1731 __ or_(Operand(operand->reg()), Immediate(value)); |
| 1729 } | 1732 } |
| 1730 } | 1733 } |
| 1731 deferred->BindExit(); | 1734 deferred->BindExit(); |
| 1732 frame_->Push(operand); | 1735 frame_->Push(operand); |
| 1733 break; | 1736 break; |
| 1734 } | 1737 } |
| 1735 | 1738 |
| 1739 case Token::MUL: { |
| 1740 operand->ToRegister(); |
| 1741 frame_->Spill(operand->reg()); |
| 1742 DeferredCode* deferred = NULL; |
| 1743 Result* answer = NULL; |
| 1744 Result answer_reg; |
| 1745 if (int_value == 0 || int_value == 1 || int_value == -1) { |
| 1746 // Re-use operand register. |
| 1747 answer = operand; |
| 1748 } else { |
| 1749 // Need a fresh register. |
| 1750 answer_reg = allocator()->Allocate(); |
| 1751 answer = &answer_reg; |
| 1752 ASSERT(answer->is_valid()); |
| 1753 } |
| 1754 if (reversed) { |
| 1755 deferred = new DeferredInlineSmiOperationReversed(op, |
| 1756 answer->reg(), |
| 1757 smi_value, |
| 1758 operand->reg(), |
| 1759 overwrite_mode); |
| 1760 } else { |
| 1761 deferred = new DeferredInlineSmiOperation(op, |
| 1762 answer->reg(), |
| 1763 operand->reg(), |
| 1764 smi_value, |
| 1765 overwrite_mode); |
| 1766 } |
| 1767 __ test(operand->reg(), Immediate(kSmiTagMask)); |
| 1768 deferred->Branch(not_zero); |
| 1769 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
| 1770 |
| 1771 if (int_value == 1) { |
| 1772 // Already have correct value in 'answer'. |
| 1773 ASSERT(answer == operand); |
| 1774 } else if (int_value == 0) { |
| 1775 // The result is positive zero or negative zero depending on the sign of |
| 1776 // the operand. |
| 1777 __ test(operand->reg(), Operand(operand->reg())); |
| 1778 deferred->Branch(negative); |
| 1779 __ Set(answer->reg(), Immediate(0)); |
| 1780 } else if (int_value == -1) { |
| 1781 ASSERT(answer == operand); |
| 1782 __ neg(answer->reg()); |
| 1783 // The only value that can overflow is MIN_SMI, for which negation |
| 1784 // yields the same bit pattern. Thus the operand register, although |
| 1785 // negated, holds the original value, ready for the deferred code. |
| 1786 deferred->Branch(overflow); |
| 1787 // If the result is zero, it should be negative zero. Again, the |
| 1788 // operand register, although negated, contains the original value! |
| 1789 deferred->Branch(zero); |
| 1790 } else { |
| 1791 __ imul(answer->reg(), operand->reg(), int_value); |
| 1792 deferred->Branch(overflow); |
| 1793 |
| 1794 if (int_value < 0) { // Negative zero test. |
| 1795 __ test(answer->reg(), Operand(answer->reg())); |
| 1796 deferred->Branch(zero); |
| 1797 } |
| 1798 } |
| 1799 deferred->BindExit(); |
| 1800 if (operand != answer) { |
| 1801 operand->Unuse(); |
| 1802 } |
| 1803 frame_->Push(answer); |
| 1804 break; |
| 1805 } |
| 1806 |
| 1736 // Generate inline code for mod of powers of 2 and negative powers of 2. | 1807 // Generate inline code for mod of powers of 2 and negative powers of 2. |
| 1737 case Token::MOD: | 1808 case Token::MOD: |
| 1738 if (!reversed && | 1809 if (!reversed && |
| 1739 int_value != 0 && | 1810 int_value != 0 && |
| 1740 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { | 1811 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { |
| 1741 operand->ToRegister(); | 1812 operand->ToRegister(); |
| 1742 frame_->Spill(operand->reg()); | 1813 frame_->Spill(operand->reg()); |
| 1743 DeferredCode* deferred = new DeferredInlineSmiOperation(op, | 1814 DeferredCode* deferred = new DeferredInlineSmiOperation(op, |
| 1744 operand->reg(), | 1815 operand->reg(), |
| 1745 operand->reg(), | 1816 operand->reg(), |
| (...skipping 5542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7288 __ j(not_equal, non_float); // argument in eax is not a number -> NaN | 7359 __ j(not_equal, non_float); // argument in eax is not a number -> NaN |
| 7289 | 7360 |
| 7290 // Fall-through: Both operands are numbers. | 7361 // Fall-through: Both operands are numbers. |
| 7291 __ bind(&done); | 7362 __ bind(&done); |
| 7292 } | 7363 } |
| 7293 | 7364 |
| 7294 | 7365 |
| 7295 void UnarySubStub::Generate(MacroAssembler* masm) { | 7366 void UnarySubStub::Generate(MacroAssembler* masm) { |
| 7296 Label undo; | 7367 Label undo; |
| 7297 Label slow; | 7368 Label slow; |
| 7298 Label done; | |
| 7299 Label try_float; | 7369 Label try_float; |
| 7300 | 7370 |
| 7301 // Check whether the value is a smi. | 7371 // Check whether the value is a smi. |
| 7302 __ test(eax, Immediate(kSmiTagMask)); | 7372 __ test(eax, Immediate(kSmiTagMask)); |
| 7303 __ j(not_zero, &try_float, not_taken); | 7373 __ j(not_zero, &try_float, not_taken); |
| 7304 | 7374 |
| 7305 // Enter runtime system if the value of the expression is zero | 7375 // Optimistically negate. There are two special case. (1) The |
| 7306 // to make sure that we switch between 0 and -0. | 7376 // smallest Smi value will overflow. (2) 0 should yield -0. Both of |
| 7307 __ test(eax, Operand(eax)); | 7377 // these cases enter the runtime system. No restoration of the |
| 7378 // operand's original value is necessary, as the two values are (the |
| 7379 // only) values such that x == -x in two's complement arithmetic. |
| 7380 __ neg(eax); |
| 7381 __ j(overflow, &slow, not_taken); |
| 7308 __ j(zero, &slow, not_taken); | 7382 __ j(zero, &slow, not_taken); |
| 7309 | 7383 |
| 7310 // The value of the expression is a smi that is not zero. Try | 7384 __ StubReturn(1); |
| 7311 // optimistic subtraction '0 - value'. | |
| 7312 __ mov(edx, Operand(eax)); | |
| 7313 __ Set(eax, Immediate(0)); | |
| 7314 __ sub(eax, Operand(edx)); | |
| 7315 __ j(overflow, &undo, not_taken); | |
| 7316 | |
| 7317 // If result is a smi we are done. | |
| 7318 __ test(eax, Immediate(kSmiTagMask)); | |
| 7319 __ j(zero, &done, taken); | |
| 7320 | 7385 |
| 7321 // Restore eax and enter runtime system. | 7386 // Restore eax and enter runtime system. |
| 7322 __ bind(&undo); | 7387 __ bind(&undo); |
| 7323 __ mov(eax, Operand(edx)); | 7388 __ mov(eax, Operand(edx)); |
| 7324 | 7389 |
| 7325 // Enter runtime system. | 7390 // Enter runtime system. |
| 7326 __ bind(&slow); | 7391 __ bind(&slow); |
| 7327 __ pop(ecx); // pop return address | 7392 __ pop(ecx); // pop return address |
| 7328 __ push(eax); | 7393 __ push(eax); |
| 7329 __ push(ecx); // push return address | 7394 __ push(ecx); // push return address |
| (...skipping 13 matching lines...) Expand all Loading... |
| 7343 // edx: operand | 7408 // edx: operand |
| 7344 __ AllocateHeapNumber(eax, ebx, ecx, &undo); | 7409 __ AllocateHeapNumber(eax, ebx, ecx, &undo); |
| 7345 // eax: allocated 'empty' number | 7410 // eax: allocated 'empty' number |
| 7346 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); | 7411 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); |
| 7347 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. | 7412 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. |
| 7348 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx); | 7413 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx); |
| 7349 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); | 7414 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); |
| 7350 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); | 7415 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); |
| 7351 } | 7416 } |
| 7352 | 7417 |
| 7353 __ bind(&done); | |
| 7354 | |
| 7355 __ StubReturn(1); | 7418 __ StubReturn(1); |
| 7356 } | 7419 } |
| 7357 | 7420 |
| 7358 | 7421 |
| 7359 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { | 7422 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { |
| 7360 // Check if the calling frame is an arguments adaptor frame. | 7423 // Check if the calling frame is an arguments adaptor frame. |
| 7361 Label adaptor; | 7424 Label adaptor; |
| 7362 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 7425 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 7363 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); | 7426 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); |
| 7364 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 7427 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| (...skipping 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8449 __ add(Operand(dest), Immediate(2)); | 8512 __ add(Operand(dest), Immediate(2)); |
| 8450 } | 8513 } |
| 8451 __ sub(Operand(count), Immediate(1)); | 8514 __ sub(Operand(count), Immediate(1)); |
| 8452 __ j(not_zero, &loop); | 8515 __ j(not_zero, &loop); |
| 8453 } | 8516 } |
| 8454 | 8517 |
| 8455 | 8518 |
| 8456 #undef __ | 8519 #undef __ |
| 8457 | 8520 |
| 8458 } } // namespace v8::internal | 8521 } } // namespace v8::internal |
| OLD | NEW |