OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
6 | 6 |
7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic/handler-compiler.h" | 10 #include "src/ic/handler-compiler.h" |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 // Right is the smi. Left is a heap number. Load left value into left_d, and | 418 // Right is the smi. Left is a heap number. Load left value into left_d, and |
419 // convert right smi into double in right_d. | 419 // convert right smi into double in right_d. |
420 __ Ldr(left_d, FieldMemOperand(left, HeapNumber::kValueOffset)); | 420 __ Ldr(left_d, FieldMemOperand(left, HeapNumber::kValueOffset)); |
421 __ SmiUntagToDouble(right_d, right); | 421 __ SmiUntagToDouble(right_d, right); |
422 | 422 |
423 // Fall through to both_loaded_as_doubles. | 423 // Fall through to both_loaded_as_doubles. |
424 __ Bind(&done); | 424 __ Bind(&done); |
425 } | 425 } |
426 | 426 |
427 | 427 |
428 // Fast negative check for internalized-to-internalized equality. | 428 // Fast negative check for internalized-to-internalized equality or receiver |
| 429 // equality. Also handles the undetectable receiver to null/undefined |
| 430 // comparison. |
429 // See call site for description. | 431 // See call site for description. |
430 static void EmitCheckForInternalizedStringsOrObjects( | 432 static void EmitCheckForInternalizedStringsOrObjects( |
431 MacroAssembler* masm, Register left, Register right, Register left_map, | 433 MacroAssembler* masm, Register left, Register right, Register left_map, |
432 Register right_map, Register left_type, Register right_type, | 434 Register right_map, Register left_type, Register right_type, |
433 Label* possible_strings, Label* runtime_call) { | 435 Label* possible_strings, Label* runtime_call) { |
434 DCHECK(!AreAliased(left, right, left_map, right_map, left_type, right_type)); | 436 DCHECK(!AreAliased(left, right, left_map, right_map, left_type, right_type)); |
435 Register result = x0; | 437 Register result = x0; |
436 DCHECK(left.is(x0) || right.is(x0)); | 438 DCHECK(left.is(x0) || right.is(x0)); |
437 | 439 |
438 Label object_test, return_unequal, undetectable; | 440 Label object_test, return_equal, return_unequal, undetectable; |
439 STATIC_ASSERT((kInternalizedTag == 0) && (kStringTag == 0)); | 441 STATIC_ASSERT((kInternalizedTag == 0) && (kStringTag == 0)); |
440 // TODO(all): reexamine this branch sequence for optimisation wrt branch | 442 // TODO(all): reexamine this branch sequence for optimisation wrt branch |
441 // prediction. | 443 // prediction. |
442 __ Tbnz(right_type, MaskToBit(kIsNotStringMask), &object_test); | 444 __ Tbnz(right_type, MaskToBit(kIsNotStringMask), &object_test); |
443 __ Tbnz(right_type, MaskToBit(kIsNotInternalizedMask), possible_strings); | 445 __ Tbnz(right_type, MaskToBit(kIsNotInternalizedMask), possible_strings); |
444 __ Tbnz(left_type, MaskToBit(kIsNotStringMask), runtime_call); | 446 __ Tbnz(left_type, MaskToBit(kIsNotStringMask), runtime_call); |
445 __ Tbnz(left_type, MaskToBit(kIsNotInternalizedMask), possible_strings); | 447 __ Tbnz(left_type, MaskToBit(kIsNotInternalizedMask), possible_strings); |
446 | 448 |
447 // Both are internalized. We already checked they weren't the same pointer so | 449 // Both are internalized. We already checked they weren't the same pointer so |
448 // they are not equal. Return non-equal by returning the non-zero object | 450 // they are not equal. Return non-equal by returning the non-zero object |
449 // pointer in x0. | 451 // pointer in x0. |
450 __ Ret(); | 452 __ Ret(); |
451 | 453 |
452 __ Bind(&object_test); | 454 __ Bind(&object_test); |
453 | 455 |
454 Register left_bitfield = left_type; | 456 Register left_bitfield = left_type; |
455 Register right_bitfield = right_type; | 457 Register right_bitfield = right_type; |
456 __ Ldrb(right_bitfield, FieldMemOperand(right_map, Map::kBitFieldOffset)); | 458 __ Ldrb(right_bitfield, FieldMemOperand(right_map, Map::kBitFieldOffset)); |
457 __ Ldrb(left_bitfield, FieldMemOperand(left_map, Map::kBitFieldOffset)); | 459 __ Ldrb(left_bitfield, FieldMemOperand(left_map, Map::kBitFieldOffset)); |
458 __ Tbnz(right_bitfield, MaskToBit(1 << Map::kIsUndetectable), &undetectable); | 460 __ Tbnz(right_bitfield, MaskToBit(1 << Map::kIsUndetectable), &undetectable); |
459 __ Tbnz(left_bitfield, MaskToBit(1 << Map::kIsUndetectable), &return_unequal); | 461 __ Tbnz(left_bitfield, MaskToBit(1 << Map::kIsUndetectable), &return_unequal); |
460 | 462 |
461 __ CompareInstanceType(right_map, right_type, FIRST_JS_RECEIVER_TYPE); | 463 __ CompareInstanceType(right_map, right_type, FIRST_JS_RECEIVER_TYPE); |
462 __ B(lt, runtime_call); | 464 __ B(lt, runtime_call); |
463 __ CompareInstanceType(left_map, left_type, FIRST_JS_RECEIVER_TYPE); | 465 __ CompareInstanceType(left_map, left_type, FIRST_JS_RECEIVER_TYPE); |
464 __ B(lt, runtime_call); | 466 __ B(lt, runtime_call); |
465 | 467 |
466 __ bind(&return_unequal); | 468 __ Bind(&return_unequal); |
467 // Return non-equal by returning the non-zero object pointer in x0. | 469 // Return non-equal by returning the non-zero object pointer in x0. |
468 __ Ret(); | 470 __ Ret(); |
469 | 471 |
470 __ bind(&undetectable); | 472 __ Bind(&undetectable); |
471 __ Tbz(left_bitfield, MaskToBit(1 << Map::kIsUndetectable), &return_unequal); | 473 __ Tbz(left_bitfield, MaskToBit(1 << Map::kIsUndetectable), &return_unequal); |
| 474 |
| 475 // If both sides are JSReceivers, then the result is false according to |
| 476 // the HTML specification, which says that only comparisons with null or |
| 477 // undefined are affected by special casing for document.all. |
| 478 __ CompareInstanceType(right_map, right_type, ODDBALL_TYPE); |
| 479 __ B(eq, &return_equal); |
| 480 __ CompareInstanceType(left_map, left_type, ODDBALL_TYPE); |
| 481 __ B(ne, &return_unequal); |
| 482 |
| 483 __ Bind(&return_equal); |
472 __ Mov(result, EQUAL); | 484 __ Mov(result, EQUAL); |
473 __ Ret(); | 485 __ Ret(); |
474 } | 486 } |
475 | 487 |
476 | 488 |
477 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, | 489 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, |
478 CompareICState::State expected, | 490 CompareICState::State expected, |
479 Label* fail) { | 491 Label* fail) { |
480 Label ok; | 492 Label ok; |
481 if (expected == CompareICState::SMI) { | 493 if (expected == CompareICState::SMI) { |
(...skipping 5492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5974 return_value_operand, NULL); | 5986 return_value_operand, NULL); |
5975 } | 5987 } |
5976 | 5988 |
5977 | 5989 |
5978 #undef __ | 5990 #undef __ |
5979 | 5991 |
5980 } // namespace internal | 5992 } // namespace internal |
5981 } // namespace v8 | 5993 } // namespace v8 |
5982 | 5994 |
5983 #endif // V8_TARGET_ARCH_ARM64 | 5995 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |