| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 ASSERT(info()->IsStub()); | 434 ASSERT(info()->IsStub()); |
| 435 frame_is_built_ = true; | 435 frame_is_built_ = true; |
| 436 // Build the frame in such a way that esi isn't trashed. | 436 // Build the frame in such a way that esi isn't trashed. |
| 437 __ push(ebp); // Caller's frame pointer. | 437 __ push(ebp); // Caller's frame pointer. |
| 438 __ push(Operand(ebp, StandardFrameConstants::kContextOffset)); | 438 __ push(Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 439 __ push(Immediate(Smi::FromInt(StackFrame::STUB))); | 439 __ push(Immediate(Smi::FromInt(StackFrame::STUB))); |
| 440 __ lea(ebp, Operand(esp, 2 * kPointerSize)); | 440 __ lea(ebp, Operand(esp, 2 * kPointerSize)); |
| 441 Comment(";;; Deferred code"); | 441 Comment(";;; Deferred code"); |
| 442 } | 442 } |
| 443 code->Generate(); | 443 code->Generate(); |
| 444 __ bind(code->done()); |
| 444 if (NeedsDeferredFrame()) { | 445 if (NeedsDeferredFrame()) { |
| 445 Comment(";;; Destroy frame"); | 446 Comment(";;; Destroy frame"); |
| 446 ASSERT(frame_is_built_); | 447 ASSERT(frame_is_built_); |
| 447 frame_is_built_ = false; | 448 frame_is_built_ = false; |
| 448 __ mov(esp, ebp); | 449 __ mov(esp, ebp); |
| 449 __ pop(ebp); | 450 __ pop(ebp); |
| 450 } | 451 } |
| 451 __ jmp(code->exit()); | 452 __ jmp(code->exit()); |
| 452 } | 453 } |
| 453 } | 454 } |
| (...skipping 4871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5325 | 5326 |
| 5326 // Smi to XMM conversion | 5327 // Smi to XMM conversion |
| 5327 __ bind(&load_smi); | 5328 __ bind(&load_smi); |
| 5328 __ SmiUntag(input_reg); // Untag smi before converting to float. | 5329 __ SmiUntag(input_reg); // Untag smi before converting to float. |
| 5329 __ cvtsi2sd(result_reg, Operand(input_reg)); | 5330 __ cvtsi2sd(result_reg, Operand(input_reg)); |
| 5330 __ SmiTag(input_reg); // Retag smi. | 5331 __ SmiTag(input_reg); // Retag smi. |
| 5331 __ bind(&done); | 5332 __ bind(&done); |
| 5332 } | 5333 } |
| 5333 | 5334 |
| 5334 | 5335 |
| 5335 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 5336 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { |
| 5336 Label done, heap_number; | |
| 5337 Register input_reg = ToRegister(instr->value()); | 5337 Register input_reg = ToRegister(instr->value()); |
| 5338 | 5338 |
| 5339 // Heap number map check. | |
| 5340 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | |
| 5341 factory()->heap_number_map()); | |
| 5342 | 5339 |
| 5343 if (instr->truncating()) { | 5340 if (instr->truncating()) { |
| 5341 Label heap_number, slow_case; |
| 5342 |
| 5343 // Heap number map check. |
| 5344 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 5345 factory()->heap_number_map()); |
| 5344 __ j(equal, &heap_number, Label::kNear); | 5346 __ j(equal, &heap_number, Label::kNear); |
| 5347 |
| 5345 // Check for undefined. Undefined is converted to zero for truncating | 5348 // Check for undefined. Undefined is converted to zero for truncating |
| 5346 // conversions. | 5349 // conversions. |
| 5347 __ cmp(input_reg, factory()->undefined_value()); | 5350 __ cmp(input_reg, factory()->undefined_value()); |
| 5348 __ RecordComment("Deferred TaggedToI: cannot truncate"); | 5351 __ RecordComment("Deferred TaggedToI: cannot truncate"); |
| 5349 DeoptimizeIf(not_equal, instr->environment()); | 5352 DeoptimizeIf(not_equal, instr->environment()); |
| 5350 __ mov(input_reg, 0); | 5353 __ mov(input_reg, 0); |
| 5351 __ jmp(&done, Label::kNear); | 5354 __ jmp(done); |
| 5352 | 5355 |
| 5353 __ bind(&heap_number); | 5356 __ bind(&heap_number); |
| 5354 if (CpuFeatures::IsSupported(SSE3)) { | 5357 __ TruncateHeapNumberToI(input_reg, input_reg); |
| 5355 CpuFeatureScope scope(masm(), SSE3); | 5358 } else { |
| 5356 Label convert; | 5359 Label bailout; |
| 5357 // Use more powerful conversion when sse3 is available. | 5360 if (instr->temp() == NULL) { |
| 5358 // Load x87 register with heap number. | 5361 __ TaggedToI(input_reg, input_reg, |
| 5359 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | 5362 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero), |
| 5360 // Get exponent alone and check for too-big exponent. | 5363 &bailout, done); |
| 5361 __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | |
| 5362 __ and_(input_reg, HeapNumber::kExponentMask); | |
| 5363 const uint32_t kTooBigExponent = | |
| 5364 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; | |
| 5365 __ cmp(Operand(input_reg), Immediate(kTooBigExponent)); | |
| 5366 __ j(less, &convert, Label::kNear); | |
| 5367 // Pop FPU stack before deoptimizing. | |
| 5368 __ fstp(0); | |
| 5369 __ RecordComment("Deferred TaggedToI: exponent too big"); | |
| 5370 DeoptimizeIf(no_condition, instr->environment()); | |
| 5371 | |
| 5372 // Reserve space for 64 bit answer. | |
| 5373 __ bind(&convert); | |
| 5374 __ sub(Operand(esp), Immediate(kDoubleSize)); | |
| 5375 // Do conversion, which cannot fail because we checked the exponent. | |
| 5376 __ fisttp_d(Operand(esp, 0)); | |
| 5377 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. | |
| 5378 __ add(Operand(esp), Immediate(kDoubleSize)); | |
| 5379 } else if (CpuFeatures::IsSupported(SSE2)) { | |
| 5380 CpuFeatureScope scope(masm(), SSE2); | |
| 5381 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); | |
| 5382 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
| 5383 __ cvttsd2si(input_reg, Operand(xmm0)); | |
| 5384 __ cmp(input_reg, 0x80000000u); | |
| 5385 __ j(not_equal, &done); | |
| 5386 // Check if the input was 0x8000000 (kMinInt). | |
| 5387 // If no, then we got an overflow and we deoptimize. | |
| 5388 ExternalReference min_int = ExternalReference::address_of_min_int(); | |
| 5389 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); | |
| 5390 __ ucomisd(xmm_temp, xmm0); | |
| 5391 DeoptimizeIf(not_equal, instr->environment()); | |
| 5392 DeoptimizeIf(parity_even, instr->environment()); // NaN. | |
| 5393 } else { | 5364 } else { |
| 5394 UNREACHABLE(); | 5365 __ TaggedToI(input_reg, input_reg, ToDoubleRegister(instr->temp()), |
| 5366 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero), |
| 5367 &bailout, done); |
| 5395 } | 5368 } |
| 5396 } else if (CpuFeatures::IsSupported(SSE2)) { | 5369 __ bind(&bailout); |
| 5397 CpuFeatureScope scope(masm(), SSE2); | 5370 DeoptimizeIf(no_condition, instr->environment()); |
| 5398 // Deoptimize if we don't have a heap number. | |
| 5399 __ RecordComment("Deferred TaggedToI: not a heap number"); | |
| 5400 DeoptimizeIf(not_equal, instr->environment()); | |
| 5401 | |
| 5402 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); | |
| 5403 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
| 5404 __ cvttsd2si(input_reg, Operand(xmm0)); | |
| 5405 __ cvtsi2sd(xmm_temp, Operand(input_reg)); | |
| 5406 __ ucomisd(xmm0, xmm_temp); | |
| 5407 __ RecordComment("Deferred TaggedToI: lost precision"); | |
| 5408 DeoptimizeIf(not_equal, instr->environment()); | |
| 5409 __ RecordComment("Deferred TaggedToI: NaN"); | |
| 5410 DeoptimizeIf(parity_even, instr->environment()); // NaN. | |
| 5411 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
| 5412 __ test(input_reg, Operand(input_reg)); | |
| 5413 __ j(not_zero, &done); | |
| 5414 __ movmskpd(input_reg, xmm0); | |
| 5415 __ and_(input_reg, 1); | |
| 5416 __ RecordComment("Deferred TaggedToI: minus zero"); | |
| 5417 DeoptimizeIf(not_zero, instr->environment()); | |
| 5418 } | |
| 5419 } else { | |
| 5420 UNREACHABLE(); | |
| 5421 } | 5371 } |
| 5422 __ bind(&done); | |
| 5423 } | 5372 } |
| 5424 | 5373 |
| 5425 | 5374 |
| 5426 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 5375 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 5427 class DeferredTaggedToI: public LDeferredCode { | 5376 class DeferredTaggedToI: public LDeferredCode { |
| 5428 public: | 5377 public: |
| 5429 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 5378 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 5430 : LDeferredCode(codegen), instr_(instr) { } | 5379 : LDeferredCode(codegen), instr_(instr) { } |
| 5431 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 5380 virtual void Generate() { |
| 5381 codegen()->DoDeferredTaggedToI(instr_, done()); |
| 5382 } |
| 5432 virtual LInstruction* instr() { return instr_; } | 5383 virtual LInstruction* instr() { return instr_; } |
| 5433 private: | 5384 private: |
| 5434 LTaggedToI* instr_; | 5385 LTaggedToI* instr_; |
| 5435 }; | 5386 }; |
| 5436 | 5387 |
| 5437 LOperand* input = instr->value(); | 5388 LOperand* input = instr->value(); |
| 5438 ASSERT(input->IsRegister()); | 5389 ASSERT(input->IsRegister()); |
| 5439 Register input_reg = ToRegister(input); | 5390 Register input_reg = ToRegister(input); |
| 5440 ASSERT(input_reg.is(ToRegister(instr->result()))); | 5391 ASSERT(input_reg.is(ToRegister(instr->result()))); |
| 5441 | 5392 |
| 5442 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); | 5393 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); |
| 5443 | 5394 |
| 5444 __ JumpIfNotSmi(input_reg, deferred->entry()); | 5395 __ JumpIfNotSmi(input_reg, deferred->entry()); |
| 5445 __ SmiUntag(input_reg); | 5396 __ SmiUntag(input_reg); |
| 5446 __ bind(deferred->exit()); | 5397 __ bind(deferred->exit()); |
| 5447 } | 5398 } |
| 5448 | 5399 |
| 5449 | 5400 |
| 5450 void LCodeGen::DoDeferredTaggedToINoSSE2(LTaggedToINoSSE2* instr) { | |
| 5451 Label done, heap_number; | |
| 5452 Register result_reg = ToRegister(instr->result()); | |
| 5453 Register input_reg = ToRegister(instr->value()); | |
| 5454 | |
| 5455 // Heap number map check. | |
| 5456 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | |
| 5457 factory()->heap_number_map()); | |
| 5458 if (instr->truncating()) { | |
| 5459 __ j(equal, &heap_number, Label::kNear); | |
| 5460 // Check for undefined. Undefined is converted to zero for truncating | |
| 5461 // conversions. | |
| 5462 __ cmp(input_reg, factory()->undefined_value()); | |
| 5463 __ RecordComment("Deferred TaggedToI: cannot truncate"); | |
| 5464 DeoptimizeIf(not_equal, instr->environment()); | |
| 5465 __ xor_(result_reg, result_reg); | |
| 5466 __ jmp(&done, Label::kFar); | |
| 5467 __ bind(&heap_number); | |
| 5468 } else { | |
| 5469 // Deoptimize if we don't have a heap number. | |
| 5470 DeoptimizeIf(not_equal, instr->environment()); | |
| 5471 } | |
| 5472 | |
| 5473 // Surprisingly, all of this crazy bit manipulation is considerably | |
| 5474 // faster than using the built-in x86 CPU conversion functions (about 6x). | |
| 5475 Label right_exponent, adjust_bias, zero_result; | |
| 5476 Register scratch = ToRegister(instr->scratch()); | |
| 5477 Register scratch2 = ToRegister(instr->scratch2()); | |
| 5478 // Get exponent word. | |
| 5479 __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | |
| 5480 // Get exponent alone in scratch2. | |
| 5481 __ mov(scratch2, scratch); | |
| 5482 __ and_(scratch2, HeapNumber::kExponentMask); | |
| 5483 __ shr(scratch2, HeapNumber::kExponentShift); | |
| 5484 if (instr->truncating()) { | |
| 5485 __ j(zero, &zero_result); | |
| 5486 } else { | |
| 5487 __ j(not_zero, &adjust_bias); | |
| 5488 __ test(scratch, Immediate(HeapNumber::kMantissaMask)); | |
| 5489 DeoptimizeIf(not_zero, instr->environment()); | |
| 5490 __ cmp(FieldOperand(input_reg, HeapNumber::kMantissaOffset), Immediate(0)); | |
| 5491 DeoptimizeIf(not_equal, instr->environment()); | |
| 5492 __ bind(&adjust_bias); | |
| 5493 } | |
| 5494 __ sub(scratch2, Immediate(HeapNumber::kExponentBias)); | |
| 5495 if (!instr->truncating()) { | |
| 5496 DeoptimizeIf(negative, instr->environment()); | |
| 5497 } else { | |
| 5498 __ j(negative, &zero_result); | |
| 5499 } | |
| 5500 | |
| 5501 // Get the second half of the double. For some exponents we don't | |
| 5502 // actually need this because the bits get shifted out again, but | |
| 5503 // it's probably slower to test than just to do it. | |
| 5504 Register scratch3 = ToRegister(instr->scratch3()); | |
| 5505 __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); | |
| 5506 __ xor_(result_reg, result_reg); | |
| 5507 | |
| 5508 const uint32_t non_int32_exponent = 31; | |
| 5509 __ cmp(scratch2, Immediate(non_int32_exponent)); | |
| 5510 // If we have a match of the int32 exponent then skip some logic. | |
| 5511 __ j(equal, &right_exponent, Label::kNear); | |
| 5512 // If the number doesn't find in an int32, deopt. | |
| 5513 DeoptimizeIf(greater, instr->environment()); | |
| 5514 | |
| 5515 // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent | |
| 5516 // < 31. | |
| 5517 __ mov(result_reg, Immediate(31)); | |
| 5518 __ sub(result_reg, scratch2); | |
| 5519 | |
| 5520 __ bind(&right_exponent); | |
| 5521 | |
| 5522 // Save off exponent for negative check later. | |
| 5523 __ mov(scratch2, scratch); | |
| 5524 | |
| 5525 // Here result_reg is the shift, scratch is the exponent word. | |
| 5526 // Get the top bits of the mantissa. | |
| 5527 __ and_(scratch, HeapNumber::kMantissaMask); | |
| 5528 // Put back the implicit 1. | |
| 5529 __ or_(scratch, 1 << HeapNumber::kExponentShift); | |
| 5530 // Shift up the mantissa bits to take up the space the exponent used to | |
| 5531 // take. We have kExponentShift + 1 significant bits int he low end of the | |
| 5532 // word. Shift them to the top bits. | |
| 5533 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 1; | |
| 5534 __ shl(scratch, shift_distance); | |
| 5535 if (!instr->truncating()) { | |
| 5536 // If not truncating, a non-zero value in the bottom 22 bits means a | |
| 5537 // non-integral value --> trigger a deopt. | |
| 5538 __ test(scratch3, Immediate((1 << (32 - shift_distance)) - 1)); | |
| 5539 DeoptimizeIf(not_equal, instr->environment()); | |
| 5540 } | |
| 5541 // Shift down 22 bits to get the most significant 10 bits or the low | |
| 5542 // mantissa word. | |
| 5543 __ shr(scratch3, 32 - shift_distance); | |
| 5544 __ or_(scratch3, scratch); | |
| 5545 if (!instr->truncating()) { | |
| 5546 // If truncating, a non-zero value in the bits that will be shifted away | |
| 5547 // when adjusting the exponent means rounding --> deopt. | |
| 5548 __ mov(scratch, 0x1); | |
| 5549 ASSERT(result_reg.is(ecx)); | |
| 5550 __ shl_cl(scratch); | |
| 5551 __ dec(scratch); | |
| 5552 __ test(scratch3, scratch); | |
| 5553 DeoptimizeIf(not_equal, instr->environment()); | |
| 5554 } | |
| 5555 // Move down according to the exponent. | |
| 5556 ASSERT(result_reg.is(ecx)); | |
| 5557 __ shr_cl(scratch3); | |
| 5558 // Now the unsigned 32-bit answer is in scratch3. We need to move it to | |
| 5559 // result_reg and we may need to fix the sign. | |
| 5560 Label negative_result; | |
| 5561 __ xor_(result_reg, result_reg); | |
| 5562 __ cmp(scratch2, result_reg); | |
| 5563 __ j(less, &negative_result, Label::kNear); | |
| 5564 __ cmp(scratch3, result_reg); | |
| 5565 __ mov(result_reg, scratch3); | |
| 5566 // If the result is > MAX_INT, result doesn't fit in signed 32-bit --> deopt. | |
| 5567 DeoptimizeIf(less, instr->environment()); | |
| 5568 __ jmp(&done, Label::kNear); | |
| 5569 __ bind(&zero_result); | |
| 5570 __ xor_(result_reg, result_reg); | |
| 5571 __ jmp(&done, Label::kNear); | |
| 5572 __ bind(&negative_result); | |
| 5573 __ sub(result_reg, scratch3); | |
| 5574 if (!instr->truncating()) { | |
| 5575 // -0.0 triggers a deopt. | |
| 5576 DeoptimizeIf(zero, instr->environment()); | |
| 5577 } | |
| 5578 // If the negative subtraction overflows into a positive number, there was an | |
| 5579 // overflow --> deopt. | |
| 5580 DeoptimizeIf(positive, instr->environment()); | |
| 5581 __ bind(&done); | |
| 5582 } | |
| 5583 | |
| 5584 | |
| 5585 void LCodeGen::DoTaggedToINoSSE2(LTaggedToINoSSE2* instr) { | |
| 5586 class DeferredTaggedToINoSSE2: public LDeferredCode { | |
| 5587 public: | |
| 5588 DeferredTaggedToINoSSE2(LCodeGen* codegen, LTaggedToINoSSE2* instr) | |
| 5589 : LDeferredCode(codegen), instr_(instr) { } | |
| 5590 virtual void Generate() { codegen()->DoDeferredTaggedToINoSSE2(instr_); } | |
| 5591 virtual LInstruction* instr() { return instr_; } | |
| 5592 private: | |
| 5593 LTaggedToINoSSE2* instr_; | |
| 5594 }; | |
| 5595 | |
| 5596 LOperand* input = instr->value(); | |
| 5597 ASSERT(input->IsRegister()); | |
| 5598 Register input_reg = ToRegister(input); | |
| 5599 ASSERT(input_reg.is(ToRegister(instr->result()))); | |
| 5600 | |
| 5601 DeferredTaggedToINoSSE2* deferred = | |
| 5602 new(zone()) DeferredTaggedToINoSSE2(this, instr); | |
| 5603 | |
| 5604 // Smi check. | |
| 5605 __ JumpIfNotSmi(input_reg, deferred->entry()); | |
| 5606 __ SmiUntag(input_reg); // Untag smi. | |
| 5607 __ bind(deferred->exit()); | |
| 5608 } | |
| 5609 | |
| 5610 | |
| 5611 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 5401 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 5612 LOperand* input = instr->value(); | 5402 LOperand* input = instr->value(); |
| 5613 ASSERT(input->IsRegister()); | 5403 ASSERT(input->IsRegister()); |
| 5614 LOperand* temp = instr->temp(); | 5404 LOperand* temp = instr->temp(); |
| 5615 ASSERT(temp == NULL || temp->IsRegister()); | 5405 ASSERT(temp == NULL || temp->IsRegister()); |
| 5616 LOperand* result = instr->result(); | 5406 LOperand* result = instr->result(); |
| 5617 ASSERT(result->IsDoubleRegister()); | 5407 ASSERT(result->IsDoubleRegister()); |
| 5618 | 5408 |
| 5619 Register input_reg = ToRegister(input); | 5409 Register input_reg = ToRegister(input); |
| 5620 bool deoptimize_on_minus_zero = | 5410 bool deoptimize_on_minus_zero = |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5657 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 5447 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 5658 LOperand* input = instr->value(); | 5448 LOperand* input = instr->value(); |
| 5659 ASSERT(input->IsDoubleRegister()); | 5449 ASSERT(input->IsDoubleRegister()); |
| 5660 LOperand* result = instr->result(); | 5450 LOperand* result = instr->result(); |
| 5661 ASSERT(result->IsRegister()); | 5451 ASSERT(result->IsRegister()); |
| 5662 CpuFeatureScope scope(masm(), SSE2); | 5452 CpuFeatureScope scope(masm(), SSE2); |
| 5663 | 5453 |
| 5664 XMMRegister input_reg = ToDoubleRegister(input); | 5454 XMMRegister input_reg = ToDoubleRegister(input); |
| 5665 Register result_reg = ToRegister(result); | 5455 Register result_reg = ToRegister(result); |
| 5666 | 5456 |
| 5667 __ cvttsd2si(result_reg, Operand(input_reg)); | |
| 5668 | |
| 5669 if (instr->truncating()) { | 5457 if (instr->truncating()) { |
| 5670 // Performs a truncating conversion of a floating point number as used by | 5458 __ TruncateDoubleToI(input_reg, result_reg); |
| 5671 // the JS bitwise operations. | |
| 5672 Label fast_case_succeeded; | |
| 5673 __ cmp(result_reg, 0x80000000u); | |
| 5674 __ j(not_equal, &fast_case_succeeded); | |
| 5675 __ sub(esp, Immediate(kDoubleSize)); | |
| 5676 __ movdbl(MemOperand(esp, 0), input_reg); | |
| 5677 DoubleToIStub stub(esp, result_reg, 0, true); | |
| 5678 __ call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | |
| 5679 __ add(esp, Immediate(kDoubleSize)); | |
| 5680 __ bind(&fast_case_succeeded); | |
| 5681 } else { | 5459 } else { |
| 5682 Label done; | 5460 Label bailout, done; |
| 5683 __ cvtsi2sd(xmm0, Operand(result_reg)); | 5461 __ DoubleToI(input_reg, result_reg, xmm0, |
| 5684 __ ucomisd(xmm0, input_reg); | 5462 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero), |
| 5685 DeoptimizeIf(not_equal, instr->environment()); | 5463 &bailout, &done, Label::kNear); |
| 5686 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 5464 __ bind(&bailout); |
| 5687 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5465 DeoptimizeIf(no_condition, instr->environment()); |
| 5688 // The integer converted back is equal to the original. We | |
| 5689 // only have to test if we got -0 as an input. | |
| 5690 __ test(result_reg, Operand(result_reg)); | |
| 5691 __ j(not_zero, &done, Label::kNear); | |
| 5692 __ movmskpd(result_reg, input_reg); | |
| 5693 // Bit 0 contains the sign of the double in input_reg. | |
| 5694 // If input was positive, we are ok and return 0, otherwise | |
| 5695 // deoptimize. | |
| 5696 __ and_(result_reg, 1); | |
| 5697 DeoptimizeIf(not_zero, instr->environment()); | |
| 5698 } | |
| 5699 __ bind(&done); | 5466 __ bind(&done); |
| 5700 } | 5467 } |
| 5701 } | 5468 } |
| 5702 | 5469 |
| 5703 | 5470 |
| 5704 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { | 5471 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
| 5705 LOperand* input = instr->value(); | 5472 LOperand* input = instr->value(); |
| 5706 ASSERT(input->IsDoubleRegister()); | 5473 ASSERT(input->IsDoubleRegister()); |
| 5707 LOperand* result = instr->result(); | 5474 LOperand* result = instr->result(); |
| 5708 ASSERT(result->IsRegister()); | 5475 ASSERT(result->IsRegister()); |
| 5709 CpuFeatureScope scope(masm(), SSE2); | 5476 CpuFeatureScope scope(masm(), SSE2); |
| 5710 | 5477 |
| 5711 XMMRegister input_reg = ToDoubleRegister(input); | 5478 XMMRegister input_reg = ToDoubleRegister(input); |
| 5712 Register result_reg = ToRegister(result); | 5479 Register result_reg = ToRegister(result); |
| 5713 | 5480 |
| 5714 Label done; | 5481 Label bailout, done; |
| 5715 __ cvttsd2si(result_reg, Operand(input_reg)); | 5482 __ DoubleToI(input_reg, result_reg, xmm0, |
| 5716 __ cvtsi2sd(xmm0, Operand(result_reg)); | 5483 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero), |
| 5717 __ ucomisd(xmm0, input_reg); | 5484 &bailout, &done, Label::kNear); |
| 5718 DeoptimizeIf(not_equal, instr->environment()); | 5485 __ bind(&bailout); |
| 5719 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 5486 DeoptimizeIf(no_condition, instr->environment()); |
| 5487 __ bind(&done); |
| 5720 | 5488 |
| 5721 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
| 5722 // The integer converted back is equal to the original. We | |
| 5723 // only have to test if we got -0 as an input. | |
| 5724 __ test(result_reg, Operand(result_reg)); | |
| 5725 __ j(not_zero, &done, Label::kNear); | |
| 5726 __ movmskpd(result_reg, input_reg); | |
| 5727 // Bit 0 contains the sign of the double in input_reg. | |
| 5728 // If input was positive, we are ok and return 0, otherwise | |
| 5729 // deoptimize. | |
| 5730 __ and_(result_reg, 1); | |
| 5731 DeoptimizeIf(not_zero, instr->environment()); | |
| 5732 __ bind(&done); | |
| 5733 } | |
| 5734 __ SmiTag(result_reg); | 5489 __ SmiTag(result_reg); |
| 5735 DeoptimizeIf(overflow, instr->environment()); | 5490 DeoptimizeIf(overflow, instr->environment()); |
| 5736 } | 5491 } |
| 5737 | 5492 |
| 5738 | 5493 |
| 5739 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 5494 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 5740 LOperand* input = instr->value(); | 5495 LOperand* input = instr->value(); |
| 5741 __ test(ToOperand(input), Immediate(kSmiTagMask)); | 5496 __ test(ToOperand(input), Immediate(kSmiTagMask)); |
| 5742 DeoptimizeIf(not_zero, instr->environment()); | 5497 DeoptimizeIf(not_zero, instr->environment()); |
| 5743 } | 5498 } |
| (...skipping 806 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6550 FixedArray::kHeaderSize - kPointerSize)); | 6305 FixedArray::kHeaderSize - kPointerSize)); |
| 6551 __ bind(&done); | 6306 __ bind(&done); |
| 6552 } | 6307 } |
| 6553 | 6308 |
| 6554 | 6309 |
| 6555 #undef __ | 6310 #undef __ |
| 6556 | 6311 |
| 6557 } } // namespace v8::internal | 6312 } } // namespace v8::internal |
| 6558 | 6313 |
| 6559 #endif // V8_TARGET_ARCH_IA32 | 6314 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |