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 "macro-assembler.h"
     32 
     33 namespace v8 {
     34 namespace internal {
     35 
     36 
     37 // IC_UTIL_LIST defines all utility functions called from generated
     38 // inline caching code. The argument for the macro, ICU, is the function name.
     39 #define IC_UTIL_LIST(ICU)                             \
     40   ICU(LoadIC_Miss)                                    \
     41   ICU(KeyedLoadIC_Miss)                               \
     42   ICU(CallIC_Miss)                                    \
     43   ICU(KeyedCallIC_Miss)                               \
     44   ICU(StoreIC_Miss)                                   \
     45   ICU(StoreIC_ArrayLength)                            \
     46   ICU(SharedStoreIC_ExtendStorage)                    \
     47   ICU(KeyedStoreIC_Miss)                              \
     48   /* Utilities for IC stubs. */                       \
     49   ICU(LoadCallbackProperty)                           \
     50   ICU(StoreCallbackProperty)                          \
     51   ICU(LoadPropertyWithInterceptorOnly)                \
     52   ICU(LoadPropertyWithInterceptorForLoad)             \
     53   ICU(LoadPropertyWithInterceptorForCall)             \
     54   ICU(KeyedLoadPropertyWithInterceptor)               \
     55   ICU(StoreInterceptorProperty)                       \
     56   ICU(TypeRecordingBinaryOp_Patch)                    \
     57   ICU(CompareIC_Miss)
     58 //
     59 // IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
     60 // and KeyedStoreIC.
     61 //
     62 class IC {
     63  public:
     64 
     65   // The ids for utility called from the generated code.
     66   enum UtilityId {
     67   #define CONST_NAME(name) k##name,
     68     IC_UTIL_LIST(CONST_NAME)
     69   #undef CONST_NAME
     70     kUtilityCount
     71   };
     72 
     73   // Looks up the address of the named utility.
     74   static Address AddressFromUtilityId(UtilityId id);
     75 
     76   // Alias the inline cache state type to make the IC code more readable.
     77   typedef InlineCacheState State;
     78 
     79   // The IC code is either invoked with no extra frames on the stack
     80   // or with a single extra frame for supporting calls.
     81   enum FrameDepth {
     82     NO_EXTRA_FRAME = 0,
     83     EXTRA_CALL_FRAME = 1
     84   };
     85 
     86   // Construct the IC structure with the given number of extra
     87   // JavaScript frames on the stack.
     88   IC(FrameDepth depth, Isolate* isolate);
     89 
     90   // Get the call-site target; used for determining the state.
     91   Code* target() { return GetTargetAtAddress(address()); }
     92   inline Address address();
     93 
     94   // Compute the current IC state based on the target stub, receiver and name.
     95   static State StateFrom(Code* target, Object* receiver, Object* name);
     96 
     97   // Clear the inline cache to initial state.
     98   static void Clear(Address address);
     99 
    100   // Computes the reloc info for this IC. This is a fairly expensive
    101   // operation as it has to search through the heap to find the code
    102   // object that contains this IC site.
    103   RelocInfo::Mode ComputeMode();
    104 
    105   // Returns if this IC is for contextual (no explicit receiver)
    106   // access to properties.
    107   bool IsContextual(Handle<Object> receiver) {
    108     if (receiver->IsGlobalObject()) {
    109       return SlowIsContextual();
    110     } else {
    111       ASSERT(!SlowIsContextual());
    112       return false;
    113     }
    114   }
    115 
    116   bool SlowIsContextual() {
    117     return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
    118   }
    119 
    120   // Determines which map must be used for keeping the code stub.
    121   // These methods should not be called with undefined or null.
    122   static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object,
    123                                                             JSObject* holder);
    124   static inline InlineCacheHolderFlag GetCodeCacheForObject(JSObject* object,
    125                                                             JSObject* holder);
    126   static inline JSObject* GetCodeCacheHolder(Object* object,
    127                                              InlineCacheHolderFlag holder);
    128 
    129  protected:
    130   Address fp() const { return fp_; }
    131   Address pc() const { return *pc_address_; }
    132   Isolate* isolate() const { return isolate_; }
    133 
    134 #ifdef ENABLE_DEBUGGER_SUPPORT
    135   // Computes the address in the original code when the code running is
    136   // containing break points (calls to DebugBreakXXX builtins).
    137   Address OriginalCodeAddress();
    138 #endif
    139 
    140   // Set the call-site target.
    141   void set_target(Code* code) { SetTargetAtAddress(address(), code); }
    142 
    143 #ifdef DEBUG
    144   static void TraceIC(const char* type,
    145                       Handle<Object> name,
    146                       State old_state,
    147                       Code* new_target,
    148                       const char* extra_info = "");
    149 #endif
    150 
    151   Failure* TypeError(const char* type,
    152                      Handle<Object> object,
    153                      Handle<Object> key);
    154   Failure* ReferenceError(const char* type, Handle<String> name);
    155 
    156   // Access the target code for the given IC address.
    157   static inline Code* GetTargetAtAddress(Address address);
    158   static inline void SetTargetAtAddress(Address address, Code* target);
    159 
    160  private:
    161   // Frame pointer for the frame that uses (calls) the IC.
    162   Address fp_;
    163 
    164   // All access to the program counter of an IC structure is indirect
    165   // to make the code GC safe. This feature is crucial since
    166   // GetProperty and SetProperty are called and they in turn might
    167   // invoke the garbage collector.
    168   Address* pc_address_;
    169 
    170   Isolate* isolate_;
    171 
    172   DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
    173 };
    174 
    175 
    176 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
    177 // cannot make forward declarations to an enum.
    178 class IC_Utility {
    179  public:
    180   explicit IC_Utility(IC::UtilityId id)
    181     : address_(IC::AddressFromUtilityId(id)), id_(id) {}
    182 
    183   Address address() const { return address_; }
    184 
    185   IC::UtilityId id() const { return id_; }
    186  private:
    187   Address address_;
    188   IC::UtilityId id_;
    189 };
    190 
    191 
    192 class CallICBase: public IC {
    193  protected:
    194   CallICBase(Code::Kind kind, Isolate* isolate)
    195       : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
    196 
    197  public:
    198   MUST_USE_RESULT MaybeObject* LoadFunction(State state,
    199                                             Code::ExtraICState extra_ic_state,
    200                                             Handle<Object> object,
    201                                             Handle<String> name);
    202 
    203  protected:
    204   Code::Kind kind_;
    205 
    206   bool TryUpdateExtraICState(LookupResult* lookup,
    207                              Handle<Object> object,
    208                              Code::ExtraICState* extra_ic_state);
    209 
    210   MUST_USE_RESULT MaybeObject* ComputeMonomorphicStub(
    211       LookupResult* lookup,
    212       State state,
    213       Code::ExtraICState extra_ic_state,
    214       Handle<Object> object,
    215       Handle<String> name);
    216 
    217   // Update the inline cache and the global stub cache based on the
    218   // lookup result.
    219   void UpdateCaches(LookupResult* lookup,
    220                     State state,
    221                     Code::ExtraICState extra_ic_state,
    222                     Handle<Object> object,
    223                     Handle<String> name);
    224 
    225   // Returns a JSFunction if the object can be called as a function,
    226   // and patches the stack to be ready for the call.
    227   // Otherwise, it returns the undefined value.
    228   Object* TryCallAsFunction(Object* object);
    229 
    230   void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
    231 
    232   static void Clear(Address address, Code* target);
    233   friend class IC;
    234 };
    235 
    236 
    237 class CallIC: public CallICBase {
    238  public:
    239   explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) {
    240     ASSERT(target()->is_call_stub());
    241   }
    242 
    243   // Code generator routines.
    244   static void GenerateInitialize(MacroAssembler* masm, int argc) {
    245     GenerateMiss(masm, argc);
    246   }
    247   static void GenerateMiss(MacroAssembler* masm, int argc);
    248   static void GenerateMegamorphic(MacroAssembler* masm, int argc);
    249   static void GenerateNormal(MacroAssembler* masm, int argc);
    250 };
    251 
    252 
    253 class KeyedCallIC: public CallICBase {
    254  public:
    255   explicit KeyedCallIC(Isolate* isolate)
    256       : CallICBase(Code::KEYED_CALL_IC, isolate) {
    257     ASSERT(target()->is_keyed_call_stub());
    258   }
    259 
    260   MUST_USE_RESULT MaybeObject* LoadFunction(State state,
    261                                             Handle<Object> object,
    262                                             Handle<Object> key);
    263 
    264   // Code generator routines.
    265   static void GenerateInitialize(MacroAssembler* masm, int argc) {
    266     GenerateMiss(masm, argc);
    267   }
    268   static void GenerateMiss(MacroAssembler* masm, int argc);
    269   static void GenerateMegamorphic(MacroAssembler* masm, int argc);
    270   static void GenerateNormal(MacroAssembler* masm, int argc);
    271 };
    272 
    273 
    274 class LoadIC: public IC {
    275  public:
    276   explicit LoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
    277     ASSERT(target()->is_load_stub());
    278   }
    279 
    280   MUST_USE_RESULT MaybeObject* Load(State state,
    281                                     Handle<Object> object,
    282                                     Handle<String> name);
    283 
    284   // Code generator routines.
    285   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
    286   static void GeneratePreMonomorphic(MacroAssembler* masm) {
    287     GenerateMiss(masm);
    288   }
    289   static void GenerateMiss(MacroAssembler* masm);
    290   static void GenerateMegamorphic(MacroAssembler* masm);
    291   static void GenerateNormal(MacroAssembler* masm);
    292 
    293   // Specialized code generator routines.
    294   static void GenerateArrayLength(MacroAssembler* masm);
    295   static void GenerateStringLength(MacroAssembler* masm,
    296                                    bool support_wrappers);
    297   static void GenerateFunctionPrototype(MacroAssembler* masm);
    298 
    299   // Clear the use of the inlined version.
    300   static void ClearInlinedVersion(Address address);
    301 
    302   // The offset from the inlined patch site to the start of the
    303   // inlined load instruction.  It is architecture-dependent, and not
    304   // used on ARM.
    305   static const int kOffsetToLoadInstruction;
    306 
    307  private:
    308   // Update the inline cache and the global stub cache based on the
    309   // lookup result.
    310   void UpdateCaches(LookupResult* lookup,
    311                     State state,
    312                     Handle<Object> object,
    313                     Handle<String> name);
    314 
    315   // Stub accessors.
    316   Code* megamorphic_stub() {
    317     return isolate()->builtins()->builtin(
    318         Builtins::kLoadIC_Megamorphic);
    319   }
    320   static Code* initialize_stub() {
    321     return Isolate::Current()->builtins()->builtin(
    322         Builtins::kLoadIC_Initialize);
    323   }
    324   Code* pre_monomorphic_stub() {
    325     return isolate()->builtins()->builtin(
    326         Builtins::kLoadIC_PreMonomorphic);
    327   }
    328 
    329   static void Clear(Address address, Code* target);
    330 
    331   static bool PatchInlinedLoad(Address address, Object* map, int index);
    332 
    333   static bool PatchInlinedContextualLoad(Address address,
    334                                          Object* map,
    335                                          Object* cell,
    336                                          bool is_dont_delete);
    337 
    338   friend class IC;
    339 };
    340 
    341 
    342 class KeyedLoadIC: public IC {
    343  public:
    344   explicit KeyedLoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
    345     ASSERT(target()->is_keyed_load_stub());
    346   }
    347 
    348   MUST_USE_RESULT MaybeObject* Load(State state,
    349                                     Handle<Object> object,
    350                                     Handle<Object> key);
    351 
    352   // Code generator routines.
    353   static void GenerateMiss(MacroAssembler* masm);
    354   static void GenerateRuntimeGetProperty(MacroAssembler* masm);
    355   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
    356   static void GeneratePreMonomorphic(MacroAssembler* masm) {
    357     GenerateMiss(masm);
    358   }
    359   static void GenerateGeneric(MacroAssembler* masm);
    360   static void GenerateString(MacroAssembler* masm);
    361 
    362   static void GenerateIndexedInterceptor(MacroAssembler* masm);
    363 
    364   // Clear the use of the inlined version.
    365   static void ClearInlinedVersion(Address address);
    366 
    367   // Bit mask to be tested against bit field for the cases when
    368   // generic stub should go into slow case.
    369   // Access check is necessary explicitly since generic stub does not perform
    370   // map checks.
    371   static const int kSlowCaseBitFieldMask =
    372       (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
    373 
    374  private:
    375   // Update the inline cache.
    376   void UpdateCaches(LookupResult* lookup,
    377                     State state,
    378                     Handle<Object> object,
    379                     Handle<String> name);
    380 
    381   // Stub accessors.
    382   static Code* initialize_stub() {
    383     return Isolate::Current()->builtins()->builtin(
    384         Builtins::kKeyedLoadIC_Initialize);
    385   }
    386   Code* megamorphic_stub() {
    387     return isolate()->builtins()->builtin(
    388         Builtins::kKeyedLoadIC_Generic);
    389   }
    390   Code* generic_stub() {
    391     return isolate()->builtins()->builtin(
    392         Builtins::kKeyedLoadIC_Generic);
    393   }
    394   Code* pre_monomorphic_stub() {
    395     return isolate()->builtins()->builtin(
    396         Builtins::kKeyedLoadIC_PreMonomorphic);
    397   }
    398   Code* string_stub() {
    399     return isolate()->builtins()->builtin(
    400         Builtins::kKeyedLoadIC_String);
    401   }
    402 
    403   Code* indexed_interceptor_stub() {
    404     return isolate()->builtins()->builtin(
    405         Builtins::kKeyedLoadIC_IndexedInterceptor);
    406   }
    407 
    408   static void Clear(Address address, Code* target);
    409 
    410   // Support for patching the map that is checked in an inlined
    411   // version of keyed load.
    412   static bool PatchInlinedLoad(Address address, Object* map);
    413 
    414   friend class IC;
    415 };
    416 
    417 
    418 class StoreIC: public IC {
    419  public:
    420   explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
    421     ASSERT(target()->is_store_stub());
    422   }
    423 
    424   MUST_USE_RESULT MaybeObject* Store(State state,
    425                                      StrictModeFlag strict_mode,
    426                                      Handle<Object> object,
    427                                      Handle<String> name,
    428                                      Handle<Object> value);
    429 
    430   // Code generators for stub routines. Only called once at startup.
    431   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
    432   static void GenerateMiss(MacroAssembler* masm);
    433   static void GenerateMegamorphic(MacroAssembler* masm,
    434                                   StrictModeFlag strict_mode);
    435   static void GenerateArrayLength(MacroAssembler* masm);
    436   static void GenerateNormal(MacroAssembler* masm);
    437   static void GenerateGlobalProxy(MacroAssembler* masm,
    438                                   StrictModeFlag strict_mode);
    439 
    440   // Clear the use of an inlined version.
    441   static void ClearInlinedVersion(Address address);
    442 
    443   // The offset from the inlined patch site to the start of the
    444   // inlined store instruction.
    445   static const int kOffsetToStoreInstruction;
    446 
    447  private:
    448   // Update the inline cache and the global stub cache based on the
    449   // lookup result.
    450   void UpdateCaches(LookupResult* lookup,
    451                     State state,
    452                     StrictModeFlag strict_mode,
    453                     Handle<JSObject> receiver,
    454                     Handle<String> name,
    455                     Handle<Object> value);
    456 
    457   void set_target(Code* code) {
    458     // Strict mode must be preserved across IC patching.
    459     ASSERT((code->extra_ic_state() & kStrictMode) ==
    460            (target()->extra_ic_state() & kStrictMode));
    461     IC::set_target(code);
    462   }
    463 
    464   // Stub accessors.
    465   Code* megamorphic_stub() {
    466     return isolate()->builtins()->builtin(
    467         Builtins::kStoreIC_Megamorphic);
    468   }
    469   Code* megamorphic_stub_strict() {
    470     return isolate()->builtins()->builtin(
    471         Builtins::kStoreIC_Megamorphic_Strict);
    472   }
    473   static Code* initialize_stub() {
    474     return Isolate::Current()->builtins()->builtin(
    475         Builtins::kStoreIC_Initialize);
    476   }
    477   static Code* initialize_stub_strict() {
    478     return Isolate::Current()->builtins()->builtin(
    479         Builtins::kStoreIC_Initialize_Strict);
    480   }
    481   Code* global_proxy_stub() {
    482     return isolate()->builtins()->builtin(
    483         Builtins::kStoreIC_GlobalProxy);
    484   }
    485   Code* global_proxy_stub_strict() {
    486     return isolate()->builtins()->builtin(
    487         Builtins::kStoreIC_GlobalProxy_Strict);
    488   }
    489 
    490   static void Clear(Address address, Code* target);
    491 
    492   // Support for patching the index and the map that is checked in an
    493   // inlined version of the named store.
    494   static bool PatchInlinedStore(Address address, Object* map, int index);
    495 
    496   friend class IC;
    497 };
    498 
    499 
    500 class KeyedStoreIC: public IC {
    501  public:
    502   explicit KeyedStoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
    503 
    504   MUST_USE_RESULT MaybeObject* Store(State state,
    505                                      StrictModeFlag strict_mode,
    506                                      Handle<Object> object,
    507                                      Handle<Object> name,
    508                                      Handle<Object> value);
    509 
    510   // Code generators for stub routines.  Only called once at startup.
    511   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
    512   static void GenerateMiss(MacroAssembler* masm);
    513   static void GenerateRuntimeSetProperty(MacroAssembler* masm,
    514                                          StrictModeFlag strict_mode);
    515   static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
    516 
    517   // Clear the inlined version so the IC is always hit.
    518   static void ClearInlinedVersion(Address address);
    519 
    520   // Restore the inlined version so the fast case can get hit.
    521   static void RestoreInlinedVersion(Address address);
    522 
    523  private:
    524   // Update the inline cache.
    525   void UpdateCaches(LookupResult* lookup,
    526                     State state,
    527                     StrictModeFlag strict_mode,
    528                     Handle<JSObject> receiver,
    529                     Handle<String> name,
    530                     Handle<Object> value);
    531 
    532   void set_target(Code* code) {
    533     // Strict mode must be preserved across IC patching.
    534     ASSERT((code->extra_ic_state() & kStrictMode) ==
    535            (target()->extra_ic_state() & kStrictMode));
    536     IC::set_target(code);
    537   }
    538 
    539   // Stub accessors.
    540   static Code* initialize_stub() {
    541     return Isolate::Current()->builtins()->builtin(
    542         Builtins::kKeyedStoreIC_Initialize);
    543   }
    544   Code* megamorphic_stub() {
    545     return isolate()->builtins()->builtin(
    546         Builtins::kKeyedStoreIC_Generic);
    547   }
    548   static Code* initialize_stub_strict() {
    549     return Isolate::Current()->builtins()->builtin(
    550         Builtins::kKeyedStoreIC_Initialize_Strict);
    551   }
    552   Code* megamorphic_stub_strict() {
    553     return isolate()->builtins()->builtin(
    554         Builtins::kKeyedStoreIC_Generic_Strict);
    555   }
    556   Code* generic_stub() {
    557     return isolate()->builtins()->builtin(
    558         Builtins::kKeyedStoreIC_Generic);
    559   }
    560   Code* generic_stub_strict() {
    561     return isolate()->builtins()->builtin(
    562         Builtins::kKeyedStoreIC_Generic_Strict);
    563   }
    564 
    565   static void Clear(Address address, Code* target);
    566 
    567   // Support for patching the map that is checked in an inlined
    568   // version of keyed store.
    569   // The address is the patch point for the IC call
    570   // (Assembler::kCallTargetAddressOffset before the end of
    571   // the call/return address).
    572   // The map is the new map that the inlined code should check against.
    573   static bool PatchInlinedStore(Address address, Object* map);
    574 
    575   friend class IC;
    576 };
    577 
    578 
    579 // Type Recording BinaryOpIC, that records the types of the inputs and outputs.
    580 class TRBinaryOpIC: public IC {
    581  public:
    582 
    583   enum TypeInfo {
    584     UNINITIALIZED,
    585     SMI,
    586     INT32,
    587     HEAP_NUMBER,
    588     ODDBALL,
    589     STRING,  // Only used for addition operation.  At least one string operand.
    590     GENERIC
    591   };
    592 
    593   explicit TRBinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
    594 
    595   void patch(Code* code);
    596 
    597   static const char* GetName(TypeInfo type_info);
    598 
    599   static State ToState(TypeInfo type_info);
    600 
    601   static TypeInfo GetTypeInfo(Handle<Object> left, Handle<Object> right);
    602 
    603   static TypeInfo JoinTypes(TypeInfo x, TypeInfo y);
    604 };
    605 
    606 
    607 class CompareIC: public IC {
    608  public:
    609   enum State {
    610     UNINITIALIZED,
    611     SMIS,
    612     HEAP_NUMBERS,
    613     OBJECTS,
    614     GENERIC
    615   };
    616 
    617   CompareIC(Isolate* isolate, Token::Value op)
    618       : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
    619 
    620   // Update the inline cache for the given operands.
    621   void UpdateCaches(Handle<Object> x, Handle<Object> y);
    622 
    623   // Factory method for getting an uninitialized compare stub.
    624   static Handle<Code> GetUninitialized(Token::Value op);
    625 
    626   // Helper function for computing the condition for a compare operation.
    627   static Condition ComputeCondition(Token::Value op);
    628 
    629   // Helper function for determining the state of a compare IC.
    630   static State ComputeState(Code* target);
    631 
    632   static const char* GetStateName(State state);
    633 
    634  private:
    635   State TargetState(State state, bool has_inlined_smi_code,
    636                     Handle<Object> x, Handle<Object> y);
    637 
    638   bool strict() const { return op_ == Token::EQ_STRICT; }
    639   Condition GetCondition() const { return ComputeCondition(op_); }
    640   State GetState() { return ComputeState(target()); }
    641 
    642   Token::Value op_;
    643 };
    644 
    645 // Helper for TRBinaryOpIC and CompareIC.
    646 void PatchInlinedSmiCode(Address address);
    647 
    648 } }  // namespace v8::internal
    649 
    650 #endif  // V8_IC_H_
    651