| 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 5240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5251 } | 5251 } |
| 5252 operand->Unuse(); | 5252 operand->Unuse(); |
| 5253 ASSERT(kSmiTag == 0); | 5253 ASSERT(kSmiTag == 0); |
| 5254 ASSERT(kSmiTagSize == 1); | 5254 ASSERT(kSmiTagSize == 1); |
| 5255 __ addl(answer.reg(), answer.reg()); | 5255 __ addl(answer.reg(), answer.reg()); |
| 5256 deferred->BindExit(); | 5256 deferred->BindExit(); |
| 5257 frame_->Push(&answer); | 5257 frame_->Push(&answer); |
| 5258 } | 5258 } |
| 5259 break; | 5259 break; |
| 5260 | 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 |
| 5261 case Token::BIT_OR: | 5313 case Token::BIT_OR: |
| 5262 case Token::BIT_XOR: | 5314 case Token::BIT_XOR: |
| 5263 case Token::BIT_AND: { | 5315 case Token::BIT_AND: { |
| 5264 operand->ToRegister(); | 5316 operand->ToRegister(); |
| 5265 frame_->Spill(operand->reg()); | 5317 frame_->Spill(operand->reg()); |
| 5266 if (reversed) { | 5318 if (reversed) { |
| 5267 // Bit operations with a constant smi are commutative. | 5319 // Bit operations with a constant smi are commutative. |
| 5268 // We can swap left and right operands with no problem. | 5320 // We can swap left and right operands with no problem. |
| 5269 // Swap left and right overwrite modes. 0->0, 1->2, 2->1. | 5321 // Swap left and right overwrite modes. 0->0, 1->2, 2->1. |
| 5270 overwrite_mode = static_cast<OverwriteMode>((2 * overwrite_mode) % 3); | 5322 overwrite_mode = static_cast<OverwriteMode>((2 * overwrite_mode) % 3); |
| (...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6006 // We can skip the write barrier for smis and constants. | 6058 // We can skip the write barrier for smis and constants. |
| 6007 if (!value_is_constant) { | 6059 if (!value_is_constant) { |
| 6008 __ testl(value.reg(), Immediate(kSmiTagMask)); | 6060 __ testl(value.reg(), Immediate(kSmiTagMask)); |
| 6009 deferred->Branch(not_zero); | 6061 deferred->Branch(not_zero); |
| 6010 } | 6062 } |
| 6011 | 6063 |
| 6012 // Check that the key is a non-negative smi. | 6064 // Check that the key is a non-negative smi. |
| 6013 __ testl(key.reg(), | 6065 __ testl(key.reg(), |
| 6014 Immediate(static_cast<uint32_t>(kSmiTagMask | 0x80000000U))); | 6066 Immediate(static_cast<uint32_t>(kSmiTagMask | 0x80000000U))); |
| 6015 deferred->Branch(not_zero); | 6067 deferred->Branch(not_zero); |
| 6068 // Ensure that the smi is zero-extended. This is not guaranteed. |
| 6069 __ movl(key.reg(), key.reg()); |
| 6016 | 6070 |
| 6017 // Check that the receiver is not a smi. | 6071 // Check that the receiver is not a smi. |
| 6018 __ testl(receiver.reg(), Immediate(kSmiTagMask)); | 6072 __ testl(receiver.reg(), Immediate(kSmiTagMask)); |
| 6019 deferred->Branch(zero); | 6073 deferred->Branch(zero); |
| 6020 | 6074 |
| 6021 // Check that the receiver is a JSArray. | 6075 // Check that the receiver is a JSArray. |
| 6022 __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister); | 6076 __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister); |
| 6023 deferred->Branch(not_equal); | 6077 deferred->Branch(not_equal); |
| 6024 | 6078 |
| 6025 // Check that the key is within bounds. Both the key and the | 6079 // Check that the key is within bounds. Both the key and the |
| (...skipping 1139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7165 __ fld_d(FieldOperand(kScratchRegister, HeapNumber::kValueOffset)); | 7219 __ fld_d(FieldOperand(kScratchRegister, HeapNumber::kValueOffset)); |
| 7166 __ bind(&done_load_1); | 7220 __ bind(&done_load_1); |
| 7167 | 7221 |
| 7168 __ movq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); | 7222 __ movq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); |
| 7169 __ testl(kScratchRegister, Immediate(kSmiTagMask)); | 7223 __ testl(kScratchRegister, Immediate(kSmiTagMask)); |
| 7170 __ j(zero, &load_smi_2); | 7224 __ j(zero, &load_smi_2); |
| 7171 __ fld_d(FieldOperand(kScratchRegister, HeapNumber::kValueOffset)); | 7225 __ fld_d(FieldOperand(kScratchRegister, HeapNumber::kValueOffset)); |
| 7172 __ jmp(&done); | 7226 __ jmp(&done); |
| 7173 | 7227 |
| 7174 __ bind(&load_smi_1); | 7228 __ bind(&load_smi_1); |
| 7175 __ sar(kScratchRegister, Immediate(kSmiTagSize)); | 7229 __ sarl(kScratchRegister, Immediate(kSmiTagSize)); |
| 7176 __ push(kScratchRegister); | 7230 __ push(kScratchRegister); |
| 7177 __ fild_s(Operand(rsp, 0)); | 7231 __ fild_s(Operand(rsp, 0)); |
| 7178 __ pop(kScratchRegister); | 7232 __ pop(kScratchRegister); |
| 7179 __ jmp(&done_load_1); | 7233 __ jmp(&done_load_1); |
| 7180 | 7234 |
| 7181 __ bind(&load_smi_2); | 7235 __ bind(&load_smi_2); |
| 7182 __ sar(kScratchRegister, Immediate(kSmiTagSize)); | 7236 __ sarl(kScratchRegister, Immediate(kSmiTagSize)); |
| 7183 __ push(kScratchRegister); | 7237 __ push(kScratchRegister); |
| 7184 __ fild_s(Operand(rsp, 0)); | 7238 __ fild_s(Operand(rsp, 0)); |
| 7185 __ pop(kScratchRegister); | 7239 __ pop(kScratchRegister); |
| 7186 | 7240 |
| 7187 __ bind(&done); | 7241 __ bind(&done); |
| 7188 } | 7242 } |
| 7189 | 7243 |
| 7190 | 7244 |
| 7191 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | 7245 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, |
| 7192 Register lhs, | 7246 Register lhs, |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7527 if (op_ == Token::SHR) { | 7581 if (op_ == Token::SHR) { |
| 7528 // Check if result is non-negative and fits in a smi. | 7582 // Check if result is non-negative and fits in a smi. |
| 7529 __ testl(rax, Immediate(0xc0000000)); | 7583 __ testl(rax, Immediate(0xc0000000)); |
| 7530 __ j(not_zero, &non_smi_result); | 7584 __ j(not_zero, &non_smi_result); |
| 7531 } else { | 7585 } else { |
| 7532 // Check if result fits in a smi. | 7586 // Check if result fits in a smi. |
| 7533 __ cmpl(rax, Immediate(0xc0000000)); | 7587 __ cmpl(rax, Immediate(0xc0000000)); |
| 7534 __ j(negative, &non_smi_result); | 7588 __ j(negative, &non_smi_result); |
| 7535 } | 7589 } |
| 7536 // Tag smi result and return. | 7590 // Tag smi result and return. |
| 7537 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 7591 ASSERT(kSmiTagSize == 1); // adjust code if not the case |
| 7538 __ lea(rax, Operand(rax, rax, times_1, kSmiTag)); | 7592 __ lea(rax, Operand(rax, rax, times_1, kSmiTag)); |
| 7539 __ ret(2 * kPointerSize); | 7593 __ ret(2 * kPointerSize); |
| 7540 | 7594 |
| 7541 // All ops except SHR return a signed int32 that we load in a HeapNumber. | 7595 // All ops except SHR return a signed int32 that we load in a HeapNumber. |
| 7542 if (op_ != Token::SHR) { | 7596 if (op_ != Token::SHR) { |
| 7543 __ bind(&non_smi_result); | 7597 __ bind(&non_smi_result); |
| 7544 // Allocate a heap number if needed. | 7598 // Allocate a heap number if needed. |
| 7545 __ movsxlq(rbx, rax); // rbx: sign extended 32-bit result | 7599 __ movsxlq(rbx, rax); // rbx: sign extended 32-bit result |
| 7546 switch (mode_) { | 7600 switch (mode_) { |
| 7547 case OVERWRITE_LEFT: | 7601 case OVERWRITE_LEFT: |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7640 int CompareStub::MinorKey() { | 7694 int CompareStub::MinorKey() { |
| 7641 // Encode the two parameters in a unique 16 bit value. | 7695 // Encode the two parameters in a unique 16 bit value. |
| 7642 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); | 7696 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); |
| 7643 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); | 7697 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); |
| 7644 } | 7698 } |
| 7645 | 7699 |
| 7646 | 7700 |
| 7647 #undef __ | 7701 #undef __ |
| 7648 | 7702 |
| 7649 } } // namespace v8::internal | 7703 } } // namespace v8::internal |
| OLD | NEW |