OLD | NEW |
---|---|
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_SRC_IC_ACCESSOR_ASSEMBLER_H_ | 5 #ifndef V8_SRC_IC_ACCESSOR_ASSEMBLER_H_ |
6 #define V8_SRC_IC_ACCESSOR_ASSEMBLER_H_ | 6 #define V8_SRC_IC_ACCESSOR_ASSEMBLER_H_ |
7 | 7 |
8 #include "src/code-stub-assembler.h" | 8 #include "src/code-stub-assembler.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 | 12 |
13 namespace compiler { | 13 namespace compiler { |
14 class CodeAssemblerState; | 14 class CodeAssemblerState; |
15 } | 15 } |
16 | 16 |
17 class ExitPoint; | |
18 | |
17 class AccessorAssembler : public CodeStubAssembler { | 19 class AccessorAssembler : public CodeStubAssembler { |
18 public: | 20 public: |
19 typedef compiler::Node Node; | 21 typedef compiler::Node Node; |
20 | 22 |
21 explicit AccessorAssembler(compiler::CodeAssemblerState* state) | 23 explicit AccessorAssembler(compiler::CodeAssemblerState* state) |
22 : CodeStubAssembler(state) {} | 24 : CodeStubAssembler(state) {} |
23 | 25 |
24 void GenerateLoadIC(); | 26 void GenerateLoadIC(); |
25 void GenerateLoadField(); | 27 void GenerateLoadField(); |
26 void GenerateLoadICTrampoline(); | 28 void GenerateLoadICTrampoline(); |
(...skipping 15 matching lines...) Expand all Loading... | |
42 Label* if_handler, Variable* var_handler, | 44 Label* if_handler, Variable* var_handler, |
43 Label* if_miss); | 45 Label* if_miss); |
44 | 46 |
45 Node* StubCachePrimaryOffsetForTesting(Node* name, Node* map) { | 47 Node* StubCachePrimaryOffsetForTesting(Node* name, Node* map) { |
46 return StubCachePrimaryOffset(name, map); | 48 return StubCachePrimaryOffset(name, map); |
47 } | 49 } |
48 Node* StubCacheSecondaryOffsetForTesting(Node* name, Node* map) { | 50 Node* StubCacheSecondaryOffsetForTesting(Node* name, Node* map) { |
49 return StubCacheSecondaryOffset(name, map); | 51 return StubCacheSecondaryOffset(name, map); |
50 } | 52 } |
51 | 53 |
52 protected: | |
53 struct LoadICParameters { | 54 struct LoadICParameters { |
54 LoadICParameters(Node* context, Node* receiver, Node* name, Node* slot, | 55 LoadICParameters(Node* context, Node* receiver, Node* name, Node* slot, |
55 Node* vector) | 56 Node* vector) |
56 : context(context), | 57 : context(context), |
57 receiver(receiver), | 58 receiver(receiver), |
58 name(name), | 59 name(name), |
59 slot(slot), | 60 slot(slot), |
60 vector(vector) {} | 61 vector(vector) {} |
61 | 62 |
62 Node* context; | 63 Node* context; |
63 Node* receiver; | 64 Node* receiver; |
64 Node* name; | 65 Node* name; |
65 Node* slot; | 66 Node* slot; |
66 Node* vector; | 67 Node* vector; |
67 }; | 68 }; |
68 | 69 |
70 void LoadGlobalICData(const LoadICParameters* p, ExitPoint* exit_point, | |
71 Label* try_handler, Label* miss); | |
72 void LoadGlobalICHandler(const LoadICParameters* p, TypeofMode typeof_mode, | |
73 ExitPoint* exit_point, Label* miss); | |
74 void LoadGlobalICMiss(const LoadICParameters* p, ExitPoint* exit_point); | |
75 | |
76 protected: | |
69 struct StoreICParameters : public LoadICParameters { | 77 struct StoreICParameters : public LoadICParameters { |
70 StoreICParameters(Node* context, Node* receiver, Node* name, Node* value, | 78 StoreICParameters(Node* context, Node* receiver, Node* name, Node* value, |
71 Node* slot, Node* vector) | 79 Node* slot, Node* vector) |
72 : LoadICParameters(context, receiver, name, slot, vector), | 80 : LoadICParameters(context, receiver, name, slot, vector), |
73 value(value) {} | 81 value(value) {} |
74 Node* value; | 82 Node* value; |
75 }; | 83 }; |
76 | 84 |
77 enum ElementSupport { kOnlyProperties, kSupportElements }; | 85 enum ElementSupport { kOnlyProperties, kSupportElements }; |
78 void HandleStoreICHandlerCase( | 86 void HandleStoreICHandlerCase( |
(...skipping 28 matching lines...) Expand all Loading... | |
107 Label* if_miss); | 115 Label* if_miss); |
108 | 116 |
109 // LoadIC implementation. | 117 // LoadIC implementation. |
110 | 118 |
111 void HandleLoadICHandlerCase( | 119 void HandleLoadICHandlerCase( |
112 const LoadICParameters* p, Node* handler, Label* miss, | 120 const LoadICParameters* p, Node* handler, Label* miss, |
113 ElementSupport support_elements = kOnlyProperties); | 121 ElementSupport support_elements = kOnlyProperties); |
114 | 122 |
115 void HandleLoadICSmiHandlerCase(const LoadICParameters* p, Node* holder, | 123 void HandleLoadICSmiHandlerCase(const LoadICParameters* p, Node* holder, |
116 Node* smi_handler, Label* miss, | 124 Node* smi_handler, Label* miss, |
125 ExitPoint* exit_point, | |
117 ElementSupport support_elements); | 126 ElementSupport support_elements); |
118 | 127 |
119 void HandleLoadICProtoHandlerCase(const LoadICParameters* p, Node* handler, | 128 void HandleLoadICProtoHandlerCase(const LoadICParameters* p, Node* handler, |
120 Variable* var_holder, | 129 Variable* var_holder, |
121 Variable* var_smi_handler, | 130 Variable* var_smi_handler, |
122 Label* if_smi_handler, Label* miss, | 131 Label* if_smi_handler, Label* miss, |
132 ExitPoint* exit_point, | |
123 bool throw_reference_error_if_nonexistent); | 133 bool throw_reference_error_if_nonexistent); |
124 | 134 |
125 Node* EmitLoadICProtoArrayCheck(const LoadICParameters* p, Node* handler, | 135 Node* EmitLoadICProtoArrayCheck(const LoadICParameters* p, Node* handler, |
126 Node* handler_length, Node* handler_flags, | 136 Node* handler_length, Node* handler_flags, |
127 Label* miss, | 137 Label* miss, |
128 bool throw_reference_error_if_nonexistent); | 138 bool throw_reference_error_if_nonexistent); |
129 | 139 |
130 // LoadGlobalIC implementation. | 140 // LoadGlobalIC implementation. |
131 | 141 |
132 void HandleLoadGlobalICHandlerCase(const LoadICParameters* p, Node* handler, | 142 void HandleLoadGlobalICHandlerCase(const LoadICParameters* p, Node* handler, |
133 Label* miss, | 143 Label* miss, ExitPoint* exit_point, |
134 bool throw_reference_error_if_nonexistent); | 144 bool throw_reference_error_if_nonexistent); |
135 | 145 |
136 // StoreIC implementation. | 146 // StoreIC implementation. |
137 | 147 |
138 void HandleStoreICElementHandlerCase(const StoreICParameters* p, | 148 void HandleStoreICElementHandlerCase(const StoreICParameters* p, |
139 Node* handler, Label* miss); | 149 Node* handler, Label* miss); |
140 | 150 |
141 void HandleStoreICProtoHandler(const StoreICParameters* p, Node* handler, | 151 void HandleStoreICProtoHandler(const StoreICParameters* p, Node* handler, |
142 Label* miss); | 152 Label* miss); |
143 // If |transition| is nullptr then the normal field store is generated or | 153 // If |transition| is nullptr then the normal field store is generated or |
(...skipping 28 matching lines...) Expand all Loading... | |
172 Representation representation, Node* value, | 182 Representation representation, Node* value, |
173 bool transition_to_field); | 183 bool transition_to_field); |
174 | 184 |
175 void EmitFastElementsBoundsCheck(Node* object, Node* elements, | 185 void EmitFastElementsBoundsCheck(Node* object, Node* elements, |
176 Node* intptr_index, | 186 Node* intptr_index, |
177 Node* is_jsarray_condition, Label* miss); | 187 Node* is_jsarray_condition, Label* miss); |
178 void EmitElementLoad(Node* object, Node* elements, Node* elements_kind, | 188 void EmitElementLoad(Node* object, Node* elements, Node* elements_kind, |
179 Node* key, Node* is_jsarray_condition, Label* if_hole, | 189 Node* key, Node* is_jsarray_condition, Label* if_hole, |
180 Label* rebox_double, Variable* var_double_value, | 190 Label* rebox_double, Variable* var_double_value, |
181 Label* unimplemented_elements_kind, Label* out_of_bounds, | 191 Label* unimplemented_elements_kind, Label* out_of_bounds, |
182 Label* miss); | 192 Label* miss, ExitPoint* exit_point); |
183 void CheckPrototype(Node* prototype_cell, Node* name, Label* miss); | 193 void CheckPrototype(Node* prototype_cell, Node* name, Label* miss); |
184 void NameDictionaryNegativeLookup(Node* object, Node* name, Label* miss); | 194 void NameDictionaryNegativeLookup(Node* object, Node* name, Label* miss); |
185 | 195 |
186 // Stub cache access helpers. | 196 // Stub cache access helpers. |
187 | 197 |
188 // This enum is used here as a replacement for StubCache::Table to avoid | 198 // This enum is used here as a replacement for StubCache::Table to avoid |
189 // including stub cache header. | 199 // including stub cache header. |
190 enum StubCacheTable : int; | 200 enum StubCacheTable : int; |
191 | 201 |
192 Node* StubCachePrimaryOffset(Node* name, Node* map); | 202 Node* StubCachePrimaryOffset(Node* name, Node* map); |
193 Node* StubCacheSecondaryOffset(Node* name, Node* seed); | 203 Node* StubCacheSecondaryOffset(Node* name, Node* seed); |
194 | 204 |
195 void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id, | 205 void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id, |
196 Node* entry_offset, Node* name, Node* map, | 206 Node* entry_offset, Node* name, Node* map, |
197 Label* if_handler, Variable* var_handler, | 207 Label* if_handler, Variable* var_handler, |
198 Label* if_miss); | 208 Label* if_miss); |
199 }; | 209 }; |
200 | 210 |
211 // Abstraction over direct and indirect exit points. Direct exits correspond to | |
212 // tailcalls and Return, while indirect exits store the result in a variable | |
213 // and then jump to an exit label. | |
214 class ExitPoint { | |
215 private: | |
216 typedef compiler::Node Node; | |
217 typedef compiler::CodeAssemblerLabel CodeAssemblerLabel; | |
218 typedef compiler::CodeAssemblerVariable CodeAssemblerVariable; | |
219 | |
220 public: | |
221 explicit ExitPoint(CodeStubAssembler* assembler) | |
222 : ExitPoint(assembler, nullptr, nullptr) {} | |
223 ExitPoint(CodeStubAssembler* assembler, CodeAssemblerLabel* out, | |
224 CodeAssemblerVariable* var_result) | |
225 : out_(out), var_result_(var_result), asm_(assembler) { | |
226 DCHECK(out_ != nullptr || var_result_ == nullptr); | |
Igor Sheludko
2017/02/08 15:26:32
DCHECK_EQ(out != nullptr, var_result != nullptr);
jgruber
2017/02/09 09:23:42
Done.
| |
227 } | |
228 | |
229 template <class... TArgs> | |
230 void ReturnRuntime(Runtime::FunctionId function, Node* context, | |
Igor Sheludko
2017/02/08 15:26:32
ReturnCallRuntime
jgruber
2017/02/09 09:23:42
Done.
| |
231 TArgs... args) { | |
232 if (IsDirect()) { | |
233 asm_->TailCallRuntime(function, context, args...); | |
234 } else { | |
235 IndirectReturn(asm_->CallRuntime(function, context, args...)); | |
236 } | |
237 } | |
238 | |
239 template <class... TArgs> | |
240 void ReturnStub(Callable const& callable, Node* context, TArgs... args) { | |
Igor Sheludko
2017/02/08 15:26:32
ReturnCallStub
jgruber
2017/02/09 09:23:42
Done.
| |
241 if (IsDirect()) { | |
242 asm_->TailCallStub(callable, context, args...); | |
243 } else { | |
244 IndirectReturn(asm_->CallStub(callable, context, args...)); | |
245 } | |
246 } | |
247 | |
248 template <class... TArgs> | |
249 void ReturnStub(const CallInterfaceDescriptor& descriptor, Node* target, | |
Igor Sheludko
2017/02/08 15:26:32
ReturnCallStub
jgruber
2017/02/09 09:23:42
Done.
| |
250 Node* context, TArgs... args) { | |
251 if (IsDirect()) { | |
252 asm_->TailCallStub(descriptor, target, context, args...); | |
253 } else { | |
254 IndirectReturn(asm_->CallStub(descriptor, target, context, args...)); | |
255 } | |
256 } | |
257 | |
258 void Return(Node* const result) { | |
259 if (IsDirect()) { | |
260 asm_->Return(result); | |
261 } else { | |
262 IndirectReturn(result); | |
263 } | |
264 } | |
265 | |
266 bool IsDirect() const { return out_ == nullptr; } | |
267 bool IsIndirect() const { return !IsDirect(); } | |
Igor Sheludko
2017/02/08 15:26:32
I'd just leave IsDirect()
jgruber
2017/02/09 09:23:42
Done.
| |
268 | |
269 private: | |
270 void IndirectReturn(Node* const result) { | |
271 var_result_->Bind(result); | |
272 asm_->Goto(out_); | |
273 } | |
274 | |
275 CodeAssemblerLabel* const out_; | |
276 CodeAssemblerVariable* const var_result_; | |
277 CodeStubAssembler* const asm_; | |
278 }; | |
279 | |
201 } // namespace internal | 280 } // namespace internal |
202 } // namespace v8 | 281 } // namespace v8 |
203 | 282 |
204 #endif // V8_SRC_IC_ACCESSOR_ASSEMBLER_H_ | 283 #endif // V8_SRC_IC_ACCESSOR_ASSEMBLER_H_ |
OLD | NEW |