Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/arm/regexp-macro-assembler-arm.cc

Issue 10386090: Implement loop for global regexps in regexp assembler. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix bugs, add tests, port to x64 and arm. Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698