f5dafe9038a11c6ba21b4f8d09461ebfb634a654
[platform/upstream/v8.git] / src / ic / handler-compiler.h
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
3 // found in the LICENSE file.
4
5 #ifndef V8_IC_HANDLER_COMPILER_H_
6 #define V8_IC_HANDLER_COMPILER_H_
7
8 #include "src/ic/access-compiler.h"
9 #include "src/ic/ic-state.h"
10
11 namespace v8 {
12 namespace internal {
13
14 class CallOptimization;
15
16 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
17 enum ReturnHolder { RETURN_HOLDER, DONT_RETURN_ANYTHING };
18
19 class PropertyHandlerCompiler : public PropertyAccessCompiler {
20  public:
21   static Handle<Code> Find(Handle<Name> name, Handle<Map> map, Code::Kind kind,
22                            CacheHolderFlag cache_holder, Code::StubType type);
23
24  protected:
25   PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind, Handle<Map> map,
26                           Handle<JSObject> holder, CacheHolderFlag cache_holder)
27       : PropertyAccessCompiler(isolate, kind, cache_holder),
28         map_(map),
29         holder_(holder) {}
30
31   virtual ~PropertyHandlerCompiler() {}
32
33   virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
34                                   Label* miss, ReturnHolder return_what) {
35     UNREACHABLE();
36     return receiver();
37   }
38
39   virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); }
40
41   // Frontend loads from receiver(), returns holder register which may be
42   // different.
43   Register Frontend(Handle<Name> name);
44   void NonexistentFrontendHeader(Handle<Name> name, Label* miss,
45                                  Register scratch1, Register scratch2);
46
47   // When FLAG_vector_ics is true, handlers that have the possibility of missing
48   // will need to save and pass these to miss handlers.
49   void PushVectorAndSlot() { PushVectorAndSlot(vector(), slot()); }
50   void PushVectorAndSlot(Register vector, Register slot);
51   void PopVectorAndSlot() { PopVectorAndSlot(vector(), slot()); }
52   void PopVectorAndSlot(Register vector, Register slot);
53
54   void DiscardVectorAndSlot();
55
56   // TODO(verwaest): Make non-static.
57   static void GenerateApiAccessorCall(MacroAssembler* masm,
58                                       const CallOptimization& optimization,
59                                       Handle<Map> receiver_map,
60                                       Register receiver, Register scratch,
61                                       bool is_store, Register store_parameter,
62                                       Register accessor_holder,
63                                       int accessor_index);
64
65   // Helper function used to check that the dictionary doesn't contain
66   // the property. This function may return false negatives, so miss_label
67   // must always call a backup property check that is complete.
68   // This function is safe to call if the receiver has fast properties.
69   // Name must be unique and receiver must be a heap object.
70   static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
71                                                Label* miss_label,
72                                                Register receiver,
73                                                Handle<Name> name, Register r0,
74                                                Register r1);
75
76   // Generate code to check that a global property cell is empty. Create
77   // the property cell at compilation time if no cell exists for the
78   // property.
79   static void GenerateCheckPropertyCell(MacroAssembler* masm,
80                                         Handle<JSGlobalObject> global,
81                                         Handle<Name> name, Register scratch,
82                                         Label* miss);
83
84   // Generates code that verifies that the property holder has not changed
85   // (checking maps of objects in the prototype chain for fast and global
86   // objects or doing negative lookup for slow objects, ensures that the
87   // property cells for global objects are still empty) and checks that the map
88   // of the holder has not changed. If necessary the function also generates
89   // code for security check in case of global object holders. Helps to make
90   // sure that the current IC is still valid.
91   //
92   // The scratch and holder registers are always clobbered, but the object
93   // register is only clobbered if it the same as the holder register. The
94   // function returns a register containing the holder - either object_reg or
95   // holder_reg.
96   Register CheckPrototypes(Register object_reg, Register holder_reg,
97                            Register scratch1, Register scratch2,
98                            Handle<Name> name, Label* miss,
99                            PrototypeCheckType check, ReturnHolder return_what);
100
101   Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name);
102   void set_holder(Handle<JSObject> holder) { holder_ = holder; }
103   Handle<Map> map() const { return map_; }
104   void set_map(Handle<Map> map) { map_ = map; }
105   Handle<JSObject> holder() const { return holder_; }
106
107  private:
108   Handle<Map> map_;
109   Handle<JSObject> holder_;
110 };
111
112
113 class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
114  public:
115   NamedLoadHandlerCompiler(Isolate* isolate, Handle<Map> map,
116                            Handle<JSObject> holder,
117                            CacheHolderFlag cache_holder)
118       : PropertyHandlerCompiler(isolate, Code::LOAD_IC, map, holder,
119                                 cache_holder) {}
120
121   virtual ~NamedLoadHandlerCompiler() {}
122
123   Handle<Code> CompileLoadField(Handle<Name> name, FieldIndex index);
124
125   Handle<Code> CompileLoadCallback(Handle<Name> name,
126                                    Handle<ExecutableAccessorInfo> callback);
127
128   Handle<Code> CompileLoadCallback(Handle<Name> name,
129                                    const CallOptimization& call_optimization,
130                                    int accessor_index);
131
132   Handle<Code> CompileLoadConstant(Handle<Name> name, int constant_index);
133
134   // The LookupIterator is used to perform a lookup behind the interceptor. If
135   // the iterator points to a LookupIterator::PROPERTY, its access will be
136   // inlined.
137   Handle<Code> CompileLoadInterceptor(LookupIterator* it);
138
139   Handle<Code> CompileLoadViaGetter(Handle<Name> name, int accessor_index,
140                                     int expected_arguments);
141
142   Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name,
143                                  bool is_configurable);
144
145   // Static interface
146   static Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
147                                              Handle<Map> map);
148
149   static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<Map> map,
150                                     Register receiver, Register holder,
151                                     int accessor_index, int expected_arguments,
152                                     Register scratch);
153
154   static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) {
155     GenerateLoadViaGetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
156                           no_reg);
157   }
158
159   static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
160                                             Register receiver,
161                                             Register scratch1,
162                                             Register scratch2,
163                                             Label* miss_label);
164
165   // These constants describe the structure of the interceptor arguments on the
166   // stack. The arguments are pushed by the (platform-specific)
167   // PushInterceptorArguments and read by LoadPropertyWithInterceptorOnly and
168   // LoadWithInterceptor.
169   static const int kInterceptorArgsNameIndex = 0;
170   static const int kInterceptorArgsThisIndex = 1;
171   static const int kInterceptorArgsHolderIndex = 2;
172   static const int kInterceptorArgsLength = 3;
173
174  protected:
175   virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
176                                   Label* miss, ReturnHolder return_what);
177
178   virtual void FrontendFooter(Handle<Name> name, Label* miss);
179
180  private:
181   Handle<Code> CompileLoadNonexistent(Handle<Name> name);
182   void GenerateLoadConstant(Handle<Object> value);
183   void GenerateLoadCallback(Register reg,
184                             Handle<ExecutableAccessorInfo> callback);
185   void GenerateLoadCallback(const CallOptimization& call_optimization,
186                             Handle<Map> receiver_map);
187
188   // Helper emits no code if vector-ics are disabled.
189   void InterceptorVectorSlotPush(Register holder_reg);
190   enum PopMode { POP, DISCARD };
191   void InterceptorVectorSlotPop(Register holder_reg, PopMode mode = POP);
192
193   void GenerateLoadInterceptor(Register holder_reg);
194   void GenerateLoadInterceptorWithFollowup(LookupIterator* it,
195                                            Register holder_reg);
196   void GenerateLoadPostInterceptor(LookupIterator* it, Register reg);
197
198   // Generates prototype loading code that uses the objects from the
199   // context we were in when this function was called. If the context
200   // has changed, a jump to miss is performed. This ties the generated
201   // code to a particular context and so must not be used in cases
202   // where the generated code is not allowed to have references to
203   // objects from a context.
204   static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
205                                                         int index,
206                                                         Register prototype,
207                                                         Label* miss);
208
209
210   Register scratch4() { return registers_[5]; }
211 };
212
213
214 class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
215  public:
216   explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<Map> map,
217                                      Handle<JSObject> holder)
218       : PropertyHandlerCompiler(isolate, Code::STORE_IC, map, holder,
219                                 kCacheOnReceiver) {}
220
221   virtual ~NamedStoreHandlerCompiler() {}
222
223   Handle<Code> CompileStoreTransition(Handle<Map> transition,
224                                       Handle<Name> name);
225   Handle<Code> CompileStoreField(LookupIterator* it);
226   Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
227                                     Handle<ExecutableAccessorInfo> callback);
228   Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
229                                     const CallOptimization& call_optimization,
230                                     int accessor_index);
231   Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, Handle<Name> name,
232                                      int accessor_index,
233                                      int expected_arguments);
234   Handle<Code> CompileStoreInterceptor(Handle<Name> name);
235
236   static void GenerateStoreViaSetter(MacroAssembler* masm, Handle<Map> map,
237                                      Register receiver, Register holder,
238                                      int accessor_index, int expected_arguments,
239                                      Register scratch);
240
241   static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) {
242     GenerateStoreViaSetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
243                            no_reg);
244   }
245
246   static void GenerateSlow(MacroAssembler* masm);
247
248  protected:
249   virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
250                                   Label* miss, ReturnHolder return_what);
251
252   virtual void FrontendFooter(Handle<Name> name, Label* miss);
253   void GenerateRestoreName(Label* label, Handle<Name> name);
254   void GeneratePushMap(Register map_reg, Register scratch);
255
256  private:
257   void GenerateRestoreName(Handle<Name> name);
258   void GenerateRestoreMap(Handle<Map> transition, Register map_reg,
259                           Register scratch, Label* miss);
260
261   void GenerateConstantCheck(Register map_reg, int descriptor,
262                              Register value_reg, Register scratch,
263                              Label* miss_label);
264
265   bool RequiresFieldTypeChecks(HeapType* field_type) const;
266   void GenerateFieldTypeChecks(HeapType* field_type, Register value_reg,
267                                Label* miss_label);
268
269   static Builtins::Name SlowBuiltin(Code::Kind kind) {
270     switch (kind) {
271       case Code::STORE_IC:
272         return Builtins::kStoreIC_Slow;
273       case Code::KEYED_STORE_IC:
274         return Builtins::kKeyedStoreIC_Slow;
275       default:
276         UNREACHABLE();
277     }
278     return Builtins::kStoreIC_Slow;
279   }
280
281   static Register value();
282 };
283
284
285 class ElementHandlerCompiler : public PropertyHandlerCompiler {
286  public:
287   explicit ElementHandlerCompiler(Isolate* isolate)
288       : PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC,
289                                 Handle<Map>::null(), Handle<JSObject>::null(),
290                                 kCacheOnReceiver) {}
291
292   virtual ~ElementHandlerCompiler() {}
293
294   void CompileElementHandlers(MapHandleList* receiver_maps,
295                               CodeHandleList* handlers,
296                               LanguageMode language_mode);
297
298   static void GenerateStoreSlow(MacroAssembler* masm);
299 };
300 }
301 }  // namespace v8::internal
302
303 #endif  // V8_IC_HANDLER_COMPILER_H_