OLD | NEW |
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 3161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3172 | 3172 |
3173 | 3173 |
3174 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 3174 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
3175 Handle<Map> receiver_map) { | 3175 Handle<Map> receiver_map) { |
3176 // ----------- S t a t e ------------- | 3176 // ----------- S t a t e ------------- |
3177 // -- rax : key | 3177 // -- rax : key |
3178 // -- rdx : receiver | 3178 // -- rdx : receiver |
3179 // -- rsp[0] : return address | 3179 // -- rsp[0] : return address |
3180 // ----------------------------------- | 3180 // ----------------------------------- |
3181 ElementsKind elements_kind = receiver_map->elements_kind(); | 3181 ElementsKind elements_kind = receiver_map->elements_kind(); |
3182 Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); | 3182 if (receiver_map->has_fast_elements() || |
| 3183 receiver_map->has_external_array_elements()) { |
| 3184 Handle<Code> stub = KeyedLoadFastElementStub( |
| 3185 receiver_map->instance_type() == JS_ARRAY_TYPE, |
| 3186 elements_kind).GetCode(); |
| 3187 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); |
| 3188 } else { |
| 3189 Handle<Code> stub = |
| 3190 KeyedLoadDictionaryElementStub().GetCode(); |
| 3191 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); |
| 3192 } |
3183 | 3193 |
3184 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); | 3194 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3185 | |
3186 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | |
3187 __ jmp(ic, RelocInfo::CODE_TARGET); | |
3188 | 3195 |
3189 // Return the generated code. | 3196 // Return the generated code. |
3190 return GetCode(Code::NORMAL, factory()->empty_string()); | 3197 return GetCode(Code::NORMAL, factory()->empty_string()); |
3191 } | 3198 } |
3192 | 3199 |
3193 | 3200 |
3194 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3201 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( |
3195 MapHandleList* receiver_maps, | 3202 MapHandleList* receiver_maps, |
3196 CodeHandleList* handler_ics) { | 3203 CodeHandleList* handler_ics) { |
3197 // ----------- S t a t e ------------- | 3204 // ----------- S t a t e ------------- |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3419 __ cvttsd2si(scratch, xmm_scratch0); | 3426 __ cvttsd2si(scratch, xmm_scratch0); |
3420 __ cvtlsi2sd(xmm_scratch1, scratch); | 3427 __ cvtlsi2sd(xmm_scratch1, scratch); |
3421 __ ucomisd(xmm_scratch1, xmm_scratch0); | 3428 __ ucomisd(xmm_scratch1, xmm_scratch0); |
3422 __ j(not_equal, fail); | 3429 __ j(not_equal, fail); |
3423 __ j(parity_even, fail); // NaN. | 3430 __ j(parity_even, fail); // NaN. |
3424 __ Integer32ToSmi(key, scratch); | 3431 __ Integer32ToSmi(key, scratch); |
3425 __ bind(&key_ok); | 3432 __ bind(&key_ok); |
3426 } | 3433 } |
3427 | 3434 |
3428 | 3435 |
3429 void KeyedLoadStubCompiler::GenerateLoadExternalArray( | |
3430 MacroAssembler* masm, | |
3431 ElementsKind elements_kind) { | |
3432 // ----------- S t a t e ------------- | |
3433 // -- rax : key | |
3434 // -- rdx : receiver | |
3435 // -- rsp[0] : return address | |
3436 // ----------------------------------- | |
3437 Label slow, miss_force_generic; | |
3438 | |
3439 // This stub is meant to be tail-jumped to, the receiver must already | |
3440 // have been verified by the caller to not be a smi. | |
3441 | |
3442 // Check that the key is a smi or a heap number convertible to a smi. | |
3443 GenerateSmiKeyCheck(masm, rax, rcx, xmm0, xmm1, &miss_force_generic); | |
3444 | |
3445 // Check that the index is in range. | |
3446 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | |
3447 __ SmiToInteger32(rcx, rax); | |
3448 __ cmpq(rax, FieldOperand(rbx, ExternalArray::kLengthOffset)); | |
3449 // Unsigned comparison catches both negative and too-large values. | |
3450 __ j(above_equal, &miss_force_generic); | |
3451 | |
3452 // rax: index (as a smi) | |
3453 // rdx: receiver (JSObject) | |
3454 // rcx: untagged index | |
3455 // rbx: elements array | |
3456 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); | |
3457 // rbx: base pointer of external storage | |
3458 switch (elements_kind) { | |
3459 case EXTERNAL_BYTE_ELEMENTS: | |
3460 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0)); | |
3461 break; | |
3462 case EXTERNAL_PIXEL_ELEMENTS: | |
3463 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
3464 __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0)); | |
3465 break; | |
3466 case EXTERNAL_SHORT_ELEMENTS: | |
3467 __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0)); | |
3468 break; | |
3469 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
3470 __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0)); | |
3471 break; | |
3472 case EXTERNAL_INT_ELEMENTS: | |
3473 __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0)); | |
3474 break; | |
3475 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
3476 __ movl(rcx, Operand(rbx, rcx, times_4, 0)); | |
3477 break; | |
3478 case EXTERNAL_FLOAT_ELEMENTS: | |
3479 __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0)); | |
3480 break; | |
3481 case EXTERNAL_DOUBLE_ELEMENTS: | |
3482 __ movsd(xmm0, Operand(rbx, rcx, times_8, 0)); | |
3483 break; | |
3484 default: | |
3485 UNREACHABLE(); | |
3486 break; | |
3487 } | |
3488 | |
3489 // rax: index | |
3490 // rdx: receiver | |
3491 // For integer array types: | |
3492 // rcx: value | |
3493 // For floating-point array type: | |
3494 // xmm0: value as double. | |
3495 | |
3496 ASSERT(kSmiValueSize == 32); | |
3497 if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { | |
3498 // For the UnsignedInt array type, we need to see whether | |
3499 // the value can be represented in a Smi. If not, we need to convert | |
3500 // it to a HeapNumber. | |
3501 Label box_int; | |
3502 | |
3503 __ JumpIfUIntNotValidSmiValue(rcx, &box_int, Label::kNear); | |
3504 | |
3505 __ Integer32ToSmi(rax, rcx); | |
3506 __ ret(0); | |
3507 | |
3508 __ bind(&box_int); | |
3509 | |
3510 // Allocate a HeapNumber for the int and perform int-to-double | |
3511 // conversion. | |
3512 // The value is zero-extended since we loaded the value from memory | |
3513 // with movl. | |
3514 __ cvtqsi2sd(xmm0, rcx); | |
3515 | |
3516 __ AllocateHeapNumber(rcx, rbx, &slow); | |
3517 // Set the value. | |
3518 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); | |
3519 __ movq(rax, rcx); | |
3520 __ ret(0); | |
3521 } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | |
3522 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | |
3523 // For the floating-point array type, we need to always allocate a | |
3524 // HeapNumber. | |
3525 __ AllocateHeapNumber(rcx, rbx, &slow); | |
3526 // Set the value. | |
3527 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); | |
3528 __ movq(rax, rcx); | |
3529 __ ret(0); | |
3530 } else { | |
3531 __ Integer32ToSmi(rax, rcx); | |
3532 __ ret(0); | |
3533 } | |
3534 | |
3535 // Slow case: Jump to runtime. | |
3536 __ bind(&slow); | |
3537 Counters* counters = masm->isolate()->counters(); | |
3538 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); | |
3539 | |
3540 // ----------- S t a t e ------------- | |
3541 // -- rax : key | |
3542 // -- rdx : receiver | |
3543 // -- rsp[0] : return address | |
3544 // ----------------------------------- | |
3545 | |
3546 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow(); | |
3547 __ jmp(ic, RelocInfo::CODE_TARGET); | |
3548 | |
3549 // Miss case: Jump to runtime. | |
3550 __ bind(&miss_force_generic); | |
3551 | |
3552 // ----------- S t a t e ------------- | |
3553 // -- rax : key | |
3554 // -- rdx : receiver | |
3555 // -- rsp[0] : return address | |
3556 // ----------------------------------- | |
3557 Handle<Code> miss_ic = | |
3558 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | |
3559 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
3560 } | |
3561 | |
3562 | |
3563 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3436 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
3564 MacroAssembler* masm, | 3437 MacroAssembler* masm, |
3565 ElementsKind elements_kind) { | 3438 ElementsKind elements_kind) { |
3566 // ----------- S t a t e ------------- | 3439 // ----------- S t a t e ------------- |
3567 // -- rax : value | 3440 // -- rax : value |
3568 // -- rcx : key | 3441 // -- rcx : key |
3569 // -- rdx : receiver | 3442 // -- rdx : receiver |
3570 // -- rsp[0] : return address | 3443 // -- rsp[0] : return address |
3571 // ----------------------------------- | 3444 // ----------------------------------- |
3572 Label slow, miss_force_generic; | 3445 Label slow, miss_force_generic; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3742 // -- rdx : receiver | 3615 // -- rdx : receiver |
3743 // -- rsp[0] : return address | 3616 // -- rsp[0] : return address |
3744 // ----------------------------------- | 3617 // ----------------------------------- |
3745 | 3618 |
3746 Handle<Code> miss_ic = | 3619 Handle<Code> miss_ic = |
3747 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3620 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3748 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 3621 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
3749 } | 3622 } |
3750 | 3623 |
3751 | 3624 |
3752 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { | |
3753 // ----------- S t a t e ------------- | |
3754 // -- rax : key | |
3755 // -- rdx : receiver | |
3756 // -- rsp[0] : return address | |
3757 // ----------------------------------- | |
3758 Label miss_force_generic; | |
3759 | |
3760 // This stub is meant to be tail-jumped to, the receiver must already | |
3761 // have been verified by the caller to not be a smi. | |
3762 | |
3763 // Check that the key is a smi or a heap number convertible to a smi. | |
3764 GenerateSmiKeyCheck(masm, rax, rcx, xmm0, xmm1, &miss_force_generic); | |
3765 | |
3766 // Get the elements array. | |
3767 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); | |
3768 __ AssertFastElements(rcx); | |
3769 | |
3770 // Check that the key is within bounds. | |
3771 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); | |
3772 __ j(above_equal, &miss_force_generic); | |
3773 | |
3774 // Load the result and make sure it's not the hole. | |
3775 SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2); | |
3776 __ movq(rbx, FieldOperand(rcx, | |
3777 index.reg, | |
3778 index.scale, | |
3779 FixedArray::kHeaderSize)); | |
3780 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | |
3781 __ j(equal, &miss_force_generic); | |
3782 __ movq(rax, rbx); | |
3783 __ ret(0); | |
3784 | |
3785 __ bind(&miss_force_generic); | |
3786 Code* code = masm->isolate()->builtins()->builtin( | |
3787 Builtins::kKeyedLoadIC_MissForceGeneric); | |
3788 Handle<Code> ic(code); | |
3789 __ jmp(ic, RelocInfo::CODE_TARGET); | |
3790 } | |
3791 | |
3792 | |
3793 void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( | |
3794 MacroAssembler* masm) { | |
3795 // ----------- S t a t e ------------- | |
3796 // -- rax : key | |
3797 // -- rdx : receiver | |
3798 // -- rsp[0] : return address | |
3799 // ----------------------------------- | |
3800 Label miss_force_generic, slow_allocate_heapnumber; | |
3801 | |
3802 // This stub is meant to be tail-jumped to, the receiver must already | |
3803 // have been verified by the caller to not be a smi. | |
3804 | |
3805 // Check that the key is a smi or a heap number convertible to a smi. | |
3806 GenerateSmiKeyCheck(masm, rax, rcx, xmm0, xmm1, &miss_force_generic); | |
3807 | |
3808 // Get the elements array. | |
3809 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); | |
3810 __ AssertFastElements(rcx); | |
3811 | |
3812 // Check that the key is within bounds. | |
3813 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); | |
3814 __ j(above_equal, &miss_force_generic); | |
3815 | |
3816 // Check for the hole | |
3817 __ SmiToInteger32(kScratchRegister, rax); | |
3818 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); | |
3819 __ cmpl(FieldOperand(rcx, kScratchRegister, times_8, offset), | |
3820 Immediate(kHoleNanUpper32)); | |
3821 __ j(equal, &miss_force_generic); | |
3822 | |
3823 // Always allocate a heap number for the result. | |
3824 __ movsd(xmm0, FieldOperand(rcx, kScratchRegister, times_8, | |
3825 FixedDoubleArray::kHeaderSize)); | |
3826 __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber); | |
3827 // Set the value. | |
3828 __ movq(rax, rcx); | |
3829 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); | |
3830 __ ret(0); | |
3831 | |
3832 __ bind(&slow_allocate_heapnumber); | |
3833 Handle<Code> slow_ic = | |
3834 masm->isolate()->builtins()->KeyedLoadIC_Slow(); | |
3835 __ jmp(slow_ic, RelocInfo::CODE_TARGET); | |
3836 | |
3837 __ bind(&miss_force_generic); | |
3838 Handle<Code> miss_ic = | |
3839 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | |
3840 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
3841 } | |
3842 | |
3843 | |
3844 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 3625 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
3845 MacroAssembler* masm, | 3626 MacroAssembler* masm, |
3846 bool is_js_array, | 3627 bool is_js_array, |
3847 ElementsKind elements_kind, | 3628 ElementsKind elements_kind, |
3848 KeyedAccessGrowMode grow_mode) { | 3629 KeyedAccessGrowMode grow_mode) { |
3849 // ----------- S t a t e ------------- | 3630 // ----------- S t a t e ------------- |
3850 // -- rax : value | 3631 // -- rax : value |
3851 // -- rcx : key | 3632 // -- rcx : key |
3852 // -- rdx : receiver | 3633 // -- rdx : receiver |
3853 // -- rsp[0] : return address | 3634 // -- rsp[0] : return address |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4105 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 3886 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
4106 } | 3887 } |
4107 } | 3888 } |
4108 | 3889 |
4109 | 3890 |
4110 #undef __ | 3891 #undef __ |
4111 | 3892 |
4112 } } // namespace v8::internal | 3893 } } // namespace v8::internal |
4113 | 3894 |
4114 #endif // V8_TARGET_ARCH_X64 | 3895 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |