ic-state.h 8.06 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// 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"

namespace v8 {
namespace internal {


const int kMaxKeyedPolymorphism = 4;


class ICUtility : public AllStatic {
 public:
  // 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
 public:
  explicit CallICState(ExtraICState extra_ic_state);

  enum CallType { METHOD, FUNCTION };

  CallICState(int argc, CallType call_type)
      : argc_(argc), call_type_(call_type) {}

  ExtraICState GetExtraICState() const;

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

  int arg_count() const { return argc_; }
  CallType call_type() const { return call_type_; }

  bool CallAsMethod() const { return call_type_ == METHOD; }

 private:
  class ArgcBits : public BitField<int, 0, Code::kArgumentsBits> {};
  class CallTypeBits : public BitField<CallType, Code::kArgumentsBits, 1> {};

  const int argc_;
  const CallType call_type_;
};


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


56
class BinaryOpICState final BASE_EMBEDDED {
57 58
 public:
  BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state);
59
  BinaryOpICState(Isolate* isolate, Token::Value op, Strength strength)
60
      : op_(op),
61
        strong_(is_strong(strength)),
62 63 64
        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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
        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;

  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;
  }

108 109
  Strength strength() const {
    return strong_ ? Strength::STRONG : Strength::WEAK;
110 111
  }

112 113 114 115 116 117
  // 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_);
  }

118 119
  static const int FIRST_TOKEN = Token::BIT_OR;
  static const int LAST_TOKEN = Token::MOD;
120 121 122 123 124 125 126 127 128 129 130 131 132

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

  Type* GetLeftType(Zone* zone) const { return KindToType(left_kind_, zone); }
  Type* GetRightType(Zone* zone) const { return KindToType(right_kind_, zone); }
  Type* GetResultType(Zone* zone) const;

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

  Isolate* isolate() const { return isolate_; }

 private:
133
  friend std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s);
134 135 136 137 138 139 140 141 142 143 144 145 146 147

  enum Kind { NONE, SMI, INT32, NUMBER, STRING, GENERIC };

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

  static const char* KindToString(Kind kind);
  static Type* KindToType(Kind kind, Zone* zone);
  static bool KindMaybeSmi(Kind kind) {
    return (kind >= SMI && kind <= NUMBER) || kind == GENERIC;
  }

  // We truncate the last bit of the token.
  STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 4));
  class OpField : public BitField<int, 0, 4> {};
148 149
  class ResultKindField : public BitField<Kind, 4, 3> {};
  class LeftKindField : public BitField<Kind, 7, 3> {};
150
  class StrengthField : public BitField<bool, 10, 1> {};
151 152
  // When fixed right arg is set, we don't need to store the right kind.
  // Thus the two fields can overlap.
153 154 155
  class HasFixedRightArgField : public BitField<bool, 11, 1> {};
  class FixedRightArgValueField : public BitField<int, 12, 4> {};
  class RightKindField : public BitField<Kind, 12, 3> {};
156 157

  Token::Value op_;
158
  bool strong_;
159 160 161 162 163 164 165 166
  Kind left_kind_;
  Kind right_kind_;
  Kind result_kind_;
  Maybe<int> fixed_right_arg_;
  Isolate* isolate_;
};


167
std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s);
168 169 170 171 172 173 174 175 176


class CompareICState {
 public:
  // The type/state lattice is defined by the following inequations:
  //   UNINITIALIZED < ...
  //   ... < GENERIC
  //   SMI < NUMBER
  //   INTERNALIZED_STRING < STRING
177
  //   INTERNALIZED_STRING < UNIQUE_NAME
178 179 180
  //   KNOWN_OBJECT < OBJECT
  enum State {
    UNINITIALIZED,
181
    BOOLEAN,
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
    SMI,
    NUMBER,
    STRING,
    INTERNALIZED_STRING,
    UNIQUE_NAME,   // Symbol or InternalizedString
    OBJECT,        // JSObject
    KNOWN_OBJECT,  // JSObject with specific map (faster check)
    GENERIC
  };

  static Type* StateToType(Zone* zone, State state,
                           Handle<Map> map = Handle<Map>());

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

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

  static State TargetState(State old_state, State old_left, State old_right,
                           Token::Value op, bool has_inlined_smi_code,
                           Handle<Object> x, Handle<Object> y);
};


205
class LoadICState final BASE_EMBEDDED {
206
 private:
207
  class TypeofModeBits : public BitField<TypeofMode, 0, 1> {};
208
  class LanguageModeBits
209 210
      : public BitField<LanguageMode, TypeofModeBits::kNext, 2> {};
  STATIC_ASSERT(static_cast<int>(INSIDE_TYPEOF) == 0);
211 212
  const ExtraICState state_;

213
 public:
214 215 216 217 218
  static const uint32_t kNextBitFieldOffset = LanguageModeBits::kNext;

  static const ExtraICState kStrongModeState = STRONG
                                               << LanguageModeBits::kShift;

219 220
  explicit LoadICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {}

221 222
  explicit LoadICState(TypeofMode typeof_mode, LanguageMode language_mode)
      : state_(TypeofModeBits::encode(typeof_mode) |
223
               LanguageModeBits::encode(language_mode)) {}
224 225 226

  ExtraICState GetExtraICState() const { return state_; }

227
  TypeofMode typeof_mode() const { return TypeofModeBits::decode(state_); }
228

229 230 231 232
  LanguageMode language_mode() const {
    return LanguageModeBits::decode(state_);
  }

233 234
  static TypeofMode GetTypeofMode(ExtraICState state) {
    return LoadICState(state).typeof_mode();
235 236
  }

237 238 239
  static LanguageMode GetLanguageMode(ExtraICState state) {
    return LoadICState(state).language_mode();
  }
240
};
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270


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();
  }

  class LanguageModeState : public BitField<LanguageMode, 1, 2> {};
  STATIC_ASSERT(i::LANGUAGE_END == 3);

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

 private:
  const ExtraICState state_;
};
271 272 273

}  // namespace internal
}  // namespace v8
274 275

#endif  // V8_IC_STATE_H_