Commit e852c49e authored by mbrandy's avatar mbrandy Committed by Commit bot

PPC: Experimental support for RegExp lookbehind.

Port 906903ac

R=yangguo@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=v8:4545
LOG=N

Review URL: https://codereview.chromium.org/1454783002

Cr-Commit-Position: refs/heads/master@{#32056}
parent acf3baf4
...@@ -60,7 +60,7 @@ namespace internal { ...@@ -60,7 +60,7 @@ namespace internal {
* - fp[-32] void* input_string (location of a handle containing the string). * - fp[-32] void* input_string (location of a handle containing the string).
* - fp[-36] success counter (only for global regexps to count matches). * - fp[-36] success counter (only for global regexps to count matches).
* - fp[-40] Offset of location before start of input (effectively character * - fp[-40] Offset of location before start of input (effectively character
* position -1). Used to initialize capture registers to a * string start - 1). Used to initialize capture registers to a
* non-position. * non-position.
* - fp[-44] At start (if 1, we are starting at the start of the * - fp[-44] At start (if 1, we are starting at the start of the
* string, otherwise 0) * string, otherwise 0)
...@@ -189,30 +189,18 @@ void RegExpMacroAssemblerPPC::CheckCharacterGT(uc16 limit, Label* on_greater) { ...@@ -189,30 +189,18 @@ void RegExpMacroAssemblerPPC::CheckCharacterGT(uc16 limit, Label* on_greater) {
void RegExpMacroAssemblerPPC::CheckAtStart(Label* on_at_start) { void RegExpMacroAssemblerPPC::CheckAtStart(Label* on_at_start) {
Label not_at_start; __ LoadP(r4, MemOperand(frame_pointer(), kStringStartMinusOne));
// Did we start the match at the start of the string at all? __ addi(r3, current_input_offset(), Operand(-char_size()));
__ LoadP(r3, MemOperand(frame_pointer(), kStartIndex)); __ cmp(r3, r4);
__ cmpi(r3, Operand::Zero());
BranchOrBacktrack(ne, &not_at_start);
// If we did, are we still at the start of the input?
__ LoadP(r4, MemOperand(frame_pointer(), kInputStart));
__ mr(r0, current_input_offset());
__ add(r3, end_of_input_address(), r0);
__ cmp(r4, r3);
BranchOrBacktrack(eq, on_at_start); BranchOrBacktrack(eq, on_at_start);
__ bind(&not_at_start);
} }
void RegExpMacroAssemblerPPC::CheckNotAtStart(Label* on_not_at_start) { void RegExpMacroAssemblerPPC::CheckNotAtStart(int cp_offset,
// Did we start the match at the start of the string at all? Label* on_not_at_start) {
__ LoadP(r3, MemOperand(frame_pointer(), kStartIndex)); __ LoadP(r4, MemOperand(frame_pointer(), kStringStartMinusOne));
__ cmpi(r3, Operand::Zero()); __ addi(r3, current_input_offset(),
BranchOrBacktrack(ne, on_not_at_start); Operand(-char_size() + cp_offset * char_size()));
// If we did, are we still at the start of the input?
__ LoadP(r4, MemOperand(frame_pointer(), kInputStart));
__ add(r3, end_of_input_address(), current_input_offset());
__ cmp(r3, r4); __ cmp(r3, r4);
BranchOrBacktrack(ne, on_not_at_start); BranchOrBacktrack(ne, on_not_at_start);
} }
...@@ -238,20 +226,27 @@ void RegExpMacroAssemblerPPC::CheckGreedyLoop(Label* on_equal) { ...@@ -238,20 +226,27 @@ void RegExpMacroAssemblerPPC::CheckGreedyLoop(Label* on_equal) {
void RegExpMacroAssemblerPPC::CheckNotBackReferenceIgnoreCase( void RegExpMacroAssemblerPPC::CheckNotBackReferenceIgnoreCase(
int start_reg, Label* on_no_match) { int start_reg, bool read_backward, Label* on_no_match) {
Label fallthrough; Label fallthrough;
__ LoadP(r3, register_location(start_reg), r0); // Index of start of capture __ LoadP(r3, register_location(start_reg), r0); // Index of start of capture
__ LoadP(r4, register_location(start_reg + 1), r0); // Index of end __ LoadP(r4, register_location(start_reg + 1), r0); // Index of end
__ sub(r4, r4, r3, LeaveOE, SetRC); // Length of capture. __ sub(r4, r4, r3, LeaveOE, SetRC); // Length of capture.
// If length is zero, either the capture is empty or it is not participating. // At this point, the capture registers are either both set or both cleared.
// In either case succeed immediately. // If the capture length is zero, then the capture is either empty or cleared.
// Fall through in both cases.
__ beq(&fallthrough, cr0); __ beq(&fallthrough, cr0);
// Check that there are enough characters left in the input. // Check that there are enough characters left in the input.
if (read_backward) {
__ LoadP(r6, MemOperand(frame_pointer(), kStringStartMinusOne));
__ add(r6, r6, r4);
__ cmp(current_input_offset(), r6);
BranchOrBacktrack(le, on_no_match);
} else {
__ add(r0, r4, current_input_offset(), LeaveOE, SetRC); __ add(r0, r4, current_input_offset(), LeaveOE, SetRC);
// __ cmn(r1, Operand(current_input_offset()));
BranchOrBacktrack(gt, on_no_match, cr0); BranchOrBacktrack(gt, on_no_match, cr0);
}
if (mode_ == LATIN1) { if (mode_ == LATIN1) {
Label success; Label success;
...@@ -262,6 +257,9 @@ void RegExpMacroAssemblerPPC::CheckNotBackReferenceIgnoreCase( ...@@ -262,6 +257,9 @@ void RegExpMacroAssemblerPPC::CheckNotBackReferenceIgnoreCase(
// r4 - length of capture // r4 - length of capture
__ add(r3, r3, end_of_input_address()); __ add(r3, r3, end_of_input_address());
__ add(r5, end_of_input_address(), current_input_offset()); __ add(r5, end_of_input_address(), current_input_offset());
if (read_backward) {
__ sub(r5, r5, r4); // Offset by length when matching backwards.
}
__ add(r4, r3, r4); __ add(r4, r3, r4);
// r3 - Address of start of capture. // r3 - Address of start of capture.
...@@ -303,6 +301,13 @@ void RegExpMacroAssemblerPPC::CheckNotBackReferenceIgnoreCase( ...@@ -303,6 +301,13 @@ void RegExpMacroAssemblerPPC::CheckNotBackReferenceIgnoreCase(
__ bind(&success); __ bind(&success);
// Compute new value of character position after the matched part. // Compute new value of character position after the matched part.
__ sub(current_input_offset(), r5, end_of_input_address()); __ sub(current_input_offset(), r5, end_of_input_address());
if (read_backward) {
__ LoadP(r3, register_location(start_reg)); // Index of start of capture
__ LoadP(r4,
register_location(start_reg + 1)); // Index of end of capture
__ add(current_input_offset(), current_input_offset(), r3);
__ sub(current_input_offset(), current_input_offset(), r4);
}
} else { } else {
DCHECK(mode_ == UC16); DCHECK(mode_ == UC16);
int argument_count = 4; int argument_count = 4;
...@@ -326,6 +331,9 @@ void RegExpMacroAssemblerPPC::CheckNotBackReferenceIgnoreCase( ...@@ -326,6 +331,9 @@ void RegExpMacroAssemblerPPC::CheckNotBackReferenceIgnoreCase(
__ mr(r25, r4); __ mr(r25, r4);
// Address of current input position. // Address of current input position.
__ add(r4, current_input_offset(), end_of_input_address()); __ add(r4, current_input_offset(), end_of_input_address());
if (read_backward) {
__ sub(r4, r4, r25);
}
// Isolate. // Isolate.
__ mov(r6, Operand(ExternalReference::isolate_address(isolate()))); __ mov(r6, Operand(ExternalReference::isolate_address(isolate())));
...@@ -339,15 +347,21 @@ void RegExpMacroAssemblerPPC::CheckNotBackReferenceIgnoreCase( ...@@ -339,15 +347,21 @@ void RegExpMacroAssemblerPPC::CheckNotBackReferenceIgnoreCase(
// Check if function returned non-zero for success or zero for failure. // Check if function returned non-zero for success or zero for failure.
__ cmpi(r3, Operand::Zero()); __ cmpi(r3, Operand::Zero());
BranchOrBacktrack(eq, on_no_match); BranchOrBacktrack(eq, on_no_match);
// On success, increment position by length of capture.
// On success, advance position by length of capture.
if (read_backward) {
__ sub(current_input_offset(), current_input_offset(), r25);
} else {
__ add(current_input_offset(), current_input_offset(), r25); __ add(current_input_offset(), current_input_offset(), r25);
} }
}
__ bind(&fallthrough); __ bind(&fallthrough);
} }
void RegExpMacroAssemblerPPC::CheckNotBackReference(int start_reg, void RegExpMacroAssemblerPPC::CheckNotBackReference(int start_reg,
bool read_backward,
Label* on_no_match) { Label* on_no_match) {
Label fallthrough; Label fallthrough;
Label success; Label success;
...@@ -356,16 +370,30 @@ void RegExpMacroAssemblerPPC::CheckNotBackReference(int start_reg, ...@@ -356,16 +370,30 @@ void RegExpMacroAssemblerPPC::CheckNotBackReference(int start_reg,
__ LoadP(r3, register_location(start_reg), r0); __ LoadP(r3, register_location(start_reg), r0);
__ LoadP(r4, register_location(start_reg + 1), r0); __ LoadP(r4, register_location(start_reg + 1), r0);
__ sub(r4, r4, r3, LeaveOE, SetRC); // Length to check. __ sub(r4, r4, r3, LeaveOE, SetRC); // Length to check.
// Succeed on empty capture (including no capture).
// At this point, the capture registers are either both set or both cleared.
// If the capture length is zero, then the capture is either empty or cleared.
// Fall through in both cases.
__ beq(&fallthrough, cr0); __ beq(&fallthrough, cr0);
// Check that there are enough characters left in the input. // Check that there are enough characters left in the input.
if (read_backward) {
__ LoadP(r6, MemOperand(frame_pointer(), kStringStartMinusOne));
__ add(r6, r6, r4);
__ cmp(current_input_offset(), r6);
BranchOrBacktrack(lt, on_no_match);
} else {
__ add(r0, r4, current_input_offset(), LeaveOE, SetRC); __ add(r0, r4, current_input_offset(), LeaveOE, SetRC);
BranchOrBacktrack(gt, on_no_match, cr0); BranchOrBacktrack(gt, on_no_match, cr0);
}
// Compute pointers to match string and capture string // r3 - offset of start of capture
// r4 - length of capture
__ add(r3, r3, end_of_input_address()); __ add(r3, r3, end_of_input_address());
__ add(r5, end_of_input_address(), current_input_offset()); __ add(r5, end_of_input_address(), current_input_offset());
if (read_backward) {
__ sub(r5, r5, r4); // Offset by length when matching backwards.
}
__ add(r4, r4, r3); __ add(r4, r4, r3);
Label loop; Label loop;
...@@ -389,6 +417,13 @@ void RegExpMacroAssemblerPPC::CheckNotBackReference(int start_reg, ...@@ -389,6 +417,13 @@ void RegExpMacroAssemblerPPC::CheckNotBackReference(int start_reg,
// Move current character position to position after match. // Move current character position to position after match.
__ sub(current_input_offset(), r5, end_of_input_address()); __ sub(current_input_offset(), r5, end_of_input_address());
if (read_backward) {
__ LoadP(r3, register_location(start_reg)); // Index of start of capture
__ LoadP(r4, register_location(start_reg + 1)); // Index of end of capture
__ add(current_input_offset(), current_input_offset(), r3);
__ sub(current_input_offset(), current_input_offset(), r4);
}
__ bind(&fallthrough); __ bind(&fallthrough);
} }
...@@ -639,7 +674,7 @@ Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) { ...@@ -639,7 +674,7 @@ Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) {
__ addi(frame_pointer(), sp, Operand(8 * kPointerSize)); __ addi(frame_pointer(), sp, Operand(8 * kPointerSize));
__ li(r3, Operand::Zero()); __ li(r3, Operand::Zero());
__ push(r3); // Make room for success counter and initialize it to 0. __ push(r3); // Make room for success counter and initialize it to 0.
__ push(r3); // Make room for "position - 1" constant (value is irrelevant) __ push(r3); // Make room for "string start - 1" constant.
// Check if we have space on the stack for registers. // Check if we have space on the stack for registers.
Label stack_limit_hit; Label stack_limit_hit;
Label stack_ok; Label stack_ok;
...@@ -688,7 +723,7 @@ Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) { ...@@ -688,7 +723,7 @@ Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) {
} }
// Store this value in a local variable, for use when clearing // Store this value in a local variable, for use when clearing
// position registers. // position registers.
__ StoreP(r3, MemOperand(frame_pointer(), kInputStartMinusOne)); __ StoreP(r3, MemOperand(frame_pointer(), kStringStartMinusOne));
// Initialize code pointer register // Initialize code pointer register
__ mov(code_pointer(), Operand(masm_->CodeObject())); __ mov(code_pointer(), Operand(masm_->CodeObject()));
...@@ -797,7 +832,7 @@ Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) { ...@@ -797,7 +832,7 @@ Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) {
__ StoreP(r5, MemOperand(frame_pointer(), kRegisterOutput)); __ StoreP(r5, MemOperand(frame_pointer(), kRegisterOutput));
// Prepare r3 to initialize registers with its value in the next run. // Prepare r3 to initialize registers with its value in the next run.
__ LoadP(r3, MemOperand(frame_pointer(), kInputStartMinusOne)); __ LoadP(r3, MemOperand(frame_pointer(), kStringStartMinusOne));
if (global_with_zero_length_check()) { if (global_with_zero_length_check()) {
// Special case for zero-length matches. // Special case for zero-length matches.
...@@ -936,10 +971,13 @@ void RegExpMacroAssemblerPPC::LoadCurrentCharacter(int cp_offset, ...@@ -936,10 +971,13 @@ void RegExpMacroAssemblerPPC::LoadCurrentCharacter(int cp_offset,
Label* on_end_of_input, Label* on_end_of_input,
bool check_bounds, bool check_bounds,
int characters) { int characters) {
DCHECK(cp_offset >= -1); // ^ and \b can look behind one character.
DCHECK(cp_offset < (1 << 30)); // Be sane! (And ensure negation works) DCHECK(cp_offset < (1 << 30)); // Be sane! (And ensure negation works)
if (check_bounds) { if (check_bounds) {
if (cp_offset >= 0) {
CheckPosition(cp_offset + characters - 1, on_end_of_input); CheckPosition(cp_offset + characters - 1, on_end_of_input);
} else {
CheckPosition(cp_offset, on_end_of_input);
}
} }
LoadCurrentCharacterUnchecked(cp_offset, characters); LoadCurrentCharacterUnchecked(cp_offset, characters);
} }
...@@ -1028,7 +1066,7 @@ void RegExpMacroAssemblerPPC::WriteCurrentPositionToRegister(int reg, ...@@ -1028,7 +1066,7 @@ void RegExpMacroAssemblerPPC::WriteCurrentPositionToRegister(int reg,
void RegExpMacroAssemblerPPC::ClearRegisters(int reg_from, int reg_to) { void RegExpMacroAssemblerPPC::ClearRegisters(int reg_from, int reg_to) {
DCHECK(reg_from <= reg_to); DCHECK(reg_from <= reg_to);
__ LoadP(r3, MemOperand(frame_pointer(), kInputStartMinusOne)); __ LoadP(r3, MemOperand(frame_pointer(), kStringStartMinusOne));
for (int reg = reg_from; reg <= reg_to; reg++) { for (int reg = reg_from; reg <= reg_to; reg++) {
__ StoreP(r3, register_location(reg), r0); __ StoreP(r3, register_location(reg), r0);
} }
...@@ -1132,8 +1170,15 @@ MemOperand RegExpMacroAssemblerPPC::register_location(int register_index) { ...@@ -1132,8 +1170,15 @@ MemOperand RegExpMacroAssemblerPPC::register_location(int register_index) {
void RegExpMacroAssemblerPPC::CheckPosition(int cp_offset, void RegExpMacroAssemblerPPC::CheckPosition(int cp_offset,
Label* on_outside_input) { Label* on_outside_input) {
if (cp_offset >= 0) {
__ Cmpi(current_input_offset(), Operand(-cp_offset * char_size()), r0); __ Cmpi(current_input_offset(), Operand(-cp_offset * char_size()), r0);
BranchOrBacktrack(ge, on_outside_input); BranchOrBacktrack(ge, on_outside_input);
} else {
__ LoadP(r4, MemOperand(frame_pointer(), kStringStartMinusOne));
__ addi(r3, current_input_offset(), Operand(cp_offset * char_size()));
__ cmp(r3, r4);
BranchOrBacktrack(le, on_outside_input);
}
} }
......
...@@ -34,9 +34,11 @@ class RegExpMacroAssemblerPPC : public NativeRegExpMacroAssembler { ...@@ -34,9 +34,11 @@ class RegExpMacroAssemblerPPC : public NativeRegExpMacroAssembler {
// A "greedy loop" is a loop that is both greedy and with a simple // A "greedy loop" is a loop that is both greedy and with a simple
// body. It has a particularly simple implementation. // body. It has a particularly simple implementation.
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position); virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
virtual void CheckNotAtStart(Label* on_not_at_start); virtual void CheckNotAtStart(int cp_offset, Label* on_not_at_start);
virtual void CheckNotBackReference(int start_reg, Label* on_no_match); virtual void CheckNotBackReference(int start_reg, bool read_backward,
Label* on_no_match);
virtual void CheckNotBackReferenceIgnoreCase(int start_reg, virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
bool read_backward,
Label* on_no_match); Label* on_no_match);
virtual void CheckNotCharacter(unsigned c, Label* on_not_equal); virtual void CheckNotCharacter(unsigned c, Label* on_not_equal);
virtual void CheckNotCharacterAfterAnd(unsigned c, unsigned mask, virtual void CheckNotCharacterAfterAnd(unsigned c, unsigned mask,
...@@ -112,9 +114,9 @@ class RegExpMacroAssemblerPPC : public NativeRegExpMacroAssembler { ...@@ -112,9 +114,9 @@ class RegExpMacroAssemblerPPC : public NativeRegExpMacroAssembler {
// When adding local variables remember to push space for them in // When adding local variables remember to push space for them in
// the frame in GetCode. // the frame in GetCode.
static const int kSuccessfulCaptures = kInputString - kPointerSize; static const int kSuccessfulCaptures = kInputString - kPointerSize;
static const int kInputStartMinusOne = kSuccessfulCaptures - kPointerSize; static const int kStringStartMinusOne = kSuccessfulCaptures - kPointerSize;
// First register address. Following registers are below it on the stack. // First register address. Following registers are below it on the stack.
static const int kRegisterZero = kInputStartMinusOne - kPointerSize; static const int kRegisterZero = kStringStartMinusOne - kPointerSize;
// Initial size of code buffer. // Initial size of code buffer.
static const size_t kRegExpCodeSize = 1024; static const size_t kRegExpCodeSize = 1024;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment