| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3858 Register mask = scratch1; | 3858 Register mask = scratch1; |
| 3859 Register scratch = scratch2; | 3859 Register scratch = scratch2; |
| 3860 | 3860 |
| 3861 // Load the number string cache. | 3861 // Load the number string cache. |
| 3862 ExternalReference roots_address = | 3862 ExternalReference roots_address = |
| 3863 ExternalReference::roots_address(masm->isolate()); | 3863 ExternalReference::roots_address(masm->isolate()); |
| 3864 __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex)); | 3864 __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex)); |
| 3865 __ mov(number_string_cache, | 3865 __ mov(number_string_cache, |
| 3866 Operand::StaticArray(scratch, times_pointer_size, roots_address)); | 3866 Operand::StaticArray(scratch, times_pointer_size, roots_address)); |
| 3867 // Make the hash mask from the length of the number string cache. It | 3867 // Make the hash mask from the length of the number string cache. It |
| 3868 // contains two elements (number and string) for each cache entry. | 3868 // contains three elements (number, string and age) for each cache entry. |
| 3869 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); | 3869 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); |
| 3870 __ shr(mask, kSmiTagSize + 1); // Untag length and divide it by two. | 3870 __ lea(scratch, Operand(mask, mask, times_1, 0)); |
| 3871 __ sub(mask, Immediate(1)); // Make mask. | 3871 STATIC_ASSERT(Heap::kNSCSlotsPerEntry == 3); |
| 3872 __ and_(mask, scratch); // Multiply mask by 2/3, making it a power of 2. |
| 3873 // Make mask. It is 4 times the number of entries (2 times for Smi tag, |
| 3874 // 2 times for the size of the array * 2/3). |
| 3875 STATIC_ASSERT(kSmiTagSize == 1); |
| 3876 STATIC_ASSERT(kPointerSize == 4); |
| 3877 __ sub(mask, Immediate(kPointerSize - 1)); |
| 3872 | 3878 |
| 3873 // Calculate the entry in the number string cache. The hash value in the | 3879 // Calculate the entry in the number string cache. The hash value in the |
| 3874 // number string cache for smis is just the smi value, and the hash for | 3880 // number string cache for smis is just the smi value, and the hash for |
| 3875 // doubles is the xor of the upper and lower words. See | 3881 // doubles is the xor of the upper and lower words. See |
| 3876 // Heap::GetNumberStringCache. | 3882 // Heap::GetNumberStringCache. |
| 3877 Label smi_hash_calculated; | 3883 Label smi_hash_calculated; |
| 3878 Label load_result_from_cache; | 3884 Label load_result_from_cache; |
| 3879 if (object_is_smi) { | 3885 if (object_is_smi) { |
| 3880 __ mov(scratch, object); | 3886 STATIC_ASSERT(kPointerSizeLog2 - kSmiTagSize == 1); |
| 3881 __ SmiUntag(scratch); | 3887 STATIC_ASSERT(kSmiTag == 0); |
| 3888 __ lea(scratch, Operand(object, object, times_1, 0)); |
| 3882 } else { | 3889 } else { |
| 3883 Label not_smi; | 3890 Label not_smi; |
| 3884 STATIC_ASSERT(kSmiTag == 0); | 3891 STATIC_ASSERT(kSmiTag == 0); |
| 3885 __ JumpIfNotSmi(object, ¬_smi, Label::kNear); | 3892 __ JumpIfNotSmi(object, ¬_smi, Label::kNear); |
| 3886 __ mov(scratch, object); | 3893 STATIC_ASSERT(kPointerSizeLog2 - kSmiTagSize == 1); |
| 3887 __ SmiUntag(scratch); | 3894 STATIC_ASSERT(kSmiTag == 0); |
| 3895 __ lea(scratch, Operand(object, object, times_1, 0)); |
| 3888 __ jmp(&smi_hash_calculated, Label::kNear); | 3896 __ jmp(&smi_hash_calculated, Label::kNear); |
| 3889 __ bind(¬_smi); | 3897 __ bind(¬_smi); |
| 3890 __ cmp(FieldOperand(object, HeapObject::kMapOffset), | 3898 __ cmp(FieldOperand(object, HeapObject::kMapOffset), |
| 3891 masm->isolate()->factory()->heap_number_map()); | 3899 masm->isolate()->factory()->heap_number_map()); |
| 3892 __ j(not_equal, not_found); | 3900 __ j(not_equal, not_found); |
| 3893 STATIC_ASSERT(8 == kDoubleSize); | 3901 STATIC_ASSERT(8 == kDoubleSize); |
| 3894 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset)); | 3902 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset)); |
| 3895 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); | 3903 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); |
| 3896 // Object is heap number and hash is now in scratch. Calculate cache index. | 3904 // Object is heap number and hash is now in scratch. Scale hash to pointer |
| 3905 // size and apply the mask. |
| 3906 __ shl(scratch, kPointerSizeLog2); |
| 3897 __ and_(scratch, mask); | 3907 __ and_(scratch, mask); |
| 3908 // Multiply by 3. |
| 3909 STATIC_ASSERT(Heap::kNSCSlotsPerEntry == 3); |
| 3910 __ lea(scratch, Operand(scratch, scratch, times_2, 0)); |
| 3898 Register index = scratch; | 3911 Register index = scratch; |
| 3899 Register probe = mask; | 3912 Register probe = mask; |
| 3900 __ mov(probe, | 3913 __ mov(probe, FieldOperand( |
| 3901 FieldOperand(number_string_cache, | 3914 number_string_cache, |
| 3902 index, | 3915 index, |
| 3903 times_twice_pointer_size, | 3916 times_1, |
| 3904 FixedArray::kHeaderSize)); | 3917 FixedArray::kHeaderSize + kPointerSizeLog2 * Heap::kNSCNumberOffset)); |
| 3905 __ JumpIfSmi(probe, not_found); | 3918 __ JumpIfSmi(probe, not_found); |
| 3906 if (CpuFeatures::IsSupported(SSE2)) { | 3919 if (CpuFeatures::IsSupported(SSE2)) { |
| 3907 CpuFeatures::Scope fscope(SSE2); | 3920 CpuFeatures::Scope fscope(SSE2); |
| 3908 __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); | 3921 __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); |
| 3909 __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); | 3922 __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); |
| 3910 __ ucomisd(xmm0, xmm1); | 3923 __ ucomisd(xmm0, xmm1); |
| 3911 } else { | 3924 } else { |
| 3912 __ fld_d(FieldOperand(object, HeapNumber::kValueOffset)); | 3925 __ fld_d(FieldOperand(object, HeapNumber::kValueOffset)); |
| 3913 __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset)); | 3926 __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset)); |
| 3914 __ FCmp(); | 3927 __ FCmp(); |
| 3915 } | 3928 } |
| 3916 __ j(parity_even, not_found); // Bail out if NaN is involved. | 3929 __ j(parity_even, not_found); // Bail out if NaN is involved. |
| 3917 __ j(not_equal, not_found); // The cache did not contain this value. | 3930 __ j(not_equal, not_found); // The cache did not contain this value. |
| 3918 __ jmp(&load_result_from_cache, Label::kNear); | 3931 __ jmp(&load_result_from_cache, Label::kNear); |
| 3919 } | 3932 } |
| 3920 | 3933 |
| 3921 __ bind(&smi_hash_calculated); | 3934 __ bind(&smi_hash_calculated); |
| 3922 // Object is smi and hash is now in scratch. Calculate cache index. | 3935 // Object is smi and hash is now in scratch. Calculate cache index. |
| 3923 __ and_(scratch, mask); | 3936 __ and_(scratch, mask); |
| 3937 // Multiply by 3. |
| 3924 Register index = scratch; | 3938 Register index = scratch; |
| 3939 __ lea(index, Operand(scratch, scratch, times_2, 0)); |
| 3925 // Check if the entry is the smi we are looking for. | 3940 // Check if the entry is the smi we are looking for. |
| 3926 __ cmp(object, | 3941 __ cmp(object, FieldOperand( |
| 3927 FieldOperand(number_string_cache, | 3942 number_string_cache, |
| 3928 index, | 3943 index, |
| 3929 times_twice_pointer_size, | 3944 times_1, |
| 3930 FixedArray::kHeaderSize)); | 3945 FixedArray::kHeaderSize + kPointerSizeLog2 * Heap::kNSCNumberOffset)); |
| 3931 __ j(not_equal, not_found); | 3946 __ j(not_equal, not_found); |
| 3932 | 3947 |
| 3933 // Get the result from the cache. | 3948 // Get the result from the cache. |
| 3934 __ bind(&load_result_from_cache); | 3949 __ bind(&load_result_from_cache); |
| 3950 int kAgeOffset = FixedArray::kHeaderSize + kPointerSize * Heap::kNSCAgeOffset; |
| 3951 __ mov(FieldOperand(number_string_cache, index, times_1, kAgeOffset), |
| 3952 Immediate(Smi::FromInt(Heap::kNSCMinAge))); // Reset age field. |
| 3935 __ mov(result, | 3953 __ mov(result, |
| 3936 FieldOperand(number_string_cache, | 3954 FieldOperand( |
| 3937 index, | 3955 number_string_cache, |
| 3938 times_twice_pointer_size, | 3956 index, |
| 3939 FixedArray::kHeaderSize + kPointerSize)); | 3957 times_1, |
| 3958 FixedArray::kHeaderSize + kPointerSize * Heap::kNSCStringOffset)); |
| 3940 Counters* counters = masm->isolate()->counters(); | 3959 Counters* counters = masm->isolate()->counters(); |
| 3941 __ IncrementCounter(counters->number_to_string_native(), 1); | 3960 __ IncrementCounter(counters->number_to_string_native(), 1); |
| 3942 } | 3961 } |
| 3943 | 3962 |
| 3944 | 3963 |
| 3945 void NumberToStringStub::Generate(MacroAssembler* masm) { | 3964 void NumberToStringStub::Generate(MacroAssembler* masm) { |
| 3946 Label runtime; | 3965 Label runtime; |
| 3947 | 3966 |
| 3948 __ mov(ebx, Operand(esp, kPointerSize)); | 3967 __ mov(ebx, Operand(esp, kPointerSize)); |
| 3949 | 3968 |
| (...skipping 3297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7247 // Restore registers. | 7266 // Restore registers. |
| 7248 __ pop(eax); | 7267 __ pop(eax); |
| 7249 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 7268 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 7250 } | 7269 } |
| 7251 | 7270 |
| 7252 #undef __ | 7271 #undef __ |
| 7253 | 7272 |
| 7254 } } // namespace v8::internal | 7273 } } // namespace v8::internal |
| 7255 | 7274 |
| 7256 #endif // V8_TARGET_ARCH_IA32 | 7275 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |