Home | History | Annotate | Download | only in src
      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.
     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.
    108   bool IsContextual(Handle<Object> receiver) {
    109     if (receiver->IsGlobalObject()) {
    110       return SlowIsContextual();
    111     } else {
    112       ASSERT(!SlowIsContextual());
    113       return false;
    114     }
    115   }
    116 
    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:
    126   Address fp() const { return fp_; }
    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.
    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:
    173   explicit IC_Utility(IC::UtilityId id)
    174     : address_(IC::AddressFromUtilityId(id)), id_(id) {}
    175 
    176   Address address() const { return address_; }
    177 
    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:
    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.
    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:
    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.
    227   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(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.
    254   static Code* megamorphic_stub() {
    255     return Builtins::builtin(Builtins::LoadIC_Megamorphic);
    256   }
    257   static Code* initialize_stub() {
    258     return Builtins::builtin(Builtins::LoadIC_Initialize);
    259   }
    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:
    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);
    284   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(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.
    317   static Code* initialize_stub() {
    318     return Builtins::builtin(Builtins::KeyedLoadIC_Initialize);
    319   }
    320   static Code* megamorphic_stub() {
    321     return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
    322   }
    323   static Code* generic_stub() {
    324     return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
    325   }
    326   static Code* pre_monomorphic_stub() {
    327     return Builtins::builtin(Builtins::KeyedLoadIC_PreMonomorphic);
    328   }
    329   static Code* string_stub() {
    330     return Builtins::builtin(Builtins::KeyedLoadIC_String);
    331   }
    332   static Code* external_array_stub(JSObject::ElementsKind elements_kind);
    333 
    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:
    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.
    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.
    371   static Code* megamorphic_stub() {
    372     return Builtins::builtin(Builtins::StoreIC_Megamorphic);
    373   }
    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:
    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.
    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.
    420   static Code* initialize_stub() {
    421     return Builtins::builtin(Builtins::KeyedStoreIC_Initialize);
    422   }
    423   static Code* megamorphic_stub() {
    424     return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
    425   }
    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