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 3709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3720 static void GenerateRecordCallTargetNoArray(MacroAssembler* masm) { | 3720 static void GenerateRecordCallTargetNoArray(MacroAssembler* masm) { |
3721 // Cache the called function in a global property cell. Cache states | 3721 // Cache the called function in a global property cell. Cache states |
3722 // are uninitialized, monomorphic (indicated by a JSFunction), and | 3722 // are uninitialized, monomorphic (indicated by a JSFunction), and |
3723 // megamorphic. | 3723 // megamorphic. |
3724 // rbx : cache cell for call target | 3724 // rbx : cache cell for call target |
3725 // rdi : the function to call | 3725 // rdi : the function to call |
3726 Isolate* isolate = masm->isolate(); | 3726 Isolate* isolate = masm->isolate(); |
3727 Label initialize, done; | 3727 Label initialize, done; |
3728 | 3728 |
3729 // Load the cache state into rcx. | 3729 // Load the cache state into rcx. |
3730 __ movq(rcx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); | 3730 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); |
3731 | 3731 |
3732 // A monomorphic cache hit or an already megamorphic state: invoke the | 3732 // A monomorphic cache hit or an already megamorphic state: invoke the |
3733 // function without changing the state. | 3733 // function without changing the state. |
3734 __ cmpq(rcx, rdi); | 3734 __ cmpq(rcx, rdi); |
3735 __ j(equal, &done, Label::kNear); | 3735 __ j(equal, &done, Label::kNear); |
3736 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); | 3736 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); |
3737 __ j(equal, &done, Label::kNear); | 3737 __ j(equal, &done, Label::kNear); |
3738 | 3738 |
3739 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 3739 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
3740 // megamorphic. | 3740 // megamorphic. |
3741 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate)); | 3741 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate)); |
3742 __ j(equal, &initialize, Label::kNear); | 3742 __ j(equal, &initialize, Label::kNear); |
3743 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 3743 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
3744 // write-barrier is needed. | 3744 // write-barrier is needed. |
3745 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), | 3745 __ Move(FieldOperand(rbx, Cell::kValueOffset), |
3746 TypeFeedbackCells::MegamorphicSentinel(isolate)); | 3746 TypeFeedbackCells::MegamorphicSentinel(isolate)); |
3747 __ jmp(&done, Label::kNear); | 3747 __ jmp(&done, Label::kNear); |
3748 | 3748 |
3749 // An uninitialized cache is patched with the function. | 3749 // An uninitialized cache is patched with the function. |
3750 __ bind(&initialize); | 3750 __ bind(&initialize); |
3751 __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rdi); | 3751 __ movq(FieldOperand(rbx, Cell::kValueOffset), rdi); |
3752 // No need for a write barrier here - cells are rescanned. | 3752 // No need for a write barrier here - cells are rescanned. |
3753 | 3753 |
3754 __ bind(&done); | 3754 __ bind(&done); |
3755 } | 3755 } |
3756 | 3756 |
3757 | 3757 |
3758 static void GenerateRecordCallTarget(MacroAssembler* masm) { | 3758 static void GenerateRecordCallTarget(MacroAssembler* masm) { |
3759 // Cache the called function in a global property cell. Cache states | 3759 // Cache the called function in a global property cell. Cache states |
3760 // are uninitialized, monomorphic (indicated by a JSFunction), and | 3760 // are uninitialized, monomorphic (indicated by a JSFunction), and |
3761 // megamorphic. | 3761 // megamorphic. |
3762 // rbx : cache cell for call target | 3762 // rbx : cache cell for call target |
3763 // rdi : the function to call | 3763 // rdi : the function to call |
3764 ASSERT(FLAG_optimize_constructed_arrays); | 3764 ASSERT(FLAG_optimize_constructed_arrays); |
3765 Isolate* isolate = masm->isolate(); | 3765 Isolate* isolate = masm->isolate(); |
3766 Label initialize, done, miss, megamorphic, not_array_function; | 3766 Label initialize, done, miss, megamorphic, not_array_function; |
3767 | 3767 |
3768 // Load the cache state into rcx. | 3768 // Load the cache state into rcx. |
3769 __ movq(rcx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); | 3769 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); |
3770 | 3770 |
3771 // A monomorphic cache hit or an already megamorphic state: invoke the | 3771 // A monomorphic cache hit or an already megamorphic state: invoke the |
3772 // function without changing the state. | 3772 // function without changing the state. |
3773 __ cmpq(rcx, rdi); | 3773 __ cmpq(rcx, rdi); |
3774 __ j(equal, &done); | 3774 __ j(equal, &done); |
3775 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); | 3775 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); |
3776 __ j(equal, &done); | 3776 __ j(equal, &done); |
3777 | 3777 |
3778 // Special handling of the Array() function, which caches not only the | 3778 // Special handling of the Array() function, which caches not only the |
3779 // monomorphic Array function but the initial ElementsKind with special | 3779 // monomorphic Array function but the initial ElementsKind with special |
(...skipping 12 matching lines...) Expand all Loading... |
3792 | 3792 |
3793 __ bind(&miss); | 3793 __ bind(&miss); |
3794 | 3794 |
3795 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 3795 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
3796 // megamorphic. | 3796 // megamorphic. |
3797 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate)); | 3797 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate)); |
3798 __ j(equal, &initialize); | 3798 __ j(equal, &initialize); |
3799 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 3799 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
3800 // write-barrier is needed. | 3800 // write-barrier is needed. |
3801 __ bind(&megamorphic); | 3801 __ bind(&megamorphic); |
3802 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), | 3802 __ Move(FieldOperand(rbx, Cell::kValueOffset), |
3803 TypeFeedbackCells::MegamorphicSentinel(isolate)); | 3803 TypeFeedbackCells::MegamorphicSentinel(isolate)); |
3804 __ jmp(&done, Label::kNear); | 3804 __ jmp(&done, Label::kNear); |
3805 | 3805 |
3806 // An uninitialized cache is patched with the function or sentinel to | 3806 // An uninitialized cache is patched with the function or sentinel to |
3807 // indicate the ElementsKind if function is the Array constructor. | 3807 // indicate the ElementsKind if function is the Array constructor. |
3808 __ bind(&initialize); | 3808 __ bind(&initialize); |
3809 // Make sure the function is the Array() function | 3809 // Make sure the function is the Array() function |
3810 __ LoadArrayFunction(rcx); | 3810 __ LoadArrayFunction(rcx); |
3811 __ cmpq(rdi, rcx); | 3811 __ cmpq(rdi, rcx); |
3812 __ j(not_equal, ¬_array_function); | 3812 __ j(not_equal, ¬_array_function); |
3813 | 3813 |
3814 // The target function is the Array constructor, install a sentinel value in | 3814 // The target function is the Array constructor, install a sentinel value in |
3815 // the constructor's type info cell that will track the initial ElementsKind | 3815 // the constructor's type info cell that will track the initial ElementsKind |
3816 // that should be used for the array when its constructed. | 3816 // that should be used for the array when its constructed. |
3817 Handle<Object> initial_kind_sentinel = | 3817 Handle<Object> initial_kind_sentinel = |
3818 TypeFeedbackCells::MonomorphicArraySentinel(isolate, | 3818 TypeFeedbackCells::MonomorphicArraySentinel(isolate, |
3819 GetInitialFastElementsKind()); | 3819 GetInitialFastElementsKind()); |
3820 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), | 3820 __ Move(FieldOperand(rbx, Cell::kValueOffset), |
3821 initial_kind_sentinel); | 3821 initial_kind_sentinel); |
3822 __ jmp(&done); | 3822 __ jmp(&done); |
3823 | 3823 |
3824 __ bind(¬_array_function); | 3824 __ bind(¬_array_function); |
3825 __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rdi); | 3825 __ movq(FieldOperand(rbx, Cell::kValueOffset), rdi); |
3826 // No need for a write barrier here - cells are rescanned. | 3826 // No need for a write barrier here - cells are rescanned. |
3827 | 3827 |
3828 __ bind(&done); | 3828 __ bind(&done); |
3829 } | 3829 } |
3830 | 3830 |
3831 | 3831 |
3832 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3832 void CallFunctionStub::Generate(MacroAssembler* masm) { |
3833 // rbx : cache cell for call target | 3833 // rbx : cache cell for call target |
3834 // rdi : the function to call | 3834 // rdi : the function to call |
3835 Isolate* isolate = masm->isolate(); | 3835 Isolate* isolate = masm->isolate(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3886 JUMP_FUNCTION, | 3886 JUMP_FUNCTION, |
3887 NullCallWrapper(), | 3887 NullCallWrapper(), |
3888 CALL_AS_FUNCTION); | 3888 CALL_AS_FUNCTION); |
3889 | 3889 |
3890 // Slow-case: Non-function called. | 3890 // Slow-case: Non-function called. |
3891 __ bind(&slow); | 3891 __ bind(&slow); |
3892 if (RecordCallTarget()) { | 3892 if (RecordCallTarget()) { |
3893 // If there is a call target cache, mark it megamorphic in the | 3893 // If there is a call target cache, mark it megamorphic in the |
3894 // non-function case. MegamorphicSentinel is an immortal immovable | 3894 // non-function case. MegamorphicSentinel is an immortal immovable |
3895 // object (undefined) so no write barrier is needed. | 3895 // object (undefined) so no write barrier is needed. |
3896 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), | 3896 __ Move(FieldOperand(rbx, Cell::kValueOffset), |
3897 TypeFeedbackCells::MegamorphicSentinel(isolate)); | 3897 TypeFeedbackCells::MegamorphicSentinel(isolate)); |
3898 } | 3898 } |
3899 // Check for function proxy. | 3899 // Check for function proxy. |
3900 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); | 3900 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); |
3901 __ j(not_equal, &non_function); | 3901 __ j(not_equal, &non_function); |
3902 __ pop(rcx); | 3902 __ pop(rcx); |
3903 __ push(rdi); // put proxy as additional argument under return address | 3903 __ push(rdi); // put proxy as additional argument under return address |
3904 __ push(rcx); | 3904 __ push(rcx); |
3905 __ Set(rax, argc_ + 1); | 3905 __ Set(rax, argc_ + 1); |
3906 __ Set(rbx, 0); | 3906 __ Set(rbx, 0); |
(...skipping 3020 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6927 | 6927 |
6928 // Initial map for the builtin Array function should be a map. | 6928 // Initial map for the builtin Array function should be a map. |
6929 __ movq(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); | 6929 __ movq(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); |
6930 // Will both indicate a NULL and a Smi. | 6930 // Will both indicate a NULL and a Smi. |
6931 STATIC_ASSERT(kSmiTag == 0); | 6931 STATIC_ASSERT(kSmiTag == 0); |
6932 Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); | 6932 Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); |
6933 __ Check(not_smi, "Unexpected initial map for Array function"); | 6933 __ Check(not_smi, "Unexpected initial map for Array function"); |
6934 __ CmpObjectType(rcx, MAP_TYPE, rcx); | 6934 __ CmpObjectType(rcx, MAP_TYPE, rcx); |
6935 __ Check(equal, "Unexpected initial map for Array function"); | 6935 __ Check(equal, "Unexpected initial map for Array function"); |
6936 | 6936 |
6937 // We should either have undefined in ebx or a valid jsglobalpropertycell | 6937 // We should either have undefined in ebx or a valid cell |
6938 Label okay_here; | 6938 Label okay_here; |
6939 Handle<Map> global_property_cell_map( | 6939 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); |
6940 masm->isolate()->heap()->global_property_cell_map()); | |
6941 __ Cmp(rbx, undefined_sentinel); | 6940 __ Cmp(rbx, undefined_sentinel); |
6942 __ j(equal, &okay_here); | 6941 __ j(equal, &okay_here); |
6943 __ Cmp(FieldOperand(rbx, 0), global_property_cell_map); | 6942 __ Cmp(FieldOperand(rbx, 0), cell_map); |
6944 __ Assert(equal, "Expected property cell in register rbx"); | 6943 __ Assert(equal, "Expected property cell in register rbx"); |
6945 __ bind(&okay_here); | 6944 __ bind(&okay_here); |
6946 } | 6945 } |
6947 | 6946 |
6948 if (FLAG_optimize_constructed_arrays) { | 6947 if (FLAG_optimize_constructed_arrays) { |
6949 Label no_info, switch_ready; | 6948 Label no_info, switch_ready; |
6950 // Get the elements kind and case on that. | 6949 // Get the elements kind and case on that. |
6951 __ Cmp(rbx, undefined_sentinel); | 6950 __ Cmp(rbx, undefined_sentinel); |
6952 __ j(equal, &no_info); | 6951 __ j(equal, &no_info); |
6953 __ movq(rdx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); | 6952 __ movq(rdx, FieldOperand(rbx, Cell::kValueOffset)); |
6954 __ JumpIfNotSmi(rdx, &no_info); | 6953 __ JumpIfNotSmi(rdx, &no_info); |
6955 __ SmiToInteger32(rdx, rdx); | 6954 __ SmiToInteger32(rdx, rdx); |
6956 __ jmp(&switch_ready); | 6955 __ jmp(&switch_ready); |
6957 __ bind(&no_info); | 6956 __ bind(&no_info); |
6958 __ movq(rdx, Immediate(GetInitialFastElementsKind())); | 6957 __ movq(rdx, Immediate(GetInitialFastElementsKind())); |
6959 __ bind(&switch_ready); | 6958 __ bind(&switch_ready); |
6960 | 6959 |
6961 if (argument_count_ == ANY) { | 6960 if (argument_count_ == ANY) { |
6962 Label not_zero_case, not_one_case; | 6961 Label not_zero_case, not_one_case; |
6963 __ testq(rax, rax); | 6962 __ testq(rax, rax); |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7095 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 7094 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
7096 } | 7095 } |
7097 } | 7096 } |
7098 | 7097 |
7099 | 7098 |
7100 #undef __ | 7099 #undef __ |
7101 | 7100 |
7102 } } // namespace v8::internal | 7101 } } // namespace v8::internal |
7103 | 7102 |
7104 #endif // V8_TARGET_ARCH_X64 | 7103 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |