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:
parent
98c37e1f4c
commit
85e3fba8a3
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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(¯o_assembler,
|
||||
node,
|
||||
|
@ -37,7 +37,7 @@ namespace internal {
|
||||
|
||||
RegExpMacroAssembler::RegExpMacroAssembler()
|
||||
: slow_safe_compiler_(false),
|
||||
global_(false) {
|
||||
global_mode_(NOT_GLOBAL) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user