Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / v8 / src / ic / ic-state.cc
1 // Copyright 2014 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 #include "src/v8.h"
6
7 #include "src/ic/ic.h"
8 #include "src/ic/ic-state.h"
9
10 namespace v8 {
11 namespace internal {
12
13 // static
14 void ICUtility::Clear(Isolate* isolate, Address address,
15                       ConstantPoolArray* constant_pool) {
16   IC::Clear(isolate, address, constant_pool);
17 }
18
19
20 // static
21 template <class Nexus>
22 void ICUtility::Clear(Isolate* isolate, Code::Kind kind, Code* host,
23                       Nexus* nexus) {
24   IC::Clear<Nexus>(isolate, kind, host, nexus);
25 }
26
27
28 // Force instantiation of template instances for vector-based IC clearing.
29 template void ICUtility::Clear<CallICNexus>(Isolate*, Code::Kind, Code*,
30                                             CallICNexus*);
31
32
33 CallICState::CallICState(ExtraICState extra_ic_state)
34     : argc_(ArgcBits::decode(extra_ic_state)),
35       call_type_(CallTypeBits::decode(extra_ic_state)) {}
36
37
38 ExtraICState CallICState::GetExtraICState() const {
39   ExtraICState extra_ic_state =
40       ArgcBits::encode(argc_) | CallTypeBits::encode(call_type_);
41   return extra_ic_state;
42 }
43
44
45 std::ostream& operator<<(std::ostream& os, const CallICState& s) {
46   return os << "(args(" << s.arg_count() << "), "
47             << (s.call_type() == CallICState::METHOD ? "METHOD" : "FUNCTION")
48             << ", ";
49 }
50
51
52 BinaryOpICState::BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state)
53     : isolate_(isolate) {
54   op_ =
55       static_cast<Token::Value>(FIRST_TOKEN + OpField::decode(extra_ic_state));
56   mode_ = OverwriteModeField::decode(extra_ic_state);
57   fixed_right_arg_ =
58       Maybe<int>(HasFixedRightArgField::decode(extra_ic_state),
59                  1 << FixedRightArgValueField::decode(extra_ic_state));
60   left_kind_ = LeftKindField::decode(extra_ic_state);
61   if (fixed_right_arg_.has_value) {
62     right_kind_ = Smi::IsValid(fixed_right_arg_.value) ? SMI : INT32;
63   } else {
64     right_kind_ = RightKindField::decode(extra_ic_state);
65   }
66   result_kind_ = ResultKindField::decode(extra_ic_state);
67   DCHECK_LE(FIRST_TOKEN, op_);
68   DCHECK_LE(op_, LAST_TOKEN);
69 }
70
71
72 ExtraICState BinaryOpICState::GetExtraICState() const {
73   ExtraICState extra_ic_state =
74       OpField::encode(op_ - FIRST_TOKEN) | OverwriteModeField::encode(mode_) |
75       LeftKindField::encode(left_kind_) |
76       ResultKindField::encode(result_kind_) |
77       HasFixedRightArgField::encode(fixed_right_arg_.has_value);
78   if (fixed_right_arg_.has_value) {
79     extra_ic_state = FixedRightArgValueField::update(
80         extra_ic_state, WhichPowerOf2(fixed_right_arg_.value));
81   } else {
82     extra_ic_state = RightKindField::update(extra_ic_state, right_kind_);
83   }
84   return extra_ic_state;
85 }
86
87
88 // static
89 void BinaryOpICState::GenerateAheadOfTime(
90     Isolate* isolate, void (*Generate)(Isolate*, const BinaryOpICState&)) {
91 // TODO(olivf) We should investigate why adding stubs to the snapshot is so
92 // expensive at runtime. When solved we should be able to add most binops to
93 // the snapshot instead of hand-picking them.
94 // Generated list of commonly used stubs
95 #define GENERATE(op, left_kind, right_kind, result_kind, mode) \
96   do {                                                         \
97     BinaryOpICState state(isolate, op, mode);                  \
98     state.left_kind_ = left_kind;                              \
99     state.fixed_right_arg_.has_value = false;                  \
100     state.right_kind_ = right_kind;                            \
101     state.result_kind_ = result_kind;                          \
102     Generate(isolate, state);                                  \
103   } while (false)
104   GENERATE(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE);
105   GENERATE(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT);
106   GENERATE(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE);
107   GENERATE(Token::ADD, INT32, INT32, NUMBER, OVERWRITE_LEFT);
108   GENERATE(Token::ADD, INT32, NUMBER, NUMBER, NO_OVERWRITE);
109   GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
110   GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT);
111   GENERATE(Token::ADD, INT32, SMI, INT32, NO_OVERWRITE);
112   GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_LEFT);
113   GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_RIGHT);
114   GENERATE(Token::ADD, NUMBER, INT32, NUMBER, NO_OVERWRITE);
115   GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
116   GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT);
117   GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
118   GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
119   GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
120   GENERATE(Token::ADD, NUMBER, SMI, NUMBER, NO_OVERWRITE);
121   GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
122   GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
123   GENERATE(Token::ADD, SMI, INT32, INT32, NO_OVERWRITE);
124   GENERATE(Token::ADD, SMI, INT32, INT32, OVERWRITE_LEFT);
125   GENERATE(Token::ADD, SMI, INT32, NUMBER, NO_OVERWRITE);
126   GENERATE(Token::ADD, SMI, NUMBER, NUMBER, NO_OVERWRITE);
127   GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
128   GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
129   GENERATE(Token::ADD, SMI, SMI, INT32, OVERWRITE_LEFT);
130   GENERATE(Token::ADD, SMI, SMI, SMI, OVERWRITE_RIGHT);
131   GENERATE(Token::BIT_AND, INT32, INT32, INT32, NO_OVERWRITE);
132   GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_LEFT);
133   GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_RIGHT);
134   GENERATE(Token::BIT_AND, INT32, INT32, SMI, NO_OVERWRITE);
135   GENERATE(Token::BIT_AND, INT32, INT32, SMI, OVERWRITE_RIGHT);
136   GENERATE(Token::BIT_AND, INT32, SMI, INT32, NO_OVERWRITE);
137   GENERATE(Token::BIT_AND, INT32, SMI, INT32, OVERWRITE_RIGHT);
138   GENERATE(Token::BIT_AND, INT32, SMI, SMI, NO_OVERWRITE);
139   GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_LEFT);
140   GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_RIGHT);
141   GENERATE(Token::BIT_AND, NUMBER, INT32, INT32, OVERWRITE_RIGHT);
142   GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, NO_OVERWRITE);
143   GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
144   GENERATE(Token::BIT_AND, SMI, INT32, INT32, NO_OVERWRITE);
145   GENERATE(Token::BIT_AND, SMI, INT32, SMI, OVERWRITE_RIGHT);
146   GENERATE(Token::BIT_AND, SMI, NUMBER, SMI, OVERWRITE_RIGHT);
147   GENERATE(Token::BIT_AND, SMI, SMI, SMI, NO_OVERWRITE);
148   GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_LEFT);
149   GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_RIGHT);
150   GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_LEFT);
151   GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_RIGHT);
152   GENERATE(Token::BIT_OR, INT32, INT32, SMI, OVERWRITE_LEFT);
153   GENERATE(Token::BIT_OR, INT32, SMI, INT32, NO_OVERWRITE);
154   GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_LEFT);
155   GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_RIGHT);
156   GENERATE(Token::BIT_OR, INT32, SMI, SMI, NO_OVERWRITE);
157   GENERATE(Token::BIT_OR, INT32, SMI, SMI, OVERWRITE_RIGHT);
158   GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, NO_OVERWRITE);
159   GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_LEFT);
160   GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_RIGHT);
161   GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, NO_OVERWRITE);
162   GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, OVERWRITE_LEFT);
163   GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_LEFT);
164   GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_RIGHT);
165   GENERATE(Token::BIT_OR, SMI, INT32, SMI, OVERWRITE_RIGHT);
166   GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_LEFT);
167   GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_RIGHT);
168   GENERATE(Token::BIT_XOR, INT32, INT32, INT32, NO_OVERWRITE);
169   GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_LEFT);
170   GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_RIGHT);
171   GENERATE(Token::BIT_XOR, INT32, INT32, SMI, NO_OVERWRITE);
172   GENERATE(Token::BIT_XOR, INT32, INT32, SMI, OVERWRITE_LEFT);
173   GENERATE(Token::BIT_XOR, INT32, NUMBER, SMI, NO_OVERWRITE);
174   GENERATE(Token::BIT_XOR, INT32, SMI, INT32, NO_OVERWRITE);
175   GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_LEFT);
176   GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_RIGHT);
177   GENERATE(Token::BIT_XOR, NUMBER, INT32, INT32, NO_OVERWRITE);
178   GENERATE(Token::BIT_XOR, NUMBER, SMI, INT32, NO_OVERWRITE);
179   GENERATE(Token::BIT_XOR, NUMBER, SMI, SMI, NO_OVERWRITE);
180   GENERATE(Token::BIT_XOR, SMI, INT32, INT32, NO_OVERWRITE);
181   GENERATE(Token::BIT_XOR, SMI, INT32, INT32, OVERWRITE_LEFT);
182   GENERATE(Token::BIT_XOR, SMI, INT32, SMI, OVERWRITE_LEFT);
183   GENERATE(Token::BIT_XOR, SMI, SMI, SMI, NO_OVERWRITE);
184   GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_LEFT);
185   GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_RIGHT);
186   GENERATE(Token::DIV, INT32, INT32, INT32, NO_OVERWRITE);
187   GENERATE(Token::DIV, INT32, INT32, NUMBER, NO_OVERWRITE);
188   GENERATE(Token::DIV, INT32, NUMBER, NUMBER, NO_OVERWRITE);
189   GENERATE(Token::DIV, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
190   GENERATE(Token::DIV, INT32, SMI, INT32, NO_OVERWRITE);
191   GENERATE(Token::DIV, INT32, SMI, NUMBER, NO_OVERWRITE);
192   GENERATE(Token::DIV, NUMBER, INT32, NUMBER, NO_OVERWRITE);
193   GENERATE(Token::DIV, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
194   GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
195   GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
196   GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
197   GENERATE(Token::DIV, NUMBER, SMI, NUMBER, NO_OVERWRITE);
198   GENERATE(Token::DIV, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
199   GENERATE(Token::DIV, SMI, INT32, INT32, NO_OVERWRITE);
200   GENERATE(Token::DIV, SMI, INT32, NUMBER, NO_OVERWRITE);
201   GENERATE(Token::DIV, SMI, INT32, NUMBER, OVERWRITE_LEFT);
202   GENERATE(Token::DIV, SMI, NUMBER, NUMBER, NO_OVERWRITE);
203   GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
204   GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
205   GENERATE(Token::DIV, SMI, SMI, NUMBER, NO_OVERWRITE);
206   GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_LEFT);
207   GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_RIGHT);
208   GENERATE(Token::DIV, SMI, SMI, SMI, NO_OVERWRITE);
209   GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_LEFT);
210   GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_RIGHT);
211   GENERATE(Token::MOD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
212   GENERATE(Token::MOD, SMI, SMI, SMI, NO_OVERWRITE);
213   GENERATE(Token::MOD, SMI, SMI, SMI, OVERWRITE_LEFT);
214   GENERATE(Token::MUL, INT32, INT32, INT32, NO_OVERWRITE);
215   GENERATE(Token::MUL, INT32, INT32, NUMBER, NO_OVERWRITE);
216   GENERATE(Token::MUL, INT32, NUMBER, NUMBER, NO_OVERWRITE);
217   GENERATE(Token::MUL, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
218   GENERATE(Token::MUL, INT32, SMI, INT32, NO_OVERWRITE);
219   GENERATE(Token::MUL, INT32, SMI, INT32, OVERWRITE_LEFT);
220   GENERATE(Token::MUL, INT32, SMI, NUMBER, NO_OVERWRITE);
221   GENERATE(Token::MUL, NUMBER, INT32, NUMBER, NO_OVERWRITE);
222   GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
223   GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT);
224   GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
225   GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
226   GENERATE(Token::MUL, NUMBER, SMI, NUMBER, NO_OVERWRITE);
227   GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
228   GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
229   GENERATE(Token::MUL, SMI, INT32, INT32, NO_OVERWRITE);
230   GENERATE(Token::MUL, SMI, INT32, INT32, OVERWRITE_LEFT);
231   GENERATE(Token::MUL, SMI, INT32, NUMBER, NO_OVERWRITE);
232   GENERATE(Token::MUL, SMI, NUMBER, NUMBER, NO_OVERWRITE);
233   GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
234   GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
235   GENERATE(Token::MUL, SMI, SMI, INT32, NO_OVERWRITE);
236   GENERATE(Token::MUL, SMI, SMI, NUMBER, NO_OVERWRITE);
237   GENERATE(Token::MUL, SMI, SMI, NUMBER, OVERWRITE_LEFT);
238   GENERATE(Token::MUL, SMI, SMI, SMI, NO_OVERWRITE);
239   GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_LEFT);
240   GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_RIGHT);
241   GENERATE(Token::SAR, INT32, SMI, INT32, OVERWRITE_RIGHT);
242   GENERATE(Token::SAR, INT32, SMI, SMI, NO_OVERWRITE);
243   GENERATE(Token::SAR, INT32, SMI, SMI, OVERWRITE_RIGHT);
244   GENERATE(Token::SAR, NUMBER, SMI, SMI, NO_OVERWRITE);
245   GENERATE(Token::SAR, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
246   GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_LEFT);
247   GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_RIGHT);
248   GENERATE(Token::SHL, INT32, SMI, INT32, NO_OVERWRITE);
249   GENERATE(Token::SHL, INT32, SMI, INT32, OVERWRITE_RIGHT);
250   GENERATE(Token::SHL, INT32, SMI, SMI, NO_OVERWRITE);
251   GENERATE(Token::SHL, INT32, SMI, SMI, OVERWRITE_RIGHT);
252   GENERATE(Token::SHL, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
253   GENERATE(Token::SHL, SMI, SMI, INT32, NO_OVERWRITE);
254   GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_LEFT);
255   GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_RIGHT);
256   GENERATE(Token::SHL, SMI, SMI, SMI, NO_OVERWRITE);
257   GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_LEFT);
258   GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_RIGHT);
259   GENERATE(Token::SHR, INT32, SMI, SMI, NO_OVERWRITE);
260   GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_LEFT);
261   GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_RIGHT);
262   GENERATE(Token::SHR, NUMBER, SMI, SMI, NO_OVERWRITE);
263   GENERATE(Token::SHR, NUMBER, SMI, SMI, OVERWRITE_LEFT);
264   GENERATE(Token::SHR, NUMBER, SMI, INT32, OVERWRITE_RIGHT);
265   GENERATE(Token::SHR, SMI, SMI, SMI, NO_OVERWRITE);
266   GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_LEFT);
267   GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_RIGHT);
268   GENERATE(Token::SUB, INT32, INT32, INT32, NO_OVERWRITE);
269   GENERATE(Token::SUB, INT32, INT32, INT32, OVERWRITE_LEFT);
270   GENERATE(Token::SUB, INT32, NUMBER, NUMBER, NO_OVERWRITE);
271   GENERATE(Token::SUB, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT);
272   GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_LEFT);
273   GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_RIGHT);
274   GENERATE(Token::SUB, NUMBER, INT32, NUMBER, NO_OVERWRITE);
275   GENERATE(Token::SUB, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
276   GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
277   GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
278   GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
279   GENERATE(Token::SUB, NUMBER, SMI, NUMBER, NO_OVERWRITE);
280   GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
281   GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
282   GENERATE(Token::SUB, SMI, INT32, INT32, NO_OVERWRITE);
283   GENERATE(Token::SUB, SMI, NUMBER, NUMBER, NO_OVERWRITE);
284   GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
285   GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
286   GENERATE(Token::SUB, SMI, SMI, SMI, NO_OVERWRITE);
287   GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_LEFT);
288   GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_RIGHT);
289 #undef GENERATE
290 #define GENERATE(op, left_kind, fixed_right_arg_value, result_kind, mode) \
291   do {                                                                    \
292     BinaryOpICState state(isolate, op, mode);                             \
293     state.left_kind_ = left_kind;                                         \
294     state.fixed_right_arg_.has_value = true;                              \
295     state.fixed_right_arg_.value = fixed_right_arg_value;                 \
296     state.right_kind_ = SMI;                                              \
297     state.result_kind_ = result_kind;                                     \
298     Generate(isolate, state);                                             \
299   } while (false)
300   GENERATE(Token::MOD, SMI, 2, SMI, NO_OVERWRITE);
301   GENERATE(Token::MOD, SMI, 4, SMI, NO_OVERWRITE);
302   GENERATE(Token::MOD, SMI, 4, SMI, OVERWRITE_LEFT);
303   GENERATE(Token::MOD, SMI, 8, SMI, NO_OVERWRITE);
304   GENERATE(Token::MOD, SMI, 16, SMI, OVERWRITE_LEFT);
305   GENERATE(Token::MOD, SMI, 32, SMI, NO_OVERWRITE);
306   GENERATE(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE);
307 #undef GENERATE
308 }
309
310
311 Type* BinaryOpICState::GetResultType(Zone* zone) const {
312   Kind result_kind = result_kind_;
313   if (HasSideEffects()) {
314     result_kind = NONE;
315   } else if (result_kind == GENERIC && op_ == Token::ADD) {
316     return Type::Union(Type::Number(zone), Type::String(zone), zone);
317   } else if (result_kind == NUMBER && op_ == Token::SHR) {
318     return Type::Unsigned32(zone);
319   }
320   DCHECK_NE(GENERIC, result_kind);
321   return KindToType(result_kind, zone);
322 }
323
324
325 std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s) {
326   os << "(" << Token::Name(s.op_);
327   if (s.mode_ == OVERWRITE_LEFT)
328     os << "_ReuseLeft";
329   else if (s.mode_ == OVERWRITE_RIGHT)
330     os << "_ReuseRight";
331   if (s.CouldCreateAllocationMementos()) os << "_CreateAllocationMementos";
332   os << ":" << BinaryOpICState::KindToString(s.left_kind_) << "*";
333   if (s.fixed_right_arg_.has_value) {
334     os << s.fixed_right_arg_.value;
335   } else {
336     os << BinaryOpICState::KindToString(s.right_kind_);
337   }
338   return os << "->" << BinaryOpICState::KindToString(s.result_kind_) << ")";
339 }
340
341
342 void BinaryOpICState::Update(Handle<Object> left, Handle<Object> right,
343                              Handle<Object> result) {
344   ExtraICState old_extra_ic_state = GetExtraICState();
345
346   left_kind_ = UpdateKind(left, left_kind_);
347   right_kind_ = UpdateKind(right, right_kind_);
348
349   int32_t fixed_right_arg_value = 0;
350   bool has_fixed_right_arg =
351       op_ == Token::MOD && right->ToInt32(&fixed_right_arg_value) &&
352       fixed_right_arg_value > 0 &&
353       base::bits::IsPowerOfTwo32(fixed_right_arg_value) &&
354       FixedRightArgValueField::is_valid(WhichPowerOf2(fixed_right_arg_value)) &&
355       (left_kind_ == SMI || left_kind_ == INT32) &&
356       (result_kind_ == NONE || !fixed_right_arg_.has_value);
357   fixed_right_arg_ = Maybe<int32_t>(has_fixed_right_arg, fixed_right_arg_value);
358
359   result_kind_ = UpdateKind(result, result_kind_);
360
361   if (!Token::IsTruncatingBinaryOp(op_)) {
362     Kind input_kind = Max(left_kind_, right_kind_);
363     if (result_kind_ < input_kind && input_kind <= NUMBER) {
364       result_kind_ = input_kind;
365     }
366   }
367
368   // We don't want to distinguish INT32 and NUMBER for string add (because
369   // NumberToString can't make use of this anyway).
370   if (left_kind_ == STRING && right_kind_ == INT32) {
371     DCHECK_EQ(STRING, result_kind_);
372     DCHECK_EQ(Token::ADD, op_);
373     right_kind_ = NUMBER;
374   } else if (right_kind_ == STRING && left_kind_ == INT32) {
375     DCHECK_EQ(STRING, result_kind_);
376     DCHECK_EQ(Token::ADD, op_);
377     left_kind_ = NUMBER;
378   }
379
380   // Reset overwrite mode unless we can actually make use of it, or may be able
381   // to make use of it at some point in the future.
382   if ((mode_ == OVERWRITE_LEFT && left_kind_ > NUMBER) ||
383       (mode_ == OVERWRITE_RIGHT && right_kind_ > NUMBER) ||
384       result_kind_ > NUMBER) {
385     mode_ = NO_OVERWRITE;
386   }
387
388   if (old_extra_ic_state == GetExtraICState()) {
389     // Tagged operations can lead to non-truncating HChanges
390     if (left->IsUndefined() || left->IsBoolean()) {
391       left_kind_ = GENERIC;
392     } else {
393       DCHECK(right->IsUndefined() || right->IsBoolean());
394       right_kind_ = GENERIC;
395     }
396   }
397 }
398
399
400 BinaryOpICState::Kind BinaryOpICState::UpdateKind(Handle<Object> object,
401                                                   Kind kind) const {
402   Kind new_kind = GENERIC;
403   bool is_truncating = Token::IsTruncatingBinaryOp(op());
404   if (object->IsBoolean() && is_truncating) {
405     // Booleans will be automatically truncated by HChange.
406     new_kind = INT32;
407   } else if (object->IsUndefined()) {
408     // Undefined will be automatically truncated by HChange.
409     new_kind = is_truncating ? INT32 : NUMBER;
410   } else if (object->IsSmi()) {
411     new_kind = SMI;
412   } else if (object->IsHeapNumber()) {
413     double value = Handle<HeapNumber>::cast(object)->value();
414     new_kind = IsInt32Double(value) ? INT32 : NUMBER;
415   } else if (object->IsString() && op() == Token::ADD) {
416     new_kind = STRING;
417   }
418   if (new_kind == INT32 && SmiValuesAre32Bits()) {
419     new_kind = NUMBER;
420   }
421   if (kind != NONE && ((new_kind <= NUMBER && kind > NUMBER) ||
422                        (new_kind > NUMBER && kind <= NUMBER))) {
423     new_kind = GENERIC;
424   }
425   return Max(kind, new_kind);
426 }
427
428
429 // static
430 const char* BinaryOpICState::KindToString(Kind kind) {
431   switch (kind) {
432     case NONE:
433       return "None";
434     case SMI:
435       return "Smi";
436     case INT32:
437       return "Int32";
438     case NUMBER:
439       return "Number";
440     case STRING:
441       return "String";
442     case GENERIC:
443       return "Generic";
444   }
445   UNREACHABLE();
446   return NULL;
447 }
448
449
450 // static
451 Type* BinaryOpICState::KindToType(Kind kind, Zone* zone) {
452   switch (kind) {
453     case NONE:
454       return Type::None(zone);
455     case SMI:
456       return Type::SignedSmall(zone);
457     case INT32:
458       return Type::Signed32(zone);
459     case NUMBER:
460       return Type::Number(zone);
461     case STRING:
462       return Type::String(zone);
463     case GENERIC:
464       return Type::Any(zone);
465   }
466   UNREACHABLE();
467   return NULL;
468 }
469
470
471 const char* CompareICState::GetStateName(State state) {
472   switch (state) {
473     case UNINITIALIZED:
474       return "UNINITIALIZED";
475     case SMI:
476       return "SMI";
477     case NUMBER:
478       return "NUMBER";
479     case INTERNALIZED_STRING:
480       return "INTERNALIZED_STRING";
481     case STRING:
482       return "STRING";
483     case UNIQUE_NAME:
484       return "UNIQUE_NAME";
485     case OBJECT:
486       return "OBJECT";
487     case KNOWN_OBJECT:
488       return "KNOWN_OBJECT";
489     case GENERIC:
490       return "GENERIC";
491   }
492   UNREACHABLE();
493   return NULL;
494 }
495
496
497 Type* CompareICState::StateToType(Zone* zone, State state, Handle<Map> map) {
498   switch (state) {
499     case UNINITIALIZED:
500       return Type::None(zone);
501     case SMI:
502       return Type::SignedSmall(zone);
503     case NUMBER:
504       return Type::Number(zone);
505     case STRING:
506       return Type::String(zone);
507     case INTERNALIZED_STRING:
508       return Type::InternalizedString(zone);
509     case UNIQUE_NAME:
510       return Type::UniqueName(zone);
511     case OBJECT:
512       return Type::Receiver(zone);
513     case KNOWN_OBJECT:
514       return map.is_null() ? Type::Receiver(zone) : Type::Class(map, zone);
515     case GENERIC:
516       return Type::Any(zone);
517   }
518   UNREACHABLE();
519   return NULL;
520 }
521
522
523 CompareICState::State CompareICState::NewInputState(State old_state,
524                                                     Handle<Object> value) {
525   switch (old_state) {
526     case UNINITIALIZED:
527       if (value->IsSmi()) return SMI;
528       if (value->IsHeapNumber()) return NUMBER;
529       if (value->IsInternalizedString()) return INTERNALIZED_STRING;
530       if (value->IsString()) return STRING;
531       if (value->IsSymbol()) return UNIQUE_NAME;
532       if (value->IsJSObject()) return OBJECT;
533       break;
534     case SMI:
535       if (value->IsSmi()) return SMI;
536       if (value->IsHeapNumber()) return NUMBER;
537       break;
538     case NUMBER:
539       if (value->IsNumber()) return NUMBER;
540       break;
541     case INTERNALIZED_STRING:
542       if (value->IsInternalizedString()) return INTERNALIZED_STRING;
543       if (value->IsString()) return STRING;
544       if (value->IsSymbol()) return UNIQUE_NAME;
545       break;
546     case STRING:
547       if (value->IsString()) return STRING;
548       break;
549     case UNIQUE_NAME:
550       if (value->IsUniqueName()) return UNIQUE_NAME;
551       break;
552     case OBJECT:
553       if (value->IsJSObject()) return OBJECT;
554       break;
555     case GENERIC:
556       break;
557     case KNOWN_OBJECT:
558       UNREACHABLE();
559       break;
560   }
561   return GENERIC;
562 }
563
564
565 // static
566 CompareICState::State CompareICState::TargetState(
567     State old_state, State old_left, State old_right, Token::Value op,
568     bool has_inlined_smi_code, Handle<Object> x, Handle<Object> y) {
569   switch (old_state) {
570     case UNINITIALIZED:
571       if (x->IsSmi() && y->IsSmi()) return SMI;
572       if (x->IsNumber() && y->IsNumber()) return NUMBER;
573       if (Token::IsOrderedRelationalCompareOp(op)) {
574         // Ordered comparisons treat undefined as NaN, so the
575         // NUMBER stub will do the right thing.
576         if ((x->IsNumber() && y->IsUndefined()) ||
577             (y->IsNumber() && x->IsUndefined())) {
578           return NUMBER;
579         }
580       }
581       if (x->IsInternalizedString() && y->IsInternalizedString()) {
582         // We compare internalized strings as plain ones if we need to determine
583         // the order in a non-equality compare.
584         return Token::IsEqualityOp(op) ? INTERNALIZED_STRING : STRING;
585       }
586       if (x->IsString() && y->IsString()) return STRING;
587       if (!Token::IsEqualityOp(op)) return GENERIC;
588       if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
589       if (x->IsJSObject() && y->IsJSObject()) {
590         if (Handle<JSObject>::cast(x)->map() ==
591             Handle<JSObject>::cast(y)->map()) {
592           return KNOWN_OBJECT;
593         } else {
594           return OBJECT;
595         }
596       }
597       return GENERIC;
598     case SMI:
599       return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC;
600     case INTERNALIZED_STRING:
601       DCHECK(Token::IsEqualityOp(op));
602       if (x->IsString() && y->IsString()) return STRING;
603       if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
604       return GENERIC;
605     case NUMBER:
606       // If the failure was due to one side changing from smi to heap number,
607       // then keep the state (if other changed at the same time, we will get
608       // a second miss and then go to generic).
609       if (old_left == SMI && x->IsHeapNumber()) return NUMBER;
610       if (old_right == SMI && y->IsHeapNumber()) return NUMBER;
611       return GENERIC;
612     case KNOWN_OBJECT:
613       DCHECK(Token::IsEqualityOp(op));
614       if (x->IsJSObject() && y->IsJSObject()) {
615         return OBJECT;
616       }
617       return GENERIC;
618     case STRING:
619     case UNIQUE_NAME:
620     case OBJECT:
621     case GENERIC:
622       return GENERIC;
623   }
624   UNREACHABLE();
625   return GENERIC;  // Make the compiler happy.
626 }
627 }
628 }  // namespace v8::internal