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       : bit_field_(ArgcBits::encode(argc) |
     30                    ConvertModeBits::encode(convert_mode)) {}
     31 
     32   ExtraICState GetExtraICState() const { return bit_field_; }
     33 
     34   static void GenerateAheadOfTime(Isolate*,
     35                                   void (*Generate)(Isolate*,
     36                                                    const CallICState&));
     37 
     38   int argc() const { return ArgcBits::decode(bit_field_); }
     39   ConvertReceiverMode convert_mode() const {
     40     return ConvertModeBits::decode(bit_field_);
     41   }
     42 
     43  private:
     44   typedef BitField<int, 0, Code::kArgumentsBits> ArgcBits;
     45   typedef BitField<ConvertReceiverMode, Code::kArgumentsBits, 2>
     46       ConvertModeBits;
     47 
     48   int const bit_field_;
     49 };
     50 
     51 
     52 std::ostream& operator<<(std::ostream& os, const CallICState& s);
     53 
     54 
     55 class BinaryOpICState final BASE_EMBEDDED {
     56  public:
     57   BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state);
     58   BinaryOpICState(Isolate* isolate, Token::Value op, Strength strength)
     59       : op_(op),
     60         strong_(is_strong(strength)),
     61         left_kind_(NONE),
     62         right_kind_(NONE),
     63         result_kind_(NONE),
     64         fixed_right_arg_(Nothing<int>()),
     65         isolate_(isolate) {
     66     DCHECK_LE(FIRST_TOKEN, op);
     67     DCHECK_LE(op, LAST_TOKEN);
     68   }
     69 
     70   InlineCacheState GetICState() const {
     71     if (Max(left_kind_, right_kind_) == NONE) {
     72       return ::v8::internal::UNINITIALIZED;
     73     }
     74     if (Max(left_kind_, right_kind_) == GENERIC) {
     75       return ::v8::internal::MEGAMORPHIC;
     76     }
     77     if (Min(left_kind_, right_kind_) == GENERIC) {
     78       return ::v8::internal::GENERIC;
     79     }
     80     return ::v8::internal::MONOMORPHIC;
     81   }
     82 
     83   ExtraICState GetExtraICState() const;
     84 
     85   static void GenerateAheadOfTime(Isolate*,
     86                                   void (*Generate)(Isolate*,
     87                                                    const BinaryOpICState&));
     88 
     89   // Returns true if the IC _could_ create allocation mementos.
     90   bool CouldCreateAllocationMementos() const {
     91     if (left_kind_ == STRING || right_kind_ == STRING) {
     92       DCHECK_EQ(Token::ADD, op_);
     93       return true;
     94     }
     95     return false;
     96   }
     97 
     98   // Returns true if the IC _should_ create allocation mementos.
     99   bool ShouldCreateAllocationMementos() const {
    100     return FLAG_allocation_site_pretenuring && CouldCreateAllocationMementos();
    101   }
    102 
    103   bool HasSideEffects() const {
    104     return Max(left_kind_, right_kind_) == GENERIC;
    105   }
    106 
    107   Strength strength() const {
    108     return strong_ ? Strength::STRONG : Strength::WEAK;
    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   class StrengthField : public BitField<bool, 10, 1> {};
    150   // When fixed right arg is set, we don't need to store the right kind.
    151   // Thus the two fields can overlap.
    152   class HasFixedRightArgField : public BitField<bool, 11, 1> {};
    153   class FixedRightArgValueField : public BitField<int, 12, 4> {};
    154   class RightKindField : public BitField<Kind, 12, 3> {};
    155 
    156   Token::Value op_;
    157   bool strong_;
    158   Kind left_kind_;
    159   Kind right_kind_;
    160   Kind result_kind_;
    161   Maybe<int> fixed_right_arg_;
    162   Isolate* isolate_;
    163 };
    164 
    165 
    166 std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s);
    167 
    168 
    169 class CompareICState {
    170  public:
    171   // The type/state lattice is defined by the following inequations:
    172   //   UNINITIALIZED < ...
    173   //   ... < GENERIC
    174   //   SMI < NUMBER
    175   //   INTERNALIZED_STRING < STRING
    176   //   INTERNALIZED_STRING < UNIQUE_NAME
    177   //   KNOWN_RECEIVER < RECEIVER
    178   enum State {
    179     UNINITIALIZED,
    180     BOOLEAN,
    181     SMI,
    182     NUMBER,
    183     STRING,
    184     INTERNALIZED_STRING,
    185     UNIQUE_NAME,     // Symbol or InternalizedString
    186     RECEIVER,        // JSReceiver
    187     KNOWN_RECEIVER,  // JSReceiver with specific map (faster check)
    188     GENERIC
    189   };
    190 
    191   static Type* StateToType(Zone* zone, State state,
    192                            Handle<Map> map = Handle<Map>());
    193 
    194   static State NewInputState(State old_state, Handle<Object> value);
    195 
    196   static const char* GetStateName(CompareICState::State state);
    197 
    198   static State TargetState(State old_state, State old_left, State old_right,
    199                            Token::Value op, bool has_inlined_smi_code,
    200                            Handle<Object> x, Handle<Object> y);
    201 };
    202 
    203 
    204 class LoadICState final BASE_EMBEDDED {
    205  private:
    206   class TypeofModeBits : public BitField<TypeofMode, 0, 1> {};
    207   class LanguageModeBits
    208       : public BitField<LanguageMode, TypeofModeBits::kNext, 2> {};
    209   STATIC_ASSERT(static_cast<int>(INSIDE_TYPEOF) == 0);
    210   const ExtraICState state_;
    211 
    212  public:
    213   static const uint32_t kNextBitFieldOffset = LanguageModeBits::kNext;
    214 
    215   static const ExtraICState kStrongModeState = STRONG
    216                                                << LanguageModeBits::kShift;
    217 
    218   explicit LoadICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {}
    219 
    220   explicit LoadICState(TypeofMode typeof_mode, LanguageMode language_mode)
    221       : state_(TypeofModeBits::encode(typeof_mode) |
    222                LanguageModeBits::encode(language_mode)) {}
    223 
    224   ExtraICState GetExtraICState() const { return state_; }
    225 
    226   TypeofMode typeof_mode() const { return TypeofModeBits::decode(state_); }
    227 
    228   LanguageMode language_mode() const {
    229     return LanguageModeBits::decode(state_);
    230   }
    231 
    232   static TypeofMode GetTypeofMode(ExtraICState state) {
    233     return LoadICState(state).typeof_mode();
    234   }
    235 
    236   static LanguageMode GetLanguageMode(ExtraICState state) {
    237     return LoadICState(state).language_mode();
    238   }
    239 };
    240 
    241 
    242 class StoreICState final BASE_EMBEDDED {
    243  public:
    244   explicit StoreICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {}
    245 
    246   explicit StoreICState(LanguageMode mode)
    247       : state_(LanguageModeState::encode(mode)) {}
    248 
    249   ExtraICState GetExtraICState() const { return state_; }
    250 
    251   LanguageMode language_mode() const {
    252     return LanguageModeState::decode(state_);
    253   }
    254 
    255   static LanguageMode GetLanguageMode(ExtraICState state) {
    256     return StoreICState(state).language_mode();
    257   }
    258 
    259   class LanguageModeState : public BitField<LanguageMode, 1, 2> {};
    260   STATIC_ASSERT(i::LANGUAGE_END == 3);
    261 
    262   // For convenience, a statically declared encoding of strict mode extra
    263   // IC state.
    264   static const ExtraICState kStrictModeState = STRICT
    265                                                << LanguageModeState::kShift;
    266 
    267  private:
    268   const ExtraICState state_;
    269 };
    270 
    271 }  // namespace internal
    272 }  // namespace v8
    273 
    274 #endif  // V8_IC_STATE_H_
    275