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