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 1751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1762 // [Object] | 1762 // [Object] |
1763 | 1763 |
1764 // Check if enumerable is already a JSObject | 1764 // Check if enumerable is already a JSObject |
1765 __ tst(r0, Operand(kSmiTagMask)); | 1765 __ tst(r0, Operand(kSmiTagMask)); |
1766 primitive.Branch(eq); | 1766 primitive.Branch(eq); |
1767 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); | 1767 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); |
1768 jsobject.Branch(hs); | 1768 jsobject.Branch(hs); |
1769 | 1769 |
1770 primitive.Bind(); | 1770 primitive.Bind(); |
1771 frame_->EmitPush(r0); | 1771 frame_->EmitPush(r0); |
1772 Result arg_count(r0); | 1772 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, 1); |
1773 __ mov(r0, Operand(0)); | |
1774 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, &arg_count, 1); | |
1775 | 1773 |
1776 jsobject.Bind(); | 1774 jsobject.Bind(); |
1777 // Get the set of properties (as a FixedArray or Map). | 1775 // Get the set of properties (as a FixedArray or Map). |
1778 // r0: value to be iterated over | 1776 // r0: value to be iterated over |
1779 frame_->EmitPush(r0); // Push the object being iterated over. | 1777 frame_->EmitPush(r0); // Push the object being iterated over. |
1780 | 1778 |
1781 // Check cache validity in generated code. This is a fast case for | 1779 // Check cache validity in generated code. This is a fast case for |
1782 // the JSObject::IsSimpleEnum cache validity checks. If we cannot | 1780 // the JSObject::IsSimpleEnum cache validity checks. If we cannot |
1783 // guarantee cache validity, call the runtime system to check cache | 1781 // guarantee cache validity, call the runtime system to check cache |
1784 // validity or get the property names in a fixed array. | 1782 // validity or get the property names in a fixed array. |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1903 // If not, we have to filter the key. | 1901 // If not, we have to filter the key. |
1904 __ ldr(r1, frame_->ElementAt(4)); | 1902 __ ldr(r1, frame_->ElementAt(4)); |
1905 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); | 1903 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); |
1906 __ cmp(r1, Operand(r2)); | 1904 __ cmp(r1, Operand(r2)); |
1907 end_del_check.Branch(eq); | 1905 end_del_check.Branch(eq); |
1908 | 1906 |
1909 // Convert the entry to a string (or null if it isn't a property anymore). | 1907 // Convert the entry to a string (or null if it isn't a property anymore). |
1910 __ ldr(r0, frame_->ElementAt(4)); // push enumerable | 1908 __ ldr(r0, frame_->ElementAt(4)); // push enumerable |
1911 frame_->EmitPush(r0); | 1909 frame_->EmitPush(r0); |
1912 frame_->EmitPush(r3); // push entry | 1910 frame_->EmitPush(r3); // push entry |
1913 Result arg_count_reg(r0); | 1911 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS, 2); |
1914 __ mov(r0, Operand(1)); | |
1915 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS, &arg_count_reg, 2); | |
1916 __ mov(r3, Operand(r0)); | 1912 __ mov(r3, Operand(r0)); |
1917 | 1913 |
1918 // If the property has been removed while iterating, we just skip it. | 1914 // If the property has been removed while iterating, we just skip it. |
1919 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 1915 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
1920 __ cmp(r3, ip); | 1916 __ cmp(r3, ip); |
1921 node->continue_target()->Branch(eq); | 1917 node->continue_target()->Branch(eq); |
1922 | 1918 |
1923 end_del_check.Bind(); | 1919 end_del_check.Bind(); |
1924 // Store the entry in the 'each' expression and take another spin in the | 1920 // Store the entry in the 'each' expression and take another spin in the |
1925 // loop. r3: i'th entry of the enum cache (or string there of) | 1921 // loop. r3: i'th entry of the enum cache (or string there of) |
(...skipping 1727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3653 // LoadCondition may (and usually does) leave a test and branch to | 3649 // LoadCondition may (and usually does) leave a test and branch to |
3654 // be emitted by the caller. In that case, negate the condition. | 3650 // be emitted by the caller. In that case, negate the condition. |
3655 if (has_cc()) cc_reg_ = NegateCondition(cc_reg_); | 3651 if (has_cc()) cc_reg_ = NegateCondition(cc_reg_); |
3656 | 3652 |
3657 } else if (op == Token::DELETE) { | 3653 } else if (op == Token::DELETE) { |
3658 Property* property = node->expression()->AsProperty(); | 3654 Property* property = node->expression()->AsProperty(); |
3659 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); | 3655 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); |
3660 if (property != NULL) { | 3656 if (property != NULL) { |
3661 LoadAndSpill(property->obj()); | 3657 LoadAndSpill(property->obj()); |
3662 LoadAndSpill(property->key()); | 3658 LoadAndSpill(property->key()); |
3663 Result arg_count(r0); | 3659 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); |
3664 __ mov(r0, Operand(1)); // not counting receiver | |
3665 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2); | |
3666 | 3660 |
3667 } else if (variable != NULL) { | 3661 } else if (variable != NULL) { |
3668 Slot* slot = variable->slot(); | 3662 Slot* slot = variable->slot(); |
3669 if (variable->is_global()) { | 3663 if (variable->is_global()) { |
3670 LoadGlobal(); | 3664 LoadGlobal(); |
3671 __ mov(r0, Operand(variable->name())); | 3665 __ mov(r0, Operand(variable->name())); |
3672 frame_->EmitPush(r0); | 3666 frame_->EmitPush(r0); |
3673 Result arg_count(r0); | 3667 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); |
3674 __ mov(r0, Operand(1)); // not counting receiver | |
3675 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2); | |
3676 | 3668 |
3677 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 3669 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
3678 // lookup the context holding the named variable | 3670 // lookup the context holding the named variable |
3679 frame_->EmitPush(cp); | 3671 frame_->EmitPush(cp); |
3680 __ mov(r0, Operand(variable->name())); | 3672 __ mov(r0, Operand(variable->name())); |
3681 frame_->EmitPush(r0); | 3673 frame_->EmitPush(r0); |
3682 frame_->CallRuntime(Runtime::kLookupContext, 2); | 3674 frame_->CallRuntime(Runtime::kLookupContext, 2); |
3683 // r0: context | 3675 // r0: context |
3684 frame_->EmitPush(r0); | 3676 frame_->EmitPush(r0); |
3685 __ mov(r0, Operand(variable->name())); | 3677 __ mov(r0, Operand(variable->name())); |
3686 frame_->EmitPush(r0); | 3678 frame_->EmitPush(r0); |
3687 Result arg_count(r0); | 3679 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); |
3688 __ mov(r0, Operand(1)); // not counting receiver | |
3689 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2); | |
3690 | 3680 |
3691 } else { | 3681 } else { |
3692 // Default: Result of deleting non-global, not dynamically | 3682 // Default: Result of deleting non-global, not dynamically |
3693 // introduced variables is false. | 3683 // introduced variables is false. |
3694 __ LoadRoot(r0, Heap::kFalseValueRootIndex); | 3684 __ LoadRoot(r0, Heap::kFalseValueRootIndex); |
3695 } | 3685 } |
3696 | 3686 |
3697 } else { | 3687 } else { |
3698 // Default: Result of deleting expressions is true. | 3688 // Default: Result of deleting expressions is true. |
3699 LoadAndSpill(node->expression()); // may have side-effects | 3689 LoadAndSpill(node->expression()); // may have side-effects |
(...skipping 29 matching lines...) Expand all Loading... |
3729 } | 3719 } |
3730 | 3720 |
3731 case Token::BIT_NOT: { | 3721 case Token::BIT_NOT: { |
3732 // smi check | 3722 // smi check |
3733 JumpTarget smi_label; | 3723 JumpTarget smi_label; |
3734 JumpTarget continue_label; | 3724 JumpTarget continue_label; |
3735 __ tst(r0, Operand(kSmiTagMask)); | 3725 __ tst(r0, Operand(kSmiTagMask)); |
3736 smi_label.Branch(eq); | 3726 smi_label.Branch(eq); |
3737 | 3727 |
3738 frame_->EmitPush(r0); | 3728 frame_->EmitPush(r0); |
3739 Result arg_count(r0); | 3729 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, 1); |
3740 __ mov(r0, Operand(0)); // not counting receiver | |
3741 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, &arg_count, 1); | |
3742 | 3730 |
3743 continue_label.Jump(); | 3731 continue_label.Jump(); |
3744 smi_label.Bind(); | 3732 smi_label.Bind(); |
3745 __ mvn(r0, Operand(r0)); | 3733 __ mvn(r0, Operand(r0)); |
3746 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag | 3734 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag |
3747 continue_label.Bind(); | 3735 continue_label.Bind(); |
3748 break; | 3736 break; |
3749 } | 3737 } |
3750 | 3738 |
3751 case Token::VOID: | 3739 case Token::VOID: |
3752 // since the stack top is cached in r0, popping and then | 3740 // since the stack top is cached in r0, popping and then |
3753 // pushing a value can be done by just writing to r0. | 3741 // pushing a value can be done by just writing to r0. |
3754 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 3742 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
3755 break; | 3743 break; |
3756 | 3744 |
3757 case Token::ADD: { | 3745 case Token::ADD: { |
3758 // Smi check. | 3746 // Smi check. |
3759 JumpTarget continue_label; | 3747 JumpTarget continue_label; |
3760 __ tst(r0, Operand(kSmiTagMask)); | 3748 __ tst(r0, Operand(kSmiTagMask)); |
3761 continue_label.Branch(eq); | 3749 continue_label.Branch(eq); |
3762 frame_->EmitPush(r0); | 3750 frame_->EmitPush(r0); |
3763 Result arg_count(r0); | 3751 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1); |
3764 __ mov(r0, Operand(0)); // not counting receiver | |
3765 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1); | |
3766 continue_label.Bind(); | 3752 continue_label.Bind(); |
3767 break; | 3753 break; |
3768 } | 3754 } |
3769 default: | 3755 default: |
3770 UNREACHABLE(); | 3756 UNREACHABLE(); |
3771 } | 3757 } |
3772 frame_->EmitPush(r0); // r0 has result | 3758 frame_->EmitPush(r0); // r0 has result |
3773 } | 3759 } |
3774 ASSERT(!has_valid_frame() || | 3760 ASSERT(!has_valid_frame() || |
3775 (has_cc() && frame_->height() == original_height) || | 3761 (has_cc() && frame_->height() == original_height) || |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3840 __ sub(r0, r0, Operand(r1)); | 3826 __ sub(r0, r0, Operand(r1)); |
3841 } else { | 3827 } else { |
3842 __ add(r0, r0, Operand(r1)); | 3828 __ add(r0, r0, Operand(r1)); |
3843 } | 3829 } |
3844 | 3830 |
3845 // Slow case: Convert to number. | 3831 // Slow case: Convert to number. |
3846 slow.Bind(); | 3832 slow.Bind(); |
3847 { | 3833 { |
3848 // Convert the operand to a number. | 3834 // Convert the operand to a number. |
3849 frame_->EmitPush(r0); | 3835 frame_->EmitPush(r0); |
3850 Result arg_count(r0); | 3836 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1); |
3851 __ mov(r0, Operand(0)); | |
3852 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1); | |
3853 } | 3837 } |
3854 if (is_postfix) { | 3838 if (is_postfix) { |
3855 // Postfix: store to result (on the stack). | 3839 // Postfix: store to result (on the stack). |
3856 __ str(r0, frame_->ElementAt(target.size())); | 3840 __ str(r0, frame_->ElementAt(target.size())); |
3857 } | 3841 } |
3858 | 3842 |
3859 // Compute the new value. | 3843 // Compute the new value. |
3860 __ mov(r1, Operand(Smi::FromInt(1))); | 3844 __ mov(r1, Operand(Smi::FromInt(1))); |
3861 frame_->EmitPush(r0); | 3845 frame_->EmitPush(r0); |
3862 frame_->EmitPush(r1); | 3846 frame_->EmitPush(r1); |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4228 Comparison(ge, left, right); | 4212 Comparison(ge, left, right); |
4229 break; | 4213 break; |
4230 | 4214 |
4231 case Token::EQ_STRICT: | 4215 case Token::EQ_STRICT: |
4232 Comparison(eq, left, right, true); | 4216 Comparison(eq, left, right, true); |
4233 break; | 4217 break; |
4234 | 4218 |
4235 case Token::IN: { | 4219 case Token::IN: { |
4236 LoadAndSpill(left); | 4220 LoadAndSpill(left); |
4237 LoadAndSpill(right); | 4221 LoadAndSpill(right); |
4238 Result arg_count(r0); | 4222 frame_->InvokeBuiltin(Builtins::IN, CALL_JS, 2); |
4239 __ mov(r0, Operand(1)); // not counting receiver | |
4240 frame_->InvokeBuiltin(Builtins::IN, CALL_JS, &arg_count, 2); | |
4241 frame_->EmitPush(r0); | 4223 frame_->EmitPush(r0); |
4242 break; | 4224 break; |
4243 } | 4225 } |
4244 | 4226 |
4245 case Token::INSTANCEOF: { | 4227 case Token::INSTANCEOF: { |
4246 LoadAndSpill(left); | 4228 LoadAndSpill(left); |
4247 LoadAndSpill(right); | 4229 LoadAndSpill(right); |
4248 InstanceofStub stub; | 4230 InstanceofStub stub; |
4249 frame_->CallStub(&stub, 2); | 4231 frame_->CallStub(&stub, 2); |
4250 // At this point if instanceof succeeded then r0 == 0. | 4232 // At this point if instanceof succeeded then r0 == 0. |
(...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5138 ASSERT(cc_ == gt || cc_ == ge); // remaining cases | 5120 ASSERT(cc_ == gt || cc_ == ge); // remaining cases |
5139 ncr = LESS; | 5121 ncr = LESS; |
5140 } | 5122 } |
5141 arg_count++; | 5123 arg_count++; |
5142 __ mov(r0, Operand(Smi::FromInt(ncr))); | 5124 __ mov(r0, Operand(Smi::FromInt(ncr))); |
5143 __ push(r0); | 5125 __ push(r0); |
5144 } | 5126 } |
5145 | 5127 |
5146 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 5128 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
5147 // tagged as a small integer. | 5129 // tagged as a small integer. |
5148 __ mov(r0, Operand(arg_count)); | |
5149 __ InvokeBuiltin(native, CALL_JS); | 5130 __ InvokeBuiltin(native, CALL_JS); |
5150 __ cmp(r0, Operand(0)); | 5131 __ cmp(r0, Operand(0)); |
5151 __ pop(pc); | 5132 __ pop(pc); |
5152 } | 5133 } |
5153 | 5134 |
5154 | 5135 |
5155 // Allocates a heap number or jumps to the label if the young space is full and | 5136 // Allocates a heap number or jumps to the label if the young space is full and |
5156 // a scavenge is needed. | 5137 // a scavenge is needed. |
5157 static void AllocateHeapNumber( | 5138 static void AllocateHeapNumber( |
5158 MacroAssembler* masm, | 5139 MacroAssembler* masm, |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5237 __ tst(r0, Operand(kSmiTagMask)); | 5218 __ tst(r0, Operand(kSmiTagMask)); |
5238 __ b(eq, &string1); | 5219 __ b(eq, &string1); |
5239 __ CompareObjectType(r0, r2, r2, FIRST_NONSTRING_TYPE); | 5220 __ CompareObjectType(r0, r2, r2, FIRST_NONSTRING_TYPE); |
5240 __ b(ge, &string1); | 5221 __ b(ge, &string1); |
5241 | 5222 |
5242 // First and second argument are strings. | 5223 // First and second argument are strings. |
5243 __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1); | 5224 __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1); |
5244 | 5225 |
5245 // Only first argument is a string. | 5226 // Only first argument is a string. |
5246 __ bind(&string1); | 5227 __ bind(&string1); |
5247 __ mov(r0, Operand(2)); // Set number of arguments. | |
5248 __ InvokeBuiltin(Builtins::STRING_ADD_LEFT, JUMP_JS); | 5228 __ InvokeBuiltin(Builtins::STRING_ADD_LEFT, JUMP_JS); |
5249 | 5229 |
5250 // First argument was not a string, test second. | 5230 // First argument was not a string, test second. |
5251 __ bind(¬_string1); | 5231 __ bind(¬_string1); |
5252 __ tst(r0, Operand(kSmiTagMask)); | 5232 __ tst(r0, Operand(kSmiTagMask)); |
5253 __ b(eq, ¬_strings); | 5233 __ b(eq, ¬_strings); |
5254 __ CompareObjectType(r0, r2, r2, FIRST_NONSTRING_TYPE); | 5234 __ CompareObjectType(r0, r2, r2, FIRST_NONSTRING_TYPE); |
5255 __ b(ge, ¬_strings); | 5235 __ b(ge, ¬_strings); |
5256 | 5236 |
5257 // Only second argument is a string. | 5237 // Only second argument is a string. |
5258 __ b(¬_strings); | 5238 __ b(¬_strings); |
5259 __ mov(r0, Operand(2)); // Set number of arguments. | |
5260 __ InvokeBuiltin(Builtins::STRING_ADD_RIGHT, JUMP_JS); | 5239 __ InvokeBuiltin(Builtins::STRING_ADD_RIGHT, JUMP_JS); |
5261 | 5240 |
5262 __ bind(¬_strings); | 5241 __ bind(¬_strings); |
5263 } | 5242 } |
5264 | 5243 |
5265 __ mov(r0, Operand(1)); // Set number of arguments. | |
5266 __ InvokeBuiltin(builtin, JUMP_JS); // Tail call. No return. | 5244 __ InvokeBuiltin(builtin, JUMP_JS); // Tail call. No return. |
5267 | 5245 |
5268 // We branch here if at least one of r0 and r1 is not a Smi. | 5246 // We branch here if at least one of r0 and r1 is not a Smi. |
5269 __ bind(not_smi); | 5247 __ bind(not_smi); |
5270 if (mode == NO_OVERWRITE) { | 5248 if (mode == NO_OVERWRITE) { |
5271 // In the case where there is no chance of an overwritable float we may as | 5249 // In the case where there is no chance of an overwritable float we may as |
5272 // well do the allocation immediately while r0 and r1 are untouched. | 5250 // well do the allocation immediately while r0 and r1 are untouched. |
5273 AllocateHeapNumber(masm, &slow, r5, r6, r7); | 5251 AllocateHeapNumber(masm, &slow, r5, r6, r7); |
5274 } | 5252 } |
5275 | 5253 |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5591 __ bind(&have_to_allocate); | 5569 __ bind(&have_to_allocate); |
5592 // Get a new heap number in r5. r6 and r7 are scratch. | 5570 // Get a new heap number in r5. r6 and r7 are scratch. |
5593 AllocateHeapNumber(masm, &slow, r5, r6, r7); | 5571 AllocateHeapNumber(masm, &slow, r5, r6, r7); |
5594 __ jmp(&got_a_heap_number); | 5572 __ jmp(&got_a_heap_number); |
5595 } | 5573 } |
5596 | 5574 |
5597 // If all else failed then we go to the runtime system. | 5575 // If all else failed then we go to the runtime system. |
5598 __ bind(&slow); | 5576 __ bind(&slow); |
5599 __ push(r1); // restore stack | 5577 __ push(r1); // restore stack |
5600 __ push(r0); | 5578 __ push(r0); |
5601 __ mov(r0, Operand(1)); // 1 argument (not counting receiver). | |
5602 switch (op_) { | 5579 switch (op_) { |
5603 case Token::BIT_OR: | 5580 case Token::BIT_OR: |
5604 __ InvokeBuiltin(Builtins::BIT_OR, JUMP_JS); | 5581 __ InvokeBuiltin(Builtins::BIT_OR, JUMP_JS); |
5605 break; | 5582 break; |
5606 case Token::BIT_AND: | 5583 case Token::BIT_AND: |
5607 __ InvokeBuiltin(Builtins::BIT_AND, JUMP_JS); | 5584 __ InvokeBuiltin(Builtins::BIT_AND, JUMP_JS); |
5608 break; | 5585 break; |
5609 case Token::BIT_XOR: | 5586 case Token::BIT_XOR: |
5610 __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_JS); | 5587 __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_JS); |
5611 break; | 5588 break; |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5973 // optimistic subtraction '0 - value'. | 5950 // optimistic subtraction '0 - value'. |
5974 __ rsb(r1, r0, Operand(0), SetCC); | 5951 __ rsb(r1, r0, Operand(0), SetCC); |
5975 __ b(vs, &slow); | 5952 __ b(vs, &slow); |
5976 | 5953 |
5977 __ mov(r0, Operand(r1)); // Set r0 to result. | 5954 __ mov(r0, Operand(r1)); // Set r0 to result. |
5978 __ StubReturn(1); | 5955 __ StubReturn(1); |
5979 | 5956 |
5980 // Enter runtime system. | 5957 // Enter runtime system. |
5981 __ bind(&slow); | 5958 __ bind(&slow); |
5982 __ push(r0); | 5959 __ push(r0); |
5983 __ mov(r0, Operand(0)); // Set number of arguments. | |
5984 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_JS); | 5960 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_JS); |
5985 | 5961 |
5986 __ bind(¬_smi); | 5962 __ bind(¬_smi); |
5987 __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE); | 5963 __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE); |
5988 __ b(ne, &slow); | 5964 __ b(ne, &slow); |
5989 // r0 is a heap number. Get a new heap number in r1. | 5965 // r0 is a heap number. Get a new heap number in r1. |
5990 if (overwrite_) { | 5966 if (overwrite_) { |
5991 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 5967 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
5992 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. | 5968 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. |
5993 __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 5969 __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6449 __ mov(pc, Operand(lr)); // Return. | 6425 __ mov(pc, Operand(lr)); // Return. |
6450 | 6426 |
6451 __ bind(&is_not_instance); | 6427 __ bind(&is_not_instance); |
6452 __ mov(r0, Operand(Smi::FromInt(1))); | 6428 __ mov(r0, Operand(Smi::FromInt(1))); |
6453 __ pop(); | 6429 __ pop(); |
6454 __ pop(); | 6430 __ pop(); |
6455 __ mov(pc, Operand(lr)); // Return. | 6431 __ mov(pc, Operand(lr)); // Return. |
6456 | 6432 |
6457 // Slow-case. Tail call builtin. | 6433 // Slow-case. Tail call builtin. |
6458 __ bind(&slow); | 6434 __ bind(&slow); |
6459 __ mov(r0, Operand(1)); // Arg count without receiver. | |
6460 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_JS); | 6435 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_JS); |
6461 } | 6436 } |
6462 | 6437 |
6463 | 6438 |
6464 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { | 6439 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { |
6465 // Check if the calling frame is an arguments adaptor frame. | 6440 // Check if the calling frame is an arguments adaptor frame. |
6466 Label adaptor; | 6441 Label adaptor; |
6467 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 6442 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
6468 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); | 6443 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); |
6469 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 6444 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6584 int CompareStub::MinorKey() { | 6559 int CompareStub::MinorKey() { |
6585 // Encode the two parameters in a unique 16 bit value. | 6560 // Encode the two parameters in a unique 16 bit value. |
6586 ASSERT(static_cast<unsigned>(cc_) >> 28 < (1 << 15)); | 6561 ASSERT(static_cast<unsigned>(cc_) >> 28 < (1 << 15)); |
6587 return (static_cast<unsigned>(cc_) >> 27) | (strict_ ? 1 : 0); | 6562 return (static_cast<unsigned>(cc_) >> 27) | (strict_ ? 1 : 0); |
6588 } | 6563 } |
6589 | 6564 |
6590 | 6565 |
6591 #undef __ | 6566 #undef __ |
6592 | 6567 |
6593 } } // namespace v8::internal | 6568 } } // namespace v8::internal |
OLD | NEW |