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 
Clear(Isolate * isolate,Address address,ConstantPoolArray * constant_pool)13 void ICUtility::Clear(Isolate* isolate, Address address,
14                       ConstantPoolArray* constant_pool) {
15   IC::Clear(isolate, address, constant_pool);
16 }
17 
18 
CallICState(ExtraICState extra_ic_state)19 CallICState::CallICState(ExtraICState extra_ic_state)
20     : argc_(ArgcBits::decode(extra_ic_state)),
21       call_type_(CallTypeBits::decode(extra_ic_state)) {}
22 
23 
GetExtraICState() const24 ExtraICState CallICState::GetExtraICState() const {
25   ExtraICState extra_ic_state =
26       ArgcBits::encode(argc_) | CallTypeBits::encode(call_type_);
27   return extra_ic_state;
28 }
29 
30 
operator <<(OStream & os,const CallICState & s)31 OStream& 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 
BinaryOpICState(Isolate * isolate,ExtraICState extra_ic_state)38 BinaryOpICState::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 
GetExtraICState() const58 ExtraICState 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
GenerateAheadOfTime(Isolate * isolate,void (* Generate)(Isolate *,const BinaryOpICState &))75 void 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 
GetResultType(Zone * zone) const297 Type* 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 
operator <<(OStream & os,const BinaryOpICState & s)311 OStream& 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 
Update(Handle<Object> left,Handle<Object> right,Handle<Object> result)328 void 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 
UpdateKind(Handle<Object> object,Kind kind) const386 BinaryOpICState::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
KindToString(Kind kind)416 const 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
KindToType(Kind kind,Zone * zone)437 Type* 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 
GetStateName(State state)457 const 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 
StateToType(Zone * zone,State state,Handle<Map> map)483 Type* 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 
NewInputState(State old_state,Handle<Object> value)509 CompareICState::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
TargetState(State old_state,State old_left,State old_right,Token::Value op,bool has_inlined_smi_code,Handle<Object> x,Handle<Object> y)552 CompareICState::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