Author: [EMAIL PROTECTED]
Date: Tue Nov 25 05:13:02 2008
New Revision: 837
Modified:
branches/bleeding_edge/src/assembler-ia32.cc
branches/bleeding_edge/src/jsregexp.cc
branches/bleeding_edge/src/regexp-macro-assembler-ia32.cc
branches/bleeding_edge/src/regexp-macro-assembler-ia32.h
branches/bleeding_edge/test/cctest/cctest.h
branches/bleeding_edge/test/cctest/test-regexp.cc
Log:
Tests for RegExpMacroAssemblerIA32.
Disabled stack-limit checks.
Modified: branches/bleeding_edge/src/assembler-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/assembler-ia32.cc (original)
+++ branches/bleeding_edge/src/assembler-ia32.cc Tue Nov 25 05:13:02 2008
@@ -427,14 +427,14 @@
// If reloc_mode == NONE, the label is stored as buffer relative.
ASSERT(reloc_mode == RelocInfo::NONE);
if (label->is_bound()) {
- // Index of position in Code object:
- int pos = label->pos() + Code::kHeaderSize;
- if (pos >= 0 && pos < 256) {
+ // Index of position relative to Code Object-pointer.
+ int rel_pos = label->pos() + Code::kHeaderSize - kHeapObjectTag;
+ if (rel_pos >= 0 && rel_pos < 256) {
EMIT(0x6a);
- EMIT(pos);
+ EMIT(rel_pos);
} else {
EMIT(0x68);
- emit(pos);
+ emit(rel_pos);
}
} else {
EMIT(0x68);
@@ -1337,7 +1337,8 @@
Displacement disp = disp_at(L);
int fixup_pos = L->pos();
if (disp.type() == Displacement::CODE_RELATIVE) {
- long_at_put(fixup_pos, pos + Code::kHeaderSize);
+ // Relative to Code* heap object pointer.
+ long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
} else {
if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
ASSERT(byte_at(fixup_pos - 1) == 0xE9); // jmp expected
Modified: branches/bleeding_edge/src/jsregexp.cc
==============================================================================
--- branches/bleeding_edge/src/jsregexp.cc (original)
+++ branches/bleeding_edge/src/jsregexp.cc Tue Nov 25 05:13:02 2008
@@ -2586,8 +2586,7 @@
// of the RegExp. We don't know the type of input string yet.
// For now, always assume two-byte strings.
RegExpMacroAssemblerIA32
macro_assembler(RegExpMacroAssemblerIA32::UC16,
- (input->capture_count + 1) *
2,
- ignore_case);
+ (input->capture_count + 1) *
2);
return compiler.Assemble(¯o_assembler,
node,
input->capture_count);
Modified: branches/bleeding_edge/src/regexp-macro-assembler-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/regexp-macro-assembler-ia32.cc (original)
+++ branches/bleeding_edge/src/regexp-macro-assembler-ia32.cc Tue Nov 25
05:13:02 2008
@@ -35,13 +35,10 @@
namespace v8 { namespace internal {
/*
* This assembler uses the following register assignment convention
- * - edx : current character, or kEndOfInput if current position is not
- * inside string. The kEndOfInput value is greater than 0xffff,
- * so any tests that don't check whether the current position
- * is inside the correct range should retain bits above the
- * 15th in their computations, and fail if the value is too
- * great.
+ * - edx : current character. Must be loaded using LoadCurrentCharacter
+ * before using any of the dispatch methods.
* - edi : current position in input, as negative offset from end of
string.
+ * Please notice that this is the byte offset, not the character
offset!
* - esi : end of input (points to byte after last character in input).
* - ebp : points to the location above the registers on the stack,
* as if by the "enter <register_count>" opcode.
@@ -60,12 +57,16 @@
* - backup of esi
* - backup of edi
* ebp-> - old ebp
- * - register 0 ebp[-4]
- * - register 1 ebp[-8]
+ * - register 0 ebp[-4] (Only positions must be stored in the first
+ * - register 1 ebp[-8] num_saved_registers_ registers)
* - ...
*
- * The data before ebp must be placed there by the calling code, e.g.,
- * by calling the code as cast to:
+ * The first num_saved_registers_ registers are initialized to point to
+ * "character -1" in the string (i.e., char_size() bytes before the first
+ * character of the string). The remaining registers starts out as garbage.
+ *
+ * The data up to the return address must be placed there by the calling
+ * code, e.g., by calling the code as cast to:
* bool (*match)(String** string_base,
* int start_offset,
* int end_offset,
@@ -76,14 +77,12 @@
RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(
Mode mode,
- int registers_to_save,
- bool ignore_case)
+ int registers_to_save)
: masm_(new MacroAssembler(NULL, kRegExpCodeSize)),
constants_(kRegExpConstantsSize),
mode_(mode),
num_registers_(registers_to_save),
num_saved_registers_(registers_to_save),
- ignore_case_(ignore_case),
entry_label_(),
start_label_(),
success_label_(),
@@ -108,10 +107,6 @@
ASSERT(by > 0);
Label inside_string;
__ add(Operand(edi), Immediate(by * char_size()));
- __ j(below, &inside_string);
- Backtrack();
-
- __ bind(&inside_string);
}
@@ -136,6 +131,7 @@
void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start,
Label* bitmap,
Label* on_zero) {
+ UNREACHABLE();
ReadCurrentChar(eax);
__ sub(Operand(eax), Immediate(start));
__ cmp(eax, 64); // FIXME: 64 = length_of_bitmap_in_bits.
@@ -173,25 +169,25 @@
int cp_offset,
Label* on_failure) {
int byte_length = str.length() * char_size();
- int start_offset = cp_offset * char_size();
+ int byte_offset = cp_offset * char_size();
__ mov(ebx, edi);
- __ add(Operand(ebx), Immediate(start_offset + byte_length));
+ __ add(Operand(ebx), Immediate(byte_offset + byte_length));
BranchOrBacktrack(greater_equal, on_failure);
ArraySlice constant_buffer = constants_.GetBuffer(str.length(),
char_size());
- for (int i = 0; i < str.length(); i++) {
- if (mode_ == ASCII) {
+ if (mode_ == ASCII) {
+ for (int i = 0; i < str.length(); i++) {
constant_buffer.at<char>(i) = static_cast<char>(str[i]);
- } else {
- memcpy(constant_buffer.location<void>(),
- str.start(),
- str.length() * sizeof(uc16));
}
+ } else {
+ memcpy(constant_buffer.location<void>(),
+ str.start(),
+ str.length() * sizeof(uc16));
}
__ mov(eax, edi);
__ mov(ebx, esi);
- __ lea(edi, Operand(esi, edi, times_1, start_offset));
+ __ lea(edi, Operand(esi, edi, times_1, byte_offset));
LoadConstantBufferAddress(esi, &constant_buffer);
__ mov(ecx, str.length());
if (mode_ == ASCII) {
@@ -314,7 +310,7 @@
__ sub(Operand(eax), Immediate(start));
__ cmp(eax, 64); // FIXME: 64 = size of map. Found somehow??
__ j(greater_equal, &fallthrough);
- // FIXME: ecx must hold address of map
+ // TODO(lrn): ecx must hold address of map
__ movzx_b(eax, Operand(ecx, eax, times_1, 0));
// jump table: jump to destinations[eax];
@@ -327,6 +323,8 @@
byte start,
Label* byte_map,
const Vector<Label*>& destinations) {
+ UNREACHABLE();
+
Label fallthrough;
ReadCurrentChar(eax);
__ shr(eax, 8);
@@ -345,7 +343,7 @@
void RegExpMacroAssemblerIA32::Fail() {
- __ mov(eax, 0);
+ __ xor_(eax, Operand(eax)); // zero eax.
__ jmp(&exit_label_);
}
@@ -365,19 +363,35 @@
__ mov(edx, Operand(ebp, kInputBuffer));
__ mov(edx, Operand(edx, 0));
__ add(esi, Operand(edx));
+ if (num_saved_registers_ > 0) {
+ // Fill saved registers with initial value = start offset - 1
+ __ mov(ecx, -num_saved_registers_);
+ __ mov(eax, Operand(edi));
+ __ sub(Operand(eax), Immediate(char_size()));
+ Label init_loop;
+ __ bind(&init_loop);
+ __ mov(Operand(ebp, ecx, times_4, +0), eax);
+ __ inc(ecx);
+ __ j(not_equal, &init_loop);
+ }
__ jmp(&start_label_);
// Exit code:
__ bind(&success_label_);
- __ mov(ebx, Operand(ebp, kRegisterOutput));
- __ mov(ecx, Operand(ebp, kInputEndOffset));
- __ sub(ecx, Operand(ebp, kInputStartOffset));
- for (int i = 0; i < num_saved_registers_; i++) {
- __ mov(eax, register_location(i));
- __ sub(eax, Operand(ecx)); // Convert to index from start, not end.
- __ mov(Operand(ebx, i * sizeof(int32_t)), eax);
+ if (num_saved_registers_ > 0) {
+ // copy captures to output
+ __ mov(ebx, Operand(ebp, kRegisterOutput));
+ __ mov(ecx, Operand(ebp, kInputEndOffset));
+ __ sub(ecx, Operand(ebp, kInputStartOffset));
+ for (int i = 0; i < num_saved_registers_; i++) {
+ __ mov(eax, register_location(i));
+ __ add(eax, Operand(ecx)); // Convert to index from start, not end.
+ if (char_size() == 2) {
+ __ shr(eax);
+ }
+ __ mov(Operand(ebx, i * sizeof(int32_t)), eax);
+ }
}
- // copy captures to output
__ mov(eax, Immediate(1));
__ bind(&exit_label_);
@@ -432,8 +446,8 @@
Label*
on_end_of_input) {
ASSERT(cp_offset >= 0);
ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works)
- __ cmp(edi, -cp_offset);
- BranchOrBacktrack(less_equal, on_end_of_input);
+ __ cmp(edi, -cp_offset * char_size());
+ BranchOrBacktrack(greater_equal, on_end_of_input);
ReadChar(edx, cp_offset);
}
@@ -450,37 +464,7 @@
void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) {
- // Check for preemption first.
- Label no_preempt;
- Label retry_preempt;
- // Check for preemption.
- ExternalReference stack_limit =
- ExternalReference::address_of_stack_guard_limit();
- __ cmp(esp, Operand::StaticVariable(stack_limit));
- __ j(above, &no_preempt);
-
- __ push(edi); // Current position.
- __ push(edx); // Current character.
- // Restore original edi, esi.
- __ mov(edi, Operand(ebp, kBackup_edi));
- __ mov(esi, Operand(ebp, kBackup_esi));
-
- __ bind(&retry_preempt);
- // simulate stack for Runtime call.
- __ push(Immediate(0)); // Dummy receiver
- __ CallRuntime(Runtime::kStackGuard, 0);
- __ cmp(esp, Operand::StaticVariable(stack_limit));
- __ j(below_equal, &retry_preempt);
-
- __ pop(edx);
- __ pop(edi);
- __ mov(esi, Operand(ebp, kInputBuffer));
- __ mov(esi, Operand(esi, 0));
- __ add(esi, Operand(ebp, kInputEndOffset));
-
- __ bind(&no_preempt);
-
- Label cont;
+ // CheckStackLimit(); // Not ready yet.
__ push(label, RelocInfo::NONE);
}
@@ -506,6 +490,7 @@
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));
}
@@ -518,6 +503,7 @@
void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(
int register_index) {
+ RecordRegister(register_index);
__ mov(register_location(register_index), edi);
}
@@ -549,7 +535,8 @@
}
__ jmp(to);
return;
- } else if (to == NULL) {
+ }
+ if (to == NULL) {
Label skip;
__ j(NegateCondition(condition), &skip);
Backtrack();
@@ -573,6 +560,44 @@
}
ASSERT(mode_ == UC16);
// TODO(lrn): Use some tables.
+}
+
+
+void RegExpMacroAssemblerIA32::CheckStackLimit() {
+ if (FLAG_check_stack) {
+ // Check for preemption first.
+ Label no_preempt;
+ Label retry_preempt;
+ // Check for preemption.
+ ExternalReference stack_guard_limit =
+ ExternalReference::address_of_stack_guard_limit();
+ __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
+ __ j(above, &no_preempt, taken);
+
+ __ push(edi); // Current position.
+ __ push(edx); // Current character.
+ // Restore original edi, esi.
+ __ mov(edi, Operand(ebp, kBackup_edi));
+ __ mov(esi, Operand(ebp, kBackup_esi));
+
+ __ bind(&retry_preempt);
+ // simulate stack for Runtime call.
+ __ push(eax);
+ __ push(Immediate(Smi::FromInt(0))); // Dummy receiver
+ __ CallRuntime(Runtime::kStackGuard, 1);
+ __ pop(eax);
+
+ __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
+ __ j(below_equal, &retry_preempt);
+
+ __ pop(edx);
+ __ pop(edi);
+ __ mov(esi, Operand(ebp, kInputBuffer));
+ __ mov(esi, Operand(esi, 0));
+ __ add(esi, Operand(ebp, kInputEndOffset));
+
+ __ bind(&no_preempt);
+ }
}
Modified: branches/bleeding_edge/src/regexp-macro-assembler-ia32.h
==============================================================================
--- branches/bleeding_edge/src/regexp-macro-assembler-ia32.h (original)
+++ branches/bleeding_edge/src/regexp-macro-assembler-ia32.h Tue Nov 25
05:13:02 2008
@@ -38,7 +38,7 @@
class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
public:
enum Mode {ASCII = 1, UC16 = 2};
- RegExpMacroAssemblerIA32(Mode mode, int registers_to_save, bool
ignore_case);
+ RegExpMacroAssemblerIA32(Mode mode, int registers_to_save);
virtual ~RegExpMacroAssemblerIA32();
virtual void AdvanceCurrentPosition(int by);
virtual void AdvanceRegister(int reg, int by);
@@ -100,9 +100,6 @@
// The ebp-relative location of a regexp register.
Operand register_location(int register_index);
- // Whether to implement case-insensitive matching.
- bool ignore_case();
-
// Byte size of chars in the string to match (decided by the Mode
argument)
size_t char_size();
@@ -129,6 +126,10 @@
// 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();
+
// Initial size of code buffer.
static const size_t kRegExpCodeSize = 1024;
// Initial size of constant buffers allocated during compilation.
@@ -149,7 +150,6 @@
int num_saved_registers_;
// Whether to generate code that is case-insensitive. Only relevant for
// back-references.
- bool ignore_case_;
Label entry_label_;
Label start_label_;
Label success_label_;
Modified: branches/bleeding_edge/test/cctest/cctest.h
==============================================================================
--- branches/bleeding_edge/test/cctest/cctest.h (original)
+++ branches/bleeding_edge/test/cctest/cctest.h Tue Nov 25 05:13:02 2008
@@ -42,6 +42,14 @@
static void Test##Name()
#endif
+#if (defined __arm__ || defined __thumb__ || defined ARM)
+#define IA32TEST DISABLED_TEST
+#define ARMTEST TEST
+#else // ia32
+#define IA32TEST TEST
+#define ARMTEST DISABLED_TEST
+#endif
+
class CcTest {
public:
Modified: branches/bleeding_edge/test/cctest/test-regexp.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-regexp.cc (original)
+++ branches/bleeding_edge/test/cctest/test-regexp.cc Tue Nov 25 05:13:02
2008
@@ -720,6 +720,239 @@
}
+IA32TEST(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
+ // byte-arrays for constants.
+ v8::HandleScope scope;
+
+ RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 4);
+
+ m.Succeed();
+
+ Handle<Object> code_object = m.GetCode();
+ Handle<Code> code = Handle<Code>::cast(code_object);
+ AsciiTest test = FUNCTION_CAST<AsciiTest>(code->entry());
+
+ int captures[4] = {42, 37, 87, 117};
+ Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo"));
+ 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 =
+ test(seq_input.location(), start_offset, end_offset, captures);
+
+ CHECK(success);
+ CHECK_EQ(-1, captures[0]);
+ CHECK_EQ(-1, captures[1]);
+ CHECK_EQ(-1, captures[2]);
+ CHECK_EQ(-1, captures[3]);
+}
+
+
+IA32TEST(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
+ // byte-arrays for constants.
+ v8::HandleScope scope;
+
+ RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 4);
+
+ uc16 foo_chars[3] = {'f', 'o', 'o'};
+ Vector<const uc16> foo(foo_chars, 3);
+
+ Label fail;
+ m.CheckCharacters(foo, 0, &fail);
+ m.WriteCurrentPositionToRegister(0);
+ m.AdvanceCurrentPosition(3);
+ m.WriteCurrentPositionToRegister(1);
+ m.Succeed();
+ m.Bind(&fail);
+ m.Fail();
+
+ Handle<Object> code_object = m.GetCode();
+ Handle<Code> code = Handle<Code>::cast(code_object);
+ AsciiTest test = FUNCTION_CAST<AsciiTest>(code->entry());
+
+ int captures[4] = {42, 37, 87, 117};
+ Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo"));
+ 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 =
+ test(seq_input.location(), start_offset, end_offset, captures);
+
+ CHECK(success);
+ CHECK_EQ(0, captures[0]);
+ CHECK_EQ(3, captures[1]);
+ CHECK_EQ(-1, captures[2]);
+ CHECK_EQ(-1, captures[3]);
+
+ input = Factory::NewStringFromAscii(CStrVector("barbarbar"));
+ seq_input = Handle<SeqAsciiString>::cast(input);
+ start_adr = seq_input->GetCharsAddress();
+ start_offset = start_adr - reinterpret_cast<Address>(*seq_input);
+ end_offset = start_offset + seq_input->length();
+
+ success = test(seq_input.location(), start_offset, end_offset, captures);
+
+ CHECK(!success);
+}
+
+
+IA32TEST(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
+ // 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 fail;
+ Label backtrack;
+ m.LoadCurrentCharacter(10, &fail);
+ m.Succeed();
+ m.Bind(&fail);
+ m.PushBacktrack(&backtrack);
+ m.LoadCurrentCharacter(10, NULL);
+ m.Succeed();
+ m.Bind(&backtrack);
+ m.Fail();
+
+ Handle<Object> code_object = m.GetCode();
+ Handle<Code> code = Handle<Code>::cast(code_object);
+ AsciiTest test = FUNCTION_CAST<AsciiTest>(code->entry());
+
+ Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo"));
+ 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 =
+ test(seq_input.location(), start_offset, end_offset, NULL);
+
+ CHECK(!success);
+}
+
+
+IA32TEST(MacroAssemblerIA32Registers) {
+ 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
+ // byte-arrays for constants.
+ v8::HandleScope scope;
+
+ RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 5);
+
+ uc16 foo_chars[3] = {'f', 'o', 'o'};
+ Vector<const uc16> foo(foo_chars, 3);
+
+ enum registers { out1, out2, out3, out4, out5, sp, loop_cnt };
+ Label fail;
+ Label backtrack;
+ m.WriteCurrentPositionToRegister(out1); // Output: [0]
+ m.PushRegister(out1);
+ m.PushBacktrack(&backtrack);
+ m.WriteStackPointerToRegister(sp);
+ // Fill stack and registers
+ m.AdvanceCurrentPosition(2);
+ m.WriteCurrentPositionToRegister(out1);
+ m.PushRegister(out1);
+ m.PushBacktrack(&fail);
+ // Drop backtrack stack frames.
+ m.ReadStackPointerFromRegister(sp);
+ // And take the first backtrack (to &backtrack)
+ m.Backtrack();
+
+ m.PushCurrentPosition();
+ m.AdvanceCurrentPosition(2);
+ m.PopCurrentPosition();
+
+ m.Bind(&backtrack);
+ m.PopRegister(out1);
+ m.ReadCurrentPositionFromRegister(out1);
+ m.AdvanceCurrentPosition(3);
+ m.WriteCurrentPositionToRegister(out2); // [0,3]
+
+ Label loop;
+ m.SetRegister(loop_cnt, 0); // loop counter
+ m.Bind(&loop);
+ m.AdvanceRegister(loop_cnt, 1);
+ m.AdvanceCurrentPosition(1);
+ m.IfRegisterLT(loop_cnt, 3, &loop);
+ m.WriteCurrentPositionToRegister(out3); // [0,3,6]
+
+ Label loop2;
+ m.SetRegister(loop_cnt, 2); // loop counter
+ m.Bind(&loop2);
+ m.AdvanceRegister(loop_cnt, -1);
+ m.AdvanceCurrentPosition(1);
+ m.IfRegisterGE(loop_cnt, 0, &loop2);
+ m.WriteCurrentPositionToRegister(out4); // [0,3,6,9]
+
+ Label loop3;
+ Label exit_loop3;
+ m.ReadCurrentPositionFromRegister(out3);
+ m.Bind(&loop3);
+ m.AdvanceCurrentPosition(1);
+ m.CheckCurrentPosition(out4, &exit_loop3);
+ m.GoTo(&loop3);
+ m.Bind(&exit_loop3);
+ m.WriteCurrentPositionToRegister(out5); // [0,3,6,9,9]
+
+ m.Succeed();
+
+ m.Bind(&fail);
+ m.Fail();
+
+ Handle<Object> code_object = m.GetCode();
+ Handle<Code> code = Handle<Code>::cast(code_object);
+ AsciiTest test = FUNCTION_CAST<AsciiTest>(code->entry());
+
+ // String long enough for test (content doesn't matter).
+ Handle<String> input =
+ Factory::NewStringFromAscii(CStrVector("foofoofoofoofoo"));
+ 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();
+
+ int output[5];
+ bool success =
+ test(seq_input.location(), start_offset, end_offset, output);
+
+ CHECK(success);
+ CHECK_EQ(0, output[0]);
+ CHECK_EQ(3, output[1]);
+ CHECK_EQ(6, output[2]);
+ CHECK_EQ(9, output[3]);
+ CHECK_EQ(9, output[4]);
+}
+
+
TEST(AddInverseToTable) {
static const int kLimit = 1000;
static const int kRangeCount = 16;
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"v8-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/v8-dev?hl=en
-~----------~----~----~----~------~----~------~--~---