| 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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 const int kValueOffset = kElementsStartOffset + kPointerSize; | 209 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 210 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); | 210 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); |
| 211 __ mov(Operand(r0, 0), value); | 211 __ mov(Operand(r0, 0), value); |
| 212 | 212 |
| 213 // Update write barrier. Make sure not to clobber the value. | 213 // Update write barrier. Make sure not to clobber the value. |
| 214 __ mov(r1, value); | 214 __ mov(r1, value); |
| 215 __ RecordWrite(elements, r0, r1); | 215 __ RecordWrite(elements, r0, r1); |
| 216 } | 216 } |
| 217 | 217 |
| 218 | 218 |
| 219 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, | |
| 220 Label* miss, | |
| 221 Register elements, | |
| 222 Register key, | |
| 223 Register r0, | |
| 224 Register r1, | |
| 225 Register r2, | |
| 226 Register result) { | |
| 227 // Register use: | |
| 228 // | |
| 229 // elements - holds the slow-case elements of the receiver and is unchanged. | |
| 230 // | |
| 231 // key - holds the smi key on entry and is unchanged. | |
| 232 // | |
| 233 // Scratch registers: | |
| 234 // | |
| 235 // r0 - holds the untagged key on entry and holds the hash once computed. | |
| 236 // | |
| 237 // r1 - used to hold the capacity mask of the dictionary | |
| 238 // | |
| 239 // r2 - used for the index into the dictionary. | |
| 240 // | |
| 241 // result - holds the result on exit if the load succeeds and we fall through. | |
| 242 | |
| 243 Label done; | |
| 244 | |
| 245 // Compute the hash code from the untagged key. This must be kept in sync | |
| 246 // with ComputeIntegerHash in utils.h. | |
| 247 // | |
| 248 // hash = ~hash + (hash << 15); | |
| 249 __ mov(r1, r0); | |
| 250 __ not_(r0); | |
| 251 __ shl(r1, 15); | |
| 252 __ add(r0, Operand(r1)); | |
| 253 // hash = hash ^ (hash >> 12); | |
| 254 __ mov(r1, r0); | |
| 255 __ shr(r1, 12); | |
| 256 __ xor_(r0, Operand(r1)); | |
| 257 // hash = hash + (hash << 2); | |
| 258 __ lea(r0, Operand(r0, r0, times_4, 0)); | |
| 259 // hash = hash ^ (hash >> 4); | |
| 260 __ mov(r1, r0); | |
| 261 __ shr(r1, 4); | |
| 262 __ xor_(r0, Operand(r1)); | |
| 263 // hash = hash * 2057; | |
| 264 __ imul(r0, r0, 2057); | |
| 265 // hash = hash ^ (hash >> 16); | |
| 266 __ mov(r1, r0); | |
| 267 __ shr(r1, 16); | |
| 268 __ xor_(r0, Operand(r1)); | |
| 269 | |
| 270 // Compute capacity mask. | |
| 271 __ mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset)); | |
| 272 __ shr(r1, kSmiTagSize); // convert smi to int | |
| 273 __ dec(r1); | |
| 274 | |
| 275 // Generate an unrolled loop that performs a few probes before giving up. | |
| 276 const int kProbes = 4; | |
| 277 for (int i = 0; i < kProbes; i++) { | |
| 278 // Use r2 for index calculations and keep the hash intact in r0. | |
| 279 __ mov(r2, r0); | |
| 280 // Compute the masked index: (hash + i + i * i) & mask. | |
| 281 if (i > 0) { | |
| 282 __ add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i))); | |
| 283 } | |
| 284 __ and_(r2, Operand(r1)); | |
| 285 | |
| 286 // Scale the index by multiplying by the entry size. | |
| 287 ASSERT(NumberDictionary::kEntrySize == 3); | |
| 288 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 | |
| 289 | |
| 290 // Check if the key matches. | |
| 291 __ cmp(key, FieldOperand(elements, | |
| 292 r2, | |
| 293 times_pointer_size, | |
| 294 NumberDictionary::kElementsStartOffset)); | |
| 295 if (i != (kProbes - 1)) { | |
| 296 __ j(equal, &done); | |
| 297 } else { | |
| 298 __ j(not_equal, miss); | |
| 299 } | |
| 300 } | |
| 301 | |
| 302 __ bind(&done); | |
| 303 // Check that the value is a normal propety. | |
| 304 const int kDetailsOffset = | |
| 305 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; | |
| 306 ASSERT_EQ(NORMAL, 0); | |
| 307 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), | |
| 308 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); | |
| 309 __ j(not_zero, miss); | |
| 310 | |
| 311 // Get the value at the masked, scaled index. | |
| 312 const int kValueOffset = | |
| 313 NumberDictionary::kElementsStartOffset + kPointerSize; | |
| 314 __ mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); | |
| 315 } | |
| 316 | |
| 317 | |
| 318 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { | 219 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { |
| 319 // ----------- S t a t e ------------- | 220 // ----------- S t a t e ------------- |
| 320 // -- eax : receiver | 221 // -- eax : receiver |
| 321 // -- ecx : name | 222 // -- ecx : name |
| 322 // -- esp[0] : return address | 223 // -- esp[0] : return address |
| 323 // ----------------------------------- | 224 // ----------------------------------- |
| 324 Label miss; | 225 Label miss; |
| 325 | 226 |
| 326 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); | 227 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); |
| 327 __ bind(&miss); | 228 __ bind(&miss); |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 // eax: key | 485 // eax: key |
| 585 // ecx: elements | 486 // ecx: elements |
| 586 __ CheckMap(ecx, | 487 __ CheckMap(ecx, |
| 587 isolate->factory()->hash_table_map(), | 488 isolate->factory()->hash_table_map(), |
| 588 &slow, | 489 &slow, |
| 589 DONT_DO_SMI_CHECK); | 490 DONT_DO_SMI_CHECK); |
| 590 Label slow_pop_receiver; | 491 Label slow_pop_receiver; |
| 591 // Push receiver on the stack to free up a register for the dictionary | 492 // Push receiver on the stack to free up a register for the dictionary |
| 592 // probing. | 493 // probing. |
| 593 __ push(edx); | 494 __ push(edx); |
| 594 GenerateNumberDictionaryLoad(masm, | 495 __ LoadFromNumberDictionary(&slow_pop_receiver, |
| 595 &slow_pop_receiver, | 496 ecx, |
| 596 ecx, | 497 eax, |
| 597 eax, | 498 ebx, |
| 598 ebx, | 499 edx, |
| 599 edx, | 500 edi, |
| 600 edi, | 501 eax); |
| 601 eax); | |
| 602 // Pop receiver before returning. | 502 // Pop receiver before returning. |
| 603 __ pop(edx); | 503 __ pop(edx); |
| 604 __ ret(0); | 504 __ ret(0); |
| 605 | 505 |
| 606 __ bind(&slow_pop_receiver); | 506 __ bind(&slow_pop_receiver); |
| 607 // Pop the receiver from the stack and jump to runtime. | 507 // Pop the receiver from the stack and jump to runtime. |
| 608 __ pop(edx); | 508 __ pop(edx); |
| 609 | 509 |
| 610 __ bind(&slow); | 510 __ bind(&slow); |
| 611 // Slow case: jump to runtime. | 511 // Slow case: jump to runtime. |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1193 // ecx: smi key | 1093 // ecx: smi key |
| 1194 // Check whether the elements is a number dictionary. | 1094 // Check whether the elements is a number dictionary. |
| 1195 __ CheckMap(eax, | 1095 __ CheckMap(eax, |
| 1196 isolate->factory()->hash_table_map(), | 1096 isolate->factory()->hash_table_map(), |
| 1197 &slow_load, | 1097 &slow_load, |
| 1198 DONT_DO_SMI_CHECK); | 1098 DONT_DO_SMI_CHECK); |
| 1199 __ mov(ebx, ecx); | 1099 __ mov(ebx, ecx); |
| 1200 __ SmiUntag(ebx); | 1100 __ SmiUntag(ebx); |
| 1201 // ebx: untagged index | 1101 // ebx: untagged index |
| 1202 // Receiver in edx will be clobbered, need to reload it on miss. | 1102 // Receiver in edx will be clobbered, need to reload it on miss. |
| 1203 GenerateNumberDictionaryLoad( | 1103 __ LoadFromNumberDictionary( |
| 1204 masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi); | 1104 &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi); |
| 1205 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1); | 1105 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1); |
| 1206 __ jmp(&do_call); | 1106 __ jmp(&do_call); |
| 1207 | 1107 |
| 1208 __ bind(&slow_reload_receiver); | 1108 __ bind(&slow_reload_receiver); |
| 1209 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1109 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1210 | 1110 |
| 1211 __ bind(&slow_load); | 1111 __ bind(&slow_load); |
| 1212 // This branch is taken when calling KeyedCallIC_Miss is neither required | 1112 // This branch is taken when calling KeyedCallIC_Miss is neither required |
| 1213 // nor beneficial. | 1113 // nor beneficial. |
| 1214 __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1); | 1114 __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1); |
| (...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1737 Condition cc = *jmp_address == Assembler::kJncShortOpcode | 1637 Condition cc = *jmp_address == Assembler::kJncShortOpcode |
| 1738 ? not_zero | 1638 ? not_zero |
| 1739 : zero; | 1639 : zero; |
| 1740 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1640 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1741 } | 1641 } |
| 1742 | 1642 |
| 1743 | 1643 |
| 1744 } } // namespace v8::internal | 1644 } } // namespace v8::internal |
| 1745 | 1645 |
| 1746 #endif // V8_TARGET_ARCH_IA32 | 1646 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |