• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #ifndef V8_SRC_IC_ACCESSOR_ASSEMBLER_H_
6 #define V8_SRC_IC_ACCESSOR_ASSEMBLER_H_
7 
8 #include "src/code-stub-assembler.h"
9 
10 namespace v8 {
11 namespace internal {
12 
13 namespace compiler {
14 class CodeAssemblerState;
15 }
16 
17 class ExitPoint;
18 
19 class AccessorAssembler : public CodeStubAssembler {
20  public:
21   typedef compiler::Node Node;
22 
AccessorAssembler(compiler::CodeAssemblerState * state)23   explicit AccessorAssembler(compiler::CodeAssemblerState* state)
24       : CodeStubAssembler(state) {}
25 
26   void GenerateLoadIC();
27   void GenerateLoadField();
28   void GenerateLoadICTrampoline();
29   void GenerateKeyedLoadIC();
30   void GenerateKeyedLoadICTrampoline();
31   void GenerateKeyedLoadIC_Megamorphic();
32   void GenerateStoreIC();
33   void GenerateStoreICTrampoline();
34 
35   void GenerateLoadICProtoArray(bool throw_reference_error_if_nonexistent);
36 
37   void GenerateLoadGlobalIC(TypeofMode typeof_mode);
38   void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode);
39 
40   void GenerateKeyedStoreIC(LanguageMode language_mode);
41   void GenerateKeyedStoreICTrampoline(LanguageMode language_mode);
42 
43   void TryProbeStubCache(StubCache* stub_cache, Node* receiver, Node* name,
44                          Label* if_handler, Variable* var_handler,
45                          Label* if_miss);
46 
StubCachePrimaryOffsetForTesting(Node * name,Node * map)47   Node* StubCachePrimaryOffsetForTesting(Node* name, Node* map) {
48     return StubCachePrimaryOffset(name, map);
49   }
StubCacheSecondaryOffsetForTesting(Node * name,Node * map)50   Node* StubCacheSecondaryOffsetForTesting(Node* name, Node* map) {
51     return StubCacheSecondaryOffset(name, map);
52   }
53 
54   struct LoadICParameters {
LoadICParametersLoadICParameters55     LoadICParameters(Node* context, Node* receiver, Node* name, Node* slot,
56                      Node* vector)
57         : context(context),
58           receiver(receiver),
59           name(name),
60           slot(slot),
61           vector(vector) {}
62 
63     Node* context;
64     Node* receiver;
65     Node* name;
66     Node* slot;
67     Node* vector;
68   };
69 
70   void LoadGlobalIC_TryPropertyCellCase(
71       Node* vector, Node* slot, ExitPoint* exit_point, Label* try_handler,
72       Label* miss, ParameterMode slot_mode = SMI_PARAMETERS);
73   void LoadGlobalIC_TryHandlerCase(const LoadICParameters* p,
74                                    TypeofMode typeof_mode,
75                                    ExitPoint* exit_point, Label* miss);
76   void LoadGlobalIC_MissCase(const LoadICParameters* p, ExitPoint* exit_point);
77 
78  protected:
79   struct StoreICParameters : public LoadICParameters {
StoreICParametersStoreICParameters80     StoreICParameters(Node* context, Node* receiver, Node* name, Node* value,
81                       Node* slot, Node* vector)
82         : LoadICParameters(context, receiver, name, slot, vector),
83           value(value) {}
84     Node* value;
85   };
86 
87   enum ElementSupport { kOnlyProperties, kSupportElements };
88   void HandleStoreICHandlerCase(
89       const StoreICParameters* p, Node* handler, Label* miss,
90       ElementSupport support_elements = kOnlyProperties);
91 
92  private:
93   // Stub generation entry points.
94 
95   void LoadIC(const LoadICParameters* p);
96   void LoadICProtoArray(const LoadICParameters* p, Node* handler,
97                         bool throw_reference_error_if_nonexistent);
98   void LoadGlobalIC(const LoadICParameters* p, TypeofMode typeof_mode);
99   void KeyedLoadIC(const LoadICParameters* p);
100   void KeyedLoadICGeneric(const LoadICParameters* p);
101   void StoreIC(const StoreICParameters* p);
102   void KeyedStoreIC(const StoreICParameters* p, LanguageMode language_mode);
103 
104   // IC dispatcher behavior.
105 
106   // Checks monomorphic case. Returns {feedback} entry of the vector.
107   Node* TryMonomorphicCase(Node* slot, Node* vector, Node* receiver_map,
108                            Label* if_handler, Variable* var_handler,
109                            Label* if_miss);
110   void HandlePolymorphicCase(Node* receiver_map, Node* feedback,
111                              Label* if_handler, Variable* var_handler,
112                              Label* if_miss, int unroll_count);
113   void HandleKeyedStorePolymorphicCase(Node* receiver_map, Node* feedback,
114                                        Label* if_handler, Variable* var_handler,
115                                        Label* if_transition_handler,
116                                        Variable* var_transition_map_cell,
117                                        Label* if_miss);
118 
119   // LoadIC implementation.
120 
121   void HandleLoadICHandlerCase(
122       const LoadICParameters* p, Node* handler, Label* miss,
123       ElementSupport support_elements = kOnlyProperties);
124 
125   void HandleLoadICSmiHandlerCase(const LoadICParameters* p, Node* holder,
126                                   Node* smi_handler, Label* miss,
127                                   ExitPoint* exit_point,
128                                   ElementSupport support_elements);
129 
130   void HandleLoadICProtoHandlerCase(const LoadICParameters* p, Node* handler,
131                                     Variable* var_holder,
132                                     Variable* var_smi_handler,
133                                     Label* if_smi_handler, Label* miss,
134                                     ExitPoint* exit_point,
135                                     bool throw_reference_error_if_nonexistent);
136 
137   Node* EmitLoadICProtoArrayCheck(const LoadICParameters* p, Node* handler,
138                                   Node* handler_length, Node* handler_flags,
139                                   Label* miss,
140                                   bool throw_reference_error_if_nonexistent);
141 
142   // LoadGlobalIC implementation.
143 
144   void HandleLoadGlobalICHandlerCase(const LoadICParameters* p, Node* handler,
145                                      Label* miss, ExitPoint* exit_point,
146                                      bool throw_reference_error_if_nonexistent);
147 
148   // StoreIC implementation.
149 
150   void HandleStoreICElementHandlerCase(const StoreICParameters* p,
151                                        Node* handler, Label* miss);
152 
153   void HandleStoreICProtoHandler(const StoreICParameters* p, Node* handler,
154                                  Label* miss);
155   // If |transition| is nullptr then the normal field store is generated or
156   // transitioning store otherwise.
157   void HandleStoreICSmiHandlerCase(Node* handler_word, Node* holder,
158                                    Node* value, Node* transition, Label* miss);
159   // If |transition| is nullptr then the normal field store is generated or
160   // transitioning store otherwise.
161   void HandleStoreFieldAndReturn(Node* handler_word, Node* holder,
162                                  Representation representation, Node* value,
163                                  Node* transition, Label* miss);
164 
165   // KeyedLoadIC_Generic implementation.
166 
167   void GenericElementLoad(Node* receiver, Node* receiver_map,
168                           Node* instance_type, Node* index, Label* slow);
169 
170   void GenericPropertyLoad(Node* receiver, Node* receiver_map,
171                            Node* instance_type, Node* key,
172                            const LoadICParameters* p, Label* slow);
173 
174   // Low-level helpers.
175 
176   Node* PrepareValueForStore(Node* handler_word, Node* holder,
177                              Representation representation, Node* transition,
178                              Node* value, Label* bailout);
179 
180   // Extends properties backing store by JSObject::kFieldsAdded elements.
181   void ExtendPropertiesBackingStore(Node* object);
182 
183   void StoreNamedField(Node* handler_word, Node* object, bool is_inobject,
184                        Representation representation, Node* value,
185                        bool transition_to_field, Label* bailout);
186 
187   void EmitFastElementsBoundsCheck(Node* object, Node* elements,
188                                    Node* intptr_index,
189                                    Node* is_jsarray_condition, Label* miss);
190   void EmitElementLoad(Node* object, Node* elements, Node* elements_kind,
191                        Node* key, Node* is_jsarray_condition, Label* if_hole,
192                        Label* rebox_double, Variable* var_double_value,
193                        Label* unimplemented_elements_kind, Label* out_of_bounds,
194                        Label* miss, ExitPoint* exit_point);
195   void CheckPrototype(Node* prototype_cell, Node* name, Label* miss);
196   void NameDictionaryNegativeLookup(Node* object, Node* name, Label* miss);
197 
198   // Stub cache access helpers.
199 
200   // This enum is used here as a replacement for StubCache::Table to avoid
201   // including stub cache header.
202   enum StubCacheTable : int;
203 
204   Node* StubCachePrimaryOffset(Node* name, Node* map);
205   Node* StubCacheSecondaryOffset(Node* name, Node* seed);
206 
207   void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id,
208                               Node* entry_offset, Node* name, Node* map,
209                               Label* if_handler, Variable* var_handler,
210                               Label* if_miss);
211 };
212 
213 // Abstraction over direct and indirect exit points. Direct exits correspond to
214 // tailcalls and Return, while indirect exits store the result in a variable
215 // and then jump to an exit label.
216 class ExitPoint {
217  private:
218   typedef compiler::Node Node;
219   typedef compiler::CodeAssemblerLabel CodeAssemblerLabel;
220   typedef compiler::CodeAssemblerVariable CodeAssemblerVariable;
221 
222  public:
ExitPoint(CodeStubAssembler * assembler)223   explicit ExitPoint(CodeStubAssembler* assembler)
224       : ExitPoint(assembler, nullptr, nullptr) {}
ExitPoint(CodeStubAssembler * assembler,CodeAssemblerLabel * out,CodeAssemblerVariable * var_result)225   ExitPoint(CodeStubAssembler* assembler, CodeAssemblerLabel* out,
226             CodeAssemblerVariable* var_result)
227       : out_(out), var_result_(var_result), asm_(assembler) {
228     DCHECK_EQ(out != nullptr, var_result != nullptr);
229   }
230 
231   template <class... TArgs>
ReturnCallRuntime(Runtime::FunctionId function,Node * context,TArgs...args)232   void ReturnCallRuntime(Runtime::FunctionId function, Node* context,
233                          TArgs... args) {
234     if (IsDirect()) {
235       asm_->TailCallRuntime(function, context, args...);
236     } else {
237       IndirectReturn(asm_->CallRuntime(function, context, args...));
238     }
239   }
240 
241   template <class... TArgs>
ReturnCallStub(Callable const & callable,Node * context,TArgs...args)242   void ReturnCallStub(Callable const& callable, Node* context, TArgs... args) {
243     if (IsDirect()) {
244       asm_->TailCallStub(callable, context, args...);
245     } else {
246       IndirectReturn(asm_->CallStub(callable, context, args...));
247     }
248   }
249 
250   template <class... TArgs>
ReturnCallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,TArgs...args)251   void ReturnCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
252                       Node* context, TArgs... args) {
253     if (IsDirect()) {
254       asm_->TailCallStub(descriptor, target, context, args...);
255     } else {
256       IndirectReturn(asm_->CallStub(descriptor, target, context, args...));
257     }
258   }
259 
Return(Node * const result)260   void Return(Node* const result) {
261     if (IsDirect()) {
262       asm_->Return(result);
263     } else {
264       IndirectReturn(result);
265     }
266   }
267 
IsDirect()268   bool IsDirect() const { return out_ == nullptr; }
269 
270  private:
IndirectReturn(Node * const result)271   void IndirectReturn(Node* const result) {
272     var_result_->Bind(result);
273     asm_->Goto(out_);
274   }
275 
276   CodeAssemblerLabel* const out_;
277   CodeAssemblerVariable* const var_result_;
278   CodeStubAssembler* const asm_;
279 };
280 
281 }  // namespace internal
282 }  // namespace v8
283 
284 #endif  // V8_SRC_IC_ACCESSOR_ASSEMBLER_H_
285