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 3707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3718 frame_->EmitPush(r0); | 3718 frame_->EmitPush(r0); |
3719 | 3719 |
3720 } else if (op == Token::TYPEOF) { | 3720 } else if (op == Token::TYPEOF) { |
3721 // Special case for loading the typeof expression; see comment on | 3721 // Special case for loading the typeof expression; see comment on |
3722 // LoadTypeofExpression(). | 3722 // LoadTypeofExpression(). |
3723 LoadTypeofExpression(node->expression()); | 3723 LoadTypeofExpression(node->expression()); |
3724 frame_->CallRuntime(Runtime::kTypeof, 1); | 3724 frame_->CallRuntime(Runtime::kTypeof, 1); |
3725 frame_->EmitPush(r0); // r0 has result | 3725 frame_->EmitPush(r0); // r0 has result |
3726 | 3726 |
3727 } else { | 3727 } else { |
| 3728 bool overwrite = |
| 3729 (node->expression()->AsBinaryOperation() != NULL && |
| 3730 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); |
3728 LoadAndSpill(node->expression()); | 3731 LoadAndSpill(node->expression()); |
3729 frame_->EmitPop(r0); | 3732 frame_->EmitPop(r0); |
3730 switch (op) { | 3733 switch (op) { |
3731 case Token::NOT: | 3734 case Token::NOT: |
3732 case Token::DELETE: | 3735 case Token::DELETE: |
3733 case Token::TYPEOF: | 3736 case Token::TYPEOF: |
3734 UNREACHABLE(); // handled above | 3737 UNREACHABLE(); // handled above |
3735 break; | 3738 break; |
3736 | 3739 |
3737 case Token::SUB: { | 3740 case Token::SUB: { |
3738 bool overwrite = | |
3739 (node->expression()->AsBinaryOperation() != NULL && | |
3740 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); | |
3741 GenericUnaryOpStub stub(Token::SUB, overwrite); | 3741 GenericUnaryOpStub stub(Token::SUB, overwrite); |
3742 frame_->CallStub(&stub, 0); | 3742 frame_->CallStub(&stub, 0); |
3743 break; | 3743 break; |
3744 } | 3744 } |
3745 | 3745 |
3746 case Token::BIT_NOT: { | 3746 case Token::BIT_NOT: { |
3747 // smi check | 3747 // smi check |
3748 JumpTarget smi_label; | 3748 JumpTarget smi_label; |
3749 JumpTarget continue_label; | 3749 JumpTarget continue_label; |
3750 __ tst(r0, Operand(kSmiTagMask)); | 3750 __ tst(r0, Operand(kSmiTagMask)); |
3751 smi_label.Branch(eq); | 3751 smi_label.Branch(eq); |
3752 | 3752 |
3753 frame_->EmitPush(r0); | 3753 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); |
3754 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, 1); | 3754 frame_->CallStub(&stub, 0); |
| 3755 continue_label.Jump(); |
3755 | 3756 |
3756 continue_label.Jump(); | |
3757 smi_label.Bind(); | 3757 smi_label.Bind(); |
3758 __ mvn(r0, Operand(r0)); | 3758 __ mvn(r0, Operand(r0)); |
3759 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag | 3759 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag |
3760 continue_label.Bind(); | 3760 continue_label.Bind(); |
3761 break; | 3761 break; |
3762 } | 3762 } |
3763 | 3763 |
3764 case Token::VOID: | 3764 case Token::VOID: |
3765 // since the stack top is cached in r0, popping and then | 3765 // since the stack top is cached in r0, popping and then |
3766 // pushing a value can be done by just writing to r0. | 3766 // pushing a value can be done by just writing to r0. |
(...skipping 2303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6070 // argument, so give it a Smi. | 6070 // argument, so give it a Smi. |
6071 __ mov(r0, Operand(Smi::FromInt(0))); | 6071 __ mov(r0, Operand(Smi::FromInt(0))); |
6072 __ push(r0); | 6072 __ push(r0); |
6073 __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1, 1); | 6073 __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1, 1); |
6074 | 6074 |
6075 __ StubReturn(1); | 6075 __ StubReturn(1); |
6076 } | 6076 } |
6077 | 6077 |
6078 | 6078 |
6079 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { | 6079 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { |
6080 ASSERT(op_ == Token::SUB); | 6080 Label slow, done; |
6081 | 6081 |
6082 Label undo; | 6082 if (op_ == Token::SUB) { |
6083 Label slow; | 6083 // Check whether the value is a smi. |
6084 Label not_smi; | 6084 Label try_float; |
| 6085 __ tst(r0, Operand(kSmiTagMask)); |
| 6086 __ b(ne, &try_float); |
6085 | 6087 |
6086 // Enter runtime system if the value is not a smi. | 6088 // Go slow case if the value of the expression is zero |
6087 __ tst(r0, Operand(kSmiTagMask)); | 6089 // to make sure that we switch between 0 and -0. |
6088 __ b(ne, ¬_smi); | 6090 __ cmp(r0, Operand(0)); |
| 6091 __ b(eq, &slow); |
6089 | 6092 |
6090 // Enter runtime system if the value of the expression is zero | 6093 // The value of the expression is a smi that is not zero. Try |
6091 // to make sure that we switch between 0 and -0. | 6094 // optimistic subtraction '0 - value'. |
6092 __ cmp(r0, Operand(0)); | 6095 __ rsb(r1, r0, Operand(0), SetCC); |
6093 __ b(eq, &slow); | 6096 __ b(vs, &slow); |
6094 | 6097 |
6095 // The value of the expression is a smi that is not zero. Try | 6098 __ mov(r0, Operand(r1)); // Set r0 to result. |
6096 // optimistic subtraction '0 - value'. | 6099 __ b(&done); |
6097 __ rsb(r1, r0, Operand(0), SetCC); | |
6098 __ b(vs, &slow); | |
6099 | 6100 |
6100 __ mov(r0, Operand(r1)); // Set r0 to result. | 6101 __ bind(&try_float); |
| 6102 __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE); |
| 6103 __ b(ne, &slow); |
| 6104 // r0 is a heap number. Get a new heap number in r1. |
| 6105 if (overwrite_) { |
| 6106 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
| 6107 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. |
| 6108 __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
| 6109 } else { |
| 6110 AllocateHeapNumber(masm, &slow, r1, r2, r3); |
| 6111 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
| 6112 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
| 6113 __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset)); |
| 6114 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. |
| 6115 __ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset)); |
| 6116 __ mov(r0, Operand(r1)); |
| 6117 } |
| 6118 } else if (op_ == Token::BIT_NOT) { |
| 6119 // Check if the operand is a heap number. |
| 6120 __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE); |
| 6121 __ b(ne, &slow); |
| 6122 |
| 6123 // Convert the heap number is r0 to an untagged integer in r1. |
| 6124 GetInt32(masm, r0, r1, r2, r3, &slow); |
| 6125 |
| 6126 // Do the bitwise operation (move negated) and check if the result |
| 6127 // fits in a smi. |
| 6128 Label try_float; |
| 6129 __ mvn(r1, Operand(r1)); |
| 6130 __ add(r2, r1, Operand(0x40000000), SetCC); |
| 6131 __ b(mi, &try_float); |
| 6132 __ mov(r0, Operand(r1, LSL, kSmiTagSize)); |
| 6133 __ b(&done); |
| 6134 |
| 6135 __ bind(&try_float); |
| 6136 if (!overwrite_) { |
| 6137 // Allocate a fresh heap number, but don't overwrite r0 until |
| 6138 // we're sure we can do it without going through the slow case |
| 6139 // that needs the value in r0. |
| 6140 AllocateHeapNumber(masm, &slow, r2, r3, r4); |
| 6141 __ mov(r0, Operand(r2)); |
| 6142 } |
| 6143 |
| 6144 // WriteInt32ToHeapNumberStub does not trigger GC, so we do not |
| 6145 // have to set up a frame. |
| 6146 WriteInt32ToHeapNumberStub stub(r1, r0, r2); |
| 6147 __ push(lr); |
| 6148 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 6149 __ pop(lr); |
| 6150 } else { |
| 6151 UNIMPLEMENTED(); |
| 6152 } |
| 6153 |
| 6154 __ bind(&done); |
6101 __ StubReturn(1); | 6155 __ StubReturn(1); |
6102 | 6156 |
6103 // Enter runtime system. | 6157 // Handle the slow case by jumping to the JavaScript builtin. |
6104 __ bind(&slow); | 6158 __ bind(&slow); |
6105 __ push(r0); | 6159 __ push(r0); |
6106 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_JS); | 6160 switch (op_) { |
6107 | 6161 case Token::SUB: |
6108 __ bind(¬_smi); | 6162 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_JS); |
6109 __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE); | 6163 break; |
6110 __ b(ne, &slow); | 6164 case Token::BIT_NOT: |
6111 // r0 is a heap number. Get a new heap number in r1. | 6165 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_JS); |
6112 if (overwrite_) { | 6166 break; |
6113 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 6167 default: |
6114 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. | 6168 UNREACHABLE(); |
6115 __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | |
6116 } else { | |
6117 AllocateHeapNumber(masm, &slow, r1, r2, r3); | |
6118 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | |
6119 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | |
6120 __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset)); | |
6121 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. | |
6122 __ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset)); | |
6123 __ mov(r0, Operand(r1)); | |
6124 } | 6169 } |
6125 __ StubReturn(1); | |
6126 } | 6170 } |
6127 | 6171 |
6128 | 6172 |
6129 int CEntryStub::MinorKey() { | 6173 int CEntryStub::MinorKey() { |
6130 ASSERT(result_size_ <= 2); | 6174 ASSERT(result_size_ <= 2); |
6131 // Result returned in r0 or r0+r1 by default. | 6175 // Result returned in r0 or r0+r1 by default. |
6132 return 0; | 6176 return 0; |
6133 } | 6177 } |
6134 | 6178 |
6135 | 6179 |
(...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6870 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 6914 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
6871 // tagged as a small integer. | 6915 // tagged as a small integer. |
6872 __ bind(&runtime); | 6916 __ bind(&runtime); |
6873 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); | 6917 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); |
6874 } | 6918 } |
6875 | 6919 |
6876 | 6920 |
6877 #undef __ | 6921 #undef __ |
6878 | 6922 |
6879 } } // namespace v8::internal | 6923 } } // namespace v8::internal |
OLD | NEW |