OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
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/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 3055 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3066 DCHECK(csp.Is(__ StackPointer())); | 3066 DCHECK(csp.Is(__ StackPointer())); |
3067 | 3067 |
3068 intptr_t code = | 3068 intptr_t code = |
3069 reinterpret_cast<intptr_t>(GetCode().location()); | 3069 reinterpret_cast<intptr_t>(GetCode().location()); |
3070 __ Mov(lr, Operand(code, RelocInfo::CODE_TARGET)); | 3070 __ Mov(lr, Operand(code, RelocInfo::CODE_TARGET)); |
3071 __ Mov(x10, target); | 3071 __ Mov(x10, target); |
3072 // Branch to the stub. | 3072 // Branch to the stub. |
3073 __ Blr(lr); | 3073 __ Blr(lr); |
3074 } | 3074 } |
3075 | 3075 |
3076 | |
3077 // Probe the name dictionary in the 'elements' register. | |
3078 // Jump to the 'done' label if a property with the given name is found. | |
3079 // Jump to the 'miss' label otherwise. | |
3080 // | |
3081 // If lookup was successful 'scratch2' will be equal to elements + 4 * index. | |
3082 // 'elements' and 'name' registers are preserved on miss. | |
3083 void NameDictionaryLookupStub::GeneratePositiveLookup( | |
3084 MacroAssembler* masm, | |
3085 Label* miss, | |
3086 Label* done, | |
3087 Register elements, | |
3088 Register name, | |
3089 Register scratch1, | |
3090 Register scratch2) { | |
3091 DCHECK(!AreAliased(elements, name, scratch1, scratch2)); | |
3092 | |
3093 // Assert that name contains a string. | |
3094 __ AssertName(name); | |
3095 | |
3096 // Compute the capacity mask. | |
3097 __ Ldrsw(scratch1, UntagSmiFieldMemOperand(elements, kCapacityOffset)); | |
3098 __ Sub(scratch1, scratch1, 1); | |
3099 | |
3100 // Generate an unrolled loop that performs a few probes before giving up. | |
3101 for (int i = 0; i < kInlinedProbes; i++) { | |
3102 // Compute the masked index: (hash + i + i * i) & mask. | |
3103 __ Ldr(scratch2, FieldMemOperand(name, Name::kHashFieldOffset)); | |
3104 if (i > 0) { | |
3105 // Add the probe offset (i + i * i) left shifted to avoid right shifting | |
3106 // the hash in a separate instruction. The value hash + i + i * i is right | |
3107 // shifted in the following and instruction. | |
3108 DCHECK(NameDictionary::GetProbeOffset(i) < | |
3109 1 << (32 - Name::kHashFieldOffset)); | |
3110 __ Add(scratch2, scratch2, Operand( | |
3111 NameDictionary::GetProbeOffset(i) << Name::kHashShift)); | |
3112 } | |
3113 __ And(scratch2, scratch1, Operand(scratch2, LSR, Name::kHashShift)); | |
3114 | |
3115 // Scale the index by multiplying by the element size. | |
3116 STATIC_ASSERT(NameDictionary::kEntrySize == 3); | |
3117 __ Add(scratch2, scratch2, Operand(scratch2, LSL, 1)); | |
3118 | |
3119 // Check if the key is identical to the name. | |
3120 UseScratchRegisterScope temps(masm); | |
3121 Register scratch3 = temps.AcquireX(); | |
3122 __ Add(scratch2, elements, Operand(scratch2, LSL, kPointerSizeLog2)); | |
3123 __ Ldr(scratch3, FieldMemOperand(scratch2, kElementsStartOffset)); | |
3124 __ Cmp(name, scratch3); | |
3125 __ B(eq, done); | |
3126 } | |
3127 | |
3128 // The inlined probes didn't find the entry. | |
3129 // Call the complete stub to scan the whole dictionary. | |
3130 | |
3131 CPURegList spill_list(CPURegister::kRegister, kXRegSizeInBits, 0, 6); | |
3132 spill_list.Combine(lr); | |
3133 spill_list.Remove(scratch1); | |
3134 spill_list.Remove(scratch2); | |
3135 | |
3136 __ PushCPURegList(spill_list); | |
3137 | |
3138 if (name.is(x0)) { | |
3139 DCHECK(!elements.is(x1)); | |
3140 __ Mov(x1, name); | |
3141 __ Mov(x0, elements); | |
3142 } else { | |
3143 __ Mov(x0, elements); | |
3144 __ Mov(x1, name); | |
3145 } | |
3146 | |
3147 Label not_found; | |
3148 NameDictionaryLookupStub stub(masm->isolate(), POSITIVE_LOOKUP); | |
3149 __ CallStub(&stub); | |
3150 __ Cbz(x0, ¬_found); | |
3151 __ Mov(scratch2, x2); // Move entry index into scratch2. | |
3152 __ PopCPURegList(spill_list); | |
3153 __ B(done); | |
3154 | |
3155 __ Bind(¬_found); | |
3156 __ PopCPURegList(spill_list); | |
3157 __ B(miss); | |
3158 } | |
3159 | |
3160 | |
3161 void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, | 3076 void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, |
3162 Label* miss, | 3077 Label* miss, |
3163 Label* done, | 3078 Label* done, |
3164 Register receiver, | 3079 Register receiver, |
3165 Register properties, | 3080 Register properties, |
3166 Handle<Name> name, | 3081 Handle<Name> name, |
3167 Register scratch0) { | 3082 Register scratch0) { |
3168 DCHECK(!AreAliased(receiver, properties, scratch0)); | 3083 DCHECK(!AreAliased(receiver, properties, scratch0)); |
3169 DCHECK(name->IsUniqueName()); | 3084 DCHECK(name->IsUniqueName()); |
3170 // If names of slots in range from 1 to kProbes - 1 for the hash value are | 3085 // If names of slots in range from 1 to kProbes - 1 for the hash value are |
(...skipping 1384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4555 kStackUnwindSpace, NULL, spill_offset, | 4470 kStackUnwindSpace, NULL, spill_offset, |
4556 return_value_operand, NULL); | 4471 return_value_operand, NULL); |
4557 } | 4472 } |
4558 | 4473 |
4559 #undef __ | 4474 #undef __ |
4560 | 4475 |
4561 } // namespace internal | 4476 } // namespace internal |
4562 } // namespace v8 | 4477 } // namespace v8 |
4563 | 4478 |
4564 #endif // V8_TARGET_ARCH_ARM64 | 4479 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |