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,TailCallMode tail_call_mode)28 CallICState(int argc, ConvertReceiverMode convert_mode, 29 TailCallMode tail_call_mode) 30 : bit_field_(ArgcBits::encode(argc) | 31 ConvertModeBits::encode(convert_mode) | 32 TailCallModeBits::encode(tail_call_mode)) {} 33 GetExtraICState()34 ExtraICState GetExtraICState() const { return bit_field_; } 35 36 static void GenerateAheadOfTime(Isolate*, 37 void (*Generate)(Isolate*, 38 const CallICState&)); 39 argc()40 int argc() const { return ArgcBits::decode(bit_field_); } convert_mode()41 ConvertReceiverMode convert_mode() const { 42 return ConvertModeBits::decode(bit_field_); 43 } tail_call_mode()44 TailCallMode tail_call_mode() const { 45 return TailCallModeBits::decode(bit_field_); 46 } 47 48 private: 49 typedef BitField<int, 0, Code::kArgumentsBits> ArgcBits; 50 typedef BitField<ConvertReceiverMode, ArgcBits::kNext, 2> ConvertModeBits; 51 typedef BitField<TailCallMode, ConvertModeBits::kNext, 1> TailCallModeBits; 52 53 int const bit_field_; 54 }; 55 56 57 std::ostream& operator<<(std::ostream& os, const CallICState& s); 58 59 60 class BinaryOpICState final BASE_EMBEDDED { 61 public: 62 BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state); BinaryOpICState(Isolate * isolate,Token::Value op)63 BinaryOpICState(Isolate* isolate, Token::Value op) 64 : op_(op), 65 left_kind_(NONE), 66 right_kind_(NONE), 67 result_kind_(NONE), 68 fixed_right_arg_(Nothing<int>()), 69 isolate_(isolate) { 70 DCHECK_LE(FIRST_TOKEN, op); 71 DCHECK_LE(op, LAST_TOKEN); 72 } 73 GetICState()74 InlineCacheState GetICState() const { 75 if (Max(left_kind_, right_kind_) == NONE) { 76 return ::v8::internal::UNINITIALIZED; 77 } 78 if (Max(left_kind_, right_kind_) == GENERIC) { 79 return ::v8::internal::MEGAMORPHIC; 80 } 81 if (Min(left_kind_, right_kind_) == GENERIC) { 82 return ::v8::internal::GENERIC; 83 } 84 return ::v8::internal::MONOMORPHIC; 85 } 86 87 ExtraICState GetExtraICState() const; 88 89 static void GenerateAheadOfTime(Isolate*, 90 void (*Generate)(Isolate*, 91 const BinaryOpICState&)); 92 93 // Returns true if the IC _could_ create allocation mementos. CouldCreateAllocationMementos()94 bool CouldCreateAllocationMementos() const { 95 if (left_kind_ == STRING || right_kind_ == STRING) { 96 DCHECK_EQ(Token::ADD, op_); 97 return true; 98 } 99 return false; 100 } 101 102 // Returns true if the IC _should_ create allocation mementos. ShouldCreateAllocationMementos()103 bool ShouldCreateAllocationMementos() const { 104 return FLAG_allocation_site_pretenuring && CouldCreateAllocationMementos(); 105 } 106 HasSideEffects()107 bool HasSideEffects() const { 108 return Max(left_kind_, right_kind_) == GENERIC; 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 // When fixed right arg is set, we don't need to store the right kind. 150 // Thus the two fields can overlap. 151 class HasFixedRightArgField : public BitField<bool, 10, 1> {}; 152 class FixedRightArgValueField : public BitField<int, 11, 4> {}; 153 class RightKindField : public BitField<Kind, 11, 3> {}; 154 155 Token::Value op_; 156 Kind left_kind_; 157 Kind right_kind_; 158 Kind result_kind_; 159 Maybe<int> fixed_right_arg_; 160 Isolate* isolate_; 161 }; 162 163 164 std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s); 165 166 167 class CompareICState { 168 public: 169 // The type/state lattice is defined by the following inequations: 170 // UNINITIALIZED < ... 171 // ... < GENERIC 172 // SMI < NUMBER 173 // INTERNALIZED_STRING < STRING 174 // INTERNALIZED_STRING < UNIQUE_NAME 175 // KNOWN_RECEIVER < RECEIVER 176 enum State { 177 UNINITIALIZED, 178 BOOLEAN, 179 SMI, 180 NUMBER, 181 STRING, 182 INTERNALIZED_STRING, 183 UNIQUE_NAME, // Symbol or InternalizedString 184 RECEIVER, // JSReceiver 185 KNOWN_RECEIVER, // JSReceiver with specific map (faster check) 186 GENERIC 187 }; 188 189 static Type* StateToType(Zone* zone, State state, 190 Handle<Map> map = Handle<Map>()); 191 192 static State NewInputState(State old_state, Handle<Object> value); 193 194 static const char* GetStateName(CompareICState::State state); 195 196 static State TargetState(Isolate* isolate, State old_state, State old_left, 197 State old_right, Token::Value op, 198 bool has_inlined_smi_code, Handle<Object> x, 199 Handle<Object> y); 200 }; 201 202 class LoadGlobalICState final BASE_EMBEDDED { 203 private: 204 class TypeofModeBits : public BitField<TypeofMode, 0, 1> {}; 205 STATIC_ASSERT(static_cast<int>(INSIDE_TYPEOF) == 0); 206 const ExtraICState state_; 207 208 public: 209 static const uint32_t kNextBitFieldOffset = TypeofModeBits::kNext; 210 LoadGlobalICState(ExtraICState extra_ic_state)211 explicit LoadGlobalICState(ExtraICState extra_ic_state) 212 : state_(extra_ic_state) {} 213 LoadGlobalICState(TypeofMode typeof_mode)214 explicit LoadGlobalICState(TypeofMode typeof_mode) 215 : state_(TypeofModeBits::encode(typeof_mode)) {} 216 GetExtraICState()217 ExtraICState GetExtraICState() const { return state_; } 218 typeof_mode()219 TypeofMode typeof_mode() const { return TypeofModeBits::decode(state_); } 220 GetTypeofMode(ExtraICState state)221 static TypeofMode GetTypeofMode(ExtraICState state) { 222 return LoadGlobalICState(state).typeof_mode(); 223 } 224 }; 225 226 227 class StoreICState final BASE_EMBEDDED { 228 public: StoreICState(ExtraICState extra_ic_state)229 explicit StoreICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {} 230 StoreICState(LanguageMode mode)231 explicit StoreICState(LanguageMode mode) 232 : state_(LanguageModeState::encode(mode)) {} 233 GetExtraICState()234 ExtraICState GetExtraICState() const { return state_; } 235 language_mode()236 LanguageMode language_mode() const { 237 return LanguageModeState::decode(state_); 238 } 239 GetLanguageMode(ExtraICState state)240 static LanguageMode GetLanguageMode(ExtraICState state) { 241 return StoreICState(state).language_mode(); 242 } 243 244 class LanguageModeState : public BitField<LanguageMode, 1, 2> {}; 245 STATIC_ASSERT(i::LANGUAGE_END == 3); 246 247 // For convenience, a statically declared encoding of strict mode extra 248 // IC state. 249 static const ExtraICState kStrictModeState = STRICT 250 << LanguageModeState::kShift; 251 252 private: 253 const ExtraICState state_; 254 }; 255 256 } // namespace internal 257 } // namespace v8 258 259 #endif // V8_IC_STATE_H_ 260