OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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_IC_IC_COMPILER_H_ | 5 #ifndef V8_IC_IC_COMPILER_H_ |
6 #define V8_IC_IC_COMPILER_H_ | 6 #define V8_IC_IC_COMPILER_H_ |
7 | 7 |
8 #include "src/code-stubs.h" | |
9 #include "src/ic/access-compiler.h" | 8 #include "src/ic/access-compiler.h" |
10 #include "src/macro-assembler.h" | |
11 #include "src/objects.h" | |
12 | 9 |
13 namespace v8 { | 10 namespace v8 { |
14 namespace internal { | 11 namespace internal { |
15 | 12 |
16 | 13 |
17 class CallOptimization; | |
18 | |
19 | |
20 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER }; | |
21 enum IcCheckType { ELEMENT, PROPERTY }; | 14 enum IcCheckType { ELEMENT, PROPERTY }; |
22 | 15 |
23 | 16 |
24 class PropertyICCompiler : public PropertyAccessCompiler { | 17 class PropertyICCompiler : public PropertyAccessCompiler { |
25 public: | 18 public: |
26 // Finds the Code object stored in the Heap::non_monomorphic_cache(). | 19 // Finds the Code object stored in the Heap::non_monomorphic_cache(). |
27 static Code* FindPreMonomorphic(Isolate* isolate, Code::Kind kind, | 20 static Code* FindPreMonomorphic(Isolate* isolate, Code::Kind kind, |
28 ExtraICState extra_ic_state); | 21 ExtraICState extra_ic_state); |
29 | 22 |
30 // Named | 23 // Named |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 return code->ic_state() == MONOMORPHIC | 113 return code->ic_state() == MONOMORPHIC |
121 ? Logger::KEYED_STORE_IC_TAG | 114 ? Logger::KEYED_STORE_IC_TAG |
122 : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG; | 115 : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG; |
123 } | 116 } |
124 } | 117 } |
125 | 118 |
126 const ExtraICState extra_ic_state_; | 119 const ExtraICState extra_ic_state_; |
127 }; | 120 }; |
128 | 121 |
129 | 122 |
130 class PropertyHandlerCompiler : public PropertyAccessCompiler { | |
131 public: | |
132 static Handle<Code> Find(Handle<Name> name, Handle<Map> map, Code::Kind kind, | |
133 CacheHolderFlag cache_holder, Code::StubType type); | |
134 | |
135 protected: | |
136 PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind, | |
137 Handle<HeapType> type, Handle<JSObject> holder, | |
138 CacheHolderFlag cache_holder) | |
139 : PropertyAccessCompiler(isolate, kind, cache_holder), | |
140 type_(type), | |
141 holder_(holder) {} | |
142 | |
143 virtual ~PropertyHandlerCompiler() {} | |
144 | |
145 virtual Register FrontendHeader(Register object_reg, Handle<Name> name, | |
146 Label* miss) { | |
147 UNREACHABLE(); | |
148 return receiver(); | |
149 } | |
150 | |
151 virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); } | |
152 | |
153 Register Frontend(Register object_reg, Handle<Name> name); | |
154 void NonexistentFrontendHeader(Handle<Name> name, Label* miss, | |
155 Register scratch1, Register scratch2); | |
156 | |
157 // TODO(verwaest): Make non-static. | |
158 static void GenerateFastApiCall(MacroAssembler* masm, | |
159 const CallOptimization& optimization, | |
160 Handle<Map> receiver_map, Register receiver, | |
161 Register scratch, bool is_store, int argc, | |
162 Register* values); | |
163 | |
164 // Helper function used to check that the dictionary doesn't contain | |
165 // the property. This function may return false negatives, so miss_label | |
166 // must always call a backup property check that is complete. | |
167 // This function is safe to call if the receiver has fast properties. | |
168 // Name must be unique and receiver must be a heap object. | |
169 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, | |
170 Label* miss_label, | |
171 Register receiver, | |
172 Handle<Name> name, Register r0, | |
173 Register r1); | |
174 | |
175 // Generate code to check that a global property cell is empty. Create | |
176 // the property cell at compilation time if no cell exists for the | |
177 // property. | |
178 static void GenerateCheckPropertyCell(MacroAssembler* masm, | |
179 Handle<JSGlobalObject> global, | |
180 Handle<Name> name, Register scratch, | |
181 Label* miss); | |
182 | |
183 // Generates code that verifies that the property holder has not changed | |
184 // (checking maps of objects in the prototype chain for fast and global | |
185 // objects or doing negative lookup for slow objects, ensures that the | |
186 // property cells for global objects are still empty) and checks that the map | |
187 // of the holder has not changed. If necessary the function also generates | |
188 // code for security check in case of global object holders. Helps to make | |
189 // sure that the current IC is still valid. | |
190 // | |
191 // The scratch and holder registers are always clobbered, but the object | |
192 // register is only clobbered if it the same as the holder register. The | |
193 // function returns a register containing the holder - either object_reg or | |
194 // holder_reg. | |
195 Register CheckPrototypes(Register object_reg, Register holder_reg, | |
196 Register scratch1, Register scratch2, | |
197 Handle<Name> name, Label* miss, | |
198 PrototypeCheckType check = CHECK_ALL_MAPS); | |
199 | |
200 Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name); | |
201 void set_type_for_object(Handle<Object> object) { | |
202 type_ = IC::CurrentTypeOf(object, isolate()); | |
203 } | |
204 void set_holder(Handle<JSObject> holder) { holder_ = holder; } | |
205 Handle<HeapType> type() const { return type_; } | |
206 Handle<JSObject> holder() const { return holder_; } | |
207 | |
208 private: | |
209 Handle<HeapType> type_; | |
210 Handle<JSObject> holder_; | |
211 }; | |
212 | |
213 | |
214 class NamedLoadHandlerCompiler : public PropertyHandlerCompiler { | |
215 public: | |
216 NamedLoadHandlerCompiler(Isolate* isolate, Handle<HeapType> type, | |
217 Handle<JSObject> holder, | |
218 CacheHolderFlag cache_holder) | |
219 : PropertyHandlerCompiler(isolate, Code::LOAD_IC, type, holder, | |
220 cache_holder) {} | |
221 | |
222 virtual ~NamedLoadHandlerCompiler() {} | |
223 | |
224 Handle<Code> CompileLoadField(Handle<Name> name, FieldIndex index); | |
225 | |
226 Handle<Code> CompileLoadCallback(Handle<Name> name, | |
227 Handle<ExecutableAccessorInfo> callback); | |
228 | |
229 Handle<Code> CompileLoadCallback(Handle<Name> name, | |
230 const CallOptimization& call_optimization); | |
231 | |
232 Handle<Code> CompileLoadConstant(Handle<Name> name, int constant_index); | |
233 | |
234 // The LookupIterator is used to perform a lookup behind the interceptor. If | |
235 // the iterator points to a LookupIterator::PROPERTY, its access will be | |
236 // inlined. | |
237 Handle<Code> CompileLoadInterceptor(LookupIterator* it); | |
238 | |
239 Handle<Code> CompileLoadViaGetter(Handle<Name> name, | |
240 Handle<JSFunction> getter); | |
241 | |
242 Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name, | |
243 bool is_configurable); | |
244 | |
245 // Static interface | |
246 static Handle<Code> ComputeLoadNonexistent(Handle<Name> name, | |
247 Handle<HeapType> type); | |
248 | |
249 static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<HeapType> type, | |
250 Register receiver, | |
251 Handle<JSFunction> getter); | |
252 | |
253 static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) { | |
254 GenerateLoadViaGetter(masm, Handle<HeapType>::null(), no_reg, | |
255 Handle<JSFunction>()); | |
256 } | |
257 | |
258 static void GenerateLoadFunctionPrototype(MacroAssembler* masm, | |
259 Register receiver, | |
260 Register scratch1, | |
261 Register scratch2, | |
262 Label* miss_label); | |
263 | |
264 // These constants describe the structure of the interceptor arguments on the | |
265 // stack. The arguments are pushed by the (platform-specific) | |
266 // PushInterceptorArguments and read by LoadPropertyWithInterceptorOnly and | |
267 // LoadWithInterceptor. | |
268 static const int kInterceptorArgsNameIndex = 0; | |
269 static const int kInterceptorArgsInfoIndex = 1; | |
270 static const int kInterceptorArgsThisIndex = 2; | |
271 static const int kInterceptorArgsHolderIndex = 3; | |
272 static const int kInterceptorArgsLength = 4; | |
273 | |
274 protected: | |
275 virtual Register FrontendHeader(Register object_reg, Handle<Name> name, | |
276 Label* miss); | |
277 | |
278 virtual void FrontendFooter(Handle<Name> name, Label* miss); | |
279 | |
280 private: | |
281 Handle<Code> CompileLoadNonexistent(Handle<Name> name); | |
282 void GenerateLoadConstant(Handle<Object> value); | |
283 void GenerateLoadCallback(Register reg, | |
284 Handle<ExecutableAccessorInfo> callback); | |
285 void GenerateLoadCallback(const CallOptimization& call_optimization, | |
286 Handle<Map> receiver_map); | |
287 void GenerateLoadInterceptor(Register holder_reg); | |
288 void GenerateLoadInterceptorWithFollowup(LookupIterator* it, | |
289 Register holder_reg); | |
290 void GenerateLoadPostInterceptor(LookupIterator* it, Register reg); | |
291 | |
292 // Generates prototype loading code that uses the objects from the | |
293 // context we were in when this function was called. If the context | |
294 // has changed, a jump to miss is performed. This ties the generated | |
295 // code to a particular context and so must not be used in cases | |
296 // where the generated code is not allowed to have references to | |
297 // objects from a context. | |
298 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm, | |
299 int index, | |
300 Register prototype, | |
301 Label* miss); | |
302 | |
303 | |
304 Register scratch4() { return registers_[5]; } | |
305 }; | |
306 | |
307 | |
308 class NamedStoreHandlerCompiler : public PropertyHandlerCompiler { | |
309 public: | |
310 explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<HeapType> type, | |
311 Handle<JSObject> holder) | |
312 : PropertyHandlerCompiler(isolate, Code::STORE_IC, type, holder, | |
313 kCacheOnReceiver) {} | |
314 | |
315 virtual ~NamedStoreHandlerCompiler() {} | |
316 | |
317 Handle<Code> CompileStoreTransition(Handle<Map> transition, | |
318 Handle<Name> name); | |
319 Handle<Code> CompileStoreField(LookupIterator* it); | |
320 Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name, | |
321 Handle<ExecutableAccessorInfo> callback); | |
322 Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name, | |
323 const CallOptimization& call_optimization); | |
324 Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, Handle<Name> name, | |
325 Handle<JSFunction> setter); | |
326 Handle<Code> CompileStoreInterceptor(Handle<Name> name); | |
327 | |
328 static void GenerateStoreViaSetter(MacroAssembler* masm, | |
329 Handle<HeapType> type, Register receiver, | |
330 Handle<JSFunction> setter); | |
331 | |
332 static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) { | |
333 GenerateStoreViaSetter(masm, Handle<HeapType>::null(), no_reg, | |
334 Handle<JSFunction>()); | |
335 } | |
336 | |
337 protected: | |
338 virtual Register FrontendHeader(Register object_reg, Handle<Name> name, | |
339 Label* miss); | |
340 | |
341 virtual void FrontendFooter(Handle<Name> name, Label* miss); | |
342 void GenerateRestoreName(Label* label, Handle<Name> name); | |
343 | |
344 private: | |
345 void GenerateStoreTransition(Handle<Map> transition, Handle<Name> name, | |
346 Register receiver_reg, Register name_reg, | |
347 Register value_reg, Register scratch1, | |
348 Register scratch2, Register scratch3, | |
349 Label* miss_label, Label* slow); | |
350 | |
351 void GenerateStoreField(LookupIterator* lookup, Register value_reg, | |
352 Label* miss_label); | |
353 | |
354 static Builtins::Name SlowBuiltin(Code::Kind kind) { | |
355 switch (kind) { | |
356 case Code::STORE_IC: | |
357 return Builtins::kStoreIC_Slow; | |
358 case Code::KEYED_STORE_IC: | |
359 return Builtins::kKeyedStoreIC_Slow; | |
360 default: | |
361 UNREACHABLE(); | |
362 } | |
363 return Builtins::kStoreIC_Slow; | |
364 } | |
365 | |
366 static Register value(); | |
367 }; | |
368 | |
369 | |
370 class ElementHandlerCompiler : public PropertyHandlerCompiler { | |
371 public: | |
372 explicit ElementHandlerCompiler(Isolate* isolate) | |
373 : PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC, | |
374 Handle<HeapType>::null(), | |
375 Handle<JSObject>::null(), kCacheOnReceiver) {} | |
376 | |
377 virtual ~ElementHandlerCompiler() {} | |
378 | |
379 void CompileElementHandlers(MapHandleList* receiver_maps, | |
380 CodeHandleList* handlers); | |
381 | |
382 static void GenerateLoadDictionaryElement(MacroAssembler* masm); | |
383 static void GenerateStoreDictionaryElement(MacroAssembler* masm); | |
384 }; | |
385 | |
386 | |
387 } | 123 } |
388 } // namespace v8::internal | 124 } // namespace v8::internal |
389 | 125 |
390 #endif // V8_IC_IC_COMPILER_H_ | 126 #endif // V8_IC_IC_COMPILER_H_ |
OLD | NEW |