Home | History | Annotate | Download | only in ic
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_IC_STATE_H_
      6 #define V8_IC_STATE_H_
      7 
      8 #include "src/macro-assembler.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 
     13 
     14 const int kMaxKeyedPolymorphism = 4;
     15 
     16 
     17 class ICUtility : public AllStatic {
     18  public:
     19   // Clear the inline cache to initial state.
     20   static void Clear(Isolate* isolate, Address address, Address constant_pool);
     21 };
     22 
     23 
     24 class CallICState final BASE_EMBEDDED {
     25  public:
     26   explicit CallICState(ExtraICState extra_ic_state)
     27       : bit_field_(extra_ic_state) {}
     28   CallICState(int argc, ConvertReceiverMode convert_mode,
     29               TailCallMode tail_call_mode)
     30       : bit_field_(ArgcBits::encode(argc) |
     31                    ConvertModeBits::encode(convert_mode) |
     32                    TailCallModeBits::encode(tail_call_mode)) {}
     33 
     34   ExtraICState GetExtraICState() const { return bit_field_; }
     35 
     36   static void GenerateAheadOfTime(Isolate*,
     37                                   void (*Generate)(Isolate*,
     38                                                    const CallICState&));
     39 
     40   int argc() const { return ArgcBits::decode(bit_field_); }
     41   ConvertReceiverMode convert_mode() const {
     42     return ConvertModeBits::decode(bit_field_);
     43   }
     44   TailCallMode tail_call_mode() const {
     45     return TailCallModeBits::decode(bit_field_);
     46   }
     47 
     48  private:
     49   typedef BitField<int, 0, Code::kArgumentsBits> ArgcBits;
     50   typedef BitField<ConvertReceiverMode, ArgcBits::kNext, 2> ConvertModeBits;
     51   typedef BitField<TailCallMode, ConvertModeBits::kNext, 1> TailCallModeBits;
     52 
     53   int const bit_field_;
     54 };
     55 
     56 
     57 std::ostream& operator<<(std::ostream& os, const CallICState& s);
     58 
     59 
     60 class BinaryOpICState final BASE_EMBEDDED {
     61  public:
     62   BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state);
     63   BinaryOpICState(Isolate* isolate, Token::Value op)
     64       : op_(op),
     65         left_kind_(NONE),
     66         right_kind_(NONE),
     67         result_kind_(NONE),
     68         fixed_right_arg_(Nothing<int>()),
     69         isolate_(isolate) {
     70     DCHECK_LE(FIRST_TOKEN, op);
     71     DCHECK_LE(op, LAST_TOKEN);
     72   }
     73 
     74   InlineCacheState GetICState() const {
     75     if (Max(left_kind_, right_kind_) == NONE) {
     76       return ::v8::internal::UNINITIALIZED;
     77     }
     78     if (Max(left_kind_, right_kind_) == GENERIC) {
     79       return ::v8::internal::MEGAMORPHIC;
     80     }
     81     if (Min(left_kind_, right_kind_) == GENERIC) {
     82       return ::v8::internal::GENERIC;
     83     }
     84     return ::v8::internal::MONOMORPHIC;
     85   }
     86 
     87   ExtraICState GetExtraICState() const;
     88 
     89   static void GenerateAheadOfTime(Isolate*,
     90                                   void (*Generate)(Isolate*,
     91                                                    const BinaryOpICState&));
     92 
     93   // Returns true if the IC _could_ create allocation mementos.
     94   bool CouldCreateAllocationMementos() const {
     95     if (left_kind_ == STRING || right_kind_ == STRING) {
     96       DCHECK_EQ(Token::ADD, op_);
     97       return true;
     98     }
     99     return false;
    100   }
    101 
    102   // Returns true if the IC _should_ create allocation mementos.
    103   bool ShouldCreateAllocationMementos() const {
    104     return FLAG_allocation_site_pretenuring && CouldCreateAllocationMementos();
    105   }
    106 
    107   bool HasSideEffects() const {
    108     return Max(left_kind_, right_kind_) == GENERIC;
    109   }
    110 
    111   // Returns true if the IC should enable the inline smi code (i.e. if either
    112   // parameter may be a smi).
    113   bool UseInlinedSmiCode() const {
    114     return KindMaybeSmi(left_kind_) || KindMaybeSmi(right_kind_);
    115   }
    116 
    117   static const int FIRST_TOKEN = Token::BIT_OR;
    118   static const int LAST_TOKEN = Token::MOD;
    119 
    120   Token::Value op() const { return op_; }
    121   Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
    122 
    123   Type* GetLeftType() const { return KindToType(left_kind_); }
    124   Type* GetRightType() const { return KindToType(right_kind_); }
    125   Type* GetResultType() const;
    126 
    127   void Update(Handle<Object> left, Handle<Object> right, Handle<Object> result);
    128 
    129   Isolate* isolate() const { return isolate_; }
    130 
    131  private:
    132   friend std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s);
    133 
    134   enum Kind { NONE, SMI, INT32, NUMBER, STRING, GENERIC };
    135 
    136   Kind UpdateKind(Handle<Object> object, Kind kind) const;
    137 
    138   static const char* KindToString(Kind kind);
    139   static Type* KindToType(Kind kind);
    140   static bool KindMaybeSmi(Kind kind) {
    141     return (kind >= SMI && kind <= NUMBER) || kind == GENERIC;
    142   }
    143 
    144   // We truncate the last bit of the token.
    145   STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 4));
    146   class OpField : public BitField<int, 0, 4> {};
    147   class ResultKindField : public BitField<Kind, 4, 3> {};
    148   class LeftKindField : public BitField<Kind, 7, 3> {};
    149   // When fixed right arg is set, we don't need to store the right kind.
    150   // Thus the two fields can overlap.
    151   class HasFixedRightArgField : public BitField<bool, 10, 1> {};
    152   class FixedRightArgValueField : public BitField<int, 11, 4> {};
    153   class RightKindField : public BitField<Kind, 11, 3> {};
    154 
    155   Token::Value op_;
    156   Kind left_kind_;
    157   Kind right_kind_;
    158   Kind result_kind_;
    159   Maybe<int> fixed_right_arg_;
    160   Isolate* isolate_;
    161 };
    162 
    163 
    164 std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s);
    165 
    166 
    167 class CompareICState {
    168  public:
    169   // The type/state lattice is defined by the following inequations:
    170   //   UNINITIALIZED < ...
    171   //   ... < GENERIC
    172   //   SMI < NUMBER
    173   //   INTERNALIZED_STRING < STRING
    174   //   INTERNALIZED_STRING < UNIQUE_NAME
    175   //   KNOWN_RECEIVER < RECEIVER
    176   enum State {
    177     UNINITIALIZED,
    178     BOOLEAN,
    179     SMI,
    180     NUMBER,
    181     STRING,
    182     INTERNALIZED_STRING,
    183     UNIQUE_NAME,     // Symbol or InternalizedString
    184     RECEIVER,        // JSReceiver
    185     KNOWN_RECEIVER,  // JSReceiver with specific map (faster check)
    186     GENERIC
    187   };
    188 
    189   static Type* StateToType(Zone* zone, State state,
    190                            Handle<Map> map = Handle<Map>());
    191 
    192   static State NewInputState(State old_state, Handle<Object> value);
    193 
    194   static const char* GetStateName(CompareICState::State state);
    195 
    196   static State TargetState(Isolate* isolate, State old_state, State old_left,
    197                            State old_right, Token::Value op,
    198                            bool has_inlined_smi_code, Handle<Object> x,
    199                            Handle<Object> y);
    200 };
    201 
    202 class LoadGlobalICState final BASE_EMBEDDED {
    203  private:
    204   class TypeofModeBits : public BitField<TypeofMode, 0, 1> {};
    205   STATIC_ASSERT(static_cast<int>(INSIDE_TYPEOF) == 0);
    206   const ExtraICState state_;
    207 
    208  public:
    209   static const uint32_t kNextBitFieldOffset = TypeofModeBits::kNext;
    210 
    211   explicit LoadGlobalICState(ExtraICState extra_ic_state)
    212       : state_(extra_ic_state) {}
    213 
    214   explicit LoadGlobalICState(TypeofMode typeof_mode)
    215       : state_(TypeofModeBits::encode(typeof_mode)) {}
    216 
    217   ExtraICState GetExtraICState() const { return state_; }
    218 
    219   TypeofMode typeof_mode() const { return TypeofModeBits::decode(state_); }
    220 
    221   static TypeofMode GetTypeofMode(ExtraICState state) {
    222     return LoadGlobalICState(state).typeof_mode();
    223   }
    224 };
    225 
    226 
    227 class StoreICState final BASE_EMBEDDED {
    228  public:
    229   explicit StoreICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {}
    230 
    231   explicit StoreICState(LanguageMode mode)
    232       : state_(LanguageModeState::encode(mode)) {}
    233 
    234   ExtraICState GetExtraICState() const { return state_; }
    235 
    236   LanguageMode language_mode() const {
    237     return LanguageModeState::decode(state_);
    238   }
    239 
    240   static LanguageMode GetLanguageMode(ExtraICState state) {
    241     return StoreICState(state).language_mode();
    242   }
    243 
    244   class LanguageModeState : public BitField<LanguageMode, 1, 2> {};
    245   STATIC_ASSERT(i::LANGUAGE_END == 3);
    246 
    247   // For convenience, a statically declared encoding of strict mode extra
    248   // IC state.
    249   static const ExtraICState kStrictModeState = STRICT
    250                                                << LanguageModeState::kShift;
    251 
    252  private:
    253   const ExtraICState state_;
    254 };
    255 
    256 }  // namespace internal
    257 }  // namespace v8
    258 
    259 #endif  // V8_IC_STATE_H_
    260