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 6030 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6041 default: | 6041 default: |
6042 UNREACHABLE(); | 6042 UNREACHABLE(); |
6043 } | 6043 } |
6044 } | 6044 } |
6045 ASSERT(!has_valid_frame() || | 6045 ASSERT(!has_valid_frame() || |
6046 (has_cc() && frame_->height() == original_height) || | 6046 (has_cc() && frame_->height() == original_height) || |
6047 (!has_cc() && frame_->height() == original_height + 1)); | 6047 (!has_cc() && frame_->height() == original_height + 1)); |
6048 } | 6048 } |
6049 | 6049 |
6050 | 6050 |
6051 class DeferredCountOperation: public DeferredCode { | |
6052 public: | |
6053 DeferredCountOperation(Register value, | |
6054 bool is_increment, | |
6055 bool is_postfix, | |
6056 int target_size) | |
6057 : value_(value), | |
6058 is_increment_(is_increment), | |
6059 is_postfix_(is_postfix), | |
6060 target_size_(target_size) {} | |
6061 | |
6062 virtual void Generate() { | |
6063 VirtualFrame copied_frame(*frame_state()->frame()); | |
6064 | |
6065 Label slow; | |
6066 // Check for smi operand. | |
6067 __ tst(value_, Operand(kSmiTagMask)); | |
6068 __ b(ne, &slow); | |
6069 | |
6070 // Revert optimistic increment/decrement. | |
6071 if (is_increment_) { | |
6072 __ sub(value_, value_, Operand(Smi::FromInt(1))); | |
6073 } else { | |
6074 __ add(value_, value_, Operand(Smi::FromInt(1))); | |
6075 } | |
6076 | |
6077 // Slow case: Convert to number. At this point the | |
6078 // value to be incremented is in the value register.. | |
6079 __ bind(&slow); | |
6080 | |
6081 // Convert the operand to a number. | |
6082 copied_frame.EmitPush(value_); | |
6083 | |
6084 copied_frame.InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1); | |
6085 | |
6086 if (is_postfix_) { | |
6087 // Postfix: store to result (on the stack). | |
6088 __ str(r0, MemOperand(sp, target_size_ * kPointerSize)); | |
6089 } | |
6090 | |
6091 copied_frame.EmitPush(r0); | |
6092 copied_frame.EmitPush(Operand(Smi::FromInt(1))); | |
6093 | |
6094 if (is_increment_) { | |
6095 copied_frame.CallRuntime(Runtime::kNumberAdd, 2); | |
6096 } else { | |
6097 copied_frame.CallRuntime(Runtime::kNumberSub, 2); | |
6098 } | |
6099 | |
6100 if (!value_.is(r0)) | |
Erik Corry
2010/11/24 09:56:33
The 'if' is not needed. I corrected this.
| |
6101 __ Move(value_, r0); | |
6102 | |
6103 copied_frame.MergeTo(frame_state()->frame()); | |
6104 } | |
6105 | |
6106 private: | |
6107 Register value_; | |
6108 bool is_increment_; | |
6109 bool is_postfix_; | |
6110 int target_size_; | |
6111 }; | |
6112 | |
6113 | |
6051 void CodeGenerator::VisitCountOperation(CountOperation* node) { | 6114 void CodeGenerator::VisitCountOperation(CountOperation* node) { |
6052 #ifdef DEBUG | 6115 #ifdef DEBUG |
6053 int original_height = frame_->height(); | 6116 int original_height = frame_->height(); |
6054 #endif | 6117 #endif |
6055 Comment cmnt(masm_, "[ CountOperation"); | 6118 Comment cmnt(masm_, "[ CountOperation"); |
6056 VirtualFrame::RegisterAllocationScope scope(this); | 6119 VirtualFrame::RegisterAllocationScope scope(this); |
6057 | 6120 |
6058 bool is_postfix = node->is_postfix(); | 6121 bool is_postfix = node->is_postfix(); |
6059 bool is_increment = node->op() == Token::INC; | 6122 bool is_increment = node->op() == Token::INC; |
6060 | 6123 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6100 // than on entry). | 6163 // than on entry). |
6101 if (!placeholder_pushed) frame_->EmitPush(Operand(Smi::FromInt(0))); | 6164 if (!placeholder_pushed) frame_->EmitPush(Operand(Smi::FromInt(0))); |
6102 ASSERT_EQ(original_height + 1, frame_->height()); | 6165 ASSERT_EQ(original_height + 1, frame_->height()); |
6103 return; | 6166 return; |
6104 } | 6167 } |
6105 | 6168 |
6106 // This pushes 0, 1 or 2 words on the object to be used later when updating | 6169 // This pushes 0, 1 or 2 words on the object to be used later when updating |
6107 // the target. It also pushes the current value of the target. | 6170 // the target. It also pushes the current value of the target. |
6108 target.GetValue(); | 6171 target.GetValue(); |
6109 | 6172 |
6110 JumpTarget slow; | |
6111 JumpTarget exit; | |
6112 | |
6113 Register value = frame_->PopToRegister(); | 6173 Register value = frame_->PopToRegister(); |
6114 | 6174 |
6115 // Postfix: Store the old value as the result. | 6175 // Postfix: Store the old value as the result. |
6116 if (placeholder_pushed) { | 6176 if (placeholder_pushed) { |
6117 frame_->SetElementAt(value, target.size()); | 6177 frame_->SetElementAt(value, target.size()); |
6118 } else if (is_postfix) { | 6178 } else if (is_postfix) { |
6119 frame_->EmitPush(value); | 6179 frame_->EmitPush(value); |
6120 __ mov(VirtualFrame::scratch0(), value); | 6180 __ mov(VirtualFrame::scratch0(), value); |
6121 value = VirtualFrame::scratch0(); | 6181 value = VirtualFrame::scratch0(); |
6122 } | 6182 } |
6123 | 6183 |
6124 // Check for smi operand. | 6184 // Check for smi operand. |
6125 __ tst(value, Operand(kSmiTagMask)); | 6185 __ tst(value, Operand(kSmiTagMask)); |
6126 slow.Branch(ne); | 6186 |
6187 DeferredCode* deferred = | |
6188 new DeferredCountOperation(value, | |
6189 is_increment, | |
6190 is_postfix, | |
6191 target.size()); | |
6192 deferred->Branch(ne); | |
6127 | 6193 |
6128 // Perform optimistic increment/decrement. | 6194 // Perform optimistic increment/decrement. |
6129 if (is_increment) { | 6195 if (is_increment) { |
6130 __ add(value, value, Operand(Smi::FromInt(1)), SetCC); | 6196 __ add(value, value, Operand(Smi::FromInt(1)), SetCC); |
6131 } else { | 6197 } else { |
6132 __ sub(value, value, Operand(Smi::FromInt(1)), SetCC); | 6198 __ sub(value, value, Operand(Smi::FromInt(1)), SetCC); |
6133 } | 6199 } |
6134 | 6200 |
6135 // If the increment/decrement didn't overflow, we're done. | 6201 // If increment/decrement overflows, go to deferred code. |
6136 exit.Branch(vc); | 6202 deferred->Branch(vs); |
6137 | 6203 |
6138 // Revert optimistic increment/decrement. | 6204 deferred->BindExit(); |
6139 if (is_increment) { | |
6140 __ sub(value, value, Operand(Smi::FromInt(1))); | |
6141 } else { | |
6142 __ add(value, value, Operand(Smi::FromInt(1))); | |
6143 } | |
6144 | 6205 |
6145 // Slow case: Convert to number. At this point the | |
6146 // value to be incremented is in the value register.. | |
6147 slow.Bind(); | |
6148 | |
6149 // Convert the operand to a number. | |
6150 frame_->EmitPush(value); | |
6151 | |
6152 { | |
6153 VirtualFrame::SpilledScope spilled(frame_); | |
6154 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1); | |
6155 | |
6156 if (is_postfix) { | |
6157 // Postfix: store to result (on the stack). | |
6158 __ str(r0, frame_->ElementAt(target.size())); | |
6159 } | |
6160 | |
6161 // Compute the new value. | |
6162 frame_->EmitPush(r0); | |
6163 frame_->EmitPush(Operand(Smi::FromInt(1))); | |
6164 if (is_increment) { | |
6165 frame_->CallRuntime(Runtime::kNumberAdd, 2); | |
6166 } else { | |
6167 frame_->CallRuntime(Runtime::kNumberSub, 2); | |
6168 } | |
6169 } | |
6170 | |
6171 __ Move(value, r0); | |
6172 // Store the new value in the target if not const. | 6206 // Store the new value in the target if not const. |
6173 // At this point the answer is in the value register. | 6207 // At this point the answer is in the value register. |
6174 exit.Bind(); | |
6175 frame_->EmitPush(value); | 6208 frame_->EmitPush(value); |
6176 // Set the target with the result, leaving the result on | 6209 // Set the target with the result, leaving the result on |
6177 // top of the stack. Removes the target from the stack if | 6210 // top of the stack. Removes the target from the stack if |
6178 // it has a non-zero size. | 6211 // it has a non-zero size. |
6179 if (!is_const) target.SetValue(NOT_CONST_INIT, LIKELY_SMI); | 6212 if (!is_const) target.SetValue(NOT_CONST_INIT, LIKELY_SMI); |
6180 } | 6213 } |
6181 | 6214 |
6182 // Postfix: Discard the new value and use the old. | 6215 // Postfix: Discard the new value and use the old. |
6183 if (is_postfix) frame_->Pop(); | 6216 if (is_postfix) frame_->Pop(); |
6184 ASSERT_EQ(original_height + 1, frame_->height()); | 6217 ASSERT_EQ(original_height + 1, frame_->height()); |
(...skipping 1119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7304 BinaryOpIC::GetName(runtime_operands_type_)); | 7337 BinaryOpIC::GetName(runtime_operands_type_)); |
7305 return name_; | 7338 return name_; |
7306 } | 7339 } |
7307 | 7340 |
7308 | 7341 |
7309 #undef __ | 7342 #undef __ |
7310 | 7343 |
7311 } } // namespace v8::internal | 7344 } } // namespace v8::internal |
7312 | 7345 |
7313 #endif // V8_TARGET_ARCH_ARM | 7346 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |