Revert revision 5657.
TBR: erik.corry Review URL: http://codereview.chromium.org/3812012 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5658 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f80da64d36
commit
00e23b719d
@ -142,6 +142,7 @@ int RegExpMacroAssemblerARM::stack_limit_slack() {
|
||||
|
||||
void RegExpMacroAssemblerARM::AdvanceCurrentPosition(int by) {
|
||||
if (by != 0) {
|
||||
Label inside_string;
|
||||
__ add(current_input_offset(),
|
||||
current_input_offset(), Operand(by * char_size()));
|
||||
}
|
||||
@ -926,19 +927,6 @@ void RegExpMacroAssemblerARM::ReadStackPointerFromRegister(int reg) {
|
||||
}
|
||||
|
||||
|
||||
void RegExpMacroAssemblerARM::SetCurrentPositionFromEnd(int by) {
|
||||
NearLabel after_position;
|
||||
__ cmp(current_input_offset(), Operand(by * char_size()));
|
||||
__ b(hs, &after_position);
|
||||
__ mov(current_input_offset(), Operand(by * char_size()));
|
||||
// On RegExp code entry (where this operation is used), the character before
|
||||
// the current position is expected to be already loaded.
|
||||
// We have advenced the position, so it's safe to read backwards.
|
||||
LoadCurrentCharacterUnchecked(-1, 1);
|
||||
__ bind(&after_position);
|
||||
}
|
||||
|
||||
|
||||
void RegExpMacroAssemblerARM::SetRegister(int register_index, int to) {
|
||||
ASSERT(register_index >= num_saved_registers_); // Reserved for positions!
|
||||
__ mov(r0, Operand(to));
|
||||
|
@ -100,7 +100,6 @@ class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
|
||||
StackCheckFlag check_stack_limit);
|
||||
virtual void ReadCurrentPositionFromRegister(int reg);
|
||||
virtual void ReadStackPointerFromRegister(int reg);
|
||||
virtual void SetCurrentPositionFromEnd(int by);
|
||||
virtual void SetRegister(int register_index, int to);
|
||||
virtual void Succeed();
|
||||
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
|
||||
|
49
src/ast.cc
49
src/ast.cc
@ -398,70 +398,39 @@ Interval RegExpQuantifier::CaptureRegisters() {
|
||||
}
|
||||
|
||||
|
||||
bool RegExpAssertion::IsAnchoredAtStart() {
|
||||
bool RegExpAssertion::IsAnchored() {
|
||||
return type() == RegExpAssertion::START_OF_INPUT;
|
||||
}
|
||||
|
||||
|
||||
bool RegExpAssertion::IsAnchoredAtEnd() {
|
||||
return type() == RegExpAssertion::END_OF_INPUT;
|
||||
}
|
||||
|
||||
|
||||
bool RegExpAlternative::IsAnchoredAtStart() {
|
||||
bool RegExpAlternative::IsAnchored() {
|
||||
ZoneList<RegExpTree*>* nodes = this->nodes();
|
||||
for (int i = 0; i < nodes->length(); i++) {
|
||||
RegExpTree* node = nodes->at(i);
|
||||
if (node->IsAnchoredAtStart()) { return true; }
|
||||
if (node->IsAnchored()) { return true; }
|
||||
if (node->max_match() > 0) { return false; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool RegExpAlternative::IsAnchoredAtEnd() {
|
||||
ZoneList<RegExpTree*>* nodes = this->nodes();
|
||||
for (int i = nodes->length() - 1; i >= 0; i--) {
|
||||
RegExpTree* node = nodes->at(i);
|
||||
if (node->IsAnchoredAtEnd()) { return true; }
|
||||
if (node->max_match() > 0) { return false; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool RegExpDisjunction::IsAnchoredAtStart() {
|
||||
bool RegExpDisjunction::IsAnchored() {
|
||||
ZoneList<RegExpTree*>* alternatives = this->alternatives();
|
||||
for (int i = 0; i < alternatives->length(); i++) {
|
||||
if (!alternatives->at(i)->IsAnchoredAtStart())
|
||||
if (!alternatives->at(i)->IsAnchored())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool RegExpDisjunction::IsAnchoredAtEnd() {
|
||||
ZoneList<RegExpTree*>* alternatives = this->alternatives();
|
||||
for (int i = 0; i < alternatives->length(); i++) {
|
||||
if (!alternatives->at(i)->IsAnchoredAtEnd())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
bool RegExpLookahead::IsAnchored() {
|
||||
return is_positive() && body()->IsAnchored();
|
||||
}
|
||||
|
||||
|
||||
bool RegExpLookahead::IsAnchoredAtStart() {
|
||||
return is_positive() && body()->IsAnchoredAtStart();
|
||||
}
|
||||
|
||||
|
||||
bool RegExpCapture::IsAnchoredAtStart() {
|
||||
return body()->IsAnchoredAtStart();
|
||||
}
|
||||
|
||||
|
||||
bool RegExpCapture::IsAnchoredAtEnd() {
|
||||
return body()->IsAnchoredAtEnd();
|
||||
bool RegExpCapture::IsAnchored() {
|
||||
return body()->IsAnchored();
|
||||
}
|
||||
|
||||
|
||||
|
17
src/ast.h
17
src/ast.h
@ -1523,8 +1523,7 @@ class RegExpTree: public ZoneObject {
|
||||
virtual RegExpNode* ToNode(RegExpCompiler* compiler,
|
||||
RegExpNode* on_success) = 0;
|
||||
virtual bool IsTextElement() { return false; }
|
||||
virtual bool IsAnchoredAtStart() { return false; }
|
||||
virtual bool IsAnchoredAtEnd() { return false; }
|
||||
virtual bool IsAnchored() { return false; }
|
||||
virtual int min_match() = 0;
|
||||
virtual int max_match() = 0;
|
||||
// Returns the interval of registers used for captures within this
|
||||
@ -1549,8 +1548,7 @@ class RegExpDisjunction: public RegExpTree {
|
||||
virtual RegExpDisjunction* AsDisjunction();
|
||||
virtual Interval CaptureRegisters();
|
||||
virtual bool IsDisjunction();
|
||||
virtual bool IsAnchoredAtStart();
|
||||
virtual bool IsAnchoredAtEnd();
|
||||
virtual bool IsAnchored();
|
||||
virtual int min_match() { return min_match_; }
|
||||
virtual int max_match() { return max_match_; }
|
||||
ZoneList<RegExpTree*>* alternatives() { return alternatives_; }
|
||||
@ -1570,8 +1568,7 @@ class RegExpAlternative: public RegExpTree {
|
||||
virtual RegExpAlternative* AsAlternative();
|
||||
virtual Interval CaptureRegisters();
|
||||
virtual bool IsAlternative();
|
||||
virtual bool IsAnchoredAtStart();
|
||||
virtual bool IsAnchoredAtEnd();
|
||||
virtual bool IsAnchored();
|
||||
virtual int min_match() { return min_match_; }
|
||||
virtual int max_match() { return max_match_; }
|
||||
ZoneList<RegExpTree*>* nodes() { return nodes_; }
|
||||
@ -1598,8 +1595,7 @@ class RegExpAssertion: public RegExpTree {
|
||||
RegExpNode* on_success);
|
||||
virtual RegExpAssertion* AsAssertion();
|
||||
virtual bool IsAssertion();
|
||||
virtual bool IsAnchoredAtStart();
|
||||
virtual bool IsAnchoredAtEnd();
|
||||
virtual bool IsAnchored();
|
||||
virtual int min_match() { return 0; }
|
||||
virtual int max_match() { return 0; }
|
||||
Type type() { return type_; }
|
||||
@ -1772,8 +1768,7 @@ class RegExpCapture: public RegExpTree {
|
||||
RegExpCompiler* compiler,
|
||||
RegExpNode* on_success);
|
||||
virtual RegExpCapture* AsCapture();
|
||||
virtual bool IsAnchoredAtStart();
|
||||
virtual bool IsAnchoredAtEnd();
|
||||
virtual bool IsAnchored();
|
||||
virtual Interval CaptureRegisters();
|
||||
virtual bool IsCapture();
|
||||
virtual int min_match() { return body_->min_match(); }
|
||||
@ -1805,7 +1800,7 @@ class RegExpLookahead: public RegExpTree {
|
||||
virtual RegExpLookahead* AsLookahead();
|
||||
virtual Interval CaptureRegisters();
|
||||
virtual bool IsLookahead();
|
||||
virtual bool IsAnchoredAtStart();
|
||||
virtual bool IsAnchored();
|
||||
virtual int min_match() { return 0; }
|
||||
virtual int max_match() { return 0; }
|
||||
RegExpTree* body() { return body_; }
|
||||
|
@ -88,8 +88,7 @@ V(CHECK_REGISTER_EQ_POS, 43, 8) /* bc8 reg_idx24 addr32 */ \
|
||||
V(CHECK_AT_START, 44, 8) /* bc8 pad24 addr32 */ \
|
||||
V(CHECK_NOT_AT_START, 45, 8) /* bc8 pad24 addr32 */ \
|
||||
V(CHECK_GREEDY, 46, 8) /* bc8 pad24 addr32 */ \
|
||||
V(ADVANCE_CP_AND_GOTO, 47, 8) /* bc8 offset24 addr32 */ \
|
||||
V(SET_CURRENT_POSITION_FROM_END, 48, 4) /* bc8 idx24 */
|
||||
V(ADVANCE_CP_AND_GOTO, 47, 8) /* bc8 offset24 addr32 */
|
||||
|
||||
#define DECLARE_BYTECODES(name, code, length) \
|
||||
static const int BC_##name = code;
|
||||
|
@ -133,6 +133,7 @@ int RegExpMacroAssemblerIA32::stack_limit_slack() {
|
||||
|
||||
void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) {
|
||||
if (by != 0) {
|
||||
Label inside_string;
|
||||
__ add(Operand(edi), Immediate(by * char_size()));
|
||||
}
|
||||
}
|
||||
@ -963,17 +964,6 @@ void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) {
|
||||
__ add(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
|
||||
}
|
||||
|
||||
void RegExpMacroAssemblerIA32::SetCurrentPositionFromEnd(int by) {
|
||||
NearLabel after_position;
|
||||
__ cmp(edi, -by * char_size());
|
||||
__ j(above_equal, &after_position);
|
||||
__ mov(edi, -by * char_size());
|
||||
// On RegExp code entry (where this operation is used), the character before
|
||||
// the current position is expected to be already loaded.
|
||||
// We have advenced the position, so it's safe to read backwards.
|
||||
LoadCurrentCharacterUnchecked(-1, 1);
|
||||
__ bind(&after_position);
|
||||
}
|
||||
|
||||
void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) {
|
||||
ASSERT(register_index >= num_saved_registers_); // Reserved for positions!
|
||||
|
@ -98,7 +98,6 @@ class RegExpMacroAssemblerIA32: public NativeRegExpMacroAssembler {
|
||||
StackCheckFlag check_stack_limit);
|
||||
virtual void ReadCurrentPositionFromRegister(int reg);
|
||||
virtual void ReadStackPointerFromRegister(int reg);
|
||||
virtual void SetCurrentPositionFromEnd(int by);
|
||||
virtual void SetRegister(int register_index, int to);
|
||||
virtual void Succeed();
|
||||
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
|
||||
|
@ -607,15 +607,6 @@ static bool RawMatch(const byte* code_base,
|
||||
pc = code_base + Load32Aligned(pc + 4);
|
||||
}
|
||||
break;
|
||||
BYTECODE(SET_CURRENT_POSITION_FROM_END) {
|
||||
int by = static_cast<uint32_t>(insn) >> BYTECODE_SHIFT;
|
||||
if (subject.length() - current > by) {
|
||||
current = subject.length() - by;
|
||||
current_char = subject[current - 1];
|
||||
}
|
||||
pc += BC_SET_CURRENT_POSITION_FROM_END_LENGTH;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -5180,10 +5180,7 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(RegExpCompileData* data,
|
||||
&compiler,
|
||||
compiler.accept());
|
||||
RegExpNode* node = captured_body;
|
||||
bool is_end_anchored = data->tree->IsAnchoredAtEnd();
|
||||
bool is_start_anchored = data->tree->IsAnchoredAtStart();
|
||||
int max_length = data->tree->max_match();
|
||||
if (!is_start_anchored) {
|
||||
if (!data->tree->IsAnchored()) {
|
||||
// Add a .*? at the beginning, outside the body capture, unless
|
||||
// this expression is anchored at the beginning.
|
||||
RegExpNode* loop_node =
|
||||
@ -5239,15 +5236,6 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(RegExpCompileData* data,
|
||||
RegExpMacroAssemblerIrregexp macro_assembler(codes);
|
||||
#endif // V8_INTERPRETED_REGEXP
|
||||
|
||||
// Inserted here, instead of in Assembler, because it depends on information
|
||||
// in the AST that isn't replicated in the Node structure.
|
||||
static const int kMaxBacksearchLimit = 1024;
|
||||
if (is_end_anchored &&
|
||||
!is_start_anchored &&
|
||||
max_length < kMaxBacksearchLimit) {
|
||||
macro_assembler.SetCurrentPositionFromEnd(max_length);
|
||||
}
|
||||
|
||||
return compiler.Assemble(¯o_assembler,
|
||||
node,
|
||||
data->capture_count,
|
||||
|
@ -145,12 +145,6 @@ void RegExpMacroAssemblerIrregexp::ReadStackPointerFromRegister(
|
||||
}
|
||||
|
||||
|
||||
void RegExpMacroAssemblerIrregexp::SetCurrentPositionFromEnd(int by) {
|
||||
ASSERT(is_uint24(by));
|
||||
Emit(BC_SET_CURRENT_POSITION_FROM_END, by);
|
||||
}
|
||||
|
||||
|
||||
void RegExpMacroAssemblerIrregexp::SetRegister(int register_index, int to) {
|
||||
ASSERT(register_index >= 0);
|
||||
ASSERT(register_index <= kMaxRegister);
|
||||
|
@ -65,7 +65,6 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
|
||||
virtual void PushRegister(int register_index,
|
||||
StackCheckFlag check_stack_limit);
|
||||
virtual void AdvanceRegister(int reg, int by); // r[reg] += by.
|
||||
virtual void SetCurrentPositionFromEnd(int by);
|
||||
virtual void SetRegister(int register_index, int to);
|
||||
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
|
||||
virtual void ClearRegisters(int reg_from, int reg_to);
|
||||
|
@ -136,12 +136,6 @@ void RegExpMacroAssemblerTracer::AdvanceRegister(int reg, int by) {
|
||||
}
|
||||
|
||||
|
||||
void RegExpMacroAssemblerTracer::SetCurrentPositionFromEnd(int by) {
|
||||
PrintF(" SetCurrentPositionFromEnd(by=%d);\n", by);
|
||||
assembler_->SetCurrentPositionFromEnd(by);
|
||||
}
|
||||
|
||||
|
||||
void RegExpMacroAssemblerTracer::SetRegister(int register_index, int to) {
|
||||
PrintF(" SetRegister(register=%d, to=%d);\n", register_index, to);
|
||||
assembler_->SetRegister(register_index, to);
|
||||
|
@ -89,7 +89,6 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler {
|
||||
StackCheckFlag check_stack_limit);
|
||||
virtual void ReadCurrentPositionFromRegister(int reg);
|
||||
virtual void ReadStackPointerFromRegister(int reg);
|
||||
virtual void SetCurrentPositionFromEnd(int by);
|
||||
virtual void SetRegister(int register_index, int to);
|
||||
virtual void Succeed();
|
||||
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
|
||||
|
@ -155,7 +155,6 @@ class RegExpMacroAssembler {
|
||||
StackCheckFlag check_stack_limit) = 0;
|
||||
virtual void ReadCurrentPositionFromRegister(int reg) = 0;
|
||||
virtual void ReadStackPointerFromRegister(int reg) = 0;
|
||||
virtual void SetCurrentPositionFromEnd(int by) = 0;
|
||||
virtual void SetRegister(int register_index, int to) = 0;
|
||||
virtual void Succeed() = 0;
|
||||
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset) = 0;
|
||||
|
@ -145,6 +145,7 @@ int RegExpMacroAssemblerX64::stack_limit_slack() {
|
||||
|
||||
void RegExpMacroAssemblerX64::AdvanceCurrentPosition(int by) {
|
||||
if (by != 0) {
|
||||
Label inside_string;
|
||||
__ addq(rdi, Immediate(by * char_size()));
|
||||
}
|
||||
}
|
||||
@ -1052,19 +1053,6 @@ void RegExpMacroAssemblerX64::ReadStackPointerFromRegister(int reg) {
|
||||
}
|
||||
|
||||
|
||||
void RegExpMacroAssemblerX64::SetCurrentPositionFromEnd(int by) {
|
||||
NearLabel after_position;
|
||||
__ cmpq(rdi, Immediate(-by * char_size()));
|
||||
__ j(above_equal, &after_position);
|
||||
__ movq(rdi, Immediate(-by * char_size()));
|
||||
// On RegExp code entry (where this operation is used), the character before
|
||||
// the current position is expected to be already loaded.
|
||||
// We have advenced the position, so it's safe to read backwards.
|
||||
LoadCurrentCharacterUnchecked(-1, 1);
|
||||
__ bind(&after_position);
|
||||
}
|
||||
|
||||
|
||||
void RegExpMacroAssemblerX64::SetRegister(int register_index, int to) {
|
||||
ASSERT(register_index >= num_saved_registers_); // Reserved for positions!
|
||||
__ movq(register_location(register_index), Immediate(to));
|
||||
|
@ -93,7 +93,6 @@ class RegExpMacroAssemblerX64: public NativeRegExpMacroAssembler {
|
||||
StackCheckFlag check_stack_limit);
|
||||
virtual void ReadCurrentPositionFromRegister(int reg);
|
||||
virtual void ReadStackPointerFromRegister(int reg);
|
||||
virtual void SetCurrentPositionFromEnd(int by);
|
||||
virtual void SetRegister(int register_index, int to);
|
||||
virtual void Succeed();
|
||||
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
|
||||
|
@ -589,59 +589,3 @@ assertEquals(0, desc.value);
|
||||
assertEquals(false, desc.configurable);
|
||||
assertEquals(false, desc.enumerable);
|
||||
assertEquals(true, desc.writable);
|
||||
|
||||
|
||||
// Check that end-anchored regexps are optimized correctly.
|
||||
var re = /(?:a|bc)g$/;
|
||||
assertTrue(re.test("ag"));
|
||||
assertTrue(re.test("bcg"));
|
||||
assertTrue(re.test("abcg"));
|
||||
assertTrue(re.test("zimbag"));
|
||||
assertTrue(re.test("zimbcg"));
|
||||
|
||||
assertFalse(re.test("g"));
|
||||
assertFalse(re.test(""));
|
||||
|
||||
// Global regexp (non-zero start).
|
||||
var re = /(?:a|bc)g$/g;
|
||||
assertTrue(re.test("ag"));
|
||||
re.lastIndex = 1; // Near start of string.
|
||||
assertTrue(re.test("zimbag"));
|
||||
re.lastIndex = 5; // Near end of string.
|
||||
assertFalse(re.test("zimbag"));
|
||||
re.lastIndex = 4;
|
||||
assertTrue(re.test("zimbag"));
|
||||
|
||||
// Anchored at both ends.
|
||||
var re = /^(?:a|bc)g$/g;
|
||||
assertTrue(re.test("ag"));
|
||||
re.lastIndex = 1;
|
||||
assertFalse(re.test("ag"));
|
||||
re.lastIndex = 1;
|
||||
assertFalse(re.test("zag"));
|
||||
|
||||
// Long max_length of RegExp.
|
||||
var re = /VeryLongRegExp!{1,1000}$/;
|
||||
assertTrue(re.test("BahoolaVeryLongRegExp!!!!!!"));
|
||||
assertFalse(re.test("VeryLongRegExp"));
|
||||
assertFalse(re.test("!"));
|
||||
|
||||
// End anchor inside disjunction.
|
||||
var re = /(?:a$|bc$)/;
|
||||
assertTrue(re.test("a"));
|
||||
assertTrue(re.test("bc"));
|
||||
assertTrue(re.test("abc"));
|
||||
assertTrue(re.test("zimzamzumba"));
|
||||
assertTrue(re.test("zimzamzumbc"));
|
||||
assertFalse(re.test("c"));
|
||||
assertFalse(re.test(""));
|
||||
|
||||
// Only partially anchored.
|
||||
var re = /(?:a|bc$)/;
|
||||
assertTrue(re.test("a"));
|
||||
assertTrue(re.test("bc"));
|
||||
assertEquals(["a"], re.exec("abc"));
|
||||
assertEquals(4, re.exec("zimzamzumba").index);
|
||||
assertEquals(["bc"], re.exec("zimzomzumbc"));
|
||||
assertFalse(re.test("c"));
|
||||
assertFalse(re.test(""));
|
||||
|
Loading…
Reference in New Issue
Block a user