[presubmit] Enable readability/namespace linter checking.
[platform/upstream/v8.git] / src / ic / ic-state.h
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:
26   explicit CallICState(ExtraICState extra_ic_state);
27
28   enum CallType { METHOD, FUNCTION };
29
30   CallICState(int argc, CallType call_type)
31       : argc_(argc), call_type_(call_type) {}
32
33   ExtraICState GetExtraICState() const;
34
35   static void GenerateAheadOfTime(Isolate*,
36                                   void (*Generate)(Isolate*,
37                                                    const CallICState&));
38
39   int arg_count() const { return argc_; }
40   CallType call_type() const { return call_type_; }
41
42   bool CallAsMethod() const { return call_type_ == METHOD; }
43
44  private:
45   class ArgcBits : public BitField<int, 0, Code::kArgumentsBits> {};
46   class CallTypeBits : public BitField<CallType, Code::kArgumentsBits, 1> {};
47
48   const int argc_;
49   const CallType call_type_;
50 };
51
52
53 std::ostream& operator<<(std::ostream& os, const CallICState& s);
54
55
56 class BinaryOpICState final BASE_EMBEDDED {
57  public:
58   BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state);
59   BinaryOpICState(Isolate* isolate, Token::Value op, Strength strength)
60       : op_(op),
61         strong_(is_strong(strength)),
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
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.
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.
100   bool ShouldCreateAllocationMementos() const {
101     return FLAG_allocation_site_pretenuring && CouldCreateAllocationMementos();
102   }
103
104   bool HasSideEffects() const {
105     return Max(left_kind_, right_kind_) == GENERIC;
106   }
107
108   Strength strength() const {
109     return strong_ ? Strength::STRONG : Strength::WEAK;
110   }
111
112   // Returns true if the IC should enable the inline smi code (i.e. if either
113   // parameter may be a smi).
114   bool UseInlinedSmiCode() const {
115     return KindMaybeSmi(left_kind_) || KindMaybeSmi(right_kind_);
116   }
117
118   static const int FIRST_TOKEN = Token::BIT_OR;
119   static const int LAST_TOKEN = Token::MOD;
120
121   Token::Value op() const { return op_; }
122   Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
123
124   Type* GetLeftType(Zone* zone) const { return KindToType(left_kind_, zone); }
125   Type* GetRightType(Zone* zone) const { return KindToType(right_kind_, zone); }
126   Type* GetResultType(Zone* zone) const;
127
128   void Update(Handle<Object> left, Handle<Object> right, Handle<Object> result);
129
130   Isolate* isolate() const { return isolate_; }
131
132  private:
133   friend std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s);
134
135   enum Kind { NONE, SMI, INT32, NUMBER, STRING, GENERIC };
136
137   Kind UpdateKind(Handle<Object> object, Kind kind) const;
138
139   static const char* KindToString(Kind kind);
140   static Type* KindToType(Kind kind, Zone* zone);
141   static bool KindMaybeSmi(Kind kind) {
142     return (kind >= SMI && kind <= NUMBER) || kind == GENERIC;
143   }
144
145   // We truncate the last bit of the token.
146   STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 4));
147   class OpField : public BitField<int, 0, 4> {};
148   class ResultKindField : public BitField<Kind, 4, 3> {};
149   class LeftKindField : public BitField<Kind, 7, 3> {};
150   class StrengthField : public BitField<bool, 10, 1> {};
151   // When fixed right arg is set, we don't need to store the right kind.
152   // Thus the two fields can overlap.
153   class HasFixedRightArgField : public BitField<bool, 11, 1> {};
154   class FixedRightArgValueField : public BitField<int, 12, 4> {};
155   class RightKindField : public BitField<Kind, 12, 3> {};
156
157   Token::Value op_;
158   bool strong_;
159   Kind left_kind_;
160   Kind right_kind_;
161   Kind result_kind_;
162   Maybe<int> fixed_right_arg_;
163   Isolate* isolate_;
164 };
165
166
167 std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s);
168
169
170 class CompareICState {
171  public:
172   // The type/state lattice is defined by the following inequations:
173   //   UNINITIALIZED < ...
174   //   ... < GENERIC
175   //   SMI < NUMBER
176   //   INTERNALIZED_STRING < STRING
177   //   INTERNALIZED_STRING < UNIQUE_NAME
178   //   KNOWN_OBJECT < OBJECT
179   enum State {
180     UNINITIALIZED,
181     BOOLEAN,
182     SMI,
183     NUMBER,
184     STRING,
185     INTERNALIZED_STRING,
186     UNIQUE_NAME,   // Symbol or InternalizedString
187     OBJECT,        // JSObject
188     KNOWN_OBJECT,  // JSObject with specific map (faster check)
189     GENERIC
190   };
191
192   static Type* StateToType(Zone* zone, State state,
193                            Handle<Map> map = Handle<Map>());
194
195   static State NewInputState(State old_state, Handle<Object> value);
196
197   static const char* GetStateName(CompareICState::State state);
198
199   static State TargetState(State old_state, State old_left, State old_right,
200                            Token::Value op, bool has_inlined_smi_code,
201                            Handle<Object> x, Handle<Object> y);
202 };
203
204
205 class LoadICState final BASE_EMBEDDED {
206  private:
207   class TypeofModeBits : public BitField<TypeofMode, 0, 1> {};
208   class LanguageModeBits
209       : public BitField<LanguageMode, TypeofModeBits::kNext, 2> {};
210   STATIC_ASSERT(static_cast<int>(INSIDE_TYPEOF) == 0);
211   const ExtraICState state_;
212
213  public:
214   static const uint32_t kNextBitFieldOffset = LanguageModeBits::kNext;
215
216   static const ExtraICState kStrongModeState = STRONG
217                                                << LanguageModeBits::kShift;
218
219   explicit LoadICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {}
220
221   explicit LoadICState(TypeofMode typeof_mode, LanguageMode language_mode)
222       : state_(TypeofModeBits::encode(typeof_mode) |
223                LanguageModeBits::encode(language_mode)) {}
224
225   ExtraICState GetExtraICState() const { return state_; }
226
227   TypeofMode typeof_mode() const { return TypeofModeBits::decode(state_); }
228
229   LanguageMode language_mode() const {
230     return LanguageModeBits::decode(state_);
231   }
232
233   static TypeofMode GetTypeofMode(ExtraICState state) {
234     return LoadICState(state).typeof_mode();
235   }
236
237   static LanguageMode GetLanguageMode(ExtraICState state) {
238     return LoadICState(state).language_mode();
239   }
240 };
241
242
243 class StoreICState final BASE_EMBEDDED {
244  public:
245   explicit StoreICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {}
246
247   explicit StoreICState(LanguageMode mode)
248       : state_(LanguageModeState::encode(mode)) {}
249
250   ExtraICState GetExtraICState() const { return state_; }
251
252   LanguageMode language_mode() const {
253     return LanguageModeState::decode(state_);
254   }
255
256   static LanguageMode GetLanguageMode(ExtraICState state) {
257     return StoreICState(state).language_mode();
258   }
259
260   class LanguageModeState : public BitField<LanguageMode, 1, 2> {};
261   STATIC_ASSERT(i::LANGUAGE_END == 3);
262
263   // For convenience, a statically declared encoding of strict mode extra
264   // IC state.
265   static const ExtraICState kStrictModeState = STRICT
266                                                << LanguageModeState::kShift;
267
268  private:
269   const ExtraICState state_;
270 };
271
272 }  // namespace internal
273 }  // namespace v8
274
275 #endif  // V8_IC_STATE_H_