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

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 9310117: Implement KeyedStoreICs to grow arrays on out-of-bound stores. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add missing WB stub Created 8 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.cc ('k') | test/mjsunit/array-store-and-grow.js » ('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 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 2423 matching lines...) Expand 10 before | Expand all | Expand 10 after
2434 // ----------- S t a t e ------------- 2434 // ----------- S t a t e -------------
2435 // -- rax : value 2435 // -- rax : value
2436 // -- rcx : key 2436 // -- rcx : key
2437 // -- rdx : receiver 2437 // -- rdx : receiver
2438 // -- rsp[0] : return address 2438 // -- rsp[0] : return address
2439 // ----------------------------------- 2439 // -----------------------------------
2440 2440
2441 ElementsKind elements_kind = receiver_map->elements_kind(); 2441 ElementsKind elements_kind = receiver_map->elements_kind();
2442 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; 2442 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
2443 Handle<Code> stub = 2443 Handle<Code> stub =
2444 KeyedStoreElementStub(is_js_array, elements_kind).GetCode(); 2444 KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode();
2445 2445
2446 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); 2446 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
2447 2447
2448 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2448 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2449 __ jmp(ic, RelocInfo::CODE_TARGET); 2449 __ jmp(ic, RelocInfo::CODE_TARGET);
2450 2450
2451 // Return the generated code. 2451 // Return the generated code.
2452 return GetCode(NORMAL, factory()->empty_string()); 2452 return GetCode(NORMAL, factory()->empty_string());
2453 } 2453 }
2454 2454
(...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after
3492 __ bind(&miss_force_generic); 3492 __ bind(&miss_force_generic);
3493 Handle<Code> miss_ic = 3493 Handle<Code> miss_ic =
3494 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3494 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3495 __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3495 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3496 } 3496 }
3497 3497
3498 3498
3499 void KeyedStoreStubCompiler::GenerateStoreFastElement( 3499 void KeyedStoreStubCompiler::GenerateStoreFastElement(
3500 MacroAssembler* masm, 3500 MacroAssembler* masm,
3501 bool is_js_array, 3501 bool is_js_array,
3502 ElementsKind elements_kind) { 3502 ElementsKind elements_kind,
3503 KeyedAccessGrowMode grow_mode) {
3503 // ----------- S t a t e ------------- 3504 // ----------- S t a t e -------------
3504 // -- rax : value 3505 // -- rax : value
3505 // -- rcx : key 3506 // -- rcx : key
3506 // -- rdx : receiver 3507 // -- rdx : receiver
3507 // -- rsp[0] : return address 3508 // -- rsp[0] : return address
3508 // ----------------------------------- 3509 // -----------------------------------
3509 Label miss_force_generic, transition_elements_kind; 3510 Label miss_force_generic, transition_elements_kind, finish_store, grow;
3511 Label check_capacity, slow;
3510 3512
3511 // This stub is meant to be tail-jumped to, the receiver must already 3513 // This stub is meant to be tail-jumped to, the receiver must already
3512 // have been verified by the caller to not be a smi. 3514 // have been verified by the caller to not be a smi.
3513 3515
3514 // Check that the key is a smi. 3516 // Check that the key is a smi.
3515 __ JumpIfNotSmi(rcx, &miss_force_generic); 3517 __ JumpIfNotSmi(rcx, &miss_force_generic);
3516 3518
3519 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
3520 __ JumpIfNotSmi(rax, &transition_elements_kind);
3521 }
3522
3517 // Get the elements array and make sure it is a fast element array, not 'cow'. 3523 // Get the elements array and make sure it is a fast element array, not 'cow'.
3518 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 3524 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
3519 __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset),
3520 Heap::kFixedArrayMapRootIndex);
3521 __ j(not_equal, &miss_force_generic);
3522
3523 // Check that the key is within bounds. 3525 // Check that the key is within bounds.
3524 if (is_js_array) { 3526 if (is_js_array) {
3525 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); 3527 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
3526 __ j(above_equal, &miss_force_generic); 3528 if (grow_mode == ALLOW_JSARRAY_GROWTH) {
3529 __ j(above_equal, &grow);
3530 } else {
3531 __ j(above_equal, &miss_force_generic);
3532 }
3527 } else { 3533 } else {
3528 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); 3534 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
3529 __ j(above_equal, &miss_force_generic); 3535 __ j(above_equal, &miss_force_generic);
3530 } 3536 }
3531 3537
3538 __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset),
3539 Heap::kFixedArrayMapRootIndex);
3540 __ j(not_equal, &miss_force_generic);
3541
3542 __ bind(&finish_store);
3532 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 3543 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
3533 __ JumpIfNotSmi(rax, &transition_elements_kind);
3534 __ SmiToInteger32(rcx, rcx); 3544 __ SmiToInteger32(rcx, rcx);
3535 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize), 3545 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
3536 rax); 3546 rax);
3537 } else { 3547 } else {
3538 // Do the store and update the write barrier. 3548 // Do the store and update the write barrier.
3539 ASSERT(elements_kind == FAST_ELEMENTS); 3549 ASSERT(elements_kind == FAST_ELEMENTS);
3540 __ SmiToInteger32(rcx, rcx); 3550 __ SmiToInteger32(rcx, rcx);
3541 __ lea(rcx, 3551 __ lea(rcx,
3542 FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize)); 3552 FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize));
3543 __ movq(Operand(rcx, 0), rax); 3553 __ movq(Operand(rcx, 0), rax);
3544 // Make sure to preserve the value in register rax. 3554 // Make sure to preserve the value in register rax.
3545 __ movq(rdx, rax); 3555 __ movq(rbx, rax);
3546 __ RecordWrite(rdi, rcx, rdx, kDontSaveFPRegs); 3556 __ RecordWrite(rdi, rcx, rbx, kDontSaveFPRegs);
3547 } 3557 }
3548 3558
3549 // Done. 3559 // Done.
3550 __ ret(0); 3560 __ ret(0);
3551 3561
3552 // Handle store cache miss. 3562 // Handle store cache miss.
3553 __ bind(&miss_force_generic); 3563 __ bind(&miss_force_generic);
3554 Handle<Code> ic_force_generic = 3564 Handle<Code> ic_force_generic =
3555 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3565 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3556 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 3566 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3557 3567
3558 __ bind(&transition_elements_kind); 3568 __ bind(&transition_elements_kind);
3559 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 3569 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
3560 __ jmp(ic_miss, RelocInfo::CODE_TARGET); 3570 __ jmp(ic_miss, RelocInfo::CODE_TARGET);
3571
3572 if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
3573 // Grow the array by a single element if possible.
3574 __ bind(&grow);
3575
3576 // Make sure the array is only growing by a single element, anything else
3577 // must be handled by the runtime. Flags are already set by previous
3578 // compare.
3579 __ j(not_equal, &miss_force_generic);
3580
3581 // Check for the empty array, and preallocate a small backing store if
3582 // possible.
3583 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
3584 __ CompareRoot(rdi, Heap::kEmptyFixedArrayRootIndex);
3585 __ j(not_equal, &check_capacity);
3586
3587 int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
3588 __ AllocateInNewSpace(size, rdi, rbx, r8, &slow, TAG_OBJECT);
3589
3590 // rax: value
3591 // rcx: key
3592 // rdx: receiver
3593 // rdi: elements
3594 // Make sure that the backing store can hold additional elements.
3595 __ Move(FieldOperand(rdi, JSObject::kMapOffset),
3596 masm->isolate()->factory()->fixed_array_map());
3597 __ Move(FieldOperand(rdi, FixedArray::kLengthOffset),
3598 Smi::FromInt(JSArray::kPreallocatedArrayElements));
3599 __ LoadRoot(rbx, Heap::kTheHoleValueRootIndex);
3600 for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
3601 __ movq(FieldOperand(rdi, FixedArray::SizeFor(i)), rbx);
3602 }
3603
3604 // Store the element at index zero.
3605 __ movq(FieldOperand(rdi, FixedArray::SizeFor(0)), rax);
3606
3607 // Install the new backing store in the JSArray.
3608 __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rdi);
3609 __ RecordWriteField(rdx, JSObject::kElementsOffset, rdi, rbx,
3610 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
3611
3612 // Increment the length of the array.
3613 __ Move(FieldOperand(rdx, JSArray::kLengthOffset), Smi::FromInt(1));
3614 __ ret(0);
3615
3616 __ bind(&check_capacity);
3617 // Check for cow elements, in general they are not handled by this stub.
3618 __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset),
3619 Heap::kFixedCOWArrayMapRootIndex);
3620 __ j(equal, &miss_force_generic);
3621
3622 // rax: value
3623 // rcx: key
3624 // rdx: receiver
3625 // rdi: elements
3626 // Make sure that the backing store can hold additional elements.
3627 __ cmpq(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
3628 __ j(above_equal, &slow);
3629
3630 // Grow the array and finish the store.
3631 __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset),
3632 Smi::FromInt(1));
3633 __ jmp(&finish_store);
3634
3635 __ bind(&slow);
3636 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3637 __ jmp(ic_slow, RelocInfo::CODE_TARGET);
3638 }
3561 } 3639 }
3562 3640
3563 3641
3564 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 3642 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
3565 MacroAssembler* masm, 3643 MacroAssembler* masm,
3566 bool is_js_array) { 3644 bool is_js_array,
3645 KeyedAccessGrowMode grow_mode) {
3567 // ----------- S t a t e ------------- 3646 // ----------- S t a t e -------------
3568 // -- rax : value 3647 // -- rax : value
3569 // -- rcx : key 3648 // -- rcx : key
3570 // -- rdx : receiver 3649 // -- rdx : receiver
3571 // -- rsp[0] : return address 3650 // -- rsp[0] : return address
3572 // ----------------------------------- 3651 // -----------------------------------
3573 Label miss_force_generic, transition_elements_kind; 3652 Label miss_force_generic, transition_elements_kind, finish_store;
3653 Label grow, slow, check_capacity;
3574 3654
3575 // This stub is meant to be tail-jumped to, the receiver must already 3655 // This stub is meant to be tail-jumped to, the receiver must already
3576 // have been verified by the caller to not be a smi. 3656 // have been verified by the caller to not be a smi.
3577 3657
3578 // Check that the key is a smi. 3658 // Check that the key is a smi.
3579 __ JumpIfNotSmi(rcx, &miss_force_generic); 3659 __ JumpIfNotSmi(rcx, &miss_force_generic);
3580 3660
3581 // Get the elements array. 3661 // Get the elements array.
3582 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 3662 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
3583 __ AssertFastElements(rdi); 3663 __ AssertFastElements(rdi);
3584 3664
3585 // Check that the key is within bounds. 3665 // Check that the key is within bounds.
3586 if (is_js_array) { 3666 if (is_js_array) {
3587 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); 3667 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
3668 if (grow_mode == ALLOW_JSARRAY_GROWTH) {
3669 __ j(above_equal, &grow);
3670 } else {
3671 __ j(above_equal, &miss_force_generic);
3672 }
3588 } else { 3673 } else {
3589 __ SmiCompare(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset)); 3674 __ SmiCompare(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset));
3675 __ j(above_equal, &miss_force_generic);
3590 } 3676 }
3591 __ j(above_equal, &miss_force_generic);
3592 3677
3593 // Handle smi values specially 3678 // Handle smi values specially
3679 __ bind(&finish_store);
3594 __ SmiToInteger32(rcx, rcx); 3680 __ SmiToInteger32(rcx, rcx);
3595 __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0, 3681 __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0,
3596 &transition_elements_kind); 3682 &transition_elements_kind);
3597 __ ret(0); 3683 __ ret(0);
3598 3684
3599 // Handle store cache miss, replacing the ic with the generic stub. 3685 // Handle store cache miss, replacing the ic with the generic stub.
3600 __ bind(&miss_force_generic); 3686 __ bind(&miss_force_generic);
3601 Handle<Code> ic_force_generic = 3687 Handle<Code> ic_force_generic =
3602 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3688 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3603 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 3689 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3604 3690
3605 __ bind(&transition_elements_kind); 3691 __ bind(&transition_elements_kind);
3606 // Restore smi-tagging of rcx. 3692 // Restore smi-tagging of rcx.
3607 __ Integer32ToSmi(rcx, rcx); 3693 __ Integer32ToSmi(rcx, rcx);
3608 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 3694 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
3609 __ jmp(ic_miss, RelocInfo::CODE_TARGET); 3695 __ jmp(ic_miss, RelocInfo::CODE_TARGET);
3696
3697 if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
3698 // Grow the array by a single element if possible.
3699 __ bind(&grow);
3700
3701 // Make sure the array is only growing by a single element, anything else
3702 // must be handled by the runtime. Flags are already set by previous
3703 // compare.
3704 __ j(not_equal, &miss_force_generic);
3705
3706 // Transition on values that can't be stored in a FixedDoubleArray.
3707 Label value_is_smi;
3708 __ JumpIfSmi(rax, &value_is_smi);
3709 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
3710 Heap::kHeapNumberMapRootIndex);
3711 __ j(not_equal, &transition_elements_kind);
3712 __ bind(&value_is_smi);
3713
3714 // Check for the empty array, and preallocate a small backing store if
3715 // possible.
3716 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
3717 __ CompareRoot(rdi, Heap::kEmptyFixedArrayRootIndex);
3718 __ j(not_equal, &check_capacity);
3719
3720 int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
3721 __ AllocateInNewSpace(size, rdi, rbx, r8, &slow, TAG_OBJECT);
3722
3723 // rax: value
3724 // rcx: key
3725 // rdx: receiver
3726 // rdi: elements
3727 // Initialize the new FixedDoubleArray. Leave elements unitialized for
3728 // efficiency, they are guaranteed to be initialized before use.
3729 __ Move(FieldOperand(rdi, JSObject::kMapOffset),
3730 masm->isolate()->factory()->fixed_double_array_map());
3731 __ Move(FieldOperand(rdi, FixedDoubleArray::kLengthOffset),
3732 Smi::FromInt(JSArray::kPreallocatedArrayElements));
3733
3734 // Install the new backing store in the JSArray.
3735 __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rdi);
3736 __ RecordWriteField(rdx, JSObject::kElementsOffset, rdi, rbx,
3737 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
3738
3739 // Increment the length of the array.
3740 __ Move(FieldOperand(rdx, JSArray::kLengthOffset), Smi::FromInt(1));
3741 __ jmp(&finish_store);
3742
3743 __ bind(&check_capacity);
3744 // rax: value
3745 // rcx: key
3746 // rdx: receiver
3747 // rdi: elements
3748 // Make sure that the backing store can hold additional elements.
3749 __ cmpq(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset));
3750 __ j(above_equal, &slow);
3751
3752 // Grow the array and finish the store.
3753 __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset),
3754 Smi::FromInt(1));
3755 __ jmp(&finish_store);
3756
3757 __ bind(&slow);
3758 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3759 __ jmp(ic_slow, RelocInfo::CODE_TARGET);
3760 }
3610 } 3761 }
3611 3762
3612 3763
3613 #undef __ 3764 #undef __
3614 3765
3615 } } // namespace v8::internal 3766 } } // namespace v8::internal
3616 3767
3617 #endif // V8_TARGET_ARCH_X64 3768 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.cc ('k') | test/mjsunit/array-store-and-grow.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698