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,
     21                     ConstantPoolArray* constant_pool);
     22 };
     23 
     24 
     25 class CallICState FINAL BASE_EMBEDDED {
     26  public:
     27   explicit CallICState(ExtraICState extra_ic_state);
     28 
     29   enum CallType { METHOD, FUNCTION };
     30 
     31   CallICState(int argc, CallType call_type)
     32       : argc_(argc), call_type_(call_type) {}
     33 
     34   ExtraICState GetExtraICState() const;
     35 
     36   static void GenerateAheadOfTime(Isolate*,
     37                                   void (*Generate)(Isolate*,
     38                                                    const CallICState&));
     39 
     40   int arg_count() const { return argc_; }
     41   CallType call_type() const { return call_type_; }
     42 
     43   bool CallAsMethod() const { return call_type_ == METHOD; }
     44 
     45  private:
     46   class ArgcBits : public BitField<int, 0, Code::kArgumentsBits> {};
     47   class CallTypeBits : public BitField<CallType, Code::kArgumentsBits, 1> {};
     48 
     49   const int argc_;
     50   const CallType call_type_;
     51 };
     52 
     53 
     54 OStream& operator<<(OStream& os, const CallICState& s);
     55 
     56 
     57 // Mode to overwrite BinaryExpression values.
     58 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
     59 
     60 class BinaryOpICState FINAL BASE_EMBEDDED {
     61  public:
     62   BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state);
     63 
     64   BinaryOpICState(Isolate* isolate, Token::Value op, OverwriteMode mode)
     65       : op_(op),
     66         mode_(mode),
     67         left_kind_(NONE),
     68         right_kind_(NONE),
     69         result_kind_(NONE),
     70         isolate_(isolate) {
     71     DCHECK_LE(FIRST_TOKEN, op);
     72     DCHECK_LE(op, LAST_TOKEN);
     73   }
     74 
     75   InlineCacheState GetICState() const {
     76     if (Max(left_kind_, right_kind_) == NONE) {
     77       return ::v8::internal::UNINITIALIZED;
     78     }
     79     if (Max(left_kind_, right_kind_) == GENERIC) {
     80       return ::v8::internal::MEGAMORPHIC;
     81     }
     82     if (Min(left_kind_, right_kind_) == GENERIC) {
     83       return ::v8::internal::GENERIC;
     84     }
     85     return ::v8::internal::MONOMORPHIC;
     86   }
     87 
     88   ExtraICState GetExtraICState() const;
     89 
     90   static void GenerateAheadOfTime(Isolate*,
     91                                   void (*Generate)(Isolate*,
     92                                                    const BinaryOpICState&));
     93 
     94   bool CanReuseDoubleBox() const {
     95     return (result_kind_ > SMI && result_kind_ <= NUMBER) &&
     96            ((mode_ == OVERWRITE_LEFT && left_kind_ > SMI &&
     97              left_kind_ <= NUMBER) ||
     98             (mode_ == OVERWRITE_RIGHT && right_kind_ > SMI &&
     99              right_kind_ <= NUMBER));
    100   }
    101 
    102   // Returns true if the IC _could_ create allocation mementos.
    103   bool CouldCreateAllocationMementos() const {
    104     if (left_kind_ == STRING || right_kind_ == STRING) {
    105       DCHECK_EQ(Token::ADD, op_);
    106       return true;
    107     }
    108     return false;
    109   }
    110 
    111   // Returns true if the IC _should_ create allocation mementos.
    112   bool ShouldCreateAllocationMementos() const {
    113     return FLAG_allocation_site_pretenuring && CouldCreateAllocationMementos();
    114   }
    115 
    116   bool HasSideEffects() const {
    117     return Max(left_kind_, right_kind_) == GENERIC;
    118   }
    119 
    120   // Returns true if the IC should enable the inline smi code (i.e. if either
    121   // parameter may be a smi).
    122   bool UseInlinedSmiCode() const {
    123     return KindMaybeSmi(left_kind_) || KindMaybeSmi(right_kind_);
    124   }
    125 
    126   static const int FIRST_TOKEN = Token::BIT_OR;
    127   static const int LAST_TOKEN = Token::MOD;
    128 
    129   Token::Value op() const { return op_; }
    130   OverwriteMode mode() const { return mode_; }
    131   Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
    132 
    133   Type* GetLeftType(Zone* zone) const { return KindToType(left_kind_, zone); }
    134   Type* GetRightType(Zone* zone) const { return KindToType(right_kind_, zone); }
    135   Type* GetResultType(Zone* zone) const;
    136 
    137   void Update(Handle<Object> left, Handle<Object> right, Handle<Object> result);
    138 
    139   Isolate* isolate() const { return isolate_; }
    140 
    141  private:
    142   friend OStream& operator<<(OStream& os, const BinaryOpICState& s);
    143 
    144   enum Kind { NONE, SMI, INT32, NUMBER, STRING, GENERIC };
    145 
    146   Kind UpdateKind(Handle<Object> object, Kind kind) const;
    147 
    148   static const char* KindToString(Kind kind);
    149   static Type* KindToType(Kind kind, Zone* zone);
    150   static bool KindMaybeSmi(Kind kind) {
    151     return (kind >= SMI && kind <= NUMBER) || kind == GENERIC;
    152   }
    153 
    154   // We truncate the last bit of the token.
    155   STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 4));
    156   class OpField : public BitField<int, 0, 4> {};
    157   class OverwriteModeField : public BitField<OverwriteMode, 4, 2> {};
    158   class ResultKindField : public BitField<Kind, 6, 3> {};
    159   class LeftKindField : public BitField<Kind, 9, 3> {};
    160   // When fixed right arg is set, we don't need to store the right kind.
    161   // Thus the two fields can overlap.
    162   class HasFixedRightArgField : public BitField<bool, 12, 1> {};
    163   class FixedRightArgValueField : public BitField<int, 13, 4> {};
    164   class RightKindField : public BitField<Kind, 13, 3> {};
    165 
    166   Token::Value op_;
    167   OverwriteMode mode_;
    168   Kind left_kind_;
    169   Kind right_kind_;
    170   Kind result_kind_;
    171   Maybe<int> fixed_right_arg_;
    172   Isolate* isolate_;
    173 };
    174 
    175 
    176 OStream& operator<<(OStream& os, const BinaryOpICState& s);
    177 
    178 
    179 class CompareICState {
    180  public:
    181   // The type/state lattice is defined by the following inequations:
    182   //   UNINITIALIZED < ...
    183   //   ... < GENERIC
    184   //   SMI < NUMBER
    185   //   INTERNALIZED_STRING < STRING
    186   //   KNOWN_OBJECT < OBJECT
    187   enum State {
    188     UNINITIALIZED,
    189     SMI,
    190     NUMBER,
    191     STRING,
    192     INTERNALIZED_STRING,
    193     UNIQUE_NAME,   // Symbol or InternalizedString
    194     OBJECT,        // JSObject
    195     KNOWN_OBJECT,  // JSObject with specific map (faster check)
    196     GENERIC
    197   };
    198 
    199   static Type* StateToType(Zone* zone, State state,
    200                            Handle<Map> map = Handle<Map>());
    201 
    202   static State NewInputState(State old_state, Handle<Object> value);
    203 
    204   static const char* GetStateName(CompareICState::State state);
    205 
    206   static State TargetState(State old_state, State old_left, State old_right,
    207                            Token::Value op, bool has_inlined_smi_code,
    208                            Handle<Object> x, Handle<Object> y);
    209 };
    210 
    211 
    212 class LoadICState FINAL BASE_EMBEDDED {
    213  public:
    214   explicit LoadICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {}
    215 
    216   explicit LoadICState(ContextualMode mode)
    217       : state_(ContextualModeBits::encode(mode)) {}
    218 
    219   ExtraICState GetExtraICState() const { return state_; }
    220 
    221   ContextualMode contextual_mode() const {
    222     return ContextualModeBits::decode(state_);
    223   }
    224 
    225   static ContextualMode GetContextualMode(ExtraICState state) {
    226     return LoadICState(state).contextual_mode();
    227   }
    228 
    229  private:
    230   class ContextualModeBits : public BitField<ContextualMode, 0, 1> {};
    231   STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
    232 
    233   const ExtraICState state_;
    234 };
    235 }
    236 }
    237 
    238 #endif  // V8_IC_STATE_H_
    239