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

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

Issue 10436012: MIPS: Implement loop for global regexps in regexp assembler. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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
« no previous file with comments | « src/mips/regexp-macro-assembler-mips.h ('k') | src/mips/simulator-mips.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 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
(...skipping 25 matching lines...) Expand all
36 #include "macro-assembler.h" 36 #include "macro-assembler.h"
37 #include "regexp-macro-assembler.h" 37 #include "regexp-macro-assembler.h"
38 #include "mips/regexp-macro-assembler-mips.h" 38 #include "mips/regexp-macro-assembler-mips.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
46 * - t7 : Temporarily stores the index of capture start after a matching pass
47 * for a global regexp.
46 * - t1 : Pointer to current code object (Code*) including heap object tag. 48 * - t1 : Pointer to current code object (Code*) including heap object tag.
47 * - t2 : Current position in input, as negative offset from end of string. 49 * - t2 : Current position in input, as negative offset from end of string.
48 * Please notice that this is the byte offset, not the character offset! 50 * Please notice that this is the byte offset, not the character offset!
49 * - t3 : Currently loaded character. Must be loaded using 51 * - t3 : Currently loaded character. Must be loaded using
50 * LoadCurrentCharacter before using any of the dispatch methods. 52 * LoadCurrentCharacter before using any of the dispatch methods.
51 * - t4 : points to tip of backtrack stack 53 * - t4 : Points to tip of backtrack stack
52 * - t5 : Unused. 54 * - t5 : Unused.
53 * - t6 : End of input (points to byte after last character in input). 55 * - t6 : End of input (points to byte after last character in input).
54 * - fp : Frame pointer. Used to access arguments, local variables and 56 * - fp : Frame pointer. Used to access arguments, local variables and
55 * RegExp registers. 57 * RegExp registers.
56 * - sp : points to tip of C stack. 58 * - sp : Points to tip of C stack.
57 * 59 *
58 * The remaining registers are free for computations. 60 * The remaining registers are free for computations.
59 * Each call to a public method should retain this convention. 61 * Each call to a public method should retain this convention.
60 * 62 *
61 * The stack will have the following structure: 63 * The stack will have the following structure:
62 * 64 *
63 * - fp[56] direct_call (if 1, direct call from JavaScript code, 65 * - fp[64] Isolate* isolate (address of the current isolate)
66 * - fp[60] direct_call (if 1, direct call from JavaScript code,
64 * if 0, call through the runtime system). 67 * if 0, call through the runtime system).
65 * - fp[52] stack_area_base (High end of the memory area to use as 68 * - fp[56] stack_area_base (High end of the memory area to use as
66 * backtracking stack). 69 * backtracking stack).
70 * - fp[52] capture array size (may fit multiple sets of matches)
67 * - fp[48] int* capture_array (int[num_saved_registers_], for output). 71 * - fp[48] int* capture_array (int[num_saved_registers_], for output).
68 * - fp[44] secondary link/return address used by native call. 72 * - fp[44] secondary link/return address used by native call.
69 * --- sp when called --- 73 * --- sp when called ---
70 * - fp[40] return address (lr). 74 * - fp[40] return address (lr).
71 * - fp[36] old frame pointer (r11). 75 * - fp[36] old frame pointer (r11).
72 * - fp[0..32] backup of registers s0..s7. 76 * - fp[0..32] backup of registers s0..s7.
73 * --- frame pointer ---- 77 * --- frame pointer ----
74 * - fp[-4] end of input (Address of end of string). 78 * - fp[-4] end of input (address of end of string).
75 * - fp[-8] start of input (Address of first character in string). 79 * - fp[-8] start of input (address of first character in string).
76 * - fp[-12] start index (character index of start). 80 * - fp[-12] start index (character index of start).
77 * - fp[-16] void* input_string (location of a handle containing the string). 81 * - fp[-16] void* input_string (location of a handle containing the string).
78 * - fp[-20] Offset of location before start of input (effectively character 82 * - fp[-20] success counter (only for global regexps to count matches).
83 * - fp[-24] Offset of location before start of input (effectively character
79 * position -1). Used to initialize capture registers to a 84 * position -1). Used to initialize capture registers to a
80 * non-position. 85 * non-position.
81 * - fp[-24] At start (if 1, we are starting at the start of the 86 * - fp[-28] At start (if 1, we are starting at the start of the
82 * string, otherwise 0) 87 * string, otherwise 0)
83 * - fp[-28] register 0 (Only positions must be stored in the first 88 * - fp[-32] register 0 (Only positions must be stored in the first
84 * - register 1 num_saved_registers_ registers) 89 * - register 1 num_saved_registers_ registers)
85 * - ... 90 * - ...
86 * - register num_registers-1 91 * - register num_registers-1
87 * --- sp --- 92 * --- sp ---
88 * 93 *
89 * The first num_saved_registers_ registers are initialized to point to 94 * The first num_saved_registers_ registers are initialized to point to
90 * "character -1" in the string (i.e., char_size() bytes before the first 95 * "character -1" in the string (i.e., char_size() bytes before the first
91 * character of the string). The remaining registers start out as garbage. 96 * character of the string). The remaining registers start out as garbage.
92 * 97 *
93 * The data up to the return address must be placed there by the calling 98 * The data up to the return address must be placed there by the calling
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 199
195 200
196 void RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) { 201 void RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) {
197 BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit)); 202 BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit));
198 } 203 }
199 204
200 205
201 void RegExpMacroAssemblerMIPS::CheckAtStart(Label* on_at_start) { 206 void RegExpMacroAssemblerMIPS::CheckAtStart(Label* on_at_start) {
202 Label not_at_start; 207 Label not_at_start;
203 // Did we start the match at the start of the string at all? 208 // Did we start the match at the start of the string at all?
204 __ lw(a0, MemOperand(frame_pointer(), kAtStart)); 209 __ lw(a0, MemOperand(frame_pointer(), kStartIndex));
205 BranchOrBacktrack(&not_at_start, eq, a0, Operand(zero_reg)); 210 BranchOrBacktrack(&not_at_start, ne, a0, Operand(zero_reg));
206 211
207 // If we did, are we still at the start of the input? 212 // If we did, are we still at the start of the input?
208 __ lw(a1, MemOperand(frame_pointer(), kInputStart)); 213 __ lw(a1, MemOperand(frame_pointer(), kInputStart));
209 __ Addu(a0, end_of_input_address(), Operand(current_input_offset())); 214 __ Addu(a0, end_of_input_address(), Operand(current_input_offset()));
210 BranchOrBacktrack(on_at_start, eq, a0, Operand(a1)); 215 BranchOrBacktrack(on_at_start, eq, a0, Operand(a1));
211 __ bind(&not_at_start); 216 __ bind(&not_at_start);
212 } 217 }
213 218
214 219
215 void RegExpMacroAssemblerMIPS::CheckNotAtStart(Label* on_not_at_start) { 220 void RegExpMacroAssemblerMIPS::CheckNotAtStart(Label* on_not_at_start) {
216 // Did we start the match at the start of the string at all? 221 // Did we start the match at the start of the string at all?
217 __ lw(a0, MemOperand(frame_pointer(), kAtStart)); 222 __ lw(a0, MemOperand(frame_pointer(), kStartIndex));
218 BranchOrBacktrack(on_not_at_start, eq, a0, Operand(zero_reg)); 223 BranchOrBacktrack(on_not_at_start, ne, a0, Operand(zero_reg));
219 // If we did, are we still at the start of the input? 224 // If we did, are we still at the start of the input?
220 __ lw(a1, MemOperand(frame_pointer(), kInputStart)); 225 __ lw(a1, MemOperand(frame_pointer(), kInputStart));
221 __ Addu(a0, end_of_input_address(), Operand(current_input_offset())); 226 __ Addu(a0, end_of_input_address(), Operand(current_input_offset()));
222 BranchOrBacktrack(on_not_at_start, ne, a0, Operand(a1)); 227 BranchOrBacktrack(on_not_at_start, ne, a0, Operand(a1));
223 } 228 }
224 229
225 230
226 void RegExpMacroAssemblerMIPS::CheckCharacterLT(uc16 limit, Label* on_less) { 231 void RegExpMacroAssemblerMIPS::CheckCharacterLT(uc16 limit, Label* on_less) {
227 BranchOrBacktrack(on_less, lt, current_character(), Operand(limit)); 232 BranchOrBacktrack(on_less, lt, current_character(), Operand(limit));
228 } 233 }
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 } 638 }
634 639
635 640
636 void RegExpMacroAssemblerMIPS::Fail() { 641 void RegExpMacroAssemblerMIPS::Fail() {
637 __ li(v0, Operand(FAILURE)); 642 __ li(v0, Operand(FAILURE));
638 __ jmp(&exit_label_); 643 __ jmp(&exit_label_);
639 } 644 }
640 645
641 646
642 Handle<HeapObject> RegExpMacroAssemblerMIPS::GetCode(Handle<String> source) { 647 Handle<HeapObject> RegExpMacroAssemblerMIPS::GetCode(Handle<String> source) {
648 Label return_v0;
643 if (masm_->has_exception()) { 649 if (masm_->has_exception()) {
644 // If the code gets corrupted due to long regular expressions and lack of 650 // If the code gets corrupted due to long regular expressions and lack of
645 // space on trampolines, an internal exception flag is set. If this case 651 // space on trampolines, an internal exception flag is set. If this case
646 // is detected, we will jump into exit sequence right away. 652 // is detected, we will jump into exit sequence right away.
647 __ bind_to(&entry_label_, internal_failure_label_.pos()); 653 __ bind_to(&entry_label_, internal_failure_label_.pos());
648 } else { 654 } else {
649 // Finalize code - write the entry point code now we know how many 655 // Finalize code - write the entry point code now we know how many
650 // registers we need. 656 // registers we need.
651 657
652 // Entry code: 658 // Entry code:
653 __ bind(&entry_label_); 659 __ bind(&entry_label_);
654 660
655 // Tell the system that we have a stack frame. Because the type is MANUAL, 661 // Tell the system that we have a stack frame. Because the type is MANUAL,
656 // no is generated. 662 // no is generated.
657 FrameScope scope(masm_, StackFrame::MANUAL); 663 FrameScope scope(masm_, StackFrame::MANUAL);
658 664
659 // Actually emit code to start a new stack frame. 665 // Actually emit code to start a new stack frame.
660 // Push arguments 666 // Push arguments
661 // Save callee-save registers. 667 // Save callee-save registers.
662 // Start new stack frame. 668 // Start new stack frame.
663 // Store link register in existing stack-cell. 669 // Store link register in existing stack-cell.
664 // Order here should correspond to order of offset constants in header file. 670 // Order here should correspond to order of offset constants in header file.
665 RegList registers_to_retain = s0.bit() | s1.bit() | s2.bit() | 671 RegList registers_to_retain = s0.bit() | s1.bit() | s2.bit() |
666 s3.bit() | s4.bit() | s5.bit() | s6.bit() | s7.bit() | fp.bit(); 672 s3.bit() | s4.bit() | s5.bit() | s6.bit() | s7.bit() | fp.bit();
667 RegList argument_registers = a0.bit() | a1.bit() | a2.bit() | a3.bit(); 673 RegList argument_registers = a0.bit() | a1.bit() | a2.bit() | a3.bit();
668 __ MultiPush(argument_registers | registers_to_retain | ra.bit()); 674 __ MultiPush(argument_registers | registers_to_retain | ra.bit());
669 // Set frame pointer in space for it if this is not a direct call 675 // Set frame pointer in space for it if this is not a direct call
670 // from generated code. 676 // from generated code.
671 __ Addu(frame_pointer(), sp, Operand(4 * kPointerSize)); 677 __ Addu(frame_pointer(), sp, Operand(4 * kPointerSize));
678 __ mov(a0, zero_reg);
679 __ push(a0); // Make room for success counter and initialize it to 0.
672 __ push(a0); // Make room for "position - 1" constant (value irrelevant). 680 __ push(a0); // Make room for "position - 1" constant (value irrelevant).
673 __ push(a0); // Make room for "at start" constant (value irrelevant).
674 681
675 // Check if we have space on the stack for registers. 682 // Check if we have space on the stack for registers.
676 Label stack_limit_hit; 683 Label stack_limit_hit;
677 Label stack_ok; 684 Label stack_ok;
678 685
679 ExternalReference stack_limit = 686 ExternalReference stack_limit =
680 ExternalReference::address_of_stack_limit(masm_->isolate()); 687 ExternalReference::address_of_stack_limit(masm_->isolate());
681 __ li(a0, Operand(stack_limit)); 688 __ li(a0, Operand(stack_limit));
682 __ lw(a0, MemOperand(a0)); 689 __ lw(a0, MemOperand(a0));
683 __ Subu(a0, sp, a0); 690 __ Subu(a0, sp, a0);
684 // Handle it if the stack pointer is already below the stack limit. 691 // Handle it if the stack pointer is already below the stack limit.
685 __ Branch(&stack_limit_hit, le, a0, Operand(zero_reg)); 692 __ Branch(&stack_limit_hit, le, a0, Operand(zero_reg));
686 // Check if there is room for the variable number of registers above 693 // Check if there is room for the variable number of registers above
687 // the stack limit. 694 // the stack limit.
688 __ Branch(&stack_ok, hs, a0, Operand(num_registers_ * kPointerSize)); 695 __ Branch(&stack_ok, hs, a0, Operand(num_registers_ * kPointerSize));
689 // Exit with OutOfMemory exception. There is not enough space on the stack 696 // Exit with OutOfMemory exception. There is not enough space on the stack
690 // for our working registers. 697 // for our working registers.
691 __ li(v0, Operand(EXCEPTION)); 698 __ li(v0, Operand(EXCEPTION));
692 __ jmp(&exit_label_); 699 __ jmp(&return_v0);
693 700
694 __ bind(&stack_limit_hit); 701 __ bind(&stack_limit_hit);
695 CallCheckStackGuardState(a0); 702 CallCheckStackGuardState(a0);
696 // If returned value is non-zero, we exit with the returned value as result. 703 // If returned value is non-zero, we exit with the returned value as result.
697 __ Branch(&exit_label_, ne, v0, Operand(zero_reg)); 704 __ Branch(&return_v0, ne, v0, Operand(zero_reg));
698 705
699 __ bind(&stack_ok); 706 __ bind(&stack_ok);
700 // Allocate space on stack for registers. 707 // Allocate space on stack for registers.
701 __ Subu(sp, sp, Operand(num_registers_ * kPointerSize)); 708 __ Subu(sp, sp, Operand(num_registers_ * kPointerSize));
702 // Load string end. 709 // Load string end.
703 __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 710 __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
704 // Load input start. 711 // Load input start.
705 __ lw(a0, MemOperand(frame_pointer(), kInputStart)); 712 __ lw(a0, MemOperand(frame_pointer(), kInputStart));
706 // Find negative length (offset of start relative to end). 713 // Find negative length (offset of start relative to end).
707 __ Subu(current_input_offset(), a0, end_of_input_address()); 714 __ Subu(current_input_offset(), a0, end_of_input_address());
708 // Set a0 to address of char before start of the input string 715 // Set a0 to address of char before start of the input string
709 // (effectively string position -1). 716 // (effectively string position -1).
710 __ lw(a1, MemOperand(frame_pointer(), kStartIndex)); 717 __ lw(a1, MemOperand(frame_pointer(), kStartIndex));
711 __ Subu(a0, current_input_offset(), Operand(char_size())); 718 __ Subu(a0, current_input_offset(), Operand(char_size()));
712 __ sll(t5, a1, (mode_ == UC16) ? 1 : 0); 719 __ sll(t5, a1, (mode_ == UC16) ? 1 : 0);
713 __ Subu(a0, a0, t5); 720 __ Subu(a0, a0, t5);
714 // Store this value in a local variable, for use when clearing 721 // Store this value in a local variable, for use when clearing
715 // position registers. 722 // position registers.
716 __ sw(a0, MemOperand(frame_pointer(), kInputStartMinusOne)); 723 __ sw(a0, MemOperand(frame_pointer(), kInputStartMinusOne));
717 724
718 // Determine whether the start index is zero, that is at the start of the 725 // Initialize code pointer register
719 // string, and store that value in a local variable. 726 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
720 __ mov(t5, a1);
721 __ li(a1, Operand(1));
722 __ Movn(a1, zero_reg, t5);
723 __ sw(a1, MemOperand(frame_pointer(), kAtStart));
724 727
728 Label load_char_start_regexp, start_regexp;
729 // Load newline if index is at start, previous character otherwise.
730 __ Branch(&load_char_start_regexp, ne, a1, Operand(zero_reg));
731 __ li(current_character(), Operand('\n'));
732 __ jmp(&start_regexp);
733
734 // Global regexp restarts matching here.
735 __ bind(&load_char_start_regexp);
736 // Load previous char as initial value of current character register.
737 LoadCurrentCharacterUnchecked(-1, 1);
738 __ bind(&start_regexp);
739
740 // Initialize on-stack registers.
725 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. 741 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp.
726 // Fill saved registers with initial value = start offset - 1. 742 // Fill saved registers with initial value = start offset - 1.
727 743 if (num_saved_registers_ > 8) {
728 // Address of register 0. 744 // Address of register 0.
729 __ Addu(a1, frame_pointer(), Operand(kRegisterZero)); 745 __ Addu(a1, frame_pointer(), Operand(kRegisterZero));
730 __ li(a2, Operand(num_saved_registers_)); 746 __ li(a2, Operand(num_saved_registers_));
731 Label init_loop; 747 Label init_loop;
732 __ bind(&init_loop); 748 __ bind(&init_loop);
733 __ sw(a0, MemOperand(a1)); 749 __ sw(a0, MemOperand(a1));
734 __ Addu(a1, a1, Operand(-kPointerSize)); 750 __ Addu(a1, a1, Operand(-kPointerSize));
735 __ Subu(a2, a2, Operand(1)); 751 __ Subu(a2, a2, Operand(1));
736 __ Branch(&init_loop, ne, a2, Operand(zero_reg)); 752 __ Branch(&init_loop, ne, a2, Operand(zero_reg));
753 } else {
754 for (int i = 0; i < num_saved_registers_; i++) {
755 __ sw(a0, register_location(i));
756 }
757 }
737 } 758 }
738 759
739 // Initialize backtrack stack pointer. 760 // Initialize backtrack stack pointer.
740 __ lw(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd)); 761 __ lw(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd));
741 // Initialize code pointer register 762
742 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
743 // Load previous char as initial value of current character register.
744 Label at_start;
745 __ lw(a0, MemOperand(frame_pointer(), kAtStart));
746 __ Branch(&at_start, ne, a0, Operand(zero_reg));
747 LoadCurrentCharacterUnchecked(-1, 1); // Load previous char.
748 __ jmp(&start_label_);
749 __ bind(&at_start);
750 __ li(current_character(), Operand('\n'));
751 __ jmp(&start_label_); 763 __ jmp(&start_label_);
752 764
753 765
754 // Exit code: 766 // Exit code:
755 if (success_label_.is_linked()) { 767 if (success_label_.is_linked()) {
756 // Save captures when successful. 768 // Save captures when successful.
757 __ bind(&success_label_); 769 __ bind(&success_label_);
758 if (num_saved_registers_ > 0) { 770 if (num_saved_registers_ > 0) {
759 // Copy captures to output. 771 // Copy captures to output.
760 __ lw(a1, MemOperand(frame_pointer(), kInputStart)); 772 __ lw(a1, MemOperand(frame_pointer(), kInputStart));
761 __ lw(a0, MemOperand(frame_pointer(), kRegisterOutput)); 773 __ lw(a0, MemOperand(frame_pointer(), kRegisterOutput));
762 __ lw(a2, MemOperand(frame_pointer(), kStartIndex)); 774 __ lw(a2, MemOperand(frame_pointer(), kStartIndex));
763 __ Subu(a1, end_of_input_address(), a1); 775 __ Subu(a1, end_of_input_address(), a1);
764 // a1 is length of input in bytes. 776 // a1 is length of input in bytes.
765 if (mode_ == UC16) { 777 if (mode_ == UC16) {
766 __ srl(a1, a1, 1); 778 __ srl(a1, a1, 1);
767 } 779 }
768 // a1 is length of input in characters. 780 // a1 is length of input in characters.
769 __ Addu(a1, a1, Operand(a2)); 781 __ Addu(a1, a1, Operand(a2));
770 // a1 is length of string in characters. 782 // a1 is length of string in characters.
771 783
772 ASSERT_EQ(0, num_saved_registers_ % 2); 784 ASSERT_EQ(0, num_saved_registers_ % 2);
773 // Always an even number of capture registers. This allows us to 785 // Always an even number of capture registers. This allows us to
774 // unroll the loop once to add an operation between a load of a register 786 // unroll the loop once to add an operation between a load of a register
775 // and the following use of that register. 787 // and the following use of that register.
776 for (int i = 0; i < num_saved_registers_; i += 2) { 788 for (int i = 0; i < num_saved_registers_; i += 2) {
777 __ lw(a2, register_location(i)); 789 __ lw(a2, register_location(i));
778 __ lw(a3, register_location(i + 1)); 790 __ lw(a3, register_location(i + 1));
791 if (global()) {
792 // Keep capture start in a4 for the zero-length check later.
793 __ mov(t7, a2);
794 }
779 if (mode_ == UC16) { 795 if (mode_ == UC16) {
780 __ sra(a2, a2, 1); 796 __ sra(a2, a2, 1);
781 __ Addu(a2, a2, a1); 797 __ Addu(a2, a2, a1);
782 __ sra(a3, a3, 1); 798 __ sra(a3, a3, 1);
783 __ Addu(a3, a3, a1); 799 __ Addu(a3, a3, a1);
784 } else { 800 } else {
785 __ Addu(a2, a1, Operand(a2)); 801 __ Addu(a2, a1, Operand(a2));
786 __ Addu(a3, a1, Operand(a3)); 802 __ Addu(a3, a1, Operand(a3));
787 } 803 }
788 __ sw(a2, MemOperand(a0)); 804 __ sw(a2, MemOperand(a0));
789 __ Addu(a0, a0, kPointerSize); 805 __ Addu(a0, a0, kPointerSize);
790 __ sw(a3, MemOperand(a0)); 806 __ sw(a3, MemOperand(a0));
791 __ Addu(a0, a0, kPointerSize); 807 __ Addu(a0, a0, kPointerSize);
792 } 808 }
793 } 809 }
794 __ li(v0, Operand(SUCCESS)); 810
811 if (global()) {
812 // Restart matching if the regular expression is flagged as global.
813 __ lw(a0, MemOperand(frame_pointer(), kSuccessfulCaptures));
814 __ lw(a1, MemOperand(frame_pointer(), kNumOutputRegisters));
815 __ lw(a2, MemOperand(frame_pointer(), kRegisterOutput));
816 // Increment success counter.
817 __ Addu(a0, a0, 1);
818 __ sw(a0, MemOperand(frame_pointer(), kSuccessfulCaptures));
819 // Capture results have been stored, so the number of remaining global
820 // output registers is reduced by the number of stored captures.
821 __ Subu(a1, a1, num_saved_registers_);
822 // Check whether we have enough room for another set of capture results.
823 __ mov(v0, a0);
824 __ Branch(&return_v0, lt, a1, Operand(num_saved_registers_));
825
826 __ sw(a1, MemOperand(frame_pointer(), kNumOutputRegisters));
827 // Advance the location for output.
828 __ Addu(a2, a2, num_saved_registers_ * kPointerSize);
829 __ sw(a2, MemOperand(frame_pointer(), kRegisterOutput));
830
831 // Prepare a0 to initialize registers with its value in the next run.
832 __ lw(a0, MemOperand(frame_pointer(), kInputStartMinusOne));
833 // Special case for zero-length matches.
834 // t7: capture start index
835 // Not a zero-length match, restart.
836 __ Branch(&load_char_start_regexp, ne, current_input_offset(), Operand(t 7));
837 // Offset from the end is zero if we already reached the end.
838 __ Branch(&exit_label_, eq, current_input_offset(), Operand(zero_reg));
839 // Advance current position after a zero-length match.
840 __ Addu(current_input_offset(),
841 current_input_offset(),
842 Operand((mode_ == UC16) ? 2 : 1));
843 __ Branch(&load_char_start_regexp);
844 } else {
845 __ li(v0, Operand(SUCCESS));
846 }
795 } 847 }
796 // Exit and return v0. 848 // Exit and return v0.
797 __ bind(&exit_label_); 849 __ bind(&exit_label_);
850 if (global()) {
851 __ lw(v0, MemOperand(frame_pointer(), kSuccessfulCaptures));
852 }
853
854 __ bind(&return_v0);
798 // Skip sp past regexp registers and local variables.. 855 // Skip sp past regexp registers and local variables..
799 __ mov(sp, frame_pointer()); 856 __ mov(sp, frame_pointer());
800 // Restore registers s0..s7 and return (restoring ra to pc). 857 // Restore registers s0..s7 and return (restoring ra to pc).
801 __ MultiPop(registers_to_retain | ra.bit()); 858 __ MultiPop(registers_to_retain | ra.bit());
802 __ Ret(); 859 __ Ret();
803 860
804 // Backtrack code (branch target for conditional backtracks). 861 // Backtrack code (branch target for conditional backtracks).
805 if (backtrack_label_.is_linked()) { 862 if (backtrack_label_.is_linked()) {
806 __ bind(&backtrack_label_); 863 __ bind(&backtrack_label_);
807 Backtrack(); 864 Backtrack();
808 } 865 }
809 866
810 Label exit_with_exception; 867 Label exit_with_exception;
811 868
812 // Preempt-code. 869 // Preempt-code.
813 if (check_preempt_label_.is_linked()) { 870 if (check_preempt_label_.is_linked()) {
814 SafeCallTarget(&check_preempt_label_); 871 SafeCallTarget(&check_preempt_label_);
815 // Put regexp engine registers on stack. 872 // Put regexp engine registers on stack.
816 RegList regexp_registers_to_retain = current_input_offset().bit() | 873 RegList regexp_registers_to_retain = current_input_offset().bit() |
817 current_character().bit() | backtrack_stackpointer().bit(); 874 current_character().bit() | backtrack_stackpointer().bit();
818 __ MultiPush(regexp_registers_to_retain); 875 __ MultiPush(regexp_registers_to_retain);
819 CallCheckStackGuardState(a0); 876 CallCheckStackGuardState(a0);
820 __ MultiPop(regexp_registers_to_retain); 877 __ MultiPop(regexp_registers_to_retain);
821 // If returning non-zero, we should end execution with the given 878 // If returning non-zero, we should end execution with the given
822 // result as return value. 879 // result as return value.
823 __ Branch(&exit_label_, ne, v0, Operand(zero_reg)); 880 __ Branch(&return_v0, ne, v0, Operand(zero_reg));
824 881
825 // String might have moved: Reload end of string from frame. 882 // String might have moved: Reload end of string from frame.
826 __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 883 __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
827 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); 884 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
828 SafeReturn(); 885 SafeReturn();
829 } 886 }
830 887
831 // Backtrack stack overflow code. 888 // Backtrack stack overflow code.
832 if (stack_overflow_label_.is_linked()) { 889 if (stack_overflow_label_.is_linked()) {
833 SafeCallTarget(&stack_overflow_label_); 890 SafeCallTarget(&stack_overflow_label_);
(...skipping 23 matching lines...) Expand all
857 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); 914 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
858 __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 915 __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
859 SafeReturn(); 916 SafeReturn();
860 } 917 }
861 918
862 if (exit_with_exception.is_linked()) { 919 if (exit_with_exception.is_linked()) {
863 // If any of the code above needed to exit with an exception. 920 // If any of the code above needed to exit with an exception.
864 __ bind(&exit_with_exception); 921 __ bind(&exit_with_exception);
865 // Exit with Result EXCEPTION(-1) to signal thrown exception. 922 // Exit with Result EXCEPTION(-1) to signal thrown exception.
866 __ li(v0, Operand(EXCEPTION)); 923 __ li(v0, Operand(EXCEPTION));
867 __ jmp(&exit_label_); 924 __ jmp(&return_v0);
868 } 925 }
869 } 926 }
870 927
871 CodeDesc code_desc; 928 CodeDesc code_desc;
872 masm_->GetCode(&code_desc); 929 masm_->GetCode(&code_desc);
873 Handle<Code> code = FACTORY->NewCode(code_desc, 930 Handle<Code> code = FACTORY->NewCode(code_desc,
874 Code::ComputeFlags(Code::REGEXP), 931 Code::ComputeFlags(Code::REGEXP),
875 masm_->CodeObject()); 932 masm_->CodeObject());
876 LOG(Isolate::Current(), RegExpCodeCreateEvent(*code, *source)); 933 LOG(Isolate::Current(), RegExpCodeCreateEvent(*code, *source));
877 return Handle<HeapObject>::cast(code); 934 return Handle<HeapObject>::cast(code);
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1005 } 1062 }
1006 1063
1007 1064
1008 void RegExpMacroAssemblerMIPS::SetRegister(int register_index, int to) { 1065 void RegExpMacroAssemblerMIPS::SetRegister(int register_index, int to) {
1009 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! 1066 ASSERT(register_index >= num_saved_registers_); // Reserved for positions!
1010 __ li(a0, Operand(to)); 1067 __ li(a0, Operand(to));
1011 __ sw(a0, register_location(register_index)); 1068 __ sw(a0, register_location(register_index));
1012 } 1069 }
1013 1070
1014 1071
1015 void RegExpMacroAssemblerMIPS::Succeed() { 1072 bool RegExpMacroAssemblerMIPS::Succeed() {
1016 __ jmp(&success_label_); 1073 __ jmp(&success_label_);
1074 return global();
1017 } 1075 }
1018 1076
1019 1077
1020 void RegExpMacroAssemblerMIPS::WriteCurrentPositionToRegister(int reg, 1078 void RegExpMacroAssemblerMIPS::WriteCurrentPositionToRegister(int reg,
1021 int cp_offset) { 1079 int cp_offset) {
1022 if (cp_offset == 0) { 1080 if (cp_offset == 0) {
1023 __ sw(current_input_offset(), register_location(reg)); 1081 __ sw(current_input_offset(), register_location(reg));
1024 } else { 1082 } else {
1025 __ Addu(a0, current_input_offset(), Operand(cp_offset * char_size())); 1083 __ Addu(a0, current_input_offset(), Operand(cp_offset * char_size()));
1026 __ sw(a0, register_location(reg)); 1084 __ sw(a0, register_location(reg));
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
1273 __ lw(sp, MemOperand(sp, 16)); 1331 __ lw(sp, MemOperand(sp, 16));
1274 } 1332 }
1275 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); 1333 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
1276 } 1334 }
1277 1335
1278 1336
1279 void RegExpMacroAssemblerMIPS::LoadCurrentCharacterUnchecked(int cp_offset, 1337 void RegExpMacroAssemblerMIPS::LoadCurrentCharacterUnchecked(int cp_offset,
1280 int characters) { 1338 int characters) {
1281 Register offset = current_input_offset(); 1339 Register offset = current_input_offset();
1282 if (cp_offset != 0) { 1340 if (cp_offset != 0) {
1283 __ Addu(a0, current_input_offset(), Operand(cp_offset * char_size())); 1341 // t7 is not being used to store the capture start index at this point.
1284 offset = a0; 1342 __ Addu(t7, current_input_offset(), Operand(cp_offset * char_size()));
1343 offset = t7;
1285 } 1344 }
1286 // We assume that we cannot do unaligned loads on MIPS, so this function 1345 // We assume that we cannot do unaligned loads on MIPS, so this function
1287 // must only be used to load a single character at a time. 1346 // must only be used to load a single character at a time.
1288 ASSERT(characters == 1); 1347 ASSERT(characters == 1);
1289 __ Addu(t5, end_of_input_address(), Operand(offset)); 1348 __ Addu(t5, end_of_input_address(), Operand(offset));
1290 if (mode_ == ASCII) { 1349 if (mode_ == ASCII) {
1291 __ lbu(current_character(), MemOperand(t5, 0)); 1350 __ lbu(current_character(), MemOperand(t5, 0));
1292 } else { 1351 } else {
1293 ASSERT(mode_ == UC16); 1352 ASSERT(mode_ == UC16);
1294 __ lhu(current_character(), MemOperand(t5, 0)); 1353 __ lhu(current_character(), MemOperand(t5, 0));
(...skipping 18 matching lines...) Expand all
1313 } 1372 }
1314 1373
1315 1374
1316 #undef __ 1375 #undef __
1317 1376
1318 #endif // V8_INTERPRETED_REGEXP 1377 #endif // V8_INTERPRETED_REGEXP
1319 1378
1320 }} // namespace v8::internal 1379 }} // namespace v8::internal
1321 1380
1322 #endif // V8_TARGET_ARCH_MIPS 1381 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/regexp-macro-assembler-mips.h ('k') | src/mips/simulator-mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698