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:
parent
2c2ae533ec
commit
0269851619
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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++) {
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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) {
|
|||||||
#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(¬_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(¬_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]);
|
||||||
|
Loading…
Reference in New Issue
Block a user