• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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