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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 Isolate* isolate, | 55 Isolate* isolate, |
56 CodeStubInterfaceDescriptor* descriptor) { | 56 CodeStubInterfaceDescriptor* descriptor) { |
57 static Register registers[] = { rax, rbx }; | 57 static Register registers[] = { rax, rbx }; |
58 descriptor->register_param_count_ = 2; | 58 descriptor->register_param_count_ = 2; |
59 descriptor->register_params_ = registers; | 59 descriptor->register_params_ = registers; |
60 descriptor->deoptimization_handler_ = | 60 descriptor->deoptimization_handler_ = |
61 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; | 61 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; |
62 } | 62 } |
63 | 63 |
64 | 64 |
| 65 static void InitializeArrayConstructorDescriptor(Isolate* isolate, |
| 66 CodeStubInterfaceDescriptor* descriptor) { |
| 67 static Register registers[] = { rdi, rbx }; |
| 68 descriptor->register_param_count_ = 2; |
| 69 // stack param count needs (constructor pointer, and single argument) |
| 70 descriptor->stack_parameter_count_ = &rax; |
| 71 descriptor->register_params_ = registers; |
| 72 descriptor->extra_expression_stack_count_ = 1; |
| 73 descriptor->deoptimization_handler_ = |
| 74 FUNCTION_ADDR(ArrayConstructor_StubFailure); |
| 75 } |
| 76 |
| 77 |
| 78 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
| 79 Isolate* isolate, |
| 80 CodeStubInterfaceDescriptor* descriptor) { |
| 81 InitializeArrayConstructorDescriptor(isolate, descriptor); |
| 82 } |
| 83 |
| 84 |
| 85 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( |
| 86 Isolate* isolate, |
| 87 CodeStubInterfaceDescriptor* descriptor) { |
| 88 InitializeArrayConstructorDescriptor(isolate, descriptor); |
| 89 } |
| 90 |
| 91 |
| 92 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
| 93 Isolate* isolate, |
| 94 CodeStubInterfaceDescriptor* descriptor) { |
| 95 InitializeArrayConstructorDescriptor(isolate, descriptor); |
| 96 } |
| 97 |
| 98 |
65 #define __ ACCESS_MASM(masm) | 99 #define __ ACCESS_MASM(masm) |
66 | 100 |
67 void ToNumberStub::Generate(MacroAssembler* masm) { | 101 void ToNumberStub::Generate(MacroAssembler* masm) { |
68 // The ToNumber stub takes one argument in eax. | 102 // The ToNumber stub takes one argument in eax. |
69 Label check_heap_number, call_builtin; | 103 Label check_heap_number, call_builtin; |
70 __ SmiTest(rax); | 104 __ SmiTest(rax); |
71 __ j(not_zero, &check_heap_number, Label::kNear); | 105 __ j(not_zero, &check_heap_number, Label::kNear); |
72 __ Ret(); | 106 __ Ret(); |
73 | 107 |
74 __ bind(&check_heap_number); | 108 __ bind(&check_heap_number); |
(...skipping 3794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3869 } | 3903 } |
3870 | 3904 |
3871 | 3905 |
3872 static void GenerateRecordCallTarget(MacroAssembler* masm) { | 3906 static void GenerateRecordCallTarget(MacroAssembler* masm) { |
3873 // Cache the called function in a global property cell. Cache states | 3907 // Cache the called function in a global property cell. Cache states |
3874 // are uninitialized, monomorphic (indicated by a JSFunction), and | 3908 // are uninitialized, monomorphic (indicated by a JSFunction), and |
3875 // megamorphic. | 3909 // megamorphic. |
3876 // rbx : cache cell for call target | 3910 // rbx : cache cell for call target |
3877 // rdi : the function to call | 3911 // rdi : the function to call |
3878 Isolate* isolate = masm->isolate(); | 3912 Isolate* isolate = masm->isolate(); |
3879 Label initialize, done; | 3913 Label initialize, done, miss, megamorphic, not_array_function; |
3880 | 3914 |
3881 // Load the cache state into rcx. | 3915 // Load the cache state into rcx. |
3882 __ movq(rcx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); | 3916 __ movq(rcx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); |
3883 | 3917 |
3884 // A monomorphic cache hit or an already megamorphic state: invoke the | 3918 // A monomorphic cache hit or an already megamorphic state: invoke the |
3885 // function without changing the state. | 3919 // function without changing the state. |
3886 __ cmpq(rcx, rdi); | 3920 __ cmpq(rcx, rdi); |
3887 __ j(equal, &done, Label::kNear); | 3921 __ j(equal, &done, Label::kFar); |
3888 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); | 3922 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); |
3889 __ j(equal, &done, Label::kNear); | 3923 __ j(equal, &done, Label::kFar); |
| 3924 |
| 3925 // Special handling of the Array() function, which caches not only the |
| 3926 // monomorphic Array function but the initial ElementsKind with special |
| 3927 // sentinels |
| 3928 Handle<Object> terminal_kind_sentinel = |
| 3929 TypeFeedbackCells::MonomorphicArraySentinel(LAST_FAST_ELEMENTS_KIND); |
| 3930 __ Cmp(rcx, terminal_kind_sentinel); |
| 3931 __ j(not_equal, &miss, Label::kFar); |
| 3932 // Load the global or builtins object from the current context |
| 3933 __ movq(rcx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 3934 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset)); |
| 3935 __ movq(rcx, |
| 3936 Operand(rcx, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
| 3937 // Make sure the function is the Array() function |
| 3938 __ cmpq(rdi, rcx); |
| 3939 Label megamorphic_pre; |
| 3940 __ j(not_equal, &megamorphic_pre, Label::kFar); |
| 3941 __ jmp(&done); |
| 3942 |
| 3943 __ bind(&megamorphic_pre); |
| 3944 __ jmp(&megamorphic, Label::kFar); |
| 3945 |
| 3946 __ bind(&miss); |
3890 | 3947 |
3891 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 3948 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
3892 // megamorphic. | 3949 // megamorphic. |
3893 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate)); | 3950 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate)); |
3894 __ j(equal, &initialize, Label::kNear); | 3951 __ j(equal, &initialize, Label::kFar); |
3895 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 3952 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
3896 // write-barrier is needed. | 3953 // write-barrier is needed. |
| 3954 __ bind(&megamorphic); |
3897 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), | 3955 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), |
3898 TypeFeedbackCells::MegamorphicSentinel(isolate)); | 3956 TypeFeedbackCells::MegamorphicSentinel(isolate)); |
3899 __ jmp(&done, Label::kNear); | 3957 __ jmp(&done, Label::kNear); |
3900 | 3958 |
3901 // An uninitialized cache is patched with the function. | 3959 // An uninitialized cache is patched with the function or sentinel to |
| 3960 // indicate the ElementsKind if function is the Array constructor. |
3902 __ bind(&initialize); | 3961 __ bind(&initialize); |
| 3962 __ movq(rcx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 3963 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset)); |
| 3964 __ movq(rcx, |
| 3965 Operand(rcx, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
| 3966 // Make sure the function is the Array() function |
| 3967 __ cmpq(rdi, rcx); |
| 3968 __ j(not_equal, ¬_array_function); |
| 3969 |
| 3970 // The target function is the Array constructor, install a sentinel value in |
| 3971 // the constructor's type info cell that will track the initial ElementsKind |
| 3972 // that should be used for the array when its constructed. |
| 3973 Handle<Object> initial_kind_sentinel = |
| 3974 TypeFeedbackCells::MonomorphicArraySentinel( |
| 3975 GetInitialFastElementsKind()); |
| 3976 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), |
| 3977 initial_kind_sentinel); |
| 3978 __ jmp(&done); |
| 3979 |
| 3980 __ bind(¬_array_function); |
3903 __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rdi); | 3981 __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rdi); |
3904 // No need for a write barrier here - cells are rescanned. | 3982 // No need for a write barrier here - cells are rescanned. |
3905 | 3983 |
3906 __ bind(&done); | 3984 __ bind(&done); |
3907 } | 3985 } |
3908 | 3986 |
3909 | 3987 |
3910 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3988 void CallFunctionStub::Generate(MacroAssembler* masm) { |
3911 // rbx : cache cell for call target | 3989 // rbx : cache cell for call target |
3912 // rdi : the function to call | 3990 // rdi : the function to call |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4010 __ JumpIfSmi(rdi, &non_function_call); | 4088 __ JumpIfSmi(rdi, &non_function_call); |
4011 // Check that function is a JSFunction. | 4089 // Check that function is a JSFunction. |
4012 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 4090 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
4013 __ j(not_equal, &slow); | 4091 __ j(not_equal, &slow); |
4014 | 4092 |
4015 if (RecordCallTarget()) { | 4093 if (RecordCallTarget()) { |
4016 GenerateRecordCallTarget(masm); | 4094 GenerateRecordCallTarget(masm); |
4017 } | 4095 } |
4018 | 4096 |
4019 // Jump to the function-specific construct stub. | 4097 // Jump to the function-specific construct stub. |
4020 __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | 4098 __ movq(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
4021 __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kConstructStubOffset)); | 4099 __ movq(rcx, FieldOperand(rcx, SharedFunctionInfo::kConstructStubOffset)); |
4022 __ lea(rbx, FieldOperand(rbx, Code::kHeaderSize)); | 4100 __ lea(rcx, FieldOperand(rcx, Code::kHeaderSize)); |
4023 __ jmp(rbx); | 4101 __ jmp(rcx); |
4024 | 4102 |
4025 // rdi: called object | 4103 // rdi: called object |
4026 // rax: number of arguments | 4104 // rax: number of arguments |
4027 // rcx: object map | 4105 // rcx: object map |
4028 Label do_call; | 4106 Label do_call; |
4029 __ bind(&slow); | 4107 __ bind(&slow); |
4030 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); | 4108 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); |
4031 __ j(not_equal, &non_function_call); | 4109 __ j(not_equal, &non_function_call); |
4032 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); | 4110 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); |
4033 __ jmp(&do_call); | 4111 __ jmp(&do_call); |
(...skipping 2678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6712 #endif | 6790 #endif |
6713 | 6791 |
6714 __ Ret(); | 6792 __ Ret(); |
6715 } | 6793 } |
6716 | 6794 |
6717 #undef __ | 6795 #undef __ |
6718 | 6796 |
6719 } } // namespace v8::internal | 6797 } } // namespace v8::internal |
6720 | 6798 |
6721 #endif // V8_TARGET_ARCH_X64 | 6799 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |