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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 static Register registers[] = { rax, rbx }; | 68 static Register registers[] = { rax, rbx }; |
69 descriptor->register_param_count_ = 2; | 69 descriptor->register_param_count_ = 2; |
70 descriptor->register_params_ = registers; | 70 descriptor->register_params_ = registers; |
71 descriptor->deoptimization_handler_ = | 71 descriptor->deoptimization_handler_ = |
72 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; | 72 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; |
73 } | 73 } |
74 | 74 |
75 | 75 |
76 static void InitializeArrayConstructorDescriptor(Isolate* isolate, | 76 static void InitializeArrayConstructorDescriptor(Isolate* isolate, |
77 CodeStubInterfaceDescriptor* descriptor) { | 77 CodeStubInterfaceDescriptor* descriptor) { |
| 78 // register state |
| 79 // rdi -- constructor function |
| 80 // rbx -- type info cell with elements kind |
| 81 // rax -- number of arguments to the constructor function |
78 static Register registers[] = { rdi, rbx }; | 82 static Register registers[] = { rdi, rbx }; |
79 descriptor->register_param_count_ = 2; | 83 descriptor->register_param_count_ = 2; |
80 // stack param count needs (constructor pointer, and single argument) | 84 // stack param count needs (constructor pointer, and single argument) |
81 descriptor->stack_parameter_count_ = &rax; | 85 descriptor->stack_parameter_count_ = &rax; |
82 descriptor->register_params_ = registers; | 86 descriptor->register_params_ = registers; |
83 descriptor->extra_expression_stack_count_ = 1; | 87 descriptor->extra_expression_stack_count_ = 1; |
84 descriptor->deoptimization_handler_ = | 88 descriptor->deoptimization_handler_ = |
85 FUNCTION_ADDR(ArrayConstructor_StubFailure); | 89 FUNCTION_ADDR(ArrayConstructor_StubFailure); |
86 } | 90 } |
87 | 91 |
(...skipping 3789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3877 void StackCheckStub::Generate(MacroAssembler* masm) { | 3881 void StackCheckStub::Generate(MacroAssembler* masm) { |
3878 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); | 3882 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); |
3879 } | 3883 } |
3880 | 3884 |
3881 | 3885 |
3882 void InterruptStub::Generate(MacroAssembler* masm) { | 3886 void InterruptStub::Generate(MacroAssembler* masm) { |
3883 __ TailCallRuntime(Runtime::kInterrupt, 0, 1); | 3887 __ TailCallRuntime(Runtime::kInterrupt, 0, 1); |
3884 } | 3888 } |
3885 | 3889 |
3886 | 3890 |
| 3891 static void GenerateRecordCallTargetNoArray(MacroAssembler* masm) { |
| 3892 // Cache the called function in a global property cell. Cache states |
| 3893 // are uninitialized, monomorphic (indicated by a JSFunction), and |
| 3894 // megamorphic. |
| 3895 // rbx : cache cell for call target |
| 3896 // rdi : the function to call |
| 3897 ASSERT(!FLAG_optimize_constructed_arrays); |
| 3898 Isolate* isolate = masm->isolate(); |
| 3899 Label initialize, done; |
| 3900 |
| 3901 // Load the cache state into rcx. |
| 3902 __ movq(rcx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); |
| 3903 |
| 3904 // A monomorphic cache hit or an already megamorphic state: invoke the |
| 3905 // function without changing the state. |
| 3906 __ cmpq(rcx, rdi); |
| 3907 __ j(equal, &done, Label::kNear); |
| 3908 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); |
| 3909 __ j(equal, &done, Label::kNear); |
| 3910 |
| 3911 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
| 3912 // megamorphic. |
| 3913 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate)); |
| 3914 __ j(equal, &initialize, Label::kNear); |
| 3915 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
| 3916 // write-barrier is needed. |
| 3917 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), |
| 3918 TypeFeedbackCells::MegamorphicSentinel(isolate)); |
| 3919 __ jmp(&done, Label::kNear); |
| 3920 |
| 3921 // An uninitialized cache is patched with the function. |
| 3922 __ bind(&initialize); |
| 3923 __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rdi); |
| 3924 // No need for a write barrier here - cells are rescanned. |
| 3925 |
| 3926 __ bind(&done); |
| 3927 } |
| 3928 |
| 3929 |
3887 static void GenerateRecordCallTarget(MacroAssembler* masm) { | 3930 static void GenerateRecordCallTarget(MacroAssembler* masm) { |
3888 // Cache the called function in a global property cell. Cache states | 3931 // Cache the called function in a global property cell. Cache states |
3889 // are uninitialized, monomorphic (indicated by a JSFunction), and | 3932 // are uninitialized, monomorphic (indicated by a JSFunction), and |
3890 // megamorphic. | 3933 // megamorphic. |
3891 // rbx : cache cell for call target | 3934 // rbx : cache cell for call target |
3892 // rdi : the function to call | 3935 // rdi : the function to call |
| 3936 ASSERT(FLAG_optimize_constructed_arrays); |
3893 Isolate* isolate = masm->isolate(); | 3937 Isolate* isolate = masm->isolate(); |
3894 Label initialize, done, miss, megamorphic, not_array_function; | 3938 Label initialize, done, miss, megamorphic, not_array_function; |
3895 | 3939 |
3896 // Load the cache state into rcx. | 3940 // Load the cache state into rcx. |
3897 __ movq(rcx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); | 3941 __ movq(rcx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); |
3898 | 3942 |
3899 // A monomorphic cache hit or an already megamorphic state: invoke the | 3943 // A monomorphic cache hit or an already megamorphic state: invoke the |
3900 // function without changing the state. | 3944 // function without changing the state. |
3901 __ cmpq(rcx, rdi); | 3945 __ cmpq(rcx, rdi); |
3902 __ j(equal, &done, Label::kFar); | 3946 __ j(equal, &done); |
3903 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); | 3947 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); |
3904 __ j(equal, &done, Label::kFar); | 3948 __ j(equal, &done); |
3905 | 3949 |
3906 // Special handling of the Array() function, which caches not only the | 3950 // Special handling of the Array() function, which caches not only the |
3907 // monomorphic Array function but the initial ElementsKind with special | 3951 // monomorphic Array function but the initial ElementsKind with special |
3908 // sentinels | 3952 // sentinels |
3909 Handle<Object> terminal_kind_sentinel = | 3953 Handle<Object> terminal_kind_sentinel = |
3910 TypeFeedbackCells::MonomorphicArraySentinel(LAST_FAST_ELEMENTS_KIND); | 3954 TypeFeedbackCells::MonomorphicArraySentinel(isolate, |
| 3955 LAST_FAST_ELEMENTS_KIND); |
3911 __ Cmp(rcx, terminal_kind_sentinel); | 3956 __ Cmp(rcx, terminal_kind_sentinel); |
3912 __ j(not_equal, &miss, Label::kFar); | 3957 __ j(not_equal, &miss); |
3913 // Load the global or builtins object from the current context | |
3914 __ movq(rcx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | |
3915 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset)); | |
3916 __ movq(rcx, | |
3917 Operand(rcx, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | |
3918 // Make sure the function is the Array() function | 3958 // Make sure the function is the Array() function |
| 3959 __ LoadArrayFunction(rcx); |
3919 __ cmpq(rdi, rcx); | 3960 __ cmpq(rdi, rcx); |
3920 Label megamorphic_pre; | 3961 __ j(not_equal, &megamorphic); |
3921 __ j(not_equal, &megamorphic_pre, Label::kFar); | |
3922 __ jmp(&done); | 3962 __ jmp(&done); |
3923 | 3963 |
3924 __ bind(&megamorphic_pre); | |
3925 __ jmp(&megamorphic, Label::kFar); | |
3926 | |
3927 __ bind(&miss); | 3964 __ bind(&miss); |
3928 | 3965 |
3929 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 3966 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
3930 // megamorphic. | 3967 // megamorphic. |
3931 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate)); | 3968 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate)); |
3932 __ j(equal, &initialize, Label::kFar); | 3969 __ j(equal, &initialize); |
3933 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 3970 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
3934 // write-barrier is needed. | 3971 // write-barrier is needed. |
3935 __ bind(&megamorphic); | 3972 __ bind(&megamorphic); |
3936 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), | 3973 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), |
3937 TypeFeedbackCells::MegamorphicSentinel(isolate)); | 3974 TypeFeedbackCells::MegamorphicSentinel(isolate)); |
3938 __ jmp(&done, Label::kNear); | 3975 __ jmp(&done, Label::kNear); |
3939 | 3976 |
3940 // An uninitialized cache is patched with the function or sentinel to | 3977 // An uninitialized cache is patched with the function or sentinel to |
3941 // indicate the ElementsKind if function is the Array constructor. | 3978 // indicate the ElementsKind if function is the Array constructor. |
3942 __ bind(&initialize); | 3979 __ bind(&initialize); |
3943 __ movq(rcx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | |
3944 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset)); | |
3945 __ movq(rcx, | |
3946 Operand(rcx, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | |
3947 // Make sure the function is the Array() function | 3980 // Make sure the function is the Array() function |
| 3981 __ LoadArrayFunction(rcx); |
3948 __ cmpq(rdi, rcx); | 3982 __ cmpq(rdi, rcx); |
3949 __ j(not_equal, ¬_array_function); | 3983 __ j(not_equal, ¬_array_function); |
3950 | 3984 |
3951 // The target function is the Array constructor, install a sentinel value in | 3985 // The target function is the Array constructor, install a sentinel value in |
3952 // the constructor's type info cell that will track the initial ElementsKind | 3986 // the constructor's type info cell that will track the initial ElementsKind |
3953 // that should be used for the array when its constructed. | 3987 // that should be used for the array when its constructed. |
3954 Handle<Object> initial_kind_sentinel = | 3988 Handle<Object> initial_kind_sentinel = |
3955 TypeFeedbackCells::MonomorphicArraySentinel( | 3989 TypeFeedbackCells::MonomorphicArraySentinel(isolate, |
3956 GetInitialFastElementsKind()); | 3990 GetInitialFastElementsKind()); |
3957 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), | 3991 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), |
3958 initial_kind_sentinel); | 3992 initial_kind_sentinel); |
3959 __ jmp(&done); | 3993 __ jmp(&done); |
3960 | 3994 |
3961 __ bind(¬_array_function); | 3995 __ bind(¬_array_function); |
3962 __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rdi); | 3996 __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rdi); |
3963 // No need for a write barrier here - cells are rescanned. | 3997 // No need for a write barrier here - cells are rescanned. |
3964 | 3998 |
3965 __ bind(&done); | 3999 __ bind(&done); |
(...skipping 24 matching lines...) Expand all Loading... |
3990 __ bind(&call); | 4024 __ bind(&call); |
3991 } | 4025 } |
3992 | 4026 |
3993 // Check that the function really is a JavaScript function. | 4027 // Check that the function really is a JavaScript function. |
3994 __ JumpIfSmi(rdi, &non_function); | 4028 __ JumpIfSmi(rdi, &non_function); |
3995 // Goto slow case if we do not have a function. | 4029 // Goto slow case if we do not have a function. |
3996 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 4030 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
3997 __ j(not_equal, &slow); | 4031 __ j(not_equal, &slow); |
3998 | 4032 |
3999 if (RecordCallTarget()) { | 4033 if (RecordCallTarget()) { |
4000 GenerateRecordCallTarget(masm); | 4034 if (FLAG_optimize_constructed_arrays) { |
| 4035 GenerateRecordCallTarget(masm); |
| 4036 } else { |
| 4037 GenerateRecordCallTargetNoArray(masm); |
| 4038 } |
4001 } | 4039 } |
4002 | 4040 |
4003 // Fast-case: Just invoke the function. | 4041 // Fast-case: Just invoke the function. |
4004 ParameterCount actual(argc_); | 4042 ParameterCount actual(argc_); |
4005 | 4043 |
4006 if (ReceiverMightBeImplicit()) { | 4044 if (ReceiverMightBeImplicit()) { |
4007 Label call_as_function; | 4045 Label call_as_function; |
4008 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | 4046 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); |
4009 __ j(equal, &call_as_function); | 4047 __ j(equal, &call_as_function); |
4010 __ InvokeFunction(rdi, | 4048 __ InvokeFunction(rdi, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4065 // rdi : constructor function | 4103 // rdi : constructor function |
4066 Label slow, non_function_call; | 4104 Label slow, non_function_call; |
4067 | 4105 |
4068 // Check that function is not a smi. | 4106 // Check that function is not a smi. |
4069 __ JumpIfSmi(rdi, &non_function_call); | 4107 __ JumpIfSmi(rdi, &non_function_call); |
4070 // Check that function is a JSFunction. | 4108 // Check that function is a JSFunction. |
4071 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 4109 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
4072 __ j(not_equal, &slow); | 4110 __ j(not_equal, &slow); |
4073 | 4111 |
4074 if (RecordCallTarget()) { | 4112 if (RecordCallTarget()) { |
4075 GenerateRecordCallTarget(masm); | 4113 if (FLAG_optimize_constructed_arrays) { |
| 4114 GenerateRecordCallTarget(masm); |
| 4115 } else { |
| 4116 GenerateRecordCallTargetNoArray(masm); |
| 4117 } |
4076 } | 4118 } |
4077 | 4119 |
4078 // Jump to the function-specific construct stub. | 4120 // Jump to the function-specific construct stub. |
4079 __ movq(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | 4121 Register jmp_reg = FLAG_optimize_constructed_arrays ? rcx : rbx; |
4080 __ movq(rcx, FieldOperand(rcx, SharedFunctionInfo::kConstructStubOffset)); | 4122 __ movq(jmp_reg, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
4081 __ lea(rcx, FieldOperand(rcx, Code::kHeaderSize)); | 4123 __ movq(jmp_reg, FieldOperand(jmp_reg, |
4082 __ jmp(rcx); | 4124 SharedFunctionInfo::kConstructStubOffset)); |
| 4125 __ lea(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize)); |
| 4126 __ jmp(jmp_reg); |
4083 | 4127 |
4084 // rdi: called object | 4128 // rdi: called object |
4085 // rax: number of arguments | 4129 // rax: number of arguments |
4086 // rcx: object map | 4130 // rcx: object map |
4087 Label do_call; | 4131 Label do_call; |
4088 __ bind(&slow); | 4132 __ bind(&slow); |
4089 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); | 4133 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); |
4090 __ j(not_equal, &non_function_call); | 4134 __ j(not_equal, &non_function_call); |
4091 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); | 4135 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); |
4092 __ jmp(&do_call); | 4136 __ jmp(&do_call); |
(...skipping 2678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6771 #endif | 6815 #endif |
6772 | 6816 |
6773 __ Ret(); | 6817 __ Ret(); |
6774 } | 6818 } |
6775 | 6819 |
6776 #undef __ | 6820 #undef __ |
6777 | 6821 |
6778 } } // namespace v8::internal | 6822 } } // namespace v8::internal |
6779 | 6823 |
6780 #endif // V8_TARGET_ARCH_X64 | 6824 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |