• 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 // Flag indicating whether an IC stub needs to check that a backing
37 // store is in dictionary case.
38 enum DictionaryCheck { CHECK_DICTIONARY, DICTIONARY_CHECK_DONE };
39 
40 
41 // IC_UTIL_LIST defines all utility functions called from generated
42 // inline caching code. The argument for the macro, ICU, is the function name.
43 #define IC_UTIL_LIST(ICU)                             \
44   ICU(LoadIC_Miss)                                    \
45   ICU(KeyedLoadIC_Miss)                               \
46   ICU(CallIC_Miss)                                    \
47   ICU(StoreIC_Miss)                                   \
48   ICU(SharedStoreIC_ExtendStorage)                    \
49   ICU(KeyedStoreIC_Miss)                              \
50   /* Utilities for IC stubs. */                       \
51   ICU(LoadCallbackProperty)                           \
52   ICU(StoreCallbackProperty)                          \
53   ICU(LoadPropertyWithInterceptorOnly)                \
54   ICU(LoadPropertyWithInterceptorForLoad)             \
55   ICU(LoadPropertyWithInterceptorForCall)             \
56   ICU(KeyedLoadPropertyWithInterceptor)               \
57   ICU(StoreInterceptorProperty)
58 
59 //
60 // IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
61 // and KeyedStoreIC.
62 //
63 class IC {
64  public:
65 
66   // The ids for utility called from the generated code.
67   enum UtilityId {
68   #define CONST_NAME(name) k##name,
69     IC_UTIL_LIST(CONST_NAME)
70   #undef CONST_NAME
71     kUtilityCount
72   };
73 
74   // Looks up the address of the named utility.
75   static Address AddressFromUtilityId(UtilityId id);
76 
77   // Alias the inline cache state type to make the IC code more readable.
78   typedef InlineCacheState State;
79 
80   // The IC code is either invoked with no extra frames on the stack
81   // or with a single extra frame for supporting calls.
82   enum FrameDepth {
83     NO_EXTRA_FRAME = 0,
84     EXTRA_CALL_FRAME = 1
85   };
86 
87   // Construct the IC structure with the given number of extra
88   // JavaScript frames on the stack.
89   explicit IC(FrameDepth depth);
90 
91   // Get the call-site target; used for determining the state.
target()92   Code* target() { return GetTargetAtAddress(address()); }
93   inline Address address();
94 
95   // Compute the current IC state based on the target stub and the receiver.
96   static State StateFrom(Code* target, Object* receiver);
97 
98   // Clear the inline cache to initial state.
99   static void Clear(Address address);
100 
101   // Computes the reloc info for this IC. This is a fairly expensive
102   // operation as it has to search through the heap to find the code
103   // object that contains this IC site.
104   RelocInfo::Mode ComputeMode();
105 
106   // Returns if this IC is for contextual (no explicit receiver)
107   // access to properties.
IsContextual(Handle<Object> receiver)108   bool IsContextual(Handle<Object> receiver) {
109     if (receiver->IsGlobalObject()) {
110       return SlowIsContextual();
111     } else {
112       ASSERT(!SlowIsContextual());
113       return false;
114     }
115   }
116 
SlowIsContextual()117   bool SlowIsContextual() {
118     return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
119   }
120 
121   // Returns the map to use for caching stubs for a given object.
122   // This method should not be called with undefined or null.
123   static inline Map* GetCodeCacheMapForObject(Object* object);
124 
125  protected:
fp()126   Address fp() const { return fp_; }
pc()127   Address pc() const { return *pc_address_; }
128 
129 #ifdef ENABLE_DEBUGGER_SUPPORT
130   // Computes the address in the original code when the code running is
131   // containing break points (calls to DebugBreakXXX builtins).
132   Address OriginalCodeAddress();
133 #endif
134 
135   // Set the call-site target.
set_target(Code * code)136   void set_target(Code* code) { SetTargetAtAddress(address(), code); }
137 
138 #ifdef DEBUG
139   static void TraceIC(const char* type,
140                       Handle<String> name,
141                       State old_state,
142                       Code* new_target,
143                       const char* extra_info = "");
144 #endif
145 
146   static Failure* TypeError(const char* type,
147                             Handle<Object> object,
148                             Handle<String> name);
149   static Failure* ReferenceError(const char* type, Handle<String> name);
150 
151   // Access the target code for the given IC address.
152   static inline Code* GetTargetAtAddress(Address address);
153   static inline void SetTargetAtAddress(Address address, Code* target);
154 
155  private:
156   // Frame pointer for the frame that uses (calls) the IC.
157   Address fp_;
158 
159   // All access to the program counter of an IC structure is indirect
160   // to make the code GC safe. This feature is crucial since
161   // GetProperty and SetProperty are called and they in turn might
162   // invoke the garbage collector.
163   Address* pc_address_;
164 
165   DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
166 };
167 
168 
169 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
170 // cannot make forward declarations to an enum.
171 class IC_Utility {
172  public:
IC_Utility(IC::UtilityId id)173   explicit IC_Utility(IC::UtilityId id)
174     : address_(IC::AddressFromUtilityId(id)), id_(id) {}
175 
address()176   Address address() const { return address_; }
177 
id()178   IC::UtilityId id() const { return id_; }
179  private:
180   Address address_;
181   IC::UtilityId id_;
182 };
183 
184 
185 class CallIC: public IC {
186  public:
CallIC()187   CallIC() : IC(EXTRA_CALL_FRAME) { ASSERT(target()->is_call_stub()); }
188 
189   Object* LoadFunction(State state, Handle<Object> object, Handle<String> name);
190 
191 
192   // Code generator routines.
GenerateInitialize(MacroAssembler * masm,int argc)193   static void GenerateInitialize(MacroAssembler* masm, int argc) {
194     GenerateMiss(masm, argc);
195   }
196   static void GenerateMiss(MacroAssembler* masm, int argc);
197   static void GenerateMegamorphic(MacroAssembler* masm, int argc);
198   static void GenerateNormal(MacroAssembler* masm, int argc);
199 
200  private:
201   // Update the inline cache and the global stub cache based on the
202   // lookup result.
203   void UpdateCaches(LookupResult* lookup,
204                     State state,
205                     Handle<Object> object,
206                     Handle<String> name);
207 
208   // Returns a JSFunction if the object can be called as a function,
209   // and patches the stack to be ready for the call.
210   // Otherwise, it returns the undefined value.
211   Object* TryCallAsFunction(Object* object);
212 
213   void ReceiverToObject(Handle<Object> object);
214 
215   static void Clear(Address address, Code* target);
216   friend class IC;
217 };
218 
219 
220 class LoadIC: public IC {
221  public:
LoadIC()222   LoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_load_stub()); }
223 
224   Object* Load(State state, Handle<Object> object, Handle<String> name);
225 
226   // Code generator routines.
GenerateInitialize(MacroAssembler * masm)227   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
GeneratePreMonomorphic(MacroAssembler * masm)228   static void GeneratePreMonomorphic(MacroAssembler* masm) {
229     GenerateMiss(masm);
230   }
231   static void GenerateMiss(MacroAssembler* masm);
232   static void GenerateMegamorphic(MacroAssembler* masm);
233   static void GenerateNormal(MacroAssembler* masm);
234 
235   // Specialized code generator routines.
236   static void GenerateArrayLength(MacroAssembler* masm);
237   static void GenerateStringLength(MacroAssembler* masm);
238   static void GenerateFunctionPrototype(MacroAssembler* masm);
239 
240   // The offset from the inlined patch site to the start of the
241   // inlined load instruction.  It is architecture-dependent, and not
242   // used on ARM.
243   static const int kOffsetToLoadInstruction;
244 
245  private:
246   // Update the inline cache and the global stub cache based on the
247   // lookup result.
248   void UpdateCaches(LookupResult* lookup,
249                     State state,
250                     Handle<Object> object,
251                     Handle<String> name);
252 
253   // Stub accessors.
megamorphic_stub()254   static Code* megamorphic_stub() {
255     return Builtins::builtin(Builtins::LoadIC_Megamorphic);
256   }
initialize_stub()257   static Code* initialize_stub() {
258     return Builtins::builtin(Builtins::LoadIC_Initialize);
259   }
pre_monomorphic_stub()260   static Code* pre_monomorphic_stub() {
261     return Builtins::builtin(Builtins::LoadIC_PreMonomorphic);
262   }
263 
264   static void Clear(Address address, Code* target);
265 
266   // Clear the use of the inlined version.
267   static void ClearInlinedVersion(Address address);
268 
269   static bool PatchInlinedLoad(Address address, Object* map, int index);
270 
271   friend class IC;
272 };
273 
274 
275 class KeyedLoadIC: public IC {
276  public:
KeyedLoadIC()277   KeyedLoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_keyed_load_stub()); }
278 
279   Object* Load(State state, Handle<Object> object, Handle<Object> key);
280 
281   // Code generator routines.
282   static void GenerateMiss(MacroAssembler* masm);
283   static void GenerateRuntimeGetProperty(MacroAssembler* masm);
GenerateInitialize(MacroAssembler * masm)284   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
GeneratePreMonomorphic(MacroAssembler * masm)285   static void GeneratePreMonomorphic(MacroAssembler* masm) {
286     GenerateMiss(masm);
287   }
288   static void GenerateGeneric(MacroAssembler* masm);
289   static void GenerateString(MacroAssembler* masm);
290 
291   // Generators for external array types. See objects.h.
292   // These are similar to the generic IC; they optimize the case of
293   // operating upon external array types but fall back to the runtime
294   // for all other types.
295   static void GenerateExternalArray(MacroAssembler* masm,
296                                     ExternalArrayType array_type);
297   static void GenerateIndexedInterceptor(MacroAssembler* masm);
298 
299   // Clear the use of the inlined version.
300   static void ClearInlinedVersion(Address address);
301 
302  private:
303   // Bit mask to be tested against bit field for the cases when
304   // generic stub should go into slow case.
305   // Access check is necessary explicitly since generic stub does not perform
306   // map checks.
307   static const int kSlowCaseBitFieldMask =
308       (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
309 
310   // Update the inline cache.
311   void UpdateCaches(LookupResult* lookup,
312                     State state,
313                     Handle<Object> object,
314                     Handle<String> name);
315 
316   // Stub accessors.
initialize_stub()317   static Code* initialize_stub() {
318     return Builtins::builtin(Builtins::KeyedLoadIC_Initialize);
319   }
megamorphic_stub()320   static Code* megamorphic_stub() {
321     return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
322   }
generic_stub()323   static Code* generic_stub() {
324     return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
325   }
pre_monomorphic_stub()326   static Code* pre_monomorphic_stub() {
327     return Builtins::builtin(Builtins::KeyedLoadIC_PreMonomorphic);
328   }
string_stub()329   static Code* string_stub() {
330     return Builtins::builtin(Builtins::KeyedLoadIC_String);
331   }
332   static Code* external_array_stub(JSObject::ElementsKind elements_kind);
333 
indexed_interceptor_stub()334   static Code* indexed_interceptor_stub() {
335     return Builtins::builtin(Builtins::KeyedLoadIC_IndexedInterceptor);
336   }
337 
338   static void Clear(Address address, Code* target);
339 
340   // Support for patching the map that is checked in an inlined
341   // version of keyed load.
342   static bool PatchInlinedLoad(Address address, Object* map);
343 
344   friend class IC;
345 };
346 
347 
348 class StoreIC: public IC {
349  public:
StoreIC()350   StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); }
351 
352   Object* Store(State state,
353                 Handle<Object> object,
354                 Handle<String> name,
355                 Handle<Object> value);
356 
357   // Code generators for stub routines. Only called once at startup.
GenerateInitialize(MacroAssembler * masm)358   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
359   static void GenerateMiss(MacroAssembler* masm);
360   static void GenerateMegamorphic(MacroAssembler* masm);
361 
362  private:
363   // Update the inline cache and the global stub cache based on the
364   // lookup result.
365   void UpdateCaches(LookupResult* lookup,
366                     State state, Handle<JSObject> receiver,
367                     Handle<String> name,
368                     Handle<Object> value);
369 
370   // Stub accessors.
megamorphic_stub()371   static Code* megamorphic_stub() {
372     return Builtins::builtin(Builtins::StoreIC_Megamorphic);
373   }
initialize_stub()374   static Code* initialize_stub() {
375     return Builtins::builtin(Builtins::StoreIC_Initialize);
376   }
377 
378   static void Clear(Address address, Code* target);
379   friend class IC;
380 };
381 
382 
383 class KeyedStoreIC: public IC {
384  public:
KeyedStoreIC()385   KeyedStoreIC() : IC(NO_EXTRA_FRAME) { }
386 
387   Object* Store(State state,
388                 Handle<Object> object,
389                 Handle<Object> name,
390                 Handle<Object> value);
391 
392   // Code generators for stub routines.  Only called once at startup.
GenerateInitialize(MacroAssembler * masm)393   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
394   static void GenerateMiss(MacroAssembler* masm);
395   static void GenerateRuntimeSetProperty(MacroAssembler* masm);
396   static void GenerateGeneric(MacroAssembler* masm);
397 
398   // Generators for external array types. See objects.h.
399   // These are similar to the generic IC; they optimize the case of
400   // operating upon external array types but fall back to the runtime
401   // for all other types.
402   static void GenerateExternalArray(MacroAssembler* masm,
403                                     ExternalArrayType array_type);
404 
405   // Clear the inlined version so the IC is always hit.
406   static void ClearInlinedVersion(Address address);
407 
408   // Restore the inlined version so the fast case can get hit.
409   static void RestoreInlinedVersion(Address address);
410 
411  private:
412   // Update the inline cache.
413   void UpdateCaches(LookupResult* lookup,
414                     State state,
415                     Handle<JSObject> receiver,
416                     Handle<String> name,
417                     Handle<Object> value);
418 
419   // Stub accessors.
initialize_stub()420   static Code* initialize_stub() {
421     return Builtins::builtin(Builtins::KeyedStoreIC_Initialize);
422   }
megamorphic_stub()423   static Code* megamorphic_stub() {
424     return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
425   }
generic_stub()426   static Code* generic_stub() {
427     return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
428   }
429   static Code* external_array_stub(JSObject::ElementsKind elements_kind);
430 
431   static void Clear(Address address, Code* target);
432 
433   // Support for patching the map that is checked in an inlined
434   // version of keyed store.
435   // The address is the patch point for the IC call
436   // (Assembler::kCallTargetAddressOffset before the end of
437   // the call/return address).
438   // The map is the new map that the inlined code should check against.
439   static bool PatchInlinedStore(Address address, Object* map);
440 
441   friend class IC;
442 };
443 
444 
445 } }  // namespace v8::internal
446 
447 #endif  // V8_IC_H_
448