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 2523473002: [cleanup] Drop handwritten KeyedStoreIC code (Closed)
Patch Set: rebased Created 4 years 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/macro-assembler-ia32.cc ('k') | src/ic/arm/ic-compiler-arm.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 #if V8_TARGET_ARCH_ARM 5 #if V8_TARGET_ARCH_ARM
6 6
7 #include "src/codegen.h" 7 #include "src/codegen.h"
8 #include "src/ic/ic.h" 8 #include "src/ic/ic.h"
9 #include "src/ic/ic-compiler.h" 9 #include "src/ic/ic-compiler.h"
10 #include "src/ic/stub-cache.h" 10 #include "src/ic/stub-cache.h"
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 } 212 }
213 213
214 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { 214 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
215 StoreIC_PushArgs(masm); 215 StoreIC_PushArgs(masm);
216 216
217 // The slow case calls into the runtime to complete the store without causing 217 // The slow case calls into the runtime to complete the store without causing
218 // an IC miss that would otherwise cause a transition to the generic stub. 218 // an IC miss that would otherwise cause a transition to the generic stub.
219 __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); 219 __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
220 } 220 }
221 221
222 static void KeyedStoreGenerateMegamorphicHelper(
223 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow,
224 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length,
225 Register value, Register key, Register receiver, Register receiver_map,
226 Register elements_map, Register elements) {
227 Label transition_smi_elements;
228 Label finish_object_store, non_double_value, transition_double_elements;
229 Label fast_double_without_map_check;
230
231 // Fast case: Do the store, could be either Object or double.
232 __ bind(fast_object);
233 Register scratch = r4;
234 Register address = r5;
235 DCHECK(!AreAliased(value, key, receiver, receiver_map, elements_map, elements,
236 scratch, address));
237
238 if (check_map == kCheckMap) {
239 __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
240 __ cmp(elements_map,
241 Operand(masm->isolate()->factory()->fixed_array_map()));
242 __ b(ne, fast_double);
243 }
244
245 // HOLECHECK: guards "A[i] = V"
246 // We have to go to the runtime if the current value is the hole because
247 // there may be a callback on the element
248 Label holecheck_passed1;
249 __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
250 __ ldr(scratch, MemOperand::PointerAddressFromSmiKey(address, key, PreIndex));
251 __ cmp(scratch, Operand(masm->isolate()->factory()->the_hole_value()));
252 __ b(ne, &holecheck_passed1);
253 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch, slow);
254
255 __ bind(&holecheck_passed1);
256
257 // Smi stores don't require further checks.
258 Label non_smi_value;
259 __ JumpIfNotSmi(value, &non_smi_value);
260
261 if (increment_length == kIncrementLength) {
262 // Add 1 to receiver->length.
263 __ add(scratch, key, Operand(Smi::FromInt(1)));
264 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
265 }
266 // It's irrelevant whether array is smi-only or not when writing a smi.
267 __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
268 __ str(value, MemOperand::PointerAddressFromSmiKey(address, key));
269 __ Ret();
270
271 __ bind(&non_smi_value);
272 // Escape to elements kind transition case.
273 __ CheckFastObjectElements(receiver_map, scratch, &transition_smi_elements);
274
275 // Fast elements array, store the value to the elements backing store.
276 __ bind(&finish_object_store);
277 if (increment_length == kIncrementLength) {
278 // Add 1 to receiver->length.
279 __ add(scratch, key, Operand(Smi::FromInt(1)));
280 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
281 }
282 __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
283 __ add(address, address, Operand::PointerOffsetFromSmiKey(key));
284 __ str(value, MemOperand(address));
285 // Update write barrier for the elements array address.
286 __ mov(scratch, value); // Preserve the value which is returned.
287 __ RecordWrite(elements, address, scratch, kLRHasNotBeenSaved,
288 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
289 __ Ret();
290
291 __ bind(fast_double);
292 if (check_map == kCheckMap) {
293 // Check for fast double array case. If this fails, call through to the
294 // runtime.
295 __ CompareRoot(elements_map, Heap::kFixedDoubleArrayMapRootIndex);
296 __ b(ne, slow);
297 }
298
299 // HOLECHECK: guards "A[i] double hole?"
300 // We have to see if the double version of the hole is present. If so
301 // go to the runtime.
302 __ add(address, elements,
303 Operand((FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32)) -
304 kHeapObjectTag));
305 __ ldr(scratch, MemOperand(address, key, LSL, kPointerSizeLog2, PreIndex));
306 __ cmp(scratch, Operand(kHoleNanUpper32));
307 __ b(ne, &fast_double_without_map_check);
308 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch, slow);
309
310 __ bind(&fast_double_without_map_check);
311 __ StoreNumberToDoubleElements(value, key, elements, scratch, d0,
312 &transition_double_elements);
313 if (increment_length == kIncrementLength) {
314 // Add 1 to receiver->length.
315 __ add(scratch, key, Operand(Smi::FromInt(1)));
316 __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
317 }
318 __ Ret();
319
320 __ bind(&transition_smi_elements);
321 // Transition the array appropriately depending on the value type.
322 __ ldr(scratch, FieldMemOperand(value, HeapObject::kMapOffset));
323 __ CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
324 __ b(ne, &non_double_value);
325
326 // Value is a double. Transition FAST_SMI_ELEMENTS ->
327 // FAST_DOUBLE_ELEMENTS and complete the store.
328 __ LoadTransitionedArrayMapConditional(
329 FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS, receiver_map, scratch, slow);
330 AllocationSiteMode mode =
331 AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS);
332 ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value,
333 receiver_map, mode, slow);
334 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
335 __ jmp(&fast_double_without_map_check);
336
337 __ bind(&non_double_value);
338 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS
339 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS,
340 receiver_map, scratch, slow);
341 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS);
342 ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
343 masm, receiver, key, value, receiver_map, mode, slow);
344 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
345 __ jmp(&finish_object_store);
346
347 __ bind(&transition_double_elements);
348 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
349 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
350 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
351 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS,
352 receiver_map, scratch, slow);
353 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS);
354 ElementsTransitionGenerator::GenerateDoubleToObject(
355 masm, receiver, key, value, receiver_map, mode, slow);
356 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
357 __ jmp(&finish_object_store);
358 }
359
360
361 void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm,
362 LanguageMode language_mode) {
363 // ---------- S t a t e --------------
364 // -- r0 : value
365 // -- r1 : key
366 // -- r2 : receiver
367 // -- lr : return address
368 // -----------------------------------
369 Label slow, fast_object, fast_object_grow;
370 Label fast_double, fast_double_grow;
371 Label array, extra, check_if_double_array, maybe_name_key, miss;
372
373 // Register usage.
374 Register value = StoreDescriptor::ValueRegister();
375 Register key = StoreDescriptor::NameRegister();
376 Register receiver = StoreDescriptor::ReceiverRegister();
377 DCHECK(receiver.is(r1));
378 DCHECK(key.is(r2));
379 DCHECK(value.is(r0));
380 Register receiver_map = r3;
381 Register elements_map = r6;
382 Register elements = r9; // Elements array of the receiver.
383 // r4 and r5 are used as general scratch registers.
384
385 // Check that the key is a smi.
386 __ JumpIfNotSmi(key, &maybe_name_key);
387 // Check that the object isn't a smi.
388 __ JumpIfSmi(receiver, &slow);
389 // Get the map of the object.
390 __ ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
391 // Check that the receiver does not require access checks.
392 // The generic stub does not perform map checks.
393 __ ldrb(ip, FieldMemOperand(receiver_map, Map::kBitFieldOffset));
394 __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded));
395 __ b(ne, &slow);
396 // Check if the object is a JS array or not.
397 __ ldrb(r4, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset));
398 __ cmp(r4, Operand(JS_ARRAY_TYPE));
399 __ b(eq, &array);
400 // Check that the object is some kind of JS object EXCEPT JS Value type. In
401 // the case that the object is a value-wrapper object, we enter the runtime
402 // system to make sure that indexing into string objects works as intended.
403 STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
404 __ cmp(r4, Operand(JS_OBJECT_TYPE));
405 __ b(lo, &slow);
406
407 // Object case: Check key against length in the elements array.
408 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
409 // Check array bounds. Both the key and the length of FixedArray are smis.
410 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset));
411 __ cmp(key, Operand(ip));
412 __ b(lo, &fast_object);
413
414 // Slow case, handle jump to runtime.
415 __ bind(&slow);
416 // Entry registers are intact.
417 // r0: value.
418 // r1: key.
419 // r2: receiver.
420 PropertyICCompiler::GenerateRuntimeSetProperty(masm, language_mode);
421 // Never returns to here.
422
423 __ bind(&maybe_name_key);
424 __ ldr(r4, FieldMemOperand(key, HeapObject::kMapOffset));
425 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
426 __ JumpIfNotUniqueNameInstanceType(r4, &slow);
427
428 // We use register r8, because otherwise probing the megamorphic stub cache
429 // would require pushing temporaries on the stack.
430 // TODO(mvstanton): quit using register r8 when
431 // FLAG_enable_embedded_constant_pool is turned on.
432 DCHECK(!FLAG_enable_embedded_constant_pool);
433 Register temporary2 = r8;
434 // The handlers in the stub cache expect a vector and slot. Since we won't
435 // change the IC from any downstream misses, a dummy vector can be used.
436 Register vector = StoreWithVectorDescriptor::VectorRegister();
437 Register slot = StoreWithVectorDescriptor::SlotRegister();
438
439 DCHECK(!AreAliased(vector, slot, r5, temporary2, r6, r9));
440 Handle<TypeFeedbackVector> dummy_vector =
441 TypeFeedbackVector::DummyVector(masm->isolate());
442 int slot_index = dummy_vector->GetIndex(
443 FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot));
444 __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
445 __ mov(slot, Operand(Smi::FromInt(slot_index)));
446
447 masm->isolate()->store_stub_cache()->GenerateProbe(masm, receiver, key, r5,
448 temporary2, r6, r9);
449 // Cache miss.
450 __ b(&miss);
451
452 // Extra capacity case: Check if there is extra capacity to
453 // perform the store and update the length. Used for adding one
454 // element to the array by writing to array[array.length].
455 __ bind(&extra);
456 // Condition code from comparing key and array length is still available.
457 __ b(ne, &slow); // Only support writing to writing to array[array.length].
458 // Check for room in the elements backing store.
459 // Both the key and the length of FixedArray are smis.
460 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset));
461 __ cmp(key, Operand(ip));
462 __ b(hs, &slow);
463 __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
464 __ cmp(elements_map, Operand(masm->isolate()->factory()->fixed_array_map()));
465 __ b(ne, &check_if_double_array);
466 __ jmp(&fast_object_grow);
467
468 __ bind(&check_if_double_array);
469 __ cmp(elements_map,
470 Operand(masm->isolate()->factory()->fixed_double_array_map()));
471 __ b(ne, &slow);
472 __ jmp(&fast_double_grow);
473
474 // Array case: Get the length and the elements array from the JS
475 // array. Check that the array is in fast mode (and writable); if it
476 // is the length is always a smi.
477 __ bind(&array);
478 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
479
480 // Check the key against the length in the array.
481 __ ldr(ip, FieldMemOperand(receiver, JSArray::kLengthOffset));
482 __ cmp(key, Operand(ip));
483 __ b(hs, &extra);
484
485 KeyedStoreGenerateMegamorphicHelper(
486 masm, &fast_object, &fast_double, &slow, kCheckMap, kDontIncrementLength,
487 value, key, receiver, receiver_map, elements_map, elements);
488 KeyedStoreGenerateMegamorphicHelper(masm, &fast_object_grow,
489 &fast_double_grow, &slow, kDontCheckMap,
490 kIncrementLength, value, key, receiver,
491 receiver_map, elements_map, elements);
492
493 __ bind(&miss);
494 GenerateMiss(masm);
495 }
496
497 void StoreIC::GenerateMiss(MacroAssembler* masm) { 222 void StoreIC::GenerateMiss(MacroAssembler* masm) {
498 StoreIC_PushArgs(masm); 223 StoreIC_PushArgs(masm);
499 224
500 // Perform tail call to the entry. 225 // Perform tail call to the entry.
501 __ TailCallRuntime(Runtime::kStoreIC_Miss); 226 __ TailCallRuntime(Runtime::kStoreIC_Miss);
502 } 227 }
503 228
504 229
505 void StoreIC::GenerateNormal(MacroAssembler* masm) { 230 void StoreIC::GenerateNormal(MacroAssembler* masm) {
506 Label miss; 231 Label miss;
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 patcher.EmitCondition(ne); 345 patcher.EmitCondition(ne);
621 } else { 346 } else {
622 DCHECK(Assembler::GetCondition(branch_instr) == ne); 347 DCHECK(Assembler::GetCondition(branch_instr) == ne);
623 patcher.EmitCondition(eq); 348 patcher.EmitCondition(eq);
624 } 349 }
625 } 350 }
626 } // namespace internal 351 } // namespace internal
627 } // namespace v8 352 } // namespace v8
628 353
629 #endif // V8_TARGET_ARCH_ARM 354 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/ic/arm/ic-compiler-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698