Chromium Code Reviews| 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 |