| OLD | NEW | 
|     1 // Copyright 2014 the V8 project authors. All rights reserved. |     1 // Copyright 2014 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 #if V8_TARGET_ARCH_S390 |     5 #if V8_TARGET_ARCH_S390 | 
|     6  |     6  | 
|     7 #include "src/code-stubs.h" |     7 #include "src/code-stubs.h" | 
|     8 #include "src/api-arguments.h" |     8 #include "src/api-arguments.h" | 
|     9 #include "src/base/bits.h" |     9 #include "src/base/bits.h" | 
|    10 #include "src/bootstrapper.h" |    10 #include "src/bootstrapper.h" | 
| (...skipping 2728 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2739   __ CallStub(&stub); |  2739   __ CallStub(&stub); | 
|  2740   __ CmpP(r2, Operand::Zero()); |  2740   __ CmpP(r2, Operand::Zero()); | 
|  2741  |  2741  | 
|  2742   __ MultiPop(spill_mask);  // MultiPop does not touch condition flags |  2742   __ MultiPop(spill_mask);  // MultiPop does not touch condition flags | 
|  2743   __ LoadRR(r14, r0); |  2743   __ LoadRR(r14, r0); | 
|  2744  |  2744  | 
|  2745   __ beq(done); |  2745   __ beq(done); | 
|  2746   __ bne(miss); |  2746   __ bne(miss); | 
|  2747 } |  2747 } | 
|  2748  |  2748  | 
|  2749 // Probe the name dictionary in the |elements| register. Jump to the |  | 
|  2750 // |done| label if a property with the given name is found. Jump to |  | 
|  2751 // the |miss| label otherwise. |  | 
|  2752 // If lookup was successful |scratch2| will be equal to elements + 4 * index. |  | 
|  2753 void NameDictionaryLookupStub::GeneratePositiveLookup( |  | 
|  2754     MacroAssembler* masm, Label* miss, Label* done, Register elements, |  | 
|  2755     Register name, Register scratch1, Register scratch2) { |  | 
|  2756   DCHECK(!elements.is(scratch1)); |  | 
|  2757   DCHECK(!elements.is(scratch2)); |  | 
|  2758   DCHECK(!name.is(scratch1)); |  | 
|  2759   DCHECK(!name.is(scratch2)); |  | 
|  2760  |  | 
|  2761   __ AssertName(name); |  | 
|  2762  |  | 
|  2763   // Compute the capacity mask. |  | 
|  2764   __ LoadP(scratch1, FieldMemOperand(elements, kCapacityOffset)); |  | 
|  2765   __ SmiUntag(scratch1);  // convert smi to int |  | 
|  2766   __ SubP(scratch1, Operand(1)); |  | 
|  2767  |  | 
|  2768   // Generate an unrolled loop that performs a few probes before |  | 
|  2769   // giving up. Measurements done on Gmail indicate that 2 probes |  | 
|  2770   // cover ~93% of loads from dictionaries. |  | 
|  2771   for (int i = 0; i < kInlinedProbes; i++) { |  | 
|  2772     // Compute the masked index: (hash + i + i * i) & mask. |  | 
|  2773     __ LoadlW(scratch2, FieldMemOperand(name, String::kHashFieldOffset)); |  | 
|  2774     if (i > 0) { |  | 
|  2775       // Add the probe offset (i + i * i) left shifted to avoid right shifting |  | 
|  2776       // the hash in a separate instruction. The value hash + i + i * i is right |  | 
|  2777       // shifted in the following and instruction. |  | 
|  2778       DCHECK(NameDictionary::GetProbeOffset(i) < |  | 
|  2779              1 << (32 - Name::kHashFieldOffset)); |  | 
|  2780       __ AddP(scratch2, |  | 
|  2781               Operand(NameDictionary::GetProbeOffset(i) << Name::kHashShift)); |  | 
|  2782     } |  | 
|  2783     __ srl(scratch2, Operand(String::kHashShift)); |  | 
|  2784     __ AndP(scratch2, scratch1); |  | 
|  2785  |  | 
|  2786     // Scale the index by multiplying by the entry size. |  | 
|  2787     STATIC_ASSERT(NameDictionary::kEntrySize == 3); |  | 
|  2788     // scratch2 = scratch2 * 3. |  | 
|  2789     __ ShiftLeftP(ip, scratch2, Operand(1)); |  | 
|  2790     __ AddP(scratch2, ip); |  | 
|  2791  |  | 
|  2792     // Check if the key is identical to the name. |  | 
|  2793     __ ShiftLeftP(ip, scratch2, Operand(kPointerSizeLog2)); |  | 
|  2794     __ AddP(scratch2, elements, ip); |  | 
|  2795     __ LoadP(ip, FieldMemOperand(scratch2, kElementsStartOffset)); |  | 
|  2796     __ CmpP(name, ip); |  | 
|  2797     __ beq(done); |  | 
|  2798   } |  | 
|  2799  |  | 
|  2800   const int spill_mask = (r0.bit() | r8.bit() | r7.bit() | r6.bit() | r5.bit() | |  | 
|  2801                           r4.bit() | r3.bit() | r2.bit()) & |  | 
|  2802                          ~(scratch1.bit() | scratch2.bit()); |  | 
|  2803  |  | 
|  2804   __ LoadRR(r0, r14); |  | 
|  2805   __ MultiPush(spill_mask); |  | 
|  2806   if (name.is(r2)) { |  | 
|  2807     DCHECK(!elements.is(r3)); |  | 
|  2808     __ LoadRR(r3, name); |  | 
|  2809     __ LoadRR(r2, elements); |  | 
|  2810   } else { |  | 
|  2811     __ LoadRR(r2, elements); |  | 
|  2812     __ LoadRR(r3, name); |  | 
|  2813   } |  | 
|  2814   NameDictionaryLookupStub stub(masm->isolate(), POSITIVE_LOOKUP); |  | 
|  2815   __ CallStub(&stub); |  | 
|  2816   __ LoadRR(r1, r2); |  | 
|  2817   __ LoadRR(scratch2, r4); |  | 
|  2818   __ MultiPop(spill_mask); |  | 
|  2819   __ LoadRR(r14, r0); |  | 
|  2820  |  | 
|  2821   __ CmpP(r1, Operand::Zero()); |  | 
|  2822   __ bne(done); |  | 
|  2823   __ beq(miss); |  | 
|  2824 } |  | 
|  2825  |  | 
|  2826 void NameDictionaryLookupStub::Generate(MacroAssembler* masm) { |  2749 void NameDictionaryLookupStub::Generate(MacroAssembler* masm) { | 
|  2827   // This stub overrides SometimesSetsUpAFrame() to return false.  That means |  2750   // This stub overrides SometimesSetsUpAFrame() to return false.  That means | 
|  2828   // we cannot call anything that could cause a GC from this stub. |  2751   // we cannot call anything that could cause a GC from this stub. | 
|  2829   // Registers: |  2752   // Registers: | 
|  2830   //  result: NameDictionary to probe |  2753   //  result: NameDictionary to probe | 
|  2831   //  r3: key |  2754   //  r3: key | 
|  2832   //  dictionary: NameDictionary to probe. |  2755   //  dictionary: NameDictionary to probe. | 
|  2833   //  index: will hold an index of entry if lookup is successful. |  2756   //  index: will hold an index of entry if lookup is successful. | 
|  2834   //         might alias with result_. |  2757   //         might alias with result_. | 
|  2835   // Returns: |  2758   // Returns: | 
| (...skipping 1515 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  4351   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, |  4274   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, | 
|  4352                            kStackUnwindSpace, NULL, return_value_operand, NULL); |  4275                            kStackUnwindSpace, NULL, return_value_operand, NULL); | 
|  4353 } |  4276 } | 
|  4354  |  4277  | 
|  4355 #undef __ |  4278 #undef __ | 
|  4356  |  4279  | 
|  4357 }  // namespace internal |  4280 }  // namespace internal | 
|  4358 }  // namespace v8 |  4281 }  // namespace v8 | 
|  4359  |  4282  | 
|  4360 #endif  // V8_TARGET_ARCH_S390 |  4283 #endif  // V8_TARGET_ARCH_S390 | 
| OLD | NEW |