Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/ic/arm64/ic-arm64.cc

Issue 852313002: Add fast-path OOB support to KeyedLoadIC_Generic (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix negative indices Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ic/arm/ic-arm.cc ('k') | src/ic/ia32/ic-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_ARM64 7 #if V8_TARGET_ARCH_ARM64
8 8
9 #include "src/codegen.h" 9 #include "src/codegen.h"
10 #include "src/ic/ic.h" 10 #include "src/ic/ic.h"
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 // runtime system to make sure that indexing into string objects work 144 // runtime system to make sure that indexing into string objects work
145 // as intended. 145 // as intended.
146 STATIC_ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 146 STATIC_ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
147 __ Ldrb(scratch, FieldMemOperand(map_scratch, Map::kInstanceTypeOffset)); 147 __ Ldrb(scratch, FieldMemOperand(map_scratch, Map::kInstanceTypeOffset));
148 __ Cmp(scratch, JS_OBJECT_TYPE); 148 __ Cmp(scratch, JS_OBJECT_TYPE);
149 __ B(lt, slow); 149 __ B(lt, slow);
150 } 150 }
151 151
152 152
153 // Loads an indexed element from a fast case array. 153 // Loads an indexed element from a fast case array.
154 // If not_fast_array is NULL, doesn't perform the elements map check.
155 // 154 //
156 // receiver - holds the receiver on entry. 155 // receiver - holds the receiver on entry.
157 // Unchanged unless 'result' is the same register. 156 // Unchanged unless 'result' is the same register.
158 // 157 //
159 // key - holds the smi key on entry. 158 // key - holds the smi key on entry.
160 // Unchanged unless 'result' is the same register. 159 // Unchanged unless 'result' is the same register.
161 // 160 //
162 // elements - holds the elements of the receiver on exit. 161 // elements - holds the elements of the receiver and its prototypes. Clobbered.
163 // 162 //
164 // elements_map - holds the elements map on exit if the not_fast_array branch is 163 // result - holds the result on exit if the load succeeded.
165 // taken. Otherwise, this is used as a scratch register. 164 // Allowed to be the the same as 'receiver' or 'key'.
166 // 165 // Unchanged on bailout so 'receiver' and 'key' can be safely
167 // result - holds the result on exit if the load succeeded. 166 // used by further computation.
168 // Allowed to be the the same as 'receiver' or 'key'.
169 // Unchanged on bailout so 'receiver' and 'key' can be safely
170 // used by further computation.
171 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, 167 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
172 Register key, Register elements, 168 Register key, Register elements,
173 Register elements_map, Register scratch2, 169 Register scratch1, Register scratch2,
174 Register result, Label* not_fast_array, 170 Register result, Label* slow) {
175 Label* slow) { 171 DCHECK(!AreAliased(receiver, key, elements, scratch1, scratch2));
176 DCHECK(!AreAliased(receiver, key, elements, elements_map, scratch2)); 172
173 Label check_prototypes, check_next_prototype;
174 Label done, in_bounds, return_undefined;
177 175
178 // Check for fast array. 176 // Check for fast array.
179 __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 177 __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
180 if (not_fast_array != NULL) { 178 __ AssertFastElements(elements);
181 // Check that the object is in fast mode and writable.
182 __ Ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
183 __ JumpIfNotRoot(elements_map, Heap::kFixedArrayMapRootIndex,
184 not_fast_array);
185 } else {
186 __ AssertFastElements(elements);
187 }
188
189 // The elements_map register is only used for the not_fast_array path, which
190 // was handled above. From this point onward it is a scratch register.
191 Register scratch1 = elements_map;
192 179
193 // Check that the key (index) is within bounds. 180 // Check that the key (index) is within bounds.
194 __ Ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset)); 181 __ Ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset));
195 __ Cmp(key, scratch1); 182 __ Cmp(key, scratch1);
196 __ B(hs, slow); 183 __ B(lo, &in_bounds);
197 184
185 // Out of bounds. Check the prototype chain to see if we can just return
186 // 'undefined'.
187 __ Cmp(key, Operand(Smi::FromInt(0)));
188 __ B(lt, slow); // Negative keys can't take the fast OOB path.
189 __ Bind(&check_prototypes);
190 __ Ldr(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset));
191 __ Bind(&check_next_prototype);
192 __ Ldr(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset));
193 // scratch2: current prototype
194 __ JumpIfRoot(scratch2, Heap::kNullValueRootIndex, &return_undefined);
195 __ Ldr(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset));
196 __ Ldr(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset));
197 // elements: elements of current prototype
198 // scratch2: map of current prototype
199 __ CompareInstanceType(scratch2, scratch1, JS_OBJECT_TYPE);
200 __ B(lo, slow);
201 __ Ldrb(scratch1, FieldMemOperand(scratch2, Map::kBitFieldOffset));
202 __ Tbnz(scratch1, Map::kIsAccessCheckNeeded, slow);
203 __ Tbnz(scratch1, Map::kHasIndexedInterceptor, slow);
204 __ JumpIfNotRoot(elements, Heap::kEmptyFixedArrayRootIndex, slow);
205 __ B(&check_next_prototype);
206
207 __ Bind(&return_undefined);
208 __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
209 __ B(&done);
210
211 __ Bind(&in_bounds);
198 // Fast case: Do the load. 212 // Fast case: Do the load.
199 __ Add(scratch1, elements, FixedArray::kHeaderSize - kHeapObjectTag); 213 __ Add(scratch1, elements, FixedArray::kHeaderSize - kHeapObjectTag);
200 __ SmiUntag(scratch2, key); 214 __ SmiUntag(scratch2, key);
201 __ Ldr(scratch2, MemOperand(scratch1, scratch2, LSL, kPointerSizeLog2)); 215 __ Ldr(scratch2, MemOperand(scratch1, scratch2, LSL, kPointerSizeLog2));
202 216
203 // In case the loaded value is the_hole we have to consult GetProperty 217 // In case the loaded value is the_hole we have to check the prototype chain.
204 // to ensure the prototype chain is searched. 218 __ JumpIfRoot(scratch2, Heap::kTheHoleValueRootIndex, &check_prototypes);
205 __ JumpIfRoot(scratch2, Heap::kTheHoleValueRootIndex, slow);
206 219
207 // Move the value to the result register. 220 // Move the value to the result register.
208 // 'result' can alias with 'receiver' or 'key' but these two must be 221 // 'result' can alias with 'receiver' or 'key' but these two must be
209 // preserved if we jump to 'slow'. 222 // preserved if we jump to 'slow'.
210 __ Mov(result, scratch2); 223 __ Mov(result, scratch2);
224 __ Bind(&done);
211 } 225 }
212 226
213 227
214 // Checks whether a key is an array index string or a unique name. 228 // Checks whether a key is an array index string or a unique name.
215 // Falls through if a key is a unique name. 229 // Falls through if a key is a unique name.
216 // The map of the key is returned in 'map_scratch'. 230 // The map of the key is returned in 'map_scratch'.
217 // If the jump to 'index_string' is done the hash of the key is left 231 // If the jump to 'index_string' is done the hash of the key is left
218 // in 'hash_scratch'. 232 // in 'hash_scratch'.
219 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, 233 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
220 Register map_scratch, Register hash_scratch, 234 Register map_scratch, Register hash_scratch,
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 // If we can load the value, it should be returned in x0. 487 // If we can load the value, it should be returned in x0.
474 Register result = x0; 488 Register result = x0;
475 489
476 GenerateKeyedLoadReceiverCheck(masm, receiver, scratch1, scratch2, 490 GenerateKeyedLoadReceiverCheck(masm, receiver, scratch1, scratch2,
477 Map::kHasIndexedInterceptor, slow); 491 Map::kHasIndexedInterceptor, slow);
478 492
479 // Check the receiver's map to see if it has fast elements. 493 // Check the receiver's map to see if it has fast elements.
480 __ CheckFastElements(scratch1, scratch2, &check_number_dictionary); 494 __ CheckFastElements(scratch1, scratch2, &check_number_dictionary);
481 495
482 GenerateFastArrayLoad(masm, receiver, key, scratch3, scratch2, scratch1, 496 GenerateFastArrayLoad(masm, receiver, key, scratch3, scratch2, scratch1,
483 result, NULL, slow); 497 result, slow);
484 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, 498 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1,
485 scratch1, scratch2); 499 scratch1, scratch2);
486 __ Ret(); 500 __ Ret();
487 501
488 __ Bind(&check_number_dictionary); 502 __ Bind(&check_number_dictionary);
489 __ Ldr(scratch3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 503 __ Ldr(scratch3, FieldMemOperand(receiver, JSObject::kElementsOffset));
490 __ Ldr(scratch2, FieldMemOperand(scratch3, JSObject::kMapOffset)); 504 __ Ldr(scratch2, FieldMemOperand(scratch3, JSObject::kMapOffset));
491 505
492 // Check whether we have a number dictionary. 506 // Check whether we have a number dictionary.
493 __ JumpIfNotRoot(scratch2, Heap::kHashTableMapRootIndex, slow); 507 __ JumpIfNotRoot(scratch2, Heap::kHashTableMapRootIndex, slow);
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 } else { 1055 } else {
1042 DCHECK(to_patch->Mask(TestBranchMask) == TBNZ); 1056 DCHECK(to_patch->Mask(TestBranchMask) == TBNZ);
1043 // This is JumpIfSmi(smi_reg, branch_imm). 1057 // This is JumpIfSmi(smi_reg, branch_imm).
1044 patcher.tbz(smi_reg, 0, branch_imm); 1058 patcher.tbz(smi_reg, 0, branch_imm);
1045 } 1059 }
1046 } 1060 }
1047 } 1061 }
1048 } // namespace v8::internal 1062 } // namespace v8::internal
1049 1063
1050 #endif // V8_TARGET_ARCH_ARM64 1064 #endif // V8_TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « src/ic/arm/ic-arm.cc ('k') | src/ic/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698