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); |
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); |
5395 } | 5368 } |
5396 } else if (CpuFeatures::IsSupported(SSE2)) { | 5369 __ jmp(done); |
5397 CpuFeatureScope scope(masm(), SSE2); | 5370 __ bind(&bailout); |
5398 // Deoptimize if we don't have a heap number. | 5371 DeoptimizeIf(no_condition, instr->environment()); |
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 } | 5372 } |
5422 __ bind(&done); | |
5423 } | 5373 } |
5424 | 5374 |
5425 | 5375 |
5426 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 5376 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
5427 class DeferredTaggedToI: public LDeferredCode { | 5377 class DeferredTaggedToI: public LDeferredCode { |
5428 public: | 5378 public: |
5429 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 5379 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
5430 : LDeferredCode(codegen), instr_(instr) { } | 5380 : LDeferredCode(codegen), instr_(instr) { } |
5431 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 5381 virtual void Generate() { |
| 5382 codegen()->DoDeferredTaggedToI(instr_, done()); |
| 5383 } |
5432 virtual LInstruction* instr() { return instr_; } | 5384 virtual LInstruction* instr() { return instr_; } |
5433 private: | 5385 private: |
5434 LTaggedToI* instr_; | 5386 LTaggedToI* instr_; |
5435 }; | 5387 }; |
5436 | 5388 |
5437 LOperand* input = instr->value(); | 5389 LOperand* input = instr->value(); |
5438 ASSERT(input->IsRegister()); | 5390 ASSERT(input->IsRegister()); |
5439 Register input_reg = ToRegister(input); | 5391 Register input_reg = ToRegister(input); |
5440 ASSERT(input_reg.is(ToRegister(instr->result()))); | 5392 ASSERT(input_reg.is(ToRegister(instr->result()))); |
5441 | 5393 |
5442 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); | 5394 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); |
5443 | 5395 |
5444 __ JumpIfNotSmi(input_reg, deferred->entry()); | 5396 __ JumpIfNotSmi(input_reg, deferred->entry()); |
5445 __ SmiUntag(input_reg); | 5397 __ SmiUntag(input_reg); |
5446 __ bind(deferred->exit()); | 5398 __ bind(deferred->exit()); |
5447 } | 5399 } |
5448 | 5400 |
5449 | 5401 |
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) { | 5402 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
5612 LOperand* input = instr->value(); | 5403 LOperand* input = instr->value(); |
5613 ASSERT(input->IsRegister()); | 5404 ASSERT(input->IsRegister()); |
5614 LOperand* temp = instr->temp(); | 5405 LOperand* temp = instr->temp(); |
5615 ASSERT(temp == NULL || temp->IsRegister()); | 5406 ASSERT(temp == NULL || temp->IsRegister()); |
5616 LOperand* result = instr->result(); | 5407 LOperand* result = instr->result(); |
5617 ASSERT(result->IsDoubleRegister()); | 5408 ASSERT(result->IsDoubleRegister()); |
5618 | 5409 |
5619 Register input_reg = ToRegister(input); | 5410 Register input_reg = ToRegister(input); |
5620 bool deoptimize_on_minus_zero = | 5411 bool deoptimize_on_minus_zero = |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5657 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 5448 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
5658 LOperand* input = instr->value(); | 5449 LOperand* input = instr->value(); |
5659 ASSERT(input->IsDoubleRegister()); | 5450 ASSERT(input->IsDoubleRegister()); |
5660 LOperand* result = instr->result(); | 5451 LOperand* result = instr->result(); |
5661 ASSERT(result->IsRegister()); | 5452 ASSERT(result->IsRegister()); |
5662 CpuFeatureScope scope(masm(), SSE2); | 5453 CpuFeatureScope scope(masm(), SSE2); |
5663 | 5454 |
5664 XMMRegister input_reg = ToDoubleRegister(input); | 5455 XMMRegister input_reg = ToDoubleRegister(input); |
5665 Register result_reg = ToRegister(result); | 5456 Register result_reg = ToRegister(result); |
5666 | 5457 |
5667 __ cvttsd2si(result_reg, Operand(input_reg)); | |
5668 | |
5669 if (instr->truncating()) { | 5458 if (instr->truncating()) { |
5670 // Performs a truncating conversion of a floating point number as used by | 5459 __ 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 { | 5460 } else { |
5682 Label done; | 5461 Label bailout, done; |
5683 __ cvtsi2sd(xmm0, Operand(result_reg)); | 5462 __ DoubleToI(input_reg, result_reg, xmm0, |
5684 __ ucomisd(xmm0, input_reg); | 5463 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero), |
5685 DeoptimizeIf(not_equal, instr->environment()); | 5464 &bailout, Label::kNear); |
5686 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 5465 __ jmp(&done, Label::kNear); |
5687 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5466 __ bind(&bailout); |
5688 // The integer converted back is equal to the original. We | 5467 DeoptimizeIf(no_condition, instr->environment()); |
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); | 5468 __ bind(&done); |
5700 } | 5469 } |
5701 } | 5470 } |
5702 | 5471 |
5703 | 5472 |
5704 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { | 5473 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
5705 LOperand* input = instr->value(); | 5474 LOperand* input = instr->value(); |
5706 ASSERT(input->IsDoubleRegister()); | 5475 ASSERT(input->IsDoubleRegister()); |
5707 LOperand* result = instr->result(); | 5476 LOperand* result = instr->result(); |
5708 ASSERT(result->IsRegister()); | 5477 ASSERT(result->IsRegister()); |
5709 CpuFeatureScope scope(masm(), SSE2); | 5478 CpuFeatureScope scope(masm(), SSE2); |
5710 | 5479 |
5711 XMMRegister input_reg = ToDoubleRegister(input); | 5480 XMMRegister input_reg = ToDoubleRegister(input); |
5712 Register result_reg = ToRegister(result); | 5481 Register result_reg = ToRegister(result); |
5713 | 5482 |
5714 Label done; | 5483 Label bailout, done; |
5715 __ cvttsd2si(result_reg, Operand(input_reg)); | 5484 __ DoubleToI(input_reg, result_reg, xmm0, |
5716 __ cvtsi2sd(xmm0, Operand(result_reg)); | 5485 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero), |
5717 __ ucomisd(xmm0, input_reg); | 5486 &bailout, Label::kNear); |
5718 DeoptimizeIf(not_equal, instr->environment()); | 5487 __ jmp(&done, Label::kNear); |
5719 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 5488 __ bind(&bailout); |
| 5489 DeoptimizeIf(no_condition, instr->environment()); |
| 5490 __ bind(&done); |
5720 | 5491 |
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); | 5492 __ SmiTag(result_reg); |
5735 DeoptimizeIf(overflow, instr->environment()); | 5493 DeoptimizeIf(overflow, instr->environment()); |
5736 } | 5494 } |
5737 | 5495 |
5738 | 5496 |
5739 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 5497 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
5740 LOperand* input = instr->value(); | 5498 LOperand* input = instr->value(); |
5741 __ test(ToOperand(input), Immediate(kSmiTagMask)); | 5499 __ test(ToOperand(input), Immediate(kSmiTagMask)); |
5742 DeoptimizeIf(not_zero, instr->environment()); | 5500 DeoptimizeIf(not_zero, instr->environment()); |
5743 } | 5501 } |
(...skipping 806 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6550 FixedArray::kHeaderSize - kPointerSize)); | 6308 FixedArray::kHeaderSize - kPointerSize)); |
6551 __ bind(&done); | 6309 __ bind(&done); |
6552 } | 6310 } |
6553 | 6311 |
6554 | 6312 |
6555 #undef __ | 6313 #undef __ |
6556 | 6314 |
6557 } } // namespace v8::internal | 6315 } } // namespace v8::internal |
6558 | 6316 |
6559 #endif // V8_TARGET_ARCH_IA32 | 6317 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |