| Index: src/regexp/arm64/regexp-macro-assembler-arm64.cc
|
| diff --git a/src/regexp/arm64/regexp-macro-assembler-arm64.cc b/src/regexp/arm64/regexp-macro-assembler-arm64.cc
|
| index d440879e26f87f00c74dcbf8e8ea0e4a52440fd7..3c20956e6fbdb1d53384c3364c7ff9528d0dff12 100644
|
| --- a/src/regexp/arm64/regexp-macro-assembler-arm64.cc
|
| +++ b/src/regexp/arm64/regexp-macro-assembler-arm64.cc
|
| @@ -210,22 +210,22 @@ void RegExpMacroAssemblerARM64::CheckCharacterGT(uc16 limit,
|
|
|
|
|
| void RegExpMacroAssemblerARM64::CheckAtStart(Label* on_at_start) {
|
| - Label not_at_start;
|
| - // Did we start the match at the start of the input string?
|
| - CompareAndBranchOrBacktrack(start_offset(), 0, ne, ¬_at_start);
|
| - // If we did, are we still at the start of the input string?
|
| __ Add(x10, input_end(), Operand(current_input_offset(), SXTW));
|
| + for (int i = 0; i < char_size(); i++) {
|
| + __ Add(x10, x10, Operand(start_offset(), SXTW));
|
| + }
|
| __ Cmp(x10, input_start());
|
| BranchOrBacktrack(eq, on_at_start);
|
| - __ Bind(¬_at_start);
|
| }
|
|
|
|
|
| -void RegExpMacroAssemblerARM64::CheckNotAtStart(Label* on_not_at_start) {
|
| - // Did we start the match at the start of the input string?
|
| - CompareAndBranchOrBacktrack(start_offset(), 0, ne, on_not_at_start);
|
| - // If we did, are we still at the start of the input string?
|
| +void RegExpMacroAssemblerARM64::CheckNotAtStart(int cp_offset,
|
| + Label* on_not_at_start) {
|
| __ Add(x10, input_end(), Operand(current_input_offset(), SXTW));
|
| + __ Add(x10, x10, cp_offset * char_size());
|
| + for (int i = 0; i < char_size(); i++) {
|
| + __ Add(x10, x10, Operand(start_offset(), SXTW));
|
| + }
|
| __ Cmp(x10, input_start());
|
| BranchOrBacktrack(ne, on_not_at_start);
|
| }
|
| @@ -277,9 +277,9 @@ void RegExpMacroAssemblerARM64::CheckGreedyLoop(Label* on_equal) {
|
| BranchOrBacktrack(eq, on_equal);
|
| }
|
|
|
| +
|
| void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase(
|
| - int start_reg,
|
| - Label* on_no_match) {
|
| + int start_reg, bool read_backward, Label* on_no_match) {
|
| Label fallthrough;
|
|
|
| Register capture_start_offset = w10;
|
| @@ -297,12 +297,24 @@ void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase(
|
| __ Ldp(w11, capture_start_offset, capture_location(start_reg, x10));
|
| }
|
| __ Sub(capture_length, w11, capture_start_offset); // Length to check.
|
| - // Succeed on empty capture (including no capture).
|
| - __ Cbz(capture_length, &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.
|
| + __ CompareAndBranch(capture_length, Operand(0), le, &fallthrough);
|
|
|
| // Check that there are enough characters left in the input.
|
| - __ Cmn(capture_length, current_input_offset());
|
| - BranchOrBacktrack(gt, on_no_match);
|
| + if (read_backward) {
|
| + __ Add(x12, input_end(), Operand(current_input_offset(), SXTW));
|
| + for (int i = 0; i < char_size(); i++) {
|
| + __ Add(x12, x12, Operand(start_offset(), SXTW));
|
| + }
|
| + __ Cmp(x12, input_start());
|
| + BranchOrBacktrack(lt, on_no_match);
|
| + } else {
|
| + __ Cmn(capture_length, current_input_offset());
|
| + BranchOrBacktrack(gt, on_no_match);
|
| + }
|
|
|
| if (mode_ == LATIN1) {
|
| Label success;
|
| @@ -322,6 +334,11 @@ void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase(
|
| __ Add(current_position_address,
|
| input_end(),
|
| Operand(current_input_offset(), SXTW));
|
| + if (read_backward) {
|
| + // Offset by length when matching backwards.
|
| + __ Sub(current_position_address, current_position_address,
|
| + Operand(capture_length, SXTW));
|
| + }
|
|
|
| Label loop;
|
| __ Bind(&loop);
|
| @@ -361,6 +378,10 @@ void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase(
|
| // The current input offset should be <= 0, and fit in a W register.
|
| __ Check(le, kOffsetOutOfRange);
|
| }
|
| + if (read_backward) {
|
| + __ Sub(current_input_offset(), current_input_offset(),
|
| + Operand(capture_length, SXTW));
|
| + }
|
| } else {
|
| DCHECK(mode_ == UC16);
|
| int argument_count = 4;
|
| @@ -383,6 +404,9 @@ void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase(
|
| __ Mov(w2, capture_length);
|
| // Address of current input position.
|
| __ Add(x1, input_end(), Operand(current_input_offset(), SXTW));
|
| + if (read_backward) {
|
| + __ Sub(x1, x1, Operand(capture_length, SXTW));
|
| + }
|
| // Isolate.
|
| __ Mov(x3, ExternalReference::isolate_address(isolate()));
|
|
|
| @@ -400,16 +424,20 @@ void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase(
|
| __ PopCPURegList(cached_registers);
|
| BranchOrBacktrack(eq, on_no_match);
|
|
|
| - // On success, increment position by length of capture.
|
| - __ Add(current_input_offset(), current_input_offset(), capture_length);
|
| + // On success, advance position by length of capture.
|
| + if (read_backward) {
|
| + __ Sub(current_input_offset(), current_input_offset(), capture_length);
|
| + } else {
|
| + __ Add(current_input_offset(), current_input_offset(), capture_length);
|
| + }
|
| }
|
|
|
| __ Bind(&fallthrough);
|
| }
|
|
|
| -void RegExpMacroAssemblerARM64::CheckNotBackReference(
|
| - int start_reg,
|
| - Label* on_no_match) {
|
| +void RegExpMacroAssemblerARM64::CheckNotBackReference(int start_reg,
|
| + bool read_backward,
|
| + Label* on_no_match) {
|
| Label fallthrough;
|
|
|
| Register capture_start_address = x12;
|
| @@ -426,12 +454,23 @@ void RegExpMacroAssemblerARM64::CheckNotBackReference(
|
| __ Ldp(w11, w10, capture_location(start_reg, x10));
|
| }
|
| __ Sub(capture_length, w11, w10); // Length to check.
|
| - // Succeed on empty capture (including no capture).
|
| - __ Cbz(capture_length, &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.
|
| + __ CompareAndBranch(capture_length, Operand(0), le, &fallthrough);
|
|
|
| // Check that there are enough characters left in the input.
|
| - __ Cmn(capture_length, current_input_offset());
|
| - BranchOrBacktrack(gt, on_no_match);
|
| + if (read_backward) {
|
| + __ Add(x12, input_end(), Operand(current_input_offset(), SXTW));
|
| + for (int i = 0; i < char_size(); i++) {
|
| + __ Add(x12, x12, Operand(start_offset(), SXTW));
|
| + }
|
| + __ Cmp(x12, input_start());
|
| + BranchOrBacktrack(lt, on_no_match);
|
| + } else {
|
| + __ Cmn(capture_length, current_input_offset());
|
| + BranchOrBacktrack(gt, on_no_match);
|
| + }
|
|
|
| // Compute pointers to match string and capture string
|
| __ Add(capture_start_address, input_end(), Operand(w10, SXTW));
|
| @@ -441,6 +480,11 @@ void RegExpMacroAssemblerARM64::CheckNotBackReference(
|
| __ Add(current_position_address,
|
| input_end(),
|
| Operand(current_input_offset(), SXTW));
|
| + if (read_backward) {
|
| + // Offset by length when matching backwards.
|
| + __ Sub(current_position_address, current_position_address,
|
| + Operand(capture_length, SXTW));
|
| + }
|
|
|
| Label loop;
|
| __ Bind(&loop);
|
| @@ -459,6 +503,11 @@ void RegExpMacroAssemblerARM64::CheckNotBackReference(
|
|
|
| // Move current character position to position after match.
|
| __ Sub(current_input_offset().X(), current_position_address, input_end());
|
| + if (read_backward) {
|
| + __ Sub(current_input_offset(), current_input_offset(),
|
| + Operand(capture_length, SXTW));
|
| + }
|
| +
|
| if (masm_->emit_debug_code()) {
|
| __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW));
|
| __ Ccmp(current_input_offset(), 0, NoFlag, eq);
|
| @@ -1081,11 +1130,14 @@ void RegExpMacroAssemblerARM64::LoadCurrentCharacter(int cp_offset,
|
| int characters) {
|
| // TODO(pielan): Make sure long strings are caught before this, and not
|
| // just asserted in debug mode.
|
| - DCHECK(cp_offset >= -1); // ^ and \b can look behind one character.
|
| // Be sane! (And ensure that an int32_t can be used to index the string)
|
| DCHECK(cp_offset < (1<<30));
|
| 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);
|
| }
|
| @@ -1301,10 +1353,18 @@ int RegExpMacroAssemblerARM64::CheckStackGuardState(
|
|
|
| void RegExpMacroAssemblerARM64::CheckPosition(int cp_offset,
|
| Label* on_outside_input) {
|
| - CompareAndBranchOrBacktrack(current_input_offset(),
|
| - -cp_offset * char_size(),
|
| - ge,
|
| - on_outside_input);
|
| + if (cp_offset >= 0) {
|
| + CompareAndBranchOrBacktrack(current_input_offset(),
|
| + -cp_offset * char_size(), ge, on_outside_input);
|
| + } else {
|
| + __ Add(x12, input_end(), Operand(current_input_offset(), SXTW));
|
| + __ Add(x12, x12, cp_offset * char_size());
|
| + for (int i = 0; i < char_size(); i++) {
|
| + __ Add(x12, x12, Operand(start_offset(), SXTW));
|
| + }
|
| + __ Cmp(x12, input_start());
|
| + BranchOrBacktrack(lt, on_outside_input);
|
| + }
|
| }
|
|
|
|
|
|
|