Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(227)

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 460060: Code generation for multiply-by-constant-smi.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | test/mjsunit/smi-ops.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/smi-ops.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698