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 1008 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1019 __ Ret(); | 1019 __ Ret(); |
1020 } | 1020 } |
1021 | 1021 |
1022 | 1022 |
1023 void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, | 1023 void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, |
1024 Register object, | 1024 Register object, |
1025 Register result, | 1025 Register result, |
1026 Register scratch1, | 1026 Register scratch1, |
1027 Register scratch2, | 1027 Register scratch2, |
1028 Register scratch3, | 1028 Register scratch3, |
1029 bool object_is_smi, | |
1030 Label* not_found) { | 1029 Label* not_found) { |
1031 // Use of registers. Register result is used as a temporary. | 1030 // Use of registers. Register result is used as a temporary. |
1032 Register number_string_cache = result; | 1031 Register number_string_cache = result; |
1033 Register mask = scratch3; | 1032 Register mask = scratch3; |
1034 | 1033 |
1035 // Load the number string cache. | 1034 // Load the number string cache. |
1036 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); | 1035 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); |
1037 | 1036 |
1038 // Make the hash mask from the length of the number string cache. It | 1037 // Make the hash mask from the length of the number string cache. It |
1039 // contains two elements (number and string) for each cache entry. | 1038 // contains two elements (number and string) for each cache entry. |
1040 __ ldr(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset)); | 1039 __ ldr(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset)); |
1041 // Divide length by two (length is a smi). | 1040 // Divide length by two (length is a smi). |
1042 __ mov(mask, Operand(mask, ASR, kSmiTagSize + 1)); | 1041 __ mov(mask, Operand(mask, ASR, kSmiTagSize + 1)); |
1043 __ sub(mask, mask, Operand(1)); // Make mask. | 1042 __ sub(mask, mask, Operand(1)); // Make mask. |
1044 | 1043 |
1045 // Calculate the entry in the number string cache. The hash value in the | 1044 // Calculate the entry in the number string cache. The hash value in the |
1046 // number string cache for smis is just the smi value, and the hash for | 1045 // number string cache for smis is just the smi value, and the hash for |
1047 // doubles is the xor of the upper and lower words. See | 1046 // doubles is the xor of the upper and lower words. See |
1048 // Heap::GetNumberStringCache. | 1047 // Heap::GetNumberStringCache. |
1049 Isolate* isolate = masm->isolate(); | 1048 Isolate* isolate = masm->isolate(); |
1050 Label is_smi; | 1049 Label is_smi; |
1051 Label load_result_from_cache; | 1050 Label load_result_from_cache; |
1052 if (!object_is_smi) { | 1051 __ JumpIfSmi(object, &is_smi); |
1053 __ JumpIfSmi(object, &is_smi); | 1052 __ CheckMap(object, |
1054 __ CheckMap(object, | 1053 scratch1, |
1055 scratch1, | 1054 Heap::kHeapNumberMapRootIndex, |
1056 Heap::kHeapNumberMapRootIndex, | 1055 not_found, |
1057 not_found, | 1056 DONT_DO_SMI_CHECK); |
1058 DONT_DO_SMI_CHECK); | |
1059 | 1057 |
1060 STATIC_ASSERT(8 == kDoubleSize); | 1058 STATIC_ASSERT(8 == kDoubleSize); |
1061 __ add(scratch1, | 1059 __ add(scratch1, |
1062 object, | 1060 object, |
1063 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); | 1061 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); |
1064 __ ldm(ia, scratch1, scratch1.bit() | scratch2.bit()); | 1062 __ ldm(ia, scratch1, scratch1.bit() | scratch2.bit()); |
1065 __ eor(scratch1, scratch1, Operand(scratch2)); | 1063 __ eor(scratch1, scratch1, Operand(scratch2)); |
1066 __ and_(scratch1, scratch1, Operand(mask)); | 1064 __ and_(scratch1, scratch1, Operand(mask)); |
1067 | 1065 |
1068 // Calculate address of entry in string cache: each entry consists | 1066 // Calculate address of entry in string cache: each entry consists |
1069 // of two pointer sized fields. | 1067 // of two pointer sized fields. |
1070 __ add(scratch1, | 1068 __ add(scratch1, |
1071 number_string_cache, | 1069 number_string_cache, |
1072 Operand(scratch1, LSL, kPointerSizeLog2 + 1)); | 1070 Operand(scratch1, LSL, kPointerSizeLog2 + 1)); |
1073 | 1071 |
1074 Register probe = mask; | 1072 Register probe = mask; |
1075 __ ldr(probe, | 1073 __ ldr(probe, |
1076 FieldMemOperand(scratch1, FixedArray::kHeaderSize)); | 1074 FieldMemOperand(scratch1, FixedArray::kHeaderSize)); |
1077 __ JumpIfSmi(probe, not_found); | 1075 __ JumpIfSmi(probe, not_found); |
1078 __ sub(scratch2, object, Operand(kHeapObjectTag)); | 1076 __ sub(scratch2, object, Operand(kHeapObjectTag)); |
1079 __ vldr(d0, scratch2, HeapNumber::kValueOffset); | 1077 __ vldr(d0, scratch2, HeapNumber::kValueOffset); |
1080 __ sub(probe, probe, Operand(kHeapObjectTag)); | 1078 __ sub(probe, probe, Operand(kHeapObjectTag)); |
1081 __ vldr(d1, probe, HeapNumber::kValueOffset); | 1079 __ vldr(d1, probe, HeapNumber::kValueOffset); |
1082 __ VFPCompareAndSetFlags(d0, d1); | 1080 __ VFPCompareAndSetFlags(d0, d1); |
1083 __ b(ne, not_found); // The cache did not contain this value. | 1081 __ b(ne, not_found); // The cache did not contain this value. |
1084 __ b(&load_result_from_cache); | 1082 __ b(&load_result_from_cache); |
1085 } | |
1086 | 1083 |
1087 __ bind(&is_smi); | 1084 __ bind(&is_smi); |
1088 Register scratch = scratch1; | 1085 Register scratch = scratch1; |
1089 __ and_(scratch, mask, Operand(object, ASR, 1)); | 1086 __ and_(scratch, mask, Operand(object, ASR, 1)); |
1090 // Calculate address of entry in string cache: each entry consists | 1087 // Calculate address of entry in string cache: each entry consists |
1091 // of two pointer sized fields. | 1088 // of two pointer sized fields. |
1092 __ add(scratch, | 1089 __ add(scratch, |
1093 number_string_cache, | 1090 number_string_cache, |
1094 Operand(scratch, LSL, kPointerSizeLog2 + 1)); | 1091 Operand(scratch, LSL, kPointerSizeLog2 + 1)); |
1095 | 1092 |
1096 // Check if the entry is the smi we are looking for. | 1093 // Check if the entry is the smi we are looking for. |
1097 Register probe = mask; | |
1098 __ ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); | 1094 __ ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); |
1099 __ cmp(object, probe); | 1095 __ cmp(object, probe); |
1100 __ b(ne, not_found); | 1096 __ b(ne, not_found); |
1101 | 1097 |
1102 // Get the result from the cache. | 1098 // Get the result from the cache. |
1103 __ bind(&load_result_from_cache); | 1099 __ bind(&load_result_from_cache); |
1104 __ ldr(result, | 1100 __ ldr(result, |
1105 FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); | 1101 FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); |
1106 __ IncrementCounter(isolate->counters()->number_to_string_native(), | 1102 __ IncrementCounter(isolate->counters()->number_to_string_native(), |
1107 1, | 1103 1, |
1108 scratch1, | 1104 scratch1, |
1109 scratch2); | 1105 scratch2); |
1110 } | 1106 } |
1111 | 1107 |
1112 | 1108 |
1113 void NumberToStringStub::Generate(MacroAssembler* masm) { | 1109 void NumberToStringStub::Generate(MacroAssembler* masm) { |
1114 Label runtime; | 1110 Label runtime; |
1115 | 1111 |
1116 __ ldr(r1, MemOperand(sp, 0)); | 1112 __ ldr(r1, MemOperand(sp, 0)); |
1117 | 1113 |
1118 // Generate code to lookup number in the number string cache. | 1114 // Generate code to lookup number in the number string cache. |
1119 GenerateLookupNumberStringCache(masm, r1, r0, r2, r3, r4, false, &runtime); | 1115 GenerateLookupNumberStringCache(masm, r1, r0, r2, r3, r4, &runtime); |
1120 __ add(sp, sp, Operand(1 * kPointerSize)); | 1116 __ add(sp, sp, Operand(1 * kPointerSize)); |
1121 __ Ret(); | 1117 __ Ret(); |
1122 | 1118 |
1123 __ bind(&runtime); | 1119 __ bind(&runtime); |
1124 // Handle number to string in the runtime system if not found in the cache. | 1120 // Handle number to string in the runtime system if not found in the cache. |
1125 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); | 1121 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); |
1126 } | 1122 } |
1127 | 1123 |
1128 | 1124 |
1129 static void ICCompareStub_CheckInputType(MacroAssembler* masm, | 1125 static void ICCompareStub_CheckInputType(MacroAssembler* masm, |
(...skipping 4727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5857 // Check the number to string cache. | 5853 // Check the number to string cache. |
5858 Label not_cached; | 5854 Label not_cached; |
5859 __ bind(¬_string); | 5855 __ bind(¬_string); |
5860 // Puts the cached result into scratch1. | 5856 // Puts the cached result into scratch1. |
5861 NumberToStringStub::GenerateLookupNumberStringCache(masm, | 5857 NumberToStringStub::GenerateLookupNumberStringCache(masm, |
5862 arg, | 5858 arg, |
5863 scratch1, | 5859 scratch1, |
5864 scratch2, | 5860 scratch2, |
5865 scratch3, | 5861 scratch3, |
5866 scratch4, | 5862 scratch4, |
5867 false, | |
5868 ¬_cached); | 5863 ¬_cached); |
5869 __ mov(arg, scratch1); | 5864 __ mov(arg, scratch1); |
5870 __ str(arg, MemOperand(sp, stack_offset)); | 5865 __ str(arg, MemOperand(sp, stack_offset)); |
5871 __ jmp(&done); | 5866 __ jmp(&done); |
5872 | 5867 |
5873 // Check if the argument is a safe string wrapper. | 5868 // Check if the argument is a safe string wrapper. |
5874 __ bind(¬_cached); | 5869 __ bind(¬_cached); |
5875 __ JumpIfSmi(arg, slow); | 5870 __ JumpIfSmi(arg, slow); |
5876 __ CompareObjectType( | 5871 __ CompareObjectType( |
5877 arg, scratch1, scratch2, JS_VALUE_TYPE); // map -> scratch1. | 5872 arg, scratch1, scratch2, JS_VALUE_TYPE); // map -> scratch1. |
(...skipping 1332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7210 __ bind(&fast_elements_case); | 7205 __ bind(&fast_elements_case); |
7211 GenerateCase(masm, FAST_ELEMENTS); | 7206 GenerateCase(masm, FAST_ELEMENTS); |
7212 } | 7207 } |
7213 | 7208 |
7214 | 7209 |
7215 #undef __ | 7210 #undef __ |
7216 | 7211 |
7217 } } // namespace v8::internal | 7212 } } // namespace v8::internal |
7218 | 7213 |
7219 #endif // V8_TARGET_ARCH_ARM | 7214 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |