Line data Source code
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/ic/ic-state.h"
6 :
7 : #include "src/ast/ast-types.h"
8 : #include "src/feedback-vector.h"
9 : #include "src/ic/ic.h"
10 : #include "src/objects-inl.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 : // static
16 132634 : void ICUtility::Clear(Isolate* isolate, Address address,
17 : Address constant_pool) {
18 132634 : IC::Clear(isolate, address, constant_pool);
19 132634 : }
20 :
21 :
22 : // static
23 : STATIC_CONST_MEMBER_DEFINITION const int BinaryOpICState::FIRST_TOKEN;
24 :
25 :
26 : // static
27 : STATIC_CONST_MEMBER_DEFINITION const int BinaryOpICState::LAST_TOKEN;
28 :
29 :
30 2679937 : BinaryOpICState::BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state)
31 : : fixed_right_arg_(
32 2679937 : HasFixedRightArgField::decode(extra_ic_state)
33 1959 : ? Just(1 << FixedRightArgValueField::decode(extra_ic_state))
34 : : Nothing<int>()),
35 2681896 : isolate_(isolate) {
36 : op_ =
37 2679937 : static_cast<Token::Value>(FIRST_TOKEN + OpField::decode(extra_ic_state));
38 2679937 : left_kind_ = LeftKindField::decode(extra_ic_state);
39 2679937 : right_kind_ = fixed_right_arg_.IsJust()
40 : ? (Smi::IsValid(fixed_right_arg_.FromJust()) ? SMI : INT32)
41 5359874 : : RightKindField::decode(extra_ic_state);
42 2679937 : result_kind_ = ResultKindField::decode(extra_ic_state);
43 : DCHECK_LE(FIRST_TOKEN, op_);
44 : DCHECK_LE(op_, LAST_TOKEN);
45 2679937 : }
46 :
47 :
48 2144273 : ExtraICState BinaryOpICState::GetExtraICState() const {
49 : ExtraICState extra_ic_state =
50 8577092 : OpField::encode(op_ - FIRST_TOKEN) | LeftKindField::encode(left_kind_) |
51 4288546 : ResultKindField::encode(result_kind_) |
52 2144273 : HasFixedRightArgField::encode(fixed_right_arg_.IsJust());
53 2144273 : if (fixed_right_arg_.IsJust()) {
54 : extra_ic_state = FixedRightArgValueField::update(
55 2614 : extra_ic_state, WhichPowerOf2(fixed_right_arg_.FromJust()));
56 : } else {
57 4285932 : extra_ic_state = RightKindField::update(extra_ic_state, right_kind_);
58 : }
59 2144273 : return extra_ic_state;
60 : }
61 :
62 0 : std::string BinaryOpICState::ToString() const {
63 0 : std::string ret = "(";
64 0 : ret += Token::Name(op_);
65 0 : if (CouldCreateAllocationMementos()) ret += "_CreateAllocationMementos";
66 : ret += ":";
67 0 : ret += BinaryOpICState::KindToString(left_kind_);
68 : ret += "*";
69 0 : if (fixed_right_arg_.IsJust()) {
70 0 : ret += fixed_right_arg_.FromJust();
71 : } else {
72 0 : ret += BinaryOpICState::KindToString(right_kind_);
73 : }
74 : ret += "->";
75 0 : ret += BinaryOpICState::KindToString(result_kind_);
76 : ret += ")";
77 0 : return ret;
78 : }
79 :
80 : // static
81 86 : void BinaryOpICState::GenerateAheadOfTime(
82 : Isolate* isolate, void (*Generate)(Isolate*, const BinaryOpICState&)) {
83 : // TODO(olivf) We should investigate why adding stubs to the snapshot is so
84 : // expensive at runtime. When solved we should be able to add most binops to
85 : // the snapshot instead of hand-picking them.
86 : // Generated list of commonly used stubs
87 : #define GENERATE(op, left_kind, right_kind, result_kind) \
88 : do { \
89 : BinaryOpICState state(isolate, op); \
90 : state.left_kind_ = left_kind; \
91 : state.fixed_right_arg_ = Nothing<int>(); \
92 : state.right_kind_ = right_kind; \
93 : state.result_kind_ = result_kind; \
94 : Generate(isolate, state); \
95 : } while (false)
96 86 : GENERATE(Token::ADD, INT32, INT32, INT32);
97 86 : GENERATE(Token::ADD, INT32, INT32, NUMBER);
98 86 : GENERATE(Token::ADD, INT32, NUMBER, NUMBER);
99 86 : GENERATE(Token::ADD, INT32, SMI, INT32);
100 86 : GENERATE(Token::ADD, NUMBER, INT32, NUMBER);
101 86 : GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER);
102 86 : GENERATE(Token::ADD, NUMBER, SMI, NUMBER);
103 86 : GENERATE(Token::ADD, SMI, INT32, INT32);
104 86 : GENERATE(Token::ADD, SMI, INT32, NUMBER);
105 86 : GENERATE(Token::ADD, SMI, NUMBER, NUMBER);
106 86 : GENERATE(Token::ADD, SMI, SMI, INT32);
107 86 : GENERATE(Token::ADD, SMI, SMI, SMI);
108 86 : GENERATE(Token::BIT_AND, INT32, INT32, INT32);
109 86 : GENERATE(Token::BIT_AND, INT32, INT32, SMI);
110 86 : GENERATE(Token::BIT_AND, INT32, SMI, INT32);
111 86 : GENERATE(Token::BIT_AND, INT32, SMI, SMI);
112 86 : GENERATE(Token::BIT_AND, NUMBER, INT32, INT32);
113 86 : GENERATE(Token::BIT_AND, NUMBER, SMI, SMI);
114 86 : GENERATE(Token::BIT_AND, SMI, INT32, INT32);
115 86 : GENERATE(Token::BIT_AND, SMI, INT32, SMI);
116 86 : GENERATE(Token::BIT_AND, SMI, NUMBER, SMI);
117 86 : GENERATE(Token::BIT_AND, SMI, SMI, SMI);
118 86 : GENERATE(Token::BIT_OR, INT32, INT32, INT32);
119 86 : GENERATE(Token::BIT_OR, INT32, INT32, SMI);
120 86 : GENERATE(Token::BIT_OR, INT32, SMI, INT32);
121 86 : GENERATE(Token::BIT_OR, INT32, SMI, SMI);
122 86 : GENERATE(Token::BIT_OR, NUMBER, SMI, INT32);
123 86 : GENERATE(Token::BIT_OR, NUMBER, SMI, SMI);
124 86 : GENERATE(Token::BIT_OR, SMI, INT32, INT32);
125 86 : GENERATE(Token::BIT_OR, SMI, INT32, SMI);
126 86 : GENERATE(Token::BIT_OR, SMI, SMI, SMI);
127 86 : GENERATE(Token::BIT_XOR, INT32, INT32, INT32);
128 86 : GENERATE(Token::BIT_XOR, INT32, INT32, SMI);
129 86 : GENERATE(Token::BIT_XOR, INT32, NUMBER, SMI);
130 86 : GENERATE(Token::BIT_XOR, INT32, SMI, INT32);
131 86 : GENERATE(Token::BIT_XOR, NUMBER, INT32, INT32);
132 86 : GENERATE(Token::BIT_XOR, NUMBER, SMI, INT32);
133 86 : GENERATE(Token::BIT_XOR, NUMBER, SMI, SMI);
134 86 : GENERATE(Token::BIT_XOR, SMI, INT32, INT32);
135 86 : GENERATE(Token::BIT_XOR, SMI, INT32, SMI);
136 86 : GENERATE(Token::BIT_XOR, SMI, SMI, SMI);
137 86 : GENERATE(Token::DIV, INT32, INT32, INT32);
138 86 : GENERATE(Token::DIV, INT32, INT32, NUMBER);
139 86 : GENERATE(Token::DIV, INT32, NUMBER, NUMBER);
140 86 : GENERATE(Token::DIV, INT32, SMI, INT32);
141 86 : GENERATE(Token::DIV, INT32, SMI, NUMBER);
142 86 : GENERATE(Token::DIV, NUMBER, INT32, NUMBER);
143 86 : GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER);
144 86 : GENERATE(Token::DIV, NUMBER, SMI, NUMBER);
145 86 : GENERATE(Token::DIV, SMI, INT32, INT32);
146 86 : GENERATE(Token::DIV, SMI, INT32, NUMBER);
147 86 : GENERATE(Token::DIV, SMI, NUMBER, NUMBER);
148 86 : GENERATE(Token::DIV, SMI, SMI, NUMBER);
149 86 : GENERATE(Token::DIV, SMI, SMI, SMI);
150 86 : GENERATE(Token::MOD, NUMBER, SMI, NUMBER);
151 86 : GENERATE(Token::MOD, SMI, SMI, SMI);
152 86 : GENERATE(Token::MUL, INT32, INT32, INT32);
153 86 : GENERATE(Token::MUL, INT32, INT32, NUMBER);
154 86 : GENERATE(Token::MUL, INT32, NUMBER, NUMBER);
155 86 : GENERATE(Token::MUL, INT32, SMI, INT32);
156 86 : GENERATE(Token::MUL, INT32, SMI, NUMBER);
157 86 : GENERATE(Token::MUL, NUMBER, INT32, NUMBER);
158 86 : GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER);
159 86 : GENERATE(Token::MUL, NUMBER, SMI, NUMBER);
160 86 : GENERATE(Token::MUL, SMI, INT32, INT32);
161 86 : GENERATE(Token::MUL, SMI, INT32, NUMBER);
162 86 : GENERATE(Token::MUL, SMI, NUMBER, NUMBER);
163 86 : GENERATE(Token::MUL, SMI, SMI, INT32);
164 86 : GENERATE(Token::MUL, SMI, SMI, NUMBER);
165 86 : GENERATE(Token::MUL, SMI, SMI, SMI);
166 86 : GENERATE(Token::SAR, INT32, SMI, INT32);
167 86 : GENERATE(Token::SAR, INT32, SMI, SMI);
168 86 : GENERATE(Token::SAR, NUMBER, SMI, SMI);
169 86 : GENERATE(Token::SAR, SMI, SMI, SMI);
170 86 : GENERATE(Token::SHL, INT32, SMI, INT32);
171 86 : GENERATE(Token::SHL, INT32, SMI, SMI);
172 86 : GENERATE(Token::SHL, NUMBER, SMI, SMI);
173 86 : GENERATE(Token::SHL, SMI, SMI, INT32);
174 86 : GENERATE(Token::SHL, SMI, SMI, SMI);
175 86 : GENERATE(Token::SHR, INT32, SMI, SMI);
176 86 : GENERATE(Token::SHR, NUMBER, SMI, INT32);
177 86 : GENERATE(Token::SHR, NUMBER, SMI, SMI);
178 86 : GENERATE(Token::SHR, SMI, SMI, SMI);
179 86 : GENERATE(Token::SUB, INT32, INT32, INT32);
180 86 : GENERATE(Token::SUB, INT32, NUMBER, NUMBER);
181 86 : GENERATE(Token::SUB, INT32, SMI, INT32);
182 86 : GENERATE(Token::SUB, NUMBER, INT32, NUMBER);
183 86 : GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER);
184 86 : GENERATE(Token::SUB, NUMBER, SMI, NUMBER);
185 86 : GENERATE(Token::SUB, SMI, INT32, INT32);
186 86 : GENERATE(Token::SUB, SMI, NUMBER, NUMBER);
187 86 : GENERATE(Token::SUB, SMI, SMI, SMI);
188 : #undef GENERATE
189 : #define GENERATE(op, left_kind, fixed_right_arg_value, result_kind) \
190 : do { \
191 : BinaryOpICState state(isolate, op); \
192 : state.left_kind_ = left_kind; \
193 : state.fixed_right_arg_ = Just(fixed_right_arg_value); \
194 : state.right_kind_ = SMI; \
195 : state.result_kind_ = result_kind; \
196 : Generate(isolate, state); \
197 : } while (false)
198 86 : GENERATE(Token::MOD, SMI, 2, SMI);
199 86 : GENERATE(Token::MOD, SMI, 4, SMI);
200 86 : GENERATE(Token::MOD, SMI, 8, SMI);
201 86 : GENERATE(Token::MOD, SMI, 16, SMI);
202 86 : GENERATE(Token::MOD, SMI, 32, SMI);
203 86 : GENERATE(Token::MOD, SMI, 2048, SMI);
204 : #undef GENERATE
205 86 : }
206 :
207 1549070 : AstType* BinaryOpICState::GetResultType() const {
208 774535 : Kind result_kind = result_kind_;
209 774535 : if (HasSideEffects()) {
210 : result_kind = NONE;
211 768883 : } else if (result_kind == GENERIC && op_ == Token::ADD) {
212 : return AstType::NumberOrString();
213 768883 : } else if (result_kind == NUMBER && op_ == Token::SHR) {
214 : return AstType::Unsigned32();
215 : }
216 : DCHECK_NE(GENERIC, result_kind);
217 772879 : return KindToType(result_kind);
218 : }
219 :
220 :
221 121860 : std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s) {
222 121860 : os << "(" << Token::Name(s.op_);
223 60930 : if (s.CouldCreateAllocationMementos()) os << "_CreateAllocationMementos";
224 60930 : os << ":" << BinaryOpICState::KindToString(s.left_kind_) << "*";
225 60930 : if (s.fixed_right_arg_.IsJust()) {
226 418 : os << s.fixed_right_arg_.FromJust();
227 : } else {
228 60512 : os << BinaryOpICState::KindToString(s.right_kind_);
229 : }
230 60930 : return os << "->" << BinaryOpICState::KindToString(s.result_kind_) << ")";
231 : }
232 :
233 :
234 433805 : void BinaryOpICState::Update(Handle<Object> left, Handle<Object> right,
235 : Handle<Object> result) {
236 433805 : ExtraICState old_extra_ic_state = GetExtraICState();
237 :
238 433805 : left_kind_ = UpdateKind(left, left_kind_);
239 433805 : right_kind_ = UpdateKind(right, right_kind_);
240 :
241 433805 : int32_t fixed_right_arg_value = 0;
242 : bool has_fixed_right_arg =
243 442746 : op_ == Token::MOD && right->ToInt32(&fixed_right_arg_value) &&
244 5908 : fixed_right_arg_value > 0 &&
245 2880 : base::bits::IsPowerOfTwo32(fixed_right_arg_value) &&
246 1359 : FixedRightArgValueField::is_valid(WhichPowerOf2(fixed_right_arg_value)) &&
247 434937 : (left_kind_ == SMI || left_kind_ == INT32) &&
248 529 : (result_kind_ == NONE || !fixed_right_arg_.IsJust());
249 : fixed_right_arg_ =
250 433805 : has_fixed_right_arg ? Just(fixed_right_arg_value) : Nothing<int32_t>();
251 433805 : result_kind_ = UpdateKind(result, result_kind_);
252 :
253 867610 : if (!Token::IsTruncatingBinaryOp(op_)) {
254 301455 : Kind input_kind = Max(left_kind_, right_kind_);
255 301455 : if (result_kind_ < input_kind && input_kind <= NUMBER) {
256 10643 : result_kind_ = input_kind;
257 : }
258 : }
259 :
260 : // We don't want to distinguish INT32 and NUMBER for string add (because
261 : // NumberToString can't make use of this anyway).
262 433805 : if (left_kind_ == STRING && right_kind_ == INT32) {
263 : DCHECK_EQ(STRING, result_kind_);
264 : DCHECK_EQ(Token::ADD, op_);
265 0 : right_kind_ = NUMBER;
266 433805 : } else if (right_kind_ == STRING && left_kind_ == INT32) {
267 : DCHECK_EQ(STRING, result_kind_);
268 : DCHECK_EQ(Token::ADD, op_);
269 0 : left_kind_ = NUMBER;
270 : }
271 :
272 433805 : if (old_extra_ic_state == GetExtraICState()) {
273 : // Tagged operations can lead to non-truncating HChanges
274 721 : if (left->IsOddball()) {
275 47 : left_kind_ = GENERIC;
276 : } else {
277 : DCHECK(right->IsOddball());
278 674 : right_kind_ = GENERIC;
279 : }
280 : }
281 433805 : }
282 :
283 :
284 1301415 : BinaryOpICState::Kind BinaryOpICState::UpdateKind(Handle<Object> object,
285 1439500 : Kind kind) const {
286 : Kind new_kind = GENERIC;
287 : bool is_truncating = Token::IsTruncatingBinaryOp(op());
288 1301415 : if (object->IsOddball() && is_truncating) {
289 : // Oddballs will be automatically truncated by HChange.
290 : new_kind = INT32;
291 2599966 : } else if (object->IsUndefined(isolate_)) {
292 : // Undefined will be automatically truncated by HChange.
293 1780 : new_kind = is_truncating ? INT32 : NUMBER;
294 1298203 : } else if (object->IsSmi()) {
295 : new_kind = SMI;
296 297238 : } else if (object->IsHeapNumber()) {
297 : double value = Handle<HeapNumber>::cast(object)->value();
298 156544 : new_kind = IsInt32Double(value) ? INT32 : NUMBER;
299 278779 : } else if (object->IsString() && op() == Token::ADD) {
300 : new_kind = STRING;
301 : }
302 1301415 : if (new_kind == INT32 && SmiValuesAre32Bits()) {
303 : new_kind = NUMBER;
304 : }
305 1301415 : if (kind != NONE && ((new_kind <= NUMBER && kind > NUMBER) ||
306 : (new_kind > NUMBER && kind <= NUMBER))) {
307 : new_kind = GENERIC;
308 : }
309 1301415 : return Max(kind, new_kind);
310 : }
311 :
312 :
313 : // static
314 182372 : const char* BinaryOpICState::KindToString(Kind kind) {
315 182372 : switch (kind) {
316 : case NONE:
317 : return "None";
318 : case SMI:
319 19055 : return "Smi";
320 : case INT32:
321 4171 : return "Int32";
322 : case NUMBER:
323 5340 : return "Number";
324 : case STRING:
325 149858 : return "String";
326 : case GENERIC:
327 2400 : return "Generic";
328 : }
329 0 : UNREACHABLE();
330 : return NULL;
331 : }
332 :
333 :
334 : // static
335 2367930 : AstType* BinaryOpICState::KindToType(Kind kind) {
336 2367930 : switch (kind) {
337 : case NONE:
338 : return AstType::None();
339 : case SMI:
340 1204425 : return AstType::SignedSmall();
341 : case INT32:
342 4171 : return AstType::Signed32();
343 : case NUMBER:
344 458109 : return AstType::Number();
345 : case STRING:
346 136273 : return AstType::String();
347 : case GENERIC:
348 6115 : return AstType::Any();
349 : }
350 0 : UNREACHABLE();
351 : return NULL;
352 : }
353 :
354 :
355 0 : const char* CompareICState::GetStateName(State state) {
356 0 : switch (state) {
357 : case UNINITIALIZED:
358 : return "UNINITIALIZED";
359 : case BOOLEAN:
360 0 : return "BOOLEAN";
361 : case SMI:
362 0 : return "SMI";
363 : case NUMBER:
364 0 : return "NUMBER";
365 : case INTERNALIZED_STRING:
366 0 : return "INTERNALIZED_STRING";
367 : case STRING:
368 0 : return "STRING";
369 : case UNIQUE_NAME:
370 0 : return "UNIQUE_NAME";
371 : case RECEIVER:
372 0 : return "RECEIVER";
373 : case KNOWN_RECEIVER:
374 0 : return "KNOWN_RECEIVER";
375 : case GENERIC:
376 0 : return "GENERIC";
377 : }
378 0 : UNREACHABLE();
379 : return NULL;
380 : }
381 :
382 1344642 : AstType* CompareICState::StateToType(Zone* zone, State state, Handle<Map> map) {
383 1344642 : switch (state) {
384 : case UNINITIALIZED:
385 : return AstType::None();
386 : case BOOLEAN:
387 9711 : return AstType::Boolean();
388 : case SMI:
389 212214 : return AstType::SignedSmall();
390 : case NUMBER:
391 46489 : return AstType::Number();
392 : case STRING:
393 34146 : return AstType::String();
394 : case INTERNALIZED_STRING:
395 56416 : return AstType::InternalizedString();
396 : case UNIQUE_NAME:
397 254 : return AstType::UniqueName();
398 : case RECEIVER:
399 3214 : return AstType::Receiver();
400 : case KNOWN_RECEIVER:
401 210 : return map.is_null() ? AstType::Receiver() : AstType::Class(map, zone);
402 : case GENERIC:
403 72448 : return AstType::Any();
404 : }
405 0 : UNREACHABLE();
406 : return NULL;
407 : }
408 :
409 :
410 545824 : CompareICState::State CompareICState::NewInputState(State old_state,
411 : Handle<Object> value) {
412 545824 : switch (old_state) {
413 : case UNINITIALIZED:
414 505152 : if (value->IsBoolean()) return BOOLEAN;
415 487950 : if (value->IsSmi()) return SMI;
416 173785 : if (value->IsHeapNumber()) return NUMBER;
417 157053 : if (value->IsInternalizedString()) return INTERNALIZED_STRING;
418 42704 : if (value->IsString()) return STRING;
419 16111 : if (value->IsSymbol()) return UNIQUE_NAME;
420 22833 : if (value->IsJSReceiver() && !value->IsUndetectable()) {
421 : return RECEIVER;
422 : }
423 : break;
424 : case BOOLEAN:
425 4195 : if (value->IsBoolean()) return BOOLEAN;
426 : break;
427 : case SMI:
428 15397 : if (value->IsSmi()) return SMI;
429 10108 : if (value->IsHeapNumber()) return NUMBER;
430 : break;
431 : case NUMBER:
432 1748 : if (value->IsNumber()) return NUMBER;
433 : break;
434 : case INTERNALIZED_STRING:
435 12120 : if (value->IsInternalizedString()) return INTERNALIZED_STRING;
436 5097 : if (value->IsString()) return STRING;
437 4109 : if (value->IsSymbol()) return UNIQUE_NAME;
438 : break;
439 : case STRING:
440 4087 : if (value->IsString()) return STRING;
441 : break;
442 : case UNIQUE_NAME:
443 34 : if (value->IsUniqueName()) return UNIQUE_NAME;
444 : break;
445 : case RECEIVER:
446 4483 : if (value->IsJSReceiver() && !value->IsUndetectable()) {
447 : return RECEIVER;
448 : }
449 : break;
450 : case GENERIC:
451 : break;
452 : case KNOWN_RECEIVER:
453 0 : UNREACHABLE();
454 : break;
455 : }
456 : return GENERIC;
457 : }
458 :
459 :
460 : // static
461 272912 : CompareICState::State CompareICState::TargetState(
462 : Isolate* isolate, State old_state, State old_left, State old_right,
463 : Token::Value op, bool has_inlined_smi_code, Handle<Object> x,
464 : Handle<Object> y) {
465 272912 : switch (old_state) {
466 : case UNINITIALIZED:
467 264629 : if (x->IsBoolean() && y->IsBoolean()) return BOOLEAN;
468 397900 : if (x->IsSmi() && y->IsSmi()) return SMI;
469 122498 : if (x->IsNumber() && y->IsNumber()) return NUMBER;
470 97280 : if (Token::IsOrderedRelationalCompareOp(op)) {
471 : // Ordered comparisons treat undefined as NaN, so the
472 : // NUMBER stub will do the right thing.
473 26952 : if ((x->IsNumber() && y->IsUndefined(isolate)) ||
474 1515 : (y->IsNumber() && x->IsUndefined(isolate))) {
475 : return NUMBER;
476 : }
477 : }
478 142505 : if (x->IsInternalizedString() && y->IsInternalizedString()) {
479 : // We compare internalized strings as plain ones if we need to determine
480 : // the order in a non-equality compare.
481 38630 : return Token::IsEqualityOp(op) ? INTERNALIZED_STRING : STRING;
482 : }
483 89735 : if (x->IsString() && y->IsString()) return STRING;
484 41186 : if (x->IsJSReceiver() && y->IsJSReceiver()) {
485 5558 : if (x->IsUndetectable() || y->IsUndetectable()) {
486 : return GENERIC;
487 : }
488 2768 : if (Handle<JSReceiver>::cast(x)->map() ==
489 : Handle<JSReceiver>::cast(y)->map()) {
490 : return KNOWN_RECEIVER;
491 : } else {
492 609 : return Token::IsEqualityOp(op) ? RECEIVER : GENERIC;
493 : }
494 : }
495 34181 : if (!Token::IsEqualityOp(op)) return GENERIC;
496 34783 : if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
497 28942 : return GENERIC;
498 : case SMI:
499 8874 : return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC;
500 : case INTERNALIZED_STRING:
501 : DCHECK(Token::IsEqualityOp(op));
502 4818 : if (x->IsString() && y->IsString()) return STRING;
503 2991 : if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
504 2969 : return GENERIC;
505 : case NUMBER:
506 : // If the failure was due to one side changing from smi to heap number,
507 : // then keep the state (if other changed at the same time, we will get
508 : // a second miss and then go to generic).
509 1495 : if (old_left == SMI && x->IsHeapNumber()) return NUMBER;
510 1643 : if (old_right == SMI && y->IsHeapNumber()) return NUMBER;
511 846 : return GENERIC;
512 : case KNOWN_RECEIVER:
513 1815 : if (x->IsJSReceiver() && y->IsJSReceiver()) {
514 675 : return Token::IsEqualityOp(op) ? RECEIVER : GENERIC;
515 : }
516 : return GENERIC;
517 : case BOOLEAN:
518 : case STRING:
519 : case UNIQUE_NAME:
520 : case RECEIVER:
521 : case GENERIC:
522 : return GENERIC;
523 : }
524 0 : UNREACHABLE();
525 : return GENERIC; // Make the compiler happy.
526 : }
527 :
528 : } // namespace internal
529 : } // namespace v8
|