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

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

Issue 1168093002: [strong] Implement strong mode restrictions on property access (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase Created 5 years, 6 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/handler-compiler-arm.cc ('k') | src/ic/arm64/handler-compiler-arm64.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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_ARM 7 #if V8_TARGET_ARCH_ARM
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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 __ ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); 154 __ ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
155 __ cmp(scratch, Operand(JS_OBJECT_TYPE)); 155 __ cmp(scratch, Operand(JS_OBJECT_TYPE));
156 __ b(lt, slow); 156 __ b(lt, slow);
157 } 157 }
158 158
159 159
160 // Loads an indexed element from a fast case array. 160 // Loads an indexed element from a fast case array.
161 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, 161 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
162 Register key, Register elements, 162 Register key, Register elements,
163 Register scratch1, Register scratch2, 163 Register scratch1, Register scratch2,
164 Register result, Label* slow) { 164 Register result, Label* slow,
165 LanguageMode language_mode) {
165 // Register use: 166 // Register use:
166 // 167 //
167 // receiver - holds the receiver on entry. 168 // receiver - holds the receiver on entry.
168 // Unchanged unless 'result' is the same register. 169 // Unchanged unless 'result' is the same register.
169 // 170 //
170 // key - holds the smi key on entry. 171 // key - holds the smi key on entry.
171 // Unchanged unless 'result' is the same register. 172 // Unchanged unless 'result' is the same register.
172 // 173 //
173 // result - holds the result on exit if the load succeeded. 174 // result - holds the result on exit if the load succeeded.
174 // Allowed to be the the same as 'receiver' or 'key'. 175 // Allowed to be the the same as 'receiver' or 'key'.
175 // Unchanged on bailout so 'receiver' and 'key' can be safely 176 // Unchanged on bailout so 'receiver' and 'key' can be safely
176 // used by further computation. 177 // used by further computation.
177 // 178 //
178 // Scratch registers: 179 // Scratch registers:
179 // 180 //
180 // elements - holds the elements of the receiver and its prototypes. 181 // elements - holds the elements of the receiver and its prototypes.
181 // 182 //
182 // scratch1 - used to hold elements length, bit fields, base addresses. 183 // scratch1 - used to hold elements length, bit fields, base addresses.
183 // 184 //
184 // scratch2 - used to hold maps, prototypes, and the loaded value. 185 // scratch2 - used to hold maps, prototypes, and the loaded value.
185 Label check_prototypes, check_next_prototype; 186 Label check_prototypes, check_next_prototype;
186 Label done, in_bounds, return_undefined; 187 Label done, in_bounds, absent;
187 188
188 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 189 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
189 __ AssertFastElements(elements); 190 __ AssertFastElements(elements);
190 191
191 // Check that the key (index) is within bounds. 192 // Check that the key (index) is within bounds.
192 __ ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset)); 193 __ ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset));
193 __ cmp(key, Operand(scratch1)); 194 __ cmp(key, Operand(scratch1));
194 __ b(lo, &in_bounds); 195 __ b(lo, &in_bounds);
195 // Out-of-bounds. Check the prototype chain to see if we can just return 196 // Out-of-bounds. Check the prototype chain to see if we can just return
196 // 'undefined'. 197 // 'undefined'.
197 __ cmp(key, Operand(0)); 198 __ cmp(key, Operand(0));
198 __ b(lt, slow); // Negative keys can't take the fast OOB path. 199 __ b(lt, slow); // Negative keys can't take the fast OOB path.
199 __ bind(&check_prototypes); 200 __ bind(&check_prototypes);
200 __ ldr(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); 201 __ ldr(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset));
201 __ bind(&check_next_prototype); 202 __ bind(&check_next_prototype);
202 __ ldr(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset)); 203 __ ldr(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset));
203 // scratch2: current prototype 204 // scratch2: current prototype
204 __ CompareRoot(scratch2, Heap::kNullValueRootIndex); 205 __ CompareRoot(scratch2, Heap::kNullValueRootIndex);
205 __ b(eq, &return_undefined); 206 __ b(eq, &absent);
206 __ ldr(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset)); 207 __ ldr(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset));
207 __ ldr(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset)); 208 __ ldr(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset));
208 // elements: elements of current prototype 209 // elements: elements of current prototype
209 // scratch2: map of current prototype 210 // scratch2: map of current prototype
210 __ CompareInstanceType(scratch2, scratch1, JS_OBJECT_TYPE); 211 __ CompareInstanceType(scratch2, scratch1, JS_OBJECT_TYPE);
211 __ b(lo, slow); 212 __ b(lo, slow);
212 __ ldrb(scratch1, FieldMemOperand(scratch2, Map::kBitFieldOffset)); 213 __ ldrb(scratch1, FieldMemOperand(scratch2, Map::kBitFieldOffset));
213 __ tst(scratch1, Operand((1 << Map::kIsAccessCheckNeeded) | 214 __ tst(scratch1, Operand((1 << Map::kIsAccessCheckNeeded) |
214 (1 << Map::kHasIndexedInterceptor))); 215 (1 << Map::kHasIndexedInterceptor)));
215 __ b(ne, slow); 216 __ b(ne, slow);
216 __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex); 217 __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex);
217 __ b(ne, slow); 218 __ b(ne, slow);
218 __ jmp(&check_next_prototype); 219 __ jmp(&check_next_prototype);
219 220
220 __ bind(&return_undefined); 221 __ bind(&absent);
221 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 222 if (is_strong(language_mode)) {
222 __ jmp(&done); 223 // Strong mode accesses must throw in this case, so call the runtime.
224 __ jmp(slow);
225 } else {
226 __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
227 __ jmp(&done);
228 }
223 229
224 __ bind(&in_bounds); 230 __ bind(&in_bounds);
225 // Fast case: Do the load. 231 // Fast case: Do the load.
226 __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 232 __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
227 __ ldr(scratch2, MemOperand::PointerAddressFromSmiKey(scratch1, key)); 233 __ ldr(scratch2, MemOperand::PointerAddressFromSmiKey(scratch1, key));
228 __ CompareRoot(scratch2, Heap::kTheHoleValueRootIndex); 234 __ CompareRoot(scratch2, Heap::kTheHoleValueRootIndex);
229 // In case the loaded value is the_hole we have to check the prototype chain. 235 // In case the loaded value is the_hole we have to check the prototype chain.
230 __ b(eq, &check_prototypes); 236 __ b(eq, &check_prototypes);
231 __ mov(result, scratch2); 237 __ mov(result, scratch2);
232 __ bind(&done); 238 __ bind(&done);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 Label slow; 277 Label slow;
272 278
273 __ ldr(dictionary, FieldMemOperand(LoadDescriptor::ReceiverRegister(), 279 __ ldr(dictionary, FieldMemOperand(LoadDescriptor::ReceiverRegister(),
274 JSObject::kPropertiesOffset)); 280 JSObject::kPropertiesOffset));
275 GenerateDictionaryLoad(masm, &slow, dictionary, 281 GenerateDictionaryLoad(masm, &slow, dictionary,
276 LoadDescriptor::NameRegister(), r0, r3, r4); 282 LoadDescriptor::NameRegister(), r0, r3, r4);
277 __ Ret(); 283 __ Ret();
278 284
279 // Dictionary load failed, go slow (but don't miss). 285 // Dictionary load failed, go slow (but don't miss).
280 __ bind(&slow); 286 __ bind(&slow);
281 GenerateRuntimeGetProperty(masm); 287 GenerateSlow(masm);
282 } 288 }
283 289
284 290
285 // A register that isn't one of the parameters to the load ic. 291 // A register that isn't one of the parameters to the load ic.
286 static const Register LoadIC_TempRegister() { return r3; } 292 static const Register LoadIC_TempRegister() { return r3; }
287 293
288 294
289 static void LoadIC_PushArgs(MacroAssembler* masm) { 295 static void LoadIC_PushArgs(MacroAssembler* masm) {
290 Register receiver = LoadDescriptor::ReceiverRegister(); 296 Register receiver = LoadDescriptor::ReceiverRegister();
291 Register name = LoadDescriptor::NameRegister(); 297 Register name = LoadDescriptor::NameRegister();
(...skipping 14 matching lines...) Expand all
306 312
307 LoadIC_PushArgs(masm); 313 LoadIC_PushArgs(masm);
308 314
309 // Perform tail call to the entry. 315 // Perform tail call to the entry.
310 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate); 316 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
311 int arg_count = 4; 317 int arg_count = 4;
312 __ TailCallExternalReference(ref, arg_count, 1); 318 __ TailCallExternalReference(ref, arg_count, 1);
313 } 319 }
314 320
315 321
316 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 322 void LoadIC::GenerateSlow(MacroAssembler* masm) {
317 // The return address is in lr. 323 // The return address is in lr.
318 324
319 __ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister()); 325 __ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister());
320 __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister()); 326 __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister());
321 327
322 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); 328 // Perform tail call to the entry.
329 ExternalReference ref =
330 ExternalReference(IC_Utility(kLoadIC_Slow), masm->isolate());
331 int arg_count = 2;
332 __ TailCallExternalReference(ref, arg_count, 1);
323 } 333 }
324 334
325 335
326 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 336 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
327 // The return address is in lr. 337 // The return address is in lr.
328 Isolate* isolate = masm->isolate(); 338 Isolate* isolate = masm->isolate();
329 339
330 DCHECK(!AreAliased(r4, r5, LoadWithVectorDescriptor::SlotRegister(), 340 DCHECK(!AreAliased(r4, r5, LoadWithVectorDescriptor::SlotRegister(),
331 LoadWithVectorDescriptor::VectorRegister())); 341 LoadWithVectorDescriptor::VectorRegister()));
332 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r4, r5); 342 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r4, r5);
333 343
334 LoadIC_PushArgs(masm); 344 LoadIC_PushArgs(masm);
335 345
336 // Perform tail call to the entry. 346 // Perform tail call to the entry.
337 ExternalReference ref = 347 ExternalReference ref =
338 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); 348 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate);
339 int arg_count = 4; 349 int arg_count = 4;
340 __ TailCallExternalReference(ref, arg_count, 1); 350 __ TailCallExternalReference(ref, arg_count, 1);
341 } 351 }
342 352
343 353
344 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 354 void KeyedLoadIC::GenerateSlow(MacroAssembler* masm) {
345 // The return address is in lr. 355 // The return address is in lr.
346 356
347 __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); 357 __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
348 358
349 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 359 // Perform tail call to the entry.
360 ExternalReference ref =
361 ExternalReference(IC_Utility(kKeyedLoadIC_Slow), masm->isolate());
362 int arg_count = 2;
363 __ TailCallExternalReference(ref, arg_count, 1);
350 } 364 }
351 365
352 366
353 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { 367 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
368 LanguageMode language_mode) {
354 // The return address is in lr. 369 // The return address is in lr.
355 Label slow, check_name, index_smi, index_name, property_array_property; 370 Label slow, check_name, index_smi, index_name, property_array_property;
356 Label probe_dictionary, check_number_dictionary; 371 Label probe_dictionary, check_number_dictionary;
357 372
358 Register key = LoadDescriptor::NameRegister(); 373 Register key = LoadDescriptor::NameRegister();
359 Register receiver = LoadDescriptor::ReceiverRegister(); 374 Register receiver = LoadDescriptor::ReceiverRegister();
360 DCHECK(key.is(r2)); 375 DCHECK(key.is(r2));
361 DCHECK(receiver.is(r1)); 376 DCHECK(receiver.is(r1));
362 377
363 Isolate* isolate = masm->isolate(); 378 Isolate* isolate = masm->isolate();
364 379
365 // Check that the key is a smi. 380 // Check that the key is a smi.
366 __ JumpIfNotSmi(key, &check_name); 381 __ JumpIfNotSmi(key, &check_name);
367 __ bind(&index_smi); 382 __ bind(&index_smi);
368 // Now the key is known to be a smi. This place is also jumped to from below 383 // Now the key is known to be a smi. This place is also jumped to from below
369 // where a numeric string is converted to a smi. 384 // where a numeric string is converted to a smi.
370 385
371 GenerateKeyedLoadReceiverCheck(masm, receiver, r0, r3, 386 GenerateKeyedLoadReceiverCheck(masm, receiver, r0, r3,
372 Map::kHasIndexedInterceptor, &slow); 387 Map::kHasIndexedInterceptor, &slow);
373 388
374 // Check the receiver's map to see if it has fast elements. 389 // Check the receiver's map to see if it has fast elements.
375 __ CheckFastElements(r0, r3, &check_number_dictionary); 390 __ CheckFastElements(r0, r3, &check_number_dictionary);
376 391
377 GenerateFastArrayLoad(masm, receiver, key, r0, r3, r4, r0, &slow); 392 GenerateFastArrayLoad(masm, receiver, key, r0, r3, r4, r0, &slow,
393 language_mode);
378 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r4, r3); 394 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r4, r3);
379 __ Ret(); 395 __ Ret();
380 396
381 __ bind(&check_number_dictionary); 397 __ bind(&check_number_dictionary);
382 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); 398 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
383 __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset)); 399 __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset));
384 400
385 // Check whether the elements is a number dictionary. 401 // Check whether the elements is a number dictionary.
386 // r3: elements map 402 // r3: elements map
387 // r4: elements 403 // r4: elements
388 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 404 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
389 __ cmp(r3, ip); 405 __ cmp(r3, ip);
390 __ b(ne, &slow); 406 __ b(ne, &slow);
391 __ SmiUntag(r0, key); 407 __ SmiUntag(r0, key);
392 __ LoadFromNumberDictionary(&slow, r4, key, r0, r0, r3, r5); 408 __ LoadFromNumberDictionary(&slow, r4, key, r0, r0, r3, r5);
393 __ Ret(); 409 __ Ret();
394 410
395 // Slow case, key and receiver still in r2 and r1. 411 // Slow case, key and receiver still in r2 and r1.
396 __ bind(&slow); 412 __ bind(&slow);
397 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, r4, 413 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, r4,
398 r3); 414 r3);
399 GenerateRuntimeGetProperty(masm); 415 GenerateSlow(masm);
400 416
401 __ bind(&check_name); 417 __ bind(&check_name);
402 GenerateKeyNameCheck(masm, key, r0, r3, &index_name, &slow); 418 GenerateKeyNameCheck(masm, key, r0, r3, &index_name, &slow);
403 419
404 GenerateKeyedLoadReceiverCheck(masm, receiver, r0, r3, 420 GenerateKeyedLoadReceiverCheck(masm, receiver, r0, r3,
405 Map::kHasNamedInterceptor, &slow); 421 Map::kHasNamedInterceptor, &slow);
406 422
407 // If the receiver is a fast-case object, check the stub cache. Otherwise 423 // If the receiver is a fast-case object, check the stub cache. Otherwise
408 // probe the dictionary. 424 // probe the dictionary.
409 __ ldr(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 425 __ ldr(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 patcher.EmitCondition(ne); 878 patcher.EmitCondition(ne);
863 } else { 879 } else {
864 DCHECK(Assembler::GetCondition(branch_instr) == ne); 880 DCHECK(Assembler::GetCondition(branch_instr) == ne);
865 patcher.EmitCondition(eq); 881 patcher.EmitCondition(eq);
866 } 882 }
867 } 883 }
868 } // namespace internal 884 } // namespace internal
869 } // namespace v8 885 } // namespace v8
870 886
871 #endif // V8_TARGET_ARCH_ARM 887 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/ic/arm/handler-compiler-arm.cc ('k') | src/ic/arm64/handler-compiler-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698