• Home
  • 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 
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