| 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 |