Commit 02698516 authored by lrn@chromium.org's avatar lrn@chromium.org

Fixes (last?) bugs in regexp-ia32 core functionality. All tests run!


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@873 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2c2ae533
...@@ -840,6 +840,26 @@ void Assembler::and_(const Operand& dst, Register src) { ...@@ -840,6 +840,26 @@ void Assembler::and_(const Operand& dst, Register src) {
} }
void Assembler::cmpb(const Operand& op, int8_t imm8) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
EMIT(0x80);
emit_operand(edi, op); // edi == 7
EMIT(imm8);
}
void Assembler::cmpw(const Operand& op, Immediate imm16) {
ASSERT(imm16.is_int16());
EnsureSpace ensure_space(this);
last_pc_ = pc_;
EMIT(0x66);
EMIT(0x81);
emit_operand(edi, op);
emit_w(imm16);
}
void Assembler::cmp(Register reg, int32_t imm32) { void Assembler::cmp(Register reg, int32_t imm32) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
...@@ -877,12 +897,13 @@ void Assembler::rep_cmpsb() { ...@@ -877,12 +897,13 @@ void Assembler::rep_cmpsb() {
EMIT(0xA6); // CMPSB EMIT(0xA6); // CMPSB
} }
void Assembler::rep_cmpsl() { void Assembler::rep_cmpsw() {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0xFC); // CLD to ensure forward operation EMIT(0xFC); // CLD to ensure forward operation
EMIT(0xF3); // REP EMIT(0xF3); // REP
EMIT(0xA7); // CMPSW EMIT(0x66); // Operand size overide.
EMIT(0xA7); // CMPS
} }
......
...@@ -189,6 +189,9 @@ class Immediate BASE_EMBEDDED { ...@@ -189,6 +189,9 @@ class Immediate BASE_EMBEDDED {
bool is_int8() const { bool is_int8() const {
return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE; return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE;
} }
bool is_int16() const {
return -32768 <= x_ && x_ < 32768 && rmode_ == RelocInfo::NONE;
}
private: private:
int x_; int x_;
...@@ -493,13 +496,15 @@ class Assembler : public Malloced { ...@@ -493,13 +496,15 @@ class Assembler : public Malloced {
void and_(const Operand& src, Register dst); void and_(const Operand& src, Register dst);
void and_(const Operand& dst, const Immediate& x); void and_(const Operand& dst, const Immediate& x);
void cmpb(const Operand& op, int8_t imm8);
void cmpw(const Operand& op, Immediate imm16);
void cmp(Register reg, int32_t imm32); void cmp(Register reg, int32_t imm32);
void cmp(Register reg, Handle<Object> handle); void cmp(Register reg, Handle<Object> handle);
void cmp(Register reg, const Operand& op); void cmp(Register reg, const Operand& op);
void cmp(const Operand& op, const Immediate& imm); void cmp(const Operand& op, const Immediate& imm);
void rep_cmpsb(); void rep_cmpsb();
void rep_cmpsl(); void rep_cmpsw();
void dec_b(Register dst); void dec_b(Register dst);
......
...@@ -513,12 +513,12 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<JSRegExp> regexp, ...@@ -513,12 +513,12 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<JSRegExp> regexp,
int start_offset = string_offset + previous_index * sizeof(uc16); int start_offset = string_offset + previous_index * sizeof(uc16);
int end_offset = int end_offset =
string_offset + two_byte_subject->length() * sizeof(uc16); string_offset + two_byte_subject->length() * sizeof(uc16);
typedef bool testfunc(String**, int, int, int*); rc = RegExpMacroAssemblerIA32::Execute(code,
testfunc* test = FUNCTION_CAST<testfunc*>(code->entry()); two_byte_subject.location(),
rc = test(two_byte_subject.location(), start_offset,
start_offset, end_offset,
end_offset, offsets_vector,
offsets_vector); previous_index == 0);
if (rc) { if (rc) {
// Capture values are relative to start_offset only. // Capture values are relative to start_offset only.
for (int i = 0; i < offsets_vector_length; i++) { for (int i = 0; i < offsets_vector_length; i++) {
......
This diff is collapsed.
...@@ -88,6 +88,19 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler { ...@@ -88,6 +88,19 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
virtual void WriteCurrentPositionToRegister(int reg); virtual void WriteCurrentPositionToRegister(int reg);
virtual void WriteStackPointerToRegister(int reg); virtual void WriteStackPointerToRegister(int reg);
template <typename T>
static inline bool Execute(Code* code,
T** input,
int start_offset,
int end_offset,
int* output,
bool at_start) {
typedef bool (*matcher)(T**, int, int, int*, int);
matcher matcher_func = FUNCTION_CAST<matcher>(code->entry());
int at_start_val = at_start ? 1 : 0;
return matcher_func(input, start_offset, end_offset, output, at_start_val);
}
private: private:
// Offsets from ebp of arguments to function. // Offsets from ebp of arguments to function.
static const int kBackup_ebx = sizeof(uint32_t); static const int kBackup_ebx = sizeof(uint32_t);
...@@ -98,6 +111,7 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler { ...@@ -98,6 +111,7 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
static const int kInputStartOffset = kInputBuffer + sizeof(uint32_t); static const int kInputStartOffset = kInputBuffer + sizeof(uint32_t);
static const int kInputEndOffset = kInputStartOffset + sizeof(uint32_t); static const int kInputEndOffset = kInputStartOffset + sizeof(uint32_t);
static const int kRegisterOutput = kInputEndOffset + sizeof(uint32_t); static const int kRegisterOutput = kInputEndOffset + sizeof(uint32_t);
static const int kAtStart = kRegisterOutput + sizeof(uint32_t);
// Initial size of code buffer. // Initial size of code buffer.
static const size_t kRegExpCodeSize = 1024; static const size_t kRegExpCodeSize = 1024;
...@@ -111,32 +125,25 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler { ...@@ -111,32 +125,25 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
// The ebp-relative location of a regexp register. // The ebp-relative location of a regexp register.
Operand register_location(int register_index); Operand register_location(int register_index);
// The register containing the current character after LoadCurrentCharacter.
Register current_character();
// Byte size of chars in the string to match (decided by the Mode argument) // Byte size of chars in the string to match (decided by the Mode argument)
size_t char_size(); size_t char_size();
// Records that a register is used. At the end, we need the number of
// registers used.
void RecordRegister(int register_index);
// Equivalent to a conditional branch to the label, unless the label // Equivalent to a conditional branch to the label, unless the label
// is NULL, in which case it is a conditional Backtrack. // is NULL, in which case it is a conditional Backtrack.
void BranchOrBacktrack(Condition condition, Label* to); void BranchOrBacktrack(Condition condition, Label* to);
// Generate code to perform case-canonicalization on the register.
void Canonicalize(Register register);
// Read a character from input at the given offset from the current // Read a character from input at the given offset from the current
// position. // position.
void ReadChar(Register destination, int offset); void LoadCurrentCharToRegister(int cp_offset);
// Load the address of a "constant buffer" (a slice of a byte array) // Load the address of a "constant buffer" (a slice of a byte array)
// into a register. The address is computed from the ByteArray* address // into a register. The address is computed from the ByteArray* address
// and an offset. Uses no extra registers. // and an offset. Uses no extra registers.
void LoadConstantBufferAddress(Register reg, ArraySlice* buffer); void LoadConstantBufferAddress(Register reg, ArraySlice* buffer);
// Read the current character into the destination register.
void ReadCurrentChar(Register destination);
// Adds code that checks whether preemption has been requested // Adds code that checks whether preemption has been requested
// (and checks if we have hit the stack limit too). // (and checks if we have hit the stack limit too).
void CheckStackLimit(); void CheckStackLimit();
......
...@@ -183,6 +183,7 @@ void RegExpMacroAssemblerTracer::CheckCharacter(uc16 c, Label* on_equal) { ...@@ -183,6 +183,7 @@ void RegExpMacroAssemblerTracer::CheckCharacter(uc16 c, Label* on_equal) {
void RegExpMacroAssemblerTracer::CheckNotAtStart(Label* on_not_at_start) { void RegExpMacroAssemblerTracer::CheckNotAtStart(Label* on_not_at_start) {
PrintF(" CheckNotAtStart(label[%08x]);\n", on_not_at_start); PrintF(" CheckNotAtStart(label[%08x]);\n", on_not_at_start);
assembler_->CheckNotAtStart(on_not_at_start);
} }
......
...@@ -582,9 +582,6 @@ TEST(MacroAssembler) { ...@@ -582,9 +582,6 @@ TEST(MacroAssembler) {
#ifndef ARM // IA32 only tests. #ifndef ARM // IA32 only tests.
TEST(MacroAssemblerIA32Success) { TEST(MacroAssemblerIA32Success) {
typedef bool (*AsciiTest) (
SeqAsciiString** base, int start_index, int end_index, int* captures);
V8::Initialize(NULL); V8::Initialize(NULL);
// regexp-macro-assembler-ia32 needs a handle scope to allocate // regexp-macro-assembler-ia32 needs a handle scope to allocate
...@@ -597,7 +594,6 @@ TEST(MacroAssemblerIA32Success) { ...@@ -597,7 +594,6 @@ TEST(MacroAssemblerIA32Success) {
Handle<Object> code_object = m.GetCode(); Handle<Object> code_object = m.GetCode();
Handle<Code> code = Handle<Code>::cast(code_object); Handle<Code> code = Handle<Code>::cast(code_object);
AsciiTest test = FUNCTION_CAST<AsciiTest>(code->entry());
int captures[4] = {42, 37, 87, 117}; int captures[4] = {42, 37, 87, 117};
Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo")); Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo"));
...@@ -606,8 +602,12 @@ TEST(MacroAssemblerIA32Success) { ...@@ -606,8 +602,12 @@ TEST(MacroAssemblerIA32Success) {
int start_offset = start_adr - reinterpret_cast<Address>(*seq_input); int start_offset = start_adr - reinterpret_cast<Address>(*seq_input);
int end_offset = start_offset + seq_input->length(); int end_offset = start_offset + seq_input->length();
bool success = bool success = RegExpMacroAssemblerIA32::Execute(*code,
test(seq_input.location(), start_offset, end_offset, captures); seq_input.location(),
start_offset,
end_offset,
captures,
true);
CHECK(success); CHECK(success);
CHECK_EQ(-1, captures[0]); CHECK_EQ(-1, captures[0]);
...@@ -618,9 +618,6 @@ TEST(MacroAssemblerIA32Success) { ...@@ -618,9 +618,6 @@ TEST(MacroAssemblerIA32Success) {
TEST(MacroAssemblerIA32Simple) { TEST(MacroAssemblerIA32Simple) {
typedef bool (*AsciiTest) (
SeqAsciiString** base, int start_index, int end_index, int* captures);
V8::Initialize(NULL); V8::Initialize(NULL);
// regexp-macro-assembler-ia32 needs a handle scope to allocate // regexp-macro-assembler-ia32 needs a handle scope to allocate
...@@ -643,7 +640,6 @@ TEST(MacroAssemblerIA32Simple) { ...@@ -643,7 +640,6 @@ TEST(MacroAssemblerIA32Simple) {
Handle<Object> code_object = m.GetCode(); Handle<Object> code_object = m.GetCode();
Handle<Code> code = Handle<Code>::cast(code_object); Handle<Code> code = Handle<Code>::cast(code_object);
AsciiTest test = FUNCTION_CAST<AsciiTest>(code->entry());
int captures[4] = {42, 37, 87, 117}; int captures[4] = {42, 37, 87, 117};
Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo")); Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo"));
...@@ -652,8 +648,12 @@ TEST(MacroAssemblerIA32Simple) { ...@@ -652,8 +648,12 @@ TEST(MacroAssemblerIA32Simple) {
int start_offset = start_adr - reinterpret_cast<Address>(*seq_input); int start_offset = start_adr - reinterpret_cast<Address>(*seq_input);
int end_offset = start_offset + seq_input->length(); int end_offset = start_offset + seq_input->length();
bool success = bool success = RegExpMacroAssemblerIA32::Execute(*code,
test(seq_input.location(), start_offset, end_offset, captures); seq_input.location(),
start_offset,
end_offset,
captures,
true);
CHECK(success); CHECK(success);
CHECK_EQ(0, captures[0]); CHECK_EQ(0, captures[0]);
...@@ -667,16 +667,18 @@ TEST(MacroAssemblerIA32Simple) { ...@@ -667,16 +667,18 @@ TEST(MacroAssemblerIA32Simple) {
start_offset = start_adr - reinterpret_cast<Address>(*seq_input); start_offset = start_adr - reinterpret_cast<Address>(*seq_input);
end_offset = start_offset + seq_input->length(); end_offset = start_offset + seq_input->length();
success = test(seq_input.location(), start_offset, end_offset, captures); success = RegExpMacroAssemblerIA32::Execute(*code,
seq_input.location(),
start_offset,
end_offset,
captures,
true);
CHECK(!success); CHECK(!success);
} }
TEST(MacroAssemblerIA32SimpleUC16) { TEST(MacroAssemblerIA32SimpleUC16) {
typedef bool (*UC16Test) (
SeqTwoByteString** base, int start_index, int end_index, int* captures);
V8::Initialize(NULL); V8::Initialize(NULL);
// regexp-macro-assembler-ia32 needs a handle scope to allocate // regexp-macro-assembler-ia32 needs a handle scope to allocate
...@@ -699,7 +701,6 @@ TEST(MacroAssemblerIA32SimpleUC16) { ...@@ -699,7 +701,6 @@ TEST(MacroAssemblerIA32SimpleUC16) {
Handle<Object> code_object = m.GetCode(); Handle<Object> code_object = m.GetCode();
Handle<Code> code = Handle<Code>::cast(code_object); Handle<Code> code = Handle<Code>::cast(code_object);
UC16Test test = FUNCTION_CAST<UC16Test>(code->entry());
int captures[4] = {42, 37, 87, 117}; int captures[4] = {42, 37, 87, 117};
const uc16 input_data[6] = {'f', 'o', 'o', 'f', 'o', '\xa0'}; const uc16 input_data[6] = {'f', 'o', 'o', 'f', 'o', '\xa0'};
...@@ -710,8 +711,12 @@ TEST(MacroAssemblerIA32SimpleUC16) { ...@@ -710,8 +711,12 @@ TEST(MacroAssemblerIA32SimpleUC16) {
int start_offset = start_adr - reinterpret_cast<Address>(*seq_input); int start_offset = start_adr - reinterpret_cast<Address>(*seq_input);
int end_offset = start_offset + seq_input->length() * sizeof(uc16); int end_offset = start_offset + seq_input->length() * sizeof(uc16);
bool success = bool success = RegExpMacroAssemblerIA32::Execute(*code,
test(seq_input.location(), start_offset, end_offset, captures); seq_input.location(),
start_offset,
end_offset,
captures,
true);
CHECK(success); CHECK(success);
CHECK_EQ(0, captures[0]); CHECK_EQ(0, captures[0]);
...@@ -726,16 +731,18 @@ TEST(MacroAssemblerIA32SimpleUC16) { ...@@ -726,16 +731,18 @@ TEST(MacroAssemblerIA32SimpleUC16) {
start_offset = start_adr - reinterpret_cast<Address>(*seq_input); start_offset = start_adr - reinterpret_cast<Address>(*seq_input);
end_offset = start_offset + seq_input->length() * sizeof(uc16); end_offset = start_offset + seq_input->length() * sizeof(uc16);
success = test(seq_input.location(), start_offset, end_offset, captures); success = RegExpMacroAssemblerIA32::Execute(*code,
seq_input.location(),
start_offset,
end_offset,
captures,
true);
CHECK(!success); CHECK(!success);
} }
TEST(MacroAssemblerIA32Backtrack) { TEST(MacroAssemblerIA32Backtrack) {
typedef bool (*AsciiTest) (
SeqAsciiString** base, int start_index, int end_index, int* captures);
V8::Initialize(NULL); V8::Initialize(NULL);
// regexp-macro-assembler-ia32 needs a handle scope to allocate // regexp-macro-assembler-ia32 needs a handle scope to allocate
...@@ -760,7 +767,6 @@ TEST(MacroAssemblerIA32Backtrack) { ...@@ -760,7 +767,6 @@ TEST(MacroAssemblerIA32Backtrack) {
Handle<Object> code_object = m.GetCode(); Handle<Object> code_object = m.GetCode();
Handle<Code> code = Handle<Code>::cast(code_object); Handle<Code> code = Handle<Code>::cast(code_object);
AsciiTest test = FUNCTION_CAST<AsciiTest>(code->entry());
Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo")); Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo"));
Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input); Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
...@@ -768,17 +774,81 @@ TEST(MacroAssemblerIA32Backtrack) { ...@@ -768,17 +774,81 @@ TEST(MacroAssemblerIA32Backtrack) {
int start_offset = start_adr - reinterpret_cast<Address>(*seq_input); int start_offset = start_adr - reinterpret_cast<Address>(*seq_input);
int end_offset = start_offset + seq_input->length(); int end_offset = start_offset + seq_input->length();
bool success = bool success = RegExpMacroAssemblerIA32::Execute(*code,
test(seq_input.location(), start_offset, end_offset, NULL); seq_input.location(),
start_offset,
end_offset,
NULL,
true);
CHECK(!success); CHECK(!success);
} }
TEST(MacroAssemblerIA32AtStart) {
V8::Initialize(NULL);
// regexp-macro-assembler-ia32 needs a handle scope to allocate
// byte-arrays for constants.
v8::HandleScope scope;
TEST(MacroAssemblerIA32Registers) { RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 0);
typedef bool (*AsciiTest) (
SeqAsciiString** base, int start_index, int end_index, int* captures); uc16 foo_chars[3] = {'f', 'o', 'o'};
Vector<const uc16> foo(foo_chars, 3);
Label not_at_start, newline, fail;
m.CheckNotAtStart(&not_at_start);
// Check that prevchar = '\n' and current = 'f'.
m.CheckCharacter('\n', &newline);
m.Bind(&fail);
m.Fail();
m.Bind(&newline);
m.LoadCurrentCharacter(0, &fail);
m.CheckNotCharacter('f', &fail);
m.Succeed();
m.Bind(&not_at_start);
// Check that prevchar = 'o' and current = 'b'.
Label prevo;
m.CheckCharacter('o', &prevo);
m.Fail();
m.Bind(&prevo);
m.LoadCurrentCharacter(0, &fail);
m.CheckNotCharacter('b', &fail);
m.Succeed();
Handle<Object> code_object = m.GetCode();
Handle<Code> code = Handle<Code>::cast(code_object);
Handle<String> input = Factory::NewStringFromAscii(CStrVector("foobar"));
Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
int start_offset = start_adr - reinterpret_cast<Address>(*seq_input);
int end_offset = start_offset + seq_input->length();
bool success = RegExpMacroAssemblerIA32::Execute(*code,
seq_input.location(),
start_offset,
end_offset,
NULL,
true);
CHECK(success);
start_offset += 3;
success = RegExpMacroAssemblerIA32::Execute(*code,
seq_input.location(),
start_offset,
end_offset,
NULL,
false);
CHECK(success);
}
TEST(MacroAssemblerIA32Registers) {
V8::Initialize(NULL); V8::Initialize(NULL);
// regexp-macro-assembler-ia32 needs a handle scope to allocate // regexp-macro-assembler-ia32 needs a handle scope to allocate
...@@ -850,7 +920,6 @@ TEST(MacroAssemblerIA32Registers) { ...@@ -850,7 +920,6 @@ TEST(MacroAssemblerIA32Registers) {
Handle<Object> code_object = m.GetCode(); Handle<Object> code_object = m.GetCode();
Handle<Code> code = Handle<Code>::cast(code_object); Handle<Code> code = Handle<Code>::cast(code_object);
AsciiTest test = FUNCTION_CAST<AsciiTest>(code->entry());
// String long enough for test (content doesn't matter). // String long enough for test (content doesn't matter).
Handle<String> input = Handle<String> input =
...@@ -861,8 +930,12 @@ TEST(MacroAssemblerIA32Registers) { ...@@ -861,8 +930,12 @@ TEST(MacroAssemblerIA32Registers) {
int end_offset = start_offset + seq_input->length(); int end_offset = start_offset + seq_input->length();
int output[5]; int output[5];
bool success = bool success = RegExpMacroAssemblerIA32::Execute(*code,
test(seq_input.location(), start_offset, end_offset, output); seq_input.location(),
start_offset,
end_offset,
output,
true);
CHECK(success); CHECK(success);
CHECK_EQ(0, output[0]); CHECK_EQ(0, output[0]);
......
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