OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 10906 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10917 } | 10917 } |
10918 | 10918 |
10919 | 10919 |
10920 void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, | 10920 void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, |
10921 Register object, | 10921 Register object, |
10922 Register result, | 10922 Register result, |
10923 Register scratch1, | 10923 Register scratch1, |
10924 Register scratch2, | 10924 Register scratch2, |
10925 bool object_is_smi, | 10925 bool object_is_smi, |
10926 Label* not_found) { | 10926 Label* not_found) { |
10927 // Currently only lookup for smis. Check for smi if object is not known to be | |
10928 // a smi. | |
10929 if (!object_is_smi) { | |
10930 ASSERT(kSmiTag == 0); | |
10931 __ test(object, Immediate(kSmiTagMask)); | |
10932 __ j(not_zero, not_found); | |
10933 } | |
10934 | |
10935 // Use of registers. Register result is used as a temporary. | 10927 // Use of registers. Register result is used as a temporary. |
10936 Register number_string_cache = result; | 10928 Register number_string_cache = result; |
10937 Register mask = scratch1; | 10929 Register mask = scratch1; |
10938 Register scratch = scratch2; | 10930 Register scratch = scratch2; |
10939 | 10931 |
10940 // Load the number string cache. | 10932 // Load the number string cache. |
10941 ExternalReference roots_address = ExternalReference::roots_address(); | 10933 ExternalReference roots_address = ExternalReference::roots_address(); |
10942 __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex)); | 10934 __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex)); |
10943 __ mov(number_string_cache, | 10935 __ mov(number_string_cache, |
10944 Operand::StaticArray(scratch, times_pointer_size, roots_address)); | 10936 Operand::StaticArray(scratch, times_pointer_size, roots_address)); |
10945 // Make the hash mask from the length of the number string cache. It | 10937 // Make the hash mask from the length of the number string cache. It |
10946 // contains two elements (number and string) for each cache entry. | 10938 // contains two elements (number and string) for each cache entry. |
10947 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); | 10939 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); |
10948 __ shr(mask, 1); // Divide length by two (length is not a smi). | 10940 __ shr(mask, 1); // Divide length by two (length is not a smi). |
10949 __ sub(Operand(mask), Immediate(1)); // Make mask. | 10941 __ sub(Operand(mask), Immediate(1)); // Make mask. |
| 10942 |
10950 // Calculate the entry in the number string cache. The hash value in the | 10943 // Calculate the entry in the number string cache. The hash value in the |
10951 // number string cache for smis is just the smi value. | 10944 // number string cache for smis is just the smi value, and the hash for |
10952 __ mov(scratch, object); | 10945 // doubles is the xor of the upper and lower words. See |
10953 __ SmiUntag(scratch); | 10946 // Heap::GetNumberStringCache. |
| 10947 Label smi_hash_calculated; |
| 10948 Label load_result_from_cache; |
| 10949 if (object_is_smi) { |
| 10950 __ mov(scratch, object); |
| 10951 __ SmiUntag(scratch); |
| 10952 } else { |
| 10953 Label not_smi, hash_calculated; |
| 10954 ASSERT(kSmiTag == 0); |
| 10955 __ test(object, Immediate(kSmiTagMask)); |
| 10956 __ j(not_zero, ¬_smi); |
| 10957 __ mov(scratch, object); |
| 10958 __ SmiUntag(scratch); |
| 10959 __ jmp(&smi_hash_calculated); |
| 10960 __ bind(¬_smi); |
| 10961 __ cmp(FieldOperand(object, HeapObject::kMapOffset), |
| 10962 Factory::heap_number_map()); |
| 10963 __ j(not_equal, not_found); |
| 10964 ASSERT_EQ(8, kDoubleSize); |
| 10965 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset)); |
| 10966 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); |
| 10967 // Object is heap number and hash is now in scratch. Calculate cache index. |
| 10968 __ and_(scratch, Operand(mask)); |
| 10969 Register index = scratch; |
| 10970 Register probe = mask; |
| 10971 __ mov(probe, |
| 10972 FieldOperand(number_string_cache, |
| 10973 index, |
| 10974 times_twice_pointer_size, |
| 10975 FixedArray::kHeaderSize)); |
| 10976 __ test(probe, Immediate(kSmiTagMask)); |
| 10977 __ j(zero, not_found); |
| 10978 if (CpuFeatures::IsSupported(SSE2)) { |
| 10979 CpuFeatures::Scope fscope(SSE2); |
| 10980 __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); |
| 10981 __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); |
| 10982 __ comisd(xmm0, xmm1); |
| 10983 } else { |
| 10984 __ fld_d(FieldOperand(object, HeapNumber::kValueOffset)); |
| 10985 __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset)); |
| 10986 __ FCmp(); |
| 10987 } |
| 10988 __ j(parity_even, not_found); // Bail out if NaN is involved. |
| 10989 __ j(not_equal, not_found); // The cache did not contain this value. |
| 10990 __ jmp(&load_result_from_cache); |
| 10991 } |
| 10992 |
| 10993 __ bind(&smi_hash_calculated); |
| 10994 // Object is smi and hash is now in scratch. Calculate cache index. |
10954 __ and_(scratch, Operand(mask)); | 10995 __ and_(scratch, Operand(mask)); |
| 10996 Register index = scratch; |
10955 // Check if the entry is the smi we are looking for. | 10997 // Check if the entry is the smi we are looking for. |
10956 __ cmp(object, | 10998 __ cmp(object, |
10957 FieldOperand(number_string_cache, | 10999 FieldOperand(number_string_cache, |
10958 scratch, | 11000 index, |
10959 times_twice_pointer_size, | 11001 times_twice_pointer_size, |
10960 FixedArray::kHeaderSize)); | 11002 FixedArray::kHeaderSize)); |
10961 __ j(not_equal, not_found); | 11003 __ j(not_equal, not_found); |
10962 | 11004 |
10963 // Get the result from the cache. | 11005 // Get the result from the cache. |
| 11006 __ bind(&load_result_from_cache); |
10964 __ mov(result, | 11007 __ mov(result, |
10965 FieldOperand(number_string_cache, | 11008 FieldOperand(number_string_cache, |
10966 scratch, | 11009 index, |
10967 times_twice_pointer_size, | 11010 times_twice_pointer_size, |
10968 FixedArray::kHeaderSize + kPointerSize)); | 11011 FixedArray::kHeaderSize + kPointerSize)); |
10969 __ IncrementCounter(&Counters::number_to_string_native, 1); | 11012 __ IncrementCounter(&Counters::number_to_string_native, 1); |
10970 } | 11013 } |
10971 | 11014 |
10972 | 11015 |
10973 void NumberToStringStub::Generate(MacroAssembler* masm) { | 11016 void NumberToStringStub::Generate(MacroAssembler* masm) { |
10974 Label runtime; | 11017 Label runtime; |
10975 | 11018 |
10976 __ mov(ebx, Operand(esp, kPointerSize)); | 11019 __ mov(ebx, Operand(esp, kPointerSize)); |
10977 | 11020 |
10978 // Generate code to lookup number in the number string cache. | 11021 // Generate code to lookup number in the number string cache. |
10979 GenerateLookupNumberStringCache(masm, ebx, eax, ecx, edx, false, &runtime); | 11022 GenerateLookupNumberStringCache(masm, ebx, eax, ecx, edx, false, &runtime); |
10980 __ ret(1 * kPointerSize); | 11023 __ ret(1 * kPointerSize); |
10981 | 11024 |
10982 __ bind(&runtime); | 11025 __ bind(&runtime); |
10983 // Handle number to string in the runtime system if not found in the cache. | 11026 // Handle number to string in the runtime system if not found in the cache. |
10984 __ TailCallRuntime(Runtime::kNumberToString, 1, 1); | 11027 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); |
10985 } | 11028 } |
10986 | 11029 |
10987 | 11030 |
10988 void RecordWriteStub::Generate(MacroAssembler* masm) { | 11031 void RecordWriteStub::Generate(MacroAssembler* masm) { |
10989 masm->RecordWriteHelper(object_, addr_, scratch_); | 11032 masm->RecordWriteHelper(object_, addr_, scratch_); |
10990 masm->ret(0); | 11033 masm->ret(0); |
10991 } | 11034 } |
10992 | 11035 |
10993 | 11036 |
10994 void CompareStub::Generate(MacroAssembler* masm) { | 11037 void CompareStub::Generate(MacroAssembler* masm) { |
(...skipping 1600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12595 | 12638 |
12596 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 12639 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
12597 // tagged as a small integer. | 12640 // tagged as a small integer. |
12598 __ bind(&runtime); | 12641 __ bind(&runtime); |
12599 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 12642 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
12600 } | 12643 } |
12601 | 12644 |
12602 #undef __ | 12645 #undef __ |
12603 | 12646 |
12604 } } // namespace v8::internal | 12647 } } // namespace v8::internal |
OLD | NEW |