| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 times_pointer_size, | 218 times_pointer_size, |
| 219 kValueOffset - kHeapObjectTag)); | 219 kValueOffset - kHeapObjectTag)); |
| 220 __ movq(Operand(scratch1, 0), value); | 220 __ movq(Operand(scratch1, 0), value); |
| 221 | 221 |
| 222 // Update write barrier. Make sure not to clobber the value. | 222 // Update write barrier. Make sure not to clobber the value. |
| 223 __ movq(scratch0, value); | 223 __ movq(scratch0, value); |
| 224 __ RecordWrite(elements, scratch1, scratch0); | 224 __ RecordWrite(elements, scratch1, scratch0); |
| 225 } | 225 } |
| 226 | 226 |
| 227 | 227 |
| 228 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, | |
| 229 Label* miss, | |
| 230 Register elements, | |
| 231 Register key, | |
| 232 Register r0, | |
| 233 Register r1, | |
| 234 Register r2, | |
| 235 Register result) { | |
| 236 // Register use: | |
| 237 // | |
| 238 // elements - holds the slow-case elements of the receiver on entry. | |
| 239 // Unchanged unless 'result' is the same register. | |
| 240 // | |
| 241 // key - holds the smi key on entry. | |
| 242 // Unchanged unless 'result' is the same register. | |
| 243 // | |
| 244 // Scratch registers: | |
| 245 // | |
| 246 // r0 - holds the untagged key on entry and holds the hash once computed. | |
| 247 // | |
| 248 // r1 - used to hold the capacity mask of the dictionary | |
| 249 // | |
| 250 // r2 - used for the index into the dictionary. | |
| 251 // | |
| 252 // result - holds the result on exit if the load succeeded. | |
| 253 // Allowed to be the same as 'key' or 'result'. | |
| 254 // Unchanged on bailout so 'key' or 'result' can be used | |
| 255 // in further computation. | |
| 256 | |
| 257 Label done; | |
| 258 | |
| 259 // Compute the hash code from the untagged key. This must be kept in sync | |
| 260 // with ComputeIntegerHash in utils.h. | |
| 261 // | |
| 262 // hash = ~hash + (hash << 15); | |
| 263 __ movl(r1, r0); | |
| 264 __ notl(r0); | |
| 265 __ shll(r1, Immediate(15)); | |
| 266 __ addl(r0, r1); | |
| 267 // hash = hash ^ (hash >> 12); | |
| 268 __ movl(r1, r0); | |
| 269 __ shrl(r1, Immediate(12)); | |
| 270 __ xorl(r0, r1); | |
| 271 // hash = hash + (hash << 2); | |
| 272 __ leal(r0, Operand(r0, r0, times_4, 0)); | |
| 273 // hash = hash ^ (hash >> 4); | |
| 274 __ movl(r1, r0); | |
| 275 __ shrl(r1, Immediate(4)); | |
| 276 __ xorl(r0, r1); | |
| 277 // hash = hash * 2057; | |
| 278 __ imull(r0, r0, Immediate(2057)); | |
| 279 // hash = hash ^ (hash >> 16); | |
| 280 __ movl(r1, r0); | |
| 281 __ shrl(r1, Immediate(16)); | |
| 282 __ xorl(r0, r1); | |
| 283 | |
| 284 // Compute capacity mask. | |
| 285 __ SmiToInteger32(r1, | |
| 286 FieldOperand(elements, NumberDictionary::kCapacityOffset)); | |
| 287 __ decl(r1); | |
| 288 | |
| 289 // Generate an unrolled loop that performs a few probes before giving up. | |
| 290 const int kProbes = 4; | |
| 291 for (int i = 0; i < kProbes; i++) { | |
| 292 // Use r2 for index calculations and keep the hash intact in r0. | |
| 293 __ movq(r2, r0); | |
| 294 // Compute the masked index: (hash + i + i * i) & mask. | |
| 295 if (i > 0) { | |
| 296 __ addl(r2, Immediate(NumberDictionary::GetProbeOffset(i))); | |
| 297 } | |
| 298 __ and_(r2, r1); | |
| 299 | |
| 300 // Scale the index by multiplying by the entry size. | |
| 301 ASSERT(NumberDictionary::kEntrySize == 3); | |
| 302 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 | |
| 303 | |
| 304 // Check if the key matches. | |
| 305 __ cmpq(key, FieldOperand(elements, | |
| 306 r2, | |
| 307 times_pointer_size, | |
| 308 NumberDictionary::kElementsStartOffset)); | |
| 309 if (i != (kProbes - 1)) { | |
| 310 __ j(equal, &done); | |
| 311 } else { | |
| 312 __ j(not_equal, miss); | |
| 313 } | |
| 314 } | |
| 315 | |
| 316 __ bind(&done); | |
| 317 // Check that the value is a normal propety. | |
| 318 const int kDetailsOffset = | |
| 319 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; | |
| 320 ASSERT_EQ(NORMAL, 0); | |
| 321 __ Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), | |
| 322 Smi::FromInt(PropertyDetails::TypeField::mask())); | |
| 323 __ j(not_zero, miss); | |
| 324 | |
| 325 // Get the value at the masked, scaled index. | |
| 326 const int kValueOffset = | |
| 327 NumberDictionary::kElementsStartOffset + kPointerSize; | |
| 328 __ movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); | |
| 329 } | |
| 330 | |
| 331 | |
| 332 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { | 228 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { |
| 333 // ----------- S t a t e ------------- | 229 // ----------- S t a t e ------------- |
| 334 // -- rax : receiver | 230 // -- rax : receiver |
| 335 // -- rcx : name | 231 // -- rcx : name |
| 336 // -- rsp[0] : return address | 232 // -- rsp[0] : return address |
| 337 // ----------------------------------- | 233 // ----------------------------------- |
| 338 Label miss; | 234 Label miss; |
| 339 | 235 |
| 340 StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss); | 236 StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss); |
| 341 __ bind(&miss); | 237 __ bind(&miss); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); | 424 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); |
| 529 | 425 |
| 530 // Check whether the elements is a number dictionary. | 426 // Check whether the elements is a number dictionary. |
| 531 // rdx: receiver | 427 // rdx: receiver |
| 532 // rax: key | 428 // rax: key |
| 533 // rbx: key as untagged int32 | 429 // rbx: key as untagged int32 |
| 534 // rcx: elements | 430 // rcx: elements |
| 535 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), | 431 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), |
| 536 Heap::kHashTableMapRootIndex); | 432 Heap::kHashTableMapRootIndex); |
| 537 __ j(not_equal, &slow); | 433 __ j(not_equal, &slow); |
| 538 GenerateNumberDictionaryLoad(masm, &slow, rcx, rax, rbx, r9, rdi, rax); | 434 __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax); |
| 539 __ ret(0); | 435 __ ret(0); |
| 540 | 436 |
| 541 __ bind(&slow); | 437 __ bind(&slow); |
| 542 // Slow case: Jump to runtime. | 438 // Slow case: Jump to runtime. |
| 543 // rdx: receiver | 439 // rdx: receiver |
| 544 // rax: key | 440 // rax: key |
| 545 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); | 441 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); |
| 546 GenerateRuntimeGetProperty(masm); | 442 GenerateRuntimeGetProperty(masm); |
| 547 | 443 |
| 548 __ bind(&check_string); | 444 __ bind(&check_string); |
| (...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1092 | 988 |
| 1093 __ bind(&check_number_dictionary); | 989 __ bind(&check_number_dictionary); |
| 1094 // rax: elements | 990 // rax: elements |
| 1095 // rcx: smi key | 991 // rcx: smi key |
| 1096 // Check whether the elements is a number dictionary. | 992 // Check whether the elements is a number dictionary. |
| 1097 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), | 993 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), |
| 1098 Heap::kHashTableMapRootIndex); | 994 Heap::kHashTableMapRootIndex); |
| 1099 __ j(not_equal, &slow_load); | 995 __ j(not_equal, &slow_load); |
| 1100 __ SmiToInteger32(rbx, rcx); | 996 __ SmiToInteger32(rbx, rcx); |
| 1101 // ebx: untagged index | 997 // ebx: untagged index |
| 1102 GenerateNumberDictionaryLoad(masm, &slow_load, rax, rcx, rbx, r9, rdi, rdi); | 998 __ LoadFromNumberDictionary(&slow_load, rax, rcx, rbx, r9, rdi, rdi); |
| 1103 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1); | 999 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1); |
| 1104 __ jmp(&do_call); | 1000 __ jmp(&do_call); |
| 1105 | 1001 |
| 1106 __ bind(&slow_load); | 1002 __ bind(&slow_load); |
| 1107 // This branch is taken when calling KeyedCallIC_Miss is neither required | 1003 // This branch is taken when calling KeyedCallIC_Miss is neither required |
| 1108 // nor beneficial. | 1004 // nor beneficial. |
| 1109 __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1); | 1005 __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1); |
| 1110 __ EnterInternalFrame(); | 1006 __ EnterInternalFrame(); |
| 1111 __ push(rcx); // save the key | 1007 __ push(rcx); // save the key |
| 1112 __ push(rdx); // pass the receiver | 1008 __ push(rdx); // pass the receiver |
| (...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1766 Condition cc = *jmp_address == Assembler::kJncShortOpcode | 1662 Condition cc = *jmp_address == Assembler::kJncShortOpcode |
| 1767 ? not_zero | 1663 ? not_zero |
| 1768 : zero; | 1664 : zero; |
| 1769 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1665 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1770 } | 1666 } |
| 1771 | 1667 |
| 1772 | 1668 |
| 1773 } } // namespace v8::internal | 1669 } } // namespace v8::internal |
| 1774 | 1670 |
| 1775 #endif // V8_TARGET_ARCH_X64 | 1671 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |