• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_IC_H_
29 #define V8_IC_H_
30 
31 #include "assembler.h"
32 
33 namespace v8 {
34 namespace internal {
35 
36 // IC_UTIL_LIST defines all utility functions called from generated
37 // inline caching code. The argument for the macro, ICU, is the function name.
38 #define IC_UTIL_LIST(ICU)                             \
39   ICU(LoadIC_Miss)                                    \
40   ICU(KeyedLoadIC_Miss)                               \
41   ICU(CallIC_Miss)                                    \
42   ICU(StoreIC_Miss)                                   \
43   ICU(SharedStoreIC_ExtendStorage)                    \
44   ICU(KeyedStoreIC_Miss)                              \
45   /* Utilities for IC stubs. */                       \
46   ICU(LoadCallbackProperty)                           \
47   ICU(StoreCallbackProperty)                          \
48   ICU(LoadPropertyWithInterceptorOnly)                \
49   ICU(LoadPropertyWithInterceptorForLoad)             \
50   ICU(LoadPropertyWithInterceptorForCall)             \
51   ICU(StoreInterceptorProperty)
52 
53 //
54 // IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
55 // and KeyedStoreIC.
56 //
57 class IC {
58  public:
59 
60   // The ids for utility called from the generated code.
61   enum UtilityId {
62   #define CONST_NAME(name) k##name,
63     IC_UTIL_LIST(CONST_NAME)
64   #undef CONST_NAME
65     kUtilityCount
66   };
67 
68   // Looks up the address of the named utility.
69   static Address AddressFromUtilityId(UtilityId id);
70 
71   // Alias the inline cache state type to make the IC code more readable.
72   typedef InlineCacheState State;
73 
74   // The IC code is either invoked with no extra frames on the stack
75   // or with a single extra frame for supporting calls.
76   enum FrameDepth {
77     NO_EXTRA_FRAME = 0,
78     EXTRA_CALL_FRAME = 1
79   };
80 
81   // Construct the IC structure with the given number of extra
82   // JavaScript frames on the stack.
83   explicit IC(FrameDepth depth);
84 
85   // Get the call-site target; used for determining the state.
target()86   Code* target() { return GetTargetAtAddress(address()); }
87   inline Address address();
88 
89   // Compute the current IC state based on the target stub and the receiver.
90   static State StateFrom(Code* target, Object* receiver);
91 
92   // Clear the inline cache to initial state.
93   static void Clear(Address address);
94 
95   // Computes the reloc info for this IC. This is a fairly expensive
96   // operation as it has to search through the heap to find the code
97   // object that contains this IC site.
98   RelocInfo::Mode ComputeMode();
99 
100   // Returns if this IC is for contextual (no explicit receiver)
101   // access to properties.
is_contextual()102   bool is_contextual() {
103     return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
104   }
105 
106   // Returns the map to use for caching stubs for a given object.
107   // This method should not be called with undefined or null.
108   static inline Map* GetCodeCacheMapForObject(Object* object);
109 
110  protected:
fp()111   Address fp() const { return fp_; }
pc()112   Address pc() const { return *pc_address_; }
113 
114 #ifdef ENABLE_DEBUGGER_SUPPORT
115   // Computes the address in the original code when the code running is
116   // containing break points (calls to DebugBreakXXX builtins).
117   Address OriginalCodeAddress();
118 #endif
119 
120   // Set the call-site target.
set_target(Code * code)121   void set_target(Code* code) { SetTargetAtAddress(address(), code); }
122 
123 #ifdef DEBUG
124   static void TraceIC(const char* type,
125                       Handle<String> name,
126                       State old_state,
127                       Code* new_target,
128                       const char* extra_info = "");
129 #endif
130 
131   static Failure* TypeError(const char* type,
132                             Handle<Object> object,
133                             Handle<String> name);
134   static Failure* ReferenceError(const char* type, Handle<String> name);
135 
136   // Access the target code for the given IC address.
137   static inline Code* GetTargetAtAddress(Address address);
138   static inline void SetTargetAtAddress(Address address, Code* target);
139 
140  private:
141   // Frame pointer for the frame that uses (calls) the IC.
142   Address fp_;
143 
144   // All access to the program counter of an IC structure is indirect
145   // to make the code GC safe. This feature is crucial since
146   // GetProperty and SetProperty are called and they in turn might
147   // invoke the garbage collector.
148   Address* pc_address_;
149 
150   DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
151 };
152 
153 
154 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
155 // cannot make forward declarations to an enum.
156 class IC_Utility {
157  public:
IC_Utility(IC::UtilityId id)158   explicit IC_Utility(IC::UtilityId id)
159     : address_(IC::AddressFromUtilityId(id)), id_(id) {}
160 
address()161   Address address() const { return address_; }
162 
id()163   IC::UtilityId id() const { return id_; }
164  private:
165   Address address_;
166   IC::UtilityId id_;
167 };
168 
169 
170 class CallIC: public IC {
171  public:
CallIC()172   CallIC() : IC(EXTRA_CALL_FRAME) { ASSERT(target()->is_call_stub()); }
173 
174   Object* LoadFunction(State state, Handle<Object> object, Handle<String> name);
175 
176 
177   // Code generator routines.
178   static void GenerateInitialize(MacroAssembler* masm, int argc);
179   static void GenerateMiss(MacroAssembler* masm, int argc);
180   static void GenerateMegamorphic(MacroAssembler* masm, int argc);
181   static void GenerateNormal(MacroAssembler* masm, int argc);
182 
183  private:
184   static void Generate(MacroAssembler* masm,
185                        int argc,
186                        const ExternalReference& f);
187 
188   // Update the inline cache and the global stub cache based on the
189   // lookup result.
190   void UpdateCaches(LookupResult* lookup,
191                     State state,
192                     Handle<Object> object,
193                     Handle<String> name);
194 
195   // Returns a JSFunction if the object can be called as a function,
196   // and patches the stack to be ready for the call.
197   // Otherwise, it returns the undefined value.
198   Object* TryCallAsFunction(Object* object);
199 
200   static void Clear(Address address, Code* target);
201   friend class IC;
202 };
203 
204 
205 class LoadIC: public IC {
206  public:
LoadIC()207   LoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_load_stub()); }
208 
209   Object* Load(State state, Handle<Object> object, Handle<String> name);
210 
211   // Code generator routines.
212   static void GenerateInitialize(MacroAssembler* masm);
213   static void GeneratePreMonomorphic(MacroAssembler* masm);
214   static void GenerateMiss(MacroAssembler* masm);
215   static void GenerateMegamorphic(MacroAssembler* masm);
216   static void GenerateNormal(MacroAssembler* masm);
217 
218   // Specialized code generator routines.
219   static void GenerateArrayLength(MacroAssembler* masm);
220   static void GenerateStringLength(MacroAssembler* masm);
221   static void GenerateFunctionPrototype(MacroAssembler* masm);
222 
223   // The offset from the inlined patch site to the start of the
224   // inlined load instruction.  It is architecture-dependent, and not
225   // used on ARM.
226   static const int kOffsetToLoadInstruction;
227 
228  private:
229   static void Generate(MacroAssembler* masm, const ExternalReference& f);
230 
231   // Update the inline cache and the global stub cache based on the
232   // lookup result.
233   void UpdateCaches(LookupResult* lookup,
234                     State state,
235                     Handle<Object> object,
236                     Handle<String> name);
237 
238   // Stub accessors.
megamorphic_stub()239   static Code* megamorphic_stub() {
240     return Builtins::builtin(Builtins::LoadIC_Megamorphic);
241   }
initialize_stub()242   static Code* initialize_stub() {
243     return Builtins::builtin(Builtins::LoadIC_Initialize);
244   }
pre_monomorphic_stub()245   static Code* pre_monomorphic_stub() {
246     return Builtins::builtin(Builtins::LoadIC_PreMonomorphic);
247   }
248 
249   static void Clear(Address address, Code* target);
250 
251   // Clear the use of the inlined version.
252   static void ClearInlinedVersion(Address address);
253 
254   static bool PatchInlinedLoad(Address address, Object* map, int index);
255 
256   friend class IC;
257 };
258 
259 
260 class KeyedLoadIC: public IC {
261  public:
KeyedLoadIC()262   KeyedLoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_keyed_load_stub()); }
263 
264   Object* Load(State state, Handle<Object> object, Handle<Object> key);
265 
266   // Code generator routines.
267   static void GenerateMiss(MacroAssembler* masm);
268   static void GenerateInitialize(MacroAssembler* masm);
269   static void GeneratePreMonomorphic(MacroAssembler* masm);
270   static void GenerateGeneric(MacroAssembler* masm);
271 
272   // Clear the use of the inlined version.
273   static void ClearInlinedVersion(Address address);
274 
275  private:
276   static void Generate(MacroAssembler* masm, const ExternalReference& f);
277 
278   // Update the inline cache.
279   void UpdateCaches(LookupResult* lookup,
280                     State state,
281                     Handle<Object> object,
282                     Handle<String> name);
283 
284   // Stub accessors.
initialize_stub()285   static Code* initialize_stub() {
286     return Builtins::builtin(Builtins::KeyedLoadIC_Initialize);
287   }
megamorphic_stub()288   static Code* megamorphic_stub() {
289     return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
290   }
generic_stub()291   static Code* generic_stub() {
292     return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
293   }
pre_monomorphic_stub()294   static Code* pre_monomorphic_stub() {
295     return Builtins::builtin(Builtins::KeyedLoadIC_PreMonomorphic);
296   }
297 
298   static void Clear(Address address, Code* target);
299 
300   // Support for patching the map that is checked in an inlined
301   // version of keyed load.
302   static bool PatchInlinedLoad(Address address, Object* map);
303 
304   friend class IC;
305 };
306 
307 
308 class StoreIC: public IC {
309  public:
StoreIC()310   StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); }
311 
312   Object* Store(State state,
313                 Handle<Object> object,
314                 Handle<String> name,
315                 Handle<Object> value);
316 
317   // Code generators for stub routines. Only called once at startup.
318   static void GenerateInitialize(MacroAssembler* masm);
319   static void GenerateMiss(MacroAssembler* masm);
320   static void GenerateMegamorphic(MacroAssembler* masm);
321   static void GenerateExtendStorage(MacroAssembler* masm);
322 
323  private:
324   static void Generate(MacroAssembler* masm, const ExternalReference& f);
325 
326   // Update the inline cache and the global stub cache based on the
327   // lookup result.
328   void UpdateCaches(LookupResult* lookup,
329                     State state, Handle<JSObject> receiver,
330                     Handle<String> name,
331                     Handle<Object> value);
332 
333   // Stub accessors.
megamorphic_stub()334   static Code* megamorphic_stub() {
335     return Builtins::builtin(Builtins::StoreIC_Megamorphic);
336   }
initialize_stub()337   static Code* initialize_stub() {
338     return Builtins::builtin(Builtins::StoreIC_Initialize);
339   }
340 
341   static void Clear(Address address, Code* target);
342   friend class IC;
343 };
344 
345 
346 class KeyedStoreIC: public IC {
347  public:
KeyedStoreIC()348   KeyedStoreIC() : IC(NO_EXTRA_FRAME) { }
349 
350   Object* Store(State state,
351                 Handle<Object> object,
352                 Handle<Object> name,
353                 Handle<Object> value);
354 
355   // Code generators for stub routines.  Only called once at startup.
356   static void GenerateInitialize(MacroAssembler* masm);
357   static void GenerateMiss(MacroAssembler* masm);
358   static void GenerateGeneric(MacroAssembler* masm);
359   static void GenerateExtendStorage(MacroAssembler* masm);
360 
361   // Clear the inlined version so the IC is always hit.
362   static void ClearInlinedVersion(Address address);
363 
364   // Restore the inlined version so the fast case can get hit.
365   static void RestoreInlinedVersion(Address address);
366 
367  private:
368   static void Generate(MacroAssembler* masm, const ExternalReference& f);
369 
370   // Update the inline cache.
371   void UpdateCaches(LookupResult* lookup,
372                     State state,
373                     Handle<JSObject> receiver,
374                     Handle<String> name,
375                     Handle<Object> value);
376 
377   // Stub accessors.
initialize_stub()378   static Code* initialize_stub() {
379     return Builtins::builtin(Builtins::KeyedStoreIC_Initialize);
380   }
megamorphic_stub()381   static Code* megamorphic_stub() {
382     return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
383   }
generic_stub()384   static Code* generic_stub() {
385     return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
386   }
387 
388   static void Clear(Address address, Code* target);
389 
390   // Support for patching the map that is checked in an inlined
391   // version of keyed store.
392   // The address is the patch point for the IC call
393   // (Assembler::kPatchReturnSequenceLength before the end of
394   // the call/return address).
395   // The map is the new map that the inlined code should check against.
396   static bool PatchInlinedStore(Address address, Object* map);
397 
398   friend class IC;
399 };
400 
401 
402 } }  // namespace v8::internal
403 
404 #endif  // V8_IC_H_
405