OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 6666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6677 Result old_value; // Only allocated in the postfix case. | 6677 Result old_value; // Only allocated in the postfix case. |
6678 if (is_postfix) { | 6678 if (is_postfix) { |
6679 // Allocate a temporary to preserve the old value. | 6679 // Allocate a temporary to preserve the old value. |
6680 old_value = allocator_->Allocate(); | 6680 old_value = allocator_->Allocate(); |
6681 ASSERT(old_value.is_valid()); | 6681 ASSERT(old_value.is_valid()); |
6682 __ mov(old_value.reg(), new_value.reg()); | 6682 __ mov(old_value.reg(), new_value.reg()); |
6683 } | 6683 } |
6684 // Ensure the new value is writable. | 6684 // Ensure the new value is writable. |
6685 frame_->Spill(new_value.reg()); | 6685 frame_->Spill(new_value.reg()); |
6686 | 6686 |
6687 // In order to combine the overflow and the smi tag check, we need | 6687 Result tmp; |
6688 // to be able to allocate a byte register. We attempt to do so | 6688 if (new_value.is_smi()) { |
6689 // without spilling. If we fail, we will generate separate overflow | 6689 if (FLAG_debug_code) { |
6690 // and smi tag checks. | 6690 __ AbortIfNotSmi(new_value.reg(), "Operand not a smi"); |
6691 // | 6691 } |
6692 // We allocate and clear the temporary byte register before | 6692 } else { |
6693 // performing the count operation since clearing the register using | 6693 // We don't know statically if the input is a smi. |
6694 // xor will clear the overflow flag. | 6694 // In order to combine the overflow and the smi tag check, we need |
6695 Result tmp = allocator_->AllocateByteRegisterWithoutSpilling(); | 6695 // to be able to allocate a byte register. We attempt to do so |
6696 if (tmp.is_valid()) { | 6696 // without spilling. If we fail, we will generate separate overflow |
6697 __ Set(tmp.reg(), Immediate(0)); | 6697 // and smi tag checks. |
| 6698 // We allocate and clear a temporary byte register before performing |
| 6699 // the count operation since clearing the register using xor will clear |
| 6700 // the overflow flag. |
| 6701 tmp = allocator_->AllocateByteRegisterWithoutSpilling(); |
| 6702 if (tmp.is_valid()) { |
| 6703 __ Set(tmp.reg(), Immediate(0)); |
| 6704 } |
6698 } | 6705 } |
6699 | 6706 |
6700 | |
6701 if (is_increment) { | 6707 if (is_increment) { |
6702 __ add(Operand(new_value.reg()), Immediate(Smi::FromInt(1))); | 6708 __ add(Operand(new_value.reg()), Immediate(Smi::FromInt(1))); |
6703 } else { | 6709 } else { |
6704 __ sub(Operand(new_value.reg()), Immediate(Smi::FromInt(1))); | 6710 __ sub(Operand(new_value.reg()), Immediate(Smi::FromInt(1))); |
6705 } | 6711 } |
6706 | 6712 |
| 6713 DeferredCode* deferred = NULL; |
| 6714 if (is_postfix) { |
| 6715 deferred = new DeferredPostfixCountOperation(new_value.reg(), |
| 6716 old_value.reg(), |
| 6717 is_increment); |
| 6718 } else { |
| 6719 deferred = new DeferredPrefixCountOperation(new_value.reg(), |
| 6720 is_increment); |
| 6721 } |
| 6722 |
6707 if (new_value.is_smi()) { | 6723 if (new_value.is_smi()) { |
6708 if (FLAG_debug_code) { | 6724 // In case we have a smi as input just check for overflow. |
6709 __ AbortIfNotSmi(new_value.reg(), "Argument not a smi"); | 6725 deferred->Branch(overflow); |
6710 } | |
6711 if (tmp.is_valid()) tmp.Unuse(); | |
6712 } else { | 6726 } else { |
6713 DeferredCode* deferred = NULL; | |
6714 if (is_postfix) { | |
6715 deferred = new DeferredPostfixCountOperation(new_value.reg(), | |
6716 old_value.reg(), | |
6717 is_increment); | |
6718 } else { | |
6719 deferred = new DeferredPrefixCountOperation(new_value.reg(), | |
6720 is_increment); | |
6721 } | |
6722 | |
6723 // If the count operation didn't overflow and the result is a valid | 6727 // If the count operation didn't overflow and the result is a valid |
6724 // smi, we're done. Otherwise, we jump to the deferred slow-case | 6728 // smi, we're done. Otherwise, we jump to the deferred slow-case |
6725 // code. | 6729 // code. |
| 6730 // We combine the overflow and the smi tag check if we could |
| 6731 // successfully allocate a temporary byte register. |
6726 if (tmp.is_valid()) { | 6732 if (tmp.is_valid()) { |
6727 // We combine the overflow and the smi tag check if we could | |
6728 // successfully allocate a temporary byte register. | |
6729 __ setcc(overflow, tmp.reg()); | 6733 __ setcc(overflow, tmp.reg()); |
6730 __ or_(Operand(tmp.reg()), new_value.reg()); | 6734 __ or_(Operand(tmp.reg()), new_value.reg()); |
6731 __ test(tmp.reg(), Immediate(kSmiTagMask)); | 6735 __ test(tmp.reg(), Immediate(kSmiTagMask)); |
6732 tmp.Unuse(); | 6736 tmp.Unuse(); |
6733 deferred->Branch(not_zero); | 6737 deferred->Branch(not_zero); |
6734 } else { | 6738 } else { |
6735 // Otherwise we test separately for overflow and smi tag. | 6739 // Otherwise we test separately for overflow and smi tag. |
6736 deferred->Branch(overflow); | 6740 deferred->Branch(overflow); |
6737 __ test(new_value.reg(), Immediate(kSmiTagMask)); | 6741 __ test(new_value.reg(), Immediate(kSmiTagMask)); |
6738 deferred->Branch(not_zero); | 6742 deferred->Branch(not_zero); |
6739 } | 6743 } |
6740 deferred->BindExit(); | |
6741 } | 6744 } |
| 6745 deferred->BindExit(); |
| 6746 |
6742 | 6747 |
6743 // Postfix: store the old value in the allocated slot under the | 6748 // Postfix: store the old value in the allocated slot under the |
6744 // reference. | 6749 // reference. |
6745 if (is_postfix) frame_->SetElementAt(target.size(), &old_value); | 6750 if (is_postfix) frame_->SetElementAt(target.size(), &old_value); |
6746 | 6751 |
6747 frame_->Push(&new_value); | 6752 frame_->Push(&new_value); |
6748 // Non-constant: update the reference. | 6753 // Non-constant: update the reference. |
6749 if (!is_const) target.SetValue(NOT_CONST_INIT); | 6754 if (!is_const) target.SetValue(NOT_CONST_INIT); |
6750 } | 6755 } |
6751 | 6756 |
(...skipping 5108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11860 | 11865 |
11861 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 11866 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
11862 // tagged as a small integer. | 11867 // tagged as a small integer. |
11863 __ bind(&runtime); | 11868 __ bind(&runtime); |
11864 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 11869 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
11865 } | 11870 } |
11866 | 11871 |
11867 #undef __ | 11872 #undef __ |
11868 | 11873 |
11869 } } // namespace v8::internal | 11874 } } // namespace v8::internal |
OLD | NEW |