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 15 const int kMaxKeyedPolymorphism = 4; 16 17 18 class ICUtility : public AllStatic { 19 public: 20 // 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: CallICState(ExtraICState extra_ic_state)27 explicit CallICState(ExtraICState extra_ic_state) 28 : bit_field_(extra_ic_state) {} CallICState(ConvertReceiverMode convert_mode,TailCallMode tail_call_mode)29 CallICState(ConvertReceiverMode convert_mode, TailCallMode tail_call_mode) 30 : bit_field_(ConvertModeBits::encode(convert_mode) | 31 TailCallModeBits::encode(tail_call_mode)) {} 32 GetExtraICState()33 ExtraICState GetExtraICState() const { return bit_field_; } 34 35 static void GenerateAheadOfTime(Isolate*, 36 void (*Generate)(Isolate*, 37 const CallICState&)); 38 convert_mode()39 ConvertReceiverMode convert_mode() const { 40 return ConvertModeBits::decode(bit_field_); 41 } tail_call_mode()42 TailCallMode tail_call_mode() const { 43 return TailCallModeBits::decode(bit_field_); 44 } 45 46 private: 47 typedef BitField<ConvertReceiverMode, 0, 2> ConvertModeBits; 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 public: 59 BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state); BinaryOpICState(Isolate * isolate,Token::Value op)60 BinaryOpICState(Isolate* isolate, Token::Value op) 61 : op_(op), 62 left_kind_(NONE), 63 right_kind_(NONE), 64 result_kind_(NONE), 65 fixed_right_arg_(Nothing<int>()), 66 isolate_(isolate) { 67 DCHECK_LE(FIRST_TOKEN, op); 68 DCHECK_LE(op, LAST_TOKEN); 69 } 70 GetICState()71 InlineCacheState GetICState() const { 72 if (Max(left_kind_, right_kind_) == NONE) { 73 return ::v8::internal::UNINITIALIZED; 74 } 75 if (Max(left_kind_, right_kind_) == GENERIC) { 76 return ::v8::internal::MEGAMORPHIC; 77 } 78 if (Min(left_kind_, right_kind_) == GENERIC) { 79 return ::v8::internal::GENERIC; 80 } 81 return ::v8::internal::MONOMORPHIC; 82 } 83 84 ExtraICState GetExtraICState() const; 85 86 static void GenerateAheadOfTime(Isolate*, 87 void (*Generate)(Isolate*, 88 const BinaryOpICState&)); 89 90 // Returns true if the IC _could_ create allocation mementos. CouldCreateAllocationMementos()91 bool CouldCreateAllocationMementos() const { 92 if (left_kind_ == STRING || right_kind_ == STRING) { 93 DCHECK_EQ(Token::ADD, op_); 94 return true; 95 } 96 return false; 97 } 98 99 // Returns true if the IC _should_ create allocation mementos. ShouldCreateAllocationMementos()100 bool ShouldCreateAllocationMementos() const { 101 return FLAG_allocation_site_pretenuring && CouldCreateAllocationMementos(); 102 } 103 HasSideEffects()104 bool HasSideEffects() const { 105 return Max(left_kind_, right_kind_) == GENERIC; 106 } 107 108 // Returns true if the IC should enable the inline smi code (i.e. if either 109 // parameter may be a smi). UseInlinedSmiCode()110 bool UseInlinedSmiCode() const { 111 return KindMaybeSmi(left_kind_) || KindMaybeSmi(right_kind_); 112 } 113 114 static const int FIRST_TOKEN = Token::BIT_OR; 115 static const int LAST_TOKEN = Token::MOD; 116 op()117 Token::Value op() const { return op_; } fixed_right_arg()118 Maybe<int> fixed_right_arg() const { return fixed_right_arg_; } 119 GetLeftType()120 AstType* GetLeftType() const { return KindToType(left_kind_); } GetRightType()121 AstType* GetRightType() const { return KindToType(right_kind_); } 122 AstType* GetResultType() const; 123 124 void Update(Handle<Object> left, Handle<Object> right, Handle<Object> result); 125 isolate()126 Isolate* isolate() const { return isolate_; } 127 128 enum Kind { NONE, SMI, INT32, NUMBER, STRING, GENERIC }; kind()129 Kind kind() const { 130 return KindGeneralize(KindGeneralize(left_kind_, right_kind_), 131 result_kind_); 132 } 133 134 private: 135 friend std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s); 136 137 Kind UpdateKind(Handle<Object> object, Kind kind) const; 138 139 static const char* KindToString(Kind kind); 140 static AstType* KindToType(Kind kind); KindMaybeSmi(Kind kind)141 static bool KindMaybeSmi(Kind kind) { 142 return (kind >= SMI && kind <= NUMBER) || kind == GENERIC; 143 } KindLessGeneralThan(Kind kind1,Kind kind2)144 static bool KindLessGeneralThan(Kind kind1, Kind kind2) { 145 if (kind1 == NONE) return true; 146 if (kind1 == kind2) return true; 147 if (kind2 == GENERIC) return true; 148 if (kind2 == STRING) return false; 149 return kind1 <= kind2; 150 } KindGeneralize(Kind kind1,Kind kind2)151 static Kind KindGeneralize(Kind kind1, Kind kind2) { 152 if (KindLessGeneralThan(kind1, kind2)) return kind2; 153 if (KindLessGeneralThan(kind2, kind1)) return kind1; 154 return GENERIC; 155 } 156 157 // We truncate the last bit of the token. 158 STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 4)); 159 class OpField : public BitField<int, 0, 4> {}; 160 class ResultKindField : public BitField<Kind, 4, 3> {}; 161 class LeftKindField : public BitField<Kind, 7, 3> {}; 162 // When fixed right arg is set, we don't need to store the right kind. 163 // Thus the two fields can overlap. 164 class HasFixedRightArgField : public BitField<bool, 10, 1> {}; 165 class FixedRightArgValueField : public BitField<int, 11, 4> {}; 166 class RightKindField : public BitField<Kind, 11, 3> {}; 167 168 Token::Value op_; 169 Kind left_kind_; 170 Kind right_kind_; 171 Kind result_kind_; 172 Maybe<int> fixed_right_arg_; 173 Isolate* isolate_; 174 }; 175 176 177 std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s); 178 179 180 class CompareICState { 181 public: 182 // The type/state lattice is defined by the following inequations: 183 // UNINITIALIZED < ... 184 // ... < GENERIC 185 // SMI < NUMBER 186 // INTERNALIZED_STRING < STRING 187 // INTERNALIZED_STRING < UNIQUE_NAME 188 // KNOWN_RECEIVER < RECEIVER 189 enum State { 190 UNINITIALIZED, 191 BOOLEAN, 192 SMI, 193 NUMBER, 194 STRING, 195 INTERNALIZED_STRING, 196 UNIQUE_NAME, // Symbol or InternalizedString 197 RECEIVER, // JSReceiver 198 KNOWN_RECEIVER, // JSReceiver with specific map (faster check) 199 GENERIC 200 }; 201 202 static AstType* StateToType(Zone* zone, State state, 203 Handle<Map> map = Handle<Map>()); 204 205 static State NewInputState(State old_state, Handle<Object> value); 206 207 static const char* GetStateName(CompareICState::State state); 208 209 static State TargetState(Isolate* isolate, State old_state, State old_left, 210 State old_right, Token::Value op, 211 bool has_inlined_smi_code, Handle<Object> x, 212 Handle<Object> y); 213 }; 214 215 class LoadGlobalICState final BASE_EMBEDDED { 216 private: 217 class TypeofModeBits : public BitField<TypeofMode, 0, 1> {}; 218 STATIC_ASSERT(static_cast<int>(INSIDE_TYPEOF) == 0); 219 const ExtraICState state_; 220 221 public: 222 static const uint32_t kNextBitFieldOffset = TypeofModeBits::kNext; 223 LoadGlobalICState(ExtraICState extra_ic_state)224 explicit LoadGlobalICState(ExtraICState extra_ic_state) 225 : state_(extra_ic_state) {} 226 LoadGlobalICState(TypeofMode typeof_mode)227 explicit LoadGlobalICState(TypeofMode typeof_mode) 228 : state_(TypeofModeBits::encode(typeof_mode)) {} 229 GetExtraICState()230 ExtraICState GetExtraICState() const { return state_; } 231 typeof_mode()232 TypeofMode typeof_mode() const { return TypeofModeBits::decode(state_); } 233 GetTypeofMode(ExtraICState state)234 static TypeofMode GetTypeofMode(ExtraICState state) { 235 return LoadGlobalICState(state).typeof_mode(); 236 } 237 }; 238 239 240 class StoreICState final BASE_EMBEDDED { 241 public: StoreICState(ExtraICState extra_ic_state)242 explicit StoreICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {} 243 StoreICState(LanguageMode mode)244 explicit StoreICState(LanguageMode mode) 245 : state_(LanguageModeState::encode(mode)) {} 246 GetExtraICState()247 ExtraICState GetExtraICState() const { return state_; } 248 language_mode()249 LanguageMode language_mode() const { 250 return LanguageModeState::decode(state_); 251 } 252 GetLanguageMode(ExtraICState state)253 static LanguageMode GetLanguageMode(ExtraICState state) { 254 return StoreICState(state).language_mode(); 255 } 256 257 class LanguageModeState : public BitField<LanguageMode, 1, 1> {}; 258 STATIC_ASSERT(i::LANGUAGE_END == 2); 259 260 // For convenience, a statically declared encoding of strict mode extra 261 // IC state. 262 static const ExtraICState kStrictModeState = STRICT 263 << LanguageModeState::kShift; 264 265 private: 266 const ExtraICState state_; 267 }; 268 269 } // namespace internal 270 } // namespace v8 271 272 #endif // V8_IC_STATE_H_ 273