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 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: |
69 struct StoreICParameters : public LoadICParameters { | 79 struct StoreICParameters : public LoadICParameters { |
70 StoreICParameters(Node* context, Node* receiver, Node* name, Node* value, | 80 StoreICParameters(Node* context, Node* receiver, Node* name, Node* value, |
71 Node* slot, Node* vector) | 81 Node* slot, Node* vector) |
72 : LoadICParameters(context, receiver, name, slot, vector), | 82 : LoadICParameters(context, receiver, name, slot, vector), |
73 value(value) {} | 83 value(value) {} |
74 Node* value; | 84 Node* value; |
75 }; | 85 }; |
76 | 86 |
77 enum ElementSupport { kOnlyProperties, kSupportElements }; | 87 enum ElementSupport { kOnlyProperties, kSupportElements }; |
78 void HandleStoreICHandlerCase( | 88 void HandleStoreICHandlerCase( |
(...skipping 28 matching lines...) Expand all Loading... |
107 Label* if_miss); | 117 Label* if_miss); |
108 | 118 |
109 // LoadIC implementation. | 119 // LoadIC implementation. |
110 | 120 |
111 void HandleLoadICHandlerCase( | 121 void HandleLoadICHandlerCase( |
112 const LoadICParameters* p, Node* handler, Label* miss, | 122 const LoadICParameters* p, Node* handler, Label* miss, |
113 ElementSupport support_elements = kOnlyProperties); | 123 ElementSupport support_elements = kOnlyProperties); |
114 | 124 |
115 void HandleLoadICSmiHandlerCase(const LoadICParameters* p, Node* holder, | 125 void HandleLoadICSmiHandlerCase(const LoadICParameters* p, Node* holder, |
116 Node* smi_handler, Label* miss, | 126 Node* smi_handler, Label* miss, |
| 127 ExitPoint* exit_point, |
117 ElementSupport support_elements); | 128 ElementSupport support_elements); |
118 | 129 |
119 void HandleLoadICProtoHandlerCase(const LoadICParameters* p, Node* handler, | 130 void HandleLoadICProtoHandlerCase(const LoadICParameters* p, Node* handler, |
120 Variable* var_holder, | 131 Variable* var_holder, |
121 Variable* var_smi_handler, | 132 Variable* var_smi_handler, |
122 Label* if_smi_handler, Label* miss, | 133 Label* if_smi_handler, Label* miss, |
| 134 ExitPoint* exit_point, |
123 bool throw_reference_error_if_nonexistent); | 135 bool throw_reference_error_if_nonexistent); |
124 | 136 |
125 Node* EmitLoadICProtoArrayCheck(const LoadICParameters* p, Node* handler, | 137 Node* EmitLoadICProtoArrayCheck(const LoadICParameters* p, Node* handler, |
126 Node* handler_length, Node* handler_flags, | 138 Node* handler_length, Node* handler_flags, |
127 Label* miss, | 139 Label* miss, |
128 bool throw_reference_error_if_nonexistent); | 140 bool throw_reference_error_if_nonexistent); |
129 | 141 |
130 // LoadGlobalIC implementation. | 142 // LoadGlobalIC implementation. |
131 | 143 |
132 void HandleLoadGlobalICHandlerCase(const LoadICParameters* p, Node* handler, | 144 void HandleLoadGlobalICHandlerCase(const LoadICParameters* p, Node* handler, |
133 Label* miss, | 145 Label* miss, ExitPoint* exit_point, |
134 bool throw_reference_error_if_nonexistent); | 146 bool throw_reference_error_if_nonexistent); |
135 | 147 |
136 // StoreIC implementation. | 148 // StoreIC implementation. |
137 | 149 |
138 void HandleStoreICElementHandlerCase(const StoreICParameters* p, | 150 void HandleStoreICElementHandlerCase(const StoreICParameters* p, |
139 Node* handler, Label* miss); | 151 Node* handler, Label* miss); |
140 | 152 |
141 void HandleStoreICProtoHandler(const StoreICParameters* p, Node* handler, | 153 void HandleStoreICProtoHandler(const StoreICParameters* p, Node* handler, |
142 Label* miss); | 154 Label* miss); |
143 // If |transition| is nullptr then the normal field store is generated or | 155 // If |transition| is nullptr then the normal field store is generated or |
(...skipping 28 matching lines...) Expand all Loading... |
172 Representation representation, Node* value, | 184 Representation representation, Node* value, |
173 bool transition_to_field); | 185 bool transition_to_field); |
174 | 186 |
175 void EmitFastElementsBoundsCheck(Node* object, Node* elements, | 187 void EmitFastElementsBoundsCheck(Node* object, Node* elements, |
176 Node* intptr_index, | 188 Node* intptr_index, |
177 Node* is_jsarray_condition, Label* miss); | 189 Node* is_jsarray_condition, Label* miss); |
178 void EmitElementLoad(Node* object, Node* elements, Node* elements_kind, | 190 void EmitElementLoad(Node* object, Node* elements, Node* elements_kind, |
179 Node* key, Node* is_jsarray_condition, Label* if_hole, | 191 Node* key, Node* is_jsarray_condition, Label* if_hole, |
180 Label* rebox_double, Variable* var_double_value, | 192 Label* rebox_double, Variable* var_double_value, |
181 Label* unimplemented_elements_kind, Label* out_of_bounds, | 193 Label* unimplemented_elements_kind, Label* out_of_bounds, |
182 Label* miss); | 194 Label* miss, ExitPoint* exit_point); |
183 void CheckPrototype(Node* prototype_cell, Node* name, Label* miss); | 195 void CheckPrototype(Node* prototype_cell, Node* name, Label* miss); |
184 void NameDictionaryNegativeLookup(Node* object, Node* name, Label* miss); | 196 void NameDictionaryNegativeLookup(Node* object, Node* name, Label* miss); |
185 | 197 |
186 // Stub cache access helpers. | 198 // Stub cache access helpers. |
187 | 199 |
188 // This enum is used here as a replacement for StubCache::Table to avoid | 200 // This enum is used here as a replacement for StubCache::Table to avoid |
189 // including stub cache header. | 201 // including stub cache header. |
190 enum StubCacheTable : int; | 202 enum StubCacheTable : int; |
191 | 203 |
192 Node* StubCachePrimaryOffset(Node* name, Node* map); | 204 Node* StubCachePrimaryOffset(Node* name, Node* map); |
193 Node* StubCacheSecondaryOffset(Node* name, Node* seed); | 205 Node* StubCacheSecondaryOffset(Node* name, Node* seed); |
194 | 206 |
195 void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id, | 207 void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id, |
196 Node* entry_offset, Node* name, Node* map, | 208 Node* entry_offset, Node* name, Node* map, |
197 Label* if_handler, Variable* var_handler, | 209 Label* if_handler, Variable* var_handler, |
198 Label* if_miss); | 210 Label* if_miss); |
199 }; | 211 }; |
200 | 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: |
| 223 explicit ExitPoint(CodeStubAssembler* assembler) |
| 224 : ExitPoint(assembler, nullptr, nullptr) {} |
| 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> |
| 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> |
| 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> |
| 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 |
| 260 void Return(Node* const result) { |
| 261 if (IsDirect()) { |
| 262 asm_->Return(result); |
| 263 } else { |
| 264 IndirectReturn(result); |
| 265 } |
| 266 } |
| 267 |
| 268 bool IsDirect() const { return out_ == nullptr; } |
| 269 |
| 270 private: |
| 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 |
201 } // namespace internal | 281 } // namespace internal |
202 } // namespace v8 | 282 } // namespace v8 |
203 | 283 |
204 #endif // V8_SRC_IC_ACCESSOR_ASSEMBLER_H_ | 284 #endif // V8_SRC_IC_ACCESSOR_ASSEMBLER_H_ |
OLD | NEW |