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