Minor bugfixes and optimizations.

Added command line debugger to D8 shell.

Fixed subtle bug that caused the wrong 'this' to be used when calling a caught function in a catch clause.

Inline array loads within loops directly in the code instead of


git-svn-id: http://v8.googlecode.com/svn/trunk@1031 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/test/cctest/SConscript b/test/cctest/SConscript
index c2a96f2..c70b07d 100644
--- a/test/cctest/SConscript
+++ b/test/cctest/SConscript
@@ -38,7 +38,7 @@
     'test-ast.cc', 'test-heap.cc', 'test-utils.cc', 'test-compiler.cc',
     'test-spaces.cc', 'test-mark-compact.cc', 'test-lock.cc',
     'test-conversions.cc', 'test-strings.cc', 'test-serialize.cc',
-    'test-decls.cc', 'test-alloc.cc', 'test-regexp.cc'
+    'test-decls.cc', 'test-alloc.cc', 'test-regexp.cc', 'test-threads.cc'
   ],
   'arch:arm':  ['test-assembler-arm.cc', 'test-disasm-arm.cc'],
   'arch:ia32': ['test-assembler-ia32.cc', 'test-disasm-ia32.cc'],
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 0f6ceab..926272e 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -5094,6 +5094,12 @@
 
 static int GetSurvivingGlobalObjectsCount() {
   int count = 0;
+  // We need to collect all garbage twice to be sure that everything
+  // has been collected.  This is because inline caches are cleared in
+  // the first garbage collection but some of the maps have already
+  // been marked at that point.  Therefore some of the maps are not
+  // collected until the second garbage collection.
+  v8::internal::Heap::CollectAllGarbage();
   v8::internal::Heap::CollectAllGarbage();
   v8::internal::HeapIterator it;
   while (it.has_next()) {
@@ -5114,10 +5120,6 @@
 
   v8::V8::Initialize();
 
-  // TODO(121): when running "cctest test-api", the initial count is 2,
-  // after second GC, the counter drops to 1. Needs to figure out why
-  // one GC is not enough to collect all garbage.
-  GetSurvivingGlobalObjectsCount();
   int count = GetSurvivingGlobalObjectsCount();
 
   for (int i = 0; i < 5; i++) {
diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc
index 782bb11..19ced16 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -63,7 +63,7 @@
   return output;
 }
 
-static bool ParseEscapes(const char* input) {
+static bool CheckSimple(const char* input) {
   V8::Initialize(NULL);
   v8::HandleScope scope;
   unibrow::Utf8InputBuffer<> buffer(input, strlen(input));
@@ -73,13 +73,39 @@
   CHECK(v8::internal::ParseRegExp(&reader, false, &result));
   CHECK(result.tree != NULL);
   CHECK(result.error.is_null());
-  return result.has_character_escapes;
+  return result.simple;
+}
+
+struct MinMaxPair {
+  int min_match;
+  int max_match;
+};
+
+static MinMaxPair CheckMinMaxMatch(const char* input) {
+  V8::Initialize(NULL);
+  v8::HandleScope scope;
+  unibrow::Utf8InputBuffer<> buffer(input, strlen(input));
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  FlatStringReader reader(CStrVector(input));
+  RegExpCompileData result;
+  CHECK(v8::internal::ParseRegExp(&reader, false, &result));
+  CHECK(result.tree != NULL);
+  CHECK(result.error.is_null());
+  int min_match = result.tree->min_match();
+  int max_match = result.tree->max_match();
+  MinMaxPair pair = { min_match, max_match };
+  return pair;
 }
 
 
+
 #define CHECK_PARSE_EQ(input, expected) CHECK_EQ(expected, *Parse(input))
-#define CHECK_ESCAPES(input, has_escapes) CHECK_EQ(has_escapes, \
-                                                   ParseEscapes(input));
+#define CHECK_SIMPLE(input, simple) CHECK_EQ(simple, CheckSimple(input));
+#define CHECK_MIN_MAX(input, min, max)                                         \
+  { MinMaxPair min_max = CheckMinMaxMatch(input);                              \
+    CHECK_EQ(min, min_max.min_match);                                          \
+    CHECK_EQ(max, min_max.max_match);                                          \
+  }
 
 TEST(Parser) {
   V8::Initialize(NULL);
@@ -168,6 +194,11 @@
   CHECK_PARSE_EQ("(a)\\1", "(: (^ 'a') (<- 1))");
   CHECK_PARSE_EQ("(a\\1)", "(^ 'a')");
   CHECK_PARSE_EQ("(\\1a)", "(^ 'a')");
+  CHECK_PARSE_EQ("(?=a)?a", "'a'");
+  CHECK_PARSE_EQ("(?=a){0,10}a", "'a'");
+  CHECK_PARSE_EQ("(?=a){1,10}a", "(: (-> + 'a') 'a')");
+  CHECK_PARSE_EQ("(?=a){9,10}a", "(: (-> + 'a') 'a')");
+  CHECK_PARSE_EQ("(?!a)?a", "'a'");
   CHECK_PARSE_EQ("\\1(a)", "(^ 'a')");
   CHECK_PARSE_EQ("(?!(a))\\1", "(-> - (^ 'a'))");
   CHECK_PARSE_EQ("(?!\\1(a\\1)\\1)\\1", "(-> - (: (^ 'a') (<- 1)))");
@@ -186,47 +217,50 @@
   CHECK_PARSE_EQ("\\u003z", "'u003z'");
   CHECK_PARSE_EQ("foo[z]*", "(: 'foo' (# 0 - g [z]))");
 
-  CHECK_ESCAPES("a", false);
-  CHECK_ESCAPES("a|b", false);
-  CHECK_ESCAPES("a\\n", true);
-  CHECK_ESCAPES("^a", false);
-  CHECK_ESCAPES("a$", false);
-  CHECK_ESCAPES("a\\b!", false);
-  CHECK_ESCAPES("a\\Bb", false);
-  CHECK_ESCAPES("a*", false);
-  CHECK_ESCAPES("a*?", false);
-  CHECK_ESCAPES("a?", false);
-  CHECK_ESCAPES("a??", false);
-  CHECK_ESCAPES("a{0,1}?", false);
-  CHECK_ESCAPES("a{1,1}?", false);
-  CHECK_ESCAPES("a{1,2}?", false);
-  CHECK_ESCAPES("a+?", false);
-  CHECK_ESCAPES("(a)", false);
-  CHECK_ESCAPES("(a)\\1", false);
-  CHECK_ESCAPES("(\\1a)", false);
-  CHECK_ESCAPES("\\1(a)", false);
-  CHECK_ESCAPES("a\\s", false);
-  CHECK_ESCAPES("a\\S", false);
-  CHECK_ESCAPES("a\\d", false);
-  CHECK_ESCAPES("a\\D", false);
-  CHECK_ESCAPES("a\\w", false);
-  CHECK_ESCAPES("a\\W", false);
-  CHECK_ESCAPES("a.", false);
-  CHECK_ESCAPES("a\\q", true);
-  CHECK_ESCAPES("a[a]", false);
-  CHECK_ESCAPES("a[^a]", false);
-  CHECK_ESCAPES("a[a-z]", false);
-  CHECK_ESCAPES("a[\\q]", false);
-  CHECK_ESCAPES("a(?:b)", false);
-  CHECK_ESCAPES("a(?=b)", false);
-  CHECK_ESCAPES("a(?!b)", false);
-  CHECK_ESCAPES("\\x60", true);
-  CHECK_ESCAPES("\\u0060", true);
-  CHECK_ESCAPES("\\cA", true);
-  CHECK_ESCAPES("\\q", true);
-  CHECK_ESCAPES("\\1112", true);
-  CHECK_ESCAPES("\\0", true);
-  CHECK_ESCAPES("(a)\\1", false);
+  CHECK_SIMPLE("a", true);
+  CHECK_SIMPLE("a|b", false);
+  CHECK_SIMPLE("a\\n", false);
+  CHECK_SIMPLE("^a", false);
+  CHECK_SIMPLE("a$", false);
+  CHECK_SIMPLE("a\\b!", false);
+  CHECK_SIMPLE("a\\Bb", false);
+  CHECK_SIMPLE("a*", false);
+  CHECK_SIMPLE("a*?", false);
+  CHECK_SIMPLE("a?", false);
+  CHECK_SIMPLE("a??", false);
+  CHECK_SIMPLE("a{0,1}?", false);
+  CHECK_SIMPLE("a{1,1}?", false);
+  CHECK_SIMPLE("a{1,2}?", false);
+  CHECK_SIMPLE("a+?", false);
+  CHECK_SIMPLE("(a)", false);
+  CHECK_SIMPLE("(a)\\1", false);
+  CHECK_SIMPLE("(\\1a)", false);
+  CHECK_SIMPLE("\\1(a)", false);
+  CHECK_SIMPLE("a\\s", false);
+  CHECK_SIMPLE("a\\S", false);
+  CHECK_SIMPLE("a\\d", false);
+  CHECK_SIMPLE("a\\D", false);
+  CHECK_SIMPLE("a\\w", false);
+  CHECK_SIMPLE("a\\W", false);
+  CHECK_SIMPLE("a.", false);
+  CHECK_SIMPLE("a\\q", false);
+  CHECK_SIMPLE("a[a]", false);
+  CHECK_SIMPLE("a[^a]", false);
+  CHECK_SIMPLE("a[a-z]", false);
+  CHECK_SIMPLE("a[\\q]", false);
+  CHECK_SIMPLE("a(?:b)", false);
+  CHECK_SIMPLE("a(?=b)", false);
+  CHECK_SIMPLE("a(?!b)", false);
+  CHECK_SIMPLE("\\x60", false);
+  CHECK_SIMPLE("\\u0060", false);
+  CHECK_SIMPLE("\\cA", false);
+  CHECK_SIMPLE("\\q", false);
+  CHECK_SIMPLE("\\1112", false);
+  CHECK_SIMPLE("\\0", false);
+  CHECK_SIMPLE("(a)\\1", false);
+  CHECK_SIMPLE("(?=a)?a", false);
+  CHECK_SIMPLE("(?!a)?a\\1", false);
+  CHECK_SIMPLE("(?:(?=a))a\\1", false);
 
   CHECK_PARSE_EQ("a{}", "'a{}'");
   CHECK_PARSE_EQ("a{,}", "'a{,}'");
@@ -244,6 +278,55 @@
   CHECK_PARSE_EQ("{12z}", "'{12z}'");
   CHECK_PARSE_EQ("{12,", "'{12,'");
   CHECK_PARSE_EQ("{12,3b", "'{12,3b'");
+
+  CHECK_MIN_MAX("a", 1, 1);
+  CHECK_MIN_MAX("abc", 3, 3);
+  CHECK_MIN_MAX("a[bc]d", 3, 3);
+  CHECK_MIN_MAX("a|bc", 1, 2);
+  CHECK_MIN_MAX("ab|c", 1, 2);
+  CHECK_MIN_MAX("a||bc", 0, 2);
+  CHECK_MIN_MAX("|", 0, 0);
+  CHECK_MIN_MAX("(?:ab)", 2, 2);
+  CHECK_MIN_MAX("(?:ab|cde)", 2, 3);
+  CHECK_MIN_MAX("(?:ab)|cde", 2, 3);
+  CHECK_MIN_MAX("(ab)", 2, 2);
+  CHECK_MIN_MAX("(ab|cde)", 2, 3);
+  CHECK_MIN_MAX("(ab)\\1", 4, 4);
+  CHECK_MIN_MAX("(ab|cde)\\1", 4, 6);
+  CHECK_MIN_MAX("(?:ab)?", 0, 2);
+  CHECK_MIN_MAX("(?:ab)*", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:ab)+", 2, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a?", 0, 1);
+  CHECK_MIN_MAX("a*", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a+", 1, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a??", 0, 1);
+  CHECK_MIN_MAX("a*?", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a+?", 1, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a?)?", 0, 1);
+  CHECK_MIN_MAX("(?:a*)?", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a+)?", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a?)+", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a*)+", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a+)+", 1, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a?)*", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a*)*", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a+)*", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a{0}", 0, 0);
+  CHECK_MIN_MAX("(?:a+){0}", 0, 0);
+  CHECK_MIN_MAX("(?:a+){0,0}", 0, 0);
+  CHECK_MIN_MAX("a*b", 1, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a+b", 2, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a*b|c", 1, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a+b|c", 1, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a{5,1000000}){3,1000000}", 15, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:ab){4,7}", 8, 14);
+  CHECK_MIN_MAX("a\\bc", 2, 2);
+  CHECK_MIN_MAX("a\\Bc", 2, 2);
+  CHECK_MIN_MAX("a\\sc", 3, 3);
+  CHECK_MIN_MAX("a\\Sc", 3, 3);
+  CHECK_MIN_MAX("a(?=b)c", 2, 2);
+  CHECK_MIN_MAX("a(?=bbb|bb)c", 2, 2);
+  CHECK_MIN_MAX("a(?!bbb|bb)c", 2, 2);
 }
 
 TEST(ParserRegression) {
@@ -567,12 +650,26 @@
 
 #ifndef ARM  // IA32 only tests.
 
-TEST(MacroAssemblerIA32Success) {
-  V8::Initialize(NULL);
+class ContextInitializer {
+ public:
+  ContextInitializer() : env_(), scope_(), stack_guard_() {
+    env_ = v8::Context::New();
+    env_->Enter();
+  }
+  ~ContextInitializer() {
+    env_->Exit();
+    env_.Dispose();
+  }
+ private:
+  v8::Persistent<v8::Context> env_;
+  v8::HandleScope scope_;
+  v8::internal::StackGuard stack_guard_;
+};
 
-  // regexp-macro-assembler-ia32 needs a handle scope to allocate
-  // byte-arrays for constants.
-  v8::HandleScope scope;
+
+TEST(MacroAssemblerIA32Success) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
 
   RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 4);
 
@@ -589,14 +686,15 @@
   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,
-                                                   captures,
-                                                   true);
+  RegExpMacroAssemblerIA32::Result result =
+      RegExpMacroAssemblerIA32::Execute(*code,
+                                        seq_input.location(),
+                                        start_offset,
+                                        end_offset,
+                                        captures,
+                                        true);
 
-  CHECK(success);
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
   CHECK_EQ(-1, captures[0]);
   CHECK_EQ(-1, captures[1]);
   CHECK_EQ(-1, captures[2]);
@@ -605,11 +703,8 @@
 
 
 TEST(MacroAssemblerIA32Simple) {
-  V8::Initialize(NULL);
-
-  // regexp-macro-assembler-ia32 needs a handle scope to allocate
-  // byte-arrays for constants.
-  v8::HandleScope scope;
+  v8::V8::Initialize();
+  ContextInitializer initializer;
 
   RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 4);
 
@@ -636,14 +731,15 @@
   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,
-                                                   captures,
-                                                   true);
+  RegExpMacroAssemblerIA32::Result result =
+      RegExpMacroAssemblerIA32::Execute(*code,
+                                        seq_input.location(),
+                                        start_offset,
+                                        end_offset,
+                                        captures,
+                                        true);
 
-  CHECK(success);
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
   CHECK_EQ(0, captures[0]);
   CHECK_EQ(3, captures[1]);
   CHECK_EQ(-1, captures[2]);
@@ -655,23 +751,20 @@
   start_offset = start_adr - reinterpret_cast<Address>(*seq_input);
   end_offset = start_offset + seq_input->length();
 
-  success = RegExpMacroAssemblerIA32::Execute(*code,
-                                              seq_input.location(),
-                                              start_offset,
-                                              end_offset,
-                                              captures,
-                                              true);
+  result = RegExpMacroAssemblerIA32::Execute(*code,
+                                             seq_input.location(),
+                                             start_offset,
+                                             end_offset,
+                                             captures,
+                                             true);
 
-  CHECK(!success);
+  CHECK_EQ(RegExpMacroAssemblerIA32::FAILURE, result);
 }
 
 
 TEST(MacroAssemblerIA32SimpleUC16) {
-  V8::Initialize(NULL);
-
-  // regexp-macro-assembler-ia32 needs a handle scope to allocate
-  // byte-arrays for constants.
-  v8::HandleScope scope;
+  v8::V8::Initialize();
+  ContextInitializer initializer;
 
   RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::UC16, 4);
 
@@ -700,14 +793,15 @@
   int start_offset = start_adr - reinterpret_cast<Address>(*seq_input);
   int end_offset = start_offset + seq_input->length() * sizeof(uc16);
 
-  bool success = RegExpMacroAssemblerIA32::Execute(*code,
-                                                   seq_input.location(),
-                                                   start_offset,
-                                                   end_offset,
-                                                   captures,
-                                                   true);
+  RegExpMacroAssemblerIA32::Result result =
+      RegExpMacroAssemblerIA32::Execute(*code,
+                                        seq_input.location(),
+                                        start_offset,
+                                        end_offset,
+                                        captures,
+                                        true);
 
-  CHECK(success);
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
   CHECK_EQ(0, captures[0]);
   CHECK_EQ(3, captures[1]);
   CHECK_EQ(-1, captures[2]);
@@ -720,23 +814,20 @@
   start_offset = start_adr - reinterpret_cast<Address>(*seq_input);
   end_offset = start_offset + seq_input->length() * sizeof(uc16);
 
-  success = RegExpMacroAssemblerIA32::Execute(*code,
-                                              seq_input.location(),
-                                              start_offset,
-                                              end_offset,
-                                              captures,
-                                              true);
+  result = RegExpMacroAssemblerIA32::Execute(*code,
+                                             seq_input.location(),
+                                             start_offset,
+                                             end_offset,
+                                             captures,
+                                             true);
 
-  CHECK(!success);
+  CHECK_EQ(RegExpMacroAssemblerIA32::FAILURE, result);
 }
 
 
 TEST(MacroAssemblerIA32Backtrack) {
-  V8::Initialize(NULL);
-
-  // regexp-macro-assembler-ia32 needs a handle scope to allocate
-  // byte-arrays for constants.
-  v8::HandleScope scope;
+  v8::V8::Initialize();
+  ContextInitializer initializer;
 
   RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 0);
 
@@ -761,23 +852,21 @@
   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);
+  RegExpMacroAssemblerIA32::Result result =
+      RegExpMacroAssemblerIA32::Execute(*code,
+                                        seq_input.location(),
+                                        start_offset,
+                                        end_offset,
+                                        NULL,
+                                        true);
 
-  CHECK(!success);
+  CHECK_EQ(RegExpMacroAssemblerIA32::FAILURE, result);
 }
 
 
-TEST(MacroAssemblerIA32BackReference) {
-  V8::Initialize(NULL);
-
-  // regexp-macro-assembler-ia32 needs a handle scope to allocate
-  // byte-arrays for constants.
-  v8::HandleScope scope;
+TEST(MacroAssemblerIA32BackReferenceASCII) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
 
   RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 3);
 
@@ -807,26 +896,75 @@
   int end_offset = start_offset + seq_input->length();
 
   int output[3];
-  bool success = RegExpMacroAssemblerIA32::Execute(*code,
-                                                   seq_input.location(),
-                                                   start_offset,
-                                                   end_offset,
-                                                   output,
-                                                   true);
+  RegExpMacroAssemblerIA32::Result result =
+      RegExpMacroAssemblerIA32::Execute(*code,
+                                        seq_input.location(),
+                                        start_offset,
+                                        end_offset,
+                                        output,
+                                        true);
 
-  CHECK(success);
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
   CHECK_EQ(0, output[0]);
   CHECK_EQ(2, output[1]);
   CHECK_EQ(6, output[2]);
 }
 
 
-TEST(MacroAssemblerIA32AtStart) {
-  V8::Initialize(NULL);
+TEST(MacroAssemblerIA32BackReferenceUC16) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
 
-  // regexp-macro-assembler-ia32 needs a handle scope to allocate
-  // byte-arrays for constants.
-  v8::HandleScope scope;
+  RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::UC16, 3);
+
+  m.WriteCurrentPositionToRegister(0, 0);
+  m.AdvanceCurrentPosition(2);
+  m.WriteCurrentPositionToRegister(1, 0);
+  Label nomatch;
+  m.CheckNotBackReference(0, &nomatch);
+  m.Fail();
+  m.Bind(&nomatch);
+  m.AdvanceCurrentPosition(2);
+  Label missing_match;
+  m.CheckNotBackReference(0, &missing_match);
+  m.WriteCurrentPositionToRegister(2, 0);
+  m.Succeed();
+  m.Bind(&missing_match);
+  m.Fail();
+
+  Handle<String> source = Factory::NewStringFromAscii(CStrVector("^(..)..\1"));
+  Handle<Object> code_object = m.GetCode(source);
+  Handle<Code> code = Handle<Code>::cast(code_object);
+
+  const uc16 input_data[6] = {'f', 0x2028, 'o', 'o', 'f', 0x2028};
+  Handle<String> input =
+      Factory::NewStringFromTwoByte(Vector<const uc16>(input_data, 6));
+  Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::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() * sizeof(input_data[0]);
+
+  int output[3];
+  RegExpMacroAssemblerIA32::Result result =
+      RegExpMacroAssemblerIA32::Execute(*code,
+                                        seq_input.location(),
+                                        start_offset,
+                                        end_offset,
+                                        output,
+                                        true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
+  CHECK_EQ(0, output[0]);
+  CHECK_EQ(2, output[1]);
+  CHECK_EQ(6, output[2]);
+}
+
+
+
+TEST(MacroAssemblerIA32AtStart) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
 
   RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 0);
 
@@ -861,35 +999,33 @@
   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);
+  RegExpMacroAssemblerIA32::Result result =
+      RegExpMacroAssemblerIA32::Execute(*code,
+                                        seq_input.location(),
+                                        start_offset,
+                                        end_offset,
+                                        NULL,
+                                        true);
 
-  CHECK(success);
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
 
   start_offset += 3;
-  success = RegExpMacroAssemblerIA32::Execute(*code,
+  result = RegExpMacroAssemblerIA32::Execute(*code,
                                               seq_input.location(),
                                               start_offset,
                                               end_offset,
                                               NULL,
                                               false);
 
-  CHECK(success);
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
 }
 
 
 
 
 TEST(MacroAssemblerIA32BackRefNoCase) {
-  V8::Initialize(NULL);
-
-  // regexp-macro-assembler-ia32 needs a handle scope to allocate
-  // byte-arrays for constants.
-  v8::HandleScope scope;
+  v8::V8::Initialize();
+  ContextInitializer initializer;
 
   RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 4);
 
@@ -928,14 +1064,15 @@
   int end_offset = start_offset + seq_input->length();
 
   int output[4];
-  bool success = RegExpMacroAssemblerIA32::Execute(*code,
-                                                   seq_input.location(),
-                                                   start_offset,
-                                                   end_offset,
-                                                   output,
-                                                   true);
+  RegExpMacroAssemblerIA32::Result result =
+      RegExpMacroAssemblerIA32::Execute(*code,
+                                        seq_input.location(),
+                                        start_offset,
+                                        end_offset,
+                                        output,
+                                        true);
 
-  CHECK(success);
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
   CHECK_EQ(0, output[0]);
   CHECK_EQ(12, output[1]);
   CHECK_EQ(0, output[2]);
@@ -945,11 +1082,8 @@
 
 
 TEST(MacroAssemblerIA32Registers) {
-  V8::Initialize(NULL);
-
-  // regexp-macro-assembler-ia32 needs a handle scope to allocate
-  // byte-arrays for constants.
-  v8::HandleScope scope;
+  v8::V8::Initialize();
+  ContextInitializer initializer;
 
   RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 5);
 
@@ -1031,14 +1165,15 @@
   int end_offset = start_offset + seq_input->length();
 
   int output[5];
-  bool success = RegExpMacroAssemblerIA32::Execute(*code,
-                                                   seq_input.location(),
-                                                   start_offset,
-                                                   end_offset,
-                                                   output,
-                                                   true);
+  RegExpMacroAssemblerIA32::Result result =
+      RegExpMacroAssemblerIA32::Execute(*code,
+                                        seq_input.location(),
+                                        start_offset,
+                                        end_offset,
+                                        output,
+                                        true);
 
-  CHECK(success);
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
   CHECK_EQ(0, output[0]);
   CHECK_EQ(3, output[1]);
   CHECK_EQ(6, output[2]);
@@ -1046,6 +1181,45 @@
   CHECK_EQ(9, output[4]);
 }
 
+
+TEST(MacroAssemblerIA32StackOverflow) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
+
+  RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 0);
+
+  Label loop;
+  m.Bind(&loop);
+  m.PushBacktrack(&loop);
+  m.GoTo(&loop);
+
+  Handle<String> source =
+      Factory::NewStringFromAscii(CStrVector("<stack overflow test>"));
+  Handle<Object> code_object = m.GetCode(source);
+  Handle<Code> code = Handle<Code>::cast(code_object);
+
+  // String long enough for test (content doesn't matter).
+  Handle<String> input =
+      Factory::NewStringFromAscii(CStrVector("dummy"));
+  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();
+
+  RegExpMacroAssemblerIA32::Result result =
+      RegExpMacroAssemblerIA32::Execute(*code,
+                                        seq_input.location(),
+                                        start_offset,
+                                        end_offset,
+                                        NULL,
+                                        true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::EXCEPTION, result);
+  CHECK(Top::has_pending_exception());
+  Top::clear_pending_exception();
+}
+
+
 #endif  // !defined ARM
 
 TEST(AddInverseToTable) {
@@ -1292,5 +1466,5 @@
 
 TEST(Graph) {
   V8::Initialize(NULL);
-  Execute("\\bboy\\b", false, true, true);
+  Execute("\\b\\w+\\b", false, true, true);
 }