| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/ic/ic.h" | 10 #include "src/ic/ic.h" |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 // bit test is enough. | 267 // bit test is enough. |
| 268 STATIC_ASSERT(kNotInternalizedTag != 0); | 268 STATIC_ASSERT(kNotInternalizedTag != 0); |
| 269 __ testb(FieldOperand(map, Map::kInstanceTypeOffset), | 269 __ testb(FieldOperand(map, Map::kInstanceTypeOffset), |
| 270 Immediate(kIsNotInternalizedMask)); | 270 Immediate(kIsNotInternalizedMask)); |
| 271 __ j(not_zero, not_unique); | 271 __ j(not_zero, not_unique); |
| 272 | 272 |
| 273 __ bind(&unique); | 273 __ bind(&unique); |
| 274 } | 274 } |
| 275 | 275 |
| 276 | 276 |
| 277 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 277 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 278 // The return address is on the stack. | 278 // The return address is on the stack. |
| 279 Label slow, check_name, index_smi, index_name, property_array_property; | 279 Label slow, check_name, index_smi, index_name, property_array_property; |
| 280 Label probe_dictionary, check_number_dictionary; | 280 Label probe_dictionary, check_number_dictionary; |
| 281 | 281 |
| 282 Register receiver = LoadDescriptor::ReceiverRegister(); | 282 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 283 Register key = LoadDescriptor::NameRegister(); | 283 Register key = LoadDescriptor::NameRegister(); |
| 284 DCHECK(receiver.is(rdx)); | 284 DCHECK(receiver.is(rdx)); |
| 285 DCHECK(key.is(rcx)); | 285 DCHECK(key.is(rcx)); |
| 286 | 286 |
| 287 // Check that the key is a smi. | 287 // Check that the key is a smi. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 318 // Slow case: Jump to runtime. | 318 // Slow case: Jump to runtime. |
| 319 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); | 319 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); |
| 320 GenerateRuntimeGetProperty(masm); | 320 GenerateRuntimeGetProperty(masm); |
| 321 | 321 |
| 322 __ bind(&check_name); | 322 __ bind(&check_name); |
| 323 GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow); | 323 GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow); |
| 324 | 324 |
| 325 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, Map::kHasNamedInterceptor, | 325 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, Map::kHasNamedInterceptor, |
| 326 &slow); | 326 &slow); |
| 327 | 327 |
| 328 // If the receiver is a fast-case object, check the keyed lookup | 328 // If the receiver is a fast-case object, check the stub cache. Otherwise |
| 329 // cache. Otherwise probe the dictionary leaving result in key. | 329 // probe the dictionary. |
| 330 __ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 330 __ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 331 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 331 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
| 332 Heap::kHashTableMapRootIndex); | 332 Heap::kHashTableMapRootIndex); |
| 333 __ j(equal, &probe_dictionary); | 333 __ j(equal, &probe_dictionary); |
| 334 | 334 |
| 335 // Load the map of the receiver, compute the keyed lookup cache hash | 335 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( |
| 336 // based on 32 bits of the map pointer and the string hash. | 336 Code::ComputeHandlerFlags(Code::LOAD_IC)); |
| 337 __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset)); | 337 masm->isolate()->stub_cache()->GenerateProbe( |
| 338 __ movl(rax, rbx); | 338 masm, Code::LOAD_IC, flags, false, receiver, key, rbx, no_reg); |
| 339 __ shrl(rax, Immediate(KeyedLookupCache::kMapHashShift)); | 339 // Cache miss. |
| 340 __ movl(rdi, FieldOperand(key, String::kHashFieldOffset)); | 340 GenerateMiss(masm); |
| 341 __ shrl(rdi, Immediate(String::kHashShift)); | |
| 342 __ xorp(rax, rdi); | |
| 343 int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); | |
| 344 __ andp(rax, Immediate(mask)); | |
| 345 | |
| 346 // Load the key (consisting of map and internalized string) from the cache and | |
| 347 // check for match. | |
| 348 Label load_in_object_property; | |
| 349 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; | |
| 350 Label hit_on_nth_entry[kEntriesPerBucket]; | |
| 351 ExternalReference cache_keys = | |
| 352 ExternalReference::keyed_lookup_cache_keys(masm->isolate()); | |
| 353 | |
| 354 for (int i = 0; i < kEntriesPerBucket - 1; i++) { | |
| 355 Label try_next_entry; | |
| 356 __ movp(rdi, rax); | |
| 357 __ shlp(rdi, Immediate(kPointerSizeLog2 + 1)); | |
| 358 __ LoadAddress(kScratchRegister, cache_keys); | |
| 359 int off = kPointerSize * i * 2; | |
| 360 __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off)); | |
| 361 __ j(not_equal, &try_next_entry); | |
| 362 __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize)); | |
| 363 __ j(equal, &hit_on_nth_entry[i]); | |
| 364 __ bind(&try_next_entry); | |
| 365 } | |
| 366 | |
| 367 int off = kPointerSize * (kEntriesPerBucket - 1) * 2; | |
| 368 __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off)); | |
| 369 __ j(not_equal, &slow); | |
| 370 __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize)); | |
| 371 __ j(not_equal, &slow); | |
| 372 | |
| 373 // Get field offset, which is a 32-bit integer. | |
| 374 ExternalReference cache_field_offsets = | |
| 375 ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate()); | |
| 376 | |
| 377 // Hit on nth entry. | |
| 378 for (int i = kEntriesPerBucket - 1; i >= 0; i--) { | |
| 379 __ bind(&hit_on_nth_entry[i]); | |
| 380 if (i != 0) { | |
| 381 __ addl(rax, Immediate(i)); | |
| 382 } | |
| 383 __ LoadAddress(kScratchRegister, cache_field_offsets); | |
| 384 __ movl(rdi, Operand(kScratchRegister, rax, times_4, 0)); | |
| 385 __ movzxbp(rax, FieldOperand(rbx, Map::kInObjectPropertiesOffset)); | |
| 386 __ subp(rdi, rax); | |
| 387 __ j(above_equal, &property_array_property); | |
| 388 if (i != 0) { | |
| 389 __ jmp(&load_in_object_property); | |
| 390 } | |
| 391 } | |
| 392 | |
| 393 // Load in-object property. | |
| 394 __ bind(&load_in_object_property); | |
| 395 __ movzxbp(rax, FieldOperand(rbx, Map::kInstanceSizeOffset)); | |
| 396 __ addp(rax, rdi); | |
| 397 __ movp(rax, FieldOperand(receiver, rax, times_pointer_size, 0)); | |
| 398 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); | |
| 399 __ ret(0); | |
| 400 | |
| 401 // Load property array property. | |
| 402 __ bind(&property_array_property); | |
| 403 __ movp(rax, FieldOperand(receiver, JSObject::kPropertiesOffset)); | |
| 404 __ movp(rax, | |
| 405 FieldOperand(rax, rdi, times_pointer_size, FixedArray::kHeaderSize)); | |
| 406 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); | |
| 407 __ ret(0); | |
| 408 | 341 |
| 409 // Do a quick inline probe of the receiver's dictionary, if it | 342 // Do a quick inline probe of the receiver's dictionary, if it |
| 410 // exists. | 343 // exists. |
| 411 __ bind(&probe_dictionary); | 344 __ bind(&probe_dictionary); |
| 412 // rbx: elements | 345 // rbx: elements |
| 413 | 346 |
| 414 __ movp(rax, FieldOperand(receiver, JSObject::kMapOffset)); | 347 __ movp(rax, FieldOperand(receiver, JSObject::kMapOffset)); |
| 415 __ movb(rax, FieldOperand(rax, Map::kInstanceTypeOffset)); | 348 __ movb(rax, FieldOperand(rax, Map::kInstanceTypeOffset)); |
| 416 GenerateGlobalInstanceTypeCheck(masm, rax, &slow); | 349 GenerateGlobalInstanceTypeCheck(masm, rax, &slow); |
| 417 | 350 |
| (...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1013 Condition cc = | 946 Condition cc = |
| 1014 (check == ENABLE_INLINED_SMI_CHECK) | 947 (check == ENABLE_INLINED_SMI_CHECK) |
| 1015 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 948 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
| 1016 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 949 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
| 1017 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 950 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1018 } | 951 } |
| 1019 } | 952 } |
| 1020 } // namespace v8::internal | 953 } // namespace v8::internal |
| 1021 | 954 |
| 1022 #endif // V8_TARGET_ARCH_X64 | 955 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |