• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 ReturnHolder { RETURN_HOLDER, DONT_RETURN_ANYTHING };
17 
18 class PropertyHandlerCompiler : public PropertyAccessCompiler {
19  public:
20   static Handle<Code> Find(Handle<Name> name, Handle<Map> map, Code::Kind kind,
21                            CacheHolderFlag cache_holder);
22 
23  protected:
PropertyHandlerCompiler(Isolate * isolate,Code::Kind kind,Handle<Map> map,Handle<JSObject> holder,CacheHolderFlag cache_holder)24   PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind, Handle<Map> map,
25                           Handle<JSObject> holder, CacheHolderFlag cache_holder)
26       : PropertyAccessCompiler(isolate, kind, cache_holder),
27         map_(map),
28         holder_(holder) {}
29 
~PropertyHandlerCompiler()30   virtual ~PropertyHandlerCompiler() {}
31 
FrontendHeader(Register object_reg,Handle<Name> name,Label * miss,ReturnHolder return_what)32   virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
33                                   Label* miss, ReturnHolder return_what) {
34     UNREACHABLE();
35     return receiver();
36   }
37 
FrontendFooter(Handle<Name> name,Label * miss)38   virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); }
39 
40   // Frontend loads from receiver(), returns holder register which may be
41   // different.
42   Register Frontend(Handle<Name> name);
43 
44   // When FLAG_vector_ics is true, handlers that have the possibility of missing
45   // will need to save and pass these to miss handlers.
PushVectorAndSlot()46   void PushVectorAndSlot() { PushVectorAndSlot(vector(), slot()); }
47   void PushVectorAndSlot(Register vector, Register slot);
PopVectorAndSlot()48   void PopVectorAndSlot() { PopVectorAndSlot(vector(), slot()); }
49   void PopVectorAndSlot(Register vector, Register slot);
50 
51   void DiscardVectorAndSlot();
52 
53   // TODO(verwaest): Make non-static.
54   static void GenerateApiAccessorCall(MacroAssembler* masm,
55                                       const CallOptimization& optimization,
56                                       Handle<Map> receiver_map,
57                                       Register receiver, Register scratch,
58                                       bool is_store, Register store_parameter,
59                                       Register accessor_holder,
60                                       int accessor_index);
61 
62   // Helper function used to check that the dictionary doesn't contain
63   // the property. This function may return false negatives, so miss_label
64   // must always call a backup property check that is complete.
65   // This function is safe to call if the receiver has fast properties.
66   // Name must be unique and receiver must be a heap object.
67   static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
68                                                Label* miss_label,
69                                                Register receiver,
70                                                Handle<Name> name, Register r0,
71                                                Register r1);
72 
73   // Generate code to check that a global property cell is empty. Create
74   // the property cell at compilation time if no cell exists for the
75   // property.
76   static void GenerateCheckPropertyCell(MacroAssembler* masm,
77                                         Handle<JSGlobalObject> global,
78                                         Handle<Name> name, Register scratch,
79                                         Label* miss);
80 
81   // Generates check that current native context has the same access rights
82   // as the given |native_context_cell|.
83   // If |compare_native_contexts_only| is true then access check is considered
84   // passed if the execution-time native context is equal to contents of
85   // |native_context_cell|.
86   // If |compare_native_contexts_only| is false then access check is considered
87   // passed if the execution-time native context is equal to contents of
88   // |native_context_cell| or security tokens of both contexts are equal.
89   void GenerateAccessCheck(Handle<WeakCell> native_context_cell,
90                            Register scratch1, Register scratch2, Label* miss,
91                            bool compare_native_contexts_only);
92 
93   // Generates code that verifies that the property holder has not changed
94   // (checking maps of objects in the prototype chain for fast and global
95   // objects or doing negative lookup for slow objects, ensures that the
96   // property cells for global objects are still empty) and checks that the map
97   // of the holder has not changed. If necessary the function also generates
98   // code for security check in case of global object holders. Helps to make
99   // sure that the current IC is still valid.
100   //
101   // The scratch and holder registers are always clobbered, but the object
102   // register is only clobbered if it the same as the holder register. The
103   // function returns a register containing the holder - either object_reg or
104   // holder_reg.
105   Register CheckPrototypes(Register object_reg, Register holder_reg,
106                            Register scratch1, Register scratch2,
107                            Handle<Name> name, Label* miss,
108                            ReturnHolder return_what);
109 
110   Handle<Code> GetCode(Code::Kind kind, Handle<Name> name);
set_holder(Handle<JSObject> holder)111   void set_holder(Handle<JSObject> holder) { holder_ = holder; }
map()112   Handle<Map> map() const { return map_; }
set_map(Handle<Map> map)113   void set_map(Handle<Map> map) { map_ = map; }
holder()114   Handle<JSObject> holder() const { return holder_; }
115 
116  private:
117   Handle<Map> map_;
118   Handle<JSObject> holder_;
119 };
120 
121 
122 class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
123  public:
NamedLoadHandlerCompiler(Isolate * isolate,Handle<Map> map,Handle<JSObject> holder,CacheHolderFlag cache_holder)124   NamedLoadHandlerCompiler(Isolate* isolate, Handle<Map> map,
125                            Handle<JSObject> holder,
126                            CacheHolderFlag cache_holder)
127       : PropertyHandlerCompiler(isolate, Code::LOAD_IC, map, holder,
128                                 cache_holder) {}
129 
~NamedLoadHandlerCompiler()130   virtual ~NamedLoadHandlerCompiler() {}
131 
132   Handle<Code> CompileLoadCallback(Handle<Name> name,
133                                    Handle<AccessorInfo> callback,
134                                    Handle<Code> slow_stub);
135 
136   Handle<Code> CompileLoadCallback(Handle<Name> name,
137                                    const CallOptimization& call_optimization,
138                                    int accessor_index, Handle<Code> slow_stub);
139 
140   // The LookupIterator is used to perform a lookup behind the interceptor. If
141   // the iterator points to a LookupIterator::PROPERTY, its access will be
142   // inlined.
143   Handle<Code> CompileLoadInterceptor(LookupIterator* it);
144 
145   Handle<Code> CompileLoadViaGetter(Handle<Name> name, int accessor_index,
146                                     int expected_arguments);
147 
148   Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name,
149                                  bool is_configurable);
150 
151   static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<Map> map,
152                                     Register receiver, Register holder,
153                                     int accessor_index, int expected_arguments,
154                                     Register scratch);
155 
GenerateLoadViaGetterForDeopt(MacroAssembler * masm)156   static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) {
157     GenerateLoadViaGetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
158                           no_reg);
159   }
160 
161   // These constants describe the structure of the interceptor arguments on the
162   // stack. The arguments are pushed by the (platform-specific)
163   // PushInterceptorArguments and read by LoadPropertyWithInterceptorOnly and
164   // LoadWithInterceptor.
165   static const int kInterceptorArgsNameIndex = 0;
166   static const int kInterceptorArgsThisIndex = 1;
167   static const int kInterceptorArgsHolderIndex = 2;
168   static const int kInterceptorArgsLength = 3;
169 
170  protected:
171   virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
172                                   Label* miss, ReturnHolder return_what);
173 
174   virtual void FrontendFooter(Handle<Name> name, Label* miss);
175 
176  private:
177   void GenerateLoadCallback(Register reg, Handle<AccessorInfo> callback);
178 
179   // Helper emits no code if vector-ics are disabled.
180   void InterceptorVectorSlotPush(Register holder_reg);
181   enum PopMode { POP, DISCARD };
182   void InterceptorVectorSlotPop(Register holder_reg, PopMode mode = POP);
183 
184   void GenerateLoadInterceptor(Register holder_reg);
185   void GenerateLoadInterceptorWithFollowup(LookupIterator* it,
186                                            Register holder_reg);
187   void GenerateLoadPostInterceptor(LookupIterator* it, Register reg);
188 
scratch3()189   Register scratch3() { return registers_[4]; }
190 };
191 
192 
193 class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
194  public:
195   // All store handlers use StoreWithVectorDescriptor calling convention.
196   typedef StoreWithVectorDescriptor Descriptor;
197 
NamedStoreHandlerCompiler(Isolate * isolate,Handle<Map> map,Handle<JSObject> holder)198   explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<Map> map,
199                                      Handle<JSObject> holder)
200       : PropertyHandlerCompiler(isolate, Code::STORE_IC, map, holder,
201                                 kCacheOnReceiver) {
202 #ifdef DEBUG
203     if (Descriptor::kPassLastArgsOnStack) {
204       ZapStackArgumentsRegisterAliases();
205     }
206 #endif
207   }
208 
~NamedStoreHandlerCompiler()209   virtual ~NamedStoreHandlerCompiler() {}
210 
211   void ZapStackArgumentsRegisterAliases();
212 
213   Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
214                                     Handle<AccessorInfo> callback,
215                                     LanguageMode language_mode);
216   Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
217                                     const CallOptimization& call_optimization,
218                                     int accessor_index, Handle<Code> slow_stub);
219   Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, Handle<Name> name,
220                                      int accessor_index,
221                                      int expected_arguments);
222 
223   static void GenerateStoreViaSetter(MacroAssembler* masm, Handle<Map> map,
224                                      Register receiver, Register holder,
225                                      int accessor_index, int expected_arguments,
226                                      Register scratch);
227 
GenerateStoreViaSetterForDeopt(MacroAssembler * masm)228   static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) {
229     GenerateStoreViaSetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
230                            no_reg);
231   }
232 
233  protected:
234   virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
235                                   Label* miss, ReturnHolder return_what);
236 
237   virtual void FrontendFooter(Handle<Name> name, Label* miss);
238   void GenerateRestoreName(Label* label, Handle<Name> name);
239 
240  private:
241   static Register value();
242 };
243 
244 
245 class ElementHandlerCompiler : public PropertyHandlerCompiler {
246  public:
ElementHandlerCompiler(Isolate * isolate)247   explicit ElementHandlerCompiler(Isolate* isolate)
248       : PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC,
249                                 Handle<Map>::null(), Handle<JSObject>::null(),
250                                 kCacheOnReceiver) {}
251 
~ElementHandlerCompiler()252   virtual ~ElementHandlerCompiler() {}
253 
254   static Handle<Object> GetKeyedLoadHandler(Handle<Map> receiver_map,
255                                             Isolate* isolate);
256   void CompileElementHandlers(MapHandleList* receiver_maps,
257                               List<Handle<Object>>* handlers);
258 };
259 }  // namespace internal
260 }  // namespace v8
261 
262 #endif  // V8_IC_HANDLER_COMPILER_H_
263