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

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

Issue 1199983002: [strong] Implement strong property access semantics (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: add TODOs Created 5 years, 5 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/ia32/lithium-codegen-ia32.cc ('k') | src/ic/arm64/ic-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 23 matching lines...) Expand all
256 // map: key map 262 // map: key map
257 __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); 263 __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset));
258 STATIC_ASSERT(kInternalizedTag == 0); 264 STATIC_ASSERT(kInternalizedTag == 0);
259 __ tst(hash, Operand(kIsNotInternalizedMask)); 265 __ tst(hash, Operand(kIsNotInternalizedMask));
260 __ b(ne, not_unique); 266 __ b(ne, not_unique);
261 267
262 __ bind(&unique); 268 __ bind(&unique);
263 } 269 }
264 270
265 271
266 void LoadIC::GenerateNormal(MacroAssembler* masm) { 272 void LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) {
267 Register dictionary = r0; 273 Register dictionary = r0;
268 DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); 274 DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister()));
269 DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); 275 DCHECK(!dictionary.is(LoadDescriptor::NameRegister()));
270 276
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 GenerateRuntimeGetProperty(masm, language_mode);
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::GenerateRuntimeGetProperty(MacroAssembler* masm,
323 LanguageMode language_mode) {
317 // The return address is in lr. 324 // The return address is in lr.
318 325
319 __ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister()); 326 __ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister());
320 __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister()); 327 __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister());
321 328
322 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); 329 // Do tail-call to runtime routine.
330 __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong
331 : Runtime::kGetProperty,
332 2, 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::GenerateRuntimeGetProperty(MacroAssembler* masm,
355 LanguageMode language_mode) {
345 // The return address is in lr. 356 // The return address is in lr.
346 357
347 __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); 358 __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
348 359
349 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 360 // Perform tail call to the entry.
361 // Do tail-call to runtime routine.
362 __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong
363 : Runtime::kKeyedGetProperty,
364 2, 1);
350 } 365 }
351 366
352 367
353 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { 368 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
369 LanguageMode language_mode) {
354 // The return address is in lr. 370 // The return address is in lr.
355 Label slow, check_name, index_smi, index_name, property_array_property; 371 Label slow, check_name, index_smi, index_name, property_array_property;
356 Label probe_dictionary, check_number_dictionary; 372 Label probe_dictionary, check_number_dictionary;
357 373
358 Register key = LoadDescriptor::NameRegister(); 374 Register key = LoadDescriptor::NameRegister();
359 Register receiver = LoadDescriptor::ReceiverRegister(); 375 Register receiver = LoadDescriptor::ReceiverRegister();
360 DCHECK(key.is(r2)); 376 DCHECK(key.is(r2));
361 DCHECK(receiver.is(r1)); 377 DCHECK(receiver.is(r1));
362 378
363 Isolate* isolate = masm->isolate(); 379 Isolate* isolate = masm->isolate();
364 380
365 // Check that the key is a smi. 381 // Check that the key is a smi.
366 __ JumpIfNotSmi(key, &check_name); 382 __ JumpIfNotSmi(key, &check_name);
367 __ bind(&index_smi); 383 __ bind(&index_smi);
368 // Now the key is known to be a smi. This place is also jumped to from below 384 // 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. 385 // where a numeric string is converted to a smi.
370 386
371 GenerateKeyedLoadReceiverCheck(masm, receiver, r0, r3, 387 GenerateKeyedLoadReceiverCheck(masm, receiver, r0, r3,
372 Map::kHasIndexedInterceptor, &slow); 388 Map::kHasIndexedInterceptor, &slow);
373 389
374 // Check the receiver's map to see if it has fast elements. 390 // Check the receiver's map to see if it has fast elements.
375 __ CheckFastElements(r0, r3, &check_number_dictionary); 391 __ CheckFastElements(r0, r3, &check_number_dictionary);
376 392
377 GenerateFastArrayLoad(masm, receiver, key, r0, r3, r4, r0, &slow); 393 GenerateFastArrayLoad(masm, receiver, key, r0, r3, r4, r0, &slow,
394 language_mode);
378 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r4, r3); 395 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r4, r3);
379 __ Ret(); 396 __ Ret();
380 397
381 __ bind(&check_number_dictionary); 398 __ bind(&check_number_dictionary);
382 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); 399 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
383 __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset)); 400 __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset));
384 401
385 // Check whether the elements is a number dictionary. 402 // Check whether the elements is a number dictionary.
386 // r3: elements map 403 // r3: elements map
387 // r4: elements 404 // r4: elements
388 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 405 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
389 __ cmp(r3, ip); 406 __ cmp(r3, ip);
390 __ b(ne, &slow); 407 __ b(ne, &slow);
391 __ SmiUntag(r0, key); 408 __ SmiUntag(r0, key);
392 __ LoadFromNumberDictionary(&slow, r4, key, r0, r0, r3, r5); 409 __ LoadFromNumberDictionary(&slow, r4, key, r0, r0, r3, r5);
393 __ Ret(); 410 __ Ret();
394 411
395 // Slow case, key and receiver still in r2 and r1. 412 // Slow case, key and receiver still in r2 and r1.
396 __ bind(&slow); 413 __ bind(&slow);
397 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, r4, 414 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, r4,
398 r3); 415 r3);
399 GenerateRuntimeGetProperty(masm); 416 GenerateRuntimeGetProperty(masm, language_mode);
400 417
401 __ bind(&check_name); 418 __ bind(&check_name);
402 GenerateKeyNameCheck(masm, key, r0, r3, &index_name, &slow); 419 GenerateKeyNameCheck(masm, key, r0, r3, &index_name, &slow);
403 420
404 GenerateKeyedLoadReceiverCheck(masm, receiver, r0, r3, 421 GenerateKeyedLoadReceiverCheck(masm, receiver, r0, r3,
405 Map::kHasNamedInterceptor, &slow); 422 Map::kHasNamedInterceptor, &slow);
406 423
407 // If the receiver is a fast-case object, check the stub cache. Otherwise 424 // If the receiver is a fast-case object, check the stub cache. Otherwise
408 // probe the dictionary. 425 // probe the dictionary.
409 __ ldr(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 426 __ ldr(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
876 patcher.EmitCondition(ne); 893 patcher.EmitCondition(ne);
877 } else { 894 } else {
878 DCHECK(Assembler::GetCondition(branch_instr) == ne); 895 DCHECK(Assembler::GetCondition(branch_instr) == ne);
879 patcher.EmitCondition(eq); 896 patcher.EmitCondition(eq);
880 } 897 }
881 } 898 }
882 } // namespace internal 899 } // namespace internal
883 } // namespace v8 900 } // namespace v8
884 901
885 #endif // V8_TARGET_ARCH_ARM 902 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.cc ('k') | src/ic/arm64/ic-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698