| 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 2912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2923 Label* not_found) { | 2923 Label* not_found) { |
| 2924 // Use of registers. Register result is used as a temporary. | 2924 // Use of registers. Register result is used as a temporary. |
| 2925 Register number_string_cache = result; | 2925 Register number_string_cache = result; |
| 2926 Register mask = scratch1; | 2926 Register mask = scratch1; |
| 2927 Register scratch = scratch2; | 2927 Register scratch = scratch2; |
| 2928 | 2928 |
| 2929 // Load the number string cache. | 2929 // Load the number string cache. |
| 2930 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); | 2930 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); |
| 2931 | 2931 |
| 2932 // Make the hash mask from the length of the number string cache. It | 2932 // Make the hash mask from the length of the number string cache. It |
| 2933 // contains two elements (number and string) for each cache entry. | 2933 // contains three elements (number, string and age) for each cache entry. |
| 2934 __ SmiToInteger32( | 2934 __ SmiToInteger32( |
| 2935 mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); | 2935 scratch, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); |
| 2936 __ shrl(mask, Immediate(1)); | 2936 |
| 2937 __ subq(mask, Immediate(1)); // Make mask. | 2937 STATIC_ASSERT(Heap::kNSCSlotsPerEntry == 3); |
| 2938 // mask = scratch / 3 - 1, making it one less than a power of 2. |
| 2939 __ lea(mask, Operand(scratch, -1)); |
| 2940 __ and_(scratch, mask); |
| 2941 __ xor_(mask, scratch); |
| 2938 | 2942 |
| 2939 // Calculate the entry in the number string cache. The hash value in the | 2943 // Calculate the entry in the number string cache. The hash value in the |
| 2940 // number string cache for smis is just the smi value, and the hash for | 2944 // number string cache for smis is just the smi value, and the hash for |
| 2941 // doubles is the xor of the upper and lower words. See | 2945 // doubles is the xor of the upper and lower words. See |
| 2942 // Heap::GetNumberStringCache. | 2946 // Heap::GetNumberStringCache. |
| 2943 Label is_smi; | 2947 Label is_smi; |
| 2944 Label load_result_from_cache; | 2948 Label load_result_from_cache; |
| 2945 Factory* factory = masm->isolate()->factory(); | 2949 Factory* factory = masm->isolate()->factory(); |
| 2946 if (!object_is_smi) { | 2950 if (!object_is_smi) { |
| 2947 __ JumpIfSmi(object, &is_smi); | 2951 __ JumpIfSmi(object, &is_smi); |
| 2948 __ CheckMap(object, | 2952 __ CheckMap(object, |
| 2949 factory->heap_number_map(), | 2953 factory->heap_number_map(), |
| 2950 not_found, | 2954 not_found, |
| 2951 DONT_DO_SMI_CHECK); | 2955 DONT_DO_SMI_CHECK); |
| 2952 | 2956 |
| 2953 STATIC_ASSERT(8 == kDoubleSize); | 2957 STATIC_ASSERT(8 == kDoubleSize); |
| 2954 __ movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); | 2958 __ movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); |
| 2955 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset)); | 2959 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset)); |
| 2956 GenerateConvertHashCodeToIndex(masm, scratch, mask); | 2960 GenerateConvertHashCodeToIndex(masm, scratch, mask); |
| 2957 | 2961 |
| 2958 Register index = scratch; | 2962 Register index = scratch; |
| 2959 Register probe = mask; | 2963 Register probe = mask; |
| 2960 __ movq(probe, | 2964 __ movq(probe, FieldOperand( |
| 2961 FieldOperand(number_string_cache, | 2965 number_string_cache, |
| 2962 index, | 2966 index, |
| 2963 times_1, | 2967 times_pointer_size, |
| 2964 FixedArray::kHeaderSize)); | 2968 FixedArray::kHeaderSize + kPointerSize * Heap::kNSCNumberOffset)); |
| 2965 __ JumpIfSmi(probe, not_found); | 2969 __ JumpIfSmi(probe, not_found); |
| 2966 __ movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); | 2970 __ movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); |
| 2967 __ movsd(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); | 2971 __ movsd(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); |
| 2968 __ ucomisd(xmm0, xmm1); | 2972 __ ucomisd(xmm0, xmm1); |
| 2969 __ j(parity_even, not_found); // Bail out if NaN is involved. | 2973 __ j(parity_even, not_found); // Bail out if NaN is involved. |
| 2970 __ j(not_equal, not_found); // The cache did not contain this value. | 2974 __ j(not_equal, not_found); // The cache did not contain this value. |
| 2971 __ jmp(&load_result_from_cache); | 2975 __ jmp(&load_result_from_cache); |
| 2972 } | 2976 } |
| 2973 | 2977 |
| 2974 __ bind(&is_smi); | 2978 __ bind(&is_smi); |
| 2975 __ SmiToInteger32(scratch, object); | 2979 __ SmiToInteger32(scratch, object); |
| 2976 GenerateConvertHashCodeToIndex(masm, scratch, mask); | 2980 GenerateConvertHashCodeToIndex(masm, scratch, mask); |
| 2977 | 2981 |
| 2978 Register index = scratch; | 2982 Register index = scratch; |
| 2979 // Check if the entry is the smi we are looking for. | 2983 // Check if the entry is the smi we are looking for. |
| 2980 __ cmpq(object, | 2984 __ cmpq(object, FieldOperand( |
| 2981 FieldOperand(number_string_cache, | 2985 number_string_cache, |
| 2982 index, | 2986 index, |
| 2983 times_1, | 2987 times_pointer_size, |
| 2984 FixedArray::kHeaderSize)); | 2988 FixedArray::kHeaderSize + kPointerSize * Heap::kNSCNumberOffset)); |
| 2985 __ j(not_equal, not_found); | 2989 __ j(not_equal, not_found); |
| 2986 | 2990 |
| 2987 // Get the result from the cache. | 2991 // Get the result from the cache. |
| 2988 __ bind(&load_result_from_cache); | 2992 __ bind(&load_result_from_cache); |
| 2989 __ movq(result, | 2993 int kAgeOffset = FixedArray::kHeaderSize + kPointerSize * Heap::kNSCAgeOffset; |
| 2990 FieldOperand(number_string_cache, | 2994 __ Move(FieldOperand(number_string_cache, |
| 2991 index, | 2995 index, |
| 2992 times_1, | 2996 times_pointer_size, |
| 2993 FixedArray::kHeaderSize + kPointerSize)); | 2997 kAgeOffset), |
| 2998 Smi::FromInt(Heap::kNSCMinAge)); // Reset age field. |
| 2999 __ movq(result, FieldOperand( |
| 3000 number_string_cache, |
| 3001 index, |
| 3002 times_pointer_size, |
| 3003 FixedArray::kHeaderSize + kPointerSize * Heap::kNSCStringOffset)); |
| 2994 Counters* counters = masm->isolate()->counters(); | 3004 Counters* counters = masm->isolate()->counters(); |
| 2995 __ IncrementCounter(counters->number_to_string_native(), 1); | 3005 __ IncrementCounter(counters->number_to_string_native(), 1); |
| 2996 } | 3006 } |
| 2997 | 3007 |
| 2998 | 3008 |
| 2999 void NumberToStringStub::GenerateConvertHashCodeToIndex(MacroAssembler* masm, | 3009 void NumberToStringStub::GenerateConvertHashCodeToIndex(MacroAssembler* masm, |
| 3000 Register hash, | 3010 Register hash, |
| 3001 Register mask) { | 3011 Register mask) { |
| 3002 __ and_(hash, mask); | 3012 __ and_(hash, mask); |
| 3003 // Each entry in string cache consists of two pointer sized fields, | 3013 // Each entry in string cache consists of three pointer sized fields, |
| 3004 // but times_twice_pointer_size (multiplication by 16) scale factor | 3014 // so we multiply by 3 and we will use times_pointer_size scaling. |
| 3005 // is not supported by addrmode on x64 platform. | 3015 __ lea(hash, Operand(hash, hash, times_2, 0)); |
| 3006 // So we have to premultiply entry index before lookup. | |
| 3007 __ shl(hash, Immediate(kPointerSizeLog2 + 1)); | |
| 3008 } | 3016 } |
| 3009 | 3017 |
| 3010 | 3018 |
| 3011 void NumberToStringStub::Generate(MacroAssembler* masm) { | 3019 void NumberToStringStub::Generate(MacroAssembler* masm) { |
| 3012 Label runtime; | 3020 Label runtime; |
| 3013 | 3021 |
| 3014 __ movq(rbx, Operand(rsp, kPointerSize)); | 3022 __ movq(rbx, Operand(rsp, kPointerSize)); |
| 3015 | 3023 |
| 3016 // Generate code to lookup number in the number string cache. | 3024 // Generate code to lookup number in the number string cache. |
| 3017 GenerateLookupNumberStringCache(masm, rbx, rax, r8, r9, false, &runtime); | 3025 GenerateLookupNumberStringCache(masm, rbx, rax, r8, r9, false, &runtime); |
| (...skipping 3074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6092 OMIT_SMI_CHECK); | 6100 OMIT_SMI_CHECK); |
| 6093 __ pop(rax); | 6101 __ pop(rax); |
| 6094 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 6102 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 6095 } | 6103 } |
| 6096 | 6104 |
| 6097 #undef __ | 6105 #undef __ |
| 6098 | 6106 |
| 6099 } } // namespace v8::internal | 6107 } } // namespace v8::internal |
| 6100 | 6108 |
| 6101 #endif // V8_TARGET_ARCH_X64 | 6109 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |