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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 descriptor->deoptimization_handler_ = | 53 descriptor->deoptimization_handler_ = |
54 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; | 54 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; |
55 } | 55 } |
56 | 56 |
57 | 57 |
58 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( | 58 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( |
59 Isolate* isolate, | 59 Isolate* isolate, |
60 CodeStubInterfaceDescriptor* descriptor) { | 60 CodeStubInterfaceDescriptor* descriptor) { |
61 static Register registers[] = { edx, ecx }; | 61 static Register registers[] = { edx, ecx }; |
62 descriptor->register_param_count_ = 2; | 62 descriptor->register_param_count_ = 2; |
| 63 descriptor->register_params_ = registers; |
63 descriptor->stack_parameter_count_ = NULL; | 64 descriptor->stack_parameter_count_ = NULL; |
64 descriptor->register_params_ = registers; | |
65 descriptor->deoptimization_handler_ = | 65 descriptor->deoptimization_handler_ = |
66 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); | 66 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); |
67 } | 67 } |
68 | 68 |
69 | 69 |
70 void TransitionElementsKindStub::InitializeInterfaceDescriptor( | 70 void TransitionElementsKindStub::InitializeInterfaceDescriptor( |
71 Isolate* isolate, | 71 Isolate* isolate, |
72 CodeStubInterfaceDescriptor* descriptor) { | 72 CodeStubInterfaceDescriptor* descriptor) { |
73 static Register registers[] = { eax, ebx }; | 73 static Register registers[] = { eax, ebx }; |
74 descriptor->register_param_count_ = 2; | 74 descriptor->register_param_count_ = 2; |
75 descriptor->register_params_ = registers; | 75 descriptor->register_params_ = registers; |
76 descriptor->deoptimization_handler_ = | 76 descriptor->deoptimization_handler_ = |
77 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; | 77 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; |
78 } | 78 } |
79 | 79 |
80 | 80 |
81 static void InitializeArrayConstructorDescriptor(Isolate* isolate, | 81 static void InitializeArrayConstructorDescriptor(Isolate* isolate, |
82 CodeStubInterfaceDescriptor* descriptor) { | 82 CodeStubInterfaceDescriptor* descriptor) { |
| 83 // register state |
| 84 // edi -- constructor function |
| 85 // ebx -- type info cell with elements kind |
| 86 // eax -- number of arguments to the constructor function |
83 static Register registers[] = { edi, ebx }; | 87 static Register registers[] = { edi, ebx }; |
84 descriptor->register_param_count_ = 2; | 88 descriptor->register_param_count_ = 2; |
85 // stack param count needs (constructor pointer, and single argument) | 89 // stack param count needs (constructor pointer, and single argument) |
86 descriptor->stack_parameter_count_ = &eax; | 90 descriptor->stack_parameter_count_ = &eax; |
87 descriptor->register_params_ = registers; | 91 descriptor->register_params_ = registers; |
88 descriptor->extra_expression_stack_count_ = 1; | 92 descriptor->extra_expression_stack_count_ = 1; |
89 descriptor->deoptimization_handler_ = | 93 descriptor->deoptimization_handler_ = |
90 FUNCTION_ADDR(ArrayConstructor_StubFailure); | 94 FUNCTION_ADDR(ArrayConstructor_StubFailure); |
91 } | 95 } |
92 | 96 |
(...skipping 4723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4816 void StackCheckStub::Generate(MacroAssembler* masm) { | 4820 void StackCheckStub::Generate(MacroAssembler* masm) { |
4817 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); | 4821 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); |
4818 } | 4822 } |
4819 | 4823 |
4820 | 4824 |
4821 void InterruptStub::Generate(MacroAssembler* masm) { | 4825 void InterruptStub::Generate(MacroAssembler* masm) { |
4822 __ TailCallRuntime(Runtime::kInterrupt, 0, 1); | 4826 __ TailCallRuntime(Runtime::kInterrupt, 0, 1); |
4823 } | 4827 } |
4824 | 4828 |
4825 | 4829 |
| 4830 static void GenerateRecordCallTargetNoArray(MacroAssembler* masm) { |
| 4831 // Cache the called function in a global property cell. Cache states |
| 4832 // are uninitialized, monomorphic (indicated by a JSFunction), and |
| 4833 // megamorphic. |
| 4834 // ebx : cache cell for call target |
| 4835 // edi : the function to call |
| 4836 ASSERT(!FLAG_optimize_constructed_arrays); |
| 4837 Isolate* isolate = masm->isolate(); |
| 4838 Label initialize, done; |
| 4839 |
| 4840 // Load the cache state into ecx. |
| 4841 __ mov(ecx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
| 4842 |
| 4843 // A monomorphic cache hit or an already megamorphic state: invoke the |
| 4844 // function without changing the state. |
| 4845 __ cmp(ecx, edi); |
| 4846 __ j(equal, &done, Label::kNear); |
| 4847 __ cmp(ecx, Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); |
| 4848 __ j(equal, &done, Label::kNear); |
| 4849 |
| 4850 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
| 4851 // megamorphic. |
| 4852 __ cmp(ecx, Immediate(TypeFeedbackCells::UninitializedSentinel(isolate))); |
| 4853 __ j(equal, &initialize, Label::kNear); |
| 4854 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
| 4855 // write-barrier is needed. |
| 4856 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), |
| 4857 Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); |
| 4858 __ jmp(&done, Label::kNear); |
| 4859 |
| 4860 // An uninitialized cache is patched with the function. |
| 4861 __ bind(&initialize); |
| 4862 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), edi); |
| 4863 // No need for a write barrier here - cells are rescanned. |
| 4864 |
| 4865 __ bind(&done); |
| 4866 } |
| 4867 |
| 4868 |
4826 static void GenerateRecordCallTarget(MacroAssembler* masm) { | 4869 static void GenerateRecordCallTarget(MacroAssembler* masm) { |
4827 // Cache the called function in a global property cell. Cache states | 4870 // Cache the called function in a global property cell. Cache states |
4828 // are uninitialized, monomorphic (indicated by a JSFunction), and | 4871 // are uninitialized, monomorphic (indicated by a JSFunction), and |
4829 // megamorphic. | 4872 // megamorphic. |
4830 // ebx : cache cell for call target | 4873 // ebx : cache cell for call target |
4831 // edi : the function to call | 4874 // edi : the function to call |
| 4875 ASSERT(FLAG_optimize_constructed_arrays); |
4832 Isolate* isolate = masm->isolate(); | 4876 Isolate* isolate = masm->isolate(); |
4833 Label initialize, done, miss, megamorphic, not_array_function; | 4877 Label initialize, done, miss, megamorphic, not_array_function; |
4834 | 4878 |
4835 // Load the cache state into ecx. | 4879 // Load the cache state into ecx. |
4836 __ mov(ecx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); | 4880 __ mov(ecx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
4837 | 4881 |
4838 // A monomorphic cache hit or an already megamorphic state: invoke the | 4882 // A monomorphic cache hit or an already megamorphic state: invoke the |
4839 // function without changing the state. | 4883 // function without changing the state. |
4840 __ cmp(ecx, edi); | 4884 __ cmp(ecx, edi); |
4841 __ j(equal, &done, Label::kFar); | 4885 __ j(equal, &done); |
4842 __ cmp(ecx, Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); | 4886 __ cmp(ecx, Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); |
4843 __ j(equal, &done, Label::kFar); | 4887 __ j(equal, &done); |
4844 | 4888 |
4845 // Special handling of the Array() function, which caches not only the | 4889 // Special handling of the Array() function, which caches not only the |
4846 // monomorphic Array function but the initial ElementsKind with special | 4890 // monomorphic Array function but the initial ElementsKind with special |
4847 // sentinels | 4891 // sentinels |
4848 Handle<Object> terminal_kind_sentinel = | 4892 Handle<Object> terminal_kind_sentinel = |
4849 TypeFeedbackCells::MonomorphicArraySentinel(LAST_FAST_ELEMENTS_KIND); | 4893 TypeFeedbackCells::MonomorphicArraySentinel(isolate, |
| 4894 LAST_FAST_ELEMENTS_KIND); |
4850 __ cmp(ecx, Immediate(terminal_kind_sentinel)); | 4895 __ cmp(ecx, Immediate(terminal_kind_sentinel)); |
4851 __ j(above, &miss, Label::kFar); | 4896 __ j(above, &miss); |
4852 // Load the global or builtins object from the current context | 4897 // Load the global or builtins object from the current context |
4853 __ mov(ecx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 4898 __ LoadGlobalContext(ecx); |
4854 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset)); | |
4855 // Make sure the function is the Array() function | 4899 // Make sure the function is the Array() function |
4856 __ cmp(edi, Operand(ecx, | 4900 __ cmp(edi, Operand(ecx, |
4857 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | 4901 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
4858 Label megamorphic_pre; | 4902 __ j(not_equal, &megamorphic); |
4859 __ j(not_equal, &megamorphic_pre, Label::kFar); | |
4860 __ jmp(&done); | 4903 __ jmp(&done); |
4861 | 4904 |
4862 __ bind(&megamorphic_pre); | |
4863 __ jmp(&megamorphic, Label::kFar); | |
4864 | |
4865 __ bind(&miss); | 4905 __ bind(&miss); |
4866 | 4906 |
4867 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 4907 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
4868 // megamorphic. | 4908 // megamorphic. |
4869 __ cmp(ecx, Immediate(TypeFeedbackCells::UninitializedSentinel(isolate))); | 4909 __ cmp(ecx, Immediate(TypeFeedbackCells::UninitializedSentinel(isolate))); |
4870 __ j(equal, &initialize, Label::kFar); | 4910 __ j(equal, &initialize); |
4871 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 4911 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
4872 // write-barrier is needed. | 4912 // write-barrier is needed. |
4873 __ bind(&megamorphic); | 4913 __ bind(&megamorphic); |
4874 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), | 4914 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), |
4875 Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); | 4915 Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); |
4876 __ jmp(&done, Label::kNear); | 4916 __ jmp(&done, Label::kNear); |
4877 | 4917 |
4878 // An uninitialized cache is patched with the function or sentinel to | 4918 // An uninitialized cache is patched with the function or sentinel to |
4879 // indicate the ElementsKind if function is the Array constructor. | 4919 // indicate the ElementsKind if function is the Array constructor. |
4880 __ bind(&initialize); | 4920 __ bind(&initialize); |
4881 __ mov(ecx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 4921 __ LoadGlobalContext(ecx); |
4882 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset)); | |
4883 // Make sure the function is the Array() function | 4922 // Make sure the function is the Array() function |
4884 __ cmp(edi, Operand(ecx, | 4923 __ cmp(edi, Operand(ecx, |
4885 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | 4924 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
4886 __ j(not_equal, ¬_array_function); | 4925 __ j(not_equal, ¬_array_function); |
4887 | 4926 |
4888 // The target function is the Array constructor, install a sentinel value in | 4927 // The target function is the Array constructor, install a sentinel value in |
4889 // the constructor's type info cell that will track the initial ElementsKind | 4928 // the constructor's type info cell that will track the initial ElementsKind |
4890 // that should be used for the array when its constructed. | 4929 // that should be used for the array when its constructed. |
4891 Handle<Object> initial_kind_sentinel = | 4930 Handle<Object> initial_kind_sentinel = |
4892 TypeFeedbackCells::MonomorphicArraySentinel( | 4931 TypeFeedbackCells::MonomorphicArraySentinel(isolate, |
4893 GetInitialFastElementsKind()); | 4932 GetInitialFastElementsKind()); |
4894 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), | 4933 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), |
4895 Immediate(initial_kind_sentinel)); | 4934 Immediate(initial_kind_sentinel)); |
4896 __ jmp(&done); | 4935 __ jmp(&done); |
4897 | 4936 |
4898 __ bind(¬_array_function); | 4937 __ bind(¬_array_function); |
4899 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), edi); | 4938 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), edi); |
4900 // No need for a write barrier here - cells are rescanned. | 4939 // No need for a write barrier here - cells are rescanned. |
4901 | 4940 |
4902 __ bind(&done); | 4941 __ bind(&done); |
(...skipping 24 matching lines...) Expand all Loading... |
4927 __ bind(&receiver_ok); | 4966 __ bind(&receiver_ok); |
4928 } | 4967 } |
4929 | 4968 |
4930 // Check that the function really is a JavaScript function. | 4969 // Check that the function really is a JavaScript function. |
4931 __ JumpIfSmi(edi, &non_function); | 4970 __ JumpIfSmi(edi, &non_function); |
4932 // Goto slow case if we do not have a function. | 4971 // Goto slow case if we do not have a function. |
4933 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 4972 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
4934 __ j(not_equal, &slow); | 4973 __ j(not_equal, &slow); |
4935 | 4974 |
4936 if (RecordCallTarget()) { | 4975 if (RecordCallTarget()) { |
4937 GenerateRecordCallTarget(masm); | 4976 if (FLAG_optimize_constructed_arrays) { |
| 4977 GenerateRecordCallTarget(masm); |
| 4978 } else { |
| 4979 GenerateRecordCallTargetNoArray(masm); |
| 4980 } |
4938 } | 4981 } |
4939 | 4982 |
4940 // Fast-case: Just invoke the function. | 4983 // Fast-case: Just invoke the function. |
4941 ParameterCount actual(argc_); | 4984 ParameterCount actual(argc_); |
4942 | 4985 |
4943 if (ReceiverMightBeImplicit()) { | 4986 if (ReceiverMightBeImplicit()) { |
4944 Label call_as_function; | 4987 Label call_as_function; |
4945 __ cmp(eax, isolate->factory()->the_hole_value()); | 4988 __ cmp(eax, isolate->factory()->the_hole_value()); |
4946 __ j(equal, &call_as_function); | 4989 __ j(equal, &call_as_function); |
4947 __ InvokeFunction(edi, | 4990 __ InvokeFunction(edi, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5000 // edi : constructor function | 5043 // edi : constructor function |
5001 Label slow, non_function_call; | 5044 Label slow, non_function_call; |
5002 | 5045 |
5003 // Check that function is not a smi. | 5046 // Check that function is not a smi. |
5004 __ JumpIfSmi(edi, &non_function_call); | 5047 __ JumpIfSmi(edi, &non_function_call); |
5005 // Check that function is a JSFunction. | 5048 // Check that function is a JSFunction. |
5006 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 5049 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
5007 __ j(not_equal, &slow); | 5050 __ j(not_equal, &slow); |
5008 | 5051 |
5009 if (RecordCallTarget()) { | 5052 if (RecordCallTarget()) { |
5010 GenerateRecordCallTarget(masm); | 5053 if (FLAG_optimize_constructed_arrays) { |
| 5054 GenerateRecordCallTarget(masm); |
| 5055 } else { |
| 5056 GenerateRecordCallTargetNoArray(masm); |
| 5057 } |
5011 } | 5058 } |
5012 | 5059 |
5013 // Jump to the function-specific construct stub. | 5060 // Jump to the function-specific construct stub. |
5014 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 5061 Register jmp_reg = FLAG_optimize_constructed_arrays ? ecx : ebx; |
5015 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); | 5062 __ mov(jmp_reg, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
5016 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | 5063 __ mov(jmp_reg, FieldOperand(jmp_reg, |
5017 __ jmp(ecx); | 5064 SharedFunctionInfo::kConstructStubOffset)); |
| 5065 __ lea(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize)); |
| 5066 __ jmp(jmp_reg); |
5018 | 5067 |
5019 // edi: called object | 5068 // edi: called object |
5020 // eax: number of arguments | 5069 // eax: number of arguments |
5021 // ecx: object map | 5070 // ecx: object map |
5022 Label do_call; | 5071 Label do_call; |
5023 __ bind(&slow); | 5072 __ bind(&slow); |
5024 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); | 5073 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); |
5025 __ j(not_equal, &non_function_call); | 5074 __ j(not_equal, &non_function_call); |
5026 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); | 5075 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); |
5027 __ jmp(&do_call); | 5076 __ jmp(&do_call); |
(...skipping 2731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7759 // Restore ecx. | 7808 // Restore ecx. |
7760 __ pop(ecx); | 7809 __ pop(ecx); |
7761 __ ret(0); | 7810 __ ret(0); |
7762 } | 7811 } |
7763 | 7812 |
7764 #undef __ | 7813 #undef __ |
7765 | 7814 |
7766 } } // namespace v8::internal | 7815 } } // namespace v8::internal |
7767 | 7816 |
7768 #endif // V8_TARGET_ARCH_IA32 | 7817 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |