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(&macro_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
-~----------~----~----~----~------~----~------~--~---

Reply via email to