From 026985161900a48ba10e8dd9cf5503787c80894d Mon Sep 17 00:00:00 2001 From: "lrn@chromium.org" Date: Mon, 1 Dec 2008 09:57:14 +0000 Subject: [PATCH] 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 --- src/assembler-ia32.cc | 25 +++++- src/assembler-ia32.h | 7 +- src/jsregexp.cc | 12 +-- src/regexp-macro-assembler-ia32.cc | 164 ++++++++++++++++++++--------------- src/regexp-macro-assembler-ia32.h | 29 ++++--- src/regexp-macro-assembler-tracer.cc | 1 + test/cctest/test-regexp.cc | 137 ++++++++++++++++++++++------- 7 files changed, 252 insertions(+), 123 deletions(-) diff --git a/src/assembler-ia32.cc b/src/assembler-ia32.cc index 4c5ef16..c7571e3 100644 --- a/src/assembler-ia32.cc +++ b/src/assembler-ia32.cc @@ -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) { EnsureSpace ensure_space(this); last_pc_ = pc_; @@ -877,12 +897,13 @@ void Assembler::rep_cmpsb() { EMIT(0xA6); // CMPSB } -void Assembler::rep_cmpsl() { +void Assembler::rep_cmpsw() { EnsureSpace ensure_space(this); last_pc_ = pc_; EMIT(0xFC); // CLD to ensure forward operation EMIT(0xF3); // REP - EMIT(0xA7); // CMPSW + EMIT(0x66); // Operand size overide. + EMIT(0xA7); // CMPS } diff --git a/src/assembler-ia32.h b/src/assembler-ia32.h index 8e330d1..17c6b82 100644 --- a/src/assembler-ia32.h +++ b/src/assembler-ia32.h @@ -189,6 +189,9 @@ class Immediate BASE_EMBEDDED { bool is_int8() const { return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE; } + bool is_int16() const { + return -32768 <= x_ && x_ < 32768 && rmode_ == RelocInfo::NONE; + } private: int x_; @@ -493,13 +496,15 @@ class Assembler : public Malloced { void and_(const Operand& src, Register dst); 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, Handle handle); void cmp(Register reg, const Operand& op); void cmp(const Operand& op, const Immediate& imm); void rep_cmpsb(); - void rep_cmpsl(); + void rep_cmpsw(); void dec_b(Register dst); diff --git a/src/jsregexp.cc b/src/jsregexp.cc index 43148a9..be767bf 100644 --- a/src/jsregexp.cc +++ b/src/jsregexp.cc @@ -513,12 +513,12 @@ Handle RegExpImpl::IrregexpExecOnce(Handle regexp, int start_offset = string_offset + previous_index * sizeof(uc16); int end_offset = string_offset + two_byte_subject->length() * sizeof(uc16); - typedef bool testfunc(String**, int, int, int*); - testfunc* test = FUNCTION_CAST(code->entry()); - rc = test(two_byte_subject.location(), - start_offset, - end_offset, - offsets_vector); + rc = RegExpMacroAssemblerIA32::Execute(code, + two_byte_subject.location(), + start_offset, + end_offset, + offsets_vector, + previous_index == 0); if (rc) { // Capture values are relative to start_offset only. for (int i = 0; i < offsets_vector_length; i++) { diff --git a/src/regexp-macro-assembler-ia32.cc b/src/regexp-macro-assembler-ia32.cc index cc0a500..e58323f 100644 --- a/src/regexp-macro-assembler-ia32.cc +++ b/src/regexp-macro-assembler-ia32.cc @@ -51,6 +51,7 @@ namespace v8 { namespace internal { * * Each call to a public method should retain this convention. * 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). * - end of input (index of end of string, relative to *string_base) * - start of input (index of first character in string, relative @@ -59,6 +60,7 @@ namespace v8 { namespace internal { * - return address * - backup of esi * - backup of edi + * - backup of ebx * ebp-> - old ebp * - register 0 ebp[-4] (Only positions must be stored in the first * - register 1 ebp[-8] num_saved_registers_ registers) @@ -73,7 +75,8 @@ namespace v8 { namespace internal { * bool (*match)(String** string_base, * int start_offset, * int end_offset, - * int* capture_output_array) + * int* capture_output_array, + * bool at_start) */ #define __ masm_-> @@ -135,7 +138,7 @@ void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start, Label* bitmap, Label* on_zero) { UNREACHABLE(); - ReadCurrentChar(eax); + __ mov(eax, current_character()); __ sub(Operand(eax), Immediate(start)); __ cmp(eax, 64); // FIXME: 64 = length_of_bitmap_in_bits. BranchOrBacktrack(greater_equal, on_zero); @@ -151,24 +154,29 @@ void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start, void RegExpMacroAssemblerIA32::CheckCharacter(uc16 c, Label* on_equal) { - __ cmp(edx, c); + __ cmp(current_character(), c); BranchOrBacktrack(equal, on_equal); } void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { - __ cmp(edx, limit); + __ cmp(current_character(), limit); BranchOrBacktrack(greater, on_greater); } 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) { - __ cmp(edx, limit); + __ cmp(current_character(), limit); BranchOrBacktrack(less, on_less); } @@ -178,9 +186,23 @@ void RegExpMacroAssemblerIA32::CheckCharacters(Vector str, Label* on_failure) { int byte_length = str.length() * char_size(); int byte_offset = cp_offset * char_size(); - __ mov(ebx, edi); - __ add(Operand(ebx), Immediate(byte_offset + byte_length)); - BranchOrBacktrack(greater_equal, on_failure); + __ cmp(Operand(edi), Immediate(-(byte_offset + byte_length))); + BranchOrBacktrack(greater, 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(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()); if (mode_ == ASCII) { @@ -197,8 +219,13 @@ void RegExpMacroAssemblerIA32::CheckCharacters(Vector str, __ mov(ebx, esi); __ lea(edi, Operand(esi, edi, times_1, byte_offset)); LoadConstantBufferAddress(esi, &constant_buffer); - __ mov(ecx, str.length() * char_size()); - __ rep_cmpsb(); + __ mov(ecx, str.length()); + if (char_size() == 1) { + __ rep_cmpsb(); + } else { + ASSERT(char_size() == 2); + __ rep_cmpsw(); + } __ mov(esi, ebx); __ mov(edi, eax); BranchOrBacktrack(not_equal, on_failure); @@ -214,7 +241,16 @@ void RegExpMacroAssemblerIA32::CheckCurrentPosition(int register_index, void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( 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(ecx, register_location(start_reg + 1)); __ 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)); __ push(esi); __ add(edi, Operand(esi)); __ add(esi, Operand(eax)); - if (char_size() > 0) { - ASSERT(char_size() == 2); - __ add(ecx, Operand(ecx)); - } __ rep_cmpsb(); __ pop(esi); __ mov(edi, Operand(ebx)); @@ -245,14 +282,13 @@ void RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1, int reg2, Label* on_not_equal) { __ mov(eax, register_location(reg1)); - __ mov(ecx, register_location(reg2)); - __ cmp(ecx, Operand(eax)); + __ cmp(eax, register_location(reg2)); BranchOrBacktrack(not_equal, 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); } @@ -260,7 +296,7 @@ void RegExpMacroAssemblerIA32::CheckNotCharacter(uc16 c, Label* on_not_equal) { void RegExpMacroAssemblerIA32::CheckNotCharacterAfterOr(uc16 c, uc16 mask, Label* on_not_equal) { - __ mov(eax, Operand(edx)); + __ mov(eax, current_character()); __ or_(eax, mask); __ cmp(eax, c); BranchOrBacktrack(not_equal, on_not_equal); @@ -271,7 +307,7 @@ void RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusOr( uc16 c, uc16 mask, Label* on_not_equal) { - __ lea(eax, Operand(edx, -mask)); + __ lea(eax, Operand(current_character(), -mask)); __ or_(eax, mask); __ cmp(eax, c); BranchOrBacktrack(not_equal, on_not_equal); @@ -282,7 +318,8 @@ void RegExpMacroAssemblerIA32::DispatchHalfNibbleMap( uc16 start, Label* half_nibble_map, const Vector& destinations) { - ReadCurrentChar(eax); + UNIMPLEMENTED(); + __ mov(eax, current_character()); __ sub(Operand(eax), Immediate(start)); __ mov(ecx, eax); @@ -318,8 +355,10 @@ void RegExpMacroAssemblerIA32::DispatchByteMap( uc16 start, Label* byte_map, const Vector& destinations) { + UNIMPLEMENTED(); + Label fallthrough; - ReadCurrentChar(eax); + __ mov(eax, current_character()); __ sub(Operand(eax), Immediate(start)); __ cmp(eax, 64); // FIXME: 64 = size of map. Found somehow?? __ j(greater_equal, &fallthrough); @@ -335,10 +374,10 @@ void RegExpMacroAssemblerIA32::DispatchHighByteMap( byte start, Label* byte_map, const Vector& destinations) { - UNREACHABLE(); + UNIMPLEMENTED(); Label fallthrough; - ReadCurrentChar(eax); + __ mov(eax, current_character()); __ shr(eax, 8); __ sub(Operand(eax), Immediate(start)); __ cmp(eax, destinations.length() - start); @@ -350,7 +389,7 @@ void RegExpMacroAssemblerIA32::DispatchHighByteMap( void RegExpMacroAssemblerIA32::EmitOrLink(Label* label) { - UNREACHABLE(); // Has no use. + UNIMPLEMENTED(); // Has no use. } @@ -395,9 +434,19 @@ Handle RegExpMacroAssemblerIA32::GetCode() { __ inc(ecx); __ 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_); + // Exit code: + // Success __ bind(&success_label_); if (num_saved_registers_ > 0) { // copy captures to output @@ -416,6 +465,7 @@ Handle RegExpMacroAssemblerIA32::GetCode() { } __ mov(eax, Immediate(1)); + // Exit and return eax __ bind(&exit_label_); __ leave(); __ pop(ebx); @@ -439,7 +489,6 @@ void RegExpMacroAssemblerIA32::GoTo(Label* to) { } - void RegExpMacroAssemblerIA32::IfRegisterGE(int reg, int comparand, Label* if_ge) { @@ -448,7 +497,6 @@ void RegExpMacroAssemblerIA32::IfRegisterGE(int reg, } - void RegExpMacroAssemblerIA32::IfRegisterLT(int reg, int comparand, Label* if_lt) { @@ -457,21 +505,19 @@ void RegExpMacroAssemblerIA32::IfRegisterLT(int reg, } - RegExpMacroAssembler::IrregexpImplementation RegExpMacroAssemblerIA32::Implementation() { return kIA32Implementation; } - void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, Label* on_end_of_input) { ASSERT(cp_offset >= 0); ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) __ cmp(edi, -cp_offset * char_size()); 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) { - RecordRegister(register_index); __ pop(register_location(register_index)); } @@ -514,7 +559,6 @@ void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) { void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) { ASSERT(register_index >= num_saved_registers_); // Reserved for positions! - RecordRegister(register_index); __ mov(register_location(register_index), Immediate(to)); } @@ -524,10 +568,8 @@ void RegExpMacroAssemblerIA32::Succeed() { } -void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister( - int register_index) { - RecordRegister(register_index); - __ mov(register_location(register_index), edi); +void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg) { + __ mov(register_location(reg), edi); } void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { @@ -537,13 +579,20 @@ void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { // Private methods: -Operand RegExpMacroAssemblerIA32::register_location( - int register_index) { +Operand RegExpMacroAssemblerIA32::register_location(int register_index) { ASSERT(register_index < (1<<30)); + if (num_registers_ <= register_index) { + num_registers_ = register_index + 1; + } return Operand(ebp, -(register_index + 1) * kPointerSize); } +Register RegExpMacroAssemblerIA32::current_character() { + return edx; +} + + size_t RegExpMacroAssemblerIA32::char_size() { return static_cast(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() { if (FLAG_check_stack) { // Check for preemption first. @@ -624,25 +657,14 @@ void RegExpMacroAssemblerIA32::CheckStackLimit() { } -void RegExpMacroAssemblerIA32::RecordRegister(int register_index) { - if (register_index >= num_registers_) { - num_registers_ = register_index + 1; - } -} - - -void RegExpMacroAssemblerIA32::ReadChar(Register destination, int offset) { +void RegExpMacroAssemblerIA32::LoadCurrentCharToRegister(int cp_offset) { if (mode_ == ASCII) { - __ movzx_b(destination, Operand(esi, edi, times_1, offset)); + __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset)); return; } ASSERT(mode_ == UC16); - __ movzx_w(destination, Operand(esi, edi, times_1, offset * 2)); -} - - -void RegExpMacroAssemblerIA32::ReadCurrentChar(Register destination) { - __ mov(destination, edx); + __ movzx_w(current_character(), + Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); } diff --git a/src/regexp-macro-assembler-ia32.h b/src/regexp-macro-assembler-ia32.h index de653d5..d303910 100644 --- a/src/regexp-macro-assembler-ia32.h +++ b/src/regexp-macro-assembler-ia32.h @@ -88,6 +88,19 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler { virtual void WriteCurrentPositionToRegister(int reg); virtual void WriteStackPointerToRegister(int reg); + template + 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(code->entry()); + int at_start_val = at_start ? 1 : 0; + return matcher_func(input, start_offset, end_offset, output, at_start_val); + } + private: // Offsets from ebp of arguments to function. 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 kInputEndOffset = kInputStartOffset + sizeof(uint32_t); static const int kRegisterOutput = kInputEndOffset + sizeof(uint32_t); + static const int kAtStart = kRegisterOutput + sizeof(uint32_t); // Initial size of code buffer. static const size_t kRegExpCodeSize = 1024; @@ -111,32 +125,25 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler { // The ebp-relative location of a regexp register. 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) 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 // is NULL, in which case it is a conditional Backtrack. 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 // 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) // into a register. The address is computed from the ByteArray* address // and an offset. Uses no extra registers. 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 // (and checks if we have hit the stack limit too). void CheckStackLimit(); diff --git a/src/regexp-macro-assembler-tracer.cc b/src/regexp-macro-assembler-tracer.cc index 046d681..80dff25 100644 --- a/src/regexp-macro-assembler-tracer.cc +++ b/src/regexp-macro-assembler-tracer.cc @@ -183,6 +183,7 @@ void RegExpMacroAssemblerTracer::CheckCharacter(uc16 c, Label* on_equal) { void RegExpMacroAssemblerTracer::CheckNotAtStart(Label* on_not_at_start) { PrintF(" CheckNotAtStart(label[%08x]);\n", on_not_at_start); + assembler_->CheckNotAtStart(on_not_at_start); } diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc index 4f075a1..210e5bb 100644 --- a/test/cctest/test-regexp.cc +++ b/test/cctest/test-regexp.cc @@ -582,9 +582,6 @@ TEST(MacroAssembler) { #ifndef ARM // IA32 only tests. TEST(MacroAssemblerIA32Success) { - typedef bool (*AsciiTest) ( - SeqAsciiString** base, int start_index, int end_index, int* captures); - V8::Initialize(NULL); // regexp-macro-assembler-ia32 needs a handle scope to allocate @@ -597,7 +594,6 @@ TEST(MacroAssemblerIA32Success) { Handle code_object = m.GetCode(); Handle code = Handle::cast(code_object); - AsciiTest test = FUNCTION_CAST(code->entry()); int captures[4] = {42, 37, 87, 117}; Handle input = Factory::NewStringFromAscii(CStrVector("foofoo")); @@ -606,8 +602,12 @@ TEST(MacroAssemblerIA32Success) { int start_offset = start_adr - reinterpret_cast
(*seq_input); int end_offset = start_offset + seq_input->length(); - bool success = - test(seq_input.location(), start_offset, end_offset, captures); + bool success = RegExpMacroAssemblerIA32::Execute(*code, + seq_input.location(), + start_offset, + end_offset, + captures, + true); CHECK(success); CHECK_EQ(-1, captures[0]); @@ -618,9 +618,6 @@ TEST(MacroAssemblerIA32Success) { TEST(MacroAssemblerIA32Simple) { - typedef bool (*AsciiTest) ( - SeqAsciiString** base, int start_index, int end_index, int* captures); - V8::Initialize(NULL); // regexp-macro-assembler-ia32 needs a handle scope to allocate @@ -643,7 +640,6 @@ TEST(MacroAssemblerIA32Simple) { Handle code_object = m.GetCode(); Handle code = Handle::cast(code_object); - AsciiTest test = FUNCTION_CAST(code->entry()); int captures[4] = {42, 37, 87, 117}; Handle input = Factory::NewStringFromAscii(CStrVector("foofoo")); @@ -652,8 +648,12 @@ TEST(MacroAssemblerIA32Simple) { int start_offset = start_adr - reinterpret_cast
(*seq_input); int end_offset = start_offset + seq_input->length(); - bool success = - test(seq_input.location(), start_offset, end_offset, captures); + bool success = RegExpMacroAssemblerIA32::Execute(*code, + seq_input.location(), + start_offset, + end_offset, + captures, + true); CHECK(success); CHECK_EQ(0, captures[0]); @@ -667,16 +667,18 @@ TEST(MacroAssemblerIA32Simple) { start_offset = start_adr - reinterpret_cast
(*seq_input); 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); } TEST(MacroAssemblerIA32SimpleUC16) { - typedef bool (*UC16Test) ( - SeqTwoByteString** base, int start_index, int end_index, int* captures); - V8::Initialize(NULL); // regexp-macro-assembler-ia32 needs a handle scope to allocate @@ -699,7 +701,6 @@ TEST(MacroAssemblerIA32SimpleUC16) { Handle code_object = m.GetCode(); Handle code = Handle::cast(code_object); - UC16Test test = FUNCTION_CAST(code->entry()); int captures[4] = {42, 37, 87, 117}; const uc16 input_data[6] = {'f', 'o', 'o', 'f', 'o', '\xa0'}; @@ -710,8 +711,12 @@ TEST(MacroAssemblerIA32SimpleUC16) { int start_offset = start_adr - reinterpret_cast
(*seq_input); int end_offset = start_offset + seq_input->length() * sizeof(uc16); - bool success = - test(seq_input.location(), start_offset, end_offset, captures); + bool success = RegExpMacroAssemblerIA32::Execute(*code, + seq_input.location(), + start_offset, + end_offset, + captures, + true); CHECK(success); CHECK_EQ(0, captures[0]); @@ -726,16 +731,18 @@ TEST(MacroAssemblerIA32SimpleUC16) { start_offset = start_adr - reinterpret_cast
(*seq_input); 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); } TEST(MacroAssemblerIA32Backtrack) { - typedef bool (*AsciiTest) ( - SeqAsciiString** base, int start_index, int end_index, int* captures); - V8::Initialize(NULL); // regexp-macro-assembler-ia32 needs a handle scope to allocate @@ -760,7 +767,6 @@ TEST(MacroAssemblerIA32Backtrack) { Handle code_object = m.GetCode(); Handle code = Handle::cast(code_object); - AsciiTest test = FUNCTION_CAST(code->entry()); Handle input = Factory::NewStringFromAscii(CStrVector("foofoo")); Handle seq_input = Handle::cast(input); @@ -768,17 +774,81 @@ TEST(MacroAssemblerIA32Backtrack) { int start_offset = start_adr - reinterpret_cast
(*seq_input); int end_offset = start_offset + seq_input->length(); - bool success = - test(seq_input.location(), start_offset, end_offset, NULL); + bool success = RegExpMacroAssemblerIA32::Execute(*code, + seq_input.location(), + start_offset, + end_offset, + NULL, + true); 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) { - typedef bool (*AsciiTest) ( - SeqAsciiString** base, int start_index, int end_index, int* captures); + RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 0); + + uc16 foo_chars[3] = {'f', 'o', 'o'}; + Vector 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 code_object = m.GetCode(); + Handle code = Handle::cast(code_object); + + Handle input = Factory::NewStringFromAscii(CStrVector("foobar")); + Handle seq_input = Handle::cast(input); + Address start_adr = seq_input->GetCharsAddress(); + int start_offset = start_adr - reinterpret_cast
(*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); // regexp-macro-assembler-ia32 needs a handle scope to allocate @@ -850,7 +920,6 @@ TEST(MacroAssemblerIA32Registers) { Handle code_object = m.GetCode(); Handle code = Handle::cast(code_object); - AsciiTest test = FUNCTION_CAST(code->entry()); // String long enough for test (content doesn't matter). Handle input = @@ -861,8 +930,12 @@ TEST(MacroAssemblerIA32Registers) { int end_offset = start_offset + seq_input->length(); int output[5]; - bool success = - test(seq_input.location(), start_offset, end_offset, output); + bool success = RegExpMacroAssemblerIA32::Execute(*code, + seq_input.location(), + start_offset, + end_offset, + output, + true); CHECK(success); CHECK_EQ(0, output[0]); -- 2.7.4