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 #include "src/parsing/token.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 
     14 class AstType;
     15 
     16 const int kMaxKeyedPolymorphism = 4;
     17 
     18 
     19 class ICUtility : public AllStatic {
     20  public:
     21   // Clear the inline cache to initial state.
     22   static void Clear(Isolate* isolate, Address address, Address constant_pool);
     23 };
     24 
     25 
     26 class BinaryOpICState final BASE_EMBEDDED {
     27  public:
     28   BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state);
     29   BinaryOpICState(Isolate* isolate, Token::Value op)
     30       : op_(op),
     31         left_kind_(NONE),
     32         right_kind_(NONE),
     33         result_kind_(NONE),
     34         fixed_right_arg_(Nothing<int>()),
     35         isolate_(isolate) {
     36     DCHECK_LE(FIRST_TOKEN, op);
     37     DCHECK_LE(op, LAST_TOKEN);
     38   }
     39 
     40   InlineCacheState GetICState() const {
     41     if (Max(left_kind_, right_kind_) == NONE) {
     42       return ::v8::internal::UNINITIALIZED;
     43     }
     44     if (Max(left_kind_, right_kind_) == GENERIC) {
     45       return ::v8::internal::MEGAMORPHIC;
     46     }
     47     if (Min(left_kind_, right_kind_) == GENERIC) {
     48       return ::v8::internal::GENERIC;
     49     }
     50     return ::v8::internal::MONOMORPHIC;
     51   }
     52 
     53   ExtraICState GetExtraICState() const;
     54   std::string ToString() const;
     55 
     56   static void GenerateAheadOfTime(Isolate*,
     57                                   void (*Generate)(Isolate*,
     58                                                    const BinaryOpICState&));
     59 
     60   // Returns true if the IC _could_ create allocation mementos.
     61   bool CouldCreateAllocationMementos() const {
     62     if (left_kind_ == STRING || right_kind_ == STRING) {
     63       DCHECK_EQ(Token::ADD, op_);
     64       return true;
     65     }
     66     return false;
     67   }
     68 
     69   // Returns true if the IC _should_ create allocation mementos.
     70   bool ShouldCreateAllocationMementos() const {
     71     return FLAG_allocation_site_pretenuring && CouldCreateAllocationMementos();
     72   }
     73 
     74   bool HasSideEffects() const {
     75     return Max(left_kind_, right_kind_) == GENERIC;
     76   }
     77 
     78   // Returns true if the IC should enable the inline smi code (i.e. if either
     79   // parameter may be a smi).
     80   bool UseInlinedSmiCode() const {
     81     return KindMaybeSmi(left_kind_) || KindMaybeSmi(right_kind_);
     82   }
     83 
     84   static const int FIRST_TOKEN = Token::BIT_OR;
     85   static const int LAST_TOKEN = Token::MOD;
     86 
     87   Token::Value op() const { return op_; }
     88   Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
     89 
     90   AstType* GetLeftType() const { return KindToType(left_kind_); }
     91   AstType* GetRightType() const { return KindToType(right_kind_); }
     92   AstType* GetResultType() const;
     93 
     94   void Update(Handle<Object> left, Handle<Object> right, Handle<Object> result);
     95 
     96   Isolate* isolate() const { return isolate_; }
     97 
     98   enum Kind { NONE, SMI, INT32, NUMBER, STRING, GENERIC };
     99   Kind kind() const {
    100     return KindGeneralize(KindGeneralize(left_kind_, right_kind_),
    101                           result_kind_);
    102   }
    103 
    104  private:
    105   friend std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s);
    106 
    107   Kind UpdateKind(Handle<Object> object, Kind kind) const;
    108 
    109   static const char* KindToString(Kind kind);
    110   static AstType* KindToType(Kind kind);
    111   static bool KindMaybeSmi(Kind kind) {
    112     return (kind >= SMI && kind <= NUMBER) || kind == GENERIC;
    113   }
    114   static bool KindLessGeneralThan(Kind kind1, Kind kind2) {
    115     if (kind1 == NONE) return true;
    116     if (kind1 == kind2) return true;
    117     if (kind2 == GENERIC) return true;
    118     if (kind2 == STRING) return false;
    119     return kind1 <= kind2;
    120   }
    121   static Kind KindGeneralize(Kind kind1, Kind kind2) {
    122     if (KindLessGeneralThan(kind1, kind2)) return kind2;
    123     if (KindLessGeneralThan(kind2, kind1)) return kind1;
    124     return GENERIC;
    125   }
    126 
    127   // We truncate the last bit of the token.
    128   STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 4));
    129   class OpField : public BitField<int, 0, 4> {};
    130   class ResultKindField : public BitField<Kind, 4, 3> {};
    131   class LeftKindField : public BitField<Kind, 7, 3> {};
    132   // When fixed right arg is set, we don't need to store the right kind.
    133   // Thus the two fields can overlap.
    134   class HasFixedRightArgField : public BitField<bool, 10, 1> {};
    135   class FixedRightArgValueField : public BitField<int, 11, 4> {};
    136   class RightKindField : public BitField<Kind, 11, 3> {};
    137 
    138   Token::Value op_;
    139   Kind left_kind_;
    140   Kind right_kind_;
    141   Kind result_kind_;
    142   Maybe<int> fixed_right_arg_;
    143   Isolate* isolate_;
    144 };
    145 
    146 
    147 std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s);
    148 
    149 
    150 class CompareICState {
    151  public:
    152   // The type/state lattice is defined by the following inequations:
    153   //   UNINITIALIZED < ...
    154   //   ... < GENERIC
    155   //   SMI < NUMBER
    156   //   INTERNALIZED_STRING < STRING
    157   //   INTERNALIZED_STRING < UNIQUE_NAME
    158   //   KNOWN_RECEIVER < RECEIVER
    159   enum State {
    160     UNINITIALIZED,
    161     BOOLEAN,
    162     SMI,
    163     NUMBER,
    164     STRING,
    165     INTERNALIZED_STRING,
    166     UNIQUE_NAME,     // Symbol or InternalizedString
    167     RECEIVER,        // JSReceiver
    168     KNOWN_RECEIVER,  // JSReceiver with specific map (faster check)
    169     GENERIC
    170   };
    171 
    172   static AstType* StateToType(Zone* zone, State state,
    173                               Handle<Map> map = Handle<Map>());
    174 
    175   static State NewInputState(State old_state, Handle<Object> value);
    176 
    177   static const char* GetStateName(CompareICState::State state);
    178 
    179   static State TargetState(Isolate* isolate, State old_state, State old_left,
    180                            State old_right, Token::Value op,
    181                            bool has_inlined_smi_code, Handle<Object> x,
    182                            Handle<Object> y);
    183 };
    184 
    185 }  // namespace internal
    186 }  // namespace v8
    187 
    188 #endif  // V8_IC_STATE_H_
    189