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, 21 ConstantPoolArray* constant_pool); 22 }; 23 24 25 class CallICState FINAL BASE_EMBEDDED { 26 public: 27 explicit CallICState(ExtraICState extra_ic_state); 28 29 enum CallType { METHOD, FUNCTION }; 30 CallICState(int argc,CallType call_type)31 CallICState(int argc, CallType call_type) 32 : argc_(argc), call_type_(call_type) {} 33 34 ExtraICState GetExtraICState() const; 35 36 static void GenerateAheadOfTime(Isolate*, 37 void (*Generate)(Isolate*, 38 const CallICState&)); 39 arg_count()40 int arg_count() const { return argc_; } call_type()41 CallType call_type() const { return call_type_; } 42 CallAsMethod()43 bool CallAsMethod() const { return call_type_ == METHOD; } 44 45 private: 46 class ArgcBits : public BitField<int, 0, Code::kArgumentsBits> {}; 47 class CallTypeBits : public BitField<CallType, Code::kArgumentsBits, 1> {}; 48 49 const int argc_; 50 const CallType call_type_; 51 }; 52 53 54 OStream& operator<<(OStream& os, const CallICState& s); 55 56 57 // Mode to overwrite BinaryExpression values. 58 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT }; 59 60 class BinaryOpICState FINAL BASE_EMBEDDED { 61 public: 62 BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state); 63 BinaryOpICState(Isolate * isolate,Token::Value op,OverwriteMode mode)64 BinaryOpICState(Isolate* isolate, Token::Value op, OverwriteMode mode) 65 : op_(op), 66 mode_(mode), 67 left_kind_(NONE), 68 right_kind_(NONE), 69 result_kind_(NONE), 70 isolate_(isolate) { 71 DCHECK_LE(FIRST_TOKEN, op); 72 DCHECK_LE(op, LAST_TOKEN); 73 } 74 GetICState()75 InlineCacheState GetICState() const { 76 if (Max(left_kind_, right_kind_) == NONE) { 77 return ::v8::internal::UNINITIALIZED; 78 } 79 if (Max(left_kind_, right_kind_) == GENERIC) { 80 return ::v8::internal::MEGAMORPHIC; 81 } 82 if (Min(left_kind_, right_kind_) == GENERIC) { 83 return ::v8::internal::GENERIC; 84 } 85 return ::v8::internal::MONOMORPHIC; 86 } 87 88 ExtraICState GetExtraICState() const; 89 90 static void GenerateAheadOfTime(Isolate*, 91 void (*Generate)(Isolate*, 92 const BinaryOpICState&)); 93 CanReuseDoubleBox()94 bool CanReuseDoubleBox() const { 95 return (result_kind_ > SMI && result_kind_ <= NUMBER) && 96 ((mode_ == OVERWRITE_LEFT && left_kind_ > SMI && 97 left_kind_ <= NUMBER) || 98 (mode_ == OVERWRITE_RIGHT && right_kind_ > SMI && 99 right_kind_ <= NUMBER)); 100 } 101 102 // Returns true if the IC _could_ create allocation mementos. CouldCreateAllocationMementos()103 bool CouldCreateAllocationMementos() const { 104 if (left_kind_ == STRING || right_kind_ == STRING) { 105 DCHECK_EQ(Token::ADD, op_); 106 return true; 107 } 108 return false; 109 } 110 111 // Returns true if the IC _should_ create allocation mementos. ShouldCreateAllocationMementos()112 bool ShouldCreateAllocationMementos() const { 113 return FLAG_allocation_site_pretenuring && CouldCreateAllocationMementos(); 114 } 115 HasSideEffects()116 bool HasSideEffects() const { 117 return Max(left_kind_, right_kind_) == GENERIC; 118 } 119 120 // Returns true if the IC should enable the inline smi code (i.e. if either 121 // parameter may be a smi). UseInlinedSmiCode()122 bool UseInlinedSmiCode() const { 123 return KindMaybeSmi(left_kind_) || KindMaybeSmi(right_kind_); 124 } 125 126 static const int FIRST_TOKEN = Token::BIT_OR; 127 static const int LAST_TOKEN = Token::MOD; 128 op()129 Token::Value op() const { return op_; } mode()130 OverwriteMode mode() const { return mode_; } fixed_right_arg()131 Maybe<int> fixed_right_arg() const { return fixed_right_arg_; } 132 GetLeftType(Zone * zone)133 Type* GetLeftType(Zone* zone) const { return KindToType(left_kind_, zone); } GetRightType(Zone * zone)134 Type* GetRightType(Zone* zone) const { return KindToType(right_kind_, zone); } 135 Type* GetResultType(Zone* zone) const; 136 137 void Update(Handle<Object> left, Handle<Object> right, Handle<Object> result); 138 isolate()139 Isolate* isolate() const { return isolate_; } 140 141 private: 142 friend OStream& operator<<(OStream& os, const BinaryOpICState& s); 143 144 enum Kind { NONE, SMI, INT32, NUMBER, STRING, GENERIC }; 145 146 Kind UpdateKind(Handle<Object> object, Kind kind) const; 147 148 static const char* KindToString(Kind kind); 149 static Type* KindToType(Kind kind, Zone* zone); KindMaybeSmi(Kind kind)150 static bool KindMaybeSmi(Kind kind) { 151 return (kind >= SMI && kind <= NUMBER) || kind == GENERIC; 152 } 153 154 // We truncate the last bit of the token. 155 STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 4)); 156 class OpField : public BitField<int, 0, 4> {}; 157 class OverwriteModeField : public BitField<OverwriteMode, 4, 2> {}; 158 class ResultKindField : public BitField<Kind, 6, 3> {}; 159 class LeftKindField : public BitField<Kind, 9, 3> {}; 160 // When fixed right arg is set, we don't need to store the right kind. 161 // Thus the two fields can overlap. 162 class HasFixedRightArgField : public BitField<bool, 12, 1> {}; 163 class FixedRightArgValueField : public BitField<int, 13, 4> {}; 164 class RightKindField : public BitField<Kind, 13, 3> {}; 165 166 Token::Value op_; 167 OverwriteMode mode_; 168 Kind left_kind_; 169 Kind right_kind_; 170 Kind result_kind_; 171 Maybe<int> fixed_right_arg_; 172 Isolate* isolate_; 173 }; 174 175 176 OStream& operator<<(OStream& os, const BinaryOpICState& s); 177 178 179 class CompareICState { 180 public: 181 // The type/state lattice is defined by the following inequations: 182 // UNINITIALIZED < ... 183 // ... < GENERIC 184 // SMI < NUMBER 185 // INTERNALIZED_STRING < STRING 186 // KNOWN_OBJECT < OBJECT 187 enum State { 188 UNINITIALIZED, 189 SMI, 190 NUMBER, 191 STRING, 192 INTERNALIZED_STRING, 193 UNIQUE_NAME, // Symbol or InternalizedString 194 OBJECT, // JSObject 195 KNOWN_OBJECT, // JSObject with specific map (faster check) 196 GENERIC 197 }; 198 199 static Type* StateToType(Zone* zone, State state, 200 Handle<Map> map = Handle<Map>()); 201 202 static State NewInputState(State old_state, Handle<Object> value); 203 204 static const char* GetStateName(CompareICState::State state); 205 206 static State TargetState(State old_state, State old_left, State old_right, 207 Token::Value op, bool has_inlined_smi_code, 208 Handle<Object> x, Handle<Object> y); 209 }; 210 211 212 class LoadICState FINAL BASE_EMBEDDED { 213 public: LoadICState(ExtraICState extra_ic_state)214 explicit LoadICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {} 215 LoadICState(ContextualMode mode)216 explicit LoadICState(ContextualMode mode) 217 : state_(ContextualModeBits::encode(mode)) {} 218 GetExtraICState()219 ExtraICState GetExtraICState() const { return state_; } 220 contextual_mode()221 ContextualMode contextual_mode() const { 222 return ContextualModeBits::decode(state_); 223 } 224 GetContextualMode(ExtraICState state)225 static ContextualMode GetContextualMode(ExtraICState state) { 226 return LoadICState(state).contextual_mode(); 227 } 228 229 private: 230 class ContextualModeBits : public BitField<ContextualMode, 0, 1> {}; 231 STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0); 232 233 const ExtraICState state_; 234 }; 235 } 236 } 237 238 #endif // V8_IC_STATE_H_ 239