OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 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 5174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5185 Label add_success; | 5185 Label add_success; |
5186 __ j(no_overflow, &add_success); | 5186 __ j(no_overflow, &add_success); |
5187 __ addl(operand->reg(), Immediate(smi_value)); | 5187 __ addl(operand->reg(), Immediate(smi_value)); |
5188 deferred->Jump(); | 5188 deferred->Jump(); |
5189 __ bind(&add_success); | 5189 __ bind(&add_success); |
5190 deferred->BindExit(); | 5190 deferred->BindExit(); |
5191 frame_->Push(operand); | 5191 frame_->Push(operand); |
5192 } | 5192 } |
5193 break; | 5193 break; |
5194 } | 5194 } |
5195 // TODO(X64): Move other implementations from ia32 to here. | 5195 |
| 5196 case Token::SAR: |
| 5197 if (reversed) { |
| 5198 Result constant_operand(value); |
| 5199 LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 5200 overwrite_mode); |
| 5201 } else { |
| 5202 // Only the least significant 5 bits of the shift value are used. |
| 5203 // In the slow case, this masking is done inside the runtime call. |
| 5204 int shift_value = int_value & 0x1f; |
| 5205 operand->ToRegister(); |
| 5206 frame_->Spill(operand->reg()); |
| 5207 DeferredInlineSmiOperation* deferred = |
| 5208 new DeferredInlineSmiOperation(op, |
| 5209 operand->reg(), |
| 5210 operand->reg(), |
| 5211 smi_value, |
| 5212 overwrite_mode); |
| 5213 __ testl(operand->reg(), Immediate(kSmiTagMask)); |
| 5214 deferred->Branch(not_zero); |
| 5215 if (shift_value > 0) { |
| 5216 __ sarl(operand->reg(), Immediate(shift_value)); |
| 5217 __ and_(operand->reg(), Immediate(~kSmiTagMask)); |
| 5218 } |
| 5219 deferred->BindExit(); |
| 5220 frame_->Push(operand); |
| 5221 } |
| 5222 break; |
| 5223 |
| 5224 case Token::SHR: |
| 5225 if (reversed) { |
| 5226 Result constant_operand(value); |
| 5227 LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 5228 overwrite_mode); |
| 5229 } else { |
| 5230 // Only the least significant 5 bits of the shift value are used. |
| 5231 // In the slow case, this masking is done inside the runtime call. |
| 5232 int shift_value = int_value & 0x1f; |
| 5233 operand->ToRegister(); |
| 5234 Result answer = allocator()->Allocate(); |
| 5235 ASSERT(answer.is_valid()); |
| 5236 DeferredInlineSmiOperation* deferred = |
| 5237 new DeferredInlineSmiOperation(op, |
| 5238 answer.reg(), |
| 5239 operand->reg(), |
| 5240 smi_value, |
| 5241 overwrite_mode); |
| 5242 __ testl(operand->reg(), Immediate(kSmiTagMask)); |
| 5243 deferred->Branch(not_zero); |
| 5244 __ movl(answer.reg(), operand->reg()); |
| 5245 __ sarl(answer.reg(), Immediate(kSmiTagSize)); |
| 5246 __ shrl(answer.reg(), Immediate(shift_value)); |
| 5247 // A negative Smi shifted right two is in the positive Smi range. |
| 5248 if (shift_value < 2) { |
| 5249 __ testl(answer.reg(), Immediate(0xc0000000)); |
| 5250 deferred->Branch(not_zero); |
| 5251 } |
| 5252 operand->Unuse(); |
| 5253 ASSERT(kSmiTagSize == times_2); // Adjust the code if not true. |
| 5254 __ lea(answer.reg(), |
| 5255 Operand(answer.reg(), answer.reg(), times_1, kSmiTag)); |
| 5256 deferred->BindExit(); |
| 5257 frame_->Push(&answer); |
| 5258 } |
| 5259 break; |
| 5260 |
| 5261 case Token::SHL: |
| 5262 if (reversed) { |
| 5263 Result constant_operand(value); |
| 5264 LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 5265 overwrite_mode); |
| 5266 } else { |
| 5267 // Only the least significant 5 bits of the shift value are used. |
| 5268 // In the slow case, this masking is done inside the runtime call. |
| 5269 int shift_value = int_value & 0x1f; |
| 5270 operand->ToRegister(); |
| 5271 if (shift_value == 0) { |
| 5272 // Spill operand so it can be overwritten in the slow case. |
| 5273 frame_->Spill(operand->reg()); |
| 5274 DeferredInlineSmiOperation* deferred = |
| 5275 new DeferredInlineSmiOperation(op, |
| 5276 operand->reg(), |
| 5277 operand->reg(), |
| 5278 smi_value, |
| 5279 overwrite_mode); |
| 5280 __ testl(operand->reg(), Immediate(kSmiTagMask)); |
| 5281 deferred->Branch(not_zero); |
| 5282 deferred->BindExit(); |
| 5283 frame_->Push(operand); |
| 5284 } else { |
| 5285 // Use a fresh temporary for nonzero shift values. |
| 5286 Result answer = allocator()->Allocate(); |
| 5287 ASSERT(answer.is_valid()); |
| 5288 DeferredInlineSmiOperation* deferred = |
| 5289 new DeferredInlineSmiOperation(op, |
| 5290 answer.reg(), |
| 5291 operand->reg(), |
| 5292 smi_value, |
| 5293 overwrite_mode); |
| 5294 __ testl(operand->reg(), Immediate(kSmiTagMask)); |
| 5295 deferred->Branch(not_zero); |
| 5296 __ movl(answer.reg(), operand->reg()); |
| 5297 ASSERT(kSmiTag == 0); // adjust code if not the case |
| 5298 // We do no shifts, only the Smi conversion, if shift_value is 1. |
| 5299 if (shift_value > 1) { |
| 5300 __ shll(answer.reg(), Immediate(shift_value - 1)); |
| 5301 } |
| 5302 // Convert int result to Smi, checking that it is in int range. |
| 5303 ASSERT(kSmiTagSize == 1); // adjust code if not the case |
| 5304 __ addl(answer.reg(), answer.reg()); |
| 5305 deferred->Branch(overflow); |
| 5306 deferred->BindExit(); |
| 5307 operand->Unuse(); |
| 5308 frame_->Push(&answer); |
| 5309 } |
| 5310 } |
| 5311 break; |
| 5312 |
| 5313 case Token::BIT_OR: |
| 5314 case Token::BIT_XOR: |
| 5315 case Token::BIT_AND: { |
| 5316 operand->ToRegister(); |
| 5317 frame_->Spill(operand->reg()); |
| 5318 if (reversed) { |
| 5319 // Bit operations with a constant smi are commutative. |
| 5320 // We can swap left and right operands with no problem. |
| 5321 // Swap left and right overwrite modes. 0->0, 1->2, 2->1. |
| 5322 overwrite_mode = static_cast<OverwriteMode>((2 * overwrite_mode) % 3); |
| 5323 } |
| 5324 DeferredCode* deferred = new DeferredInlineSmiOperation(op, |
| 5325 operand->reg(), |
| 5326 operand->reg(), |
| 5327 smi_value, |
| 5328 overwrite_mode); |
| 5329 __ testl(operand->reg(), Immediate(kSmiTagMask)); |
| 5330 deferred->Branch(not_zero); |
| 5331 if (op == Token::BIT_AND) { |
| 5332 __ and_(operand->reg(), Immediate(smi_value)); |
| 5333 } else if (op == Token::BIT_XOR) { |
| 5334 if (int_value != 0) { |
| 5335 __ xor_(operand->reg(), Immediate(smi_value)); |
| 5336 } |
| 5337 } else { |
| 5338 ASSERT(op == Token::BIT_OR); |
| 5339 if (int_value != 0) { |
| 5340 __ or_(operand->reg(), Immediate(smi_value)); |
| 5341 } |
| 5342 } |
| 5343 deferred->BindExit(); |
| 5344 frame_->Push(operand); |
| 5345 break; |
| 5346 } |
5196 | 5347 |
5197 // Generate inline code for mod of powers of 2 and negative powers of 2. | 5348 // Generate inline code for mod of powers of 2 and negative powers of 2. |
5198 case Token::MOD: | 5349 case Token::MOD: |
5199 if (!reversed && | 5350 if (!reversed && |
5200 int_value != 0 && | 5351 int_value != 0 && |
5201 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { | 5352 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { |
5202 operand->ToRegister(); | 5353 operand->ToRegister(); |
5203 frame_->Spill(operand->reg()); | 5354 frame_->Spill(operand->reg()); |
5204 DeferredCode* deferred = new DeferredInlineSmiOperation(op, | 5355 DeferredCode* deferred = new DeferredInlineSmiOperation(op, |
5205 operand->reg(), | 5356 operand->reg(), |
(...skipping 2335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7541 int CompareStub::MinorKey() { | 7692 int CompareStub::MinorKey() { |
7542 // Encode the two parameters in a unique 16 bit value. | 7693 // Encode the two parameters in a unique 16 bit value. |
7543 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); | 7694 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); |
7544 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); | 7695 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); |
7545 } | 7696 } |
7546 | 7697 |
7547 | 7698 |
7548 #undef __ | 7699 #undef __ |
7549 | 7700 |
7550 } } // namespace v8::internal | 7701 } } // namespace v8::internal |
OLD | NEW |