| 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 |