| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 #include "regexp-macro-assembler.h" | 34 #include "regexp-macro-assembler.h" |
| 35 | 35 |
| 36 namespace v8 { | 36 namespace v8 { |
| 37 namespace internal { | 37 namespace internal { |
| 38 | 38 |
| 39 | 39 |
| 40 #define __ ACCESS_MASM(masm) | 40 #define __ ACCESS_MASM(masm) |
| 41 | 41 |
| 42 static void EmitIdenticalObjectComparison(MacroAssembler* masm, | 42 static void EmitIdenticalObjectComparison(MacroAssembler* masm, |
| 43 Label* slow, | 43 Label* slow, |
| 44 Condition cc, | 44 Condition cond, |
| 45 bool never_nan_nan); | 45 bool never_nan_nan); |
| 46 static void EmitSmiNonsmiComparison(MacroAssembler* masm, | 46 static void EmitSmiNonsmiComparison(MacroAssembler* masm, |
| 47 Register lhs, | 47 Register lhs, |
| 48 Register rhs, | 48 Register rhs, |
| 49 Label* lhs_not_nan, | 49 Label* lhs_not_nan, |
| 50 Label* slow, | 50 Label* slow, |
| 51 bool strict); | 51 bool strict); |
| 52 static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc); | 52 static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cond); |
| 53 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, | 53 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, |
| 54 Register lhs, | 54 Register lhs, |
| 55 Register rhs); | 55 Register rhs); |
| 56 | 56 |
| 57 | 57 |
| 58 void FastNewClosureStub::Generate(MacroAssembler* masm) { | 58 void FastNewClosureStub::Generate(MacroAssembler* masm) { |
| 59 // Create a new closure from the given function info in new | 59 // Create a new closure from the given function info in new |
| 60 // space. Set the context to the current context in cp. | 60 // space. Set the context to the current context in cp. |
| 61 Label gc; | 61 Label gc; |
| 62 | 62 |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset)); | 537 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset)); |
| 538 __ Ret(); | 538 __ Ret(); |
| 539 } | 539 } |
| 540 | 540 |
| 541 | 541 |
| 542 // Handle the case where the lhs and rhs are the same object. | 542 // Handle the case where the lhs and rhs are the same object. |
| 543 // Equality is almost reflexive (everything but NaN), so this is a test | 543 // Equality is almost reflexive (everything but NaN), so this is a test |
| 544 // for "identity and not NaN". | 544 // for "identity and not NaN". |
| 545 static void EmitIdenticalObjectComparison(MacroAssembler* masm, | 545 static void EmitIdenticalObjectComparison(MacroAssembler* masm, |
| 546 Label* slow, | 546 Label* slow, |
| 547 Condition cc, | 547 Condition cond, |
| 548 bool never_nan_nan) { | 548 bool never_nan_nan) { |
| 549 Label not_identical; | 549 Label not_identical; |
| 550 Label heap_number, return_equal; | 550 Label heap_number, return_equal; |
| 551 __ cmp(r0, r1); | 551 __ cmp(r0, r1); |
| 552 __ b(ne, ¬_identical); | 552 __ b(ne, ¬_identical); |
| 553 | 553 |
| 554 // The two objects are identical. If we know that one of them isn't NaN then | 554 // The two objects are identical. If we know that one of them isn't NaN then |
| 555 // we now know they test equal. | 555 // we now know they test equal. |
| 556 if (cc != eq || !never_nan_nan) { | 556 if (cond != eq || !never_nan_nan) { |
| 557 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), | 557 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), |
| 558 // so we do the second best thing - test it ourselves. | 558 // so we do the second best thing - test it ourselves. |
| 559 // They are both equal and they are not both Smis so both of them are not | 559 // They are both equal and they are not both Smis so both of them are not |
| 560 // Smis. If it's not a heap number, then return equal. | 560 // Smis. If it's not a heap number, then return equal. |
| 561 if (cc == lt || cc == gt) { | 561 if (cond == lt || cond == gt) { |
| 562 __ CompareObjectType(r0, r4, r4, FIRST_JS_OBJECT_TYPE); | 562 __ CompareObjectType(r0, r4, r4, FIRST_JS_OBJECT_TYPE); |
| 563 __ b(ge, slow); | 563 __ b(ge, slow); |
| 564 } else { | 564 } else { |
| 565 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); | 565 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); |
| 566 __ b(eq, &heap_number); | 566 __ b(eq, &heap_number); |
| 567 // Comparing JS objects with <=, >= is complicated. | 567 // Comparing JS objects with <=, >= is complicated. |
| 568 if (cc != eq) { | 568 if (cond != eq) { |
| 569 __ cmp(r4, Operand(FIRST_JS_OBJECT_TYPE)); | 569 __ cmp(r4, Operand(FIRST_JS_OBJECT_TYPE)); |
| 570 __ b(ge, slow); | 570 __ b(ge, slow); |
| 571 // Normally here we fall through to return_equal, but undefined is | 571 // Normally here we fall through to return_equal, but undefined is |
| 572 // special: (undefined == undefined) == true, but | 572 // special: (undefined == undefined) == true, but |
| 573 // (undefined <= undefined) == false! See ECMAScript 11.8.5. | 573 // (undefined <= undefined) == false! See ECMAScript 11.8.5. |
| 574 if (cc == le || cc == ge) { | 574 if (cond == le || cond == ge) { |
| 575 __ cmp(r4, Operand(ODDBALL_TYPE)); | 575 __ cmp(r4, Operand(ODDBALL_TYPE)); |
| 576 __ b(ne, &return_equal); | 576 __ b(ne, &return_equal); |
| 577 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | 577 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
| 578 __ cmp(r0, r2); | 578 __ cmp(r0, r2); |
| 579 __ b(ne, &return_equal); | 579 __ b(ne, &return_equal); |
| 580 if (cc == le) { | 580 if (cond == le) { |
| 581 // undefined <= undefined should fail. | 581 // undefined <= undefined should fail. |
| 582 __ mov(r0, Operand(GREATER)); | 582 __ mov(r0, Operand(GREATER)); |
| 583 } else { | 583 } else { |
| 584 // undefined >= undefined should fail. | 584 // undefined >= undefined should fail. |
| 585 __ mov(r0, Operand(LESS)); | 585 __ mov(r0, Operand(LESS)); |
| 586 } | 586 } |
| 587 __ Ret(); | 587 __ Ret(); |
| 588 } | 588 } |
| 589 } | 589 } |
| 590 } | 590 } |
| 591 } | 591 } |
| 592 | 592 |
| 593 __ bind(&return_equal); | 593 __ bind(&return_equal); |
| 594 if (cc == lt) { | 594 if (cond == lt) { |
| 595 __ mov(r0, Operand(GREATER)); // Things aren't less than themselves. | 595 __ mov(r0, Operand(GREATER)); // Things aren't less than themselves. |
| 596 } else if (cc == gt) { | 596 } else if (cond == gt) { |
| 597 __ mov(r0, Operand(LESS)); // Things aren't greater than themselves. | 597 __ mov(r0, Operand(LESS)); // Things aren't greater than themselves. |
| 598 } else { | 598 } else { |
| 599 __ mov(r0, Operand(EQUAL)); // Things are <=, >=, ==, === themselves. | 599 __ mov(r0, Operand(EQUAL)); // Things are <=, >=, ==, === themselves. |
| 600 } | 600 } |
| 601 __ Ret(); | 601 __ Ret(); |
| 602 | 602 |
| 603 if (cc != eq || !never_nan_nan) { | 603 if (cond != eq || !never_nan_nan) { |
| 604 // For less and greater we don't have to check for NaN since the result of | 604 // For less and greater we don't have to check for NaN since the result of |
| 605 // x < x is false regardless. For the others here is some code to check | 605 // x < x is false regardless. For the others here is some code to check |
| 606 // for NaN. | 606 // for NaN. |
| 607 if (cc != lt && cc != gt) { | 607 if (cond != lt && cond != gt) { |
| 608 __ bind(&heap_number); | 608 __ bind(&heap_number); |
| 609 // It is a heap number, so return non-equal if it's NaN and equal if it's | 609 // It is a heap number, so return non-equal if it's NaN and equal if it's |
| 610 // not NaN. | 610 // not NaN. |
| 611 | 611 |
| 612 // The representation of NaN values has all exponent bits (52..62) set, | 612 // The representation of NaN values has all exponent bits (52..62) set, |
| 613 // and not all mantissa bits (0..51) clear. | 613 // and not all mantissa bits (0..51) clear. |
| 614 // Read top bits of double representation (second word of value). | 614 // Read top bits of double representation (second word of value). |
| 615 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 615 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
| 616 // Test that exponent bits are all set. | 616 // Test that exponent bits are all set. |
| 617 __ Sbfx(r3, r2, HeapNumber::kExponentShift, HeapNumber::kExponentBits); | 617 __ Sbfx(r3, r2, HeapNumber::kExponentShift, HeapNumber::kExponentBits); |
| 618 // NaNs have all-one exponents so they sign extend to -1. | 618 // NaNs have all-one exponents so they sign extend to -1. |
| 619 __ cmp(r3, Operand(-1)); | 619 __ cmp(r3, Operand(-1)); |
| 620 __ b(ne, &return_equal); | 620 __ b(ne, &return_equal); |
| 621 | 621 |
| 622 // Shift out flag and all exponent bits, retaining only mantissa. | 622 // Shift out flag and all exponent bits, retaining only mantissa. |
| 623 __ mov(r2, Operand(r2, LSL, HeapNumber::kNonMantissaBitsInTopWord)); | 623 __ mov(r2, Operand(r2, LSL, HeapNumber::kNonMantissaBitsInTopWord)); |
| 624 // Or with all low-bits of mantissa. | 624 // Or with all low-bits of mantissa. |
| 625 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | 625 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
| 626 __ orr(r0, r3, Operand(r2), SetCC); | 626 __ orr(r0, r3, Operand(r2), SetCC); |
| 627 // For equal we already have the right value in r0: Return zero (equal) | 627 // For equal we already have the right value in r0: Return zero (equal) |
| 628 // if all bits in mantissa are zero (it's an Infinity) and non-zero if | 628 // if all bits in mantissa are zero (it's an Infinity) and non-zero if |
| 629 // not (it's a NaN). For <= and >= we need to load r0 with the failing | 629 // not (it's a NaN). For <= and >= we need to load r0 with the failing |
| 630 // value if it's a NaN. | 630 // value if it's a NaN. |
| 631 if (cc != eq) { | 631 if (cond != eq) { |
| 632 // All-zero means Infinity means equal. | 632 // All-zero means Infinity means equal. |
| 633 __ Ret(eq); | 633 __ Ret(eq); |
| 634 if (cc == le) { | 634 if (cond == le) { |
| 635 __ mov(r0, Operand(GREATER)); // NaN <= NaN should fail. | 635 __ mov(r0, Operand(GREATER)); // NaN <= NaN should fail. |
| 636 } else { | 636 } else { |
| 637 __ mov(r0, Operand(LESS)); // NaN >= NaN should fail. | 637 __ mov(r0, Operand(LESS)); // NaN >= NaN should fail. |
| 638 } | 638 } |
| 639 } | 639 } |
| 640 __ Ret(); | 640 __ Ret(); |
| 641 } | 641 } |
| 642 // No fall through here. | 642 // No fall through here. |
| 643 } | 643 } |
| 644 | 644 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 731 // Convert rhs to a double in r0, r1. | 731 // Convert rhs to a double in r0, r1. |
| 732 __ mov(r7, Operand(rhs)); | 732 __ mov(r7, Operand(rhs)); |
| 733 ConvertToDoubleStub stub2(r1, r0, r7, r6); | 733 ConvertToDoubleStub stub2(r1, r0, r7, r6); |
| 734 __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET); | 734 __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET); |
| 735 __ pop(lr); | 735 __ pop(lr); |
| 736 } | 736 } |
| 737 // Fall through to both_loaded_as_doubles. | 737 // Fall through to both_loaded_as_doubles. |
| 738 } | 738 } |
| 739 | 739 |
| 740 | 740 |
| 741 void EmitNanCheck(MacroAssembler* masm, Label* lhs_not_nan, Condition cc) { | 741 void EmitNanCheck(MacroAssembler* masm, Label* lhs_not_nan, Condition cond) { |
| 742 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); | 742 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); |
| 743 Register rhs_exponent = exp_first ? r0 : r1; | 743 Register rhs_exponent = exp_first ? r0 : r1; |
| 744 Register lhs_exponent = exp_first ? r2 : r3; | 744 Register lhs_exponent = exp_first ? r2 : r3; |
| 745 Register rhs_mantissa = exp_first ? r1 : r0; | 745 Register rhs_mantissa = exp_first ? r1 : r0; |
| 746 Register lhs_mantissa = exp_first ? r3 : r2; | 746 Register lhs_mantissa = exp_first ? r3 : r2; |
| 747 Label one_is_nan, neither_is_nan; | 747 Label one_is_nan, neither_is_nan; |
| 748 | 748 |
| 749 __ Sbfx(r4, | 749 __ Sbfx(r4, |
| 750 lhs_exponent, | 750 lhs_exponent, |
| 751 HeapNumber::kExponentShift, | 751 HeapNumber::kExponentShift, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 771 __ mov(r4, | 771 __ mov(r4, |
| 772 Operand(rhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord), | 772 Operand(rhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord), |
| 773 SetCC); | 773 SetCC); |
| 774 __ b(ne, &one_is_nan); | 774 __ b(ne, &one_is_nan); |
| 775 __ cmp(rhs_mantissa, Operand(0, RelocInfo::NONE)); | 775 __ cmp(rhs_mantissa, Operand(0, RelocInfo::NONE)); |
| 776 __ b(eq, &neither_is_nan); | 776 __ b(eq, &neither_is_nan); |
| 777 | 777 |
| 778 __ bind(&one_is_nan); | 778 __ bind(&one_is_nan); |
| 779 // NaN comparisons always fail. | 779 // NaN comparisons always fail. |
| 780 // Load whatever we need in r0 to make the comparison fail. | 780 // Load whatever we need in r0 to make the comparison fail. |
| 781 if (cc == lt || cc == le) { | 781 if (cond == lt || cond == le) { |
| 782 __ mov(r0, Operand(GREATER)); | 782 __ mov(r0, Operand(GREATER)); |
| 783 } else { | 783 } else { |
| 784 __ mov(r0, Operand(LESS)); | 784 __ mov(r0, Operand(LESS)); |
| 785 } | 785 } |
| 786 __ Ret(); | 786 __ Ret(); |
| 787 | 787 |
| 788 __ bind(&neither_is_nan); | 788 __ bind(&neither_is_nan); |
| 789 } | 789 } |
| 790 | 790 |
| 791 | 791 |
| 792 // See comment at call site. | 792 // See comment at call site. |
| 793 static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc) { | 793 static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, |
| 794 Condition cond) { |
| 794 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); | 795 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); |
| 795 Register rhs_exponent = exp_first ? r0 : r1; | 796 Register rhs_exponent = exp_first ? r0 : r1; |
| 796 Register lhs_exponent = exp_first ? r2 : r3; | 797 Register lhs_exponent = exp_first ? r2 : r3; |
| 797 Register rhs_mantissa = exp_first ? r1 : r0; | 798 Register rhs_mantissa = exp_first ? r1 : r0; |
| 798 Register lhs_mantissa = exp_first ? r3 : r2; | 799 Register lhs_mantissa = exp_first ? r3 : r2; |
| 799 | 800 |
| 800 // r0, r1, r2, r3 have the two doubles. Neither is a NaN. | 801 // r0, r1, r2, r3 have the two doubles. Neither is a NaN. |
| 801 if (cc == eq) { | 802 if (cond == eq) { |
| 802 // Doubles are not equal unless they have the same bit pattern. | 803 // Doubles are not equal unless they have the same bit pattern. |
| 803 // Exception: 0 and -0. | 804 // Exception: 0 and -0. |
| 804 __ cmp(rhs_mantissa, Operand(lhs_mantissa)); | 805 __ cmp(rhs_mantissa, Operand(lhs_mantissa)); |
| 805 __ orr(r0, rhs_mantissa, Operand(lhs_mantissa), LeaveCC, ne); | 806 __ orr(r0, rhs_mantissa, Operand(lhs_mantissa), LeaveCC, ne); |
| 806 // Return non-zero if the numbers are unequal. | 807 // Return non-zero if the numbers are unequal. |
| 807 __ Ret(ne); | 808 __ Ret(ne); |
| 808 | 809 |
| 809 __ sub(r0, rhs_exponent, Operand(lhs_exponent), SetCC); | 810 __ sub(r0, rhs_exponent, Operand(lhs_exponent), SetCC); |
| 810 // If exponents are equal then return 0. | 811 // If exponents are equal then return 0. |
| 811 __ Ret(eq); | 812 __ Ret(eq); |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1080 __ orr(r2, r1, r0); | 1081 __ orr(r2, r1, r0); |
| 1081 __ tst(r2, Operand(kSmiTagMask)); | 1082 __ tst(r2, Operand(kSmiTagMask)); |
| 1082 __ b(ne, ¬_two_smis); | 1083 __ b(ne, ¬_two_smis); |
| 1083 __ mov(r1, Operand(r1, ASR, 1)); | 1084 __ mov(r1, Operand(r1, ASR, 1)); |
| 1084 __ sub(r0, r1, Operand(r0, ASR, 1)); | 1085 __ sub(r0, r1, Operand(r0, ASR, 1)); |
| 1085 __ Ret(); | 1086 __ Ret(); |
| 1086 __ bind(¬_two_smis); | 1087 __ bind(¬_two_smis); |
| 1087 } else if (FLAG_debug_code) { | 1088 } else if (FLAG_debug_code) { |
| 1088 __ orr(r2, r1, r0); | 1089 __ orr(r2, r1, r0); |
| 1089 __ tst(r2, Operand(kSmiTagMask)); | 1090 __ tst(r2, Operand(kSmiTagMask)); |
| 1090 __ Assert(nz, "CompareStub: unexpected smi operands."); | 1091 __ Assert(ne, "CompareStub: unexpected smi operands."); |
| 1091 } | 1092 } |
| 1092 | 1093 |
| 1093 // NOTICE! This code is only reached after a smi-fast-case check, so | 1094 // NOTICE! This code is only reached after a smi-fast-case check, so |
| 1094 // it is certain that at least one operand isn't a smi. | 1095 // it is certain that at least one operand isn't a smi. |
| 1095 | 1096 |
| 1096 // Handle the case where the objects are identical. Either returns the answer | 1097 // Handle the case where the objects are identical. Either returns the answer |
| 1097 // or goes to slow. Only falls through if the objects were not identical. | 1098 // or goes to slow. Only falls through if the objects were not identical. |
| 1098 EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_); | 1099 EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_); |
| 1099 | 1100 |
| 1100 // If either is a Smi (we know that not both are), then they can only | 1101 // If either is a Smi (we know that not both are), then they can only |
| (...skipping 2691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3792 STATIC_ASSERT(kSmiTag == 0); | 3793 STATIC_ASSERT(kSmiTag == 0); |
| 3793 __ tst(r0, Operand(kSmiTagMask)); | 3794 __ tst(r0, Operand(kSmiTagMask)); |
| 3794 __ b(eq, &runtime); | 3795 __ b(eq, &runtime); |
| 3795 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); | 3796 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); |
| 3796 __ b(ne, &runtime); | 3797 __ b(ne, &runtime); |
| 3797 | 3798 |
| 3798 // Check that the RegExp has been compiled (data contains a fixed array). | 3799 // Check that the RegExp has been compiled (data contains a fixed array). |
| 3799 __ ldr(regexp_data, FieldMemOperand(r0, JSRegExp::kDataOffset)); | 3800 __ ldr(regexp_data, FieldMemOperand(r0, JSRegExp::kDataOffset)); |
| 3800 if (FLAG_debug_code) { | 3801 if (FLAG_debug_code) { |
| 3801 __ tst(regexp_data, Operand(kSmiTagMask)); | 3802 __ tst(regexp_data, Operand(kSmiTagMask)); |
| 3802 __ Check(nz, "Unexpected type for RegExp data, FixedArray expected"); | 3803 __ Check(ne, "Unexpected type for RegExp data, FixedArray expected"); |
| 3803 __ CompareObjectType(regexp_data, r0, r0, FIXED_ARRAY_TYPE); | 3804 __ CompareObjectType(regexp_data, r0, r0, FIXED_ARRAY_TYPE); |
| 3804 __ Check(eq, "Unexpected type for RegExp data, FixedArray expected"); | 3805 __ Check(eq, "Unexpected type for RegExp data, FixedArray expected"); |
| 3805 } | 3806 } |
| 3806 | 3807 |
| 3807 // regexp_data: RegExp data (FixedArray) | 3808 // regexp_data: RegExp data (FixedArray) |
| 3808 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. | 3809 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. |
| 3809 __ ldr(r0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); | 3810 __ ldr(r0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); |
| 3810 __ cmp(r0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); | 3811 __ cmp(r0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); |
| 3811 __ b(ne, &runtime); | 3812 __ b(ne, &runtime); |
| 3812 | 3813 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3895 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); | 3896 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); |
| 3896 __ LoadRoot(r1, Heap::kEmptyStringRootIndex); | 3897 __ LoadRoot(r1, Heap::kEmptyStringRootIndex); |
| 3897 __ cmp(r0, r1); | 3898 __ cmp(r0, r1); |
| 3898 __ b(ne, &runtime); | 3899 __ b(ne, &runtime); |
| 3899 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); | 3900 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); |
| 3900 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 3901 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
| 3901 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); | 3902 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
| 3902 // Is first part a flat string? | 3903 // Is first part a flat string? |
| 3903 STATIC_ASSERT(kSeqStringTag == 0); | 3904 STATIC_ASSERT(kSeqStringTag == 0); |
| 3904 __ tst(r0, Operand(kStringRepresentationMask)); | 3905 __ tst(r0, Operand(kStringRepresentationMask)); |
| 3905 __ b(nz, &runtime); | 3906 __ b(ne, &runtime); |
| 3906 | 3907 |
| 3907 __ bind(&seq_string); | 3908 __ bind(&seq_string); |
| 3908 // subject: Subject string | 3909 // subject: Subject string |
| 3909 // regexp_data: RegExp data (FixedArray) | 3910 // regexp_data: RegExp data (FixedArray) |
| 3910 // r0: Instance type of subject string | 3911 // r0: Instance type of subject string |
| 3911 STATIC_ASSERT(4 == kAsciiStringTag); | 3912 STATIC_ASSERT(4 == kAsciiStringTag); |
| 3912 STATIC_ASSERT(kTwoByteStringTag == 0); | 3913 STATIC_ASSERT(kTwoByteStringTag == 0); |
| 3913 // Find the code object based on the assumptions above. | 3914 // Find the code object based on the assumptions above. |
| 3914 __ and_(r0, r0, Operand(kStringEncodingMask)); | 3915 __ and_(r0, r0, Operand(kStringEncodingMask)); |
| 3915 __ mov(r3, Operand(r0, ASR, 2), SetCC); | 3916 __ mov(r3, Operand(r0, ASR, 2), SetCC); |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4343 __ LoadRoot(ip, Heap::kEmptyStringRootIndex); | 4344 __ LoadRoot(ip, Heap::kEmptyStringRootIndex); |
| 4344 __ cmp(result_, Operand(ip)); | 4345 __ cmp(result_, Operand(ip)); |
| 4345 __ b(ne, &call_runtime_); | 4346 __ b(ne, &call_runtime_); |
| 4346 // Get the first of the two strings and load its instance type. | 4347 // Get the first of the two strings and load its instance type. |
| 4347 __ ldr(object_, FieldMemOperand(object_, ConsString::kFirstOffset)); | 4348 __ ldr(object_, FieldMemOperand(object_, ConsString::kFirstOffset)); |
| 4348 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 4349 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
| 4349 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 4350 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); |
| 4350 // If the first cons component is also non-flat, then go to runtime. | 4351 // If the first cons component is also non-flat, then go to runtime. |
| 4351 STATIC_ASSERT(kSeqStringTag == 0); | 4352 STATIC_ASSERT(kSeqStringTag == 0); |
| 4352 __ tst(result_, Operand(kStringRepresentationMask)); | 4353 __ tst(result_, Operand(kStringRepresentationMask)); |
| 4353 __ b(nz, &call_runtime_); | 4354 __ b(ne, &call_runtime_); |
| 4354 | 4355 |
| 4355 // Check for 1-byte or 2-byte string. | 4356 // Check for 1-byte or 2-byte string. |
| 4356 __ bind(&flat_string); | 4357 __ bind(&flat_string); |
| 4357 STATIC_ASSERT(kAsciiStringTag != 0); | 4358 STATIC_ASSERT(kAsciiStringTag != 0); |
| 4358 __ tst(result_, Operand(kStringEncodingMask)); | 4359 __ tst(result_, Operand(kStringEncodingMask)); |
| 4359 __ b(nz, &ascii_string); | 4360 __ b(ne, &ascii_string); |
| 4360 | 4361 |
| 4361 // 2-byte string. | 4362 // 2-byte string. |
| 4362 // Load the 2-byte character code into the result register. We can | 4363 // Load the 2-byte character code into the result register. We can |
| 4363 // add without shifting since the smi tag size is the log2 of the | 4364 // add without shifting since the smi tag size is the log2 of the |
| 4364 // number of bytes in a two-byte character. | 4365 // number of bytes in a two-byte character. |
| 4365 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1 && kSmiShiftSize == 0); | 4366 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1 && kSmiShiftSize == 0); |
| 4366 __ add(scratch_, object_, Operand(scratch_)); | 4367 __ add(scratch_, object_, Operand(scratch_)); |
| 4367 __ ldrh(result_, FieldMemOperand(scratch_, SeqTwoByteString::kHeaderSize)); | 4368 __ ldrh(result_, FieldMemOperand(scratch_, SeqTwoByteString::kHeaderSize)); |
| 4368 __ jmp(&got_char_code); | 4369 __ jmp(&got_char_code); |
| 4369 | 4370 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4434 // StringCharFromCodeGenerator | 4435 // StringCharFromCodeGenerator |
| 4435 | 4436 |
| 4436 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { | 4437 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { |
| 4437 // Fast case of Heap::LookupSingleCharacterStringFromCode. | 4438 // Fast case of Heap::LookupSingleCharacterStringFromCode. |
| 4438 STATIC_ASSERT(kSmiTag == 0); | 4439 STATIC_ASSERT(kSmiTag == 0); |
| 4439 STATIC_ASSERT(kSmiShiftSize == 0); | 4440 STATIC_ASSERT(kSmiShiftSize == 0); |
| 4440 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1)); | 4441 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1)); |
| 4441 __ tst(code_, | 4442 __ tst(code_, |
| 4442 Operand(kSmiTagMask | | 4443 Operand(kSmiTagMask | |
| 4443 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); | 4444 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); |
| 4444 __ b(nz, &slow_case_); | 4445 __ b(ne, &slow_case_); |
| 4445 | 4446 |
| 4446 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); | 4447 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); |
| 4447 // At this point code register contains smi tagged ascii char code. | 4448 // At this point code register contains smi tagged ascii char code. |
| 4448 STATIC_ASSERT(kSmiTag == 0); | 4449 STATIC_ASSERT(kSmiTag == 0); |
| 4449 __ add(result_, result_, Operand(code_, LSL, kPointerSizeLog2 - kSmiTagSize)); | 4450 __ add(result_, result_, Operand(code_, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 4450 __ ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); | 4451 __ ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); |
| 4451 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 4452 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 4452 __ cmp(result_, Operand(ip)); | 4453 __ cmp(result_, Operand(ip)); |
| 4453 __ b(eq, &slow_case_); | 4454 __ b(eq, &slow_case_); |
| 4454 __ bind(&exit_); | 4455 __ bind(&exit_); |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4881 void StringHelper::GenerateHashGetHash(MacroAssembler* masm, | 4882 void StringHelper::GenerateHashGetHash(MacroAssembler* masm, |
| 4882 Register hash) { | 4883 Register hash) { |
| 4883 // hash += hash << 3; | 4884 // hash += hash << 3; |
| 4884 __ add(hash, hash, Operand(hash, LSL, 3)); | 4885 __ add(hash, hash, Operand(hash, LSL, 3)); |
| 4885 // hash ^= hash >> 11; | 4886 // hash ^= hash >> 11; |
| 4886 __ eor(hash, hash, Operand(hash, ASR, 11)); | 4887 __ eor(hash, hash, Operand(hash, ASR, 11)); |
| 4887 // hash += hash << 15; | 4888 // hash += hash << 15; |
| 4888 __ add(hash, hash, Operand(hash, LSL, 15), SetCC); | 4889 __ add(hash, hash, Operand(hash, LSL, 15), SetCC); |
| 4889 | 4890 |
| 4890 // if (hash == 0) hash = 27; | 4891 // if (hash == 0) hash = 27; |
| 4891 __ mov(hash, Operand(27), LeaveCC, nz); | 4892 __ mov(hash, Operand(27), LeaveCC, ne); |
| 4892 } | 4893 } |
| 4893 | 4894 |
| 4894 | 4895 |
| 4895 void SubStringStub::Generate(MacroAssembler* masm) { | 4896 void SubStringStub::Generate(MacroAssembler* masm) { |
| 4896 Label runtime; | 4897 Label runtime; |
| 4897 | 4898 |
| 4898 // Stack frame on entry. | 4899 // Stack frame on entry. |
| 4899 // lr: return address | 4900 // lr: return address |
| 4900 // sp[0]: to | 4901 // sp[0]: to |
| 4901 // sp[4]: from | 4902 // sp[4]: from |
| (...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5620 __ pop(r1); | 5621 __ pop(r1); |
| 5621 __ Jump(r2); | 5622 __ Jump(r2); |
| 5622 } | 5623 } |
| 5623 | 5624 |
| 5624 | 5625 |
| 5625 #undef __ | 5626 #undef __ |
| 5626 | 5627 |
| 5627 } } // namespace v8::internal | 5628 } } // namespace v8::internal |
| 5628 | 5629 |
| 5629 #endif // V8_TARGET_ARCH_ARM | 5630 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |