Chromium Code Reviews| 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 |