OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "x64/lithium-codegen-x64.h" | 9 #include "x64/lithium-codegen-x64.h" |
10 #include "code-stubs.h" | 10 #include "code-stubs.h" |
(...skipping 4526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4537 LOperand* output = instr->result(); | 4537 LOperand* output = instr->result(); |
4538 LOperand* temp = instr->temp(); | 4538 LOperand* temp = instr->temp(); |
4539 | 4539 |
4540 __ LoadUint32(ToDoubleRegister(output), | 4540 __ LoadUint32(ToDoubleRegister(output), |
4541 ToRegister(input), | 4541 ToRegister(input), |
4542 ToDoubleRegister(temp)); | 4542 ToDoubleRegister(temp)); |
4543 } | 4543 } |
4544 | 4544 |
4545 | 4545 |
4546 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4546 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
| 4547 class DeferredNumberTagI V8_FINAL : public LDeferredCode { |
| 4548 public: |
| 4549 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
| 4550 : LDeferredCode(codegen), instr_(instr) { } |
| 4551 virtual void Generate() V8_OVERRIDE { |
| 4552 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(), |
| 4553 instr_->temp2(), SIGNED_INT32); |
| 4554 } |
| 4555 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4556 private: |
| 4557 LNumberTagI* instr_; |
| 4558 }; |
| 4559 |
4547 LOperand* input = instr->value(); | 4560 LOperand* input = instr->value(); |
4548 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4561 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4549 Register reg = ToRegister(input); | 4562 Register reg = ToRegister(input); |
4550 | 4563 |
4551 __ Integer32ToSmi(reg, reg); | 4564 if (SmiValuesAre32Bits()) { |
| 4565 __ Integer32ToSmi(reg, reg); |
| 4566 } else { |
| 4567 ASSERT(SmiValuesAre31Bits()); |
| 4568 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); |
| 4569 __ Integer32ToSmi(reg, reg); |
| 4570 __ j(overflow, deferred->entry()); |
| 4571 __ bind(deferred->exit()); |
| 4572 } |
4552 } | 4573 } |
4553 | 4574 |
4554 | 4575 |
4555 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4576 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
4556 class DeferredNumberTagU V8_FINAL : public LDeferredCode { | 4577 class DeferredNumberTagU V8_FINAL : public LDeferredCode { |
4557 public: | 4578 public: |
4558 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) | 4579 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
4559 : LDeferredCode(codegen), instr_(instr) { } | 4580 : LDeferredCode(codegen), instr_(instr) { } |
4560 virtual void Generate() V8_OVERRIDE { | 4581 virtual void Generate() V8_OVERRIDE { |
4561 codegen()->DoDeferredNumberTagU(instr_); | 4582 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(), |
| 4583 instr_->temp2(), UNSIGNED_INT32); |
4562 } | 4584 } |
4563 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4585 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
4564 private: | 4586 private: |
4565 LNumberTagU* instr_; | 4587 LNumberTagU* instr_; |
4566 }; | 4588 }; |
4567 | 4589 |
4568 LOperand* input = instr->value(); | 4590 LOperand* input = instr->value(); |
4569 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4591 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4570 Register reg = ToRegister(input); | 4592 Register reg = ToRegister(input); |
4571 | 4593 |
4572 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4594 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
4573 __ cmpl(reg, Immediate(Smi::kMaxValue)); | 4595 __ cmpl(reg, Immediate(Smi::kMaxValue)); |
4574 __ j(above, deferred->entry()); | 4596 __ j(above, deferred->entry()); |
4575 __ Integer32ToSmi(reg, reg); | 4597 __ Integer32ToSmi(reg, reg); |
4576 __ bind(deferred->exit()); | 4598 __ bind(deferred->exit()); |
4577 } | 4599 } |
4578 | 4600 |
4579 | 4601 |
4580 void LCodeGen::DoDeferredNumberTagU(LNumberTagU* instr) { | 4602 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, |
| 4603 LOperand* value, |
| 4604 LOperand* temp1, |
| 4605 LOperand* temp2, |
| 4606 IntegerSignedness signedness) { |
4581 Label done, slow; | 4607 Label done, slow; |
4582 Register reg = ToRegister(instr->value()); | 4608 Register reg = ToRegister(value); |
4583 Register tmp = ToRegister(instr->temp1()); | 4609 Register tmp = ToRegister(temp1); |
4584 XMMRegister temp_xmm = ToDoubleRegister(instr->temp2()); | 4610 XMMRegister temp_xmm = ToDoubleRegister(temp2); |
4585 | 4611 |
4586 // Load value into temp_xmm which will be preserved across potential call to | 4612 // Load value into temp_xmm which will be preserved across potential call to |
4587 // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable | 4613 // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable |
4588 // XMM registers on x64). | 4614 // XMM registers on x64). |
4589 XMMRegister xmm_scratch = double_scratch0(); | 4615 if (signedness == SIGNED_INT32) { |
4590 __ LoadUint32(temp_xmm, reg, xmm_scratch); | 4616 ASSERT(SmiValuesAre31Bits()); |
| 4617 // There was overflow, so bits 30 and 31 of the original integer |
| 4618 // disagree. Try to allocate a heap number in new space and store |
| 4619 // the value in there. If that fails, call the runtime system. |
| 4620 __ SmiToInteger32(reg, reg); |
| 4621 __ xorl(reg, Immediate(0x80000000)); |
| 4622 __ cvtlsi2sd(temp_xmm, reg); |
| 4623 } else { |
| 4624 ASSERT(signedness == UNSIGNED_INT32); |
| 4625 XMMRegister xmm_scratch = double_scratch0(); |
| 4626 __ LoadUint32(temp_xmm, reg, xmm_scratch); |
| 4627 } |
4591 | 4628 |
4592 if (FLAG_inline_new) { | 4629 if (FLAG_inline_new) { |
4593 __ AllocateHeapNumber(reg, tmp, &slow); | 4630 __ AllocateHeapNumber(reg, tmp, &slow); |
4594 __ jmp(&done, Label::kNear); | 4631 __ jmp(&done, Label::kNear); |
4595 } | 4632 } |
4596 | 4633 |
4597 // Slow case: Call the runtime system to do the number allocation. | 4634 // Slow case: Call the runtime system to do the number allocation. |
4598 __ bind(&slow); | 4635 __ bind(&slow); |
4599 { | 4636 { |
4600 // Put a valid pointer value in the stack slot where the result | 4637 // Put a valid pointer value in the stack slot where the result |
4601 // register is stored, as this register is in the pointer map, but contains | 4638 // register is stored, as this register is in the pointer map, but contains |
4602 // an integer value. | 4639 // an integer value. |
4603 __ Set(reg, 0); | 4640 __ Set(reg, 0); |
4604 | 4641 |
4605 // Preserve the value of all registers. | 4642 // Preserve the value of all registers. |
4606 PushSafepointRegistersScope scope(this); | 4643 PushSafepointRegistersScope scope(this); |
4607 | 4644 |
4608 // NumberTagU uses the context from the frame, rather than | 4645 // NumberTagIU uses the context from the frame, rather than |
4609 // the environment's HContext or HInlinedContext value. | 4646 // the environment's HContext or HInlinedContext value. |
4610 // They only call Runtime::kHiddenAllocateHeapNumber. | 4647 // They only call Runtime::kHiddenAllocateHeapNumber. |
4611 // The corresponding HChange instructions are added in a phase that does | 4648 // The corresponding HChange instructions are added in a phase that does |
4612 // not have easy access to the local context. | 4649 // not have easy access to the local context. |
4613 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 4650 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
4614 __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); | 4651 __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); |
4615 RecordSafepointWithRegisters( | 4652 RecordSafepointWithRegisters( |
4616 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4653 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
4617 __ StoreToSafepointRegisterSlot(reg, rax); | 4654 __ StoreToSafepointRegisterSlot(reg, rax); |
4618 } | 4655 } |
(...skipping 1079 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5698 __ bind(deferred->exit()); | 5735 __ bind(deferred->exit()); |
5699 __ bind(&done); | 5736 __ bind(&done); |
5700 } | 5737 } |
5701 | 5738 |
5702 | 5739 |
5703 #undef __ | 5740 #undef __ |
5704 | 5741 |
5705 } } // namespace v8::internal | 5742 } } // namespace v8::internal |
5706 | 5743 |
5707 #endif // V8_TARGET_ARCH_X64 | 5744 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |