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