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: CallICState(ExtraICState extra_ic_state)26 explicit CallICState(ExtraICState extra_ic_state) 27 : bit_field_(extra_ic_state) {} CallICState(int argc,ConvertReceiverMode convert_mode)28 CallICState(int argc, ConvertReceiverMode convert_mode) 29 : bit_field_(ArgcBits::encode(argc) | 30 ConvertModeBits::encode(convert_mode)) {} 31 GetExtraICState()32 ExtraICState GetExtraICState() const { return bit_field_; } 33 34 static void GenerateAheadOfTime(Isolate*, 35 void (*Generate)(Isolate*, 36 const CallICState&)); 37 argc()38 int argc() const { return ArgcBits::decode(bit_field_); } convert_mode()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); BinaryOpICState(Isolate * isolate,Token::Value op,Strength strength)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 GetICState()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. CouldCreateAllocationMementos()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. ShouldCreateAllocationMementos()99 bool ShouldCreateAllocationMementos() const { 100 return FLAG_allocation_site_pretenuring && CouldCreateAllocationMementos(); 101 } 102 HasSideEffects()103 bool HasSideEffects() const { 104 return Max(left_kind_, right_kind_) == GENERIC; 105 } 106 strength()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). UseInlinedSmiCode()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 op()120 Token::Value op() const { return op_; } fixed_right_arg()121 Maybe<int> fixed_right_arg() const { return fixed_right_arg_; } 122 GetLeftType()123 Type* GetLeftType() const { return KindToType(left_kind_); } GetRightType()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 isolate()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); KindMaybeSmi(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 LoadICState(ExtraICState extra_ic_state)218 explicit LoadICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {} 219 LoadICState(TypeofMode typeof_mode,LanguageMode language_mode)220 explicit LoadICState(TypeofMode typeof_mode, LanguageMode language_mode) 221 : state_(TypeofModeBits::encode(typeof_mode) | 222 LanguageModeBits::encode(language_mode)) {} 223 GetExtraICState()224 ExtraICState GetExtraICState() const { return state_; } 225 typeof_mode()226 TypeofMode typeof_mode() const { return TypeofModeBits::decode(state_); } 227 language_mode()228 LanguageMode language_mode() const { 229 return LanguageModeBits::decode(state_); 230 } 231 GetTypeofMode(ExtraICState state)232 static TypeofMode GetTypeofMode(ExtraICState state) { 233 return LoadICState(state).typeof_mode(); 234 } 235 GetLanguageMode(ExtraICState state)236 static LanguageMode GetLanguageMode(ExtraICState state) { 237 return LoadICState(state).language_mode(); 238 } 239 }; 240 241 242 class StoreICState final BASE_EMBEDDED { 243 public: StoreICState(ExtraICState extra_ic_state)244 explicit StoreICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {} 245 StoreICState(LanguageMode mode)246 explicit StoreICState(LanguageMode mode) 247 : state_(LanguageModeState::encode(mode)) {} 248 GetExtraICState()249 ExtraICState GetExtraICState() const { return state_; } 250 language_mode()251 LanguageMode language_mode() const { 252 return LanguageModeState::decode(state_); 253 } 254 GetLanguageMode(ExtraICState state)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