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 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 __ Ldr(left_d, FieldMemOperand(left, HeapNumber::kValueOffset)); | 436 __ Ldr(left_d, FieldMemOperand(left, HeapNumber::kValueOffset)); |
437 __ SmiUntagToDouble(right_d, right); | 437 __ SmiUntagToDouble(right_d, right); |
438 | 438 |
439 // Fall through to both_loaded_as_doubles. | 439 // Fall through to both_loaded_as_doubles. |
440 __ Bind(&done); | 440 __ Bind(&done); |
441 } | 441 } |
442 | 442 |
443 | 443 |
444 // Fast negative check for internalized-to-internalized equality. | 444 // Fast negative check for internalized-to-internalized equality. |
445 // See call site for description. | 445 // See call site for description. |
446 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, | 446 static void EmitCheckForInternalizedStringsOrObjects( |
447 Register left, | 447 MacroAssembler* masm, Register left, Register right, Register left_map, |
448 Register right, | 448 Register right_map, Register left_type, Register right_type, |
449 Register left_map, | 449 Label* possible_strings, Label* runtime_call) { |
450 Register right_map, | |
451 Register left_type, | |
452 Register right_type, | |
453 Label* possible_strings, | |
454 Label* not_both_strings) { | |
455 DCHECK(!AreAliased(left, right, left_map, right_map, left_type, right_type)); | 450 DCHECK(!AreAliased(left, right, left_map, right_map, left_type, right_type)); |
456 Register result = x0; | 451 Register result = x0; |
| 452 DCHECK(left.is(x0) || right.is(x0)); |
457 | 453 |
458 Label object_test; | 454 Label object_test, return_unequal, undetectable; |
459 STATIC_ASSERT((kInternalizedTag == 0) && (kStringTag == 0)); | 455 STATIC_ASSERT((kInternalizedTag == 0) && (kStringTag == 0)); |
460 // TODO(all): reexamine this branch sequence for optimisation wrt branch | 456 // TODO(all): reexamine this branch sequence for optimisation wrt branch |
461 // prediction. | 457 // prediction. |
462 __ Tbnz(right_type, MaskToBit(kIsNotStringMask), &object_test); | 458 __ Tbnz(right_type, MaskToBit(kIsNotStringMask), &object_test); |
463 __ Tbnz(right_type, MaskToBit(kIsNotInternalizedMask), possible_strings); | 459 __ Tbnz(right_type, MaskToBit(kIsNotInternalizedMask), possible_strings); |
464 __ Tbnz(left_type, MaskToBit(kIsNotStringMask), not_both_strings); | 460 __ Tbnz(left_type, MaskToBit(kIsNotStringMask), runtime_call); |
465 __ Tbnz(left_type, MaskToBit(kIsNotInternalizedMask), possible_strings); | 461 __ Tbnz(left_type, MaskToBit(kIsNotInternalizedMask), possible_strings); |
466 | 462 |
467 // Both are internalized. We already checked that they weren't the same | 463 // Both are internalized. We already checked they weren't the same pointer so |
468 // pointer, so they are not equal. | 464 // they are not equal. Return non-equal by returning the non-zero object |
469 __ Mov(result, NOT_EQUAL); | 465 // pointer in x0. |
470 __ Ret(); | 466 __ Ret(); |
471 | 467 |
472 __ Bind(&object_test); | 468 __ Bind(&object_test); |
473 | 469 |
474 __ Cmp(right_type, FIRST_JS_RECEIVER_TYPE); | 470 Register left_bitfield = left_type; |
475 | |
476 // If right >= FIRST_JS_RECEIVER_TYPE, test left. | |
477 // Otherwise, right < FIRST_JS_RECEIVER_TYPE, so set lt condition. | |
478 __ Ccmp(left_type, FIRST_JS_RECEIVER_TYPE, NFlag, ge); | |
479 | |
480 __ B(lt, not_both_strings); | |
481 | |
482 // If both objects are undetectable, they are equal. Otherwise, they are not | |
483 // equal, since they are different objects and an object is not equal to | |
484 // undefined. | |
485 | |
486 // Returning here, so we can corrupt right_type and left_type. | |
487 Register right_bitfield = right_type; | 471 Register right_bitfield = right_type; |
488 Register left_bitfield = left_type; | |
489 __ Ldrb(right_bitfield, FieldMemOperand(right_map, Map::kBitFieldOffset)); | 472 __ Ldrb(right_bitfield, FieldMemOperand(right_map, Map::kBitFieldOffset)); |
490 __ Ldrb(left_bitfield, FieldMemOperand(left_map, Map::kBitFieldOffset)); | 473 __ Ldrb(left_bitfield, FieldMemOperand(left_map, Map::kBitFieldOffset)); |
491 __ And(result, right_bitfield, left_bitfield); | 474 __ Tbnz(right_bitfield, MaskToBit(1 << Map::kIsUndetectable), &undetectable); |
492 __ And(result, result, 1 << Map::kIsUndetectable); | 475 __ Tbnz(left_bitfield, MaskToBit(1 << Map::kIsUndetectable), &return_unequal); |
493 __ Eor(result, result, 1 << Map::kIsUndetectable); | 476 |
| 477 __ CompareInstanceType(right_map, right_type, FIRST_JS_RECEIVER_TYPE); |
| 478 __ B(lt, runtime_call); |
| 479 __ CompareInstanceType(left_map, left_type, FIRST_JS_RECEIVER_TYPE); |
| 480 __ B(lt, runtime_call); |
| 481 |
| 482 __ bind(&return_unequal); |
| 483 // Return non-equal by returning the non-zero object pointer in x0. |
| 484 __ Ret(); |
| 485 |
| 486 __ bind(&undetectable); |
| 487 __ Tbz(left_bitfield, MaskToBit(1 << Map::kIsUndetectable), &return_unequal); |
| 488 __ Mov(result, EQUAL); |
494 __ Ret(); | 489 __ Ret(); |
495 } | 490 } |
496 | 491 |
497 | 492 |
498 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, | 493 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, |
499 CompareICState::State expected, | 494 CompareICState::State expected, |
500 Label* fail) { | 495 Label* fail) { |
501 Label ok; | 496 Label ok; |
502 if (expected == CompareICState::SMI) { | 497 if (expected == CompareICState::SMI) { |
503 __ JumpIfNotSmi(input, fail); | 498 __ JumpIfNotSmi(input, fail); |
(...skipping 5484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5988 return_value_operand, NULL); | 5983 return_value_operand, NULL); |
5989 } | 5984 } |
5990 | 5985 |
5991 | 5986 |
5992 #undef __ | 5987 #undef __ |
5993 | 5988 |
5994 } // namespace internal | 5989 } // namespace internal |
5995 } // namespace v8 | 5990 } // namespace v8 |
5996 | 5991 |
5997 #endif // V8_TARGET_ARCH_ARM64 | 5992 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |