OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 30 matching lines...) Expand all Loading... |
41 // | 41 // |
42 | 42 |
43 #define __ ACCESS_MASM(masm) | 43 #define __ ACCESS_MASM(masm) |
44 | 44 |
45 | 45 |
46 // Helper function used to load a property from a dictionary backing storage. | 46 // Helper function used to load a property from a dictionary backing storage. |
47 // This function may return false negatives, so miss_label | 47 // This function may return false negatives, so miss_label |
48 // must always call a backup property load that is complete. | 48 // must always call a backup property load that is complete. |
49 // This function is safe to call if the receiver has fast properties, | 49 // This function is safe to call if the receiver has fast properties, |
50 // or if name is not a symbol, and will jump to the miss_label in that case. | 50 // or if name is not a symbol, and will jump to the miss_label in that case. |
51 static void GenerateDictionaryLoad(MacroAssembler* masm, | 51 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label, |
52 Label* miss_label, | 52 Register r0, Register r1, Register r2, |
53 Register r0, | 53 Register name) { |
54 Register r1, | |
55 Register r2, | |
56 Register name, | |
57 DictionaryCheck check_dictionary) { | |
58 // Register use: | 54 // Register use: |
59 // | 55 // |
60 // r0 - used to hold the property dictionary. | 56 // r0 - used to hold the property dictionary. |
61 // | 57 // |
62 // r1 - initially the receiver | 58 // r1 - initially the receiver |
63 // - used for the index into the property dictionary | 59 // - used for the index into the property dictionary |
64 // - holds the result on exit. | 60 // - holds the result on exit. |
65 // | 61 // |
66 // r2 - used to hold the capacity of the property dictionary. | 62 // r2 - used to hold the capacity of the property dictionary. |
67 // | 63 // |
(...skipping 15 matching lines...) Expand all Loading... |
83 __ movzx_b(r0, FieldOperand(r0, Map::kInstanceTypeOffset)); | 79 __ movzx_b(r0, FieldOperand(r0, Map::kInstanceTypeOffset)); |
84 __ cmp(r0, JS_GLOBAL_PROXY_TYPE); | 80 __ cmp(r0, JS_GLOBAL_PROXY_TYPE); |
85 __ j(equal, miss_label, not_taken); | 81 __ j(equal, miss_label, not_taken); |
86 | 82 |
87 // Possible work-around for http://crbug.com/16276. | 83 // Possible work-around for http://crbug.com/16276. |
88 __ cmp(r0, JS_GLOBAL_OBJECT_TYPE); | 84 __ cmp(r0, JS_GLOBAL_OBJECT_TYPE); |
89 __ j(equal, miss_label, not_taken); | 85 __ j(equal, miss_label, not_taken); |
90 __ cmp(r0, JS_BUILTINS_OBJECT_TYPE); | 86 __ cmp(r0, JS_BUILTINS_OBJECT_TYPE); |
91 __ j(equal, miss_label, not_taken); | 87 __ j(equal, miss_label, not_taken); |
92 | 88 |
93 // Load properties array. | 89 // Check that the properties array is a dictionary. |
94 __ mov(r0, FieldOperand(r1, JSObject::kPropertiesOffset)); | 90 __ mov(r0, FieldOperand(r1, JSObject::kPropertiesOffset)); |
95 | 91 __ cmp(FieldOperand(r0, HeapObject::kMapOffset), |
96 // Check that the properties array is a dictionary. | 92 Immediate(Factory::hash_table_map())); |
97 if (check_dictionary == CHECK_DICTIONARY) { | 93 __ j(not_equal, miss_label); |
98 __ cmp(FieldOperand(r0, HeapObject::kMapOffset), | |
99 Immediate(Factory::hash_table_map())); | |
100 __ j(not_equal, miss_label); | |
101 } | |
102 | 94 |
103 // Compute the capacity mask. | 95 // Compute the capacity mask. |
104 const int kCapacityOffset = | 96 const int kCapacityOffset = |
105 StringDictionary::kHeaderSize + | 97 StringDictionary::kHeaderSize + |
106 StringDictionary::kCapacityIndex * kPointerSize; | 98 StringDictionary::kCapacityIndex * kPointerSize; |
107 __ mov(r2, FieldOperand(r0, kCapacityOffset)); | 99 __ mov(r2, FieldOperand(r0, kCapacityOffset)); |
108 __ shr(r2, kSmiTagSize); // convert smi to int | 100 __ shr(r2, kSmiTagSize); // convert smi to int |
109 __ dec(r2); | 101 __ dec(r2); |
110 | 102 |
111 // Generate an unrolled loop that performs a few probes before | 103 // Generate an unrolled loop that performs a few probes before |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 216 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
225 } | 217 } |
226 | 218 |
227 | 219 |
228 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 220 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
229 // ----------- S t a t e ------------- | 221 // ----------- S t a t e ------------- |
230 // -- esp[0] : return address | 222 // -- esp[0] : return address |
231 // -- esp[4] : name | 223 // -- esp[4] : name |
232 // -- esp[8] : receiver | 224 // -- esp[8] : receiver |
233 // ----------------------------------- | 225 // ----------------------------------- |
234 Label slow, check_string, index_int, index_string; | 226 Label slow, check_string, index_int, index_string, check_pixel_array; |
235 Label check_pixel_array, probe_dictionary; | |
236 | 227 |
237 // Load name and receiver. | 228 // Load name and receiver. |
238 __ mov(eax, Operand(esp, kPointerSize)); | 229 __ mov(eax, Operand(esp, kPointerSize)); |
239 __ mov(ecx, Operand(esp, 2 * kPointerSize)); | 230 __ mov(ecx, Operand(esp, 2 * kPointerSize)); |
240 | 231 |
241 // Check that the object isn't a smi. | 232 // Check that the object isn't a smi. |
242 __ test(ecx, Immediate(kSmiTagMask)); | 233 __ test(ecx, Immediate(kSmiTagMask)); |
243 __ j(zero, &slow, not_taken); | 234 __ j(zero, &slow, not_taken); |
244 | 235 |
245 // Get the map of the receiver. | 236 // Get the map of the receiver. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 __ bind(&check_string); | 295 __ bind(&check_string); |
305 // The key is not a smi. | 296 // The key is not a smi. |
306 // Is it a string? | 297 // Is it a string? |
307 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); | 298 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); |
308 __ j(above_equal, &slow); | 299 __ j(above_equal, &slow); |
309 // Is the string an array index, with cached numeric value? | 300 // Is the string an array index, with cached numeric value? |
310 __ mov(ebx, FieldOperand(eax, String::kHashFieldOffset)); | 301 __ mov(ebx, FieldOperand(eax, String::kHashFieldOffset)); |
311 __ test(ebx, Immediate(String::kIsArrayIndexMask)); | 302 __ test(ebx, Immediate(String::kIsArrayIndexMask)); |
312 __ j(not_zero, &index_string, not_taken); | 303 __ j(not_zero, &index_string, not_taken); |
313 | 304 |
314 // Is the string a symbol? | 305 // If the string is a symbol, do a quick inline probe of the receiver's |
| 306 // dictionary, if it exists. |
315 __ movzx_b(ebx, FieldOperand(edx, Map::kInstanceTypeOffset)); | 307 __ movzx_b(ebx, FieldOperand(edx, Map::kInstanceTypeOffset)); |
316 __ test(ebx, Immediate(kIsSymbolMask)); | 308 __ test(ebx, Immediate(kIsSymbolMask)); |
317 __ j(zero, &slow, not_taken); | 309 __ j(zero, &slow, not_taken); |
318 | 310 // Probe the dictionary leaving result in ecx. |
319 // If the receiver is a fast-case object, check the keyed lookup | 311 GenerateDictionaryLoad(masm, &slow, ebx, ecx, edx, eax); |
320 // cache. Otherwise probe the dictionary leaving result in ecx. | |
321 __ mov(ebx, FieldOperand(ecx, JSObject::kPropertiesOffset)); | |
322 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | |
323 Immediate(Factory::hash_table_map())); | |
324 __ j(equal, &probe_dictionary); | |
325 | |
326 // Load the map of the receiver, compute the keyed lookup cache hash | |
327 // based on 32 bits of the map pointer and the string hash. | |
328 __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); | |
329 __ mov(edx, ebx); | |
330 __ shr(edx, KeyedLookupCache::kMapHashShift); | |
331 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); | |
332 __ shr(eax, String::kHashShift); | |
333 __ xor_(edx, Operand(eax)); | |
334 __ and_(edx, KeyedLookupCache::kCapacityMask); | |
335 | |
336 // Load the key (consisting of map and symbol) from the cache and | |
337 // check for match. | |
338 ExternalReference cache_keys | |
339 = ExternalReference::keyed_lookup_cache_keys(); | |
340 __ cmp(ebx, Operand::StaticArray(edx, two_times_pointer_size, cache_keys)); | |
341 __ j(not_equal, &slow); | |
342 __ mov(edi, Operand::StaticArray(edx, | |
343 two_times_pointer_size, | |
344 cache_keys, | |
345 kPointerSize)); | |
346 __ cmp(edi, Operand(esp, kPointerSize)); | |
347 __ j(not_equal, &slow); | |
348 | |
349 // Get field offset and check that it is an in-object property. | |
350 ExternalReference cache_field_offsets | |
351 = ExternalReference::keyed_lookup_cache_field_offsets(); | |
352 __ mov(eax, | |
353 Operand::StaticArray(edx, times_pointer_size, cache_field_offsets)); | |
354 __ movzx_b(edx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); | |
355 __ cmp(eax, Operand(edx)); | |
356 __ j(above_equal, &slow); | |
357 | |
358 // Load in-object property. | |
359 __ sub(eax, Operand(edx)); | |
360 __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceSizeOffset)); | |
361 __ add(eax, Operand(edx)); | |
362 __ mov(eax, FieldOperand(ecx, eax, times_pointer_size, 0)); | |
363 __ ret(0); | |
364 | |
365 // Do a quick inline probe of the receiver's dictionary, if it | |
366 // exists. | |
367 __ bind(&probe_dictionary); | |
368 GenerateDictionaryLoad(masm, | |
369 &slow, | |
370 ebx, | |
371 ecx, | |
372 edx, | |
373 eax, | |
374 DICTIONARY_CHECK_DONE); | |
375 GenerateCheckNonObjectOrLoaded(masm, &slow, ecx, edx); | 312 GenerateCheckNonObjectOrLoaded(masm, &slow, ecx, edx); |
376 __ mov(eax, Operand(ecx)); | 313 __ mov(eax, Operand(ecx)); |
377 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); | 314 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); |
378 __ ret(0); | 315 __ ret(0); |
379 | |
380 // If the hash field contains an array index pick it out. The assert checks | 316 // If the hash field contains an array index pick it out. The assert checks |
381 // that the constants for the maximum number of digits for an array index | 317 // that the constants for the maximum number of digits for an array index |
382 // cached in the hash field and the number of bits reserved for it does not | 318 // cached in the hash field and the number of bits reserved for it does not |
383 // conflict. | 319 // conflict. |
384 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | 320 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < |
385 (1 << String::kArrayIndexValueBits)); | 321 (1 << String::kArrayIndexValueBits)); |
386 __ bind(&index_string); | 322 __ bind(&index_string); |
387 __ mov(eax, Operand(ebx)); | 323 __ mov(eax, Operand(ebx)); |
388 __ and_(eax, String::kArrayIndexHashMask); | 324 __ and_(eax, String::kArrayIndexHashMask); |
389 __ shr(eax, String::kHashShift); | 325 __ shr(eax, String::kHashShift); |
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 __ bind(&miss); | 878 __ bind(&miss); |
943 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss))); | 879 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss))); |
944 } | 880 } |
945 | 881 |
946 | 882 |
947 static void GenerateNormalHelper(MacroAssembler* masm, | 883 static void GenerateNormalHelper(MacroAssembler* masm, |
948 int argc, | 884 int argc, |
949 bool is_global_object, | 885 bool is_global_object, |
950 Label* miss) { | 886 Label* miss) { |
951 // Search dictionary - put result in register edx. | 887 // Search dictionary - put result in register edx. |
952 GenerateDictionaryLoad(masm, miss, eax, edx, ebx, ecx, CHECK_DICTIONARY); | 888 GenerateDictionaryLoad(masm, miss, eax, edx, ebx, ecx); |
953 | 889 |
954 // Move the result to register edi and check that it isn't a smi. | 890 // Move the result to register edi and check that it isn't a smi. |
955 __ mov(edi, Operand(edx)); | 891 __ mov(edi, Operand(edx)); |
956 __ test(edx, Immediate(kSmiTagMask)); | 892 __ test(edx, Immediate(kSmiTagMask)); |
957 __ j(zero, miss, not_taken); | 893 __ j(zero, miss, not_taken); |
958 | 894 |
959 // Check that the value is a JavaScript function. | 895 // Check that the value is a JavaScript function. |
960 __ CmpObjectType(edx, JS_FUNCTION_TYPE, edx); | 896 __ CmpObjectType(edx, JS_FUNCTION_TYPE, edx); |
961 __ j(not_equal, miss, not_taken); | 897 __ j(not_equal, miss, not_taken); |
962 | 898 |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1145 __ cmp(edx, JS_GLOBAL_PROXY_TYPE); | 1081 __ cmp(edx, JS_GLOBAL_PROXY_TYPE); |
1146 __ j(equal, &global, not_taken); | 1082 __ j(equal, &global, not_taken); |
1147 | 1083 |
1148 // Check for non-global object that requires access check. | 1084 // Check for non-global object that requires access check. |
1149 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); | 1085 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); |
1150 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); | 1086 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); |
1151 __ j(not_zero, &miss, not_taken); | 1087 __ j(not_zero, &miss, not_taken); |
1152 | 1088 |
1153 // Search the dictionary placing the result in eax. | 1089 // Search the dictionary placing the result in eax. |
1154 __ bind(&probe); | 1090 __ bind(&probe); |
1155 GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx, CHECK_DICTIONARY); | 1091 GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx); |
1156 GenerateCheckNonObjectOrLoaded(masm, &miss, eax, edx); | 1092 GenerateCheckNonObjectOrLoaded(masm, &miss, eax, edx); |
1157 __ ret(0); | 1093 __ ret(0); |
1158 | 1094 |
1159 // Global object access: Check access rights. | 1095 // Global object access: Check access rights. |
1160 __ bind(&global); | 1096 __ bind(&global); |
1161 __ CheckAccessGlobalProxy(eax, edx, &miss); | 1097 __ CheckAccessGlobalProxy(eax, edx, &miss); |
1162 __ jmp(&probe); | 1098 __ jmp(&probe); |
1163 | 1099 |
1164 // Cache miss: Restore receiver from stack and jump to runtime. | 1100 // Cache miss: Restore receiver from stack and jump to runtime. |
1165 __ bind(&miss); | 1101 __ bind(&miss); |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1426 | 1362 |
1427 // Do tail-call to runtime routine. | 1363 // Do tail-call to runtime routine. |
1428 __ TailCallRuntime( | 1364 __ TailCallRuntime( |
1429 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1); | 1365 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1); |
1430 } | 1366 } |
1431 | 1367 |
1432 #undef __ | 1368 #undef __ |
1433 | 1369 |
1434 | 1370 |
1435 } } // namespace v8::internal | 1371 } } // namespace v8::internal |
OLD | NEW |