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 4879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4890 | 4890 |
4891 | 4891 |
4892 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4892 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
4893 class DeferredNumberTagI V8_FINAL : public LDeferredCode { | 4893 class DeferredNumberTagI V8_FINAL : public LDeferredCode { |
4894 public: | 4894 public: |
4895 DeferredNumberTagI(LCodeGen* codegen, | 4895 DeferredNumberTagI(LCodeGen* codegen, |
4896 LNumberTagI* instr, | 4896 LNumberTagI* instr, |
4897 const X87Stack& x87_stack) | 4897 const X87Stack& x87_stack) |
4898 : LDeferredCode(codegen, x87_stack), instr_(instr) { } | 4898 : LDeferredCode(codegen, x87_stack), instr_(instr) { } |
4899 virtual void Generate() V8_OVERRIDE { | 4899 virtual void Generate() V8_OVERRIDE { |
4900 codegen()->DoDeferredNumberTagI(instr_, instr_->value(), SIGNED_INT32); | 4900 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(), |
| 4901 NULL, SIGNED_INT32); |
4901 } | 4902 } |
4902 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4903 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
4903 private: | 4904 private: |
4904 LNumberTagI* instr_; | 4905 LNumberTagI* instr_; |
4905 }; | 4906 }; |
4906 | 4907 |
4907 LOperand* input = instr->value(); | 4908 LOperand* input = instr->value(); |
4908 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4909 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4909 Register reg = ToRegister(input); | 4910 Register reg = ToRegister(input); |
4910 | 4911 |
4911 DeferredNumberTagI* deferred = | 4912 DeferredNumberTagI* deferred = |
4912 new(zone()) DeferredNumberTagI(this, instr, x87_stack_); | 4913 new(zone()) DeferredNumberTagI(this, instr, x87_stack_); |
4913 __ SmiTag(reg); | 4914 __ SmiTag(reg); |
4914 __ j(overflow, deferred->entry()); | 4915 __ j(overflow, deferred->entry()); |
4915 __ bind(deferred->exit()); | 4916 __ bind(deferred->exit()); |
4916 } | 4917 } |
4917 | 4918 |
4918 | 4919 |
4919 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4920 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
4920 class DeferredNumberTagU V8_FINAL : public LDeferredCode { | 4921 class DeferredNumberTagU V8_FINAL : public LDeferredCode { |
4921 public: | 4922 public: |
4922 DeferredNumberTagU(LCodeGen* codegen, | 4923 DeferredNumberTagU(LCodeGen* codegen, |
4923 LNumberTagU* instr, | 4924 LNumberTagU* instr, |
4924 const X87Stack& x87_stack) | 4925 const X87Stack& x87_stack) |
4925 : LDeferredCode(codegen, x87_stack), instr_(instr) { } | 4926 : LDeferredCode(codegen, x87_stack), instr_(instr) { } |
4926 virtual void Generate() V8_OVERRIDE { | 4927 virtual void Generate() V8_OVERRIDE { |
4927 codegen()->DoDeferredNumberTagI(instr_, instr_->value(), UNSIGNED_INT32); | 4928 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(), |
| 4929 instr_->temp2(), UNSIGNED_INT32); |
4928 } | 4930 } |
4929 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4931 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
4930 private: | 4932 private: |
4931 LNumberTagU* instr_; | 4933 LNumberTagU* instr_; |
4932 }; | 4934 }; |
4933 | 4935 |
4934 LOperand* input = instr->value(); | 4936 LOperand* input = instr->value(); |
4935 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4937 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4936 Register reg = ToRegister(input); | 4938 Register reg = ToRegister(input); |
4937 | 4939 |
4938 DeferredNumberTagU* deferred = | 4940 DeferredNumberTagU* deferred = |
4939 new(zone()) DeferredNumberTagU(this, instr, x87_stack_); | 4941 new(zone()) DeferredNumberTagU(this, instr, x87_stack_); |
4940 __ cmp(reg, Immediate(Smi::kMaxValue)); | 4942 __ cmp(reg, Immediate(Smi::kMaxValue)); |
4941 __ j(above, deferred->entry()); | 4943 __ j(above, deferred->entry()); |
4942 __ SmiTag(reg); | 4944 __ SmiTag(reg); |
4943 __ bind(deferred->exit()); | 4945 __ bind(deferred->exit()); |
4944 } | 4946 } |
4945 | 4947 |
4946 | 4948 |
4947 void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, | 4949 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, |
4948 LOperand* value, | 4950 LOperand* value, |
4949 IntegerSignedness signedness) { | 4951 LOperand* temp1, |
4950 Label slow; | 4952 LOperand* temp2, |
| 4953 IntegerSignedness signedness) { |
| 4954 Label done, slow; |
4951 Register reg = ToRegister(value); | 4955 Register reg = ToRegister(value); |
4952 Register tmp = reg.is(eax) ? ecx : eax; | 4956 Register tmp = ToRegister(temp1); |
4953 XMMRegister xmm_scratch = double_scratch0(); | 4957 XMMRegister xmm_scratch = double_scratch0(); |
4954 | 4958 |
4955 // Preserve the value of all registers. | |
4956 PushSafepointRegistersScope scope(this); | |
4957 | |
4958 Label done; | |
4959 | |
4960 if (signedness == SIGNED_INT32) { | 4959 if (signedness == SIGNED_INT32) { |
4961 // There was overflow, so bits 30 and 31 of the original integer | 4960 // There was overflow, so bits 30 and 31 of the original integer |
4962 // disagree. Try to allocate a heap number in new space and store | 4961 // disagree. Try to allocate a heap number in new space and store |
4963 // the value in there. If that fails, call the runtime system. | 4962 // the value in there. If that fails, call the runtime system. |
4964 __ SmiUntag(reg); | 4963 __ SmiUntag(reg); |
4965 __ xor_(reg, 0x80000000); | 4964 __ xor_(reg, 0x80000000); |
4966 if (CpuFeatures::IsSupported(SSE2)) { | 4965 if (CpuFeatures::IsSupported(SSE2)) { |
4967 CpuFeatureScope feature_scope(masm(), SSE2); | 4966 CpuFeatureScope feature_scope(masm(), SSE2); |
4968 __ Cvtsi2sd(xmm_scratch, Operand(reg)); | 4967 __ Cvtsi2sd(xmm_scratch, Operand(reg)); |
4969 } else { | 4968 } else { |
4970 __ push(reg); | 4969 __ push(reg); |
4971 __ fild_s(Operand(esp, 0)); | 4970 __ fild_s(Operand(esp, 0)); |
4972 __ pop(reg); | 4971 __ pop(reg); |
4973 } | 4972 } |
4974 } else { | 4973 } else { |
4975 if (CpuFeatures::IsSupported(SSE2)) { | 4974 if (CpuFeatures::IsSupported(SSE2)) { |
4976 CpuFeatureScope feature_scope(masm(), SSE2); | 4975 CpuFeatureScope feature_scope(masm(), SSE2); |
4977 __ LoadUint32(xmm_scratch, reg, | 4976 __ LoadUint32(xmm_scratch, reg, ToDoubleRegister(temp2)); |
4978 ToDoubleRegister(LNumberTagU::cast(instr)->temp())); | |
4979 } else { | 4977 } else { |
4980 // There's no fild variant for unsigned values, so zero-extend to a 64-bit | 4978 // There's no fild variant for unsigned values, so zero-extend to a 64-bit |
4981 // int manually. | 4979 // int manually. |
4982 __ push(Immediate(0)); | 4980 __ push(Immediate(0)); |
4983 __ push(reg); | 4981 __ push(reg); |
4984 __ fild_d(Operand(esp, 0)); | 4982 __ fild_d(Operand(esp, 0)); |
4985 __ pop(reg); | 4983 __ pop(reg); |
4986 __ pop(reg); | 4984 __ pop(reg); |
4987 } | 4985 } |
4988 } | 4986 } |
4989 | 4987 |
4990 if (FLAG_inline_new) { | 4988 if (FLAG_inline_new) { |
4991 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); | 4989 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); |
4992 __ jmp(&done, Label::kNear); | 4990 __ jmp(&done, Label::kNear); |
4993 } | 4991 } |
4994 | 4992 |
4995 // Slow case: Call the runtime system to do the number allocation. | 4993 // Slow case: Call the runtime system to do the number allocation. |
4996 __ bind(&slow); | 4994 __ bind(&slow); |
| 4995 { |
| 4996 // TODO(3095996): Put a valid pointer value in the stack slot where the |
| 4997 // result register is stored, as this register is in the pointer map, but |
| 4998 // contains an integer value. |
| 4999 __ Set(reg, Immediate(0)); |
4997 | 5000 |
4998 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 5001 // Preserve the value of all registers. |
4999 // register is stored, as this register is in the pointer map, but contains an | 5002 PushSafepointRegistersScope scope(this); |
5000 // integer value. | 5003 |
5001 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); | 5004 // NumberTagI and NumberTagD use the context from the frame, rather than |
5002 // NumberTagI and NumberTagD use the context from the frame, rather than | 5005 // the environment's HContext or HInlinedContext value. |
5003 // the environment's HContext or HInlinedContext value. | 5006 // They only call Runtime::kAllocateHeapNumber. |
5004 // They only call Runtime::kAllocateHeapNumber. | 5007 // The corresponding HChange instructions are added in a phase that does |
5005 // The corresponding HChange instructions are added in a phase that does | 5008 // not have easy access to the local context. |
5006 // not have easy access to the local context. | 5009 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
5007 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 5010 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
5008 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 5011 RecordSafepointWithRegisters( |
5009 RecordSafepointWithRegisters( | 5012 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
5010 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 5013 __ StoreToSafepointRegisterSlot(reg, eax); |
5011 if (!reg.is(eax)) __ mov(reg, eax); | 5014 } |
5012 | 5015 |
5013 // Done. Put the value in xmm_scratch into the value of the allocated heap | 5016 // Done. Put the value in xmm_scratch into the value of the allocated heap |
5014 // number. | 5017 // number. |
5015 __ bind(&done); | 5018 __ bind(&done); |
5016 if (CpuFeatures::IsSupported(SSE2)) { | 5019 if (CpuFeatures::IsSupported(SSE2)) { |
5017 CpuFeatureScope feature_scope(masm(), SSE2); | 5020 CpuFeatureScope feature_scope(masm(), SSE2); |
5018 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm_scratch); | 5021 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm_scratch); |
5019 } else { | 5022 } else { |
5020 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 5023 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
5021 } | 5024 } |
5022 __ StoreToSafepointRegisterSlot(reg, reg); | |
5023 } | 5025 } |
5024 | 5026 |
5025 | 5027 |
5026 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 5028 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
5027 class DeferredNumberTagD V8_FINAL : public LDeferredCode { | 5029 class DeferredNumberTagD V8_FINAL : public LDeferredCode { |
5028 public: | 5030 public: |
5029 DeferredNumberTagD(LCodeGen* codegen, | 5031 DeferredNumberTagD(LCodeGen* codegen, |
5030 LNumberTagD* instr, | 5032 LNumberTagD* instr, |
5031 const X87Stack& x87_stack) | 5033 const X87Stack& x87_stack) |
5032 : LDeferredCode(codegen, x87_stack), instr_(instr) { } | 5034 : LDeferredCode(codegen, x87_stack), instr_(instr) { } |
(...skipping 1237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6270 FixedArray::kHeaderSize - kPointerSize)); | 6272 FixedArray::kHeaderSize - kPointerSize)); |
6271 __ bind(&done); | 6273 __ bind(&done); |
6272 } | 6274 } |
6273 | 6275 |
6274 | 6276 |
6275 #undef __ | 6277 #undef __ |
6276 | 6278 |
6277 } } // namespace v8::internal | 6279 } } // namespace v8::internal |
6278 | 6280 |
6279 #endif // V8_TARGET_ARCH_IA32 | 6281 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |