Remove unnecessary code for non-zero-length global regexps.

Also fixing a bug in the arm implementation.

BUG=
TEST=regexp-global.js

Review URL: https://chromiumcodereview.appspot.com/10383280

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11704 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
yangguo@chromium.org 2012-06-04 08:49:17 +00:00
parent 98c37e1f4c
commit 85e3fba8a3
7 changed files with 74 additions and 46 deletions

View File

@ -796,7 +796,7 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
for (int i = 0; i < num_saved_registers_; i += 2) {
__ ldr(r2, register_location(i));
__ ldr(r3, register_location(i + 1));
if (global()) {
if (i == 0 && global_with_zero_length_check()) {
// Keep capture start in r4 for the zero-length check later.
__ mov(r4, r2);
}
@ -834,18 +834,22 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
// Prepare r0 to initialize registers with its value in the next run.
__ ldr(r0, MemOperand(frame_pointer(), kInputStartMinusOne));
// Special case for zero-length matches.
// r4: capture start index
__ cmp(current_input_offset(), r4);
// Not a zero-length match, restart.
__ b(ne, &load_char_start_regexp);
// Offset from the end is zero if we already reached the end.
__ cmp(current_input_offset(), Operand(0));
__ b(eq, &exit_label_);
// Advance current position after a zero-length match.
__ add(current_input_offset(),
current_input_offset(),
Operand((mode_ == UC16) ? 2 : 1));
if (global_with_zero_length_check()) {
// Special case for zero-length matches.
// r4: capture start index
__ cmp(current_input_offset(), r4);
// Not a zero-length match, restart.
__ b(ne, &load_char_start_regexp);
// Offset from the end is zero if we already reached the end.
__ cmp(current_input_offset(), Operand(0));
__ b(eq, &exit_label_);
// Advance current position after a zero-length match.
__ add(current_input_offset(),
current_input_offset(),
Operand((mode_ == UC16) ? 2 : 1));
}
__ b(&load_char_start_regexp);
} else {
__ mov(r0, Operand(SUCCESS));

View File

@ -857,7 +857,7 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
}
for (int i = 0; i < num_saved_registers_; i++) {
__ mov(eax, register_location(i));
if (i == 0 && global()) {
if (i == 0 && global_with_zero_length_check()) {
// Keep capture start in edx for the zero-length check later.
__ mov(edx, eax);
}
@ -890,20 +890,23 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
// Prepare eax to initialize registers with its value in the next run.
__ mov(eax, Operand(ebp, kInputStartMinusOne));
// Special case for zero-length matches.
// edx: capture start index
__ cmp(edi, edx);
// Not a zero-length match, restart.
__ j(not_equal, &load_char_start_regexp);
// edi (offset from the end) is zero if we already reached the end.
__ test(edi, edi);
__ j(zero, &exit_label_, Label::kNear);
// Advance current position after a zero-length match.
if (mode_ == UC16) {
__ add(edi, Immediate(2));
} else {
__ inc(edi);
if (global_with_zero_length_check()) {
// Special case for zero-length matches.
// edx: capture start index
__ cmp(edi, edx);
// Not a zero-length match, restart.
__ j(not_equal, &load_char_start_regexp);
// edi (offset from the end) is zero if we already reached the end.
__ test(edi, edi);
__ j(zero, &exit_label_, Label::kNear);
// Advance current position after a zero-length match.
if (mode_ == UC16) {
__ add(edi, Immediate(2));
} else {
__ inc(edi);
}
}
__ jmp(&load_char_start_regexp);
} else {
__ mov(eax, Immediate(SUCCESS));

View File

@ -5927,7 +5927,12 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(
macro_assembler.SetCurrentPositionFromEnd(max_length);
}
macro_assembler.set_global(is_global);
if (is_global) {
macro_assembler.set_global_mode(
(data->tree->min_match() > 0)
? RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK
: RegExpMacroAssembler::GLOBAL);
}
return compiler.Assemble(&macro_assembler,
node,

View File

@ -37,7 +37,7 @@ namespace internal {
RegExpMacroAssembler::RegExpMacroAssembler()
: slow_safe_compiler_(false),
global_(false) {
global_mode_(NOT_GLOBAL) {
}

View File

@ -184,14 +184,18 @@ class RegExpMacroAssembler {
void set_slow_safe(bool ssc) { slow_safe_compiler_ = ssc; }
bool slow_safe() { return slow_safe_compiler_; }
enum GlobalMode { NOT_GLOBAL, GLOBAL, GLOBAL_NO_ZERO_LENGTH_CHECK };
// Set whether the regular expression has the global flag. Exiting due to
// a failure in a global regexp may still mean success overall.
void set_global(bool global) { global_ = global; }
bool global() { return global_; }
inline void set_global_mode(GlobalMode mode) { global_mode_ = mode; }
inline bool global() { return global_mode_ != NOT_GLOBAL; }
inline bool global_with_zero_length_check() {
return global_mode_ == GLOBAL;
}
private:
bool slow_safe_compiler_;
bool global_;
bool global_mode_;
};

View File

@ -926,7 +926,7 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
}
for (int i = 0; i < num_saved_registers_; i++) {
__ movq(rax, register_location(i));
if (i == 0 && global()) {
if (i == 0 && global_with_zero_length_check()) {
// Keep capture start in rdx for the zero-length check later.
__ movq(rdx, rax);
}
@ -958,20 +958,23 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
// Prepare rax to initialize registers with its value in the next run.
__ movq(rax, Operand(rbp, kInputStartMinusOne));
// Special case for zero-length matches.
// rdx: capture start index
__ cmpq(rdi, rdx);
// Not a zero-length match, restart.
__ j(not_equal, &load_char_start_regexp);
// rdi (offset from the end) is zero if we already reached the end.
__ testq(rdi, rdi);
__ j(zero, &exit_label_, Label::kNear);
// Advance current position after a zero-length match.
if (mode_ == UC16) {
__ addq(rdi, Immediate(2));
} else {
__ incq(rdi);
if (global_with_zero_length_check()) {
// Special case for zero-length matches.
// rdx: capture start index
__ cmpq(rdi, rdx);
// Not a zero-length match, restart.
__ j(not_equal, &load_char_start_regexp);
// rdi (offset from the end) is zero if we already reached the end.
__ testq(rdi, rdi);
__ j(zero, &exit_label_, Label::kNear);
// Advance current position after a zero-length match.
if (mode_ == UC16) {
__ addq(rdi, Immediate(2));
} else {
__ incq(rdi);
}
}
__ jmp(&load_char_start_regexp);
} else {
__ movq(rax, Immediate(SUCCESS));

View File

@ -130,3 +130,12 @@ assertEquals("4, 2!", str);
var str = "Beasts of England, beasts of Ireland";
str = str.replace(/(.*)/g, function(match) { return '~'; });
assertEquals("~~", str);
// Test zero-length matches that have non-zero-length sub-captures that do not
// start at the match start position.
str = "up up up up";
str = str.replace(/\b(?=u(p))/g, function(match, capture) {
return capture.length;
});
assertEquals("1up 1up 1up 1up", str);