Home | History | Annotate | Download | only in src
      1 // Copyright 2012 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 "macro-assembler.h"
     32 #include "type-info.h"
     33 
     34 namespace v8 {
     35 namespace internal {
     36 
     37 
     38 // IC_UTIL_LIST defines all utility functions called from generated
     39 // inline caching code. The argument for the macro, ICU, is the function name.
     40 #define IC_UTIL_LIST(ICU)                             \
     41   ICU(LoadIC_Miss)                                    \
     42   ICU(KeyedLoadIC_Miss)                               \
     43   ICU(KeyedLoadIC_MissForceGeneric)                   \
     44   ICU(CallIC_Miss)                                    \
     45   ICU(KeyedCallIC_Miss)                               \
     46   ICU(StoreIC_Miss)                                   \
     47   ICU(StoreIC_ArrayLength)                            \
     48   ICU(StoreIC_Slow)                                   \
     49   ICU(SharedStoreIC_ExtendStorage)                    \
     50   ICU(KeyedStoreIC_Miss)                              \
     51   ICU(KeyedStoreIC_MissForceGeneric)                  \
     52   ICU(KeyedStoreIC_Slow)                              \
     53   /* Utilities for IC stubs. */                       \
     54   ICU(StoreCallbackProperty)                          \
     55   ICU(LoadPropertyWithInterceptorOnly)                \
     56   ICU(LoadPropertyWithInterceptorForLoad)             \
     57   ICU(LoadPropertyWithInterceptorForCall)             \
     58   ICU(KeyedLoadPropertyWithInterceptor)               \
     59   ICU(StoreInterceptorProperty)                       \
     60   ICU(BinaryOp_Patch)                                 \
     61   ICU(CompareIC_Miss)                                 \
     62   ICU(CompareNilIC_Miss)                              \
     63   ICU(Unreachable)                                    \
     64   ICU(ToBooleanIC_Miss)
     65 //
     66 // IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
     67 // and KeyedStoreIC.
     68 //
     69 class IC {
     70  public:
     71   // The ids for utility called from the generated code.
     72   enum UtilityId {
     73   #define CONST_NAME(name) k##name,
     74     IC_UTIL_LIST(CONST_NAME)
     75   #undef CONST_NAME
     76     kUtilityCount
     77   };
     78 
     79   // Looks up the address of the named utility.
     80   static Address AddressFromUtilityId(UtilityId id);
     81 
     82   // Alias the inline cache state type to make the IC code more readable.
     83   typedef InlineCacheState State;
     84 
     85   // The IC code is either invoked with no extra frames on the stack
     86   // or with a single extra frame for supporting calls.
     87   enum FrameDepth {
     88     NO_EXTRA_FRAME = 0,
     89     EXTRA_CALL_FRAME = 1
     90   };
     91 
     92   // Construct the IC structure with the given number of extra
     93   // JavaScript frames on the stack.
     94   IC(FrameDepth depth, Isolate* isolate);
     95   virtual ~IC() {}
     96 
     97   // Get the call-site target; used for determining the state.
     98   Code* target() const { return GetTargetAtAddress(address()); }
     99   inline Address address() const;
    100 
    101   // Compute the current IC state based on the target stub, receiver and name.
    102   static State StateFrom(Code* target, Object* receiver, Object* name);
    103 
    104   // Clear the inline cache to initial state.
    105   static void Clear(Address address);
    106 
    107   // Computes the reloc info for this IC. This is a fairly expensive
    108   // operation as it has to search through the heap to find the code
    109   // object that contains this IC site.
    110   RelocInfo::Mode ComputeMode();
    111 
    112   // Returns if this IC is for contextual (no explicit receiver)
    113   // access to properties.
    114   bool IsUndeclaredGlobal(Handle<Object> receiver) {
    115     if (receiver->IsGlobalObject()) {
    116       return SlowIsUndeclaredGlobal();
    117     } else {
    118       ASSERT(!SlowIsUndeclaredGlobal());
    119       return false;
    120     }
    121   }
    122 
    123   bool SlowIsUndeclaredGlobal() {
    124     return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
    125   }
    126 
    127   // Determines which map must be used for keeping the code stub.
    128   // These methods should not be called with undefined or null.
    129   static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object,
    130                                                             JSObject* holder);
    131   static inline InlineCacheHolderFlag GetCodeCacheForObject(JSObject* object,
    132                                                             JSObject* holder);
    133   static inline JSObject* GetCodeCacheHolder(Isolate* isolate,
    134                                              Object* object,
    135                                              InlineCacheHolderFlag holder);
    136 
    137  protected:
    138   Address fp() const { return fp_; }
    139   Address pc() const { return *pc_address_; }
    140   Isolate* isolate() const { return isolate_; }
    141 
    142 #ifdef ENABLE_DEBUGGER_SUPPORT
    143   // Computes the address in the original code when the code running is
    144   // containing break points (calls to DebugBreakXXX builtins).
    145   Address OriginalCodeAddress() const;
    146 #endif
    147 
    148   // Set the call-site target.
    149   void set_target(Code* code) { SetTargetAtAddress(address(), code); }
    150 
    151 #ifdef DEBUG
    152   char TransitionMarkFromState(IC::State state);
    153 
    154   void TraceIC(const char* type,
    155                Handle<Object> name,
    156                State old_state,
    157                Code* new_target);
    158 #endif
    159 
    160   Failure* TypeError(const char* type,
    161                      Handle<Object> object,
    162                      Handle<Object> key);
    163   Failure* ReferenceError(const char* type, Handle<String> name);
    164 
    165   // Access the target code for the given IC address.
    166   static inline Code* GetTargetAtAddress(Address address);
    167   static inline void SetTargetAtAddress(Address address, Code* target);
    168   static void PostPatching(Address address, Code* target, Code* old_target);
    169 
    170   virtual void UpdateMonomorphicIC(Handle<JSObject> receiver,
    171                                    Handle<Code> handler,
    172                                    Handle<String> name,
    173                                    StrictModeFlag strict_mode) {
    174     set_target(*handler);
    175   }
    176   bool UpdatePolymorphicIC(State state,
    177                            Handle<JSObject> receiver,
    178                            Handle<String> name,
    179                            Handle<Code> code,
    180                            StrictModeFlag strict_mode);
    181 
    182   virtual Handle<Code> ComputePolymorphicIC(MapHandleList* receiver_maps,
    183                                             CodeHandleList* handlers,
    184                                             int number_of_valid_maps,
    185                                             Handle<Name> name,
    186                                             StrictModeFlag strict_mode) {
    187     UNREACHABLE();
    188     return Handle<Code>::null();
    189   };
    190 
    191   void CopyICToMegamorphicCache(Handle<String> name);
    192   bool IsTransitionedMapOfMonomorphicTarget(Map* receiver_map);
    193   void PatchCache(State state,
    194                   StrictModeFlag strict_mode,
    195                   Handle<JSObject> receiver,
    196                   Handle<String> name,
    197                   Handle<Code> code);
    198   virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code);
    199   virtual Handle<Code> megamorphic_stub() {
    200     UNREACHABLE();
    201     return Handle<Code>::null();
    202   }
    203   virtual Handle<Code> megamorphic_stub_strict() {
    204     UNREACHABLE();
    205     return Handle<Code>::null();
    206   }
    207   virtual Handle<Code> generic_stub() const {
    208     UNREACHABLE();
    209     return Handle<Code>::null();
    210   }
    211   virtual Handle<Code> generic_stub_strict() const {
    212     UNREACHABLE();
    213     return Handle<Code>::null();
    214   }
    215 
    216  private:
    217   // Frame pointer for the frame that uses (calls) the IC.
    218   Address fp_;
    219 
    220   // All access to the program counter of an IC structure is indirect
    221   // to make the code GC safe. This feature is crucial since
    222   // GetProperty and SetProperty are called and they in turn might
    223   // invoke the garbage collector.
    224   Address* pc_address_;
    225 
    226   Isolate* isolate_;
    227 
    228   DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
    229 };
    230 
    231 
    232 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
    233 // cannot make forward declarations to an enum.
    234 class IC_Utility {
    235  public:
    236   explicit IC_Utility(IC::UtilityId id)
    237     : address_(IC::AddressFromUtilityId(id)), id_(id) {}
    238 
    239   Address address() const { return address_; }
    240 
    241   IC::UtilityId id() const { return id_; }
    242  private:
    243   Address address_;
    244   IC::UtilityId id_;
    245 };
    246 
    247 
    248 class CallICBase: public IC {
    249  public:
    250   class Contextual: public BitField<bool, 0, 1> {};
    251   class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
    252 
    253   // Returns a JSFunction or a Failure.
    254   MUST_USE_RESULT MaybeObject* LoadFunction(State state,
    255                                             Code::ExtraICState extra_ic_state,
    256                                             Handle<Object> object,
    257                                             Handle<String> name);
    258 
    259  protected:
    260   CallICBase(Code::Kind kind, Isolate* isolate)
    261       : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
    262 
    263   bool TryUpdateExtraICState(LookupResult* lookup,
    264                              Handle<Object> object,
    265                              Code::ExtraICState* extra_ic_state);
    266 
    267   // Compute a monomorphic stub if possible, otherwise return a null handle.
    268   Handle<Code> ComputeMonomorphicStub(LookupResult* lookup,
    269                                       State state,
    270                                       Code::ExtraICState extra_state,
    271                                       Handle<Object> object,
    272                                       Handle<String> name);
    273 
    274   // Update the inline cache and the global stub cache based on the lookup
    275   // result.
    276   void UpdateCaches(LookupResult* lookup,
    277                     State state,
    278                     Code::ExtraICState extra_ic_state,
    279                     Handle<Object> object,
    280                     Handle<String> name);
    281 
    282   // Returns a JSFunction if the object can be called as a function, and
    283   // patches the stack to be ready for the call.  Otherwise, it returns the
    284   // undefined value.
    285   Handle<Object> TryCallAsFunction(Handle<Object> object);
    286 
    287   void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
    288 
    289   static void Clear(Address address, Code* target);
    290 
    291   // Platform-specific code generation functions used by both call and
    292   // keyed call.
    293   static void GenerateMiss(MacroAssembler* masm,
    294                            int argc,
    295                            IC::UtilityId id,
    296                            Code::ExtraICState extra_state);
    297 
    298   static void GenerateNormal(MacroAssembler* masm, int argc);
    299 
    300   static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
    301                                             int argc,
    302                                             Code::Kind kind,
    303                                             Code::ExtraICState extra_state);
    304 
    305   Code::Kind kind_;
    306 
    307   friend class IC;
    308 };
    309 
    310 
    311 class CallIC: public CallICBase {
    312  public:
    313   explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) {
    314     ASSERT(target()->is_call_stub());
    315   }
    316 
    317   // Code generator routines.
    318   static void GenerateInitialize(MacroAssembler* masm,
    319                                  int argc,
    320                                  Code::ExtraICState extra_state) {
    321     GenerateMiss(masm, argc, extra_state);
    322   }
    323 
    324   static void GenerateMiss(MacroAssembler* masm,
    325                            int argc,
    326                            Code::ExtraICState extra_state) {
    327     CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state);
    328   }
    329 
    330   static void GenerateMegamorphic(MacroAssembler* masm,
    331                                   int argc,
    332                                   Code::ExtraICState extra_ic_state);
    333 
    334   static void GenerateNormal(MacroAssembler* masm, int argc) {
    335     CallICBase::GenerateNormal(masm, argc);
    336     GenerateMiss(masm, argc, Code::kNoExtraICState);
    337   }
    338 };
    339 
    340 
    341 class KeyedCallIC: public CallICBase {
    342  public:
    343   explicit KeyedCallIC(Isolate* isolate)
    344       : CallICBase(Code::KEYED_CALL_IC, isolate) {
    345     ASSERT(target()->is_keyed_call_stub());
    346   }
    347 
    348   MUST_USE_RESULT MaybeObject* LoadFunction(State state,
    349                                             Handle<Object> object,
    350                                             Handle<Object> key);
    351 
    352   // Code generator routines.
    353   static void GenerateInitialize(MacroAssembler* masm, int argc) {
    354     GenerateMiss(masm, argc);
    355   }
    356 
    357   static void GenerateMiss(MacroAssembler* masm, int argc) {
    358     CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss,
    359                              Code::kNoExtraICState);
    360   }
    361 
    362   static void GenerateMegamorphic(MacroAssembler* masm, int argc);
    363   static void GenerateNormal(MacroAssembler* masm, int argc);
    364   static void GenerateNonStrictArguments(MacroAssembler* masm, int argc);
    365 };
    366 
    367 
    368 class LoadIC: public IC {
    369  public:
    370   explicit LoadIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) {
    371     ASSERT(target()->is_load_stub() || target()->is_keyed_load_stub());
    372   }
    373 
    374   // Code generator routines.
    375   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
    376   static void GeneratePreMonomorphic(MacroAssembler* masm) {
    377     GenerateMiss(masm);
    378   }
    379   static void GenerateMiss(MacroAssembler* masm);
    380   static void GenerateMegamorphic(MacroAssembler* masm);
    381   static void GenerateNormal(MacroAssembler* masm);
    382   static void GenerateRuntimeGetProperty(MacroAssembler* masm);
    383 
    384   MUST_USE_RESULT MaybeObject* Load(State state,
    385                                     Handle<Object> object,
    386                                     Handle<String> name);
    387 
    388  protected:
    389   virtual Code::Kind kind() const { return Code::LOAD_IC; }
    390 
    391   virtual Handle<Code> generic_stub() const {
    392     return isolate()->builtins()->LoadIC_Slow();
    393   }
    394 
    395   virtual Handle<Code> megamorphic_stub() {
    396     return isolate()->builtins()->LoadIC_Megamorphic();
    397   }
    398 
    399   // Update the inline cache and the global stub cache based on the
    400   // lookup result.
    401   void UpdateCaches(LookupResult* lookup,
    402                     State state,
    403                     Handle<Object> object,
    404                     Handle<String> name);
    405 
    406   virtual void UpdateMonomorphicIC(Handle<JSObject> receiver,
    407                                    Handle<Code> handler,
    408                                    Handle<String> name,
    409                                    StrictModeFlag strict_mode);
    410 
    411   virtual Handle<Code> ComputePolymorphicIC(MapHandleList* receiver_maps,
    412                                             CodeHandleList* handlers,
    413                                             int number_of_valid_maps,
    414                                             Handle<Name> name,
    415                                             StrictModeFlag strict_mode);
    416 
    417   virtual Handle<Code> ComputeLoadHandler(LookupResult* lookup,
    418                                           Handle<JSObject> receiver,
    419                                           Handle<String> name);
    420 
    421  private:
    422   // Stub accessors.
    423   static Handle<Code> initialize_stub() {
    424     return Isolate::Current()->builtins()->LoadIC_Initialize();
    425   }
    426   virtual Handle<Code> pre_monomorphic_stub() {
    427     return isolate()->builtins()->LoadIC_PreMonomorphic();
    428   }
    429 
    430   static void Clear(Address address, Code* target);
    431 
    432   friend class IC;
    433 };
    434 
    435 
    436 enum ICMissMode {
    437   MISS_FORCE_GENERIC,
    438   MISS
    439 };
    440 
    441 
    442 class KeyedLoadIC: public LoadIC {
    443  public:
    444   explicit KeyedLoadIC(FrameDepth depth, Isolate* isolate)
    445       : LoadIC(depth, isolate) {
    446     ASSERT(target()->is_keyed_load_stub());
    447   }
    448 
    449   MUST_USE_RESULT MaybeObject* Load(State state,
    450                                     Handle<Object> object,
    451                                     Handle<Object> key,
    452                                     ICMissMode force_generic);
    453 
    454   // Code generator routines.
    455   static void GenerateMiss(MacroAssembler* masm, ICMissMode force_generic);
    456   static void GenerateRuntimeGetProperty(MacroAssembler* masm);
    457   static void GenerateInitialize(MacroAssembler* masm) {
    458     GenerateMiss(masm, MISS);
    459   }
    460   static void GeneratePreMonomorphic(MacroAssembler* masm) {
    461     GenerateMiss(masm, MISS);
    462   }
    463   static void GenerateGeneric(MacroAssembler* masm);
    464   static void GenerateString(MacroAssembler* masm);
    465   static void GenerateIndexedInterceptor(MacroAssembler* masm);
    466   static void GenerateNonStrictArguments(MacroAssembler* masm);
    467 
    468   // Bit mask to be tested against bit field for the cases when
    469   // generic stub should go into slow case.
    470   // Access check is necessary explicitly since generic stub does not perform
    471   // map checks.
    472   static const int kSlowCaseBitFieldMask =
    473       (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
    474 
    475  protected:
    476   virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
    477 
    478   Handle<Code> LoadElementStub(Handle<JSObject> receiver);
    479 
    480   virtual Handle<Code> megamorphic_stub() {
    481     return isolate()->builtins()->KeyedLoadIC_Generic();
    482   }
    483   virtual Handle<Code> generic_stub() const {
    484     return isolate()->builtins()->KeyedLoadIC_Generic();
    485   }
    486 
    487   // Update the inline cache.
    488   virtual void UpdateMonomorphicIC(Handle<JSObject> receiver,
    489                                    Handle<Code> handler,
    490                                    Handle<String> name,
    491                                    StrictModeFlag strict_mode);
    492   virtual Handle<Code> ComputeLoadHandler(LookupResult* lookup,
    493                                           Handle<JSObject> receiver,
    494                                           Handle<String> name);
    495   virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code) { }
    496 
    497  private:
    498   // Stub accessors.
    499   static Handle<Code> initialize_stub() {
    500     return Isolate::Current()->builtins()->KeyedLoadIC_Initialize();
    501   }
    502   virtual Handle<Code> pre_monomorphic_stub() {
    503     return isolate()->builtins()->KeyedLoadIC_PreMonomorphic();
    504   }
    505   Handle<Code> indexed_interceptor_stub() {
    506     return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor();
    507   }
    508   Handle<Code> non_strict_arguments_stub() {
    509     return isolate()->builtins()->KeyedLoadIC_NonStrictArguments();
    510   }
    511   Handle<Code> string_stub() {
    512     return isolate()->builtins()->KeyedLoadIC_String();
    513   }
    514 
    515   static void Clear(Address address, Code* target);
    516 
    517   friend class IC;
    518 };
    519 
    520 
    521 class StoreIC: public IC {
    522  public:
    523   StoreIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) {
    524     ASSERT(target()->is_store_stub() || target()->is_keyed_store_stub());
    525   }
    526 
    527   // Code generators for stub routines. Only called once at startup.
    528   static void GenerateSlow(MacroAssembler* masm);
    529   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
    530   static void GenerateMiss(MacroAssembler* masm);
    531   static void GenerateMegamorphic(MacroAssembler* masm,
    532                                   StrictModeFlag strict_mode);
    533   static void GenerateNormal(MacroAssembler* masm);
    534   static void GenerateRuntimeSetProperty(MacroAssembler* masm,
    535                                          StrictModeFlag strict_mode);
    536 
    537   MUST_USE_RESULT MaybeObject* Store(
    538       State state,
    539       StrictModeFlag strict_mode,
    540       Handle<Object> object,
    541       Handle<String> name,
    542       Handle<Object> value,
    543       JSReceiver::StoreFromKeyed store_mode =
    544           JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED);
    545 
    546  protected:
    547   virtual Code::Kind kind() const { return Code::STORE_IC; }
    548   virtual Handle<Code> megamorphic_stub() {
    549     return isolate()->builtins()->StoreIC_Megamorphic();
    550   }
    551   // Stub accessors.
    552   virtual Handle<Code> megamorphic_stub_strict() {
    553     return isolate()->builtins()->StoreIC_Megamorphic_Strict();
    554   }
    555   virtual Handle<Code> generic_stub() const {
    556     return isolate()->builtins()->StoreIC_Generic();
    557   }
    558   virtual Handle<Code> generic_stub_strict() const {
    559     return isolate()->builtins()->StoreIC_Generic_Strict();
    560   }
    561   virtual Handle<Code> global_proxy_stub() {
    562     return isolate()->builtins()->StoreIC_GlobalProxy();
    563   }
    564   virtual Handle<Code> global_proxy_stub_strict() {
    565     return isolate()->builtins()->StoreIC_GlobalProxy_Strict();
    566   }
    567 
    568   virtual void UpdateMonomorphicIC(Handle<JSObject> receiver,
    569                                    Handle<Code> handler,
    570                                    Handle<String> name,
    571                                    StrictModeFlag strict_mode);
    572 
    573   virtual Handle<Code> ComputePolymorphicIC(MapHandleList* receiver_maps,
    574                                             CodeHandleList* handlers,
    575                                             int number_of_valid_maps,
    576                                             Handle<Name> name,
    577                                             StrictModeFlag strict_mode);
    578 
    579   // Update the inline cache and the global stub cache based on the
    580   // lookup result.
    581   void UpdateCaches(LookupResult* lookup,
    582                     State state,
    583                     StrictModeFlag strict_mode,
    584                     Handle<JSObject> receiver,
    585                     Handle<String> name,
    586                     Handle<Object> value);
    587   // Compute the code stub for this store; used for rewriting to
    588   // monomorphic state and making sure that the code stub is in the
    589   // stub cache.
    590   virtual Handle<Code> ComputeStoreMonomorphic(LookupResult* lookup,
    591                                                StrictModeFlag strict_mode,
    592                                                Handle<JSObject> receiver,
    593                                                Handle<String> name,
    594                                                Handle<Object> value);
    595 
    596  private:
    597   void set_target(Code* code) {
    598     // Strict mode must be preserved across IC patching.
    599     ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
    600            Code::GetStrictMode(target()->extra_ic_state()));
    601     IC::set_target(code);
    602   }
    603 
    604   static Handle<Code> initialize_stub() {
    605     return Isolate::Current()->builtins()->StoreIC_Initialize();
    606   }
    607   static Handle<Code> initialize_stub_strict() {
    608     return Isolate::Current()->builtins()->StoreIC_Initialize_Strict();
    609   }
    610   static void Clear(Address address, Code* target);
    611 
    612   friend class IC;
    613 };
    614 
    615 
    616 enum KeyedStoreCheckMap {
    617   kDontCheckMap,
    618   kCheckMap
    619 };
    620 
    621 
    622 enum KeyedStoreIncrementLength {
    623   kDontIncrementLength,
    624   kIncrementLength
    625 };
    626 
    627 
    628 class KeyedStoreIC: public StoreIC {
    629  public:
    630   KeyedStoreIC(FrameDepth depth, Isolate* isolate)
    631       : StoreIC(depth, isolate) {
    632     ASSERT(target()->is_keyed_store_stub());
    633   }
    634 
    635   MUST_USE_RESULT MaybeObject* Store(State state,
    636                                      StrictModeFlag strict_mode,
    637                                      Handle<Object> object,
    638                                      Handle<Object> name,
    639                                      Handle<Object> value,
    640                                      ICMissMode force_generic);
    641 
    642   // Code generators for stub routines.  Only called once at startup.
    643   static void GenerateInitialize(MacroAssembler* masm) {
    644     GenerateMiss(masm, MISS);
    645   }
    646   static void GenerateMiss(MacroAssembler* masm, ICMissMode force_generic);
    647   static void GenerateSlow(MacroAssembler* masm);
    648   static void GenerateRuntimeSetProperty(MacroAssembler* masm,
    649                                          StrictModeFlag strict_mode);
    650   static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
    651   static void GenerateNonStrictArguments(MacroAssembler* masm);
    652 
    653  protected:
    654   virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
    655 
    656   virtual Handle<Code> ComputeStoreMonomorphic(LookupResult* lookup,
    657                                                StrictModeFlag strict_mode,
    658                                                Handle<JSObject> receiver,
    659                                                Handle<String> name,
    660                                                Handle<Object> value);
    661   virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code) { }
    662 
    663   virtual Handle<Code> megamorphic_stub() {
    664     return isolate()->builtins()->KeyedStoreIC_Generic();
    665   }
    666   virtual Handle<Code> megamorphic_stub_strict() {
    667     return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
    668   }
    669 
    670   Handle<Code> StoreElementStub(Handle<JSObject> receiver,
    671                                 KeyedAccessStoreMode store_mode,
    672                                 StrictModeFlag strict_mode);
    673 
    674   virtual void UpdateMonomorphicIC(Handle<JSObject> receiver,
    675                                    Handle<Code> handler,
    676                                    Handle<String> name,
    677                                    StrictModeFlag strict_mode);
    678 
    679  private:
    680   void set_target(Code* code) {
    681     // Strict mode must be preserved across IC patching.
    682     ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
    683            Code::GetStrictMode(target()->extra_ic_state()));
    684     IC::set_target(code);
    685   }
    686 
    687   // Stub accessors.
    688   static Handle<Code> initialize_stub() {
    689     return Isolate::Current()->builtins()->KeyedStoreIC_Initialize();
    690   }
    691   static Handle<Code> initialize_stub_strict() {
    692     return Isolate::Current()->builtins()->KeyedStoreIC_Initialize_Strict();
    693   }
    694   Handle<Code> generic_stub() const {
    695     return isolate()->builtins()->KeyedStoreIC_Generic();
    696   }
    697   Handle<Code> generic_stub_strict() const {
    698     return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
    699   }
    700   Handle<Code> non_strict_arguments_stub() {
    701     return isolate()->builtins()->KeyedStoreIC_NonStrictArguments();
    702   }
    703 
    704   static void Clear(Address address, Code* target);
    705 
    706   KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
    707                                     Handle<Object> key,
    708                                     Handle<Object> value);
    709 
    710   Handle<Map> ComputeTransitionedMap(Handle<JSObject> receiver,
    711                                      KeyedAccessStoreMode store_mode);
    712 
    713   friend class IC;
    714 };
    715 
    716 
    717 // Type Recording BinaryOpIC, that records the types of the inputs and outputs.
    718 class BinaryOpIC: public IC {
    719  public:
    720   enum TypeInfo {
    721     UNINITIALIZED,
    722     SMI,
    723     INT32,
    724     NUMBER,
    725     ODDBALL,
    726     STRING,  // Only used for addition operation.
    727     GENERIC
    728   };
    729 
    730   static void StubInfoToType(int minor_key,
    731                              Handle<Type>* left,
    732                              Handle<Type>* right,
    733                              Handle<Type>* result,
    734                              Isolate* isolate);
    735 
    736   explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
    737 
    738   void patch(Code* code);
    739 
    740   static const char* GetName(TypeInfo type_info);
    741 
    742   static State ToState(TypeInfo type_info);
    743 
    744  private:
    745   static Handle<Type> TypeInfoToType(TypeInfo binary_type, Isolate* isolate);
    746 };
    747 
    748 
    749 class CompareIC: public IC {
    750  public:
    751   // The type/state lattice is defined by the following inequations:
    752   //   UNINITIALIZED < ...
    753   //   ... < GENERIC
    754   //   SMI < NUMBER
    755   //   INTERNALIZED_STRING < STRING
    756   //   KNOWN_OBJECT < OBJECT
    757   enum State {
    758     UNINITIALIZED,
    759     SMI,
    760     NUMBER,
    761     STRING,
    762     INTERNALIZED_STRING,
    763     UNIQUE_NAME,    // Symbol or InternalizedString
    764     OBJECT,         // JSObject
    765     KNOWN_OBJECT,   // JSObject with specific map (faster check)
    766     GENERIC
    767   };
    768 
    769   static State NewInputState(State old_state, Handle<Object> value);
    770 
    771   static Handle<Type> StateToType(Isolate* isolate,
    772                                   State state,
    773                                   Handle<Map> map = Handle<Map>());
    774 
    775   static void StubInfoToType(int stub_minor_key,
    776                              Handle<Type>* left_type,
    777                              Handle<Type>* right_type,
    778                              Handle<Type>* overall_type,
    779                              Handle<Map> map,
    780                              Isolate* isolate);
    781 
    782   CompareIC(Isolate* isolate, Token::Value op)
    783       : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
    784 
    785   // Update the inline cache for the given operands.
    786   void UpdateCaches(Handle<Object> x, Handle<Object> y);
    787 
    788 
    789   // Factory method for getting an uninitialized compare stub.
    790   static Handle<Code> GetUninitialized(Isolate* isolate, Token::Value op);
    791 
    792   // Helper function for computing the condition for a compare operation.
    793   static Condition ComputeCondition(Token::Value op);
    794 
    795   static const char* GetStateName(State state);
    796 
    797  private:
    798   static bool HasInlinedSmiCode(Address address);
    799 
    800   State TargetState(State old_state,
    801                     State old_left,
    802                     State old_right,
    803                     bool has_inlined_smi_code,
    804                     Handle<Object> x,
    805                     Handle<Object> y);
    806 
    807   bool strict() const { return op_ == Token::EQ_STRICT; }
    808   Condition GetCondition() const { return ComputeCondition(op_); }
    809 
    810   static Code* GetRawUninitialized(Token::Value op);
    811 
    812   static void Clear(Address address, Code* target);
    813 
    814   Token::Value op_;
    815 
    816   friend class IC;
    817 };
    818 
    819 
    820 class CompareNilIC: public IC {
    821  public:
    822   explicit CompareNilIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {}
    823 
    824   MUST_USE_RESULT MaybeObject* CompareNil(Handle<Object> object);
    825 
    826   static Handle<Code> GetUninitialized();
    827 
    828   static void Clear(Address address, Code* target);
    829 
    830   static MUST_USE_RESULT MaybeObject* DoCompareNilSlow(NilValue nil,
    831                                                        Handle<Object> object);
    832 };
    833 
    834 
    835 class ToBooleanIC: public IC {
    836  public:
    837   explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { }
    838 
    839   MaybeObject* ToBoolean(Handle<Object> object, Code::ExtraICState state);
    840 };
    841 
    842 
    843 // Helper for BinaryOpIC and CompareIC.
    844 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
    845 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check);
    846 
    847 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure);
    848 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure);
    849 DECLARE_RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss);
    850 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure);
    851 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss);
    852 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss);
    853 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss);
    854 
    855 
    856 } }  // namespace v8::internal
    857 
    858 #endif  // V8_IC_H_
    859