OLD | NEW |
---|---|
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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, Label* miss_label, | 51 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label, |
52 Register r0, Register r1, Register r2, | 52 Register r0, Register r1, Register r2, |
53 Register name) { | 53 Register name, bool check_dictionary) { |
Erik Corry
2009/12/09 10:43:40
Use enum.
| |
54 // Register use: | 54 // Register use: |
55 // | 55 // |
56 // r0 - used to hold the property dictionary. | 56 // r0 - used to hold the property dictionary. |
57 // | 57 // |
58 // r1 - initially the receiver | 58 // r1 - initially the receiver |
59 // - used for the index into the property dictionary | 59 // - used for the index into the property dictionary |
60 // - holds the result on exit. | 60 // - holds the result on exit. |
61 // | 61 // |
62 // r2 - used to hold the capacity of the property dictionary. | 62 // r2 - used to hold the capacity of the property dictionary. |
63 // | 63 // |
(...skipping 15 matching lines...) Expand all Loading... | |
79 __ movzxbq(r0, FieldOperand(r0, Map::kInstanceTypeOffset)); | 79 __ movzxbq(r0, FieldOperand(r0, Map::kInstanceTypeOffset)); |
80 __ cmpb(r0, Immediate(JS_GLOBAL_PROXY_TYPE)); | 80 __ cmpb(r0, Immediate(JS_GLOBAL_PROXY_TYPE)); |
81 __ j(equal, miss_label); | 81 __ j(equal, miss_label); |
82 | 82 |
83 // Possible work-around for http://crbug.com/16276. | 83 // Possible work-around for http://crbug.com/16276. |
84 __ cmpb(r0, Immediate(JS_GLOBAL_OBJECT_TYPE)); | 84 __ cmpb(r0, Immediate(JS_GLOBAL_OBJECT_TYPE)); |
85 __ j(equal, miss_label); | 85 __ j(equal, miss_label); |
86 __ cmpb(r0, Immediate(JS_BUILTINS_OBJECT_TYPE)); | 86 __ cmpb(r0, Immediate(JS_BUILTINS_OBJECT_TYPE)); |
87 __ j(equal, miss_label); | 87 __ j(equal, miss_label); |
88 | 88 |
89 // Check that the properties array is a dictionary. | 89 // Load properties array. |
90 __ movq(r0, FieldOperand(r1, JSObject::kPropertiesOffset)); | 90 __ movq(r0, FieldOperand(r1, JSObject::kPropertiesOffset)); |
91 __ Cmp(FieldOperand(r0, HeapObject::kMapOffset), Factory::hash_table_map()); | 91 |
92 __ j(not_equal, miss_label); | 92 if (check_dictionary) { |
93 // Check that the properties array is a dictionary. | |
94 __ Cmp(FieldOperand(r0, HeapObject::kMapOffset), Factory::hash_table_map()); | |
95 __ j(not_equal, miss_label); | |
96 } | |
93 | 97 |
94 // Compute the capacity mask. | 98 // Compute the capacity mask. |
95 const int kCapacityOffset = | 99 const int kCapacityOffset = |
96 StringDictionary::kHeaderSize + | 100 StringDictionary::kHeaderSize + |
97 StringDictionary::kCapacityIndex * kPointerSize; | 101 StringDictionary::kCapacityIndex * kPointerSize; |
98 __ movq(r2, FieldOperand(r0, kCapacityOffset)); | 102 __ movq(r2, FieldOperand(r0, kCapacityOffset)); |
99 __ SmiToInteger32(r2, r2); | 103 __ SmiToInteger32(r2, r2); |
100 __ decl(r2); | 104 __ decl(r2); |
101 | 105 |
102 // Generate an unrolled loop that performs a few probes before | 106 // Generate an unrolled loop that performs a few probes before |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
239 __ TailCallRuntime(f, 2, 1); | 243 __ TailCallRuntime(f, 2, 1); |
240 } | 244 } |
241 | 245 |
242 | 246 |
243 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 247 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
244 // ----------- S t a t e ------------- | 248 // ----------- S t a t e ------------- |
245 // -- rsp[0] : return address | 249 // -- rsp[0] : return address |
246 // -- rsp[8] : name | 250 // -- rsp[8] : name |
247 // -- rsp[16] : receiver | 251 // -- rsp[16] : receiver |
248 // ----------------------------------- | 252 // ----------------------------------- |
249 Label slow, check_string, index_int, index_string, check_pixel_array; | 253 Label slow, check_string, index_int, index_string; |
254 Label check_pixel_array, probe_dictionary; | |
250 | 255 |
251 // Load name and receiver. | 256 // Load name and receiver. |
252 __ movq(rax, Operand(rsp, kPointerSize)); | 257 __ movq(rax, Operand(rsp, kPointerSize)); |
253 __ movq(rcx, Operand(rsp, 2 * kPointerSize)); | 258 __ movq(rcx, Operand(rsp, 2 * kPointerSize)); |
254 | 259 |
255 // Check that the object isn't a smi. | 260 // Check that the object isn't a smi. |
256 __ JumpIfSmi(rcx, &slow); | 261 __ JumpIfSmi(rcx, &slow); |
257 | 262 |
258 // Check that the object is some kind of JS object EXCEPT JS Value type. | 263 // Check that the object is some kind of JS object EXCEPT JS Value type. |
259 // In the case that the object is a value-wrapper object, | 264 // In the case that the object is a value-wrapper object, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
312 Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); | 317 Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); |
313 __ bind(&check_string); | 318 __ bind(&check_string); |
314 // The key is not a smi. | 319 // The key is not a smi. |
315 // Is it a string? | 320 // Is it a string? |
316 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); | 321 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); |
317 __ j(above_equal, &slow); | 322 __ j(above_equal, &slow); |
318 // Is the string an array index, with cached numeric value? | 323 // Is the string an array index, with cached numeric value? |
319 __ movl(rbx, FieldOperand(rax, String::kHashFieldOffset)); | 324 __ movl(rbx, FieldOperand(rax, String::kHashFieldOffset)); |
320 __ testl(rbx, Immediate(String::kIsArrayIndexMask)); | 325 __ testl(rbx, Immediate(String::kIsArrayIndexMask)); |
321 | 326 |
322 // If the string is a symbol, do a quick inline probe of the receiver's | 327 // Is the string a symbol? |
323 // dictionary, if it exists. | |
324 __ j(not_zero, &index_string); // The value in rbx is used at jump target. | 328 __ j(not_zero, &index_string); // The value in rbx is used at jump target. |
325 __ testb(FieldOperand(rdx, Map::kInstanceTypeOffset), | 329 __ testb(FieldOperand(rdx, Map::kInstanceTypeOffset), |
326 Immediate(kIsSymbolMask)); | 330 Immediate(kIsSymbolMask)); |
327 __ j(zero, &slow); | 331 __ j(zero, &slow); |
328 // Probe the dictionary leaving result in rcx. | 332 |
329 GenerateDictionaryLoad(masm, &slow, rbx, rcx, rdx, rax); | 333 // If the receiver is a fast-case object, check the keyed lookup |
334 // cache. Otherwise probe the dictionary leaving result in rcx. | |
335 __ movq(rbx, FieldOperand(rcx, JSObject::kPropertiesOffset)); | |
336 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), Factory::hash_table_map()); | |
337 __ j(equal, &probe_dictionary); | |
338 | |
339 // Load the map of the receiver, compute the keyed lookup cache hash | |
340 // based on 32 bits of the map pointer and the string hash. | |
341 __ movq(rbx, FieldOperand(rcx, HeapObject::kMapOffset)); | |
342 __ movl(rdx, rbx); | |
343 __ shr(rdx, Immediate(KeyedLookupCache::kMapHashShift)); | |
344 __ movl(rax, FieldOperand(rax, String::kHashFieldOffset)); | |
345 __ shr(rax, Immediate(String::kHashShift)); | |
346 __ xor_(rdx, rax); | |
347 __ and_(rdx, Immediate(KeyedLookupCache::kCapacityMask)); | |
348 | |
349 // Load the key (consisting of map and symbol) from the cache and | |
350 // check for match. | |
351 ExternalReference cache_keys | |
352 = ExternalReference::keyed_lookup_cache_keys(); | |
353 __ movq(rdi, rdx); | |
354 __ shl(rdi, Immediate(kPointerSizeLog2 + 1)); | |
355 __ movq(kScratchRegister, cache_keys); | |
356 __ movq(rax, Operand(kScratchRegister, rdi, times_1, 0)); | |
357 __ cmpq(rbx, rax); | |
358 __ j(not_equal, &slow); | |
359 __ movq(rax, Operand(rsp, kPointerSize)); | |
360 __ addq(rdi, Immediate(kPointerSize)); | |
361 __ movq(rdi, Operand(kScratchRegister, rdi, times_1, 0)); | |
362 __ cmpq(rax, rdi); | |
363 __ j(not_equal, &slow); | |
364 | |
365 // Get field offset which is a 32-bit integer and check that it is | |
366 // an in-object property. | |
367 ExternalReference cache_field_offsets | |
368 = ExternalReference::keyed_lookup_cache_field_offsets(); | |
369 __ movq(kScratchRegister, cache_field_offsets); | |
370 __ movl(rax, Operand(kScratchRegister, rdx, times_4, 0)); | |
371 __ movzxbq(rdx, FieldOperand(rbx, Map::kInObjectPropertiesOffset)); | |
372 __ cmpq(rax, rdx); | |
373 __ j(above_equal, &slow); | |
374 | |
375 // Load in-object property. | |
376 __ subq(rax, rdx); | |
377 __ movzxbq(rdx, FieldOperand(rbx, Map::kInstanceSizeOffset)); | |
378 __ addq(rax, rdx); | |
379 __ movq(rax, FieldOperand(rcx, rax, times_pointer_size, 0)); | |
380 __ ret(0); | |
381 | |
382 // Do a quick inline probe of the receiver's dictionary, if it | |
383 // exists. | |
384 __ bind(&probe_dictionary); | |
385 GenerateDictionaryLoad(masm, &slow, rbx, rcx, rdx, rax, false); | |
330 GenerateCheckNonObjectOrLoaded(masm, &slow, rcx); | 386 GenerateCheckNonObjectOrLoaded(masm, &slow, rcx); |
331 __ movq(rax, rcx); | 387 __ movq(rax, rcx); |
332 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); | 388 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); |
333 __ ret(0); | 389 __ ret(0); |
334 // If the hash field contains an array index pick it out. The assert checks | 390 // If the hash field contains an array index pick it out. The assert checks |
335 // that the constants for the maximum number of digits for an array index | 391 // that the constants for the maximum number of digits for an array index |
336 // cached in the hash field and the number of bits reserved for it does not | 392 // cached in the hash field and the number of bits reserved for it does not |
337 // conflict. | 393 // conflict. |
338 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | 394 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < |
339 (1 << String::kArrayIndexValueBits)); | 395 (1 << String::kArrayIndexValueBits)); |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
964 // Cache miss: Jump to runtime. | 1020 // Cache miss: Jump to runtime. |
965 __ bind(&miss); | 1021 __ bind(&miss); |
966 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss))); | 1022 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss))); |
967 } | 1023 } |
968 | 1024 |
969 | 1025 |
970 static void GenerateNormalHelper(MacroAssembler* masm, | 1026 static void GenerateNormalHelper(MacroAssembler* masm, |
971 int argc, | 1027 int argc, |
972 bool is_global_object, | 1028 bool is_global_object, |
973 Label* miss) { | 1029 Label* miss) { |
974 // Search dictionary - put result in register edx. | 1030 // Search dictionary - put result in register rdx. |
975 GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx); | 1031 GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx, true); |
976 | 1032 |
977 // Move the result to register rdi and check that it isn't a smi. | 1033 // Move the result to register rdi and check that it isn't a smi. |
978 __ movq(rdi, rdx); | 1034 __ movq(rdi, rdx); |
979 __ JumpIfSmi(rdx, miss); | 1035 __ JumpIfSmi(rdx, miss); |
980 | 1036 |
981 // Check that the value is a JavaScript function. | 1037 // Check that the value is a JavaScript function. |
982 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rdx); | 1038 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rdx); |
983 __ j(not_equal, miss); | 1039 __ j(not_equal, miss); |
984 // Check that the function has been loaded. | 1040 // Check that the function has been loaded. |
985 __ testb(FieldOperand(rdx, Map::kBitField2Offset), | 1041 __ testb(FieldOperand(rdx, Map::kBitField2Offset), |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1189 | 1245 |
1190 // Check for access to global object (unlikely). | 1246 // Check for access to global object (unlikely). |
1191 __ CmpInstanceType(rbx, JS_GLOBAL_PROXY_TYPE); | 1247 __ CmpInstanceType(rbx, JS_GLOBAL_PROXY_TYPE); |
1192 __ j(equal, &global); | 1248 __ j(equal, &global); |
1193 | 1249 |
1194 // Check for non-global object that requires access check. | 1250 // Check for non-global object that requires access check. |
1195 __ testl(FieldOperand(rbx, Map::kBitFieldOffset), | 1251 __ testl(FieldOperand(rbx, Map::kBitFieldOffset), |
1196 Immediate(1 << Map::kIsAccessCheckNeeded)); | 1252 Immediate(1 << Map::kIsAccessCheckNeeded)); |
1197 __ j(not_zero, &miss); | 1253 __ j(not_zero, &miss); |
1198 | 1254 |
1199 // Search the dictionary placing the result in eax. | 1255 // Search the dictionary placing the result in rax. |
1200 __ bind(&probe); | 1256 __ bind(&probe); |
1201 GenerateDictionaryLoad(masm, &miss, rdx, rax, rbx, rcx); | 1257 GenerateDictionaryLoad(masm, &miss, rdx, rax, rbx, rcx, true); |
1202 GenerateCheckNonObjectOrLoaded(masm, &miss, rax); | 1258 GenerateCheckNonObjectOrLoaded(masm, &miss, rax); |
1203 __ ret(0); | 1259 __ ret(0); |
1204 | 1260 |
1205 // Global object access: Check access rights. | 1261 // Global object access: Check access rights. |
1206 __ bind(&global); | 1262 __ bind(&global); |
1207 __ CheckAccessGlobalProxy(rax, rdx, &miss); | 1263 __ CheckAccessGlobalProxy(rax, rdx, &miss); |
1208 __ jmp(&probe); | 1264 __ jmp(&probe); |
1209 | 1265 |
1210 // Cache miss: Restore receiver from stack and jump to runtime. | 1266 // Cache miss: Restore receiver from stack and jump to runtime. |
1211 __ bind(&miss); | 1267 __ bind(&miss); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1312 | 1368 |
1313 // Cache miss: Jump to runtime. | 1369 // Cache miss: Jump to runtime. |
1314 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); | 1370 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); |
1315 } | 1371 } |
1316 | 1372 |
1317 | 1373 |
1318 #undef __ | 1374 #undef __ |
1319 | 1375 |
1320 | 1376 |
1321 } } // namespace v8::internal | 1377 } } // namespace v8::internal |
OLD | NEW |