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
This commit is contained in:
lrn@chromium.org 2008-12-01 09:57:14 +00:00
parent 2c2ae533ec
commit 0269851619
7 changed files with 252 additions and 123 deletions

View File

@ -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() {
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
} }

View File

@ -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 {
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);

View File

@ -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++) {

View File

@ -51,6 +51,7 @@ namespace v8 { namespace internal {
* *
* Each call to a public method should retain this convention. * Each call to a public method should retain this convention.
* The stack will have the following structure: * The stack will have the following structure:
* - at_start (if 1, start at start of string, if 0, don't)
* - int* capture_array (int[num_saved_registers_], for output). * - int* capture_array (int[num_saved_registers_], for output).
* - end of input (index of end of string, relative to *string_base) * - end of input (index of end of string, relative to *string_base)
* - start of input (index of first character in string, relative * - start of input (index of first character in string, relative
@ -59,6 +60,7 @@ namespace v8 { namespace internal {
* - return address * - return address
* - backup of esi * - backup of esi
* - backup of edi * - backup of edi
* - backup of ebx
* ebp-> - old ebp * ebp-> - old ebp
* - register 0 ebp[-4] (Only positions must be stored in the first * - register 0 ebp[-4] (Only positions must be stored in the first
* - register 1 ebp[-8] num_saved_registers_ registers) * - register 1 ebp[-8] num_saved_registers_ registers)
@ -73,7 +75,8 @@ namespace v8 { namespace internal {
* bool (*match)(String** string_base, * bool (*match)(String** string_base,
* int start_offset, * int start_offset,
* int end_offset, * int end_offset,
* int* capture_output_array) * int* capture_output_array,
* bool at_start)
*/ */
#define __ masm_-> #define __ masm_->
@ -135,7 +138,7 @@ void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start,
Label* bitmap, Label* bitmap,
Label* on_zero) { Label* on_zero) {
UNREACHABLE(); UNREACHABLE();
ReadCurrentChar(eax); __ mov(eax, current_character());
__ sub(Operand(eax), Immediate(start)); __ sub(Operand(eax), Immediate(start));
__ cmp(eax, 64); // FIXME: 64 = length_of_bitmap_in_bits. __ cmp(eax, 64); // FIXME: 64 = length_of_bitmap_in_bits.
BranchOrBacktrack(greater_equal, on_zero); BranchOrBacktrack(greater_equal, on_zero);
@ -151,24 +154,29 @@ void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start,
void RegExpMacroAssemblerIA32::CheckCharacter(uc16 c, Label* on_equal) { void RegExpMacroAssemblerIA32::CheckCharacter(uc16 c, Label* on_equal) {
__ cmp(edx, c); __ cmp(current_character(), c);
BranchOrBacktrack(equal, on_equal); BranchOrBacktrack(equal, on_equal);
} }
void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) {
__ cmp(edx, limit); __ cmp(current_character(), limit);
BranchOrBacktrack(greater, on_greater); BranchOrBacktrack(greater, on_greater);
} }
void RegExpMacroAssemblerIA32::CheckNotAtStart(Label* on_not_at_start) { void RegExpMacroAssemblerIA32::CheckNotAtStart(Label* on_not_at_start) {
UNIMPLEMENTED(); __ cmp(Operand(ebp, kAtStart), Immediate(0));
BranchOrBacktrack(equal, on_not_at_start);
__ mov(eax, Operand(ebp, kInputEndOffset));
__ add(eax, Operand(edi));
__ cmp(eax, Operand(ebp, kInputStartOffset));
BranchOrBacktrack(not_equal, on_not_at_start);
} }
void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) { void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) {
__ cmp(edx, limit); __ cmp(current_character(), limit);
BranchOrBacktrack(less, on_less); BranchOrBacktrack(less, on_less);
} }
@ -178,9 +186,23 @@ void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
Label* on_failure) { Label* on_failure) {
int byte_length = str.length() * char_size(); int byte_length = str.length() * char_size();
int byte_offset = cp_offset * char_size(); int byte_offset = cp_offset * char_size();
__ mov(ebx, edi); __ cmp(Operand(edi), Immediate(-(byte_offset + byte_length)));
__ add(Operand(ebx), Immediate(byte_offset + byte_length)); BranchOrBacktrack(greater, on_failure);
BranchOrBacktrack(greater_equal, on_failure);
if (str.length() <= kMaxInlineStringTests) {
for (int i = 0; i < str.length(); i++) {
if (mode_ == ASCII) {
__ cmpb(Operand(esi, edi, times_1, byte_offset + i),
static_cast<int8_t>(str[i]));
} else {
ASSERT(mode_ == UC16);
__ cmpw(Operand(esi, edi, times_1, byte_offset + i * sizeof(uc16)),
Immediate(str[i]));
}
__ j(not_equal, on_failure);
}
return;
}
ArraySlice constant_buffer = constants_.GetBuffer(str.length(), char_size()); ArraySlice constant_buffer = constants_.GetBuffer(str.length(), char_size());
if (mode_ == ASCII) { if (mode_ == ASCII) {
@ -197,8 +219,13 @@ void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
__ mov(ebx, esi); __ mov(ebx, esi);
__ lea(edi, Operand(esi, edi, times_1, byte_offset)); __ lea(edi, Operand(esi, edi, times_1, byte_offset));
LoadConstantBufferAddress(esi, &constant_buffer); LoadConstantBufferAddress(esi, &constant_buffer);
__ mov(ecx, str.length() * char_size()); __ mov(ecx, str.length());
__ rep_cmpsb(); if (char_size() == 1) {
__ rep_cmpsb();
} else {
ASSERT(char_size() == 2);
__ rep_cmpsw();
}
__ mov(esi, ebx); __ mov(esi, ebx);
__ mov(edi, eax); __ mov(edi, eax);
BranchOrBacktrack(not_equal, on_failure); BranchOrBacktrack(not_equal, on_failure);
@ -214,7 +241,16 @@ void RegExpMacroAssemblerIA32::CheckCurrentPosition(int register_index,
void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
int start_reg, Label* on_no_match) { int start_reg, Label* on_no_match) {
UNIMPLEMENTED(); Label fallthrough;
__ mov(eax, register_location(start_reg));
__ mov(ecx, register_location(start_reg + 1));
__ sub(ecx, Operand(eax)); // Length to check.
__ j(less, on_no_match);
__ j(equal, &fallthrough);
UNIMPLEMENTED(); // TODO(lrn): Call runtime function to do test.
__ bind(&fallthrough);
} }
@ -224,15 +260,16 @@ void RegExpMacroAssemblerIA32::CheckNotBackReference(
__ mov(eax, register_location(start_reg)); __ mov(eax, register_location(start_reg));
__ mov(ecx, register_location(start_reg + 1)); __ mov(ecx, register_location(start_reg + 1));
__ sub(ecx, Operand(eax)); // Length to check. __ sub(ecx, Operand(eax)); // Length to check.
__ j(equal, &fallthrough); // Covers the case where it's not bound (-1,-1). __ j(less, on_no_match);
__ j(equal, &fallthrough);
// check that there are sufficient characters left in the input
__ mov(ebx, edi);
__ add(ebx, Operand(ecx));
__ j(greater, on_no_match);
__ mov(ebx, Operand(edi)); __ mov(ebx, Operand(edi));
__ push(esi); __ push(esi);
__ add(edi, Operand(esi)); __ add(edi, Operand(esi));
__ add(esi, Operand(eax)); __ add(esi, Operand(eax));
if (char_size() > 0) {
ASSERT(char_size() == 2);
__ add(ecx, Operand(ecx));
}
__ rep_cmpsb(); __ rep_cmpsb();
__ pop(esi); __ pop(esi);
__ mov(edi, Operand(ebx)); __ mov(edi, Operand(ebx));
@ -245,14 +282,13 @@ void RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1,
int reg2, int reg2,
Label* on_not_equal) { Label* on_not_equal) {
__ mov(eax, register_location(reg1)); __ mov(eax, register_location(reg1));
__ mov(ecx, register_location(reg2)); __ cmp(eax, register_location(reg2));
__ cmp(ecx, Operand(eax));
BranchOrBacktrack(not_equal, on_not_equal); BranchOrBacktrack(not_equal, on_not_equal);
} }
void RegExpMacroAssemblerIA32::CheckNotCharacter(uc16 c, Label* on_not_equal) { void RegExpMacroAssemblerIA32::CheckNotCharacter(uc16 c, Label* on_not_equal) {
__ cmp(edx, c); __ cmp(current_character(), c);
BranchOrBacktrack(not_equal, on_not_equal); BranchOrBacktrack(not_equal, on_not_equal);
} }
@ -260,7 +296,7 @@ void RegExpMacroAssemblerIA32::CheckNotCharacter(uc16 c, Label* on_not_equal) {
void RegExpMacroAssemblerIA32::CheckNotCharacterAfterOr(uc16 c, void RegExpMacroAssemblerIA32::CheckNotCharacterAfterOr(uc16 c,
uc16 mask, uc16 mask,
Label* on_not_equal) { Label* on_not_equal) {
__ mov(eax, Operand(edx)); __ mov(eax, current_character());
__ or_(eax, mask); __ or_(eax, mask);
__ cmp(eax, c); __ cmp(eax, c);
BranchOrBacktrack(not_equal, on_not_equal); BranchOrBacktrack(not_equal, on_not_equal);
@ -271,7 +307,7 @@ void RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusOr(
uc16 c, uc16 c,
uc16 mask, uc16 mask,
Label* on_not_equal) { Label* on_not_equal) {
__ lea(eax, Operand(edx, -mask)); __ lea(eax, Operand(current_character(), -mask));
__ or_(eax, mask); __ or_(eax, mask);
__ cmp(eax, c); __ cmp(eax, c);
BranchOrBacktrack(not_equal, on_not_equal); BranchOrBacktrack(not_equal, on_not_equal);
@ -282,7 +318,8 @@ void RegExpMacroAssemblerIA32::DispatchHalfNibbleMap(
uc16 start, uc16 start,
Label* half_nibble_map, Label* half_nibble_map,
const Vector<Label*>& destinations) { const Vector<Label*>& destinations) {
ReadCurrentChar(eax); UNIMPLEMENTED();
__ mov(eax, current_character());
__ sub(Operand(eax), Immediate(start)); __ sub(Operand(eax), Immediate(start));
__ mov(ecx, eax); __ mov(ecx, eax);
@ -318,8 +355,10 @@ void RegExpMacroAssemblerIA32::DispatchByteMap(
uc16 start, uc16 start,
Label* byte_map, Label* byte_map,
const Vector<Label*>& destinations) { const Vector<Label*>& destinations) {
UNIMPLEMENTED();
Label fallthrough; Label fallthrough;
ReadCurrentChar(eax); __ mov(eax, current_character());
__ sub(Operand(eax), Immediate(start)); __ sub(Operand(eax), Immediate(start));
__ cmp(eax, 64); // FIXME: 64 = size of map. Found somehow?? __ cmp(eax, 64); // FIXME: 64 = size of map. Found somehow??
__ j(greater_equal, &fallthrough); __ j(greater_equal, &fallthrough);
@ -335,10 +374,10 @@ void RegExpMacroAssemblerIA32::DispatchHighByteMap(
byte start, byte start,
Label* byte_map, Label* byte_map,
const Vector<Label*>& destinations) { const Vector<Label*>& destinations) {
UNREACHABLE(); UNIMPLEMENTED();
Label fallthrough; Label fallthrough;
ReadCurrentChar(eax); __ mov(eax, current_character());
__ shr(eax, 8); __ shr(eax, 8);
__ sub(Operand(eax), Immediate(start)); __ sub(Operand(eax), Immediate(start));
__ cmp(eax, destinations.length() - start); __ cmp(eax, destinations.length() - start);
@ -350,7 +389,7 @@ void RegExpMacroAssemblerIA32::DispatchHighByteMap(
void RegExpMacroAssemblerIA32::EmitOrLink(Label* label) { void RegExpMacroAssemblerIA32::EmitOrLink(Label* label) {
UNREACHABLE(); // Has no use. UNIMPLEMENTED(); // Has no use.
} }
@ -395,9 +434,19 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode() {
__ inc(ecx); __ inc(ecx);
__ j(not_equal, &init_loop); __ j(not_equal, &init_loop);
} }
// Load previous char as initial value of current-character.
Label at_start;
__ cmp(Operand(ebp, kAtStart), Immediate(0));
__ j(not_equal, &at_start);
LoadCurrentCharToRegister(-1); // Load previous char.
__ jmp(&start_label_);
__ bind(&at_start);
__ mov(current_character(), '\n');
__ jmp(&start_label_); __ jmp(&start_label_);
// Exit code: // Exit code:
// Success
__ bind(&success_label_); __ bind(&success_label_);
if (num_saved_registers_ > 0) { if (num_saved_registers_ > 0) {
// copy captures to output // copy captures to output
@ -416,6 +465,7 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode() {
} }
__ mov(eax, Immediate(1)); __ mov(eax, Immediate(1));
// Exit and return eax
__ bind(&exit_label_); __ bind(&exit_label_);
__ leave(); __ leave();
__ pop(ebx); __ pop(ebx);
@ -439,7 +489,6 @@ void RegExpMacroAssemblerIA32::GoTo(Label* to) {
} }
void RegExpMacroAssemblerIA32::IfRegisterGE(int reg, void RegExpMacroAssemblerIA32::IfRegisterGE(int reg,
int comparand, int comparand,
Label* if_ge) { Label* if_ge) {
@ -448,7 +497,6 @@ void RegExpMacroAssemblerIA32::IfRegisterGE(int reg,
} }
void RegExpMacroAssemblerIA32::IfRegisterLT(int reg, void RegExpMacroAssemblerIA32::IfRegisterLT(int reg,
int comparand, int comparand,
Label* if_lt) { Label* if_lt) {
@ -457,21 +505,19 @@ void RegExpMacroAssemblerIA32::IfRegisterLT(int reg,
} }
RegExpMacroAssembler::IrregexpImplementation RegExpMacroAssembler::IrregexpImplementation
RegExpMacroAssemblerIA32::Implementation() { RegExpMacroAssemblerIA32::Implementation() {
return kIA32Implementation; return kIA32Implementation;
} }
void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset,
Label* on_end_of_input) { Label* on_end_of_input) {
ASSERT(cp_offset >= 0); ASSERT(cp_offset >= 0);
ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works)
__ cmp(edi, -cp_offset * char_size()); __ cmp(edi, -cp_offset * char_size());
BranchOrBacktrack(greater_equal, on_end_of_input); BranchOrBacktrack(greater_equal, on_end_of_input);
ReadChar(edx, cp_offset); LoadCurrentCharToRegister(cp_offset);
} }
@ -481,7 +527,6 @@ void RegExpMacroAssemblerIA32::PopCurrentPosition() {
void RegExpMacroAssemblerIA32::PopRegister(int register_index) { void RegExpMacroAssemblerIA32::PopRegister(int register_index) {
RecordRegister(register_index);
__ pop(register_location(register_index)); __ pop(register_location(register_index));
} }
@ -514,7 +559,6 @@ void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) {
void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) { void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) {
ASSERT(register_index >= num_saved_registers_); // Reserved for positions! ASSERT(register_index >= num_saved_registers_); // Reserved for positions!
RecordRegister(register_index);
__ mov(register_location(register_index), Immediate(to)); __ mov(register_location(register_index), Immediate(to));
} }
@ -524,10 +568,8 @@ void RegExpMacroAssemblerIA32::Succeed() {
} }
void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister( void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg) {
int register_index) { __ mov(register_location(reg), edi);
RecordRegister(register_index);
__ mov(register_location(register_index), edi);
} }
void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
@ -537,13 +579,20 @@ void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
// Private methods: // Private methods:
Operand RegExpMacroAssemblerIA32::register_location( Operand RegExpMacroAssemblerIA32::register_location(int register_index) {
int register_index) {
ASSERT(register_index < (1<<30)); ASSERT(register_index < (1<<30));
if (num_registers_ <= register_index) {
num_registers_ = register_index + 1;
}
return Operand(ebp, -(register_index + 1) * kPointerSize); return Operand(ebp, -(register_index + 1) * kPointerSize);
} }
Register RegExpMacroAssemblerIA32::current_character() {
return edx;
}
size_t RegExpMacroAssemblerIA32::char_size() { size_t RegExpMacroAssemblerIA32::char_size() {
return static_cast<size_t>(mode_); return static_cast<size_t>(mode_);
} }
@ -570,22 +619,6 @@ void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition,
} }
void RegExpMacroAssemblerIA32::Canonicalize(Register reg) {
if (mode_ == ASCII) {
Label end;
__ cmp(Operand(reg), Immediate('a'));
__ j(below, &end);
__ cmp(Operand(reg), Immediate('z'));
__ j(above, &end);
__ sub(Operand(reg), Immediate('a' - 'A'));
__ bind(&end);
return;
}
ASSERT(mode_ == UC16);
// TODO(lrn): Use some tables.
}
void RegExpMacroAssemblerIA32::CheckStackLimit() { void RegExpMacroAssemblerIA32::CheckStackLimit() {
if (FLAG_check_stack) { if (FLAG_check_stack) {
// Check for preemption first. // Check for preemption first.
@ -624,25 +657,14 @@ void RegExpMacroAssemblerIA32::CheckStackLimit() {
} }
void RegExpMacroAssemblerIA32::RecordRegister(int register_index) { void RegExpMacroAssemblerIA32::LoadCurrentCharToRegister(int cp_offset) {
if (register_index >= num_registers_) {
num_registers_ = register_index + 1;
}
}
void RegExpMacroAssemblerIA32::ReadChar(Register destination, int offset) {
if (mode_ == ASCII) { if (mode_ == ASCII) {
__ movzx_b(destination, Operand(esi, edi, times_1, offset)); __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset));
return; return;
} }
ASSERT(mode_ == UC16); ASSERT(mode_ == UC16);
__ movzx_w(destination, Operand(esi, edi, times_1, offset * 2)); __ movzx_w(current_character(),
} Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
void RegExpMacroAssemblerIA32::ReadCurrentChar(Register destination) {
__ mov(destination, edx);
} }

View File

@ -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 {
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 {
// 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();

View File

@ -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);
} }

View File

@ -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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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;
RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 0);
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) { TEST(MacroAssemblerIA32Registers) {
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
@ -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) {
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]);