ic-state.h 8.14 KB
Newer Older
1 2 3 4 5 6 7 8
// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_IC_STATE_H_
#define V8_IC_STATE_H_

#include "src/macro-assembler.h"
9
#include "src/parsing/token.h"
10 11 12 13 14 15 16 17 18 19 20

namespace v8 {
namespace internal {


const int kMaxKeyedPolymorphism = 4;


class ICUtility : public AllStatic {
 public:
  // Clear the inline cache to initial state.
21
  static void Clear(Isolate* isolate, Address address, Address constant_pool);
22 23 24
};


25
class CallICState final BASE_EMBEDDED {
26
 public:
27 28
  explicit CallICState(ExtraICState extra_ic_state)
      : bit_field_(extra_ic_state) {}
29 30
  CallICState(ConvertReceiverMode convert_mode, TailCallMode tail_call_mode)
      : bit_field_(ConvertModeBits::encode(convert_mode) |
31
                   TailCallModeBits::encode(tail_call_mode)) {}
32

33
  ExtraICState GetExtraICState() const { return bit_field_; }
34 35 36 37 38

  static void GenerateAheadOfTime(Isolate*,
                                  void (*Generate)(Isolate*,
                                                   const CallICState&));

39 40 41
  ConvertReceiverMode convert_mode() const {
    return ConvertModeBits::decode(bit_field_);
  }
ishell's avatar
ishell committed
42 43 44
  TailCallMode tail_call_mode() const {
    return TailCallModeBits::decode(bit_field_);
  }
45 46

 private:
47
  typedef BitField<ConvertReceiverMode, 0, 2> ConvertModeBits;
ishell's avatar
ishell committed
48
  typedef BitField<TailCallMode, ConvertModeBits::kNext, 1> TailCallModeBits;
49

50
  int const bit_field_;
51 52 53
};


54
std::ostream& operator<<(std::ostream& os, const CallICState& s);
55 56


57
class BinaryOpICState final BASE_EMBEDDED {
58 59
 public:
  BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state);
60
  BinaryOpICState(Isolate* isolate, Token::Value op)
61 62 63 64
      : op_(op),
        left_kind_(NONE),
        right_kind_(NONE),
        result_kind_(NONE),
65
        fixed_right_arg_(Nothing<int>()),
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
        isolate_(isolate) {
    DCHECK_LE(FIRST_TOKEN, op);
    DCHECK_LE(op, LAST_TOKEN);
  }

  InlineCacheState GetICState() const {
    if (Max(left_kind_, right_kind_) == NONE) {
      return ::v8::internal::UNINITIALIZED;
    }
    if (Max(left_kind_, right_kind_) == GENERIC) {
      return ::v8::internal::MEGAMORPHIC;
    }
    if (Min(left_kind_, right_kind_) == GENERIC) {
      return ::v8::internal::GENERIC;
    }
    return ::v8::internal::MONOMORPHIC;
  }

  ExtraICState GetExtraICState() const;
85
  std::string ToString() const;
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114

  static void GenerateAheadOfTime(Isolate*,
                                  void (*Generate)(Isolate*,
                                                   const BinaryOpICState&));

  // Returns true if the IC _could_ create allocation mementos.
  bool CouldCreateAllocationMementos() const {
    if (left_kind_ == STRING || right_kind_ == STRING) {
      DCHECK_EQ(Token::ADD, op_);
      return true;
    }
    return false;
  }

  // Returns true if the IC _should_ create allocation mementos.
  bool ShouldCreateAllocationMementos() const {
    return FLAG_allocation_site_pretenuring && CouldCreateAllocationMementos();
  }

  bool HasSideEffects() const {
    return Max(left_kind_, right_kind_) == GENERIC;
  }

  // Returns true if the IC should enable the inline smi code (i.e. if either
  // parameter may be a smi).
  bool UseInlinedSmiCode() const {
    return KindMaybeSmi(left_kind_) || KindMaybeSmi(right_kind_);
  }

115 116
  static const int FIRST_TOKEN = Token::BIT_OR;
  static const int LAST_TOKEN = Token::MOD;
117 118 119 120

  Token::Value op() const { return op_; }
  Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }

121 122 123
  AstType* GetLeftType() const { return KindToType(left_kind_); }
  AstType* GetRightType() const { return KindToType(right_kind_); }
  AstType* GetResultType() const;
124 125 126 127 128

  void Update(Handle<Object> left, Handle<Object> right, Handle<Object> result);

  Isolate* isolate() const { return isolate_; }

129 130 131 132 133 134
  enum Kind { NONE, SMI, INT32, NUMBER, STRING, GENERIC };
  Kind kind() const {
    return KindGeneralize(KindGeneralize(left_kind_, right_kind_),
                          result_kind_);
  }

135
 private:
136
  friend std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s);
137 138 139 140

  Kind UpdateKind(Handle<Object> object, Kind kind) const;

  static const char* KindToString(Kind kind);
141
  static AstType* KindToType(Kind kind);
142 143 144
  static bool KindMaybeSmi(Kind kind) {
    return (kind >= SMI && kind <= NUMBER) || kind == GENERIC;
  }
145 146 147 148 149 150 151 152 153 154 155 156
  static bool KindLessGeneralThan(Kind kind1, Kind kind2) {
    if (kind1 == NONE) return true;
    if (kind1 == kind2) return true;
    if (kind2 == GENERIC) return true;
    if (kind2 == STRING) return false;
    return kind1 <= kind2;
  }
  static Kind KindGeneralize(Kind kind1, Kind kind2) {
    if (KindLessGeneralThan(kind1, kind2)) return kind2;
    if (KindLessGeneralThan(kind2, kind1)) return kind1;
    return GENERIC;
  }
157 158 159 160

  // We truncate the last bit of the token.
  STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 4));
  class OpField : public BitField<int, 0, 4> {};
161 162
  class ResultKindField : public BitField<Kind, 4, 3> {};
  class LeftKindField : public BitField<Kind, 7, 3> {};
163 164
  // When fixed right arg is set, we don't need to store the right kind.
  // Thus the two fields can overlap.
165 166 167
  class HasFixedRightArgField : public BitField<bool, 10, 1> {};
  class FixedRightArgValueField : public BitField<int, 11, 4> {};
  class RightKindField : public BitField<Kind, 11, 3> {};
168 169 170 171 172 173 174 175 176 177

  Token::Value op_;
  Kind left_kind_;
  Kind right_kind_;
  Kind result_kind_;
  Maybe<int> fixed_right_arg_;
  Isolate* isolate_;
};


178
std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s);
179 180 181 182 183 184 185 186 187


class CompareICState {
 public:
  // The type/state lattice is defined by the following inequations:
  //   UNINITIALIZED < ...
  //   ... < GENERIC
  //   SMI < NUMBER
  //   INTERNALIZED_STRING < STRING
188
  //   INTERNALIZED_STRING < UNIQUE_NAME
189
  //   KNOWN_RECEIVER < RECEIVER
190 191
  enum State {
    UNINITIALIZED,
192
    BOOLEAN,
193 194 195 196
    SMI,
    NUMBER,
    STRING,
    INTERNALIZED_STRING,
197 198 199
    UNIQUE_NAME,     // Symbol or InternalizedString
    RECEIVER,        // JSReceiver
    KNOWN_RECEIVER,  // JSReceiver with specific map (faster check)
200 201 202
    GENERIC
  };

203 204
  static AstType* StateToType(Zone* zone, State state,
                              Handle<Map> map = Handle<Map>());
205 206 207 208 209

  static State NewInputState(State old_state, Handle<Object> value);

  static const char* GetStateName(CompareICState::State state);

210 211 212 213
  static State TargetState(Isolate* isolate, State old_state, State old_left,
                           State old_right, Token::Value op,
                           bool has_inlined_smi_code, Handle<Object> x,
                           Handle<Object> y);
214 215
};

ishell's avatar
ishell committed
216
class LoadGlobalICState final BASE_EMBEDDED {
217
 private:
218 219
  class TypeofModeBits : public BitField<TypeofMode, 0, 1> {};
  STATIC_ASSERT(static_cast<int>(INSIDE_TYPEOF) == 0);
220 221
  const ExtraICState state_;

222
 public:
223
  static const uint32_t kNextBitFieldOffset = TypeofModeBits::kNext;
224

ishell's avatar
ishell committed
225 226
  explicit LoadGlobalICState(ExtraICState extra_ic_state)
      : state_(extra_ic_state) {}
227

ishell's avatar
ishell committed
228
  explicit LoadGlobalICState(TypeofMode typeof_mode)
229
      : state_(TypeofModeBits::encode(typeof_mode)) {}
230 231 232

  ExtraICState GetExtraICState() const { return state_; }

233
  TypeofMode typeof_mode() const { return TypeofModeBits::decode(state_); }
234

235
  static TypeofMode GetTypeofMode(ExtraICState state) {
ishell's avatar
ishell committed
236
    return LoadGlobalICState(state).typeof_mode();
237 238
  }
};
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257


class StoreICState final BASE_EMBEDDED {
 public:
  explicit StoreICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {}

  explicit StoreICState(LanguageMode mode)
      : state_(LanguageModeState::encode(mode)) {}

  ExtraICState GetExtraICState() const { return state_; }

  LanguageMode language_mode() const {
    return LanguageModeState::decode(state_);
  }

  static LanguageMode GetLanguageMode(ExtraICState state) {
    return StoreICState(state).language_mode();
  }

258 259
  class LanguageModeState : public BitField<LanguageMode, 1, 1> {};
  STATIC_ASSERT(i::LANGUAGE_END == 2);
260 261 262 263 264 265 266 267 268

  // For convenience, a statically declared encoding of strict mode extra
  // IC state.
  static const ExtraICState kStrictModeState = STRICT
                                               << LanguageModeState::kShift;

 private:
  const ExtraICState state_;
};
269 270 271

}  // namespace internal
}  // namespace v8
272 273

#endif  // V8_IC_STATE_H_