Index: src/regexp/arm/regexp-macro-assembler-arm.cc |
diff --git a/src/regexp/arm/regexp-macro-assembler-arm.cc b/src/regexp/arm/regexp-macro-assembler-arm.cc |
index d296d90e7dffecf9e8ba7b9fef78d694c9848c23..422a4eec9c645eb1f943559228bc0f7ccff9ec71 100644 |
--- a/src/regexp/arm/regexp-macro-assembler-arm.cc |
+++ b/src/regexp/arm/regexp-macro-assembler-arm.cc |
@@ -176,29 +176,26 @@ void RegExpMacroAssemblerARM::CheckCharacterGT(uc16 limit, Label* on_greater) { |
void RegExpMacroAssemblerARM::CheckAtStart(Label* on_at_start) { |
- Label not_at_start; |
- // Did we start the match at the start of the string at all? |
- __ ldr(r0, MemOperand(frame_pointer(), kStartIndex)); |
- __ cmp(r0, Operand::Zero()); |
- BranchOrBacktrack(ne, ¬_at_start); |
- |
- // If we did, are we still at the start of the input? |
+ __ add(r0, end_of_input_address(), current_input_offset()); |
+ __ ldr(r1, MemOperand(frame_pointer(), kStartIndex)); |
+ for (int i = 0; i < char_size(); i++) { |
+ __ add(r0, r0, r1); |
+ } |
__ ldr(r1, MemOperand(frame_pointer(), kInputStart)); |
- __ add(r0, end_of_input_address(), Operand(current_input_offset())); |
__ cmp(r0, r1); |
BranchOrBacktrack(eq, on_at_start); |
- __ bind(¬_at_start); |
} |
-void RegExpMacroAssemblerARM::CheckNotAtStart(Label* on_not_at_start) { |
- // Did we start the match at the start of the string at all? |
- __ ldr(r0, MemOperand(frame_pointer(), kStartIndex)); |
- __ cmp(r0, Operand::Zero()); |
- BranchOrBacktrack(ne, on_not_at_start); |
- // If we did, are we still at the start of the input? |
+void RegExpMacroAssemblerARM::CheckNotAtStart(int cp_offset, |
+ Label* on_not_at_start) { |
+ __ add(r0, end_of_input_address(), current_input_offset()); |
+ __ add(r0, r0, Operand(cp_offset * char_size())); |
+ __ ldr(r1, MemOperand(frame_pointer(), kStartIndex)); |
+ for (int i = 0; i < char_size(); i++) { |
+ __ add(r0, r0, r1); |
+ } |
__ ldr(r1, MemOperand(frame_pointer(), kInputStart)); |
- __ add(r0, end_of_input_address(), Operand(current_input_offset())); |
__ cmp(r0, r1); |
BranchOrBacktrack(ne, on_not_at_start); |
} |
@@ -220,20 +217,31 @@ void RegExpMacroAssemblerARM::CheckGreedyLoop(Label* on_equal) { |
void RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase( |
- int start_reg, |
- Label* on_no_match) { |
+ int start_reg, bool read_backward, Label* on_no_match) { |
Label fallthrough; |
__ ldr(r0, register_location(start_reg)); // Index of start of capture |
__ ldr(r1, register_location(start_reg + 1)); // Index of end of capture |
__ sub(r1, r1, r0, SetCC); // Length of capture. |
- // If length is zero, either the capture is empty or it is not participating. |
- // In either case succeed immediately. |
- __ b(eq, &fallthrough); |
+ // The length of the capture can only be negative if the end of the |
+ // capture is not yet recorded. If the length is zero, the capture is |
+ // either empty or uncaptured. In either of those cases, succeed. |
+ __ b(le, &fallthrough); |
// Check that there are enough characters left in the input. |
- __ cmn(r1, Operand(current_input_offset())); |
- BranchOrBacktrack(gt, on_no_match); |
+ if (read_backward) { |
+ __ add(r2, end_of_input_address(), current_input_offset()); |
+ __ ldr(r3, MemOperand(frame_pointer(), kStartIndex)); |
+ for (int i = 0; i < char_size(); i++) { |
+ __ add(r2, r2, r3); |
+ } |
+ __ ldr(r3, MemOperand(frame_pointer(), kInputStart)); |
+ __ cmp(r2, r3); |
+ BranchOrBacktrack(lt, on_no_match); |
+ } else { |
+ __ cmn(r1, Operand(current_input_offset())); |
+ BranchOrBacktrack(gt, on_no_match); |
+ } |
if (mode_ == LATIN1) { |
Label success; |
@@ -242,9 +250,12 @@ void RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase( |
// r0 - offset of start of capture |
// r1 - length of capture |
- __ add(r0, r0, Operand(end_of_input_address())); |
- __ add(r2, end_of_input_address(), Operand(current_input_offset())); |
- __ add(r1, r0, Operand(r1)); |
+ __ add(r0, r0, end_of_input_address()); |
+ __ add(r2, end_of_input_address(), current_input_offset()); |
+ if (read_backward) { |
+ __ sub(r2, r2, r1); // Offset by length when matching backwards. |
+ } |
+ __ add(r1, r0, r1); |
// r0 - Address of start of capture. |
// r1 - Address of end of capture |
@@ -283,6 +294,12 @@ void RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase( |
__ bind(&success); |
// Compute new value of character position after the matched part. |
__ sub(current_input_offset(), r2, end_of_input_address()); |
+ if (read_backward) { |
+ __ ldr(r0, register_location(start_reg)); // Index of start of capture |
+ __ ldr(r1, register_location(start_reg + 1)); // Index of end of capture |
+ __ add(current_input_offset(), current_input_offset(), r0); |
+ __ sub(current_input_offset(), current_input_offset(), r1); |
+ } |
} else { |
DCHECK(mode_ == UC16); |
int argument_count = 4; |
@@ -305,7 +322,10 @@ void RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase( |
// Save length in callee-save register for use on return. |
__ mov(r4, Operand(r1)); |
// Address of current input position. |
- __ add(r1, current_input_offset(), Operand(end_of_input_address())); |
+ __ add(r1, current_input_offset(), end_of_input_address()); |
+ if (read_backward) { |
+ __ sub(r1, r1, r4); |
+ } |
// Isolate. |
__ mov(r3, Operand(ExternalReference::isolate_address(isolate()))); |
@@ -319,17 +339,22 @@ void RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase( |
// Check if function returned non-zero for success or zero for failure. |
__ cmp(r0, Operand::Zero()); |
BranchOrBacktrack(eq, on_no_match); |
- // On success, increment position by length of capture. |
- __ add(current_input_offset(), current_input_offset(), Operand(r4)); |
+ |
+ // On success, advance position by length of capture. |
+ if (read_backward) { |
+ __ sub(current_input_offset(), current_input_offset(), r4); |
+ } else { |
+ __ add(current_input_offset(), current_input_offset(), r4); |
+ } |
} |
__ bind(&fallthrough); |
} |
-void RegExpMacroAssemblerARM::CheckNotBackReference( |
- int start_reg, |
- Label* on_no_match) { |
+void RegExpMacroAssemblerARM::CheckNotBackReference(int start_reg, |
+ bool read_backward, |
+ Label* on_no_match) { |
Label fallthrough; |
Label success; |
@@ -337,17 +362,35 @@ void RegExpMacroAssemblerARM::CheckNotBackReference( |
__ ldr(r0, register_location(start_reg)); |
__ ldr(r1, register_location(start_reg + 1)); |
__ sub(r1, r1, r0, SetCC); // Length to check. |
- // Succeed on empty capture (including no capture). |
- __ b(eq, &fallthrough); |
+ |
+ // The length of the capture can only be negative if the end of the |
+ // capture is not yet recorded. If the length is zero, the capture is |
+ // either empty or uncaptured. In either of those cases, succeed. |
+ __ b(le, &fallthrough); |
// Check that there are enough characters left in the input. |
- __ cmn(r1, Operand(current_input_offset())); |
- BranchOrBacktrack(gt, on_no_match); |
+ if (read_backward) { |
+ __ add(r2, end_of_input_address(), current_input_offset()); |
+ __ ldr(r3, MemOperand(frame_pointer(), kStartIndex)); |
+ for (int i = 0; i < char_size(); i++) { |
+ __ add(r2, r2, r3); |
+ } |
+ __ ldr(r3, MemOperand(frame_pointer(), kInputStart)); |
+ __ cmp(r2, r3); |
+ BranchOrBacktrack(lt, on_no_match); |
+ } else { |
+ __ cmn(r1, Operand(current_input_offset())); |
+ BranchOrBacktrack(gt, on_no_match); |
+ } |
- // Compute pointers to match string and capture string |
- __ add(r0, r0, Operand(end_of_input_address())); |
- __ add(r2, end_of_input_address(), Operand(current_input_offset())); |
- __ add(r1, r1, Operand(r0)); |
+ // r0 - offset of start of capture |
+ // r1 - length of capture |
+ __ add(r0, r0, end_of_input_address()); |
+ __ add(r2, end_of_input_address(), current_input_offset()); |
+ if (read_backward) { |
+ __ sub(r2, r2, r1); // Offset by length when matching backwards. |
+ } |
+ __ add(r1, r0, r1); |
Label loop; |
__ bind(&loop); |
@@ -366,6 +409,13 @@ void RegExpMacroAssemblerARM::CheckNotBackReference( |
// Move current character position to position after match. |
__ sub(current_input_offset(), r2, end_of_input_address()); |
+ if (read_backward) { |
+ __ ldr(r0, register_location(start_reg)); // Index of start of capture |
+ __ ldr(r1, register_location(start_reg + 1)); // Index of end of capture |
+ __ add(current_input_offset(), current_input_offset(), r0); |
+ __ sub(current_input_offset(), current_input_offset(), r1); |
+ } |
+ |
__ bind(&fallthrough); |
} |
@@ -892,10 +942,13 @@ void RegExpMacroAssemblerARM::LoadCurrentCharacter(int cp_offset, |
Label* on_end_of_input, |
bool check_bounds, |
int characters) { |
- DCHECK(cp_offset >= -1); // ^ and \b can look behind one character. |
DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works) |
if (check_bounds) { |
- CheckPosition(cp_offset + characters - 1, on_end_of_input); |
+ if (cp_offset >= 0) { |
+ CheckPosition(cp_offset + characters - 1, on_end_of_input); |
+ } else { |
+ CheckPosition(cp_offset, on_end_of_input); |
+ } |
} |
LoadCurrentCharacterUnchecked(cp_offset, characters); |
} |
@@ -1069,8 +1122,20 @@ MemOperand RegExpMacroAssemblerARM::register_location(int register_index) { |
void RegExpMacroAssemblerARM::CheckPosition(int cp_offset, |
Label* on_outside_input) { |
- __ cmp(current_input_offset(), Operand(-cp_offset * char_size())); |
- BranchOrBacktrack(ge, on_outside_input); |
+ if (cp_offset >= 0) { |
+ __ cmp(current_input_offset(), Operand(-cp_offset * char_size())); |
+ BranchOrBacktrack(ge, on_outside_input); |
+ } else { |
+ __ add(r0, end_of_input_address(), current_input_offset()); |
+ __ add(r0, r0, Operand(cp_offset * char_size())); |
+ __ ldr(r1, MemOperand(frame_pointer(), kStartIndex)); |
+ for (int i = 0; i < char_size(); i++) { |
+ __ add(r0, r0, r1); |
+ } |
+ __ ldr(r1, MemOperand(frame_pointer(), kInputStart)); |
+ __ cmp(r0, r1); |
+ BranchOrBacktrack(lt, on_outside_input); |
+ } |
} |