OLD | NEW |
---|---|
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 23 matching lines...) Expand all Loading... | |
35 #include "regexp-stack.h" | 35 #include "regexp-stack.h" |
36 #include "macro-assembler.h" | 36 #include "macro-assembler.h" |
37 #include "regexp-macro-assembler.h" | 37 #include "regexp-macro-assembler.h" |
38 #include "arm/regexp-macro-assembler-arm.h" | 38 #include "arm/regexp-macro-assembler-arm.h" |
39 | 39 |
40 namespace v8 { | 40 namespace v8 { |
41 namespace internal { | 41 namespace internal { |
42 | 42 |
43 #ifndef V8_INTERPRETED_REGEXP | 43 #ifndef V8_INTERPRETED_REGEXP |
44 /* | 44 /* |
45 * This assembler uses the following register assignment convention | 45 * This assembler uses the following register assignment convention |
Erik Corry
2012/05/22 08:32:46
This needs updating to include r4
Yang
2012/05/22 14:48:03
Done.
| |
46 * - r5 : Pointer to current code object (Code*) including heap object tag. | 46 * - r5 : Pointer to current code object (Code*) including heap object tag. |
47 * - r6 : Current position in input, as negative offset from end of string. | 47 * - r6 : Current position in input, as negative offset from end of string. |
48 * Please notice that this is the byte offset, not the character offset! | 48 * Please notice that this is the byte offset, not the character offset! |
49 * - r7 : Currently loaded character. Must be loaded using | 49 * - r7 : Currently loaded character. Must be loaded using |
50 * LoadCurrentCharacter before using any of the dispatch methods. | 50 * LoadCurrentCharacter before using any of the dispatch methods. |
51 * - r8 : points to tip of backtrack stack | 51 * - r8 : points to tip of backtrack stack |
52 * - r9 : Unused, might be used by C code and expected unchanged. | 52 * - r9 : Unused, might be used by C code and expected unchanged. |
53 * - r10 : End of input (points to byte after last character in input). | 53 * - r10 : End of input (points to byte after last character in input). |
54 * - r11 : Frame pointer. Used to access arguments, local variables and | 54 * - r11 : Frame pointer. Used to access arguments, local variables and |
55 * RegExp registers. | 55 * RegExp registers. |
56 * - r12 : IP register, used by assembler. Very volatile. | 56 * - r12 : IP register, used by assembler. Very volatile. |
57 * - r13/sp : points to tip of C stack. | 57 * - r13/sp : points to tip of C stack. |
58 * | 58 * |
59 * The remaining registers are free for computations. | 59 * The remaining registers are free for computations. |
60 * Each call to a public method should retain this convention. | 60 * Each call to a public method should retain this convention. |
61 * | 61 * |
62 * The stack will have the following structure: | 62 * The stack will have the following structure: |
63 * - fp[52] Isolate* isolate (Address of the current isolate) | 63 * - fp[56] Isolate* isolate (Address of the current isolate) |
64 * - fp[48] direct_call (if 1, direct call from JavaScript code, | 64 * - fp[52] direct_call (if 1, direct call from JavaScript code, |
65 * if 0, call through the runtime system). | 65 * if 0, call through the runtime system). |
66 * - fp[44] stack_area_base (High end of the memory area to use as | 66 * - fp[48] stack_area_base (High end of the memory area to use as |
67 * backtracking stack). | 67 * backtracking stack). |
68 * - fp[44] capture array size (may fit multiple sets of matches) | |
68 * - fp[40] int* capture_array (int[num_saved_registers_], for output). | 69 * - fp[40] int* capture_array (int[num_saved_registers_], for output). |
69 * - fp[36] secondary link/return address used by native call. | 70 * - fp[36] secondary link/return address used by native call. |
70 * --- sp when called --- | 71 * --- sp when called --- |
71 * - fp[32] return address (lr). | 72 * - fp[32] return address (lr). |
72 * - fp[28] old frame pointer (r11). | 73 * - fp[28] old frame pointer (r11). |
73 * - fp[0..24] backup of registers r4..r10. | 74 * - fp[0..24] backup of registers r4..r10. |
74 * --- frame pointer ---- | 75 * --- frame pointer ---- |
75 * - fp[-4] end of input (Address of end of string). | 76 * - fp[-4] end of input (Address of end of string). |
76 * - fp[-8] start of input (Address of first character in string). | 77 * - fp[-8] start of input (Address of first character in string). |
77 * - fp[-12] start index (character index of start). | 78 * - fp[-12] start index (character index of start). |
Erik Corry
2012/05/22 08:32:46
Inconsistent capitalization, not started by you.
Yang
2012/05/22 14:48:03
Done.
| |
78 * - fp[-16] void* input_string (location of a handle containing the string). | 79 * - fp[-16] void* input_string (location of a handle containing the string). |
79 * - fp[-20] Offset of location before start of input (effectively character | 80 * - fp[-20] success counter (only useful for global regexp to count matches ) |
Erik Corry
2012/05/22 08:32:46
Does this lint?
Yang
2012/05/22 14:48:03
Done.
| |
81 * - fp[-24] Offset of location before start of input (effectively character | |
80 * position -1). Used to initialize capture registers to a | 82 * position -1). Used to initialize capture registers to a |
81 * non-position. | 83 * non-position. |
82 * - fp[-24] At start (if 1, we are starting at the start of the | 84 * - fp[-28] At start (if 1, we are starting at the start of the |
83 * string, otherwise 0) | 85 * string, otherwise 0) |
84 * - fp[-28] register 0 (Only positions must be stored in the first | 86 * - fp[-32] register 0 (Only positions must be stored in the first |
85 * - register 1 num_saved_registers_ registers) | 87 * - register 1 num_saved_registers_ registers) |
86 * - ... | 88 * - ... |
87 * - register num_registers-1 | 89 * - register num_registers-1 |
88 * --- sp --- | 90 * --- sp --- |
89 * | 91 * |
90 * The first num_saved_registers_ registers are initialized to point to | 92 * The first num_saved_registers_ registers are initialized to point to |
91 * "character -1" in the string (i.e., char_size() bytes before the first | 93 * "character -1" in the string (i.e., char_size() bytes before the first |
92 * character of the string). The remaining registers start out as garbage. | 94 * character of the string). The remaining registers start out as garbage. |
93 * | 95 * |
94 * The data up to the return address must be placed there by the calling | 96 * The data up to the return address must be placed there by the calling |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
648 } | 650 } |
649 | 651 |
650 | 652 |
651 void RegExpMacroAssemblerARM::Fail() { | 653 void RegExpMacroAssemblerARM::Fail() { |
652 __ mov(r0, Operand(FAILURE)); | 654 __ mov(r0, Operand(FAILURE)); |
653 __ jmp(&exit_label_); | 655 __ jmp(&exit_label_); |
654 } | 656 } |
655 | 657 |
656 | 658 |
657 Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) { | 659 Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) { |
660 Label return_r0, restart; | |
658 // Finalize code - write the entry point code now we know how many | 661 // Finalize code - write the entry point code now we know how many |
659 // registers we need. | 662 // registers we need. |
660 | 663 |
661 // Entry code: | 664 // Entry code: |
662 __ bind(&entry_label_); | 665 __ bind(&entry_label_); |
663 | 666 |
664 // Tell the system that we have a stack frame. Because the type is MANUAL, no | 667 // Tell the system that we have a stack frame. Because the type is MANUAL, no |
665 // is generated. | 668 // is generated. |
666 FrameScope scope(masm_, StackFrame::MANUAL); | 669 FrameScope scope(masm_, StackFrame::MANUAL); |
667 | 670 |
668 // Actually emit code to start a new stack frame. | 671 // Actually emit code to start a new stack frame. |
669 // Push arguments | 672 // Push arguments |
670 // Save callee-save registers. | 673 // Save callee-save registers. |
671 // Start new stack frame. | 674 // Start new stack frame. |
672 // Store link register in existing stack-cell. | 675 // Store link register in existing stack-cell. |
673 // Order here should correspond to order of offset constants in header file. | 676 // Order here should correspond to order of offset constants in header file. |
674 RegList registers_to_retain = r4.bit() | r5.bit() | r6.bit() | | 677 RegList registers_to_retain = r4.bit() | r5.bit() | r6.bit() | |
675 r7.bit() | r8.bit() | r9.bit() | r10.bit() | fp.bit(); | 678 r7.bit() | r8.bit() | r9.bit() | r10.bit() | fp.bit(); |
676 RegList argument_registers = r0.bit() | r1.bit() | r2.bit() | r3.bit(); | 679 RegList argument_registers = r0.bit() | r1.bit() | r2.bit() | r3.bit(); |
677 __ stm(db_w, sp, argument_registers | registers_to_retain | lr.bit()); | 680 __ stm(db_w, sp, argument_registers | registers_to_retain | lr.bit()); |
678 // Set frame pointer in space for it if this is not a direct call | 681 // Set frame pointer in space for it if this is not a direct call |
679 // from generated code. | 682 // from generated code. |
680 __ add(frame_pointer(), sp, Operand(4 * kPointerSize)); | 683 __ add(frame_pointer(), sp, Operand(4 * kPointerSize)); |
684 __ mov(r0, Operand(0, RelocInfo::NONE)); | |
685 __ push(r0); // Make room for success counter and initialize it to 0. | |
681 __ push(r0); // Make room for "position - 1" constant (value is irrelevant). | 686 __ push(r0); // Make room for "position - 1" constant (value is irrelevant). |
682 __ push(r0); // Make room for "at start" constant (value is irrelevant). | 687 __ push(r0); // Make room for "at start" constant (value is irrelevant). |
683 // Check if we have space on the stack for registers. | 688 // Check if we have space on the stack for registers. |
684 Label stack_limit_hit; | 689 Label stack_limit_hit; |
685 Label stack_ok; | 690 Label stack_ok; |
686 | 691 |
687 ExternalReference stack_limit = | 692 ExternalReference stack_limit = |
688 ExternalReference::address_of_stack_limit(masm_->isolate()); | 693 ExternalReference::address_of_stack_limit(masm_->isolate()); |
689 __ mov(r0, Operand(stack_limit)); | 694 __ mov(r0, Operand(stack_limit)); |
690 __ ldr(r0, MemOperand(r0)); | 695 __ ldr(r0, MemOperand(r0)); |
691 __ sub(r0, sp, r0, SetCC); | 696 __ sub(r0, sp, r0, SetCC); |
692 // Handle it if the stack pointer is already below the stack limit. | 697 // Handle it if the stack pointer is already below the stack limit. |
693 __ b(ls, &stack_limit_hit); | 698 __ b(ls, &stack_limit_hit); |
694 // Check if there is room for the variable number of registers above | 699 // Check if there is room for the variable number of registers above |
695 // the stack limit. | 700 // the stack limit. |
696 __ cmp(r0, Operand(num_registers_ * kPointerSize)); | 701 __ cmp(r0, Operand(num_registers_ * kPointerSize)); |
697 __ b(hs, &stack_ok); | 702 __ b(hs, &stack_ok); |
698 // Exit with OutOfMemory exception. There is not enough space on the stack | 703 // Exit with OutOfMemory exception. There is not enough space on the stack |
699 // for our working registers. | 704 // for our working registers. |
700 __ mov(r0, Operand(EXCEPTION)); | 705 __ mov(r0, Operand(EXCEPTION)); |
701 __ jmp(&exit_label_); | 706 __ jmp(&return_r0); |
702 | 707 |
703 __ bind(&stack_limit_hit); | 708 __ bind(&stack_limit_hit); |
704 CallCheckStackGuardState(r0); | 709 CallCheckStackGuardState(r0); |
705 __ cmp(r0, Operand(0, RelocInfo::NONE)); | 710 __ cmp(r0, Operand(0, RelocInfo::NONE)); |
706 // If returned value is non-zero, we exit with the returned value as result. | 711 // If returned value is non-zero, we exit with the returned value as result. |
707 __ b(ne, &exit_label_); | 712 __ b(ne, &return_r0); |
708 | 713 |
709 __ bind(&stack_ok); | 714 __ bind(&stack_ok); |
710 | 715 |
711 // Allocate space on stack for registers. | 716 // Allocate space on stack for registers. |
712 __ sub(sp, sp, Operand(num_registers_ * kPointerSize)); | 717 __ sub(sp, sp, Operand(num_registers_ * kPointerSize)); |
713 // Load string end. | 718 // Load string end. |
714 __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); | 719 __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); |
715 // Load input start. | 720 // Load input start. |
716 __ ldr(r0, MemOperand(frame_pointer(), kInputStart)); | 721 __ ldr(r0, MemOperand(frame_pointer(), kInputStart)); |
717 // Find negative length (offset of start relative to end). | 722 // Find negative length (offset of start relative to end). |
718 __ sub(current_input_offset(), r0, end_of_input_address()); | 723 __ sub(current_input_offset(), r0, end_of_input_address()); |
719 // Set r0 to address of char before start of the input string | 724 // Set r0 to address of char before start of the input string |
720 // (effectively string position -1). | 725 // (effectively string position -1). |
721 __ ldr(r1, MemOperand(frame_pointer(), kStartIndex)); | 726 __ ldr(r1, MemOperand(frame_pointer(), kStartIndex)); |
722 __ sub(r0, current_input_offset(), Operand(char_size())); | 727 __ sub(r0, current_input_offset(), Operand(char_size())); |
723 __ sub(r0, r0, Operand(r1, LSL, (mode_ == UC16) ? 1 : 0)); | 728 __ sub(r0, r0, Operand(r1, LSL, (mode_ == UC16) ? 1 : 0)); |
724 // Store this value in a local variable, for use when clearing | 729 // Store this value in a local variable, for use when clearing |
725 // position registers. | 730 // position registers. |
726 __ str(r0, MemOperand(frame_pointer(), kInputStartMinusOne)); | 731 __ str(r0, MemOperand(frame_pointer(), kInputStartMinusOne)); |
727 | 732 |
733 // Initialize code pointer register | |
734 __ mov(code_pointer(), Operand(masm_->CodeObject())); | |
735 // Load previous char as initial value of current character register. | |
736 Label at_start, character_loaded; | |
728 // Determine whether the start index is zero, that is at the start of the | 737 // Determine whether the start index is zero, that is at the start of the |
729 // string, and store that value in a local variable. | 738 // string, and store that value in a local variable. Store the result to |
730 __ cmp(r1, Operand(0)); | 739 // local variable kAtStart. |
740 __ cmp(r1, Operand(0, RelocInfo::NONE)); | |
731 __ mov(r1, Operand(1), LeaveCC, eq); | 741 __ mov(r1, Operand(1), LeaveCC, eq); |
732 __ mov(r1, Operand(0, RelocInfo::NONE), LeaveCC, ne); | 742 __ mov(r1, Operand(0, RelocInfo::NONE), LeaveCC, ne); |
733 __ str(r1, MemOperand(frame_pointer(), kAtStart)); | 743 __ str(r1, MemOperand(frame_pointer(), kAtStart)); |
744 // Load newline if index is at start. | |
745 __ mov(current_character(), Operand('\n'), LeaveCC, eq); | |
Erik Corry
2012/05/22 08:32:46
Having conditional instructions here after non-con
Yang
2012/05/22 14:48:03
Done.
| |
746 __ b(eq, &character_loaded); | |
747 LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. | |
734 | 748 |
749 if (global()) { | |
750 // Initializing current-character already done, so skip it. | |
751 __ jmp(&character_loaded); | |
752 // Restart matching from here in a global regexp. | |
753 __ bind(&restart); | |
754 // In a restarted pass, initialize current-character here. | |
755 LoadCurrentCharacterUnchecked(-1, 1); | |
Erik Corry
2012/05/22 08:32:46
In the global case the generated code isn't making
Yang
2012/05/22 14:48:03
Done.
| |
756 } | |
757 __ bind(&character_loaded); | |
758 | |
759 // Initialize on-stack registers. | |
735 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. | 760 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. |
736 // Fill saved registers with initial value = start offset - 1 | 761 // Fill saved registers with initial value = start offset - 1 |
737 | 762 if (num_saved_registers_ > 8) { |
738 // Address of register 0. | 763 // Address of register 0. |
739 __ add(r1, frame_pointer(), Operand(kRegisterZero)); | 764 __ add(r1, frame_pointer(), Operand(kRegisterZero)); |
740 __ mov(r2, Operand(num_saved_registers_)); | 765 __ mov(r2, Operand(num_saved_registers_)); |
741 Label init_loop; | 766 Label init_loop; |
742 __ bind(&init_loop); | 767 __ bind(&init_loop); |
743 __ str(r0, MemOperand(r1, kPointerSize, NegPostIndex)); | 768 __ str(r0, MemOperand(r1, kPointerSize, NegPostIndex)); |
744 __ sub(r2, r2, Operand(1), SetCC); | 769 __ sub(r2, r2, Operand(1), SetCC); |
745 __ b(ne, &init_loop); | 770 __ b(ne, &init_loop); |
771 } else { | |
772 for (int i = 0; i < num_saved_registers_; i++) { | |
773 __ str(r0, register_location(i)); | |
774 } | |
775 } | |
746 } | 776 } |
747 | 777 |
748 // Initialize backtrack stack pointer. | 778 // Initialize backtrack stack pointer. |
749 __ ldr(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd)); | 779 __ ldr(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd)); |
750 // Initialize code pointer register | 780 |
751 __ mov(code_pointer(), Operand(masm_->CodeObject())); | |
752 // Load previous char as initial value of current character register. | |
753 Label at_start; | |
754 __ ldr(r0, MemOperand(frame_pointer(), kAtStart)); | |
755 __ cmp(r0, Operand(0, RelocInfo::NONE)); | |
756 __ b(ne, &at_start); | |
757 LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. | |
758 __ jmp(&start_label_); | 781 __ jmp(&start_label_); |
759 __ bind(&at_start); | |
760 __ mov(current_character(), Operand('\n')); | |
761 __ jmp(&start_label_); | |
762 | |
763 | 782 |
764 // Exit code: | 783 // Exit code: |
765 if (success_label_.is_linked()) { | 784 if (success_label_.is_linked()) { |
766 // Save captures when successful. | 785 // Save captures when successful. |
767 __ bind(&success_label_); | 786 __ bind(&success_label_); |
768 if (num_saved_registers_ > 0) { | 787 if (num_saved_registers_ > 0) { |
769 // copy captures to output | 788 // copy captures to output |
770 __ ldr(r1, MemOperand(frame_pointer(), kInputStart)); | 789 __ ldr(r1, MemOperand(frame_pointer(), kInputStart)); |
771 __ ldr(r0, MemOperand(frame_pointer(), kRegisterOutput)); | 790 __ ldr(r0, MemOperand(frame_pointer(), kRegisterOutput)); |
772 __ ldr(r2, MemOperand(frame_pointer(), kStartIndex)); | 791 __ ldr(r2, MemOperand(frame_pointer(), kStartIndex)); |
773 __ sub(r1, end_of_input_address(), r1); | 792 __ sub(r1, end_of_input_address(), r1); |
774 // r1 is length of input in bytes. | 793 // r1 is length of input in bytes. |
775 if (mode_ == UC16) { | 794 if (mode_ == UC16) { |
776 __ mov(r1, Operand(r1, LSR, 1)); | 795 __ mov(r1, Operand(r1, LSR, 1)); |
777 } | 796 } |
778 // r1 is length of input in characters. | 797 // r1 is length of input in characters. |
779 __ add(r1, r1, Operand(r2)); | 798 __ add(r1, r1, Operand(r2)); |
780 // r1 is length of string in characters. | 799 // r1 is length of string in characters. |
781 | 800 |
782 ASSERT_EQ(0, num_saved_registers_ % 2); | 801 ASSERT_EQ(0, num_saved_registers_ % 2); |
783 // Always an even number of capture registers. This allows us to | 802 // Always an even number of capture registers. This allows us to |
784 // unroll the loop once to add an operation between a load of a register | 803 // unroll the loop once to add an operation between a load of a register |
785 // and the following use of that register. | 804 // and the following use of that register. |
786 for (int i = 0; i < num_saved_registers_; i += 2) { | 805 for (int i = 0; i < num_saved_registers_; i += 2) { |
787 __ ldr(r2, register_location(i)); | 806 __ ldr(r2, register_location(i)); |
788 __ ldr(r3, register_location(i + 1)); | 807 __ ldr(r3, register_location(i + 1)); |
808 if (global()) { | |
809 // Keep capture start in r4 for the zero-length check later. | |
810 __ mov(r4, r2); | |
811 } | |
789 if (mode_ == UC16) { | 812 if (mode_ == UC16) { |
790 __ add(r2, r1, Operand(r2, ASR, 1)); | 813 __ add(r2, r1, Operand(r2, ASR, 1)); |
791 __ add(r3, r1, Operand(r3, ASR, 1)); | 814 __ add(r3, r1, Operand(r3, ASR, 1)); |
792 } else { | 815 } else { |
793 __ add(r2, r1, Operand(r2)); | 816 __ add(r2, r1, Operand(r2)); |
794 __ add(r3, r1, Operand(r3)); | 817 __ add(r3, r1, Operand(r3)); |
795 } | 818 } |
796 __ str(r2, MemOperand(r0, kPointerSize, PostIndex)); | 819 __ str(r2, MemOperand(r0, kPointerSize, PostIndex)); |
797 __ str(r3, MemOperand(r0, kPointerSize, PostIndex)); | 820 __ str(r3, MemOperand(r0, kPointerSize, PostIndex)); |
798 } | 821 } |
799 } | 822 } |
800 __ mov(r0, Operand(SUCCESS)); | 823 |
824 if (global()) { | |
825 // Restart matching if the regular expression is flagged as global. | |
826 __ ldr(r0, MemOperand(frame_pointer(), kSuccessfulCaptures)); | |
827 __ ldr(r1, MemOperand(frame_pointer(), kNumOutputRegisters)); | |
828 __ ldr(r2, MemOperand(frame_pointer(), kRegisterOutput)); | |
829 // Increment success counter. | |
830 __ add(r0, r0, Operand(1)); | |
831 __ str(r0, MemOperand(frame_pointer(), kSuccessfulCaptures)); | |
832 // Capture results have been stored, so the number of remaining global | |
833 // output registers is reduced by the number of stored captures. | |
834 __ sub(r1, r1, Operand(num_saved_registers_)); | |
835 // Check whether we have enough room for another set of capture results. | |
836 __ cmp(r1, Operand(num_saved_registers_)); | |
837 __ b(lt, &return_r0); | |
838 | |
839 __ str(r1, MemOperand(frame_pointer(), kNumOutputRegisters)); | |
840 // Advance the location for output. | |
841 __ add(r2, r2, Operand(num_saved_registers_ * kPointerSize)); | |
842 __ str(r2, MemOperand(frame_pointer(), kRegisterOutput)); | |
843 | |
844 // Prepare r0 to initialize registers with its value in the next run. | |
845 __ ldr(r0, MemOperand(frame_pointer(), kInputStartMinusOne)); | |
846 // Special case for zero-length matches. | |
847 // r4: capture start index | |
848 __ cmp(current_input_offset(), r4); | |
849 // Not a zero-length match, restart. | |
850 __ b(ne, &restart); | |
851 // Offset from the end is zero if we already reached the end. | |
852 __ cmp(current_input_offset(), Operand(0)); | |
853 __ b(eq, &exit_label_); | |
854 // Advance current position after a zero-length match. | |
855 __ add(current_input_offset(), | |
856 current_input_offset(), | |
857 Operand((mode_ == UC16) ? 2 : 1)); | |
858 __ b(&restart); | |
859 } else { | |
860 __ mov(r0, Operand(SUCCESS)); | |
861 } | |
801 } | 862 } |
863 | |
802 // Exit and return r0 | 864 // Exit and return r0 |
803 __ bind(&exit_label_); | 865 __ bind(&exit_label_); |
866 if (global()) { | |
867 __ ldr(r0, MemOperand(frame_pointer(), kSuccessfulCaptures)); | |
868 } | |
869 | |
870 __ bind(&return_r0); | |
804 // Skip sp past regexp registers and local variables.. | 871 // Skip sp past regexp registers and local variables.. |
805 __ mov(sp, frame_pointer()); | 872 __ mov(sp, frame_pointer()); |
806 // Restore registers r4..r11 and return (restoring lr to pc). | 873 // Restore registers r4..r11 and return (restoring lr to pc). |
807 __ ldm(ia_w, sp, registers_to_retain | pc.bit()); | 874 __ ldm(ia_w, sp, registers_to_retain | pc.bit()); |
808 | 875 |
809 // Backtrack code (branch target for conditional backtracks). | 876 // Backtrack code (branch target for conditional backtracks). |
810 if (backtrack_label_.is_linked()) { | 877 if (backtrack_label_.is_linked()) { |
811 __ bind(&backtrack_label_); | 878 __ bind(&backtrack_label_); |
812 Backtrack(); | 879 Backtrack(); |
813 } | 880 } |
814 | 881 |
815 Label exit_with_exception; | 882 Label exit_with_exception; |
816 | 883 |
817 // Preempt-code | 884 // Preempt-code |
818 if (check_preempt_label_.is_linked()) { | 885 if (check_preempt_label_.is_linked()) { |
819 SafeCallTarget(&check_preempt_label_); | 886 SafeCallTarget(&check_preempt_label_); |
820 | 887 |
821 CallCheckStackGuardState(r0); | 888 CallCheckStackGuardState(r0); |
822 __ cmp(r0, Operand(0, RelocInfo::NONE)); | 889 __ cmp(r0, Operand(0, RelocInfo::NONE)); |
823 // If returning non-zero, we should end execution with the given | 890 // If returning non-zero, we should end execution with the given |
824 // result as return value. | 891 // result as return value. |
825 __ b(ne, &exit_label_); | 892 __ b(ne, &return_r0); |
826 | 893 |
827 // String might have moved: Reload end of string from frame. | 894 // String might have moved: Reload end of string from frame. |
Erik Corry
2012/05/22 08:32:46
If this happens will r4 be updated with the correc
Yang
2012/05/22 14:48:03
r4 is a relative index from the end of string, the
| |
828 __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); | 895 __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); |
829 SafeReturn(); | 896 SafeReturn(); |
830 } | 897 } |
831 | 898 |
832 // Backtrack stack overflow code. | 899 // Backtrack stack overflow code. |
833 if (stack_overflow_label_.is_linked()) { | 900 if (stack_overflow_label_.is_linked()) { |
834 SafeCallTarget(&stack_overflow_label_); | 901 SafeCallTarget(&stack_overflow_label_); |
835 // Reached if the backtrack-stack limit has been hit. | 902 // Reached if the backtrack-stack limit has been hit. |
836 Label grow_failed; | 903 Label grow_failed; |
837 | 904 |
(...skipping 14 matching lines...) Expand all Loading... | |
852 __ mov(backtrack_stackpointer(), r0); | 919 __ mov(backtrack_stackpointer(), r0); |
853 // Restore saved registers and continue. | 920 // Restore saved registers and continue. |
854 SafeReturn(); | 921 SafeReturn(); |
855 } | 922 } |
856 | 923 |
857 if (exit_with_exception.is_linked()) { | 924 if (exit_with_exception.is_linked()) { |
858 // If any of the code above needed to exit with an exception. | 925 // If any of the code above needed to exit with an exception. |
859 __ bind(&exit_with_exception); | 926 __ bind(&exit_with_exception); |
860 // Exit with Result EXCEPTION(-1) to signal thrown exception. | 927 // Exit with Result EXCEPTION(-1) to signal thrown exception. |
861 __ mov(r0, Operand(EXCEPTION)); | 928 __ mov(r0, Operand(EXCEPTION)); |
862 __ jmp(&exit_label_); | 929 __ jmp(&return_r0); |
863 } | 930 } |
864 | 931 |
865 CodeDesc code_desc; | 932 CodeDesc code_desc; |
866 masm_->GetCode(&code_desc); | 933 masm_->GetCode(&code_desc); |
867 Handle<Code> code = FACTORY->NewCode(code_desc, | 934 Handle<Code> code = FACTORY->NewCode(code_desc, |
868 Code::ComputeFlags(Code::REGEXP), | 935 Code::ComputeFlags(Code::REGEXP), |
869 masm_->CodeObject()); | 936 masm_->CodeObject()); |
870 PROFILE(Isolate::Current(), RegExpCodeCreateEvent(*code, *source)); | 937 PROFILE(Isolate::Current(), RegExpCodeCreateEvent(*code, *source)); |
871 return Handle<HeapObject>::cast(code); | 938 return Handle<HeapObject>::cast(code); |
872 } | 939 } |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1300 __ ldr(sp, MemOperand(sp, 0)); | 1367 __ ldr(sp, MemOperand(sp, 0)); |
1301 } | 1368 } |
1302 __ mov(code_pointer(), Operand(masm_->CodeObject())); | 1369 __ mov(code_pointer(), Operand(masm_->CodeObject())); |
1303 } | 1370 } |
1304 | 1371 |
1305 | 1372 |
1306 void RegExpMacroAssemblerARM::LoadCurrentCharacterUnchecked(int cp_offset, | 1373 void RegExpMacroAssemblerARM::LoadCurrentCharacterUnchecked(int cp_offset, |
1307 int characters) { | 1374 int characters) { |
1308 Register offset = current_input_offset(); | 1375 Register offset = current_input_offset(); |
1309 if (cp_offset != 0) { | 1376 if (cp_offset != 0) { |
1310 __ add(r0, current_input_offset(), Operand(cp_offset * char_size())); | 1377 __ add(ip, current_input_offset(), Operand(cp_offset * char_size())); |
1311 offset = r0; | 1378 offset = ip; |
Erik Corry
2012/05/22 08:32:46
This is setting a trap for a future programmer. T
Yang
2012/05/22 14:48:03
Using r4 now since it's not being used at this poi
| |
1312 } | 1379 } |
1313 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU | 1380 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU |
1314 // and the operating system running on the target allow it. | 1381 // and the operating system running on the target allow it. |
1315 // If unaligned load/stores are not supported then this function must only | 1382 // If unaligned load/stores are not supported then this function must only |
1316 // be used to load a single character at a time. | 1383 // be used to load a single character at a time. |
1317 #if !V8_TARGET_CAN_READ_UNALIGNED | 1384 #if !V8_TARGET_CAN_READ_UNALIGNED |
1318 ASSERT(characters == 1); | 1385 ASSERT(characters == 1); |
1319 #endif | 1386 #endif |
1320 | 1387 |
1321 if (mode_ == ASCII) { | 1388 if (mode_ == ASCII) { |
(...skipping 28 matching lines...) Expand all Loading... | |
1350 __ ldr(pc, MemOperand(sp, stack_alignment, PostIndex)); | 1417 __ ldr(pc, MemOperand(sp, stack_alignment, PostIndex)); |
1351 } | 1418 } |
1352 | 1419 |
1353 #undef __ | 1420 #undef __ |
1354 | 1421 |
1355 #endif // V8_INTERPRETED_REGEXP | 1422 #endif // V8_INTERPRETED_REGEXP |
1356 | 1423 |
1357 }} // namespace v8::internal | 1424 }} // namespace v8::internal |
1358 | 1425 |
1359 #endif // V8_TARGET_ARCH_ARM | 1426 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |