Fixed exception reporting bug where certain exceptions were incorrectly reported as uncaught.

Improved the memory allocation strategy used during compilation to make running out of memory when compiling huge scripts less likely.

Optimized String.replace by avoiding the construction of certain sub strings.

Fixed bug in code generation for large switch statements on ARM.

Fixed bug that caused V8 to change the global object template passed in by the user.

Changed the API for creating object groups used during garbage collection.  Entire object groups are now passed to V8 instead of individual members of the groups.


git-svn-id: http://v8.googlecode.com/svn/trunk@968 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/SConscript b/src/SConscript
index d985865..d008bdd 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -51,12 +51,12 @@
     'zone.cc'
   ],
   'arch:arm':  ['assembler-arm.cc', 'builtins-arm.cc', 'codegen-arm.cc',
-      'cpu-arm.cc', 'disasm-arm.cc', 'frames-arm.cc', 'ic-arm.cc',
-      'macro-assembler-arm.cc', 'regexp-macro-assembler-arm.cc', 
+      'cpu-arm.cc', 'debug-arm.cc', 'disasm-arm.cc', 'frames-arm.cc',
+      'ic-arm.cc', 'macro-assembler-arm.cc', 'regexp-macro-assembler-arm.cc', 
       'stub-cache-arm.cc'],
   'arch:ia32': ['assembler-ia32.cc', 'builtins-ia32.cc', 'codegen-ia32.cc',
-      'cpu-ia32.cc', 'disasm-ia32.cc', 'frames-ia32.cc', 'ic-ia32.cc',
-      'macro-assembler-ia32.cc', 'regexp-macro-assembler-ia32.cc',
+      'cpu-ia32.cc', 'debug-ia32.cc', 'disasm-ia32.cc', 'frames-ia32.cc',
+      'ic-ia32.cc', 'macro-assembler-ia32.cc', 'regexp-macro-assembler-ia32.cc',
       'stub-cache-ia32.cc'],
   'simulator:arm': ['simulator-arm.cc'],
   'os:freebsd': ['platform-freebsd.cc'],
diff --git a/src/api.cc b/src/api.cc
index 885c683..546268a 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2203,7 +2203,7 @@
 
 
 const char* v8::V8::GetVersion() {
-  return "0.4.5";
+  return "0.4.6";
 }
 
 
@@ -2227,39 +2227,52 @@
   LOG_API("Context::New");
   ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
 
-  // Make sure that the global_template has a constructor.
+  v8::Handle<ObjectTemplate> proxy_template = global_template;
+  i::Handle<i::FunctionTemplateInfo> proxy_constructor;
+  i::Handle<i::FunctionTemplateInfo> global_constructor;
+
   if (!global_template.IsEmpty()) {
-    i::Handle<i::FunctionTemplateInfo> constructor =
-        EnsureConstructor(Utils::OpenHandle(*global_template));
+    // Make sure that the global_template has a constructor.
+    global_constructor = EnsureConstructor(Utils::OpenHandle(*global_template));
 
-    // Create a fresh template for global proxy object.
-    Local<ObjectTemplate> proxy_template = ObjectTemplate::New();
+    // Create a fresh template for the global proxy object.
+    proxy_template = ObjectTemplate::New();
+    proxy_constructor = EnsureConstructor(Utils::OpenHandle(*proxy_template));
 
-    i::Handle<i::FunctionTemplateInfo> proxy_constructor =
-      EnsureConstructor(Utils::OpenHandle(*proxy_template));
-
-    // Set the global template to be the prototype template
-    // of global proxy template.
+    // Set the global template to be the prototype template of global
+    // proxy template.
     proxy_constructor->set_prototype_template(
         *Utils::OpenHandle(*global_template));
 
-    // Migrate security handlers from global_template to proxy_template.
-    if (!constructor->access_check_info()->IsUndefined()) {
-       proxy_constructor->set_access_check_info(
-           constructor->access_check_info());
-       proxy_constructor->set_needs_access_check(true);
-
-       // Remove access check info from global_template.
-       constructor->set_needs_access_check(false);
-       constructor->set_access_check_info(i::Heap::undefined_value());
+    // Migrate security handlers from global_template to
+    // proxy_template.  Temporarily removing access check information
+    // from the global template.
+    if (!global_constructor->access_check_info()->IsUndefined()) {
+      proxy_constructor->set_access_check_info(
+          global_constructor->access_check_info());
+      proxy_constructor->set_needs_access_check(
+          global_constructor->needs_access_check());
+      global_constructor->set_needs_access_check(false);
+      global_constructor->set_access_check_info(i::Heap::undefined_value());
     }
-
-    global_template = proxy_template;
   }
 
+  // Create the environment.
   i::Handle<i::Context> env = i::Bootstrapper::CreateEnvironment(
       Utils::OpenHandle(*global_object),
-      global_template, extensions);
+      proxy_template,
+      extensions);
+
+  // Restore the access check info on the global template.
+  if (!global_template.IsEmpty()) {
+    ASSERT(!global_constructor.is_null());
+    ASSERT(!proxy_constructor.is_null());
+    global_constructor->set_access_check_info(
+        proxy_constructor->access_check_info());
+    global_constructor->set_needs_access_check(
+        proxy_constructor->needs_access_check());
+  }
+
   if (!ApiCheck(!env.is_null(),
                 "v8::Context::New()",
                 "Could not initialize environment"))
@@ -2628,9 +2641,10 @@
 }
 
 
-void V8::AddObjectToGroup(void* group_id, Persistent<Object> obj) {
-  if (IsDeadCheck("v8::V8::AddObjectToGroup()")) return;
-  i::GlobalHandles::AddToGroup(group_id, reinterpret_cast<i::Object**>(*obj));
+void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
+  if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
+  STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
+  i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
 }
 
 
diff --git a/src/assembler-arm.h b/src/assembler-arm.h
index 1aebc42..bd70066 100644
--- a/src/assembler-arm.h
+++ b/src/assembler-arm.h
@@ -672,6 +672,14 @@
   // Patch branch instruction at pos to branch to given branch target pos
   void target_at_put(int pos, int target_pos);
 
+  // Check if is time to emit a constant pool for pending reloc info entries
+  void CheckConstPool(bool force_emit, bool require_jump);
+
+  // Block the emission of the constant pool before pc_offset
+  void BlockConstPoolBefore(int pc_offset) {
+    if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset;
+  }
+
  private:
   // Code buffer:
   // The buffer into which code and relocation info are generated.
@@ -769,14 +777,6 @@
 
   // Record reloc info for current pc_
   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
-
-  // Check if is time to emit a constant pool for pending reloc info entries
-  void CheckConstPool(bool force_emit, bool require_jump);
-
-  // Block the emission of the constant pool before pc_offset
-  void BlockConstPoolBefore(int pc_offset) {
-    if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset;
-  }
 };
 
 } }  // namespace v8::internal
diff --git a/src/assembler.cc b/src/assembler.cc
index 1fd0dc3..c56eb2f 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -450,7 +450,7 @@
            ref_encoder.NameOfAddress(*target_reference_address()),
            *target_reference_address());
   } else if (IsCodeTarget(rmode_)) {
-    Code* code = Debug::GetCodeTarget(target_address());
+    Code* code = Code::GetCodeFromTargetAddress(target_address());
     PrintF(" (%s)  (%p)", Code::Kind2String(code->kind()), target_address());
   } else if (IsPosition(rmode_)) {
     PrintF("  (%d)", data());
diff --git a/src/ast.h b/src/ast.h
index a301ab7..528c4f5 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1216,8 +1216,7 @@
   virtual ~RegExpTree() { }
   virtual void* Accept(RegExpVisitor* visitor, void* data) = 0;
   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
-                             RegExpNode* on_success,
-                             RegExpNode* on_failure) = 0;
+                             RegExpNode* on_success) = 0;
   virtual bool IsTextElement() { return false; }
   virtual void AppendToText(RegExpText* text);
   SmartPointer<const char> ToString();
@@ -1235,8 +1234,7 @@
       : alternatives_(alternatives) { }
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
-                             RegExpNode* on_success,
-                             RegExpNode* on_failure);
+                             RegExpNode* on_success);
   virtual RegExpDisjunction* AsDisjunction();
   virtual bool IsDisjunction();
   ZoneList<RegExpTree*>* alternatives() { return alternatives_; }
@@ -1250,8 +1248,7 @@
   explicit RegExpAlternative(ZoneList<RegExpTree*>* nodes) : nodes_(nodes) { }
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
-                             RegExpNode* on_success,
-                             RegExpNode* on_failure);
+                             RegExpNode* on_success);
   virtual RegExpAlternative* AsAlternative();
   virtual bool IsAlternative();
   ZoneList<RegExpTree*>* nodes() { return nodes_; }
@@ -1265,8 +1262,7 @@
   RegExpText() : elements_(2) { }
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
-                             RegExpNode* on_success,
-                             RegExpNode* on_failure);
+                             RegExpNode* on_success);
   virtual RegExpText* AsText();
   virtual bool IsText();
   virtual bool IsTextElement() { return true; }
@@ -1291,8 +1287,7 @@
   explicit RegExpAssertion(Type type) : type_(type) { }
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
-                             RegExpNode* on_success,
-                             RegExpNode* on_failure);
+                             RegExpNode* on_success);
   virtual RegExpAssertion* AsAssertion();
   virtual bool IsAssertion();
   Type type() { return type_; }
@@ -1313,8 +1308,7 @@
   }
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
-                             RegExpNode* on_success,
-                             RegExpNode* on_failure);
+                             RegExpNode* on_success);
   virtual RegExpCharacterClass* AsCharacterClass();
   virtual bool IsCharacterClass();
   virtual bool IsTextElement() { return true; }
@@ -1332,8 +1326,7 @@
   explicit RegExpAtom(Vector<const uc16> data) : data_(data) { }
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
-                             RegExpNode* on_success,
-                             RegExpNode* on_failure);
+                             RegExpNode* on_success);
   virtual RegExpAtom* AsAtom();
   virtual bool IsAtom();
   virtual bool IsTextElement() { return true; }
@@ -1353,15 +1346,13 @@
         body_(body) { }
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
-                             RegExpNode* on_success,
-                             RegExpNode* on_failure);
+                             RegExpNode* on_success);
   static RegExpNode* ToNode(int min,
                             int max,
                             bool is_greedy,
                             RegExpTree* body,
                             RegExpCompiler* compiler,
-                            RegExpNode* on_success,
-                            RegExpNode* on_failure);
+                            RegExpNode* on_success);
   virtual RegExpQuantifier* AsQuantifier();
   virtual bool IsQuantifier();
   int min() { return min_; }
@@ -1391,13 +1382,11 @@
       : body_(body), index_(index), available_(CAPTURE_AVAILABLE) { }
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
-                             RegExpNode* on_success,
-                             RegExpNode* on_failure);
+                             RegExpNode* on_success);
   static RegExpNode* ToNode(RegExpTree* body,
                             int index,
                             RegExpCompiler* compiler,
-                            RegExpNode* on_success,
-                            RegExpNode* on_failure);
+                            RegExpNode* on_success);
   virtual RegExpCapture* AsCapture();
   virtual bool IsCapture();
   RegExpTree* body() { return body_; }
@@ -1422,8 +1411,7 @@
         is_positive_(is_positive) { }
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
-                             RegExpNode* on_success,
-                             RegExpNode* on_failure);
+                             RegExpNode* on_success);
   virtual RegExpLookahead* AsLookahead();
   virtual bool IsLookahead();
   RegExpTree* body() { return body_; }
@@ -1440,8 +1428,7 @@
       : capture_(capture) { }
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
-                             RegExpNode* on_success,
-                             RegExpNode* on_failure);
+                             RegExpNode* on_success);
   virtual RegExpBackReference* AsBackReference();
   virtual bool IsBackReference();
   int index() { return capture_->index(); }
@@ -1456,8 +1443,7 @@
   RegExpEmpty() { }
   virtual void* Accept(RegExpVisitor* visitor, void* data);
   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
-                             RegExpNode* on_success,
-                             RegExpNode* on_failure);
+                             RegExpNode* on_success);
   virtual RegExpEmpty* AsEmpty();
   virtual bool IsEmpty();
   static RegExpEmpty* GetInstance() { return &kInstance; }
diff --git a/src/builtins-arm.cc b/src/builtins-arm.cc
index 503a2d3..caddfb9 100644
--- a/src/builtins-arm.cc
+++ b/src/builtins-arm.cc
@@ -653,133 +653,6 @@
 }
 
 
-static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
-                                          RegList pointer_regs) {
-  // Save the content of all general purpose registers in memory. This copy in
-  // memory is later pushed onto the JS expression stack for the fake JS frame
-  // generated and also to the C frame generated on top of that. In the JS
-  // frame ONLY the registers containing pointers will be pushed on the
-  // expression stack. This causes the GC to update these  pointers so that
-  // they will have the correct value when returning from the debugger.
-  __ SaveRegistersToMemory(kJSCallerSaved);
-
-  __ EnterInternalFrame();
-
-  // Store the registers containing object pointers on the expression stack to
-  // make sure that these are correctly updated during GC.
-  // Use sp as base to push.
-  __ CopyRegistersFromMemoryToStack(sp, pointer_regs);
-
-#ifdef DEBUG
-  __ RecordComment("// Calling from debug break to runtime - come in - over");
-#endif
-  __ mov(r0, Operand(0));  // no arguments
-  __ mov(r1, Operand(ExternalReference::debug_break()));
-
-  CEntryDebugBreakStub ceb;
-  __ CallStub(&ceb);
-
-  // Restore the register values containing object pointers from the expression
-  // stack in the reverse order as they where pushed.
-  // Use sp as base to pop.
-  __ CopyRegistersFromStackToMemory(sp, r3, pointer_regs);
-
-  __ LeaveInternalFrame();
-
-  // Inlined ExitJSFrame ends here.
-
-  // Finally restore all registers.
-  __ RestoreRegistersFromMemory(kJSCallerSaved);
-
-  // Now that the break point has been handled, resume normal execution by
-  // jumping to the target address intended by the caller and that was
-  // overwritten by the address of DebugBreakXXX.
-  __ mov(ip, Operand(ExternalReference(Debug_Address::AfterBreakTarget())));
-  __ ldr(ip, MemOperand(ip));
-  __ Jump(ip);
-}
-
-
-void Builtins::Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
-  // Calling convention for IC load (from ic-arm.cc).
-  // ----------- S t a t e -------------
-  //  -- r0    : receiver
-  //  -- r2    : name
-  //  -- lr    : return address
-  //  -- [sp]  : receiver
-  // -----------------------------------
-  // Registers r0 and r2 contain objects that needs to be pushed on the
-  // expression stack of the fake JS frame.
-  Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit());
-}
-
-
-void Builtins::Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
-  // Calling convention for IC store (from ic-arm.cc).
-  // ----------- S t a t e -------------
-  //  -- r0    : receiver
-  //  -- r2    : name
-  //  -- lr    : return address
-  //  -- [sp]  : receiver
-  // -----------------------------------
-  // Registers r0 and r2 contain objects that needs to be pushed on the
-  // expression stack of the fake JS frame.
-  Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit());
-}
-
-
-void Builtins::Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
-  // Keyed load IC not implemented on ARM.
-}
-
-
-void Builtins::Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
-  // Keyed store IC not implemented on ARM.
-}
-
-
-void Builtins::Generate_CallIC_DebugBreak(MacroAssembler* masm) {
-  // Calling convention for IC call (from ic-arm.cc)
-  // ----------- S t a t e -------------
-  //  -- r0: number of arguments
-  //  -- r1: receiver
-  //  -- lr: return address
-  // -----------------------------------
-  // Register r1 contains an object that needs to be pushed on the expression
-  // stack of the fake JS frame. r0 is the actual number of arguments not
-  // encoded as a smi, therefore it cannot be on the expression stack of the
-  // fake JS frame as it can easily be an invalid pointer (e.g. 1). r0 will be
-  // pushed on the stack of the C frame and restored from there.
-  Generate_DebugBreakCallHelper(masm, r1.bit());
-}
-
-
-void Builtins::Generate_ConstructCall_DebugBreak(MacroAssembler* masm) {
-  // In places other than IC call sites it is expected that r0 is TOS which
-  // is an object - this is not generally the case so this should be used with
-  // care.
-  Generate_DebugBreakCallHelper(masm, r0.bit());
-}
-
-
-void Builtins::Generate_Return_DebugBreak(MacroAssembler* masm) {
-  // In places other than IC call sites it is expected that r0 is TOS which
-  // is an object - this is not generally the case so this should be used with
-  // care.
-  Generate_DebugBreakCallHelper(masm, r0.bit());
-}
-
-
-void Builtins::Generate_Return_DebugBreakEntry(MacroAssembler* masm) {
-  // Generate nothing as this handling of debug break return is not done this
-  // way on ARM  - yet.
-}
-
-void Builtins::Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) {
-  // Generate nothing as CodeStub CallFunction is not used on ARM.
-}
-
-
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/builtins-ia32.cc b/src/builtins-ia32.cc
index 55e10f3..807a4bb 100644
--- a/src/builtins-ia32.cc
+++ b/src/builtins-ia32.cc
@@ -28,8 +28,6 @@
 #include "v8.h"
 
 #include "codegen-inl.h"
-#include "debug.h"
-#include "runtime.h"
 
 namespace v8 { namespace internal {
 
@@ -756,147 +754,6 @@
 }
 
 
-static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
-                                          RegList pointer_regs,
-                                          bool convert_call_to_jmp) {
-  // Save the content of all general purpose registers in memory. This copy in
-  // memory is later pushed onto the JS expression stack for the fake JS frame
-  // generated and also to the C frame generated on top of that. In the JS
-  // frame ONLY the registers containing pointers will be pushed on the
-  // expression stack. This causes the GC to update these pointers so that
-  // they will have the correct value when returning from the debugger.
-  __ SaveRegistersToMemory(kJSCallerSaved);
-
-  // Enter an internal frame.
-  __ EnterInternalFrame();
-
-  // Store the registers containing object pointers on the expression stack to
-  // make sure that these are correctly updated during GC.
-  __ PushRegistersFromMemory(pointer_regs);
-
-#ifdef DEBUG
-  __ RecordComment("// Calling from debug break to runtime - come in - over");
-#endif
-  __ Set(eax, Immediate(0));  // no arguments
-  __ mov(ebx, Immediate(ExternalReference::debug_break()));
-
-  CEntryDebugBreakStub ceb;
-  __ CallStub(&ceb);
-
-  // Restore the register values containing object pointers from the expression
-  // stack in the reverse order as they where pushed.
-  __ PopRegistersToMemory(pointer_regs);
-
-  // Get rid of the internal frame.
-  __ LeaveInternalFrame();
-
-  // If this call did not replace a call but patched other code then there will
-  // be an unwanted return address left on the stack. Here we get rid of that.
-  if (convert_call_to_jmp) {
-    __ pop(eax);
-  }
-
-  // Finally restore all registers.
-  __ RestoreRegistersFromMemory(kJSCallerSaved);
-
-  // Now that the break point has been handled, resume normal execution by
-  // jumping to the target address intended by the caller and that was
-  // overwritten by the address of DebugBreakXXX.
-  ExternalReference after_break_target =
-      ExternalReference(Debug_Address::AfterBreakTarget());
-  __ jmp(Operand::StaticVariable(after_break_target));
-}
-
-
-void Builtins::Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
-  // Register state for IC load call (from ic-ia32.cc).
-  // ----------- S t a t e -------------
-  //  -- ecx    : name
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, ecx.bit(), false);
-}
-
-
-void Builtins::Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
-  // REgister state for IC store call (from ic-ia32.cc).
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : name
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit(), false);
-}
-
-
-void Builtins::Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
-  // Register state for keyed IC load call (from ic-ia32.cc).
-  // ----------- S t a t e -------------
-  //  No registers used on entry.
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, 0, false);
-}
-
-
-void Builtins::Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
-  // Register state for keyed IC load call (from ic-ia32.cc).
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  // -----------------------------------
-  // Register eax contains an object that needs to be pushed on the
-  // expression stack of the fake JS frame.
-  Generate_DebugBreakCallHelper(masm, eax.bit(), false);
-}
-
-
-void Builtins::Generate_CallIC_DebugBreak(MacroAssembler* masm) {
-  // Register state for keyed IC call call (from ic-ia32.cc)
-  // ----------- S t a t e -------------
-  //  -- eax: number of arguments
-  // -----------------------------------
-  // The number of arguments in eax is not smi encoded.
-  Generate_DebugBreakCallHelper(masm, 0, false);
-}
-
-
-void Builtins::Generate_ConstructCall_DebugBreak(MacroAssembler* masm) {
-  // Register state just before return from JS function (from codegen-ia32.cc).
-  // eax is the actual number of arguments not encoded as a smi see comment
-  // above IC call.
-  // ----------- S t a t e -------------
-  //  -- eax: number of arguments
-  // -----------------------------------
-  // The number of arguments in eax is not smi encoded.
-  Generate_DebugBreakCallHelper(masm, 0, false);
-}
-
-
-void Builtins::Generate_Return_DebugBreak(MacroAssembler* masm) {
-  // Register state just before return from JS function (from codegen-ia32.cc).
-  // ----------- S t a t e -------------
-  //  -- eax: return value
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, eax.bit(), true);
-}
-
-
-void Builtins::Generate_Return_DebugBreakEntry(MacroAssembler* masm) {
-  // OK to clobber ebx as we are returning from a JS function in the code
-  // generated by Ia32CodeGenerator::ExitJSFrame.
-  ExternalReference debug_break_return =
-      ExternalReference(Debug_Address::DebugBreakReturn());
-  __ mov(ebx, Operand::StaticVariable(debug_break_return));
-  __ add(Operand(ebx), Immediate(Code::kHeaderSize - kHeapObjectTag));
-  __ jmp(Operand(ebx));
-}
-
-
-void Builtins::Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) {
-  // Register state for stub CallFunction (from CallFunctionStub in ic-ia32.cc).
-  // ----------- S t a t e -------------
-  //  No registers used on entry.
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, 0, false);
-}
-
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/builtins.cc b/src/builtins.cc
index c44b2e2..c905489 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -559,6 +559,46 @@
 }
 
 
+static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateLoadICDebugBreak(masm);
+}
+
+
+static void Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateStoreICDebugBreak(masm);
+}
+
+
+static void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateKeyedLoadICDebugBreak(masm);
+}
+
+
+static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateKeyedStoreICDebugBreak(masm);
+}
+
+
+static void Generate_ConstructCall_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateConstructCallDebugBreak(masm);
+}
+
+
+static void Generate_Return_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateReturnDebugBreak(masm);
+}
+
+
+static void Generate_Return_DebugBreakEntry(MacroAssembler* masm) {
+  Debug::GenerateReturnDebugBreakEntry(masm);
+}
+
+
+static void Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateStubNoRegistersDebugBreak(masm);
+}
+
+
 Object* Builtins::builtins_[builtin_count] = { NULL, };
 const char* Builtins::names_[builtin_count] = { NULL, };
 
@@ -615,6 +655,7 @@
   static BuiltinDesc functions[] = {
       BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
       BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
+      BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
       // Terminator:
       { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0) }
   };
diff --git a/src/builtins.h b/src/builtins.h
index bcc3e89..fa443fa 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -52,11 +52,6 @@
   V(JSEntryTrampoline,          BUILTIN, UNINITIALIZED)        \
   V(JSConstructEntryTrampoline, BUILTIN, UNINITIALIZED)        \
                                                                \
-  V(Return_DebugBreak,          BUILTIN, DEBUG_BREAK)          \
-  V(Return_DebugBreakEntry,     BUILTIN, DEBUG_BREAK)          \
-  V(ConstructCall_DebugBreak,   BUILTIN, DEBUG_BREAK)          \
-  V(StubNoRegisters_DebugBreak, BUILTIN, DEBUG_BREAK)          \
-                                                               \
   V(LoadIC_Miss,                BUILTIN, UNINITIALIZED)        \
   V(KeyedLoadIC_Miss,           BUILTIN, UNINITIALIZED)        \
   V(StoreIC_Miss,               BUILTIN, UNINITIALIZED)        \
@@ -72,26 +67,34 @@
   V(LoadIC_StringLength,        LOAD_IC, MONOMORPHIC)          \
   V(LoadIC_FunctionPrototype,   LOAD_IC, MONOMORPHIC)          \
   V(LoadIC_Megamorphic,         LOAD_IC, MEGAMORPHIC)          \
-  V(LoadIC_DebugBreak,          LOAD_IC, DEBUG_BREAK)          \
                                                                \
   V(KeyedLoadIC_Initialize,     KEYED_LOAD_IC, UNINITIALIZED)  \
   V(KeyedLoadIC_PreMonomorphic, KEYED_LOAD_IC, PREMONOMORPHIC) \
   V(KeyedLoadIC_Generic,        KEYED_LOAD_IC, MEGAMORPHIC)    \
-  V(KeyedLoadIC_DebugBreak,     KEYED_LOAD_IC, DEBUG_BREAK)    \
                                                                \
   V(StoreIC_Initialize,         STORE_IC, UNINITIALIZED)       \
   V(StoreIC_Megamorphic,        STORE_IC, MEGAMORPHIC)         \
-  V(StoreIC_DebugBreak,         STORE_IC, DEBUG_BREAK)         \
                                                                \
   V(KeyedStoreIC_Initialize,    KEYED_STORE_IC, UNINITIALIZED) \
   V(KeyedStoreIC_Generic,       KEYED_STORE_IC, MEGAMORPHIC)   \
-  V(KeyedStoreIC_DebugBreak,    KEYED_STORE_IC, DEBUG_BREAK)   \
                                                                \
   /* Uses KeyedLoadIC_Initialize; must be after in list. */    \
   V(FunctionCall,               BUILTIN, UNINITIALIZED)        \
   V(FunctionApply,              BUILTIN, UNINITIALIZED)
 
 
+// Define list of builtins used by the debugger implemented in assembly.
+#define BUILTIN_LIST_DEBUG_A(V)                                \
+  V(Return_DebugBreak,          BUILTIN, DEBUG_BREAK)          \
+  V(Return_DebugBreakEntry,     BUILTIN, DEBUG_BREAK)          \
+  V(ConstructCall_DebugBreak,   BUILTIN, DEBUG_BREAK)          \
+  V(StubNoRegisters_DebugBreak, BUILTIN, DEBUG_BREAK)          \
+  V(LoadIC_DebugBreak,          LOAD_IC, DEBUG_BREAK)          \
+  V(KeyedLoadIC_DebugBreak,     KEYED_LOAD_IC, DEBUG_BREAK)    \
+  V(StoreIC_DebugBreak,         STORE_IC, DEBUG_BREAK)         \
+  V(KeyedStoreIC_DebugBreak,    KEYED_STORE_IC, DEBUG_BREAK)
+
+
 // Define list of builtins implemented in JavaScript.
 #define BUILTINS_LIST_JS(V)    \
   V(EQUALS, 1)                 \
@@ -146,6 +149,7 @@
 #define DEF_ENUM_A(name, kind, state) name,
     BUILTIN_LIST_C(DEF_ENUM_C)
     BUILTIN_LIST_A(DEF_ENUM_A)
+    BUILTIN_LIST_DEBUG_A(DEF_ENUM_A)
 #undef DEF_ENUM_C
 #undef DEF_ENUM_A
     builtin_count
@@ -184,9 +188,6 @@
   static Handle<Code> GetCode(JavaScript id, bool* resolved);
   static int NumberOfJavaScriptBuiltins() { return id_count; }
 
-  // Called from stub-cache.cc.
-  static void Generate_CallIC_DebugBreak(MacroAssembler* masm);
-
   static Object* builtin_passed_function;
 
  private:
@@ -209,15 +210,6 @@
 
   static void Generate_FunctionCall(MacroAssembler* masm);
   static void Generate_FunctionApply(MacroAssembler* masm);
-
-  static void Generate_LoadIC_DebugBreak(MacroAssembler* masm);
-  static void Generate_StoreIC_DebugBreak(MacroAssembler* masm);
-  static void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm);
-  static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm);
-  static void Generate_ConstructCall_DebugBreak(MacroAssembler* masm);
-  static void Generate_Return_DebugBreak(MacroAssembler* masm);
-  static void Generate_Return_DebugBreakEntry(MacroAssembler* masm);
-  static void Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm);
 };
 
 } }  // namespace v8::internal
diff --git a/src/bytecodes-irregexp.h b/src/bytecodes-irregexp.h
index 33a2f24..64a65cb 100644
--- a/src/bytecodes-irregexp.h
+++ b/src/bytecodes-irregexp.h
@@ -50,22 +50,24 @@
 V(ADVANCE_CP,        15, 5) /* advance_cp offset32                          */ \
 V(GOTO,              16, 5) /* goto addr32                                  */ \
 V(LOAD_CURRENT_CHAR, 17, 9) /* load offset32 addr32                         */ \
-V(CHECK_CHAR,        18, 7) /* check_char uc16 addr32                       */ \
-V(CHECK_NOT_CHAR,    19, 7) /* check_not_char uc16 addr32                   */ \
-V(OR_CHECK_NOT_CHAR, 20, 9) /* or_check_not_char uc16 uc16 addr32           */ \
-V(MINUS_OR_CHECK_NOT_CHAR, 21, 9) /* minus_or_check_not_char uc16 uc16 ad...*/ \
-V(CHECK_LT,          22, 7) /* check_lt uc16 addr32                         */ \
-V(CHECK_GT,          23, 7) /* check_gr uc16 addr32                         */ \
-V(CHECK_NOT_BACK_REF, 24, 6) /* check_not_back_ref capture_idx addr32       */ \
-V(CHECK_NOT_BACK_REF_NO_CASE, 25, 6) /* check_not_back_ref_no_case captu... */ \
-V(CHECK_NOT_REGS_EQUAL, 26, 7) /* check_not_regs_equal reg1 reg2 addr32     */ \
-V(LOOKUP_MAP1,       27, 11) /* l_map1 start16 bit_map_addr32 addr32        */ \
-V(LOOKUP_MAP2,       28, 99) /* l_map2 start16 half_nibble_map_addr32*      */ \
-V(LOOKUP_MAP8,       29, 99) /* l_map8 start16 byte_map addr32*             */ \
-V(LOOKUP_HI_MAP8,    30, 99) /* l_himap8 start8 byte_map_addr32 addr32*     */ \
-V(CHECK_REGISTER_LT, 31, 8) /* check_reg_lt register_index value16 addr32   */ \
-V(CHECK_REGISTER_GE, 32, 8) /* check_reg_ge register_index value16 addr32   */ \
-V(CHECK_NOT_AT_START, 33, 5) /* check_not_at_start addr32                   */
+V(LOAD_CURRENT_CHAR_UNCHECKED, 18, 5) /* load offset32                      */ \
+V(CHECK_CHAR,        19, 7) /* check_char uc16 addr32                       */ \
+V(CHECK_NOT_CHAR,    20, 7) /* check_not_char uc16 addr32                   */ \
+V(OR_CHECK_NOT_CHAR, 21, 9) /* or_check_not_char uc16 uc16 addr32           */ \
+V(MINUS_OR_CHECK_NOT_CHAR, 22, 9) /* minus_or_check_not_char uc16 uc16 ad...*/ \
+V(CHECK_LT,          23, 7) /* check_lt uc16 addr32                         */ \
+V(CHECK_GT,          24, 7) /* check_gr uc16 addr32                         */ \
+V(CHECK_NOT_BACK_REF, 25, 6) /* check_not_back_ref capture_idx addr32       */ \
+V(CHECK_NOT_BACK_REF_NO_CASE, 26, 6) /* check_not_back_ref_no_case captu... */ \
+V(CHECK_NOT_REGS_EQUAL, 27, 7) /* check_not_regs_equal reg1 reg2 addr32     */ \
+V(LOOKUP_MAP1,       28, 11) /* l_map1 start16 bit_map_addr32 addr32        */ \
+V(LOOKUP_MAP2,       29, 99) /* l_map2 start16 half_nibble_map_addr32*      */ \
+V(LOOKUP_MAP8,       30, 99) /* l_map8 start16 byte_map addr32*             */ \
+V(LOOKUP_HI_MAP8,    31, 99) /* l_himap8 start8 byte_map_addr32 addr32*     */ \
+V(CHECK_REGISTER_LT, 32, 8) /* check_reg_lt register_index value16 addr32   */ \
+V(CHECK_REGISTER_GE, 33, 8) /* check_reg_ge register_index value16 addr32   */ \
+V(CHECK_NOT_AT_START, 34, 5) /* check_not_at_start addr32                   */ \
+V(CHECK_GREEDY,      35, 5) /* check_greedy addr32                          */
 
 #define DECLARE_BYTECODES(name, code, length) \
   static const int BC_##name = code;
diff --git a/src/codegen-arm.cc b/src/codegen-arm.cc
index 494257a..712a989 100644
--- a/src/codegen-arm.cc
+++ b/src/codegen-arm.cc
@@ -1347,15 +1347,7 @@
   __ b(ne, fail_label);
   __ cmp(r0, Operand(Smi::FromInt(range)));
   __ b(ge, fail_label);
-  __ add(pc, pc, Operand(r0, LSL, 2 - kSmiTagSize));
-  // One extra instruction offsets the table, so the table's start address is
-  // the pc-register at the above add.
-  __ stop("Unreachable: Switch table alignment");
-
-  // Table containing branch operations.
-  for (int i = 0; i < range; i++) {
-    __ b(case_targets[i]);
-  }
+  __ SmiJumpTable(r0, case_targets);
 
   GenerateFastCaseSwitchCases(node, case_labels);
 }
diff --git a/src/codegen-ia32.cc b/src/codegen-ia32.cc
index c5987a3..8e5420b 100644
--- a/src/codegen-ia32.cc
+++ b/src/codegen-ia32.cc
@@ -2919,18 +2919,16 @@
   Label ascii_string;
   Label got_char_code;
 
-  // Load the string into eax.
+  // Load the string into eax and the index into ebx.
   Load(args->at(0));
+  Load(args->at(1));
+  frame_->Pop(ebx);
   frame_->Pop(eax);
   // If the receiver is a smi return undefined.
   ASSERT(kSmiTag == 0);
   __ test(eax, Immediate(kSmiTagMask));
   __ j(zero, &slow_case, not_taken);
 
-  // Load the index into ebx.
-  Load(args->at(1));
-  frame_->Pop(ebx);
-
   // Check for negative or non-smi index.
   ASSERT(kSmiTag == 0);
   __ test(ebx, Immediate(kSmiTagMask | 0x80000000));
diff --git a/src/codegen.cc b/src/codegen.cc
index 14c20dc..4df51e7 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -78,7 +78,9 @@
                                      Handle<Script> script,
                                      bool is_eval) {
 #ifdef ENABLE_DISASSEMBLER
-  bool print_code = FLAG_print_code && !Bootstrapper::IsActive();
+  bool print_code = Bootstrapper::IsActive()
+      ? FLAG_print_builtin_code
+      : FLAG_print_code;
 #endif
 
 #ifdef DEBUG
@@ -89,7 +91,6 @@
   if (Bootstrapper::IsActive()) {
     print_source = FLAG_print_builtin_source;
     print_ast = FLAG_print_builtin_ast;
-    print_code = FLAG_print_builtin_code;
     ftype = "builtin";
   } else {
     print_source = FLAG_print_source;
diff --git a/src/compiler.cc b/src/compiler.cc
index eb76d38..81be930 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -206,6 +206,8 @@
     }
   }
 
+  if (result.is_null()) Top::ReportPendingMessages();
+
   return result;
 }
 
@@ -235,6 +237,7 @@
       CompilationCache::PutFunction(source, entry, result);
     }
   }
+
   return result;
 }
 
diff --git a/src/constants-arm.h b/src/constants-arm.h
index 46ddb15..f553963 100644
--- a/src/constants-arm.h
+++ b/src/constants-arm.h
@@ -129,6 +129,7 @@
  public:
   enum {
     kInstrSize = 4,
+    kInstrSizeLog2 = 2,
     kPCReadOffset = 8
   };
 
diff --git a/src/d8-readline.cc b/src/d8-readline.cc
index 4cfee8b..b81a616 100644
--- a/src/d8-readline.cc
+++ b/src/d8-readline.cc
@@ -26,6 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
+#include <cstdio>  // NOLINT
 #include <readline/readline.h>
 #include <readline/history.h>
 
@@ -33,6 +34,13 @@
 #include "d8.h"
 
 
+// There are incompatibilities between different versions and different
+// implementations of readline.  This smoothes out one known incompatibility.
+#if RL_READLINE_VERSION >= 0x0500
+#define completion_matches rl_completion_matches
+#endif
+
+
 namespace v8 {
 
 
@@ -85,7 +93,7 @@
 char** ReadLineEditor::AttemptedCompletion(const char* text,
                                            int start,
                                            int end) {
-  char** result = rl_completion_matches(text, CompletionGenerator);
+  char** result = completion_matches(text, CompletionGenerator);
   rl_attempted_completion_over = true;
   return result;
 }
@@ -95,7 +103,7 @@
   static unsigned current_index;
   static Persistent<Array> current_completions;
   if (state == 0) {
-    i::SmartPointer<char> full_text(strndup(rl_line_buffer, rl_point));
+    i::SmartPointer<char> full_text(i::OS::StrNDup(rl_line_buffer, rl_point));
     HandleScope scope;
     Handle<Array> completions =
       Shell::GetCompletions(String::New(text), String::New(*full_text));
diff --git a/src/d8.cc b/src/d8.cc
index 03a6ab6..fbc91d3 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -257,6 +257,7 @@
   }
   Counter* result = counters_->GetNextCounter();
   if (result == NULL) return NULL;
+  counter_map_[name] = result;
   return result->Bind(name);
 }
 
diff --git a/src/debug-arm.cc b/src/debug-arm.cc
new file mode 100644
index 0000000..49d9723
--- /dev/null
+++ b/src/debug-arm.cc
@@ -0,0 +1,170 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "debug.h"
+
+namespace v8 { namespace internal {
+
+
+#define __ masm->
+
+
+static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
+                                          RegList pointer_regs) {
+  // Save the content of all general purpose registers in memory. This copy in
+  // memory is later pushed onto the JS expression stack for the fake JS frame
+  // generated and also to the C frame generated on top of that. In the JS
+  // frame ONLY the registers containing pointers will be pushed on the
+  // expression stack. This causes the GC to update these  pointers so that
+  // they will have the correct value when returning from the debugger.
+  __ SaveRegistersToMemory(kJSCallerSaved);
+
+  __ EnterInternalFrame();
+
+  // Store the registers containing object pointers on the expression stack to
+  // make sure that these are correctly updated during GC.
+  // Use sp as base to push.
+  __ CopyRegistersFromMemoryToStack(sp, pointer_regs);
+
+#ifdef DEBUG
+  __ RecordComment("// Calling from debug break to runtime - come in - over");
+#endif
+  __ mov(r0, Operand(0));  // no arguments
+  __ mov(r1, Operand(ExternalReference::debug_break()));
+
+  CEntryDebugBreakStub ceb;
+  __ CallStub(&ceb);
+
+  // Restore the register values containing object pointers from the expression
+  // stack in the reverse order as they where pushed.
+  // Use sp as base to pop.
+  __ CopyRegistersFromStackToMemory(sp, r3, pointer_regs);
+
+  __ LeaveInternalFrame();
+
+  // Inlined ExitJSFrame ends here.
+
+  // Finally restore all registers.
+  __ RestoreRegistersFromMemory(kJSCallerSaved);
+
+  // Now that the break point has been handled, resume normal execution by
+  // jumping to the target address intended by the caller and that was
+  // overwritten by the address of DebugBreakXXX.
+  __ mov(ip, Operand(ExternalReference(Debug_Address::AfterBreakTarget())));
+  __ ldr(ip, MemOperand(ip));
+  __ Jump(ip);
+}
+
+
+void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
+  // Calling convention for IC load (from ic-arm.cc).
+  // ----------- S t a t e -------------
+  //  -- r0    : receiver
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  // Registers r0 and r2 contain objects that needs to be pushed on the
+  // expression stack of the fake JS frame.
+  Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit());
+}
+
+
+void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
+  // Calling convention for IC store (from ic-arm.cc).
+  // ----------- S t a t e -------------
+  //  -- r0    : receiver
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  // Registers r0 and r2 contain objects that needs to be pushed on the
+  // expression stack of the fake JS frame.
+  Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit());
+}
+
+
+void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
+  // Keyed load IC not implemented on ARM.
+}
+
+
+void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
+  // Keyed store IC not implemented on ARM.
+}
+
+
+void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
+  // Calling convention for IC call (from ic-arm.cc)
+  // ----------- S t a t e -------------
+  //  -- r0: number of arguments
+  //  -- r1: receiver
+  //  -- lr: return address
+  // -----------------------------------
+  // Register r1 contains an object that needs to be pushed on the expression
+  // stack of the fake JS frame. r0 is the actual number of arguments not
+  // encoded as a smi, therefore it cannot be on the expression stack of the
+  // fake JS frame as it can easily be an invalid pointer (e.g. 1). r0 will be
+  // pushed on the stack of the C frame and restored from there.
+  Generate_DebugBreakCallHelper(masm, r1.bit());
+}
+
+
+void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) {
+  // In places other than IC call sites it is expected that r0 is TOS which
+  // is an object - this is not generally the case so this should be used with
+  // care.
+  Generate_DebugBreakCallHelper(masm, r0.bit());
+}
+
+
+void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
+  // In places other than IC call sites it is expected that r0 is TOS which
+  // is an object - this is not generally the case so this should be used with
+  // care.
+  Generate_DebugBreakCallHelper(masm, r0.bit());
+}
+
+
+void Debug::GenerateReturnDebugBreakEntry(MacroAssembler* masm) {
+  // Generate nothing as this handling of debug break return is not done this
+  // way on ARM  - yet.
+}
+
+
+void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) {
+  // Generate nothing as CodeStub CallFunction is not used on ARM.
+}
+
+
+#undef __
+
+
+} }  // namespace v8::internal
diff --git a/src/debug-delay.js b/src/debug-delay.js
index 17b82b5..6db054e 100644
--- a/src/debug-delay.js
+++ b/src/debug-delay.js
@@ -322,6 +322,10 @@
   // Convert the line and column into an absolute position within the script.
   var pos = Debug.findScriptSourcePosition(script, this.line(), column);
   
+  // If the position is not found in the script (the script might be shorter
+  // than it used to be) just ignore it.
+  if (pos === null) return;
+  
   // Create a break point object and set the break point.
   break_point = MakeBreakPoint(pos, this.line(), this.column(), this);
   break_point.setIgnoreCount(this.ignoreCount());
@@ -443,7 +447,8 @@
 // Returns the character position in a script based on a line number and an
 // optional position within that line.
 Debug.findScriptSourcePosition = function(script, opt_line, opt_column) {
-  return script.locationFromLine(opt_line, opt_column).position;
+  var location = script.locationFromLine(opt_line, opt_column);  
+  return location ? location.position : null;
 }
 
 
@@ -727,6 +732,16 @@
 }
 
 
+BreakEvent.prototype.executionState = function() {
+  return this.exec_state_;
+};
+
+
+BreakEvent.prototype.eventType = function() {
+  return Debug.DebugEvent.Break;
+};
+
+
 BreakEvent.prototype.func = function() {
   return this.exec_state_.frame(0).func();
 };
@@ -799,16 +814,34 @@
   return new ExceptionEvent(exec_state, exception, uncaught);
 }
 
+
 function ExceptionEvent(exec_state, exception, uncaught) {
   this.exec_state_ = exec_state;
   this.exception_ = exception;
   this.uncaught_ = uncaught;
 }
 
+
+ExceptionEvent.prototype.executionState = function() {
+  return this.exec_state_;
+};
+
+
+ExceptionEvent.prototype.eventType = function() {
+  return Debug.DebugEvent.Exception;
+};
+
+
+ExceptionEvent.prototype.exception = function() {
+  return this.exception_;
+}
+
+
 ExceptionEvent.prototype.uncaught = function() {
   return this.uncaught_;
 }
 
+
 ExceptionEvent.prototype.func = function() {
   return this.exec_state_.frame(0).func();
 };
@@ -855,18 +888,28 @@
 };
 
 
-function MakeCompileEvent(script_source, script_name, script_function) {
-  return new CompileEvent(script_source, script_name, script_function);
+function MakeCompileEvent(script_source, script_name, script_function, before) {
+  return new CompileEvent(script_source, script_name, script_function, before);
 }
 
 
-function CompileEvent(script_source, script_name, script_function) {
+function CompileEvent(script_source, script_name, script_function, before) {
   this.scriptSource = script_source;
   this.scriptName = script_name;
   this.scriptFunction = script_function;
+  this.before = before;
 }
 
 
+CompileEvent.prototype.eventType = function() {
+  if (this.before) {
+    return Debug.DebugEvent.BeforeComplie;
+  } else {
+    return Debug.DebugEvent.AfterComplie;
+  }
+};
+
+
 function MakeNewFunctionEvent(func) {
   return new NewFunctionEvent(func);
 }
@@ -876,6 +919,12 @@
   this.func = func;
 }
 
+
+NewFunctionEvent.prototype.eventType = function() {
+  return Debug.DebugEvent.NewFunction;
+};
+
+
 NewFunctionEvent.prototype.name = function() {
   return this.func.name;
 };
@@ -1279,6 +1328,14 @@
   // Get the number of frames.
   var total_frames = this.exec_state_.frameCount();
 
+  // Create simple response if there are no frames.
+  if (total_frames == 0) {
+    response.body = {
+      totalFrames: total_frames
+    }
+    return;
+  }
+
   // Default frame range to include in backtrace.
   var from_index = 0
   var to_index = kDefaultBacktraceLength;
diff --git a/src/debug-ia32.cc b/src/debug-ia32.cc
new file mode 100644
index 0000000..ba7d682
--- /dev/null
+++ b/src/debug-ia32.cc
@@ -0,0 +1,185 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "debug.h"
+
+
+namespace v8 { namespace internal {
+
+
+#define __ masm->
+
+
+static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
+                                          RegList pointer_regs,
+                                          bool convert_call_to_jmp) {
+  // Save the content of all general purpose registers in memory. This copy in
+  // memory is later pushed onto the JS expression stack for the fake JS frame
+  // generated and also to the C frame generated on top of that. In the JS
+  // frame ONLY the registers containing pointers will be pushed on the
+  // expression stack. This causes the GC to update these pointers so that
+  // they will have the correct value when returning from the debugger.
+  __ SaveRegistersToMemory(kJSCallerSaved);
+
+  // Enter an internal frame.
+  __ EnterInternalFrame();
+
+  // Store the registers containing object pointers on the expression stack to
+  // make sure that these are correctly updated during GC.
+  __ PushRegistersFromMemory(pointer_regs);
+
+#ifdef DEBUG
+  __ RecordComment("// Calling from debug break to runtime - come in - over");
+#endif
+  __ Set(eax, Immediate(0));  // no arguments
+  __ mov(ebx, Immediate(ExternalReference::debug_break()));
+
+  CEntryDebugBreakStub ceb;
+  __ CallStub(&ceb);
+
+  // Restore the register values containing object pointers from the expression
+  // stack in the reverse order as they where pushed.
+  __ PopRegistersToMemory(pointer_regs);
+
+  // Get rid of the internal frame.
+  __ LeaveInternalFrame();
+
+  // If this call did not replace a call but patched other code then there will
+  // be an unwanted return address left on the stack. Here we get rid of that.
+  if (convert_call_to_jmp) {
+    __ pop(eax);
+  }
+
+  // Finally restore all registers.
+  __ RestoreRegistersFromMemory(kJSCallerSaved);
+
+  // Now that the break point has been handled, resume normal execution by
+  // jumping to the target address intended by the caller and that was
+  // overwritten by the address of DebugBreakXXX.
+  ExternalReference after_break_target =
+      ExternalReference(Debug_Address::AfterBreakTarget());
+  __ jmp(Operand::StaticVariable(after_break_target));
+}
+
+
+void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
+  // Register state for IC load call (from ic-ia32.cc).
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, ecx.bit(), false);
+}
+
+
+void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
+  // REgister state for IC store call (from ic-ia32.cc).
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- ecx    : name
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit(), false);
+}
+
+
+void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
+  // Register state for keyed IC load call (from ic-ia32.cc).
+  // ----------- S t a t e -------------
+  //  No registers used on entry.
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, 0, false);
+}
+
+
+void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
+  // Register state for keyed IC load call (from ic-ia32.cc).
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  // -----------------------------------
+  // Register eax contains an object that needs to be pushed on the
+  // expression stack of the fake JS frame.
+  Generate_DebugBreakCallHelper(masm, eax.bit(), false);
+}
+
+
+void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
+  // Register state for keyed IC call call (from ic-ia32.cc)
+  // ----------- S t a t e -------------
+  //  -- eax: number of arguments
+  // -----------------------------------
+  // The number of arguments in eax is not smi encoded.
+  Generate_DebugBreakCallHelper(masm, 0, false);
+}
+
+
+void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) {
+  // Register state just before return from JS function (from codegen-ia32.cc).
+  // eax is the actual number of arguments not encoded as a smi see comment
+  // above IC call.
+  // ----------- S t a t e -------------
+  //  -- eax: number of arguments
+  // -----------------------------------
+  // The number of arguments in eax is not smi encoded.
+  Generate_DebugBreakCallHelper(masm, 0, false);
+}
+
+
+void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
+  // Register state just before return from JS function (from codegen-ia32.cc).
+  // ----------- S t a t e -------------
+  //  -- eax: return value
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, eax.bit(), true);
+}
+
+
+void Debug::GenerateReturnDebugBreakEntry(MacroAssembler* masm) {
+  // OK to clobber ebx as we are returning from a JS function in the code
+  // generated by Ia32CodeGenerator::ExitJSFrame.
+  ExternalReference debug_break_return =
+      ExternalReference(Debug_Address::DebugBreakReturn());
+  __ mov(ebx, Operand::StaticVariable(debug_break_return));
+  __ add(Operand(ebx), Immediate(Code::kHeaderSize - kHeapObjectTag));
+  __ jmp(Operand(ebx));
+}
+
+
+void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) {
+  // Register state for stub CallFunction (from CallFunctionStub in ic-ia32.cc).
+  // ----------- S t a t e -------------
+  //  No registers used on entry.
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, 0, false);
+}
+
+
+#undef __
+
+
+} }  // namespace v8::internal
diff --git a/src/debug.cc b/src/debug.cc
index 6952d8b..027c89b 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -113,7 +113,7 @@
     // be of a different kind than in the original code.
     if (RelocInfo::IsCodeTarget(rmode())) {
       Address target = original_rinfo()->target_address();
-      Code* code = Debug::GetCodeTarget(target);
+      Code* code = Code::GetCodeFromTargetAddress(target);
       if (code->is_inline_cache_stub() || RelocInfo::IsConstructCall(rmode())) {
         break_point_++;
         return;
@@ -325,7 +325,7 @@
   // Step in can only be prepared if currently positioned on an IC call or
   // construct call.
   Address target = rinfo()->target_address();
-  Code* code = Debug::GetCodeTarget(target);
+  Code* code = Code::GetCodeFromTargetAddress(target);
   if (code->is_call_stub()) {
     // Step in through IC call is handled by the runtime system. Therefore make
     // sure that the any current IC is cleared and the runtime system is
@@ -849,7 +849,12 @@
 
 
 void Debug::FloodHandlerWithOneShot() {
+  // Iterate through the JavaScript stack looking for handlers.
   StackFrame::Id id = Top::break_frame_id();
+  if (id == StackFrame::NO_ID) {
+    // If there is no JavaScript stack don't do anything.
+    return;
+  }
   for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) {
     JavaScriptFrame* frame = it.frame();
     if (frame->HasHandler()) {
@@ -886,6 +891,10 @@
   // hitting a break point. In other situations (e.g. unhandled exception) the
   // debug frame is not present.
   StackFrame::Id id = Top::break_frame_id();
+  if (id == StackFrame::NO_ID) {
+    // If there is no JavaScript stack don't do anything.
+    return;
+  }
   JavaScriptFrameIterator frames_it(id);
   JavaScriptFrame* frame = frames_it.frame();
 
@@ -923,7 +932,7 @@
   bool is_call_target = false;
   if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
     Address target = it.rinfo()->target_address();
-    Code* code = Debug::GetCodeTarget(target);
+    Code* code = Code::GetCodeFromTargetAddress(target);
     if (code->is_call_stub()) is_call_target = true;
   }
 
@@ -991,7 +1000,7 @@
 // Check whether the code object at the specified address is a debug break code
 // object.
 bool Debug::IsDebugBreak(Address addr) {
-  Code* code = GetCodeTarget(addr);
+  Code* code = Code::GetCodeFromTargetAddress(addr);
   return code->ic_state() == DEBUG_BREAK;
 }
 
@@ -1021,7 +1030,7 @@
 
   if (RelocInfo::IsCodeTarget(mode)) {
     Address target = rinfo->target_address();
-    Code* code = Debug::GetCodeTarget(target);
+    Code* code = Code::GetCodeFromTargetAddress(target);
     if (code->is_inline_cache_stub()) {
       if (code->is_call_stub()) {
         return ComputeCallDebugBreak(code->arguments_count());
@@ -1262,14 +1271,6 @@
 }
 
 
-Code* Debug::GetCodeTarget(Address target) {
-  // Maybe this can be refactored with the stuff in ic-inl.h?
-  Code* result =
-      Code::cast(HeapObject::FromAddress(target - Code::kHeaderSize));
-  return result;
-}
-
-
 bool Debug::IsDebugGlobal(GlobalObject* global) {
   return IsLoaded() && global == Debug::debug_context()->global();
 }
@@ -1700,7 +1701,7 @@
 }
 
 
-void DebugMessageThread::SetEventJSONFromEvent(Handle<Object> event_data) {
+bool DebugMessageThread::SetEventJSONFromEvent(Handle<Object> event_data) {
   v8::HandleScope scope;
   // Call toJSONProtocol on the debug event object.
   v8::Local<v8::Object> api_event_data =
@@ -1726,8 +1727,9 @@
     }
   } else {
     PrintLn(try_catch.Exception());
-    SendMessage(Vector<uint16_t>::empty());
+    return false;
   }
+  return true;
 }
 
 
@@ -1790,10 +1792,14 @@
   }
 
   // Notify the debugger that a debug event has occurred.
-  host_running_ = false;
-  SetEventJSONFromEvent(event_data);
+  bool success = SetEventJSONFromEvent(event_data);
+  if (!success) {
+    // If failed to notify debugger just continue running.
+    return;
+  }
 
   // Wait for requests from the debugger.
+  host_running_ = false;
   while (true) {
     command_received_->Wait();
     Logger::DebugTag("Got request from command queue, in interactive loop.");
diff --git a/src/debug.h b/src/debug.h
index 629cebe..fdb80bd 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -194,7 +194,6 @@
 
   static Handle<Object> GetSourceBreakLocations(
       Handle<SharedFunctionInfo> shared);
-  static Code* GetCodeTarget(Address target);
 
   // Getter for the debug_context.
   inline static Handle<Context> debug_context() { return debug_context_; }
@@ -262,6 +261,19 @@
   static const int kIa32CallInstructionLength = 5;
   static const int kIa32JSReturnSequenceLength = 6;
 
+  // Code generator routines.
+  static void GenerateLoadICDebugBreak(MacroAssembler* masm);
+  static void GenerateStoreICDebugBreak(MacroAssembler* masm);
+  static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm);
+  static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm);
+  static void GenerateConstructCallDebugBreak(MacroAssembler* masm);
+  static void GenerateReturnDebugBreak(MacroAssembler* masm);
+  static void GenerateReturnDebugBreakEntry(MacroAssembler* masm);
+  static void GenerateStubNoRegistersDebugBreak(MacroAssembler* masm);
+
+  // Called from stub-cache.cc.
+  static void GenerateCallICDebugBreak(MacroAssembler* masm);
+
  private:
   static bool CompileDebuggerScript(int index);
   static void ClearOneShot();
@@ -448,7 +460,7 @@
   // which forwards it to the debug_message_handler set by the API.
   void SendMessage(Vector<uint16_t> event_json);
   // Formats an event into JSON, and calls SendMessage.
-  void SetEventJSONFromEvent(Handle<Object> event_data);
+  bool SetEventJSONFromEvent(Handle<Object> event_data);
   // Puts a command coming from the public API on the queue.  Called
   // by the API client thread.  This is where the API client hands off
   // processing of the command to the DebugMessageThread thread.
@@ -477,16 +489,17 @@
 // some reason could not be entered FailedToEnter will return true.
 class EnterDebugger BASE_EMBEDDED {
  public:
-  EnterDebugger() : set_(!it_.done()) {
-    // If there is no JavaScript frames on the stack don't switch to new break
-    // and break frame.
-    if (set_) {
-      // Store the previous break is and frame id.
-      break_id_ = Top::break_id();
-      break_frame_id_ = Top::break_frame_id();
+  EnterDebugger() : has_js_frames_(!it_.done()) {
+    // Store the previous break id and frame id.
+    break_id_ = Top::break_id();
+    break_frame_id_ = Top::break_frame_id();
 
-      // Create the new break info.
+    // Create the new break info. If there is no JavaScript frames there is no
+    // break frame id.
+    if (has_js_frames_) {
       Top::new_break(it_.frame()->id());
+    } else {
+      Top::new_break(StackFrame::NO_ID);
     }
 
     // Make sure that debugger is loaded and enter the debugger context.
@@ -499,21 +512,19 @@
   }
 
   ~EnterDebugger() {
-    if (set_) {
-      // Restore to the previous break state.
-      Top::set_break(break_frame_id_, break_id_);
-    }
+    // Restore to the previous break state.
+    Top::set_break(break_frame_id_, break_id_);
   }
 
   // Check whether the debugger could be entered.
   inline bool FailedToEnter() { return load_failed_; }
 
   // Check whether there are any JavaScript frames on the stack.
-  inline bool HasJavaScriptFrames() { return set_; }
+  inline bool HasJavaScriptFrames() { return has_js_frames_; }
 
  private:
   JavaScriptFrameIterator it_;
-  const bool set_;  // Was the break actually set?
+  const bool has_js_frames_;  // Were there any JavaScript frames?
   StackFrame::Id break_frame_id_;  // Previous break frame id.
   int break_id_;  // Previous break id.
   bool load_failed_;  // Did the debugger fail to load?
diff --git a/src/disassembler.cc b/src/disassembler.cc
index 53f594f..af7df26 100644
--- a/src/disassembler.cc
+++ b/src/disassembler.cc
@@ -228,7 +228,7 @@
         if (rmode == RelocInfo::CONSTRUCT_CALL) {
           out.AddFormatted(" constructor,");
         }
-        Code* code = Debug::GetCodeTarget(relocinfo.target_address());
+        Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address());
         Code::Kind kind = code->kind();
         if (code->is_inline_cache_stub()) {
           if (rmode == RelocInfo::CODE_TARGET_CONTEXT) {
diff --git a/src/execution.cc b/src/execution.cc
index 996c58c..941712a 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -95,15 +95,10 @@
   *has_pending_exception = value->IsException();
   ASSERT(*has_pending_exception == Top::has_pending_exception());
   if (*has_pending_exception) {
-    Top::setup_external_caught();
-    // If the pending exception is OutOfMemoryException set out_of_memory in
-    // the global context.  Note: We have to mark the global context here
-    // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to
-    // set it.
-    if (Top::pending_exception() == Failure::OutOfMemoryException()) {
-      Top::context()->mark_out_of_memory();
-    }
+    Top::ReportPendingMessages();
     return Handle<Object>();
+  } else {
+    Top::clear_pending_message();
   }
 
   return Handle<Object>(value);
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 0db2303..eafbbad 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -250,7 +250,6 @@
 // codegen-ia32.cc / codegen-arm.cc
 DEFINE_bool(trace_codegen, false,
             "print name of functions for which code is generated")
-DEFINE_bool(print_builtin_code, false, "print generated code for builtins")
 DEFINE_bool(print_source, false, "pretty print source code")
 DEFINE_bool(print_builtin_source, false,
             "pretty print source code for builtins")
@@ -343,6 +342,7 @@
 
 // codegen-ia32.cc / codegen-arm.cc
 DEFINE_bool(print_code, false, "print generated code")
+DEFINE_bool(print_builtin_code, false, "print generated code for builtins")
 
 // Cleanup...
 #undef FLAG_FULL
diff --git a/src/global-handles.cc b/src/global-handles.cc
index 29ad86e..a92f0df 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -352,29 +352,26 @@
 
 #endif
 
-List<ObjectGroup*> GlobalHandles::object_groups_(4);
+List<ObjectGroup*>* GlobalHandles::ObjectGroups() {
+  // Lazily initialize the list to avoid startup time static constructors.
+  static List<ObjectGroup*> groups(4);
+  return &groups;
+}
 
-void GlobalHandles::AddToGroup(void* id, Object** handle) {
-  for (int i = 0; i < object_groups_.length(); i++) {
-    ObjectGroup* entry = object_groups_[i];
-    if (entry->id_ == id) {
-      entry->objects_.Add(handle);
-      return;
-    }
-  }
-
-  // not found
-  ObjectGroup* new_entry = new ObjectGroup(id);
-  new_entry->objects_.Add(handle);
-  object_groups_.Add(new_entry);
+void GlobalHandles::AddGroup(Object*** handles, size_t length) {
+  ObjectGroup* new_entry = new ObjectGroup(length);
+  for (size_t i = 0; i < length; ++i)
+    new_entry->objects_.Add(handles[i]);
+  ObjectGroups()->Add(new_entry);
 }
 
 
 void GlobalHandles::RemoveObjectGroups() {
-  for (int i = 0; i< object_groups_.length(); i++) {
-    delete object_groups_[i];
+  List<ObjectGroup*>* object_groups = ObjectGroups();
+  for (int i = 0; i< object_groups->length(); i++) {
+    delete object_groups->at(i);
   }
-  object_groups_.Clear();
+  object_groups->Clear();
 }
 
 
diff --git a/src/global-handles.h b/src/global-handles.h
index 78fb3a1..c5f4450 100644
--- a/src/global-handles.h
+++ b/src/global-handles.h
@@ -41,15 +41,14 @@
 // Callback function on handling weak global handles.
 // typedef bool (*WeakSlotCallback)(Object** pointer);
 
-// An object group is indexed by an id. An object group is treated like
-// a single JS object: if one of object in the group is alive,
-// all objects in the same group are considered alive.
+// An object group is treated like a single JS object: if one of object in
+// the group is alive, all objects in the same group are considered alive.
 // An object group is used to simulate object relationship in a DOM tree.
 class ObjectGroup : public Malloced {
  public:
-  explicit ObjectGroup(void* id) : id_(id), objects_(4) {}
+  ObjectGroup() : objects_(4) {}
+  explicit ObjectGroup(size_t capacity) : objects_(capacity) {}
 
-  void* id_;
   List<Object**> objects_;
 };
 
@@ -102,15 +101,13 @@
   // Mark the weak pointers based on the callback.
   static void MarkWeakRoots(WeakSlotCallback f);
 
-  // Add an object to a group indexed by an id.
+  // Add an object group.
   // Should only used in GC callback function before a collection.
   // All groups are destroyed after a mark-compact collection.
-  static void AddToGroup(void* id, Object** location);
+  static void AddGroup(Object*** handles, size_t length);
 
   // Returns the object groups.
-  static List<ObjectGroup*>& ObjectGroups() {
-    return object_groups_;
-  }
+  static List<ObjectGroup*>* ObjectGroups();
 
   // Remove bags, this should only happen after GC.
   static void RemoveObjectGroups();
@@ -143,9 +140,6 @@
   static Node* first_free_;
   static Node* first_free() { return first_free_; }
   static void set_first_free(Node* value) { first_free_ = value; }
-
-  // A list of object groups.
-  static List<ObjectGroup*> object_groups_;
 };
 
 
diff --git a/src/globals.h b/src/globals.h
index e2fb2a9..e174bf3 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -184,7 +184,7 @@
 class Property;
 class Proxy;
 class RegExpNode;
-struct RegExpParseResult;
+struct RegExpCompileData;
 class RegExpTree;
 class RegExpCompiler;
 class RegExpVisitor;
diff --git a/src/ic-arm.cc b/src/ic-arm.cc
index dc35256..55bbee4 100644
--- a/src/ic-arm.cc
+++ b/src/ic-arm.cc
@@ -317,8 +317,8 @@
   __ b(eq, &miss);
 
   // Check that the receiver is a valid JS object.
-  __ ldr(r0, FieldMemOperand(r1, HeapObject::kMapOffset));
-  __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
+  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldrb(r0, FieldMemOperand(r3, Map::kInstanceTypeOffset));
   __ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE));
   __ b(lt, &miss);
 
@@ -333,6 +333,10 @@
 
   // Accessing global object: Load and invoke.
   __ bind(&global_object);
+  // Check that the global object does not require access checks.
+  __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
+  __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
+  __ b(ne, &miss);
   GenerateNormalHelper(masm, argc, true, &miss);
 
   // Accessing non-global object: Check for access to global proxy.
@@ -340,6 +344,11 @@
   __ bind(&non_global_object);
   __ cmp(r0, Operand(JS_GLOBAL_PROXY_TYPE));
   __ b(eq, &global_proxy);
+  // Check that the non-global, non-global-proxy object does not
+  // require access checks.
+  __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
+  __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
+  __ b(ne, &miss);
   __ bind(&invoke);
   GenerateNormalHelper(masm, argc, false, &miss);
 
@@ -441,8 +450,8 @@
   __ b(eq, &miss);
 
   // Check that the receiver is a valid JS object.
-  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
-  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
+  __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
+  __ ldrb(r1, FieldMemOperand(r3, Map::kInstanceTypeOffset));
   __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
   __ b(lt, &miss);
   // If this assert fails, we have to check upper bound too.
@@ -452,6 +461,11 @@
   __ cmp(r1, Operand(JS_GLOBAL_PROXY_TYPE));
   __ b(eq, &global);
 
+  // Check for non-global object that requires access check.
+  __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
+  __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
+  __ b(ne, &miss);
+
   __ bind(&probe);
   GenerateDictionaryLoad(masm, &miss, r1, r0);
   GenerateCheckNonFunctionOrLoaded(masm, &miss, r0, r1);
@@ -525,12 +539,19 @@
   __ tst(r1, Operand(kSmiTagMask));
   __ b(eq, &slow);
 
+  // Get the map of the receiver.
+  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+  // Check that the receiver does not require access checks.  We need
+  // to check this explicitly since this generic stub does not perform
+  // map checks.
+  __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
+  __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
+  __ b(ne, &slow);
   // Check that the object is some kind of JS object EXCEPT JS Value type.
   // In the case that the object is a value-wrapper object,
   // we enter the runtime system to make sure that indexing into string
   // objects work as intended.
   ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
-  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
   __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
   __ cmp(r2, Operand(JS_OBJECT_TYPE));
   __ b(lt, &slow);
@@ -597,10 +618,15 @@
   // Check that the object isn't a smi.
   __ tst(r3, Operand(kSmiTagMask));
   __ b(eq, &slow);
-  // Get the type of the object from its map.
+  // Get the map of the object.
   __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
-  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+  // Check that the receiver does not require access checks.  We need
+  // to do this because this generic stub does not perform map checks.
+  __ ldrb(ip, FieldMemOperand(r2, Map::kBitFieldOffset));
+  __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded));
+  __ b(ne, &slow);
   // Check if the object is a JS array or not.
+  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
   __ cmp(r2, Operand(JS_ARRAY_TYPE));
   // r1 == key.
   __ b(eq, &array);
diff --git a/src/ic-ia32.cc b/src/ic-ia32.cc
index 7ff47b9..6021004 100644
--- a/src/ic-ia32.cc
+++ b/src/ic-ia32.cc
@@ -215,18 +215,27 @@
   // -----------------------------------
   Label slow, fast, check_string, index_int, index_string;
 
+  // Load name and receiver.
   __ mov(eax, (Operand(esp, kPointerSize)));
   __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
 
   // Check that the object isn't a smi.
   __ test(ecx, Immediate(kSmiTagMask));
   __ j(zero, &slow, not_taken);
+
+  // Get the map of the receiver.
+  __ mov(edx, FieldOperand(ecx, HeapObject::kMapOffset));
+  // Check that the receiver does not require access checks.  We need
+  // to check this explicitly since this generic stub does not perform
+  // map checks.
+  __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset));
+  __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
+  __ j(not_zero, &slow, not_taken);
   // Check that the object is some kind of JS object EXCEPT JS Value type.
   // In the case that the object is a value-wrapper object,
   // we enter the runtime system to make sure that indexing
   // into string objects work as intended.
   ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
-  __ mov(edx, FieldOperand(ecx, HeapObject::kMapOffset));
   __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
   __ cmp(edx, JS_OBJECT_TYPE);
   __ j(less, &slow, not_taken);
@@ -268,7 +277,7 @@
   // bits have been subtracted to allow space for the length and the cached
   // array index.
   ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
-             (1 << (String::kShortLengthShift - String::kHashShift)));
+         (1 << (String::kShortLengthShift - String::kHashShift)));
   __ bind(&index_string);
   const int kLengthFieldLimit =
       (String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift;
@@ -298,17 +307,25 @@
   //  -- esp[8] : receiver
   // -----------------------------------
   Label slow, fast, array, extra;
-  // Get the key and the object from the stack.
-  __ mov(ebx, Operand(esp, 1 * kPointerSize));  // 1 ~ return address
+
+  // Get the receiver from the stack.
   __ mov(edx, Operand(esp, 2 * kPointerSize));  // 2 ~ return address, key
-  // Check that the key is a smi.
-  __ test(ebx, Immediate(kSmiTagMask));
-  __ j(not_zero, &slow, not_taken);
   // Check that the object isn't a smi.
   __ test(edx, Immediate(kSmiTagMask));
   __ j(zero, &slow, not_taken);
-  // Get the type of the object from its map.
+  // Get the map from the receiver.
   __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
+  // Check that the receiver does not require access checks.  We need
+  // to do this because this generic stub does not perform map checks.
+  __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset));
+  __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
+  __ j(not_zero, &slow, not_taken);
+  // Get the key from the stack.
+  __ mov(ebx, Operand(esp, 1 * kPointerSize));  // 1 ~ return address
+  // Check that the key is a smi.
+  __ test(ebx, Immediate(kSmiTagMask));
+  __ j(not_zero, &slow, not_taken);
+  // Get the instance type from the map of the receiver.
   __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
   // Check if the object is a JS array or not.
   __ cmp(ecx, JS_ARRAY_TYPE);
@@ -317,7 +334,6 @@
   __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
   __ j(less, &slow, not_taken);
 
-
   // Object case: Check key against length in the elements array.
   // eax: value
   // edx: JSObject
@@ -515,8 +531,8 @@
   __ j(zero, &miss, not_taken);
 
   // Check that the receiver is a valid JS object.
-  __ mov(eax, FieldOperand(edx, HeapObject::kMapOffset));
-  __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
+  __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
+  __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceTypeOffset));
   __ cmp(eax, FIRST_JS_OBJECT_TYPE);
   __ j(less, &miss, not_taken);
 
@@ -531,6 +547,10 @@
 
   // Accessing global object: Load and invoke.
   __ bind(&global_object);
+  // Check that the global object does not require access checks.
+  __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
+  __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
+  __ j(not_equal, &miss, not_taken);
   GenerateNormalHelper(masm, argc, true, &miss);
 
   // Accessing non-global object: Check for access to global proxy.
@@ -538,6 +558,11 @@
   __ bind(&non_global_object);
   __ cmp(eax, JS_GLOBAL_PROXY_TYPE);
   __ j(equal, &global_proxy, not_taken);
+  // Check that the non-global, non-global-proxy object does not
+  // require access checks.
+  __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
+  __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
+  __ j(not_equal, &miss, not_taken);
   __ bind(&invoke);
   GenerateNormalHelper(masm, argc, false, &miss);
 
@@ -642,8 +667,8 @@
   __ j(zero, &miss, not_taken);
 
   // Check that the receiver is a valid JS object.
-  __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
-  __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
+  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
+  __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceTypeOffset));
   __ cmp(edx, FIRST_JS_OBJECT_TYPE);
   __ j(less, &miss, not_taken);
 
@@ -654,6 +679,11 @@
   __ cmp(edx, JS_GLOBAL_PROXY_TYPE);
   __ j(equal, &global, not_taken);
 
+  // Check for non-global object that requires access check.
+  __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
+  __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
+  __ j(not_zero, &miss, not_taken);
+
   // Search the dictionary placing the result in eax.
   __ bind(&probe);
   GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx);
diff --git a/src/ic-inl.h b/src/ic-inl.h
index 201048a..f5ce0ad 100644
--- a/src/ic-inl.h
+++ b/src/ic-inl.h
@@ -59,14 +59,11 @@
 
 
 Code* IC::GetTargetAtAddress(Address address) {
+  // Get the target address of the IC.
   Address target = Assembler::target_address_at(address);
-  HeapObject* code = HeapObject::FromAddress(target - Code::kHeaderSize);
-  // GetTargetAtAddress is called from IC::Clear which in turn is
-  // called when marking objects during mark sweep. reinterpret_cast
-  // is therefore used instead of the more appropriate
-  // Code::cast. Code::cast does not work when the object's map is
-  // marked.
-  Code* result = reinterpret_cast<Code*>(code);
+  // Convert target address to the code object. Code::GetCodeFromTargetAddress
+  // is safe for use during GC where the map might be marked.
+  Code* result = Code::GetCodeFromTargetAddress(target);
   ASSERT(result->is_inline_cache_stub());
   return result;
 }
diff --git a/src/ic.cc b/src/ic.cc
index c0b7624..2dc9742 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -514,11 +514,7 @@
     if (FLAG_strict || is_contextual()) {
       return ReferenceError("not_defined", name);
     }
-    String* class_name = object->IsJSObject()
-                         ? Handle<JSObject>::cast(object)->class_name()
-                         : Heap::empty_string();
-    LOG(SuspectReadEvent(*name, class_name));
-    USE(class_name);
+    LOG(SuspectReadEvent(*name, *object));
   }
 
   // Update inline cache and stub cache.
diff --git a/src/interpreter-irregexp.cc b/src/interpreter-irregexp.cc
index f76c135..1418443 100644
--- a/src/interpreter-irregexp.cc
+++ b/src/interpreter-irregexp.cc
@@ -60,6 +60,22 @@
 }
 
 
+static bool BackRefMatchesNoCase(int from,
+                                 int current,
+                                 int len,
+                                 Vector<const char> subject) {
+  for (int i = 0; i < len; i++) {
+    unsigned int old_char = subject[from++];
+    unsigned int new_char = subject[current++];
+    if (old_char == new_char) continue;
+    if (old_char - 'A' <= 'Z' - 'A') old_char |= 0x20;
+    if (new_char - 'A' <= 'Z' - 'A') new_char |= 0x20;
+    if (old_char != new_char) return false;
+  }
+  return true;
+}
+
+
 #ifdef DEBUG
 static void TraceInterpreter(const byte* code_base,
                              const byte* pc,
@@ -96,8 +112,9 @@
 
 
 
+template <typename Char>
 static bool RawMatch(const byte* code_base,
-                     Vector<const uc16> subject,
+                     Vector<const Char> subject,
                      int* registers,
                      int current,
                      int current_char) {
@@ -191,6 +208,15 @@
       BYTECODE(GOTO)
         pc = code_base + Load32(pc + 1);
         break;
+      BYTECODE(CHECK_GREEDY)
+        if (current == backtrack_sp[-1]) {
+          backtrack_sp--;
+          backtrack_stack_space++;
+          pc = code_base + Load32(pc + 1);
+        } else {
+          pc += BC_CHECK_GREEDY_LENGTH;
+        }
+        break;
       BYTECODE(LOAD_CURRENT_CHAR) {
         int pos = current + Load32(pc + 1);
         if (pos >= subject.length()) {
@@ -201,6 +227,12 @@
         }
         break;
       }
+      BYTECODE(LOAD_CURRENT_CHAR_UNCHECKED) {
+        int pos = current + Load32(pc + 1);
+        current_char = subject[pos];
+        pc += BC_LOAD_CURRENT_CHAR_UNCHECKED_LENGTH;
+        break;
+      }
       BYTECODE(CHECK_CHAR) {
         int c = Load16(pc + 1);
         if (c == current_char) {
@@ -366,6 +398,7 @@
           break;
         } else {
           if (BackRefMatchesNoCase(from, current, len, subject)) {
+            current += len;
             pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
           } else {
             pc = code_base + Load32(pc + 2);
@@ -389,23 +422,32 @@
 
 
 bool IrregexpInterpreter::Match(Handle<ByteArray> code_array,
-                                Handle<String> subject16,
+                                Handle<String> subject,
                                 int* registers,
                                 int start_position) {
-  ASSERT(StringShape(*subject16).IsTwoByteRepresentation());
-  ASSERT(subject16->IsFlat(StringShape(*subject16)));
+  ASSERT(subject->IsFlat(StringShape(*subject)));
 
   AssertNoAllocation a;
   const byte* code_base = code_array->GetDataStartAddress();
+  StringShape subject_shape(*subject);
   uc16 previous_char = '\n';
-  Vector<const uc16> subject_vector =
-      Vector<const uc16>(subject16->GetTwoByteData(), subject16->length());
-  if (start_position != 0) previous_char = subject_vector[start_position - 1];
-  return RawMatch(code_base,
-                  subject_vector,
-                  registers,
-                  start_position,
-                  previous_char);
+  if (subject_shape.IsAsciiRepresentation()) {
+    Vector<const char> subject_vector = subject->ToAsciiVector();
+    if (start_position != 0) previous_char = subject_vector[start_position - 1];
+    return RawMatch(code_base,
+                    subject_vector,
+                    registers,
+                    start_position,
+                    previous_char);
+  } else {
+    Vector<const uc16> subject_vector = subject->ToUC16Vector();
+    if (start_position != 0) previous_char = subject_vector[start_position - 1];
+    return RawMatch(code_base,
+                    subject_vector,
+                    registers,
+                    start_position,
+                    previous_char);
+  }
 }
 
 } }  // namespace v8::internal
diff --git a/src/interpreter-irregexp.h b/src/interpreter-irregexp.h
index 2393d74..c65cb9e 100644
--- a/src/interpreter-irregexp.h
+++ b/src/interpreter-irregexp.h
@@ -36,7 +36,7 @@
 class IrregexpInterpreter {
  public:
   static bool Match(Handle<ByteArray> code,
-                    Handle<String> subject16,
+                    Handle<String> subject,
                     int* captures,
                     int start_position);
 };
diff --git a/src/jsregexp-inl.h b/src/jsregexp-inl.h
index 9371703..09c4c8f 100644
--- a/src/jsregexp-inl.h
+++ b/src/jsregexp-inl.h
@@ -253,11 +253,6 @@
 }
 
 
-void RegExpNode::Bind(RegExpMacroAssembler* macro) {
-  macro->Bind(&label_);
-}
-
-
 }}  // namespace v8::internal
 
 
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index 3046b96..b6165c4 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -201,6 +201,50 @@
 }
 
 
+// Generic RegExp methods. Dispatches to implementation specific methods.
+
+
+class OffsetsVector {
+ public:
+  inline OffsetsVector(int num_registers)
+      : offsets_vector_length_(num_registers) {
+    if (offsets_vector_length_ > kStaticOffsetsVectorSize) {
+      vector_ = NewArray<int>(offsets_vector_length_);
+    } else {
+      vector_ = static_offsets_vector_;
+    }
+  }
+
+
+  inline ~OffsetsVector() {
+    if (offsets_vector_length_ > kStaticOffsetsVectorSize) {
+      DeleteArray(vector_);
+      vector_ = NULL;
+    }
+  }
+
+
+  inline int* vector() {
+    return vector_;
+  }
+
+
+  inline int length() {
+    return offsets_vector_length_;
+  }
+
+ private:
+  int* vector_;
+  int offsets_vector_length_;
+  static const int kStaticOffsetsVectorSize = 50;
+  static int static_offsets_vector_[kStaticOffsetsVectorSize];
+};
+
+
+int OffsetsVector::static_offsets_vector_[
+    OffsetsVector::kStaticOffsetsVectorSize];
+
+
 Handle<Object> RegExpImpl::Compile(Handle<JSRegExp> re,
                                    Handle<String> pattern,
                                    Handle<String> flag_str) {
@@ -216,7 +260,7 @@
   } else {
     FlattenString(pattern);
     ZoneScope zone_scope(DELETE_ON_EXIT);
-    RegExpParseResult parse_result;
+    RegExpCompileData parse_result;
     FlatStringReader reader(pattern);
     if (!ParseRegExp(&reader, flags.is_multiline(), &parse_result)) {
       // Throw an exception if we fail to parse the pattern.
@@ -224,7 +268,7 @@
                            pattern,
                            parse_result.error,
                            "malformed_regexp");
-      return Handle<Object>();
+      return Handle<Object>::null();
     }
     RegExpAtom* atom = parse_result.tree->AsAtom();
     if (atom != NULL && !flags.is_ignore_case()) {
@@ -237,19 +281,10 @@
         result = AtomCompile(re, pattern, flags, pattern);
       }
     } else {
-      RegExpNode* node = NULL;
-      Handle<FixedArray> irregexp_data =
-          RegExpEngine::Compile(&parse_result,
-                                &node,
-                                flags.is_ignore_case(),
-                                flags.is_multiline());
-      if (irregexp_data.is_null()) {
-        if (FLAG_disable_jscre) {
-          UNIMPLEMENTED();
-        }
-        result = JscrePrepare(re, pattern, flags);
+      if (FLAG_irregexp) {
+        result = IrregexpPrepare(re, pattern, flags);
       } else {
-        result = IrregexpPrepare(re, pattern, flags, irregexp_data);
+        result = JscrePrepare(re, pattern, flags);
       }
     }
     Object* data = re->data();
@@ -269,18 +304,29 @@
                                 Handle<String> subject,
                                 Handle<Object> index) {
   switch (regexp->TypeTag()) {
+    case JSRegExp::ATOM:
+      return AtomExec(regexp, subject, index);
+    case JSRegExp::IRREGEXP: {
+      Handle<Object> result = IrregexpExec(regexp, subject, index);
+      if (!result.is_null()) {
+        return result;
+      }
+      // We couldn't handle the regexp using Irregexp, so fall back
+      // on JSCRE.
+      // Reset the JSRegExp to use JSCRE.
+      JscrePrepare(regexp,
+                   Handle<String>(regexp->Pattern()),
+                   regexp->GetFlags());
+      // Fall-through to JSCRE.
+    }
     case JSRegExp::JSCRE:
       if (FLAG_disable_jscre) {
         UNIMPLEMENTED();
       }
       return JscreExec(regexp, subject, index);
-    case JSRegExp::ATOM:
-      return AtomExec(regexp, subject, index);
-    case JSRegExp::IRREGEXP:
-      return IrregexpExec(regexp, subject, index);
     default:
       UNREACHABLE();
-      return Handle<Object>();
+      return Handle<Object>::null();
   }
 }
 
@@ -288,22 +334,36 @@
 Handle<Object> RegExpImpl::ExecGlobal(Handle<JSRegExp> regexp,
                                 Handle<String> subject) {
   switch (regexp->TypeTag()) {
+    case JSRegExp::ATOM:
+      return AtomExecGlobal(regexp, subject);
+    case JSRegExp::IRREGEXP: {
+      Handle<Object> result = IrregexpExecGlobal(regexp, subject);
+      if (!result.is_null()) {
+        return result;
+      }
+      // We couldn't handle the regexp using Irregexp, so fall back
+      // on JSCRE.
+      // Reset the JSRegExp to use JSCRE.
+      JscrePrepare(regexp,
+                   Handle<String>(regexp->Pattern()),
+                   regexp->GetFlags());
+      // Fall-through to JSCRE.
+    }
     case JSRegExp::JSCRE:
       if (FLAG_disable_jscre) {
         UNIMPLEMENTED();
       }
       return JscreExecGlobal(regexp, subject);
-    case JSRegExp::ATOM:
-      return AtomExecGlobal(regexp, subject);
-    case JSRegExp::IRREGEXP:
-      return IrregexpExecGlobal(regexp, subject);
     default:
       UNREACHABLE();
-      return Handle<Object>();
+      return Handle<Object>::null();
   }
 }
 
 
+// RegExp Atom implementation: Simple string search using indexOf.
+
+
 Handle<Object> RegExpImpl::AtomCompile(Handle<JSRegExp> re,
                                        Handle<String> pattern,
                                        JSRegExp::Flags flags,
@@ -365,6 +425,21 @@
 }
 
 
+// JSCRE implementation.
+
+
+int RegExpImpl::JscreNumberOfCaptures(Handle<JSRegExp> re) {
+  FixedArray* value = FixedArray::cast(re->DataAt(JSRegExp::kJscreDataIndex));
+  return Smi::cast(value->get(kJscreNumberOfCapturesIndex))->value();
+}
+
+
+ByteArray* RegExpImpl::JscreInternal(Handle<JSRegExp> re) {
+  FixedArray* value = FixedArray::cast(re->DataAt(JSRegExp::kJscreDataIndex));
+  return ByteArray::cast(value->get(kJscreInternalIndex));
+}
+
+
 Handle<Object>RegExpImpl::JscrePrepare(Handle<JSRegExp> re,
                                        Handle<String> pattern,
                                        JSRegExp::Flags flags) {
@@ -374,20 +449,11 @@
 }
 
 
-Handle<Object>RegExpImpl::IrregexpPrepare(Handle<JSRegExp> re,
-                                          Handle<String> pattern,
-                                          JSRegExp::Flags flags,
-                                          Handle<FixedArray> irregexp_data) {
-  Factory::SetRegExpData(re, JSRegExp::IRREGEXP, pattern, flags, irregexp_data);
-  return re;
-}
-
-
-static inline Object* DoCompile(String* pattern,
-                                JSRegExp::Flags flags,
-                                unsigned* number_of_captures,
-                                const char** error_message,
-                                v8::jscre::JscreRegExp** code) {
+static inline Object* JscreDoCompile(String* pattern,
+                                     JSRegExp::Flags flags,
+                                     unsigned* number_of_captures,
+                                     const char** error_message,
+                                     v8::jscre::JscreRegExp** code) {
   v8::jscre::JSRegExpIgnoreCaseOption case_option = flags.is_ignore_case()
     ? v8::jscre::JSRegExpIgnoreCase
     : v8::jscre::JSRegExpDoNotIgnoreCase;
@@ -416,16 +482,16 @@
 }
 
 
-void CompileWithRetryAfterGC(Handle<String> pattern,
-                             JSRegExp::Flags flags,
-                             unsigned* number_of_captures,
-                             const char** error_message,
-                             v8::jscre::JscreRegExp** code) {
-  CALL_HEAP_FUNCTION_VOID(DoCompile(*pattern,
-                                    flags,
-                                    number_of_captures,
-                                    error_message,
-                                    code));
+static void JscreCompileWithRetryAfterGC(Handle<String> pattern,
+                                         JSRegExp::Flags flags,
+                                         unsigned* number_of_captures,
+                                         const char** error_message,
+                                         v8::jscre::JscreRegExp** code) {
+  CALL_HEAP_FUNCTION_VOID(JscreDoCompile(*pattern,
+                                         flags,
+                                         number_of_captures,
+                                         error_message,
+                                         code));
 }
 
 
@@ -444,11 +510,11 @@
   v8::jscre::JscreRegExp* code = NULL;
   FlattenString(pattern);
 
-  CompileWithRetryAfterGC(two_byte_pattern,
-                          flags,
-                          &number_of_captures,
-                          &error_message,
-                          &code);
+  JscreCompileWithRetryAfterGC(two_byte_pattern,
+                               flags,
+                               &number_of_captures,
+                               &error_message,
+                               &code);
 
   if (code == NULL) {
     // Throw an exception.
@@ -475,92 +541,31 @@
 }
 
 
-Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<JSRegExp> regexp,
-                                            int num_captures,
-                                            Handle<String> two_byte_subject,
-                                            int previous_index,
-                                            int* offsets_vector,
-                                            int offsets_vector_length) {
-#ifdef DEBUG
-  if (FLAG_trace_regexp_bytecodes) {
-    String* pattern = regexp->Pattern();
-    PrintF("\n\nRegexp match:   /%s/\n\n", *(pattern->ToCString()));
-    PrintF("\n\nSubject string: '%s'\n\n", *(two_byte_subject->ToCString()));
+Handle<Object> RegExpImpl::JscreExec(Handle<JSRegExp> regexp,
+                                     Handle<String> subject,
+                                     Handle<Object> index) {
+  ASSERT_EQ(regexp->TypeTag(), JSRegExp::JSCRE);
+  if (regexp->DataAt(JSRegExp::kJscreDataIndex)->IsUndefined()) {
+    Handle<Object> compile_result = JscreCompile(regexp);
+    if (compile_result.is_null()) return compile_result;
   }
-#endif
-  ASSERT(StringShape(*two_byte_subject).IsTwoByteRepresentation());
-  ASSERT(two_byte_subject->IsFlat(StringShape(*two_byte_subject)));
-  bool rc;
+  ASSERT(regexp->DataAt(JSRegExp::kJscreDataIndex)->IsFixedArray());
 
-  for (int i = (num_captures + 1) * 2 - 1; i >= 0; i--) {
-    offsets_vector[i] = -1;
-  }
+  int num_captures = JscreNumberOfCaptures(regexp);
 
-  LOG(RegExpExecEvent(regexp, previous_index, two_byte_subject));
+  OffsetsVector offsets((num_captures + 1) * 3);
 
-  FixedArray* irregexp =
-      FixedArray::cast(regexp->DataAt(JSRegExp::kIrregexpDataIndex));
-  int tag = Smi::cast(irregexp->get(kIrregexpImplementationIndex))->value();
+  int previous_index = static_cast<int>(DoubleToInteger(index->Number()));
 
-  switch (tag) {
-    case RegExpMacroAssembler::kIA32Implementation: {
-#ifndef ARM
-      Code* code = Code::cast(irregexp->get(kIrregexpCodeIndex));
-      Address start_addr =
-          Handle<SeqTwoByteString>::cast(two_byte_subject)->GetCharsAddress();
-      int string_offset =
-          start_addr - reinterpret_cast<Address>(*two_byte_subject);
-      int start_offset = string_offset + previous_index * sizeof(uc16);
-      int end_offset =
-          string_offset + two_byte_subject->length() * sizeof(uc16);
-      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++) {
-          if (offsets_vector[i] >= 0) {
-            offsets_vector[i] += previous_index;
-          }
-        }
-      }
-      break;
-#else
-      UNIMPLEMENTED();
-      rc = false;
-      break;
-#endif
-    }
-    case RegExpMacroAssembler::kBytecodeImplementation: {
-      Handle<ByteArray> byte_codes = IrregexpCode(regexp);
+  Handle<String> subject16 = CachedStringToTwoByte(subject);
 
-      rc = IrregexpInterpreter::Match(byte_codes,
-                                      two_byte_subject,
-                                      offsets_vector,
-                                      previous_index);
-      break;
-    }
-    case RegExpMacroAssembler::kARMImplementation:
-    default:
-      UNREACHABLE();
-      rc = false;
-      break;
-  }
-
-  if (!rc) {
-    return Factory::null_value();
-  }
-
-  Handle<FixedArray> array = Factory::NewFixedArray(2 * (num_captures+1));
-  // The captures come in (start, end+1) pairs.
-  for (int i = 0; i < 2 * (num_captures+1); i += 2) {
-    array->set(i, Smi::FromInt(offsets_vector[i]));
-    array->set(i+1, Smi::FromInt(offsets_vector[i+1]));
-  }
-  return Factory::NewJSArrayWithElements(array);
+  return JscreExecOnce(regexp,
+                       num_captures,
+                       subject,
+                       previous_index,
+                       subject16->GetTwoByteData(),
+                       offsets.vector(),
+                       offsets.length());
 }
 
 
@@ -616,155 +621,6 @@
 }
 
 
-class OffsetsVector {
- public:
-  inline OffsetsVector(int num_registers)
-      : offsets_vector_length_(num_registers) {
-    if (offsets_vector_length_ > kStaticOffsetsVectorSize) {
-      vector_ = NewArray<int>(offsets_vector_length_);
-    } else {
-      vector_ = static_offsets_vector_;
-    }
-  }
-
-
-  inline ~OffsetsVector() {
-    if (offsets_vector_length_ > kStaticOffsetsVectorSize) {
-      DeleteArray(vector_);
-      vector_ = NULL;
-    }
-  }
-
-
-  inline int* vector() {
-    return vector_;
-  }
-
-
-  inline int length() {
-    return offsets_vector_length_;
-  }
-
- private:
-  int* vector_;
-  int offsets_vector_length_;
-  static const int kStaticOffsetsVectorSize = 50;
-  static int static_offsets_vector_[kStaticOffsetsVectorSize];
-};
-
-
-int OffsetsVector::static_offsets_vector_[
-    OffsetsVector::kStaticOffsetsVectorSize];
-
-
-Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> regexp,
-                                        Handle<String> subject,
-                                        Handle<Object> index) {
-  ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
-  ASSERT(!regexp->DataAt(JSRegExp::kIrregexpDataIndex)->IsUndefined());
-
-  // Prepare space for the return values.
-  int number_of_registers = IrregexpNumberOfRegisters(regexp);
-  OffsetsVector offsets(number_of_registers);
-
-  int num_captures = IrregexpNumberOfCaptures(regexp);
-
-  int previous_index = static_cast<int>(DoubleToInteger(index->Number()));
-
-  Handle<String> subject16 = CachedStringToTwoByte(subject);
-
-  Handle<Object> result(IrregexpExecOnce(regexp,
-                                         num_captures,
-                                         subject16,
-                                         previous_index,
-                                         offsets.vector(),
-                                         offsets.length()));
-  return result;
-}
-
-
-Handle<Object> RegExpImpl::JscreExec(Handle<JSRegExp> regexp,
-                                     Handle<String> subject,
-                                     Handle<Object> index) {
-  ASSERT_EQ(regexp->TypeTag(), JSRegExp::JSCRE);
-  if (regexp->DataAt(JSRegExp::kJscreDataIndex)->IsUndefined()) {
-    Handle<Object> compile_result = JscreCompile(regexp);
-    if (compile_result.is_null()) return compile_result;
-  }
-  ASSERT(regexp->DataAt(JSRegExp::kJscreDataIndex)->IsFixedArray());
-
-  int num_captures = JscreNumberOfCaptures(regexp);
-
-  OffsetsVector offsets((num_captures + 1) * 3);
-
-  int previous_index = static_cast<int>(DoubleToInteger(index->Number()));
-
-  Handle<String> subject16 = CachedStringToTwoByte(subject);
-
-  Handle<Object> result(JscreExecOnce(regexp,
-                                      num_captures,
-                                      subject,
-                                      previous_index,
-                                      subject16->GetTwoByteData(),
-                                      offsets.vector(),
-                                      offsets.length()));
-
-  return result;
-}
-
-
-Handle<Object> RegExpImpl::IrregexpExecGlobal(Handle<JSRegExp> regexp,
-                                              Handle<String> subject) {
-  ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
-  ASSERT(!regexp->DataAt(JSRegExp::kIrregexpDataIndex)->IsUndefined());
-
-  // Prepare space for the return values.
-  int number_of_registers = IrregexpNumberOfRegisters(regexp);
-  OffsetsVector offsets(number_of_registers);
-
-  int previous_index = 0;
-
-  Handle<JSArray> result = Factory::NewJSArray(0);
-  int i = 0;
-  Handle<Object> matches;
-
-  Handle<String> subject16 = CachedStringToTwoByte(subject);
-
-  do {
-    if (previous_index > subject->length() || previous_index < 0) {
-      // Per ECMA-262 15.10.6.2, if the previous index is greater than the
-      // string length, there is no match.
-      matches = Factory::null_value();
-    } else {
-      matches = IrregexpExecOnce(regexp,
-                                 IrregexpNumberOfCaptures(regexp),
-                                 subject16,
-                                 previous_index,
-                                 offsets.vector(),
-                                 offsets.length());
-
-      if (matches->IsJSArray()) {
-        SetElement(result, i, matches);
-        i++;
-        previous_index = offsets.vector()[1];
-        if (offsets.vector()[0] == offsets.vector()[1]) {
-          previous_index++;
-        }
-      }
-    }
-  } while (matches->IsJSArray());
-
-  // If we exited the loop with an exception, throw it.
-  if (matches->IsNull()) {
-    // Exited loop normally.
-    return result;
-  } else {
-    // Exited loop with the exception in matches.
-    return matches;
-  }
-}
-
-
 Handle<Object> RegExpImpl::JscreExecGlobal(Handle<JSRegExp> regexp,
                                            Handle<String> subject) {
   ASSERT_EQ(regexp->TypeTag(), JSRegExp::JSCRE);
@@ -823,41 +679,466 @@
 }
 
 
-int RegExpImpl::JscreNumberOfCaptures(Handle<JSRegExp> re) {
-  FixedArray* value = FixedArray::cast(re->DataAt(JSRegExp::kJscreDataIndex));
-  return Smi::cast(value->get(kJscreNumberOfCapturesIndex))->value();
+// Irregexp implementation.
+
+
+static Handle<FixedArray> GetCompiledIrregexp(Handle<JSRegExp> re,
+                                              bool is_ascii) {
+  ASSERT(re->DataAt(JSRegExp::kIrregexpDataIndex)->IsFixedArray());
+  Handle<FixedArray> alternatives(
+      FixedArray::cast(re->DataAt(JSRegExp::kIrregexpDataIndex)));
+  ASSERT_EQ(2, alternatives->length());
+
+  int index = is_ascii ? 0 : 1;
+  Object* entry = alternatives->get(index);
+  if (!entry->IsNull()) {
+    return Handle<FixedArray>(FixedArray::cast(entry));
+  }
+
+  // Compile the RegExp.
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+
+  JSRegExp::Flags flags = re->GetFlags();
+
+  Handle<String> pattern(re->Pattern());
+  StringShape shape(*pattern);
+  if (!pattern->IsFlat(shape)) {
+    pattern->Flatten(shape);
+  }
+
+  RegExpCompileData compile_data;
+  FlatStringReader reader(pattern);
+  if (!ParseRegExp(&reader, flags.is_multiline(), &compile_data)) {
+    // Throw an exception if we fail to parse the pattern.
+    // THIS SHOULD NOT HAPPEN. We already parsed it successfully once.
+    ThrowRegExpException(re,
+                         pattern,
+                         compile_data.error,
+                         "malformed_regexp");
+    return Handle<FixedArray>::null();
+  }
+  Handle<FixedArray> compiled_entry =
+      RegExpEngine::Compile(&compile_data,
+                            flags.is_ignore_case(),
+                            flags.is_multiline(),
+                            pattern,
+                            is_ascii);
+  if (!compiled_entry.is_null()) {
+    alternatives->set(index, *compiled_entry);
+  }
+  return compiled_entry;
 }
 
 
-ByteArray* RegExpImpl::JscreInternal(Handle<JSRegExp> re) {
-  FixedArray* value = FixedArray::cast(re->DataAt(JSRegExp::kJscreDataIndex));
-  return ByteArray::cast(value->get(kJscreInternalIndex));
+int RegExpImpl::IrregexpNumberOfCaptures(Handle<FixedArray> irre) {
+  return Smi::cast(irre->get(kIrregexpNumberOfCapturesIndex))->value();
 }
 
 
-int RegExpImpl::IrregexpNumberOfCaptures(Handle<JSRegExp> re) {
-  FixedArray* value =
-      FixedArray::cast(re->DataAt(JSRegExp::kIrregexpDataIndex));
-  return Smi::cast(value->get(kIrregexpNumberOfCapturesIndex))->value();
+int RegExpImpl::IrregexpNumberOfRegisters(Handle<FixedArray> irre) {
+  return Smi::cast(irre->get(kIrregexpNumberOfRegistersIndex))->value();
 }
 
 
-int RegExpImpl::IrregexpNumberOfRegisters(Handle<JSRegExp> re) {
-  FixedArray* value =
-      FixedArray::cast(re->DataAt(JSRegExp::kIrregexpDataIndex));
-  return Smi::cast(value->get(kIrregexpNumberOfRegistersIndex))->value();
+Handle<ByteArray> RegExpImpl::IrregexpByteCode(Handle<FixedArray> irre) {
+  ASSERT(Smi::cast(irre->get(kIrregexpImplementationIndex))->value()
+      == RegExpMacroAssembler::kBytecodeImplementation);
+  return Handle<ByteArray>(ByteArray::cast(irre->get(kIrregexpCodeIndex)));
 }
 
 
-Handle<ByteArray> RegExpImpl::IrregexpCode(Handle<JSRegExp> re) {
-  FixedArray* value =
-      FixedArray::cast(re->DataAt(JSRegExp::kIrregexpDataIndex));
-  return Handle<ByteArray>(ByteArray::cast(value->get(kIrregexpCodeIndex)));
+Handle<Code> RegExpImpl::IrregexpNativeCode(Handle<FixedArray> irre) {
+  ASSERT(Smi::cast(irre->get(kIrregexpImplementationIndex))->value()
+      != RegExpMacroAssembler::kBytecodeImplementation);
+  return Handle<Code>(Code::cast(irre->get(kIrregexpCodeIndex)));
+}
+
+
+Handle<Object>RegExpImpl::IrregexpPrepare(Handle<JSRegExp> re,
+                                          Handle<String> pattern,
+                                          JSRegExp::Flags flags) {
+  // Make space for ASCII and UC16 versions.
+  Handle<FixedArray> alternatives = Factory::NewFixedArray(2);
+  alternatives->set_null(0);
+  alternatives->set_null(1);
+  Factory::SetRegExpData(re, JSRegExp::IRREGEXP, pattern, flags, alternatives);
+  return re;
+}
+
+
+Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> regexp,
+                                        Handle<String> subject,
+                                        Handle<Object> index) {
+  ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
+  ASSERT(regexp->DataAt(JSRegExp::kIrregexpDataIndex)->IsFixedArray());
+
+  bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
+  Handle<FixedArray> irregexp = GetCompiledIrregexp(regexp, is_ascii);
+  if (irregexp.is_null()) {
+    // We can't handle the RegExp with IRRegExp.
+    return Handle<Object>::null();
+  }
+
+  // Prepare space for the return values.
+  int number_of_registers = IrregexpNumberOfRegisters(irregexp);
+  OffsetsVector offsets(number_of_registers);
+
+  int num_captures = IrregexpNumberOfCaptures(irregexp);
+
+  int previous_index = static_cast<int>(DoubleToInteger(index->Number()));
+
+#ifdef DEBUG
+  if (FLAG_trace_regexp_bytecodes) {
+    String* pattern = regexp->Pattern();
+    PrintF("\n\nRegexp match:   /%s/\n\n", *(pattern->ToCString()));
+    PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString()));
+  }
+#endif
+  LOG(RegExpExecEvent(regexp, previous_index, subject));
+  return IrregexpExecOnce(irregexp,
+                          num_captures,
+                          subject,
+                          previous_index,
+                          offsets.vector(),
+                          offsets.length());
+}
+
+
+Handle<Object> RegExpImpl::IrregexpExecGlobal(Handle<JSRegExp> regexp,
+                                              Handle<String> subject) {
+  ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
+
+  StringShape shape(*subject);
+  bool is_ascii = shape.IsAsciiRepresentation();
+  Handle<FixedArray> irregexp = GetCompiledIrregexp(regexp, is_ascii);
+  if (irregexp.is_null()) {
+    return Handle<Object>::null();
+  }
+
+  // Prepare space for the return values.
+  int number_of_registers = IrregexpNumberOfRegisters(irregexp);
+  OffsetsVector offsets(number_of_registers);
+
+  int previous_index = 0;
+
+  Handle<JSArray> result = Factory::NewJSArray(0);
+  int i = 0;
+  Handle<Object> matches;
+
+  if (!subject->IsFlat(shape)) {
+    subject->Flatten(shape);
+  }
+
+  do {
+    if (previous_index > subject->length() || previous_index < 0) {
+      // Per ECMA-262 15.10.6.2, if the previous index is greater than the
+      // string length, there is no match.
+      matches = Factory::null_value();
+    } else {
+#ifdef DEBUG
+      if (FLAG_trace_regexp_bytecodes) {
+        String* pattern = regexp->Pattern();
+        PrintF("\n\nRegexp match:   /%s/\n\n", *(pattern->ToCString()));
+        PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString()));
+      }
+#endif
+      LOG(RegExpExecEvent(regexp, previous_index, subject));
+      matches = IrregexpExecOnce(irregexp,
+                                 IrregexpNumberOfCaptures(irregexp),
+                                 subject,
+                                 previous_index,
+                                 offsets.vector(),
+                                 offsets.length());
+
+      if (matches->IsJSArray()) {
+        SetElement(result, i, matches);
+        i++;
+        previous_index = offsets.vector()[1];
+        if (offsets.vector()[0] == offsets.vector()[1]) {
+          previous_index++;
+        }
+      }
+    }
+  } while (matches->IsJSArray());
+
+  // If we exited the loop with an exception, throw it.
+  if (matches->IsNull()) {
+    // Exited loop normally.
+    return result;
+  } else {
+    // Exited loop with the exception in matches.
+    return matches;
+  }
+}
+
+
+Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp,
+                                            int num_captures,
+                                            Handle<String> subject,
+                                            int previous_index,
+                                            int* offsets_vector,
+                                            int offsets_vector_length) {
+  bool rc;
+
+  int tag = Smi::cast(irregexp->get(kIrregexpImplementationIndex))->value();
+
+  if (!subject->IsFlat(StringShape(*subject))) {
+    FlattenString(subject);
+  }
+
+  switch (tag) {
+    case RegExpMacroAssembler::kIA32Implementation: {
+#ifndef ARM
+      Handle<Code> code = IrregexpNativeCode(irregexp);
+
+      StringShape shape(*subject);
+
+      // Character offsets into string.
+      int start_offset = previous_index;
+      int end_offset = subject->length(shape);
+
+      if (shape.IsCons()) {
+        subject = Handle<String>(ConsString::cast(*subject)->first());
+      } else if (shape.IsSliced()) {
+        SlicedString* slice = SlicedString::cast(*subject);
+        start_offset += slice->start();
+        end_offset += slice->start();
+        subject = Handle<String>(slice->buffer());
+      }
+
+      // String is now either Sequential or External
+      StringShape flatshape(*subject);
+      bool is_ascii = flatshape.IsAsciiRepresentation();
+      int char_size_shift = is_ascii ? 0 : 1;
+
+      if (flatshape.IsExternal()) {
+        const byte* address;
+        if (is_ascii) {
+          ExternalAsciiString* ext = ExternalAsciiString::cast(*subject);
+          address = reinterpret_cast<const byte*>(ext->resource()->data());
+        } else {
+          ExternalTwoByteString* ext = ExternalTwoByteString::cast(*subject);
+          address = reinterpret_cast<const byte*>(ext->resource()->data());
+        }
+        rc = RegExpMacroAssemblerIA32::Execute(
+            *code,
+            &address,
+            start_offset << char_size_shift,
+            end_offset << char_size_shift,
+            offsets_vector,
+            previous_index == 0);
+      } else {  // Sequential string
+        Address char_address =
+            is_ascii ? SeqAsciiString::cast(*subject)->GetCharsAddress()
+                     : SeqTwoByteString::cast(*subject)->GetCharsAddress();
+        int byte_offset = char_address - reinterpret_cast<Address>(*subject);
+        rc = RegExpMacroAssemblerIA32::Execute(
+            *code,
+            subject.location(),
+            byte_offset + (start_offset << char_size_shift),
+            byte_offset + (end_offset << char_size_shift),
+            offsets_vector,
+            previous_index == 0);
+      }
+
+      if (rc) {
+        // Capture values are relative to start_offset only.
+        for (int i = 0; i < offsets_vector_length; i++) {
+          if (offsets_vector[i] >= 0) {
+            offsets_vector[i] += previous_index;
+          }
+        }
+      }
+      break;
+#else
+      UNIMPLEMENTED();
+      rc = false;
+      break;
+#endif
+    }
+    case RegExpMacroAssembler::kBytecodeImplementation: {
+      for (int i = (num_captures + 1) * 2 - 1; i >= 0; i--) {
+        offsets_vector[i] = -1;
+      }
+      Handle<ByteArray> byte_codes = IrregexpByteCode(irregexp);
+
+      rc = IrregexpInterpreter::Match(byte_codes,
+                                      subject,
+                                      offsets_vector,
+                                      previous_index);
+      break;
+    }
+    case RegExpMacroAssembler::kARMImplementation:
+    default:
+      UNREACHABLE();
+      rc = false;
+      break;
+  }
+
+  if (!rc) {
+    return Factory::null_value();
+  }
+
+  Handle<FixedArray> array = Factory::NewFixedArray(2 * (num_captures+1));
+  // The captures come in (start, end+1) pairs.
+  for (int i = 0; i < 2 * (num_captures+1); i += 2) {
+    array->set(i, Smi::FromInt(offsets_vector[i]));
+    array->set(i+1, Smi::FromInt(offsets_vector[i+1]));
+  }
+  return Factory::NewJSArrayWithElements(array);
 }
 
 
 // -------------------------------------------------------------------
 // Implmentation of the Irregexp regular expression engine.
+//
+// The Irregexp regular expression engine is intended to be a complete
+// implementation of ECMAScript regular expressions.  It generates either
+// bytecodes or native code.
+
+//   The Irregexp regexp engine is structured in three steps.
+//   1) The parser generates an abstract syntax tree.  See ast.cc.
+//   2) From the AST a node network is created.  The nodes are all
+//      subclasses of RegExpNode.  The nodes represent states when
+//      executing a regular expression.  Several optimizations are
+//      performed on the node network.
+//   3) From the nodes we generate either byte codes or native code
+//      that can actually execute the regular expression (perform
+//      the search).  The code generation step is described in more
+//      detail below.
+
+// Code generation.
+//
+//   The nodes are divided into four main categories.
+//   * Choice nodes
+//        These represent places where the regular expression can
+//        match in more than one way.  For example on entry to an
+//        alternation (foo|bar) or a repetition (*, +, ? or {}).
+//   * Action nodes
+//        These represent places where some action should be
+//        performed.  Examples include recording the current position
+//        in the input string to a register (in order to implement
+//        captures) or other actions on register for example in order
+//        to implement the counters needed for {} repetitions.
+//   * Matching nodes
+//        These attempt to match some element part of the input string.
+//        Examples of elements include character classes, plain strings
+//        or back references.
+//   * End nodes
+//        These are used to implement the actions required on finding
+//        a successful match or failing to find a match.
+//
+//   The code generated (whether as byte codes or native code) maintains
+//   some state as it runs.  This consists of the following elements:
+//
+//   * The capture registers.  Used for string captures.
+//   * Other registers.  Used for counters etc.
+//   * The current position.
+//   * The stack of backtracking information.  Used when a matching node
+//     fails to find a match and needs to try an alternative.
+//
+// Conceptual regular expression execution model:
+//
+//   There is a simple conceptual model of regular expression execution
+//   which will be presented first.  The actual code generated is a more
+//   efficient simulation of the simple conceptual model:
+//
+//   * Choice nodes are implemented as follows:
+//     For each choice except the last {
+//       push current position
+//       push backtrack code location
+//       <generate code to test for choice>
+//       backtrack code location:
+//       pop current position
+//     }
+//     <generate code to test for last choice>
+//
+//   * Actions nodes are generated as follows
+//     <push affected registers on backtrack stack>
+//     <generate code to perform action>
+//     push backtrack code location
+//     <generate code to test for following nodes>
+//     backtrack code location:
+//     <pop affected registers to restore their state>
+//     <pop backtrack location from stack and go to it>
+//
+//   * Matching nodes are generated as follows:
+//     if input string matches at current position
+//       update current position
+//       <generate code to test for following nodes>
+//     else
+//       <pop backtrack location from stack and go to it>
+//
+//   Thus it can be seen that the current position is saved and restored
+//   by the choice nodes, whereas the registers are saved and restored by
+//   by the action nodes that manipulate them.
+//
+//   The other interesting aspect of this model is that nodes are generated
+//   at the point where they are needed by a recursive call to Emit().  If
+//   the node has already been code generated then the Emit() call will
+//   generate a jump to the previously generated code instead.  In order to
+//   limit recursion it is possible for the Emit() function to put the node
+//   on a work list for later generation and instead generate a jump.  The
+//   destination of the jump is resolved later when the code is generated.
+//
+// Actual regular expression code generation.
+//
+//   Code generation is actually more complicated than the above.  In order
+//   to improve the efficiency of the generated code some optimizations are
+//   performed
+//
+//   * Choice nodes have 1-character lookahead.
+//     A choice node looks at the following character and eliminates some of
+//     the choices immediately based on that character.  This is not yet
+//     implemented.
+//   * Simple greedy loops store reduced backtracking information.
+//     A quantifier like /.*foo/m will greedily match the whole input.  It will
+//     then need to backtrack to a point where it can match "foo".  The naive
+//     implementation of this would push each character position onto the
+//     backtracking stack, then pop them off one by one.  This would use space
+//     proportional to the length of the input string.  However since the "."
+//     can only match in one way and always has a constant length (in this case
+//     of 1) it suffices to store the current position on the top of the stack
+//     once.  Matching now becomes merely incrementing the current position and
+//     backtracking becomes decrementing the current position and checking the
+//     result against the stored current position.  This is faster and saves
+//     space.
+//   * The current state is virtualized.
+//     This is used to defer expensive operations until it is clear that they
+//     are needed and to generate code for a node more than once, allowing
+//     specialized an efficient versions of the code to be created. This is
+//     explained in the section below.
+//
+// Execution state virtualization.
+//
+//   Instead of emitting code, nodes that manipulate the state can record their
+//   manipulation in an object called the GenerationVariant.  The
+//   GenerationVariant object can record a current position offset, an
+//   optional backtrack code location on the top of the virtualized backtrack
+//   stack and some register changes.  When a node is to be emitted it can flush
+//   the GenerationVariant or update it.  Flushing the GenerationVariant
+//   will emit code to bring the actual state into line with the virtual state.
+//   Avoiding flushing the state can postpone some work (eg updates of capture
+//   registers).  Postponing work can save time when executing the regular
+//   expression since it may be found that the work never has to be done as a
+//   failure to match can occur.  In addition it is much faster to jump to a
+//   known backtrack code location than it is to pop an unknown backtrack
+//   location from the stack and jump there.
+//
+//   The virtual state found in the GenerationVariant affects code generation.
+//   For example the virtual state contains the difference between the actual
+//   current position and the virtual current position, and matching code needs
+//   to use this offset to attempt a match in the correct location of the input
+//   string.  Therefore code generated for a non-trivial GenerationVariant is
+//   specialized to that GenerationVariant.  The code generator therefore
+//   has the ability to generate code for each node several times.  In order to
+//   limit the size of the generated code there is an arbitrary limit on how
+//   many specialized sets of code may be generated for a given node.  If the
+//   limit is reached, the GenerationVariant is flushed and a generic version of
+//   the code for a node is emitted.  This is subsequently used for that node.
+//   The code emitted for non-generic GenerationVariants is not recorded in the
+//   node and so it cannot currently be reused in the event that code generation
+//   is requested for an identical GenerationVariant.
 
 
 void RegExpTree::AppendToText(RegExpText* text) {
@@ -908,13 +1189,14 @@
 
 class RegExpCompiler {
  public:
-  RegExpCompiler(int capture_count, bool ignore_case);
+  RegExpCompiler(int capture_count, bool ignore_case, bool is_ascii);
 
   int AllocateRegister() { return next_register_++; }
 
   Handle<FixedArray> Assemble(RegExpMacroAssembler* assembler,
                               RegExpNode* start,
-                              int capture_count);
+                              int capture_count,
+                              Handle<String> pattern);
 
   inline void AddWork(RegExpNode* node) { work_list_->Add(node); }
 
@@ -924,7 +1206,6 @@
 
   RegExpMacroAssembler* macro_assembler() { return macro_assembler_; }
   EndNode* accept() { return accept_; }
-  EndNode* backtrack() { return backtrack_; }
 
   static const int kMaxRecursion = 100;
   inline int recursion_depth() { return recursion_depth_; }
@@ -932,34 +1213,47 @@
   inline void DecrementRecursionDepth() { recursion_depth_--; }
 
   inline bool ignore_case() { return ignore_case_; }
+  inline bool ascii() { return ascii_; }
 
  private:
   EndNode* accept_;
-  EndNode* backtrack_;
   int next_register_;
   List<RegExpNode*>* work_list_;
   int recursion_depth_;
   RegExpMacroAssembler* macro_assembler_;
   bool ignore_case_;
+  bool ascii_;
+};
+
+
+class RecursionCheck {
+ public:
+  explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) {
+    compiler->IncrementRecursionDepth();
+  }
+  ~RecursionCheck() { compiler_->DecrementRecursionDepth(); }
+ private:
+  RegExpCompiler* compiler_;
 };
 
 
 // Attempts to compile the regexp using an Irregexp code generator.  Returns
 // a fixed array or a null handle depending on whether it succeeded.
-RegExpCompiler::RegExpCompiler(int capture_count, bool ignore_case)
+RegExpCompiler::RegExpCompiler(int capture_count, bool ignore_case, bool ascii)
     : next_register_(2 * (capture_count + 1)),
       work_list_(NULL),
       recursion_depth_(0),
-      ignore_case_(ignore_case) {
+      ignore_case_(ignore_case),
+      ascii_(ascii) {
   accept_ = new EndNode(EndNode::ACCEPT);
-  backtrack_ = new EndNode(EndNode::BACKTRACK);
 }
 
 
 Handle<FixedArray> RegExpCompiler::Assemble(
     RegExpMacroAssembler* macro_assembler,
     RegExpNode* start,
-    int capture_count) {
+    int capture_count,
+    Handle<String> pattern) {
 #ifdef DEBUG
   if (FLAG_trace_regexp_assembler)
     macro_assembler_ = new RegExpMacroAssemblerTracer(macro_assembler);
@@ -969,19 +1263,19 @@
   List <RegExpNode*> work_list(0);
   work_list_ = &work_list;
   Label fail;
-  macro_assembler_->PushBacktrack(&fail);
-  if (!start->GoTo(this)) {
+  macro_assembler->PushBacktrack(&fail);
+  GenerationVariant generic_variant;
+  if (!start->Emit(this, &generic_variant)) {
     fail.Unuse();
     return Handle<FixedArray>::null();
   }
+  macro_assembler_->Bind(&fail);
+  macro_assembler_->Fail();
   while (!work_list.is_empty()) {
-    if (!work_list.RemoveLast()->GoTo(this)) {
-      fail.Unuse();
+    if (!work_list.RemoveLast()->Emit(this, &generic_variant)) {
       return Handle<FixedArray>::null();
     }
   }
-  macro_assembler_->Bind(&fail);
-  macro_assembler_->Fail();
   Handle<FixedArray> array =
       Factory::NewFixedArray(RegExpImpl::kIrregexpDataLength);
   array->set(RegExpImpl::kIrregexpImplementationIndex,
@@ -990,7 +1284,7 @@
              Smi::FromInt(next_register_));
   array->set(RegExpImpl::kIrregexpNumberOfCapturesIndex,
              Smi::FromInt(capture_count));
-  Handle<Object> code = macro_assembler_->GetCode();
+  Handle<Object> code = macro_assembler_->GetCode(pattern);
   array->set(RegExpImpl::kIrregexpCodeIndex, *code);
   work_list_ = NULL;
 #ifdef DEBUG
@@ -1002,71 +1296,217 @@
 }
 
 
-bool RegExpNode::GoTo(RegExpCompiler* compiler) {
-  // TODO(erikcorry): Implement support.
-  if (info_.follows_word_interest ||
-      info_.follows_newline_interest ||
-      info_.follows_start_interest) {
-    return false;
+bool GenerationVariant::mentions_reg(int reg) {
+  for (DeferredAction* action = actions_;
+       action != NULL;
+       action = action->next()) {
+    if (reg == action->reg()) return true;
   }
-  if (label_.is_bound()) {
-    compiler->macro_assembler()->GoTo(&label_);
-    return true;
-  } else {
-    if (compiler->recursion_depth() > RegExpCompiler::kMaxRecursion) {
-      compiler->macro_assembler()->GoTo(&label_);
-      compiler->AddWork(this);
-      return true;
+  return false;
+}
+
+
+int GenerationVariant::FindAffectedRegisters(OutSet* affected_registers) {
+  int max_register = -1;
+  for (DeferredAction* action = actions_;
+       action != NULL;
+       action = action->next()) {
+    affected_registers->Set(action->reg());
+    if (action->reg() > max_register) max_register = action->reg();
+  }
+  return max_register;
+}
+
+
+void GenerationVariant::PushAffectedRegisters(RegExpMacroAssembler* macro,
+                                              int max_register,
+                                              OutSet& affected_registers) {
+  for (int reg = 0; reg <= max_register; reg++) {
+    if (affected_registers.Get(reg)) macro->PushRegister(reg);
+  }
+}
+
+
+void GenerationVariant::RestoreAffectedRegisters(RegExpMacroAssembler* macro,
+                                                 int max_register,
+                                                 OutSet& affected_registers) {
+  for (int reg = max_register; reg >= 0; reg--) {
+    if (affected_registers.Get(reg)) macro->PopRegister(reg);
+  }
+}
+
+
+void GenerationVariant::PerformDeferredActions(RegExpMacroAssembler* macro,
+                                               int max_register,
+                                               OutSet& affected_registers) {
+  for (int reg = 0; reg <= max_register; reg++) {
+    if (!affected_registers.Get(reg)) {
+      continue;
+    }
+    int value = 0;
+    bool absolute = false;
+    int store_position = -1;
+    // This is a little tricky because we are scanning the actions in reverse
+    // historical order (newest first).
+    for (DeferredAction* action = actions_;
+         action != NULL;
+         action = action->next()) {
+      if (action->reg() == reg) {
+        switch (action->type()) {
+          case ActionNode::SET_REGISTER: {
+            GenerationVariant::DeferredSetRegister* psr =
+                static_cast<GenerationVariant::DeferredSetRegister*>(action);
+            value += psr->value();
+            absolute = true;
+            ASSERT_EQ(store_position, -1);
+            break;
+          }
+          case ActionNode::INCREMENT_REGISTER:
+            if (!absolute) {
+              value++;
+            }
+            ASSERT_EQ(store_position, -1);
+            break;
+          case ActionNode::STORE_POSITION: {
+            GenerationVariant::DeferredCapture* pc =
+                static_cast<GenerationVariant::DeferredCapture*>(action);
+            if (store_position == -1) {
+              store_position = pc->cp_offset();
+            }
+            ASSERT(!absolute);
+            ASSERT_EQ(value, 0);
+            break;
+          }
+          default:
+            UNREACHABLE();
+            break;
+        }
+      }
+    }
+    if (store_position != -1) {
+      macro->WriteCurrentPositionToRegister(reg, store_position);
     } else {
-      compiler->IncrementRecursionDepth();
-      bool how_it_went = Emit(compiler);
-      compiler->DecrementRecursionDepth();
-      return how_it_went;
+      if (absolute) {
+        macro->SetRegister(reg, value);
+      } else {
+        if (value != 0) {
+          macro->AdvanceRegister(reg, value);
+        }
+      }
     }
   }
 }
 
 
-// EndNodes are special.  Because they can be very common and they are very
-// short we normally inline them.  That is, if we are asked to emit a GoTo
-// we just emit the entire node.  Since they don't have successors this
-// works.
-bool EndNode::GoTo(RegExpCompiler* compiler) {
-  if (info()->follows_word_interest ||
-      info()->follows_newline_interest ||
-      info()->follows_start_interest) {
-    return false;
-  }
-  return Emit(compiler);
-}
-
-
-Label* RegExpNode::label() {
-  return &label_;
-}
-
-
-bool EndNode::Emit(RegExpCompiler* compiler) {
+// This is called as we come into a loop choice node and some other tricky
+// nodes.  It normalises the state of the code generator to ensure we can
+// generate generic code.
+bool GenerationVariant::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
   RegExpMacroAssembler* macro = compiler->macro_assembler();
+
+  ASSERT(actions_ != NULL || cp_offset_ != 0 || backtrack() != NULL);
+
+  if (actions_ == NULL && backtrack() == NULL) {
+    // Here we just have some deferred cp advances to fix and we are back to
+    // a normal situation.
+    macro->AdvanceCurrentPosition(cp_offset_);
+    // Create a new trivial state and generate the node with that.
+    GenerationVariant new_state;
+    return successor->Emit(compiler, &new_state);
+  }
+
+  // Generate deferred actions here along with code to undo them again.
+  OutSet affected_registers;
+  int max_register = FindAffectedRegisters(&affected_registers);
+  PushAffectedRegisters(macro, max_register, affected_registers);
+  PerformDeferredActions(macro, max_register, affected_registers);
+  if (backtrack() != NULL) {
+    // Here we have a concrete backtrack location.  These are set up by choice
+    // nodes and so they indicate that we have a deferred save of the current
+    // position which we may need to emit here.
+    macro->PushCurrentPosition();
+  }
+  if (cp_offset_ != 0) {
+    macro->AdvanceCurrentPosition(cp_offset_);
+  }
+
+  // Create a new trivial state and generate the node with that.
+  Label undo;
+  macro->PushBacktrack(&undo);
+  GenerationVariant new_state;
+  bool ok = successor->Emit(compiler, &new_state);
+
+  // On backtrack we need to restore state.
+  macro->Bind(&undo);
+  if (!ok) return false;
+  if (backtrack() != NULL) {
+    macro->PopCurrentPosition();
+  }
+  RestoreAffectedRegisters(macro, max_register, affected_registers);
+  if (backtrack() == NULL) {
+    macro->Backtrack();
+  } else {
+    macro->GoTo(backtrack());
+  }
+
+  return true;
+}
+
+
+void EndNode::EmitInfoChecks(RegExpMacroAssembler* macro,
+                             GenerationVariant* variant) {
+  if (info()->at_end) {
+    Label succeed;
+    // LoadCurrentCharacter will go to the label if we are at the end of the
+    // input string.
+    macro->LoadCurrentCharacter(0, &succeed);
+    macro->GoTo(variant->backtrack());
+    macro->Bind(&succeed);
+  }
+}
+
+
+bool NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler,
+                                   GenerationVariant* variant) {
+  if (!variant->is_trivial()) {
+    return variant->Flush(compiler, this);
+  }
+  RegExpMacroAssembler* macro = compiler->macro_assembler();
+  if (!label()->is_bound()) {
+    macro->Bind(label());
+  }
+  EmitInfoChecks(macro, variant);
+  macro->ReadCurrentPositionFromRegister(current_position_register_);
+  macro->ReadStackPointerFromRegister(stack_pointer_register_);
+  // Now that we have unwound the stack we find at the top of the stack the
+  // backtrack that the BeginSubmatch node got.
+  macro->Backtrack();
+  return true;
+}
+
+
+bool EndNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) {
+  if (!variant->is_trivial()) {
+    return variant->Flush(compiler, this);
+  }
+  RegExpMacroAssembler* macro = compiler->macro_assembler();
+  if (!label()->is_bound()) {
+    macro->Bind(label());
+  }
   switch (action_) {
     case ACCEPT:
-      if (!label()->is_bound()) Bind(macro);
-      if (info()->at_end) {
-        Label succeed;
-        // LoadCurrentCharacter will go to the label if we are at the end of the
-        // input string.
-        macro->LoadCurrentCharacter(0, &succeed);
-        macro->Backtrack();
-        macro->Bind(&succeed);
-      }
+      EmitInfoChecks(macro, variant);
       macro->Succeed();
       return true;
     case BACKTRACK:
-      if (!label()->is_bound()) Bind(macro);
       ASSERT(!info()->at_end);
-      macro->Backtrack();
+      macro->GoTo(variant->backtrack());
       return true;
+    case NEGATIVE_SUBMATCH_SUCCESS:
+      // This case is handled in a different virtual method.
+      UNREACHABLE();
   }
+  UNIMPLEMENTED();
   return false;
 }
 
@@ -1078,10 +1518,10 @@
 }
 
 
-ActionNode* ActionNode::StoreRegister(int reg,
-                                      int val,
-                                      RegExpNode* on_success) {
-  ActionNode* result = new ActionNode(STORE_REGISTER, on_success);
+ActionNode* ActionNode::SetRegister(int reg,
+                                    int val,
+                                    RegExpNode* on_success) {
+  ActionNode* result = new ActionNode(SET_REGISTER, on_success);
   result->data_.u_store_register.reg = reg;
   result->data_.u_store_register.value = val;
   return result;
@@ -1102,13 +1542,6 @@
 }
 
 
-ActionNode* ActionNode::RestorePosition(int reg, RegExpNode* on_success) {
-  ActionNode* result = new ActionNode(RESTORE_POSITION, on_success);
-  result->data_.u_position_register.reg = reg;
-  return result;
-}
-
-
 ActionNode* ActionNode::BeginSubmatch(int stack_reg,
                                       int position_reg,
                                       RegExpNode* on_success) {
@@ -1119,17 +1552,12 @@
 }
 
 
-ActionNode* ActionNode::EscapeSubmatch(int stack_reg,
-                                       bool restore_position,
-                                       int position_reg,
-                                       RegExpNode* on_success) {
-  ActionNode* result = new ActionNode(ESCAPE_SUBMATCH, on_success);
+ActionNode* ActionNode::PositiveSubmatchSuccess(int stack_reg,
+                                                int position_reg,
+                                                RegExpNode* on_success) {
+  ActionNode* result = new ActionNode(POSITIVE_SUBMATCH_SUCCESS, on_success);
   result->data_.u_submatch.stack_pointer_register = stack_reg;
-  if (restore_position) {
-    result->data_.u_submatch.current_position_register = position_reg;
-  } else {
-    result->data_.u_submatch.current_position_register = -1;
-  }
+  result->data_.u_submatch.current_position_register = position_reg;
   return result;
 }
 
@@ -1148,13 +1576,19 @@
 
 void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler,
                                Guard* guard,
-                               Label* on_failure) {
+                               GenerationVariant* variant) {
   switch (guard->op()) {
     case Guard::LT:
-      macro_assembler->IfRegisterGE(guard->reg(), guard->value(), on_failure);
+      ASSERT(!variant->mentions_reg(guard->reg()));
+      macro_assembler->IfRegisterGE(guard->reg(),
+                                    guard->value(),
+                                    variant->backtrack());
       break;
     case Guard::GEQ:
-      macro_assembler->IfRegisterLT(guard->reg(), guard->value(), on_failure);
+      ASSERT(!variant->mentions_reg(guard->reg()));
+      macro_assembler->IfRegisterLT(guard->reg(),
+                                    guard->value(),
+                                    variant->backtrack());
       break;
   }
 }
@@ -1169,13 +1603,22 @@
     TextElement elm,
     Vector<const uc16> quarks,
     Label* on_failure,
-    int cp_offset) {
+    int cp_offset,
+    bool check_offset) {
   unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+  // It is vital that this loop is backwards due to the unchecked character
+  // load below.
   for (int i = quarks.length() - 1; i >= 0; i--) {
     uc16 c = quarks[i];
     int length = uncanonicalize.get(c, '\0', chars);
     if (length <= 1) {
-      macro_assembler->LoadCurrentCharacter(cp_offset + i, on_failure);
+      if (check_offset && i == quarks.length() - 1) {
+        macro_assembler->LoadCurrentCharacter(cp_offset + i, on_failure);
+      } else {
+        // Here we don't need to check against the end of the input string
+        // since this character lies before a character that matched.
+        macro_assembler->LoadCurrentCharacterUnchecked(cp_offset + i);
+      }
       macro_assembler->CheckNotCharacter(c, on_failure);
     }
   }
@@ -1216,13 +1659,22 @@
     TextElement elm,
     Vector<const uc16> quarks,
     Label* on_failure,
-    int cp_offset) {
+    int cp_offset,
+    bool check_offset) {
   unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+  // It is vital that this loop is backwards due to the unchecked character
+  // load below.
   for (int i = quarks.length() - 1; i >= 0; i--) {
     uc16 c = quarks[i];
     int length = uncanonicalize.get(c, '\0', chars);
     if (length <= 1) continue;
-    macro_assembler->LoadCurrentCharacter(cp_offset + i, on_failure);
+    if (check_offset && i == quarks.length() - 1) {
+      macro_assembler->LoadCurrentCharacter(cp_offset + i, on_failure);
+    } else {
+      // Here we don't need to check against the end of the input string
+      // since this character lies before a character that matched.
+      macro_assembler->LoadCurrentCharacterUnchecked(cp_offset + i);
+    }
     Label ok;
     ASSERT(unibrow::Ecma262UnCanonicalize::kMaxWidth == 4);
     switch (length) {
@@ -1231,7 +1683,6 @@
                                       chars[0],
                                       chars[1],
                                       on_failure)) {
-          ok.Unuse();
         } else {
           macro_assembler->CheckCharacter(chars[0], &ok);
           macro_assembler->CheckNotCharacter(chars[1], on_failure);
@@ -1259,11 +1710,16 @@
 static void EmitCharClass(RegExpMacroAssembler* macro_assembler,
                           RegExpCharacterClass* cc,
                           int cp_offset,
-                          Label* on_failure) {
-  macro_assembler->LoadCurrentCharacter(cp_offset, on_failure);
-  cp_offset++;
-
+                          Label* on_failure,
+                          bool check_offset,
+                          bool ascii) {
   ZoneList<CharacterRange>* ranges = cc->ranges();
+  int max_char;
+  if (ascii) {
+    max_char = String::kMaxAsciiCharCode;
+  } else {
+    max_char = String::kMaxUC16CharCode;
+  }
 
   Label success;
 
@@ -1272,25 +1728,60 @@
 
   int range_count = ranges->length();
 
-  if (range_count == 0) {
+  int last_valid_range = range_count - 1;
+  while (last_valid_range >= 0) {
+    CharacterRange& range = ranges->at(last_valid_range);
+    if (range.from() <= max_char) {
+      break;
+    }
+    last_valid_range--;
+  }
+
+  if (last_valid_range < 0) {
     if (!cc->is_negated()) {
+      // TODO(plesner): We can remove this when the node level does our
+      // ASCII optimizations for us.
       macro_assembler->GoTo(on_failure);
     }
     return;
   }
 
-  for (int i = 0; i < range_count - 1; i++) {
+  if (last_valid_range == 0 &&
+      !cc->is_negated() &&
+      ranges->at(0).IsEverything(max_char)) {
+    // This is a common case hit by non-anchored expressions.
+    // TODO(erikcorry): We should have a macro assembler instruction that just
+    // checks for end of string without loading the character.
+    if (check_offset) {
+      macro_assembler->LoadCurrentCharacter(cp_offset, on_failure);
+    }
+    return;
+  }
+
+  if (check_offset) {
+    macro_assembler->LoadCurrentCharacter(cp_offset, on_failure);
+  } else {
+    // Here we don't need to check against the end of the input string
+    // since this character lies before a character that matched.
+    macro_assembler->LoadCurrentCharacterUnchecked(cp_offset);
+  }
+
+  for (int i = 0; i <= last_valid_range; i++) {
     CharacterRange& range = ranges->at(i);
     Label next_range;
     uc16 from = range.from();
     uc16 to = range.to();
+    if (from > max_char) {
+      continue;
+    }
+    if (to > max_char) to = max_char;
     if (to == from) {
       macro_assembler->CheckCharacter(to, char_is_in_class);
     } else {
       if (from != 0) {
         macro_assembler->CheckCharacterLT(from, &next_range);
       }
-      if (to != 0xffff) {
+      if (to != max_char) {
         macro_assembler->CheckCharacterLT(to + 1, char_is_in_class);
       } else {
         macro_assembler->GoTo(char_is_in_class);
@@ -1299,10 +1790,13 @@
     macro_assembler->Bind(&next_range);
   }
 
-  CharacterRange& range = ranges->at(range_count - 1);
+  CharacterRange& range = ranges->at(last_valid_range);
   uc16 from = range.from();
   uc16 to = range.to();
 
+  if (to > max_char) to = max_char;
+  ASSERT(to >= from);
+
   if (to == from) {
     if (cc->is_negated()) {
       macro_assembler->CheckCharacter(to, on_failure);
@@ -1317,7 +1811,7 @@
         macro_assembler->CheckCharacterLT(from, on_failure);
       }
     }
-    if (to != 0xffff) {
+    if (to != String::kMaxUC16CharCode) {
       if (cc->is_negated()) {
         macro_assembler->CheckCharacterLT(to + 1, on_failure);
       } else {
@@ -1333,73 +1827,162 @@
 }
 
 
+RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler,
+                                                  GenerationVariant* variant) {
+  // TODO(erikcorry): Implement support.
+  if (info_.follows_word_interest ||
+      info_.follows_newline_interest ||
+      info_.follows_start_interest) {
+    return FAIL;
+  }
 
-bool TextNode::Emit(RegExpCompiler* compiler) {
+  // If we are generating a greedy loop then don't stop and don't reuse code.
+  if (variant->stop_node() != NULL) {
+    return CONTINUE;
+  }
+
   RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
-  Bind(macro_assembler);
+  if (variant->is_trivial()) {
+    if (label_.is_bound()) {
+      // We are being asked to generate a generic version, but that's already
+      // been done so just go to it.
+      macro_assembler->GoTo(&label_);
+      return DONE;
+    }
+    if (compiler->recursion_depth() >= RegExpCompiler::kMaxRecursion) {
+      // To avoid too deep recursion we push the node to the work queue and just
+      // generate a goto here.
+      compiler->AddWork(this);
+      macro_assembler->GoTo(&label_);
+      return DONE;
+    }
+    // Generate generic version of the node and bind the label for later use.
+    macro_assembler->Bind(&label_);
+    return CONTINUE;
+  }
+
+  // We are being asked to make a non-generic version.  Keep track of how many
+  // non-generic versions we generate so as not to overdo it.
+  variants_generated_++;
+  if (variants_generated_ < kMaxVariantsGenerated &&
+      compiler->recursion_depth() <= RegExpCompiler::kMaxRecursion) {
+    return CONTINUE;
+  }
+
+  // If we get here there have been too many variants generated or recursion
+  // is too deep.  Time to switch to a generic version.  The code for
+  // generic versions above can handle deep recursion properly.
+  bool ok = variant->Flush(compiler, this);
+  return ok ? DONE : FAIL;
+}
+
+
+// This generates the code to match a text node.  A text node can contain
+// straight character sequences (possibly to be matched in a case-independent
+// way) and character classes.  In order to be most efficient we test for the
+// simple things first and then move on to the more complicated things.  The
+// simplest thing is a non-letter or a letter if we are matching case.  The
+// next-most simple thing is a case-independent letter.  The least simple is
+// a character class.  Another optimization is that we test the last one first.
+// If that succeeds we don't need to test for the end of the string when we
+// load other characters.
+bool TextNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) {
+  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
+  Label *backtrack = variant->backtrack();
+  LimitResult limit_result = LimitVersions(compiler, variant);
+  if (limit_result == FAIL) return false;
+  if (limit_result == DONE) return true;
+  ASSERT(limit_result == CONTINUE);
+
   int element_count = elms_->length();
   ASSERT(element_count != 0);
-  int cp_offset = 0;
   if (info()->at_end) {
-    macro_assembler->Backtrack();
+    macro_assembler->GoTo(backtrack);
     return true;
   }
-  // First, handle straight character matches.
-  for (int i = 0; i < element_count; i++) {
+  // First check for non-ASCII text.
+  // TODO(plesner): We should do this at node level.
+  if (compiler->ascii()) {
+    for (int i = element_count - 1; i >= 0; i--) {
+      TextElement elm = elms_->at(i);
+      if (elm.type == TextElement::ATOM) {
+        Vector<const uc16> quarks = elm.data.u_atom->data();
+        for (int j = quarks.length() - 1; j >= 0; j--) {
+          if (quarks[j] > String::kMaxAsciiCharCode) {
+            macro_assembler->GoTo(backtrack);
+            return true;
+          }
+        }
+      } else {
+        ASSERT_EQ(elm.type, TextElement::CHAR_CLASS);
+      }
+    }
+  }
+  // Second, handle straight character matches.
+  int checked_up_to = -1;
+  for (int i = element_count - 1; i >= 0; i--) {
     TextElement elm = elms_->at(i);
+    ASSERT(elm.cp_offset >= 0);
+    int cp_offset = variant->cp_offset() + elm.cp_offset;
     if (elm.type == TextElement::ATOM) {
       Vector<const uc16> quarks = elm.data.u_atom->data();
+      int last_cp_offset = cp_offset + quarks.length();
       if (compiler->ignore_case()) {
         EmitAtomNonLetters(macro_assembler,
                            elm,
                            quarks,
-                           on_failure_->label(),
-                           cp_offset);
+                           backtrack,
+                           cp_offset,
+                           checked_up_to < last_cp_offset);
       } else {
         macro_assembler->CheckCharacters(quarks,
                                          cp_offset,
-                                         on_failure_->label());
+                                         backtrack,
+                                         checked_up_to < last_cp_offset);
       }
-      cp_offset += quarks.length();
+      if (last_cp_offset > checked_up_to) checked_up_to = last_cp_offset - 1;
     } else {
       ASSERT_EQ(elm.type, TextElement::CHAR_CLASS);
-      cp_offset++;
     }
   }
-  // Second, handle case independent letter matches if any.
+  // Third, handle case independent letter matches if any.
   if (compiler->ignore_case()) {
-    cp_offset = 0;
-    for (int i = 0; i < element_count; i++) {
+    for (int i = element_count - 1; i >= 0; i--) {
       TextElement elm = elms_->at(i);
+      int cp_offset = variant->cp_offset() + elm.cp_offset;
       if (elm.type == TextElement::ATOM) {
         Vector<const uc16> quarks = elm.data.u_atom->data();
+        int last_cp_offset = cp_offset + quarks.length();
         EmitAtomLetters(macro_assembler,
                         elm,
                         quarks,
-                        on_failure_->label(),
-                        cp_offset);
-        cp_offset += quarks.length();
-      } else {
-        cp_offset++;
+                        backtrack,
+                        cp_offset,
+                        checked_up_to < last_cp_offset);
+        if (last_cp_offset > checked_up_to) checked_up_to = last_cp_offset - 1;
       }
     }
   }
   // If the fast character matches passed then do the character classes.
-  cp_offset = 0;
-  for (int i = 0; i < element_count; i++) {
+  for (int i = element_count - 1; i >= 0; i--) {
     TextElement elm = elms_->at(i);
+    int cp_offset = variant->cp_offset() + elm.cp_offset;
     if (elm.type == TextElement::CHAR_CLASS) {
       RegExpCharacterClass* cc = elm.data.u_char_class;
-      EmitCharClass(macro_assembler, cc, cp_offset, on_failure_->label());
-      cp_offset++;
-    } else {
-      cp_offset += elm.data.u_atom->data().length();
+      EmitCharClass(macro_assembler,
+                    cc,
+                    cp_offset,
+                    backtrack,
+                    checked_up_to < cp_offset,
+                    compiler->ascii());
+      if (cp_offset > checked_up_to) checked_up_to = cp_offset;
     }
   }
 
-  compiler->AddWork(on_failure_);
-  macro_assembler->AdvanceCurrentPosition(cp_offset);
-  return on_success()->GoTo(compiler);
+  GenerationVariant new_variant(*variant);
+  new_variant.set_cp_offset(checked_up_to + 1);
+  RecursionCheck rc(compiler);
+  return on_success()->Emit(compiler, &new_variant);
 }
 
 
@@ -1419,141 +2002,257 @@
 }
 
 
-bool ChoiceNode::Emit(RegExpCompiler* compiler) {
-  int choice_count = alternatives_->length();
+int TextNode::GreedyLoopTextLength() {
+  TextElement elm = elms_->at(elms_->length() - 1);
+  if (elm.type == TextElement::CHAR_CLASS) {
+    return elm.cp_offset + 1;
+  } else {
+    return elm.cp_offset + elm.data.u_atom->data().length();
+  }
+}
+
+
+// Finds the fixed match length of a sequence of nodes that goes from
+// this alternative and back to this choice node.  If there are variable
+// length nodes or other complications in the way then return a sentinel
+// value indicating that a greedy loop cannot be constructed.
+int ChoiceNode::GreedyLoopTextLength(GuardedAlternative* alternative) {
+  int length = 0;
+  RegExpNode* node = alternative->node();
+  // Later we will generate code for all these text nodes using recursion
+  // so we have to limit the max number.
+  int recursion_depth = 0;
+  while (node != this) {
+    if (recursion_depth++ > RegExpCompiler::kMaxRecursion) {
+      return kNodeIsTooComplexForGreedyLoops;
+    }
+    NodeInfo* info = node->info();
+    if (info->follows_word_interest ||
+        info->follows_newline_interest ||
+        info->follows_start_interest) {
+      return kNodeIsTooComplexForGreedyLoops;
+    }
+    int node_length = node->GreedyLoopTextLength();
+    if (node_length == kNodeIsTooComplexForGreedyLoops) {
+      return kNodeIsTooComplexForGreedyLoops;
+    }
+    length += node_length;
+    SeqRegExpNode* seq_node = static_cast<SeqRegExpNode*>(node);
+    node = seq_node->on_success();
+  }
+  return length;
+}
+
+
+bool LoopChoiceNode::Emit(RegExpCompiler* compiler,
+                          GenerationVariant* variant) {
   RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
-  Bind(macro_assembler);
-  // For now we just call all choices one after the other.  The idea ultimately
-  // is to use the Dispatch table to try only the relevant ones.
+  if (variant->stop_node() == this) {
+    int text_length = GreedyLoopTextLength(&(alternatives_->at(0)));
+    ASSERT(text_length != kNodeIsTooComplexForGreedyLoops);
+    // Update the counter-based backtracking info on the stack.  This is an
+    // optimization for greedy loops (see below).
+    ASSERT(variant->cp_offset() == text_length);
+    macro_assembler->AdvanceCurrentPosition(text_length);
+    macro_assembler->GoTo(variant->loop_label());
+    return true;
+  }
+  ASSERT(variant->stop_node() == NULL);
+  if (!variant->is_trivial()) {
+    return variant->Flush(compiler, this);
+  }
+  return ChoiceNode::Emit(compiler, variant);
+}
+
+
+bool ChoiceNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) {
+  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
+  int choice_count = alternatives_->length();
+#ifdef DEBUG
   for (int i = 0; i < choice_count - 1; i++) {
     GuardedAlternative alternative = alternatives_->at(i);
-    Label after;
-    Label after_no_pop_cp;
     ZoneList<Guard*>* guards = alternative.guards();
-    if (guards != NULL) {
-      int guard_count = guards->length();
-      for (int j = 0; j < guard_count; j++) {
-        GenerateGuard(macro_assembler, guards->at(j), &after_no_pop_cp);
-      }
+    int guard_count = (guards == NULL) ? 0 : guards->length();
+    for (int j = 0; j < guard_count; j++) {
+      ASSERT(!variant->mentions_reg(guards->at(j)->reg()));
     }
+  }
+#endif
+
+  LimitResult limit_result = LimitVersions(compiler, variant);
+  if (limit_result == DONE) return true;
+  if (limit_result == FAIL) return false;
+  ASSERT(limit_result == CONTINUE);
+
+  RecursionCheck rc(compiler);
+
+  GenerationVariant* current_variant = variant;
+
+  int text_length = GreedyLoopTextLength(&(alternatives_->at(0)));
+  bool greedy_loop = false;
+  Label greedy_loop_label;
+  GenerationVariant counter_backtrack_variant(&greedy_loop_label);
+  if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) {
+    // Here we have special handling for greedy loops containing only text nodes
+    // and other simple nodes.  These are handled by pushing the current
+    // position on the stack and then incrementing the current position each
+    // time around the switch.  On backtrack we decrement the current position
+    // and check it against the pushed value.  This avoids pushing backtrack
+    // information for each iteration of the loop, which could take up a lot of
+    // space.
+    greedy_loop = true;
+    ASSERT(variant->stop_node() == NULL);
     macro_assembler->PushCurrentPosition();
-    macro_assembler->PushBacktrack(&after);
-    if (!alternative.node()->GoTo(compiler)) {
+    current_variant = &counter_backtrack_variant;
+    Label greedy_match_failed;
+    GenerationVariant greedy_match_variant(&greedy_match_failed);
+    Label loop_label;
+    macro_assembler->Bind(&loop_label);
+    greedy_match_variant.set_stop_node(this);
+    greedy_match_variant.set_loop_label(&loop_label);
+    bool ok = alternatives_->at(0).node()->Emit(compiler,
+                                                &greedy_match_variant);
+    macro_assembler->Bind(&greedy_match_failed);
+    if (!ok) {
+      greedy_loop_label.Unuse();
+      return false;
+    }
+  }
+
+  Label second_choice;  // For use in greedy matches.
+  macro_assembler->Bind(&second_choice);
+
+  // For now we just call all choices one after the other.  The idea ultimately
+  // is to use the Dispatch table to try only the relevant ones.
+  for (int i = greedy_loop ? 1 : 0; i < choice_count - 1; i++) {
+    GuardedAlternative alternative = alternatives_->at(i);
+    Label after;
+    ZoneList<Guard*>* guards = alternative.guards();
+    int guard_count = (guards == NULL) ? 0 : guards->length();
+    GenerationVariant new_variant(*current_variant);
+    new_variant.set_backtrack(&after);
+    for (int j = 0; j < guard_count; j++) {
+      GenerateGuard(macro_assembler, guards->at(j), &new_variant);
+    }
+    if (!alternative.node()->Emit(compiler, &new_variant)) {
       after.Unuse();
-      after_no_pop_cp.Unuse();
       return false;
     }
     macro_assembler->Bind(&after);
-    macro_assembler->PopCurrentPosition();
-    macro_assembler->Bind(&after_no_pop_cp);
   }
   GuardedAlternative alternative = alternatives_->at(choice_count - 1);
   ZoneList<Guard*>* guards = alternative.guards();
-  if (guards != NULL) {
-    int guard_count = guards->length();
-    for (int j = 0; j < guard_count; j++) {
-      GenerateGuard(macro_assembler, guards->at(j), on_failure_->label());
-    }
+  int guard_count = (guards == NULL) ? 0 : guards->length();
+  for (int j = 0; j < guard_count; j++) {
+    GenerateGuard(macro_assembler, guards->at(j), current_variant);
   }
-  if (!on_failure_->IsBacktrack()) {
-    ASSERT_NOT_NULL(on_failure_ -> label());
-    macro_assembler->PushBacktrack(on_failure_->label());
-    compiler->AddWork(on_failure_);
-  }
-  if (!alternative.node()->GoTo(compiler)) {
-    return false;
+  bool ok = alternative.node()->Emit(compiler, current_variant);
+  if (!ok) return false;
+  if (greedy_loop) {
+    macro_assembler->Bind(&greedy_loop_label);
+    // If we have unwound to the bottom then backtrack.
+    macro_assembler->CheckGreedyLoop(variant->backtrack());
+    // Otherwise try the second priority at an earlier position.
+    macro_assembler->AdvanceCurrentPosition(-text_length);
+    macro_assembler->GoTo(&second_choice);
   }
   return true;
 }
 
 
-bool ActionNode::Emit(RegExpCompiler* compiler) {
+bool ActionNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) {
   RegExpMacroAssembler* macro = compiler->macro_assembler();
-  Bind(macro);
+  LimitResult limit_result = LimitVersions(compiler, variant);
+  if (limit_result == DONE) return true;
+  if (limit_result == FAIL) return false;
+  ASSERT(limit_result == CONTINUE);
+
+  RecursionCheck rc(compiler);
+
   switch (type_) {
-    case STORE_REGISTER:
-      macro->SetRegister(data_.u_store_register.reg,
-                         data_.u_store_register.value);
-      break;
-    case INCREMENT_REGISTER: {
-      Label undo;
-      macro->PushBacktrack(&undo);
-      macro->AdvanceRegister(data_.u_increment_register.reg, 1);
-      bool ok = on_success()->GoTo(compiler);
-      if (!ok) {
-        undo.Unuse();
-        return false;
-      }
-      macro->Bind(&undo);
-      macro->AdvanceRegister(data_.u_increment_register.reg, -1);
-      macro->Backtrack();
-      break;
-    }
     case STORE_POSITION: {
-      Label undo;
-      macro->PushRegister(data_.u_position_register.reg);
-      macro->PushBacktrack(&undo);
-      macro->WriteCurrentPositionToRegister(data_.u_position_register.reg);
-      bool ok = on_success()->GoTo(compiler);
-      if (!ok) {
-        undo.Unuse();
-        return false;
-      }
-      macro->Bind(&undo);
-      macro->PopRegister(data_.u_position_register.reg);
-      macro->Backtrack();
-      break;
+      GenerationVariant::DeferredCapture
+          new_capture(data_.u_position_register.reg, variant);
+      GenerationVariant new_variant = *variant;
+      new_variant.add_action(&new_capture);
+      return on_success()->Emit(compiler, &new_variant);
     }
-    case RESTORE_POSITION:
-      macro->ReadCurrentPositionFromRegister(
-          data_.u_position_register.reg);
-      break;
+    case INCREMENT_REGISTER: {
+      GenerationVariant::DeferredIncrementRegister
+          new_increment(data_.u_increment_register.reg);
+      GenerationVariant new_variant = *variant;
+      new_variant.add_action(&new_increment);
+      return on_success()->Emit(compiler, &new_variant);
+    }
+    case SET_REGISTER: {
+      GenerationVariant::DeferredSetRegister
+          new_set(data_.u_store_register.reg, data_.u_store_register.value);
+      GenerationVariant new_variant = *variant;
+      new_variant.add_action(&new_set);
+      return on_success()->Emit(compiler, &new_variant);
+    }
     case BEGIN_SUBMATCH:
+      if (!variant->is_trivial()) return variant->Flush(compiler, this);
       macro->WriteCurrentPositionToRegister(
-          data_.u_submatch.current_position_register);
+          data_.u_submatch.current_position_register, 0);
       macro->WriteStackPointerToRegister(
           data_.u_submatch.stack_pointer_register);
-      break;
-    case ESCAPE_SUBMATCH:
+      return on_success()->Emit(compiler, variant);
+    case POSITIVE_SUBMATCH_SUCCESS:
+      if (!variant->is_trivial()) return variant->Flush(compiler, this);
+      // TODO(erikcorry): Implement support.
+      if (info()->follows_word_interest ||
+          info()->follows_newline_interest ||
+          info()->follows_start_interest) {
+        return false;
+      }
       if (info()->at_end) {
         Label at_end;
         // Load current character jumps to the label if we are beyond the string
         // end.
         macro->LoadCurrentCharacter(0, &at_end);
-        macro->Backtrack();
+        macro->GoTo(variant->backtrack());
         macro->Bind(&at_end);
       }
-      if (data_.u_submatch.current_position_register != -1) {
-        macro->ReadCurrentPositionFromRegister(
-            data_.u_submatch.current_position_register);
-      }
+      macro->ReadCurrentPositionFromRegister(
+          data_.u_submatch.current_position_register);
       macro->ReadStackPointerFromRegister(
           data_.u_submatch.stack_pointer_register);
-      break;
+      return on_success()->Emit(compiler, variant);
     default:
       UNREACHABLE();
       return false;
   }
-  return on_success()->GoTo(compiler);
 }
 
 
-bool BackReferenceNode::Emit(RegExpCompiler* compiler) {
+bool BackReferenceNode::Emit(RegExpCompiler* compiler,
+                             GenerationVariant* variant) {
   RegExpMacroAssembler* macro = compiler->macro_assembler();
-  Bind(macro);
+  if (!variant->is_trivial()) {
+    return variant->Flush(compiler, this);
+  }
+
+  LimitResult limit_result = LimitVersions(compiler, variant);
+  if (limit_result == DONE) return true;
+  if (limit_result == FAIL) return false;
+  ASSERT(limit_result == CONTINUE);
+
+  RecursionCheck rc(compiler);
+
   ASSERT_EQ(start_reg_ + 1, end_reg_);
   if (info()->at_end) {
     // If we are constrained to match at the end of the input then succeed
     // iff the back reference is empty.
-    macro->CheckNotRegistersEqual(start_reg_, end_reg_, on_failure_->label());
+    macro->CheckNotRegistersEqual(start_reg_, end_reg_, variant->backtrack());
   } else {
     if (compiler->ignore_case()) {
-      macro->CheckNotBackReferenceIgnoreCase(start_reg_, on_failure_->label());
+      macro->CheckNotBackReferenceIgnoreCase(start_reg_, variant->backtrack());
     } else {
-      macro->CheckNotBackReference(start_reg_, on_failure_->label());
+      macro->CheckNotBackReference(start_reg_, variant->backtrack());
     }
   }
-  return on_success()->GoTo(compiler);
+  return on_success()->Emit(compiler, variant);
 }
 
 
@@ -1571,9 +2270,9 @@
         stream_(&alloc_) { }
   void PrintNode(const char* label, RegExpNode* node);
   void Visit(RegExpNode* node);
-  void PrintOnFailure(RegExpNode* from, RegExpNode* on_failure);
   void PrintAttributes(RegExpNode* from);
   StringStream* stream() { return &stream_; }
+  void PrintOnFailure(RegExpNode* from, RegExpNode* to);
 #define DECLARE_VISIT(Type)                                          \
   virtual void Visit##Type(Type##Node* that);
 FOR_EACH_NODE_TYPE(DECLARE_VISIT)
@@ -1615,7 +2314,6 @@
 
 
 void DotPrinter::PrintOnFailure(RegExpNode* from, RegExpNode* on_failure) {
-  if (on_failure->IsBacktrack()) return;
   stream()->Add("  n%p -> n%p [style=dotted];\n", from, on_failure);
   Visit(on_failure);
 }
@@ -1740,7 +2438,6 @@
     PrintAttributes(that);
     TableEntryBodyPrinter body_printer(stream(), that);
     that->GetTable(ignore_case_)->ForEach(&body_printer);
-    PrintOnFailure(that, that->on_failure());
   } else {
     stream()->Add("  n%p [shape=Mrecord, label=\"?\"];\n", that);
     for (int i = 0; i < that->alternatives()->length(); i++) {
@@ -1785,7 +2482,6 @@
   PrintAttributes(that);
   stream()->Add("  n%p -> n%p;\n", that, that->on_success());
   Visit(that->on_success());
-  PrintOnFailure(that, that->on_failure());
 }
 
 
@@ -1797,7 +2493,6 @@
   PrintAttributes(that);
   stream()->Add("  n%p -> n%p;\n", that, that->on_success());
   Visit(that->on_success());
-  PrintOnFailure(that, that->on_failure());
 }
 
 
@@ -1810,7 +2505,7 @@
 void DotPrinter::VisitAction(ActionNode* that) {
   stream()->Add("  n%p [", that);
   switch (that->type_) {
-    case ActionNode::STORE_REGISTER:
+    case ActionNode::SET_REGISTER:
       stream()->Add("label=\"$%i:=%i\", shape=octagon",
                     that->data_.u_store_register.reg,
                     that->data_.u_store_register.value);
@@ -1823,22 +2518,19 @@
       stream()->Add("label=\"$%i:=$pos\", shape=octagon",
                     that->data_.u_position_register.reg);
       break;
-    case ActionNode::RESTORE_POSITION:
-      stream()->Add("label=\"$pos:=$%i\", shape=octagon",
-                    that->data_.u_position_register.reg);
-      break;
     case ActionNode::BEGIN_SUBMATCH:
       stream()->Add("label=\"$%i:=$pos,begin\", shape=septagon",
                     that->data_.u_submatch.current_position_register);
       break;
-    case ActionNode::ESCAPE_SUBMATCH:
+    case ActionNode::POSITIVE_SUBMATCH_SUCCESS:
       stream()->Add("label=\"escape\", shape=septagon");
       break;
   }
   stream()->Add("];\n");
   PrintAttributes(that);
-  stream()->Add("  n%p -> n%p;\n", that, that->on_success());
-  Visit(that->on_success());
+  RegExpNode* successor = that->on_success();
+  stream()->Add("  n%p -> n%p;\n", that, successor);
+  Visit(successor);
 }
 
 
@@ -1895,40 +2587,33 @@
 
 
 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler,
-                               RegExpNode* on_success,
-                               RegExpNode* on_failure) {
+                               RegExpNode* on_success) {
   ZoneList<TextElement>* elms = new ZoneList<TextElement>(1);
   elms->Add(TextElement::Atom(this));
-  return new TextNode(elms, on_success, on_failure);
+  return new TextNode(elms, on_success);
 }
 
 
 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler,
-                               RegExpNode* on_success,
-                               RegExpNode* on_failure) {
-  return new TextNode(elements(), on_success, on_failure);
+                               RegExpNode* on_success) {
+  return new TextNode(elements(), on_success);
 }
 
 
 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler,
-                                         RegExpNode* on_success,
-                                         RegExpNode* on_failure) {
-  ZoneList<TextElement>* elms = new ZoneList<TextElement>(1);
-  elms->Add(TextElement::CharClass(this));
-  return new TextNode(elms, on_success, on_failure);
+                                         RegExpNode* on_success) {
+  return new TextNode(this, on_success);
 }
 
 
 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler,
-                                      RegExpNode* on_success,
-                                      RegExpNode* on_failure) {
+                                      RegExpNode* on_success) {
   ZoneList<RegExpTree*>* alternatives = this->alternatives();
   int length = alternatives->length();
-  ChoiceNode* result = new ChoiceNode(length, on_failure);
+  ChoiceNode* result = new ChoiceNode(length);
   for (int i = 0; i < length; i++) {
     GuardedAlternative alternative(alternatives->at(i)->ToNode(compiler,
-                                                               on_success,
-                                                               on_failure));
+                                                               on_success));
     result->AddAlternative(alternative);
   }
   return result;
@@ -1936,15 +2621,13 @@
 
 
 RegExpNode* RegExpQuantifier::ToNode(RegExpCompiler* compiler,
-                                     RegExpNode* on_success,
-                                     RegExpNode* on_failure) {
+                                     RegExpNode* on_success) {
   return ToNode(min(),
                 max(),
                 is_greedy(),
                 body(),
                 compiler,
-                on_success,
-                on_failure);
+                on_success);
 }
 
 
@@ -1953,8 +2636,7 @@
                                      bool is_greedy,
                                      RegExpTree* body,
                                      RegExpCompiler* compiler,
-                                     RegExpNode* on_success,
-                                     RegExpNode* on_failure) {
+                                     RegExpNode* on_success) {
   // x{f, t} becomes this:
   //
   //             (r++)<-.
@@ -1972,11 +2654,11 @@
   bool has_max = max < RegExpQuantifier::kInfinity;
   bool needs_counter = has_min || has_max;
   int reg_ctr = needs_counter ? compiler->AllocateRegister() : -1;
-  ChoiceNode* center = new ChoiceNode(2, on_failure);
+  ChoiceNode* center = new LoopChoiceNode(2);
   RegExpNode* loop_return = needs_counter
       ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center))
       : static_cast<RegExpNode*>(center);
-  RegExpNode* body_node = body->ToNode(compiler, loop_return, on_failure);
+  RegExpNode* body_node = body->ToNode(compiler, loop_return);
   GuardedAlternative body_alt(body_node);
   if (has_max) {
     Guard* body_guard = new Guard(reg_ctr, Guard::LT, max);
@@ -1995,7 +2677,7 @@
     center->AddAlternative(body_alt);
   }
   if (needs_counter) {
-    return ActionNode::StoreRegister(reg_ctr, 0, center);
+    return ActionNode::SetRegister(reg_ctr, 0, center);
   } else {
     return center;
   }
@@ -2003,8 +2685,7 @@
 
 
 RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler,
-                                    RegExpNode* on_success,
-                                    RegExpNode* on_failure) {
+                                    RegExpNode* on_success) {
   NodeInfo info;
   switch (type()) {
     case START_OF_LINE:
@@ -2028,108 +2709,85 @@
 
 
 RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler,
-                                        RegExpNode* on_success,
-                                        RegExpNode* on_failure) {
+                                        RegExpNode* on_success) {
   return new BackReferenceNode(RegExpCapture::StartRegister(index()),
                                RegExpCapture::EndRegister(index()),
-                               on_success,
-                               on_failure);
+                               on_success);
 }
 
 
 RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler,
-                                RegExpNode* on_success,
-                                RegExpNode* on_failure) {
+                                RegExpNode* on_success) {
   return on_success;
 }
 
 
 RegExpNode* RegExpLookahead::ToNode(RegExpCompiler* compiler,
-                                    RegExpNode* on_success,
-                                    RegExpNode* on_failure) {
+                                    RegExpNode* on_success) {
   int stack_pointer_register = compiler->AllocateRegister();
   int position_register = compiler->AllocateRegister();
+  RegExpNode* success;
   if (is_positive()) {
-    // begin submatch scope
-    // $reg = $pos
-    // if [body]
-    // then
-    //   $pos = $reg
-    //   escape submatch scope (drop all backtracks created in scope)
-    //   succeed
-    // else
-    //   end submatch scope (nothing to clean up, just exit the scope)
-    //   fail
     return ActionNode::BeginSubmatch(
         stack_pointer_register,
         position_register,
         body()->ToNode(
             compiler,
-            ActionNode::EscapeSubmatch(
-                stack_pointer_register,
-                true,                    // Also restore input position.
-                position_register,
-                on_success),
-            on_failure));
+            ActionNode::PositiveSubmatchSuccess(stack_pointer_register,
+                                                position_register,
+                                                on_success)));
   } else {
-    // begin submatch scope
-    // try
-    // first if (body)
-    //       then
-    //         escape submatch scope
-    //         fail
-    //       else
-    //         backtrack
-    // second
-    //       end submatch scope
-    //       restore current position
-    //       succeed
-    ChoiceNode* try_node =
-        new ChoiceNode(1, ActionNode::RestorePosition(position_register,
-                                                      on_success));
-    RegExpNode* body_node = body()->ToNode(
-        compiler,
-        ActionNode::EscapeSubmatch(stack_pointer_register,
-                                   false,        // Don't also restore position
-                                   0,            // Unused arguments.
-                                   on_failure),
-        compiler->backtrack());
-    GuardedAlternative body_alt(body_node);
-    try_node->AddAlternative(body_alt);
+    // We use a ChoiceNode for a negative lookahead because it has most of
+    // the characteristics we need.  It has the body of the lookahead as its
+    // first alternative and the expression after the lookahead of the second
+    // alternative.  If the first alternative succeeds then the
+    // NegativeSubmatchSuccess will unwind the stack including everything the
+    // choice node set up and backtrack.  If the first alternative fails then
+    // the second alternative is tried, which is exactly the desired result
+    // for a negative lookahead.  In the case where the dispatch table
+    // determines that the first alternative cannot match we will save time
+    // by not trying it.  Things are not quite so well-optimized if the
+    // dispatch table determines that the second alternative cannot match.
+    // In this case we could optimize by immediately backtracking.
+    ChoiceNode* choice_node = new ChoiceNode(2);
+    GuardedAlternative body_alt(
+        body()->ToNode(
+            compiler,
+            success = new NegativeSubmatchSuccess(stack_pointer_register,
+                                                  position_register)));
+    choice_node->AddAlternative(body_alt);
+    choice_node->AddAlternative(GuardedAlternative(on_success));
     return ActionNode::BeginSubmatch(stack_pointer_register,
                                      position_register,
-                                     try_node);
+                                     choice_node);
   }
 }
 
 
 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler,
-                                  RegExpNode* on_success,
-                                  RegExpNode* on_failure) {
-  return ToNode(body(), index(), compiler, on_success, on_failure);
+                                  RegExpNode* on_success) {
+  return ToNode(body(), index(), compiler, on_success);
 }
 
 
 RegExpNode* RegExpCapture::ToNode(RegExpTree* body,
                                   int index,
                                   RegExpCompiler* compiler,
-                                  RegExpNode* on_success,
-                                  RegExpNode* on_failure) {
+                                  RegExpNode* on_success) {
   int start_reg = RegExpCapture::StartRegister(index);
   int end_reg = RegExpCapture::EndRegister(index);
   RegExpNode* store_end = ActionNode::StorePosition(end_reg, on_success);
-  RegExpNode* body_node = body->ToNode(compiler, store_end, on_failure);
+  RegExpNode* body_node = body->ToNode(compiler, store_end);
   return ActionNode::StorePosition(start_reg, body_node);
 }
 
 
 RegExpNode* RegExpAlternative::ToNode(RegExpCompiler* compiler,
-                                      RegExpNode* on_success,
-                                      RegExpNode* on_failure) {
+                                      RegExpNode* on_success) {
   ZoneList<RegExpTree*>* children = nodes();
   RegExpNode* current = on_success;
   for (int i = children->length() - 1; i >= 0; i--) {
-    current = children->at(i)->ToNode(compiler, current, on_failure);
+    current = children->at(i)->ToNode(compiler, current);
   }
   return current;
 }
@@ -2175,7 +2833,7 @@
                             int elmc,
                             ZoneList<CharacterRange>* ranges) {
   ASSERT(elmv[0] != 0x0000);
-  ASSERT(elmv[elmc-1] != 0xFFFF);
+  ASSERT(elmv[elmc-1] != String::kMaxUC16CharCode);
   uc16 last = 0x0000;
   for (int i = 0; i < elmc; i += 2) {
     ASSERT(last <= elmv[i] - 1);
@@ -2183,7 +2841,7 @@
     ranges->Add(CharacterRange(last, elmv[i] - 1));
     last = elmv[i + 1] + 1;
   }
-  ranges->Add(CharacterRange(last, 0xFFFF));
+  ranges->Add(CharacterRange(last, String::kMaxUC16CharCode));
 }
 
 
@@ -2400,9 +3058,7 @@
   full_info.AddFromPreceding(info);
   bool cloned = false;
   ActionNode* action = EnsureSibling(this, &full_info, &cloned);
-  if (cloned && type_ != ESCAPE_SUBMATCH) {
-    action->set_on_success(action->on_success()->PropagateForward(info));
-  }
+  action->set_on_success(action->on_success()->PropagateForward(info));
   return action;
 }
 
@@ -2421,9 +3077,6 @@
       alternative.set_node(alternative.node()->PropagateForward(info));
       choice->alternatives()->Add(alternative);
     }
-    if (!choice->on_failure_->IsBacktrack()) {
-      choice->on_failure_ = choice->on_failure_->PropagateForward(info);
-    }
   }
   return choice;
 }
@@ -2576,7 +3229,7 @@
       entry->AddValue(value);
       // Bail out if the last interval ended at 0xFFFF since otherwise
       // adding 1 will wrap around to 0.
-      if (entry->to() == 0xFFFF)
+      if (entry->to() == String::kMaxUC16CharCode)
         break;
       ASSERT(entry->to() + 1 > current.from());
       current.set_from(entry->to() + 1);
@@ -2609,7 +3262,7 @@
 // Analysis
 
 
-void Analysis::EnsureAnalyzed(RegExpNode* that) {
+void AssertionPropagation::EnsureAnalyzed(RegExpNode* that) {
   if (that->info()->been_analyzed || that->info()->being_analyzed)
     return;
   that->info()->being_analyzed = true;
@@ -2619,17 +3272,34 @@
 }
 
 
-void Analysis::VisitEnd(EndNode* that) {
+void AssertionPropagation::VisitEnd(EndNode* that) {
   // nothing to do
 }
 
 
-void Analysis::VisitText(TextNode* that) {
+void TextNode::CalculateOffsets() {
+  int element_count = elements()->length();
+  // Set up the offsets of the elements relative to the start.  This is a fixed
+  // quantity since a TextNode can only contain fixed-width things.
+  int cp_offset = 0;
+  for (int i = 0; i < element_count; i++) {
+    TextElement& elm = elements()->at(i);
+    elm.cp_offset = cp_offset;
+    if (elm.type == TextElement::ATOM) {
+      cp_offset += elm.data.u_atom->data().length();
+    } else {
+      cp_offset++;
+      Vector<const uc16> quarks = elm.data.u_atom->data();
+    }
+  }
+}
+
+
+void AssertionPropagation::VisitText(TextNode* that) {
   if (ignore_case_) {
     that->MakeCaseIndependent();
   }
   EnsureAnalyzed(that->on_success());
-  EnsureAnalyzed(that->on_failure());
   NodeInfo* info = that->info();
   NodeInfo* next_info = that->on_success()->info();
   // If the following node is interested in what it follows then this
@@ -2637,18 +3307,20 @@
   info->determine_newline = next_info->follows_newline_interest;
   info->determine_word = next_info->follows_word_interest;
   info->determine_start = next_info->follows_start_interest;
+  that->CalculateOffsets();
 }
 
 
-void Analysis::VisitAction(ActionNode* that) {
-  EnsureAnalyzed(that->on_success());
+void AssertionPropagation::VisitAction(ActionNode* that) {
+  RegExpNode* target = that->on_success();
+  EnsureAnalyzed(target);
   // If the next node is interested in what it follows then this node
   // has to be interested too so it can pass the information on.
-  that->info()->AddFromFollowing(that->on_success()->info());
+  that->info()->AddFromFollowing(target->info());
 }
 
 
-void Analysis::VisitChoice(ChoiceNode* that) {
+void AssertionPropagation::VisitChoice(ChoiceNode* that) {
   NodeInfo* info = that->info();
   for (int i = 0; i < that->alternatives()->length(); i++) {
     RegExpNode* node = that->alternatives()->at(i).node();
@@ -2657,13 +3329,11 @@
     // this node also, so it can pass it on.
     info->AddFromFollowing(node->info());
   }
-  EnsureAnalyzed(that->on_failure());
 }
 
 
-void Analysis::VisitBackReference(BackReferenceNode* that) {
+void AssertionPropagation::VisitBackReference(BackReferenceNode* that) {
   EnsureAnalyzed(that->on_success());
-  EnsureAnalyzed(that->on_failure());
 }
 
 
@@ -2746,7 +3416,7 @@
       } else {
         // If this character class contains both word and non-word
         // characters we need to split it into two.
-        ChoiceNode* result = new ChoiceNode(2, on_failure());
+        ChoiceNode* result = new ChoiceNode(2);
         // Welcome to the family, son!
         result->set_siblings(this->siblings());
         *result->info() = *this->info();
@@ -2754,16 +3424,14 @@
         result->info()->AddAssumptions(info);
         RegExpNode* word_node
             = new TextNode(new RegExpCharacterClass(word, false),
-                           on_success(),
-                           on_failure());
+                           on_success());
         word_node->info()->determine_word = true;
         word_node->info()->does_determine_word = true;
         word_node->info()->is_word = NodeInfo::TRUE;
         result->alternatives()->Add(GuardedAlternative(word_node));
         RegExpNode* non_word_node
             = new TextNode(new RegExpCharacterClass(non_word, false),
-                           on_success(),
-                           on_failure());
+                           on_success());
         non_word_node->info()->determine_word = true;
         non_word_node->info()->does_determine_word = true;
         non_word_node->info()->is_word = NodeInfo::FALSE;
@@ -2936,14 +3604,14 @@
     if (last < range.from())
       AddRange(CharacterRange(last, range.from() - 1));
     if (range.to() >= last) {
-      if (range.to() == 0xFFFF) {
+      if (range.to() == String::kMaxUC16CharCode) {
         return;
       } else {
         last = range.to() + 1;
       }
     }
   }
-  AddRange(CharacterRange(last, 0xFFFF));
+  AddRange(CharacterRange(last, String::kMaxUC16CharCode));
 }
 
 
@@ -2974,21 +3642,126 @@
 
 
 void DispatchTableConstructor::VisitAction(ActionNode* that) {
+  RegExpNode* target = that->on_success();
+  target->Accept(this);
+}
+
+
+#ifdef DEBUG
+
+
+class VisitNodeScope {
+ public:
+  explicit VisitNodeScope(RegExpNode* node) : node_(node) {
+    ASSERT(!node->info()->visited);
+    node->info()->visited = true;
+  }
+  ~VisitNodeScope() {
+    node_->info()->visited = false;
+  }
+ private:
+  RegExpNode* node_;
+};
+
+
+class NodeValidator : public NodeVisitor {
+ public:
+  virtual void ValidateInfo(NodeInfo* info) = 0;
+#define DECLARE_VISIT(Type)                                          \
+  virtual void Visit##Type(Type##Node* that);
+FOR_EACH_NODE_TYPE(DECLARE_VISIT)
+#undef DECLARE_VISIT
+};
+
+
+class PostAnalysisNodeValidator : public NodeValidator {
+ public:
+  virtual void ValidateInfo(NodeInfo* info);
+};
+
+
+class PostExpansionNodeValidator : public NodeValidator {
+ public:
+  virtual void ValidateInfo(NodeInfo* info);
+};
+
+
+void PostAnalysisNodeValidator::ValidateInfo(NodeInfo* info) {
+  ASSERT(info->been_analyzed);
+}
+
+
+void PostExpansionNodeValidator::ValidateInfo(NodeInfo* info) {
+  ASSERT_EQ(info->determine_newline, info->does_determine_newline);
+  ASSERT_EQ(info->determine_start, info->does_determine_start);
+  ASSERT_EQ(info->determine_word, info->does_determine_word);
+  ASSERT_EQ(info->follows_word_interest,
+            (info->follows_word != NodeInfo::UNKNOWN));
+  if (false) {
+    // These are still unimplemented.
+    ASSERT_EQ(info->follows_start_interest,
+              (info->follows_start != NodeInfo::UNKNOWN));
+    ASSERT_EQ(info->follows_newline_interest,
+              (info->follows_newline != NodeInfo::UNKNOWN));
+  }
+}
+
+
+void NodeValidator::VisitAction(ActionNode* that) {
+  if (that->info()->visited) return;
+  VisitNodeScope scope(that);
+  ValidateInfo(that->info());
   that->on_success()->Accept(this);
 }
 
 
-Handle<FixedArray> RegExpEngine::Compile(RegExpParseResult* input,
-                                         RegExpNode** node_return,
+void NodeValidator::VisitBackReference(BackReferenceNode* that) {
+  if (that->info()->visited) return;
+  VisitNodeScope scope(that);
+  ValidateInfo(that->info());
+  that->on_success()->Accept(this);
+}
+
+
+void NodeValidator::VisitChoice(ChoiceNode* that) {
+  if (that->info()->visited) return;
+  VisitNodeScope scope(that);
+  ValidateInfo(that->info());
+  ZoneList<GuardedAlternative>* alts = that->alternatives();
+  for (int i = 0; i < alts->length(); i++)
+    alts->at(i).node()->Accept(this);
+}
+
+
+void NodeValidator::VisitEnd(EndNode* that) {
+  if (that->info()->visited) return;
+  VisitNodeScope scope(that);
+  ValidateInfo(that->info());
+}
+
+
+void NodeValidator::VisitText(TextNode* that) {
+  if (that->info()->visited) return;
+  VisitNodeScope scope(that);
+  ValidateInfo(that->info());
+  that->on_success()->Accept(this);
+}
+
+
+#endif
+
+
+Handle<FixedArray> RegExpEngine::Compile(RegExpCompileData* data,
                                          bool ignore_case,
-                                         bool is_multiline) {
-  RegExpCompiler compiler(input->capture_count, ignore_case);
+                                         bool is_multiline,
+                                         Handle<String> pattern,
+                                         bool is_ascii) {
+  RegExpCompiler compiler(data->capture_count, ignore_case, is_ascii);
   // Wrap the body of the regexp in capture #0.
-  RegExpNode* captured_body = RegExpCapture::ToNode(input->tree,
+  RegExpNode* captured_body = RegExpCapture::ToNode(data->tree,
                                                     0,
                                                     &compiler,
-                                                    compiler.accept(),
-                                                    compiler.backtrack());
+                                                    compiler.accept());
   // Add a .*? at the beginning, outside the body capture.
   // Note: We could choose to not add this if the regexp is anchored at
   //   the start of the input but I'm not sure how best to do that and
@@ -2999,20 +3772,41 @@
                                               false,
                                               new RegExpCharacterClass('*'),
                                               &compiler,
-                                              captured_body,
-                                              compiler.backtrack());
-  if (node_return != NULL) *node_return = node;
-  Analysis analysis(ignore_case);
+                                              captured_body);
+  AssertionPropagation analysis(ignore_case);
   analysis.EnsureAnalyzed(node);
 
   NodeInfo info = *node->info();
+  data->has_lookbehind = info.HasLookbehind();
+  if (data->has_lookbehind) {
+    // If this node needs information about the preceding text we let
+    // it start with a character class that consumes a single character
+    // and proceeds to wherever is appropriate.  This means that if
+    // has_lookbehind is set the code generator must start one character
+    // before the start position.
+    node = new TextNode(new RegExpCharacterClass('*'), node);
+    analysis.EnsureAnalyzed(node);
+  }
+
+#ifdef DEBUG
+  PostAnalysisNodeValidator post_analysis_validator;
+  node->Accept(&post_analysis_validator);
+#endif
+
   node = node->EnsureExpanded(&info);
 
-  if (!FLAG_irregexp) {
+#ifdef DEBUG
+  PostExpansionNodeValidator post_expansion_validator;
+  node->Accept(&post_expansion_validator);
+#endif
+
+  data->node = node;
+
+  if (is_multiline && !FLAG_attempt_multiline_irregexp) {
     return Handle<FixedArray>::null();
   }
 
-  if (is_multiline && !FLAG_attempt_multiline_irregexp) {
+  if (data->has_lookbehind) {
     return Handle<FixedArray>::null();
   }
 
@@ -3020,18 +3814,26 @@
 #ifdef ARM
     // Unimplemented, fall-through to bytecode implementation.
 #else  // IA32
-    RegExpMacroAssemblerIA32 macro_assembler(RegExpMacroAssemblerIA32::UC16,
-                                             (input->capture_count + 1) * 2);
+    RegExpMacroAssemblerIA32::Mode mode;
+    if (is_ascii) {
+      mode = RegExpMacroAssemblerIA32::ASCII;
+    } else {
+      mode = RegExpMacroAssemblerIA32::UC16;
+    }
+    RegExpMacroAssemblerIA32 macro_assembler(mode,
+                                             (data->capture_count + 1) * 2);
     return compiler.Assemble(&macro_assembler,
                              node,
-                             input->capture_count);
+                             data->capture_count,
+                             pattern);
 #endif
   }
   EmbeddedVector<byte, 1024> codes;
   RegExpMacroAssemblerIrregexp macro_assembler(codes);
   return compiler.Assemble(&macro_assembler,
                            node,
-                           input->capture_count);
+                           data->capture_count,
+                           pattern);
 }
 
 
diff --git a/src/jsregexp.h b/src/jsregexp.h
index 3ab6651..dbeb6e2 100644
--- a/src/jsregexp.h
+++ b/src/jsregexp.h
@@ -48,6 +48,9 @@
   // This function calls the garbage collector if necessary.
   static Handle<String> ToString(Handle<Object> value);
 
+  // Parses the RegExp pattern and prepares the JSRegExp object with
+  // generic data and choice of implementation - as well as what
+  // the implementation wants to store in the data field.
   static Handle<Object> Compile(Handle<JSRegExp> re,
                                 Handle<String> pattern,
                                 Handle<String> flags);
@@ -71,12 +74,10 @@
                                      Handle<String> pattern,
                                      JSRegExp::Flags flags);
 
-  // Stores a compiled RegExp pattern in the JSRegExp object.
-  // The pattern is compiled by Irregexp.
+  // Prepares a JSRegExp object with Irregexp-specific data.
   static Handle<Object> IrregexpPrepare(Handle<JSRegExp> re,
                                         Handle<String> pattern,
-                                        JSRegExp::Flags flags,
-                                        Handle<FixedArray> irregexp_data);
+                                        JSRegExp::Flags flags);
 
 
   // Compile the pattern using JSCRE and store the result in the
@@ -140,9 +141,10 @@
   static int JscreNumberOfCaptures(Handle<JSRegExp> re);
   static ByteArray* JscreInternal(Handle<JSRegExp> re);
 
-  static int IrregexpNumberOfCaptures(Handle<JSRegExp> re);
-  static int IrregexpNumberOfRegisters(Handle<JSRegExp> re);
-  static Handle<ByteArray> IrregexpCode(Handle<JSRegExp> re);
+  static int IrregexpNumberOfCaptures(Handle<FixedArray> re);
+  static int IrregexpNumberOfRegisters(Handle<FixedArray> re);
+  static Handle<ByteArray> IrregexpByteCode(Handle<FixedArray> re);
+  static Handle<Code> IrregexpNativeCode(Handle<FixedArray> re);
 
   // Call jsRegExpExecute once
   static Handle<Object> JscreExecOnce(Handle<JSRegExp> regexp,
@@ -153,7 +155,7 @@
                                       int* ovector,
                                       int ovector_length);
 
-  static Handle<Object> IrregexpExecOnce(Handle<JSRegExp> regexp,
+  static Handle<Object> IrregexpExecOnce(Handle<FixedArray> regexp,
                                          int num_captures,
                                          Handle<String> subject16,
                                          int previous_index,
@@ -202,6 +204,7 @@
   uc16 to() const { return to_; }
   void set_to(uc16 value) { to_ = value; }
   bool is_valid() { return from_ <= to_; }
+  bool IsEverything(uc16 max) { return from_ == 0 && to_ >= max; }
   bool IsSingleton() { return (from_ == to_); }
   void AddCaseEquivalents(ZoneList<CharacterRange>* ranges);
   static void Split(ZoneList<CharacterRange>* base,
@@ -346,6 +349,7 @@
   uint32_t first_;
   ZoneList<unsigned>* remaining_;
   ZoneList<OutSet*>* successors_;
+  friend class GenerationVariant;
 };
 
 
@@ -432,7 +436,7 @@
  public:
   enum Type {UNINITIALIZED, ATOM, CHAR_CLASS};
   TextElement() : type(UNINITIALIZED) { }
-  explicit TextElement(Type t) : type(t) { }
+  explicit TextElement(Type t) : type(t), cp_offset(-1) { }
   static TextElement Atom(RegExpAtom* atom);
   static TextElement CharClass(RegExpCharacterClass* char_class);
   Type type;
@@ -440,9 +444,13 @@
     RegExpAtom* u_atom;
     RegExpCharacterClass* u_char_class;
   } data;
+  int cp_offset;
 };
 
 
+class GenerationVariant;
+
+
 struct NodeInfo {
   enum TriBool {
     UNKNOWN = -1, FALSE = 0, TRUE = 1
@@ -520,6 +528,12 @@
     does_determine_start = that->does_determine_start;
   }
 
+  bool HasLookbehind() {
+    return follows_word_interest ||
+           follows_newline_interest ||
+           follows_start_interest;
+  }
+
   // Sets the interests of this node to include the interests of the
   // following node.
   void AddFromFollowing(NodeInfo* that) {
@@ -607,17 +621,17 @@
 
 class RegExpNode: public ZoneObject {
  public:
+  RegExpNode() : variants_generated_(0) { }
   virtual ~RegExpNode() { }
   virtual void Accept(NodeVisitor* visitor) = 0;
   // Generates a goto to this node or actually generates the code at this point.
   // Until the implementation is complete we will return true for success and
   // false for failure.
-  virtual bool GoTo(RegExpCompiler* compiler);
-  Label* label();
-
-  // Until the implementation is complete we will return true for success and
-  // false for failure.
-  virtual bool Emit(RegExpCompiler* compiler) = 0;
+  virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant) = 0;
+  static const int kNodeIsTooComplexForGreedyLoops = -1;
+  virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
+  Label* label() { return &label_; }
+  static const int kMaxVariantsGenerated = 10;
 
   RegExpNode* EnsureExpanded(NodeInfo* info);
   virtual RegExpNode* ExpandLocal(NodeInfo* info) = 0;
@@ -630,7 +644,6 @@
   virtual RegExpNode* PropagateForward(NodeInfo* info) = 0;
 
   NodeInfo* info() { return &info_; }
-  virtual bool IsBacktrack() { return false; }
 
   void AddSibling(RegExpNode* node) { siblings_.Add(node); }
 
@@ -645,6 +658,9 @@
   void set_siblings(SiblingList* other) { siblings_ = *other; }
 
  protected:
+  enum LimitResult { DONE, FAIL, CONTINUE };
+  LimitResult LimitVersions(RegExpCompiler* compiler,
+                            GenerationVariant* variant);
 
   // Returns a sibling of this node whose interests and assumptions
   // match the ones in the given node info.  If no sibling exists NULL
@@ -663,12 +679,11 @@
   // processed before it is on a useable state.
   virtual RegExpNode* Clone() = 0;
 
-  inline void Bind(RegExpMacroAssembler* macro);
-
  private:
   Label label_;
   NodeInfo info_;
   SiblingList siblings_;
+  int variants_generated_;
 };
 
 
@@ -678,7 +693,6 @@
       : on_success_(on_success) { }
   RegExpNode* on_success() { return on_success_; }
   void set_on_success(RegExpNode* node) { on_success_ = node; }
-  virtual bool Emit(RegExpCompiler* compiler) { return false; }
  private:
   RegExpNode* on_success_;
 };
@@ -687,29 +701,31 @@
 class ActionNode: public SeqRegExpNode {
  public:
   enum Type {
-    STORE_REGISTER,
+    SET_REGISTER,
     INCREMENT_REGISTER,
     STORE_POSITION,
-    RESTORE_POSITION,
     BEGIN_SUBMATCH,
-    ESCAPE_SUBMATCH
+    POSITIVE_SUBMATCH_SUCCESS
   };
-  static ActionNode* StoreRegister(int reg, int val, RegExpNode* on_success);
+  static ActionNode* SetRegister(int reg, int val, RegExpNode* on_success);
   static ActionNode* IncrementRegister(int reg, RegExpNode* on_success);
   static ActionNode* StorePosition(int reg, RegExpNode* on_success);
-  static ActionNode* RestorePosition(int reg, RegExpNode* on_success);
-  static ActionNode* BeginSubmatch(int stack_pointer_reg,
-                                   int position_reg,
-                                   RegExpNode* on_success);
-  static ActionNode* EscapeSubmatch(int stack_pointer_reg,
-                                    bool and_restore_position,
-                                    int restore_reg,
-                                    RegExpNode* on_success);
+  static ActionNode* BeginSubmatch(
+      int stack_pointer_reg,
+      int position_reg,
+      RegExpNode* on_success);
+  static ActionNode* PositiveSubmatchSuccess(
+      int stack_pointer_reg,
+      int restore_reg,
+      RegExpNode* on_success);
   virtual void Accept(NodeVisitor* visitor);
-  virtual bool Emit(RegExpCompiler* compiler);
+  virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
   virtual RegExpNode* ExpandLocal(NodeInfo* info);
   virtual void ExpandChildren();
   virtual RegExpNode* PropagateForward(NodeInfo* info);
+  Type type() { return type_; }
+  // TODO(erikcorry): We should allow some action nodes in greedy loops.
+  virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
   virtual ActionNode* Clone() { return new ActionNode(*this); }
 
  private:
@@ -740,16 +756,12 @@
 class TextNode: public SeqRegExpNode {
  public:
   TextNode(ZoneList<TextElement>* elms,
-           RegExpNode* on_success,
-           RegExpNode* on_failure)
+           RegExpNode* on_success)
       : SeqRegExpNode(on_success),
-        on_failure_(on_failure),
         elms_(elms) { }
   TextNode(RegExpCharacterClass* that,
-           RegExpNode* on_success,
-           RegExpNode* on_failure)
+           RegExpNode* on_success)
       : SeqRegExpNode(on_success),
-        on_failure_(on_failure),
         elms_(new ZoneList<TextElement>(1)) {
     elms_->Add(TextElement::CharClass(that));
   }
@@ -757,17 +769,20 @@
   virtual RegExpNode* PropagateForward(NodeInfo* info);
   virtual RegExpNode* ExpandLocal(NodeInfo* info);
   virtual void ExpandChildren();
-  RegExpNode* on_failure() { return on_failure_; }
-  virtual bool Emit(RegExpCompiler* compiler);
+  virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
   ZoneList<TextElement>* elements() { return elms_; }
   void MakeCaseIndependent();
-  virtual TextNode* Clone() { return new TextNode(*this); }
-
+  virtual int GreedyLoopTextLength();
+  virtual TextNode* Clone() {
+    TextNode* result = new TextNode(*this);
+    result->CalculateOffsets();
+    return result;
+  }
+  void CalculateOffsets();
  private:
   void ExpandAtomChildren(RegExpAtom* that);
   void ExpandCharClassChildren(RegExpCharacterClass* that);
 
-  RegExpNode* on_failure_;
   ZoneList<TextElement>* elms_;
 };
 
@@ -776,24 +791,20 @@
  public:
   BackReferenceNode(int start_reg,
                     int end_reg,
-                    RegExpNode* on_success,
-                    RegExpNode* on_failure)
+                    RegExpNode* on_success)
       : SeqRegExpNode(on_success),
-        on_failure_(on_failure),
         start_reg_(start_reg),
         end_reg_(end_reg) { }
   virtual void Accept(NodeVisitor* visitor);
-  RegExpNode* on_failure() { return on_failure_; }
   int start_register() { return start_reg_; }
   int end_register() { return end_reg_; }
-  virtual bool Emit(RegExpCompiler* compiler);
+  virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
   virtual RegExpNode* PropagateForward(NodeInfo* info);
   virtual RegExpNode* ExpandLocal(NodeInfo* info);
   virtual void ExpandChildren();
   virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); }
 
  private:
-  RegExpNode* on_failure_;
   int start_reg_;
   int end_reg_;
 };
@@ -801,22 +812,37 @@
 
 class EndNode: public RegExpNode {
  public:
-  enum Action { ACCEPT, BACKTRACK };
+  enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS };
   explicit EndNode(Action action) : action_(action) { }
   virtual void Accept(NodeVisitor* visitor);
-  virtual bool Emit(RegExpCompiler* compiler);
+  virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
   virtual RegExpNode* PropagateForward(NodeInfo* info);
   virtual RegExpNode* ExpandLocal(NodeInfo* info);
   virtual void ExpandChildren();
-  virtual bool IsBacktrack() { return action_ == BACKTRACK; }
-  virtual bool GoTo(RegExpCompiler* compiler);
   virtual EndNode* Clone() { return new EndNode(*this); }
 
+ protected:
+  void EmitInfoChecks(RegExpMacroAssembler* macro, GenerationVariant* variant);
+
  private:
   Action action_;
 };
 
 
+class NegativeSubmatchSuccess: public EndNode {
+ public:
+  NegativeSubmatchSuccess(int stack_pointer_reg, int position_reg)
+      : EndNode(NEGATIVE_SUBMATCH_SUCCESS),
+        stack_pointer_register_(stack_pointer_reg),
+        current_position_register_(position_reg) { }
+  virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
+
+ private:
+  int stack_pointer_register_;
+  int current_position_register_;
+};
+
+
 class Guard: public ZoneObject {
  public:
   enum Relation { LT, GEQ };
@@ -851,17 +877,15 @@
 
 class ChoiceNode: public RegExpNode {
  public:
-  explicit ChoiceNode(int expected_size, RegExpNode* on_failure)
-      : on_failure_(on_failure),
-        alternatives_(new ZoneList<GuardedAlternative>(expected_size)),
+  explicit ChoiceNode(int expected_size)
+      : alternatives_(new ZoneList<GuardedAlternative>(expected_size)),
         table_(NULL),
         being_calculated_(false) { }
   virtual void Accept(NodeVisitor* visitor);
   void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); }
   ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
   DispatchTable* GetTable(bool ignore_case);
-  RegExpNode* on_failure() { return on_failure_; }
-  virtual bool Emit(RegExpCompiler* compiler);
+  virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
   virtual RegExpNode* PropagateForward(NodeInfo* info);
   virtual RegExpNode* ExpandLocal(NodeInfo* info);
   virtual void ExpandChildren();
@@ -870,19 +894,128 @@
   bool being_calculated() { return being_calculated_; }
   void set_being_calculated(bool b) { being_calculated_ = b; }
 
+ protected:
+  int GreedyLoopTextLength(GuardedAlternative *alternative);
+  ZoneList<GuardedAlternative>* alternatives_;
+
  private:
   friend class DispatchTableConstructor;
-  friend class Analysis;
+  friend class AssertionPropagation;
   void GenerateGuard(RegExpMacroAssembler* macro_assembler,
                      Guard *guard,
-                     Label* on_failure);
-  RegExpNode* on_failure_;
-  ZoneList<GuardedAlternative>* alternatives_;
+                     GenerationVariant* variant);
   DispatchTable* table_;
   bool being_calculated_;
 };
 
 
+class LoopChoiceNode: public ChoiceNode {
+ public:
+  explicit LoopChoiceNode(int expected_size) : ChoiceNode(expected_size) { }
+  virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
+  virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); }
+};
+
+
+// There are many ways to generate code for a node.  This class encapsulates
+// the current way we should be generating.  In other words it encapsulates
+// the current state of the code generator.
+class GenerationVariant {
+ public:
+  class DeferredAction {
+   public:
+    DeferredAction(ActionNode::Type type, int reg)
+        : type_(type), reg_(reg), next_(NULL) { }
+    DeferredAction* next() { return next_; }
+    int reg() { return reg_; }
+    ActionNode::Type type() { return type_; }
+   private:
+    ActionNode::Type type_;
+    int reg_;
+    DeferredAction* next_;
+    friend class GenerationVariant;
+  };
+
+  class DeferredCapture: public DeferredAction {
+   public:
+    DeferredCapture(int reg, GenerationVariant* variant)
+        : DeferredAction(ActionNode::STORE_POSITION, reg),
+          cp_offset_(variant->cp_offset()) { }
+    int cp_offset() { return cp_offset_; }
+   private:
+    int cp_offset_;
+    void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; }
+  };
+
+  class DeferredSetRegister :public DeferredAction {
+   public:
+    DeferredSetRegister(int reg, int value)
+        : DeferredAction(ActionNode::SET_REGISTER, reg),
+          value_(value) { }
+    int value() { return value_; }
+   private:
+    int value_;
+  };
+
+  class DeferredIncrementRegister: public DeferredAction {
+   public:
+    explicit DeferredIncrementRegister(int reg)
+        : DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { }
+  };
+
+  explicit GenerationVariant(Label* backtrack)
+      : cp_offset_(0),
+        actions_(NULL),
+        backtrack_(backtrack),
+        stop_node_(NULL),
+        loop_label_(NULL) { }
+  GenerationVariant()
+      : cp_offset_(0),
+        actions_(NULL),
+        backtrack_(NULL),
+        stop_node_(NULL),
+        loop_label_(NULL) { }
+  bool Flush(RegExpCompiler* compiler, RegExpNode* successor);
+  int cp_offset() { return cp_offset_; }
+  DeferredAction* actions() { return actions_; }
+  bool is_trivial() {
+    return backtrack_ == NULL && actions_ == NULL && cp_offset_ == 0;
+  }
+  Label* backtrack() { return backtrack_; }
+  Label* loop_label() { return loop_label_; }
+  RegExpNode* stop_node() { return stop_node_; }
+  // These set methods should be used only on new GenerationVariants - the
+  // intention is that GenerationVariants are immutable after creation.
+  void add_action(DeferredAction* new_action) {
+    ASSERT(new_action->next_ == NULL);
+    new_action->next_ = actions_;
+    actions_ = new_action;
+  }
+  void set_cp_offset(int new_cp_offset) {
+    ASSERT(new_cp_offset >= cp_offset_);
+    cp_offset_ = new_cp_offset;
+  }
+  void set_backtrack(Label* backtrack) { backtrack_ = backtrack; }
+  void set_stop_node(RegExpNode* node) { stop_node_ = node; }
+  void set_loop_label(Label* label) { loop_label_ = label; }
+  bool mentions_reg(int reg);
+ private:
+  int FindAffectedRegisters(OutSet* affected_registers);
+  void PerformDeferredActions(RegExpMacroAssembler* macro,
+                               int max_register,
+                               OutSet& affected_registers);
+  void RestoreAffectedRegisters(RegExpMacroAssembler* macro,
+                                int max_register,
+                                OutSet& affected_registers);
+  void PushAffectedRegisters(RegExpMacroAssembler* macro,
+                             int max_register,
+                             OutSet& affected_registers);
+  int cp_offset_;
+  DeferredAction* actions_;
+  Label* backtrack_;
+  RegExpNode* stop_node_;
+  Label* loop_label_;
+};
 class NodeVisitor {
  public:
   virtual ~NodeVisitor() { }
@@ -925,9 +1058,45 @@
 };
 
 
-class Analysis: public NodeVisitor {
+// Assertion propagation moves information about assertions such as
+// \b to the affected nodes.  For instance, in /.\b./ information must
+// be propagated to the first '.' that whatever follows needs to know
+// if it matched a word or a non-word, and to the second '.' that it
+// has to check if it succeeds a word or non-word.  In this case the
+// result will be something like:
+//
+//   +-------+        +------------+
+//   |   .   |        |      .     |
+//   +-------+  --->  +------------+
+//   | word? |        | check word |
+//   +-------+        +------------+
+//
+// At a later phase all nodes that determine information for their
+// following nodes are split into several 'sibling' nodes.  In this
+// case the first '.' is split into one node that only matches words
+// and one that only matches non-words.  The second '.' is also split,
+// into one node that assumes that the previous character was a word
+// character and one that assumes that is was non-word.  In this case
+// the result is
+//
+//         +------------------+        +------------------+
+//   /-->  | intersect(., \w) |  --->  | intersect(., \W) |
+//   |     +------------------+        +------------------+
+//   |                                 |    follows \w    |
+//   |                                 +------------------+
+// --?
+//   |     +------------------+        +------------------+
+//   \-->  | intersect(., \W) |  --->  | intersect(., \w) |
+//         +------------------+        +------------------+
+//                                     |    follows \W    |
+//                                     +------------------+
+//
+// This way we don't need to explicitly check the previous character
+// but can always assume that whoever consumed the previous character
+// has propagated the relevant information forward.
+class AssertionPropagation: public NodeVisitor {
  public:
-  explicit Analysis(bool ignore_case)
+  explicit AssertionPropagation(bool ignore_case)
       : ignore_case_(ignore_case) { }
   void EnsureAnalyzed(RegExpNode* node);
 
@@ -939,12 +1108,20 @@
  private:
   bool ignore_case_;
 
-  DISALLOW_IMPLICIT_CONSTRUCTORS(Analysis);
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AssertionPropagation);
 };
 
 
-struct RegExpParseResult {
+struct RegExpCompileData {
+  RegExpCompileData()
+    : tree(NULL),
+      node(NULL),
+      has_lookbehind(false),
+      has_character_escapes(false),
+      capture_count(0) { }
   RegExpTree* tree;
+  RegExpNode* node;
+  bool has_lookbehind;
   bool has_character_escapes;
   Handle<String> error;
   int capture_count;
@@ -953,10 +1130,12 @@
 
 class RegExpEngine: public AllStatic {
  public:
-  static Handle<FixedArray> Compile(RegExpParseResult* input,
-                                    RegExpNode** node_return,
+  static Handle<FixedArray> Compile(RegExpCompileData* input,
                                     bool ignore_case,
-                                    bool multiline);
+                                    bool multiline,
+                                    Handle<String> pattern,
+                                    bool is_ascii);
+
   static void DotPrint(const char* label, RegExpNode* node, bool ignore_case);
 };
 
diff --git a/src/log.cc b/src/log.cc
index d145480..4fa398c 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -593,12 +593,15 @@
 }
 
 
-void Logger::SuspectReadEvent(String* name, String* obj) {
+void Logger::SuspectReadEvent(String* name, Object* obj) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
   if (logfile_ == NULL || !FLAG_log_suspect) return;
+  String* class_name = obj->IsJSObject()
+                       ? JSObject::cast(obj)->class_name()
+                       : Heap::empty_string();
   ScopedLock sl(mutex_);
   fprintf(logfile_, "suspect-read,");
-  obj->PrintOn(logfile_);
+  class_name->PrintOn(logfile_);
   fprintf(logfile_, ",\"");
   name->PrintOn(logfile_);
   fprintf(logfile_, "\"\n");
diff --git a/src/log.h b/src/log.h
index eb082da..89d3e8a 100644
--- a/src/log.h
+++ b/src/log.h
@@ -134,7 +134,7 @@
 
   // Emits an event that an undefined property was read from an
   // object.
-  static void SuspectReadEvent(String* name, String* obj);
+  static void SuspectReadEvent(String* name, Object* obj);
 
   // Emits an event when a message is put on or read from a debugging queue.
   // DebugTag lets us put a call-site specific label on the event.
diff --git a/src/macro-assembler-arm.cc b/src/macro-assembler-arm.cc
index 7016145..5cbeae9 100644
--- a/src/macro-assembler-arm.cc
+++ b/src/macro-assembler-arm.cc
@@ -176,6 +176,20 @@
 }
 
 
+void MacroAssembler::SmiJumpTable(Register index, Vector<Label*> targets) {
+  // Empty the const pool.
+  CheckConstPool(true, true);
+  add(pc, pc, Operand(index,
+                      LSL,
+                      assembler::arm::Instr::kInstrSizeLog2 - kSmiTagSize));
+  BlockConstPoolBefore(pc_offset() + (targets.length() + 1) * sizeof(Instr));
+  nop();  // Jump table alignment.
+  for (int i = 0; i < targets.length(); i++) {
+    b(targets[i]);
+  }
+}
+
+
 // Will clobber 4 registers: object, offset, scratch, ip.  The
 // register 'object' contains a heap object pointer.  The heap object
 // tag is shifted away.
diff --git a/src/macro-assembler-arm.h b/src/macro-assembler-arm.h
index 7cc843f..b2edf3e 100644
--- a/src/macro-assembler-arm.h
+++ b/src/macro-assembler-arm.h
@@ -87,7 +87,8 @@
   void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al);
   void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
   void Ret();
-
+  // Jumps to the label at the index given by the Smi in "index".
+  void SmiJumpTable(Register index, Vector<Label*> targets);
 
   // Sets the remembered set bit for [address+offset], where address is the
   // address of the heap object 'object'.  The address must be in the first 8K
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index de05339..ede5741 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -564,10 +564,10 @@
 
 
 void MarkCompactCollector::MarkObjectGroups() {
-  List<ObjectGroup*>& object_groups = GlobalHandles::ObjectGroups();
+  List<ObjectGroup*>* object_groups = GlobalHandles::ObjectGroups();
 
-  for (int i = 0; i < object_groups.length(); i++) {
-    ObjectGroup* entry = object_groups[i];
+  for (int i = 0; i < object_groups->length(); i++) {
+    ObjectGroup* entry = object_groups->at(i);
     if (entry == NULL) continue;
 
     List<Object**>& objects = entry->objects_;
@@ -591,8 +591,8 @@
     }
     // Once the entire group has been colored gray, set the object group
     // to NULL so it won't be processed again.
-    delete object_groups[i];
-    object_groups[i] = NULL;
+    delete object_groups->at(i);
+    object_groups->at(i) = NULL;
   }
 }
 
diff --git a/src/objects-inl.h b/src/objects-inl.h
index e8c4e91..5c70463 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1877,6 +1877,17 @@
 }
 
 
+Code* Code::GetCodeFromTargetAddress(Address address) {
+  HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
+  // GetCodeFromTargetAddress might be called when marking objects during mark
+  // sweep. reinterpret_cast is therefore used instead of the more appropriate
+  // Code::cast. Code::cast does not work when the object's map is
+  // marked.
+  Code* result = reinterpret_cast<Code*>(code);
+  return result;
+}
+
+
 Object* Map::prototype() {
   return READ_FIELD(this, kPrototypeOffset);
 }
diff --git a/src/objects.cc b/src/objects.cc
index 6068898..edc5a0d 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -147,7 +147,9 @@
                                         PropertyAttributes* attributes) {
   LookupResult result;
   Lookup(name, &result);
-  return GetProperty(receiver, &result, name, attributes);
+  Object* value = GetProperty(receiver, &result, name, attributes);
+  ASSERT(*attributes <= ABSENT);
+  return value;
 }
 
 
@@ -215,9 +217,11 @@
 
 
 // Only deal with CALLBACKS and INTERCEPTOR
-Object* JSObject::GetPropertyWithFailedAccessCheck(Object* receiver,
-                                                   LookupResult* result,
-                                                   String* name) {
+Object* JSObject::GetPropertyWithFailedAccessCheck(
+    Object* receiver,
+    LookupResult* result,
+    String* name,
+    PropertyAttributes* attributes) {
   if (result->IsValid()) {
     switch (result->type()) {
       case CALLBACKS: {
@@ -226,6 +230,7 @@
         if (obj->IsAccessorInfo()) {
           AccessorInfo* info = AccessorInfo::cast(obj);
           if (info->all_can_read()) {
+            *attributes = result->GetAttributes();
             return GetPropertyWithCallback(receiver,
                                            result->GetCallbackObject(),
                                            name,
@@ -241,7 +246,10 @@
         LookupResult r;
         result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
         if (r.IsValid()) {
-          return GetPropertyWithFailedAccessCheck(receiver, &r, name);
+          return GetPropertyWithFailedAccessCheck(receiver,
+                                                  &r,
+                                                  name,
+                                                  attributes);
         }
         break;
       }
@@ -251,9 +259,11 @@
         LookupResult r;
         result->holder()->LookupRealNamedProperty(name, &r);
         if (r.IsValid()) {
-          return GetPropertyWithFailedAccessCheck(receiver, &r, name);
+          return GetPropertyWithFailedAccessCheck(receiver,
+                                                  &r,
+                                                  name,
+                                                  attributes);
         }
-        break;
       }
       default: {
         break;
@@ -261,6 +271,8 @@
     }
   }
 
+  // No accessible property found.
+  *attributes = ABSENT;
   Top::ReportFailedAccessCheck(this, v8::ACCESS_GET);
   return Heap::undefined_value();
 }
@@ -402,7 +414,8 @@
       if (!Top::MayNamedAccess(checked, name, v8::ACCESS_GET)) {
         return checked->GetPropertyWithFailedAccessCheck(receiver,
                                                          result,
-                                                         name);
+                                                         name,
+                                                         attributes);
       }
     }
     // Stop traversing the chain once we reach the last object in the
diff --git a/src/objects.h b/src/objects.h
index f6feca8..f400e99 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1185,7 +1185,8 @@
   // Used from Object::GetProperty().
   Object* GetPropertyWithFailedAccessCheck(Object* receiver,
                                            LookupResult* result,
-                                           String* name);
+                                           String* name,
+                                           PropertyAttributes* attributes);
   Object* GetPropertyWithInterceptor(JSObject* receiver,
                                      String* name,
                                      PropertyAttributes* attributes);
@@ -2200,6 +2201,8 @@
   static inline int ExtractArgumentsCountFromFlags(Flags flags);
   static inline Flags RemoveTypeFromFlags(Flags flags);
 
+  // Convert a target address into a code object.
+  static inline Code* GetCodeFromTargetAddress(Address address);
 
   // Returns the address of the first instruction.
   inline byte* instruction_start();
@@ -2923,7 +2926,7 @@
   // ATOM: A simple string to match against using an indexOf operation.
   // IRREGEXP: Compiled with Irregexp.
   // IRREGEXP_NATIVE: Compiled to native code with Irregexp.
-  enum Type { NOT_COMPILED, JSCRE, ATOM, IRREGEXP, IRREGEXP_NATIVE };
+  enum Type { NOT_COMPILED, JSCRE, ATOM, IRREGEXP };
   enum Flag { NONE = 0, GLOBAL = 1, IGNORE_CASE = 2, MULTILINE = 4 };
 
   class Flags {
@@ -3211,6 +3214,7 @@
 
   // Max ascii char code.
   static const int kMaxAsciiCharCode = unibrow::Utf8::kMaxOneByteChar;
+  static const int kMaxUC16CharCode = 0xffff;
 
   // Minimum length for a cons or sliced string.
   static const int kMinNonFlatLength = 13;
diff --git a/src/parser.cc b/src/parser.cc
index 8217315..7236cb4 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -4302,7 +4302,7 @@
 
 bool ParseRegExp(FlatStringReader* input,
                  bool multiline,
-                 RegExpParseResult* result) {
+                 RegExpCompileData* result) {
   ASSERT(result != NULL);
   // Make sure we have a stack guard.
   StackGuard guard;
diff --git a/src/parser.h b/src/parser.h
index 0ebef74..6e86f09 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -147,7 +147,7 @@
 
 bool ParseRegExp(FlatStringReader* input,
                  bool multiline,
-                 RegExpParseResult* result);
+                 RegExpCompileData* result);
 
 
 // Support for doing lazy compilation. The script is the script containing full
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 75140c9..d7b3223 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -194,6 +194,11 @@
 }
 
 
+char* OS::StrNDup(const char* str, size_t n) {
+  return strndup(str, n);
+}
+
+
 double OS::nan_value() {
   return NAN;
 }
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 2bb9665..96ef899 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -185,11 +185,16 @@
 }
 
 
-char *OS::StrDup(const char* str) {
+char* OS::StrDup(const char* str) {
   return strdup(str);
 }
 
 
+char* OS::StrNDup(const char* str, size_t n) {
+  return strndup(str, n);
+}
+
+
 double OS::nan_value() {
   return NAN;
 }
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index f08d64d..122e7fa 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -190,11 +190,26 @@
 }
 
 
-char *OS::StrDup(const char* str) {
+char* OS::StrDup(const char* str) {
   return strdup(str);
 }
 
 
+char* OS::StrNDup(const char* str, size_t n) {
+  // Stupid implementation of strndup since macos isn't born with
+  // one.
+  size_t len = strlen(str);
+  if (len <= n)
+    return StrDup(str);
+  char* result = new char[n+1];
+  size_t i;
+  for (i = 0; i <= n; i++)
+    result[i] = str[i];
+  result[i] = '\0';
+  return result;
+}
+
+
 // We keep the lowest and highest addresses mapped as a quick way of
 // determining that pointers are outside the heap (used mostly in assertions
 // and verification).  The estimate is conservative, ie, not all addresses in
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index bd65dde..ada090a 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -695,11 +695,26 @@
 }
 
 
-char *OS::StrDup(const char* str) {
+char* OS::StrDup(const char* str) {
   return _strdup(str);
 }
 
 
+char* OS::StrNDup(const char* str, size_t n) {
+  // Stupid implementation of strndup since windows isn't born with
+  // one.
+  size_t len = strlen(str);
+  if (len <= n)
+    return StrDup(str);
+  char* result = new char[n+1];
+  size_t i;
+  for (i = 0; i <= n; i++)
+    result[i] = str[i];
+  result[i] = '\0';
+  return result;
+}
+
+
 // We keep the lowest and highest addresses mapped as a quick way of
 // determining that pointers are outside the heap (used mostly in assertions
 // and verification).  The estimate is conservative, ie, not all addresses in
diff --git a/src/platform.h b/src/platform.h
index cc44718..8d62efd 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -206,6 +206,7 @@
 
   static void StrNCpy(Vector<char> dest, const char* src, size_t n);
   static char* StrDup(const char* str);
+  static char* StrNDup(const char* str, size_t n);
 
   // Support for profiler.  Can do nothing, in which case ticks
   // occuring in shared libraries will not be properly accounted
diff --git a/src/regexp-macro-assembler-ia32.cc b/src/regexp-macro-assembler-ia32.cc
index 76b4bcf..be2990e 100644
--- a/src/regexp-macro-assembler-ia32.cc
+++ b/src/regexp-macro-assembler-ia32.cc
@@ -27,6 +27,7 @@
 
 #include <string.h>
 #include "v8.h"
+#include "unicode.h"
 #include "log.h"
 #include "ast.h"
 #include "macro-assembler.h"
@@ -110,9 +111,10 @@
 
 
 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) {
-  ASSERT(by > 0);
-  Label inside_string;
-  __ add(Operand(edi), Immediate(by * char_size()));
+  if (by != 0) {
+    Label inside_string;
+    __ add(Operand(edi), Immediate(by * char_size()));
+  }
 }
 
 
@@ -137,7 +139,7 @@
 void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start,
                                            Label* bitmap,
                                            Label* on_zero) {
-  UNREACHABLE();
+  UNIMPLEMENTED();
   __ mov(eax, current_character());
   __ sub(Operand(eax), Immediate(start));
   __ cmp(eax, 64);  // FIXME: 64 = length_of_bitmap_in_bits.
@@ -149,7 +151,7 @@
   __ movzx_b(ebx, Operand(ecx, ebx, times_1, 0));
   __ and_(eax, (1<<3)-1);
   __ bt(Operand(ebx), eax);
-  __ j(carry, on_zero);
+  BranchOrBacktrack(carry, on_zero);
 }
 
 
@@ -183,11 +185,14 @@
 
 void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
                                                int cp_offset,
-                                               Label* on_failure) {
+                                               Label* on_failure,
+                                               bool check_end_of_string) {
   int byte_length = str.length() * char_size();
   int byte_offset = cp_offset * char_size();
-  __ cmp(Operand(edi), Immediate(-(byte_offset + byte_length)));
-  BranchOrBacktrack(greater, on_failure);
+  if (check_end_of_string) {
+    __ cmp(Operand(edi), Immediate(-(byte_offset + byte_length)));
+    BranchOrBacktrack(greater, on_failure);
+  }
 
   if (str.length() <= kMaxInlineStringTests) {
     for (int i = 0; i < str.length(); i++) {
@@ -199,7 +204,7 @@
         __ cmpw(Operand(esi, edi, times_1, byte_offset + i * sizeof(uc16)),
                 Immediate(str[i]));
       }
-      __ j(not_equal, on_failure);
+      BranchOrBacktrack(not_equal, on_failure);
     }
     return;
   }
@@ -232,30 +237,108 @@
 }
 
 
-void RegExpMacroAssemblerIA32::CheckCurrentPosition(int register_index,
-                                                    Label* on_equal) {
-  __ cmp(edi, register_location(register_index));
-  BranchOrBacktrack(equal, on_equal);
+void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) {
+  Label fallthrough;
+  __ cmp(edi, Operand(esp, 0));
+  __ j(not_equal, &fallthrough);
+  __ add(Operand(esp), Immediate(4));  // Pop.
+  BranchOrBacktrack(no_condition, on_equal);
+  __ bind(&fallthrough);
 }
 
 
 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
-    int start_reg, Label* on_no_match) {
+    int start_reg,
+    Label* on_no_match) {
   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);
+  BranchOrBacktrack(less, on_no_match);
   __ j(equal, &fallthrough);
 
-  UNIMPLEMENTED();  // TODO(lrn): Call runtime function to do test.
+  if (mode_ == ASCII) {
+    Label success;
+    Label fail;
+    __ push(esi);
+    __ push(edi);
+    __ add(edi, Operand(esi));
+    __ add(esi, Operand(eax));
+    Label loop;
+    __ bind(&loop);
+    __ rep_cmpsb();
+    __ j(equal, &success);
+    // Compare lower-case if letters.
+    __ movzx_b(eax, Operand(edi, -1));
+    __ or_(eax, 0x20);  // To-lower-case
+    __ lea(ebx, Operand(eax, -'a'));
+    __ cmp(ebx, static_cast<int32_t>('z' - 'a'));
+    __ j(above, &fail);
+    __ movzx_b(ebx, Operand(esi, -1));
+    __ or_(ebx, 0x20);  // To-lower-case
+    __ cmp(eax, Operand(ebx));
+    __ j(not_equal, &fail);
+    __ or_(ecx, Operand(ecx));
+    __ j(not_equal, &loop);
+    __ jmp(&success);
 
+    __ bind(&fail);
+    __ pop(edi);
+    __ pop(esi);
+    BranchOrBacktrack(no_condition, on_no_match);
+
+    __ bind(&success);
+    __ pop(eax);  // discard original value of edi
+    __ pop(esi);
+    __ sub(edi, Operand(esi));
+  } else {
+    // store state
+    __ push(esi);
+    __ push(edi);
+    __ push(ecx);
+    // align stack
+    int frameAlignment = OS::ActivationFrameAlignment();
+    if (frameAlignment != 0) {
+      __ mov(ebx, esp);
+      __ sub(Operand(esp), Immediate(5 * kPointerSize));  // args + esp.
+      ASSERT(IsPowerOf2(frameAlignment));
+      __ and_(esp, -frameAlignment);
+      __ mov(Operand(esp, 4 * kPointerSize), ebx);
+    } else {
+      __ sub(Operand(esp), Immediate(4 * kPointerSize));
+    }
+    // Put arguments on stack.
+    __ mov(Operand(esp, 3 * kPointerSize), ecx);
+    __ mov(ebx, Operand(ebp, kInputEndOffset));
+    __ add(edi, Operand(ebx));
+    __ mov(Operand(esp, 2 * kPointerSize), edi);
+    __ add(eax, Operand(ebx));
+    __ mov(Operand(esp, 1 * kPointerSize), eax);
+    __ mov(eax, Operand(ebp, kInputBuffer));
+    __ mov(Operand(esp, 0 * kPointerSize), eax);
+    Address function_address = FUNCTION_ADDR(&CaseInsensitiveCompareUC16);
+    __ mov(Operand(eax),
+        Immediate(reinterpret_cast<int32_t>(function_address)));
+    __ call(Operand(eax));
+    if (frameAlignment != 0) {
+      __ mov(esp, Operand(esp, 4 * kPointerSize));
+    } else {
+      __ add(Operand(esp), Immediate(4 * sizeof(int32_t)));
+    }
+    __ pop(ecx);
+    __ pop(edi);
+    __ pop(esi);
+    __ or_(eax, Operand(eax));
+    BranchOrBacktrack(zero, on_no_match);
+    __ add(edi, Operand(ecx));
+  }
   __ bind(&fallthrough);
 }
 
 
 void RegExpMacroAssemblerIA32::CheckNotBackReference(
-    int start_reg, Label* on_no_match) {
+    int start_reg,
+    Label* on_no_match) {
   Label fallthrough;
   __ mov(eax, register_location(start_reg));
   __ mov(ecx, register_location(start_reg + 1));
@@ -406,7 +489,7 @@
 }
 
 
-Handle<Object> RegExpMacroAssemblerIA32::GetCode() {
+Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
   // Finalize code - write the entry point code now we know how many
   // registers we need.
 
@@ -445,7 +528,7 @@
   Label at_start;
   __ cmp(Operand(ebp, kAtStart), Immediate(0));
   __ j(not_equal, &at_start);
-  LoadCurrentCharToRegister(-1);  // Load previous char.
+  LoadCurrentCharacterUnchecked(-1);  // Load previous char.
   __ jmp(&start_label_);
   __ bind(&at_start);
   __ mov(current_character(), '\n');
@@ -486,13 +569,13 @@
                                        NULL,
                                        Code::ComputeFlags(Code::REGEXP),
                                        self_);
-  LOG(CodeCreateEvent("RegExp", *code, "(Compiled RegExp)"));
+  LOG(CodeCreateEvent("RegExp", *code, *(source->ToCString())));
   return Handle<Object>::cast(code);
 }
 
 
 void RegExpMacroAssemblerIA32::GoTo(Label* to) {
-  __ jmp(to);
+  BranchOrBacktrack(no_condition, to);
 }
 
 
@@ -524,7 +607,7 @@
   ASSERT(cp_offset < (1<<30));  // Be sane! (And ensure negation works)
   __ cmp(edi, -cp_offset * char_size());
   BranchOrBacktrack(greater_equal, on_end_of_input);
-  LoadCurrentCharToRegister(cp_offset);
+  LoadCurrentCharacterUnchecked(cp_offset);
 }
 
 
@@ -575,10 +658,17 @@
 }
 
 
-void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg) {
-  __ mov(register_location(reg), edi);
+void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg,
+                                                              int cp_offset) {
+  if (cp_offset == 0) {
+    __ mov(register_location(reg), edi);
+  } else {
+    __ lea(eax, Operand(edi, cp_offset * char_size()));
+    __ mov(register_location(reg), eax);
+  }
 }
 
+
 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
   __ mov(register_location(reg), esp);
 }
@@ -586,6 +676,40 @@
 
 // Private methods:
 
+
+static unibrow::Mapping<unibrow::Ecma262Canonicalize> canonicalize;
+
+
+int RegExpMacroAssemblerIA32::CaseInsensitiveCompareUC16(uc16** buffer,
+                                                         int byte_offset1,
+                                                         int byte_offset2,
+                                                         size_t byte_length) {
+  // This function is not allowed to cause a garbage collection.
+  // A GC might move the calling generated code and invalidate the
+  // return address on the stack.
+  ASSERT(byte_length % 2 == 0);
+  Address buffer_address = reinterpret_cast<Address>(*buffer);
+  uc16* substring1 = reinterpret_cast<uc16*>(buffer_address + byte_offset1);
+  uc16* substring2 = reinterpret_cast<uc16*>(buffer_address + byte_offset2);
+  size_t length = byte_length >> 1;
+
+  for (size_t i = 0; i < length; i++) {
+    unibrow::uchar c1 = substring1[i];
+    unibrow::uchar c2 = substring2[i];
+    if (c1 != c2) {
+      canonicalize.get(c1, '\0', &c1);
+      if (c1 != c2) {
+        canonicalize.get(c2, '\0', &c2);
+        if (c1 != c2) {
+          return 0;
+        }
+      }
+    }
+  }
+  return 1;
+}
+
+
 Operand RegExpMacroAssemblerIA32::register_location(int register_index) {
   ASSERT(register_index < (1<<30));
   if (num_registers_ <= register_index) {
@@ -663,7 +787,7 @@
 }
 
 
-void RegExpMacroAssemblerIA32::LoadCurrentCharToRegister(int cp_offset) {
+void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset) {
   if (mode_ == ASCII) {
     __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset));
     return;
diff --git a/src/regexp-macro-assembler-ia32.h b/src/regexp-macro-assembler-ia32.h
index d303910..78ab2bd 100644
--- a/src/regexp-macro-assembler-ia32.h
+++ b/src/regexp-macro-assembler-ia32.h
@@ -47,8 +47,9 @@
   virtual void CheckCharacterLT(uc16 limit, Label* on_less);
   virtual void CheckCharacters(Vector<const uc16> str,
                                int cp_offset,
-                               Label* on_failure);
-  virtual void CheckCurrentPosition(int register_index, Label* on_equal);
+                               Label* on_failure,
+                               bool check_end_of_string);
+  virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
   virtual void CheckNotAtStart(Label* on_not_at_start);
   virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
   virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
@@ -70,12 +71,14 @@
                                    const Vector<Label*>& destinations);
   virtual void EmitOrLink(Label* label);
   virtual void Fail();
-  virtual Handle<Object> GetCode();
+  virtual Handle<Object> GetCode(Handle<String> source);
   virtual void GoTo(Label* label);
   virtual void IfRegisterGE(int reg, int comparand, Label* if_ge);
   virtual void IfRegisterLT(int reg, int comparand, Label* if_lt);
   virtual IrregexpImplementation Implementation();
   virtual void LoadCurrentCharacter(int cp_offset, Label* on_end_of_input);
+  virtual void LoadCurrentCharacterUnchecked(int cp_offset);
+
   virtual void PopCurrentPosition();
   virtual void PopRegister(int register_index);
   virtual void PushBacktrack(Label* label);
@@ -85,7 +88,7 @@
   virtual void ReadStackPointerFromRegister(int reg);
   virtual void SetRegister(int register_index, int to);
   virtual void Succeed();
-  virtual void WriteCurrentPositionToRegister(int reg);
+  virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
   virtual void WriteStackPointerToRegister(int reg);
 
   template <typename T>
@@ -119,8 +122,12 @@
   static const int kRegExpConstantsSize = 256;
   // Only unroll loops up to this length.
   static const int kMaxInlineStringTests = 8;
-  // Special "character" marking end of input.
-  static const uint32_t kEndOfInput = ~0;
+
+  // Compares two-byte strings case insenstively.
+  static int CaseInsensitiveCompareUC16(uc16** buffer,
+                                        int byte_offset1,
+                                        int byte_offset2,
+                                        size_t byte_length);
 
   // The ebp-relative location of a regexp register.
   Operand register_location(int register_index);
@@ -135,10 +142,6 @@
   // is NULL, in which case it is a conditional Backtrack.
   void BranchOrBacktrack(Condition condition, Label* to);
 
-  // Read a character from input at the given offset from the current
-  // position.
-  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.
diff --git a/src/regexp-macro-assembler-irregexp.cc b/src/regexp-macro-assembler-irregexp.cc
index b821788..44fa33c 100644
--- a/src/regexp-macro-assembler-irregexp.cc
+++ b/src/regexp-macro-assembler-irregexp.cc
@@ -68,6 +68,7 @@
 
 
 void RegExpMacroAssemblerIrregexp::EmitOrLink(Label* l) {
+  if (l == NULL) l = &backtrack_;
   if (l->is_bound()) {
     Emit32(l->pos());
   } else {
@@ -95,11 +96,11 @@
 
 
 void RegExpMacroAssemblerIrregexp::WriteCurrentPositionToRegister(
-    int register_index) {
+    int register_index, int cp_offset) {
   ASSERT(register_index >= 0);
   Emit(BC_SET_REGISTER_TO_CP);
   Emit(register_index);
-  Emit32(0);  // Current position offset.
+  Emit32(cp_offset);  // Current position offset.
 }
 
 
@@ -187,11 +188,10 @@
 }
 
 
-void RegExpMacroAssemblerIrregexp::CheckCurrentPosition(
-  int register_index,
-  Label* on_equal) {
-  // TODO(erikcorry): Implement.
-  UNIMPLEMENTED();
+void RegExpMacroAssemblerIrregexp::CheckGreedyLoop(
+      Label* on_tos_equals_current_position) {
+  Emit(BC_CHECK_GREEDY);
+  EmitOrLink(on_tos_equals_current_position);
 }
 
 
@@ -203,6 +203,13 @@
 }
 
 
+void RegExpMacroAssemblerIrregexp::LoadCurrentCharacterUnchecked(
+      int cp_offset) {
+  Emit(BC_LOAD_CURRENT_CHAR_UNCHECKED);
+  Emit32(cp_offset);
+}
+
+
 void RegExpMacroAssemblerIrregexp::CheckCharacterLT(uc16 limit,
                                                     Label* on_less) {
   Emit(BC_CHECK_LT);
@@ -263,7 +270,7 @@
 
 
 void RegExpMacroAssemblerIrregexp::CheckNotBackReference(int start_reg,
-                                                     Label* on_not_equal) {
+                                                         Label* on_not_equal) {
   Emit(BC_CHECK_NOT_BACK_REF);
   Emit(start_reg);
   EmitOrLink(on_not_equal);
@@ -323,11 +330,19 @@
 void RegExpMacroAssemblerIrregexp::CheckCharacters(
   Vector<const uc16> str,
   int cp_offset,
-  Label* on_failure) {
+  Label* on_failure,
+  bool check_end_of_string) {
+  // It is vital that this loop is backwards due to the unchecked character
+  // load below.
   for (int i = str.length() - 1; i >= 0; i--) {
-    Emit(BC_LOAD_CURRENT_CHAR);
-    Emit32(cp_offset + i);
-    EmitOrLink(on_failure);
+    if (check_end_of_string && i == str.length() - 1) {
+      Emit(BC_LOAD_CURRENT_CHAR);
+      Emit32(cp_offset + i);
+      EmitOrLink(on_failure);
+    } else {
+      Emit(BC_LOAD_CURRENT_CHAR_UNCHECKED);
+      Emit32(cp_offset + i);
+    }
     Emit(BC_CHECK_NOT_CHAR);
     Emit16(str[i]);
     EmitOrLink(on_failure);
@@ -357,7 +372,9 @@
 }
 
 
-Handle<Object> RegExpMacroAssemblerIrregexp::GetCode() {
+Handle<Object> RegExpMacroAssemblerIrregexp::GetCode(Handle<String> source) {
+  Bind(&backtrack_);
+  Emit(BC_POP_BT);
   Handle<ByteArray> array = Factory::NewByteArray(length());
   Copy(array->GetDataStartAddress());
   return array;
diff --git a/src/regexp-macro-assembler-irregexp.h b/src/regexp-macro-assembler-irregexp.h
index 77d18e1..722e779 100644
--- a/src/regexp-macro-assembler-irregexp.h
+++ b/src/regexp-macro-assembler-irregexp.h
@@ -62,14 +62,16 @@
   virtual void PushRegister(int register_index);
   virtual void AdvanceRegister(int reg, int by);  // r[reg] += by.
   virtual void SetRegister(int register_index, int to);
-  virtual void WriteCurrentPositionToRegister(int reg);
+  virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
   virtual void ReadCurrentPositionFromRegister(int reg);
   virtual void WriteStackPointerToRegister(int reg);
   virtual void ReadStackPointerFromRegister(int reg);
   virtual void LoadCurrentCharacter(int cp_offset, Label* on_end_of_input);
+  virtual void LoadCurrentCharacterUnchecked(int cp_offset);
   virtual void CheckCharacterLT(uc16 limit, Label* on_less);
   virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
   virtual void CheckCharacter(uc16 c, Label* on_equal);
+  virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
   virtual void CheckNotAtStart(Label* on_not_at_start);
   virtual void CheckNotCharacter(uc16 c, Label* on_not_equal);
   virtual void CheckNotCharacterAfterOr(uc16 c, uc16 mask, Label* on_not_equal);
@@ -82,8 +84,8 @@
   virtual void CheckNotRegistersEqual(int reg1, int reg2, Label* on_not_equal);
   virtual void CheckCharacters(Vector<const uc16> str,
                                int cp_offset,
-                               Label* on_failure);
-  virtual void CheckCurrentPosition(int register_index, Label* on_equal);
+                               Label* on_failure,
+                               bool check_end_of_string);
   virtual void CheckBitmap(uc16 start, Label* bitmap, Label* on_zero);
   virtual void DispatchHalfNibbleMap(uc16 start,
                                      Label* half_nibble_map,
@@ -98,7 +100,7 @@
   virtual void IfRegisterGE(int register_index, int comparand, Label* if_ge);
 
   virtual IrregexpImplementation Implementation();
-  virtual Handle<Object> GetCode();
+  virtual Handle<Object> GetCode(Handle<String> source);
  private:
   void Expand();
   // Code and bitmap emission.
@@ -109,14 +111,13 @@
   int length();
   void Copy(Address a);
 
-
-
   // The buffer into which code and relocation info are generated.
   Vector<byte> buffer_;
   // The program counter.
   int pc_;
   // True if the assembler owns the buffer, false if buffer is external.
   bool own_buffer_;
+  Label backtrack_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(RegExpMacroAssemblerIrregexp);
 };
diff --git a/src/regexp-macro-assembler-tracer.cc b/src/regexp-macro-assembler-tracer.cc
index 80dff25..fc3629c 100644
--- a/src/regexp-macro-assembler-tracer.cc
+++ b/src/regexp-macro-assembler-tracer.cc
@@ -64,6 +64,12 @@
 }
 
 
+void RegExpMacroAssemblerTracer::CheckGreedyLoop(Label* label) {
+  PrintF(" CheckGreedyLoop(label[%08x]);\n\n", label);
+  assembler_->CheckGreedyLoop(label);
+}
+
+
 void RegExpMacroAssemblerTracer::PopCurrentPosition() {
   PrintF(" PopCurrentPosition();\n");
   assembler_->PopCurrentPosition();
@@ -130,9 +136,12 @@
 }
 
 
-void RegExpMacroAssemblerTracer::WriteCurrentPositionToRegister(int reg) {
-  PrintF(" WriteCurrentPositionToRegister(register=%d);\n", reg);
-  assembler_->WriteCurrentPositionToRegister(reg);
+void RegExpMacroAssemblerTracer::WriteCurrentPositionToRegister(int reg,
+                                                                int cp_offset) {
+  PrintF(" WriteCurrentPositionToRegister(register=%d,cp_offset=%d);\n",
+         reg,
+         cp_offset);
+  assembler_->WriteCurrentPositionToRegister(reg, cp_offset);
 }
 
 
@@ -156,12 +165,20 @@
 
 void RegExpMacroAssemblerTracer::LoadCurrentCharacter(int cp_offset,
                                                       Label* on_end_of_input) {
-  PrintF(" LoadCurrentCharacter(cp_offset=%d, label[%08x]);\n", cp_offset,
+  PrintF(" LoadCurrentCharacter(cp_offset=%d, label[%08x]);\n",
+         cp_offset,
          on_end_of_input);
   assembler_->LoadCurrentCharacter(cp_offset, on_end_of_input);
 }
 
 
+void RegExpMacroAssemblerTracer::LoadCurrentCharacterUnchecked(int cp_offset) {
+  PrintF(" LoadCurrentCharacterUnchecked(cp_offset=%d);\n",
+         cp_offset);
+  assembler_->LoadCurrentCharacterUnchecked(cp_offset);
+}
+
+
 void RegExpMacroAssemblerTracer::CheckCharacterLT(uc16 limit, Label* on_less) {
   PrintF(" CheckCharacterLT(c='u%04x', label[%08x]);\n", limit, on_less);
   assembler_->CheckCharacterLT(limit, on_less);
@@ -242,21 +259,15 @@
 
 void RegExpMacroAssemblerTracer::CheckCharacters(Vector<const uc16> str,
                                                  int cp_offset,
-                                                 Label* on_failure) {
-  PrintF(" CheckCharacters(str=\"");
+                                                 Label* on_failure,
+                                                 bool check_end_of_string) {
+  PrintF(" %s(str=\"",
+         check_end_of_string ? "CheckCharacters" : "CheckCharactersUnchecked");
   for (int i = 0; i < str.length(); i++) {
     PrintF("u%04x", str[i]);
   }
   PrintF("\", cp_offset=%d, label[%08x])\n", cp_offset, on_failure);
-  assembler_->CheckCharacters(str, cp_offset, on_failure);
-}
-
-
-void RegExpMacroAssemblerTracer::CheckCurrentPosition(int register_index,
-                                                      Label* on_equal) {
-  PrintF(" CheckCurrentPosition(register=%d, label[%08x]);\n", register_index,
-         on_equal);
-  assembler_->CheckCurrentPosition(register_index, on_equal);
+  assembler_->CheckCharacters(str, cp_offset, on_failure, check_end_of_string);
 }
 
 
@@ -334,9 +345,9 @@
 }
 
 
-Handle<Object> RegExpMacroAssemblerTracer::GetCode() {
-  PrintF(" GetCode();\n");
-  return assembler_->GetCode();
+Handle<Object> RegExpMacroAssemblerTracer::GetCode(Handle<String> source) {
+  PrintF(" GetCode(%s);\n", *(source->ToCString()));
+  return assembler_->GetCode(source);
 }
 
 }}  // namespace v8::internal
diff --git a/src/regexp-macro-assembler-tracer.h b/src/regexp-macro-assembler-tracer.h
index 3488082..88d4cc1 100644
--- a/src/regexp-macro-assembler-tracer.h
+++ b/src/regexp-macro-assembler-tracer.h
@@ -47,10 +47,9 @@
   virtual void CheckCharacters(
       Vector<const uc16> str,
       int cp_offset,
-      Label* on_failure);
-  virtual void CheckCurrentPosition(
-      int register_index,
-      Label* on_equal);
+      Label* on_failure,
+      bool check_end_of_string);
+  virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
   virtual void CheckNotAtStart(Label* on_not_at_start);
   virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
   virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
@@ -77,12 +76,13 @@
       const Vector<Label*>& destinations);
   virtual void EmitOrLink(Label* label);
   virtual void Fail();
-  virtual Handle<Object> GetCode();
+  virtual Handle<Object> GetCode(Handle<String> source);
   virtual void GoTo(Label* label);
   virtual void IfRegisterGE(int reg, int comparand, Label* if_ge);
   virtual void IfRegisterLT(int reg, int comparand, Label* if_lt);
   virtual IrregexpImplementation Implementation();
   virtual void LoadCurrentCharacter(int cp_offset, Label* on_end_of_input);
+  virtual void LoadCurrentCharacterUnchecked(int cp_offset);
   virtual void PopCurrentPosition();
   virtual void PopRegister(int register_index);
   virtual void PushBacktrack(Label* label);
@@ -92,7 +92,7 @@
   virtual void ReadStackPointerFromRegister(int reg);
   virtual void SetRegister(int register_index, int to);
   virtual void Succeed();
-  virtual void WriteCurrentPositionToRegister(int reg);
+  virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
   virtual void WriteStackPointerToRegister(int reg);
  private:
   RegExpMacroAssembler* assembler_;
diff --git a/src/regexp-macro-assembler.cc b/src/regexp-macro-assembler.cc
index 27bf9e2..34925f5 100644
--- a/src/regexp-macro-assembler.cc
+++ b/src/regexp-macro-assembler.cc
@@ -64,7 +64,7 @@
     current_byte_array_ = Factory::NewByteArray(byte_array_size_, TENURED);
     free_offset = 0;
   }
-  current_byte_array_free_offset_ = free_offset + size;
+  current_byte_array_free_offset_ = free_offset + byte_size;
   return ArraySlice(current_byte_array_, free_offset);
 }
 
diff --git a/src/regexp-macro-assembler.h b/src/regexp-macro-assembler.h
index 8cbd274..5ed1523 100644
--- a/src/regexp-macro-assembler.h
+++ b/src/regexp-macro-assembler.h
@@ -62,19 +62,17 @@
   virtual void CheckCharacterGT(uc16 limit, Label* on_greater) = 0;
   virtual void CheckCharacterLT(uc16 limit, Label* on_less) = 0;
   // Check the current character for a match with a literal string.  If we
-  // fail to match then goto the on_failure label.  End of input always
-  // matches.  If the label is NULL then we should pop a backtrack address off
-  // the stack abnd go to that.
+  // fail to match then goto the on_failure label.  If check_eos is set then
+  // the end of input always fails.  If check_eos is clear then it is the
+  // caller's responsibility to ensure that the end of string is not hit.
+  // If the label is NULL then we should pop a backtrack address off
+  // the stack and go to that.
   virtual void CheckCharacters(
       Vector<const uc16> str,
       int cp_offset,
-      Label* on_failure) = 0;
-  // Check the current input position against a register.  If the register is
-  // equal to the current position then go to the label.  If the label is NULL
-  // then backtrack instead.
-  virtual void CheckCurrentPosition(
-      int register_index,
-      Label* on_equal) = 0;
+      Label* on_failure,
+      bool check_eos) = 0;
+  virtual void CheckGreedyLoop(Label* on_tos_equals_current_position) = 0;
   virtual void CheckNotAtStart(Label* on_not_at_start) = 0;
   virtual void CheckNotBackReference(int start_reg, Label* on_no_match) = 0;
   virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
@@ -115,7 +113,7 @@
       const Vector<Label*>& destinations) = 0;
   virtual void EmitOrLink(Label* label) = 0;
   virtual void Fail() = 0;
-  virtual Handle<Object> GetCode() = 0;
+  virtual Handle<Object> GetCode(Handle<String> source) = 0;
   virtual void GoTo(Label* label) = 0;
   // Check whether a register is >= a given constant and go to a label if it
   // is.  Backtracks instead if the label is NULL.
@@ -125,6 +123,7 @@
   virtual void IfRegisterLT(int reg, int comparand, Label* if_lt) = 0;
   virtual IrregexpImplementation Implementation() = 0;
   virtual void LoadCurrentCharacter(int cp_offset, Label* on_end_of_input) = 0;
+  virtual void LoadCurrentCharacterUnchecked(int cp_offset) = 0;
   virtual void PopCurrentPosition() = 0;
   virtual void PopRegister(int register_index) = 0;
   virtual void PushBacktrack(Label* label) = 0;
@@ -134,7 +133,7 @@
   virtual void ReadStackPointerFromRegister(int reg) = 0;
   virtual void SetRegister(int register_index, int to) = 0;
   virtual void Succeed() = 0;
-  virtual void WriteCurrentPositionToRegister(int reg) = 0;
+  virtual void WriteCurrentPositionToRegister(int reg, int cp_offset) = 0;
   virtual void WriteStackPointerToRegister(int reg) = 0;
 
  private:
diff --git a/src/runtime.cc b/src/runtime.cc
index 749bee0..8c3d043 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -1733,13 +1733,19 @@
   ASSERT(args.length() == 2);
 
   // Fast cases for getting named properties of the receiver JSObject
-  // itself. The global proxy objects has to be excluded since
-  // LocalLookup on the global proxy object can return a valid result
-  // eventhough the global proxy object never has properties.  This is
-  // the case because the global proxy object forwards everything to
-  // its hidden prototype including local lookups.
+  // itself.
+  //
+  // The global proxy objects has to be excluded since LocalLookup on
+  // the global proxy object can return a valid result eventhough the
+  // global proxy object never has properties.  This is the case
+  // because the global proxy object forwards everything to its hidden
+  // prototype including local lookups.
+  //
+  // Additionally, we need to make sure that we do not cache results
+  // for objects that require access checks.
   if (args[0]->IsJSObject() &&
       !args[0]->IsJSGlobalProxy() &&
+      !args[0]->IsAccessCheckNeeded() &&
       args[1]->IsString()) {
     JSObject* receiver = JSObject::cast(args[0]);
     String* key = String::cast(args[1]);
@@ -4758,10 +4764,8 @@
 static Object* Runtime_CheckExecutionState(Arguments args) {
   ASSERT(args.length() >= 1);
   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
-  // Check that the break id is valid and that there is a valid frame
-  // where execution is broken.
-  if (break_id != Top::break_id() ||
-      Top::break_frame_id() == StackFrame::NO_ID) {
+  // Check that the break id is valid.
+  if (Top::break_id() == 0 || break_id != Top::break_id()) {
     return Top::Throw(Heap::illegal_execution_state_symbol());
   }
 
@@ -4780,6 +4784,10 @@
   // Count all frames which are relevant to debugging stack trace.
   int n = 0;
   StackFrame::Id id = Top::break_frame_id();
+  if (id == StackFrame::NO_ID) {
+    // If there is no JavaScript stack frame count is 0.
+    return Smi::FromInt(0);
+  }
   for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) n++;
   return Smi::FromInt(n);
 }
@@ -4821,6 +4829,10 @@
 
   // Find the relevant frame with the requested index.
   StackFrame::Id id = Top::break_frame_id();
+  if (id == StackFrame::NO_ID) {
+    // If there are no JavaScript stack frames return undefined.
+    return Heap::undefined_value();
+  }
   int count = 0;
   JavaScriptFrameIterator it(id);
   for (; !it.done(); it.Advance()) {
diff --git a/src/serialize.cc b/src/serialize.cc
index 359d627..4ecb2a5 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -470,6 +470,7 @@
 
   BUILTIN_LIST_C(DEF_ENTRY_C)
   BUILTIN_LIST_A(DEF_ENTRY_A)
+  BUILTIN_LIST_DEBUG_A(DEF_ENTRY_A)
 #undef DEF_ENTRY_C
 #undef DEF_ENTRY_A
 
diff --git a/src/string.js b/src/string.js
index 984d969..78606a6 100644
--- a/src/string.js
+++ b/src/string.js
@@ -198,9 +198,9 @@
   if (start < 0) return subject;
   var end = start + search.length;
 
-  var builder = new StringBuilder();
+  var builder = new ReplaceResultBuilder(subject);
   // prefix
-  builder.add(SubString(subject, 0, start));
+  builder.addSpecialSlice(0, start);
 
   // Compute the string to replace with.
   if (IS_FUNCTION(replace)) {
@@ -210,7 +210,7 @@
   }
 
   // suffix
-  builder.add(SubString(subject, end, subject.length));
+  builder.addSpecialSlice(end, subject.length);
 
   return builder.generate();
 }
@@ -234,18 +234,27 @@
   var length = matches.length;
 
   // Build the resulting string of subject slices and replacements.
-  var result = new StringBuilder();
+  var result = new ReplaceResultBuilder(subject);
   var previous = 0;
   // The caller of StringReplaceRegExp must ensure that replace is not a
   // function.
   replace = ToString(replace);
-  for (var i = 0; i < length; i++) {
-    var captures = matches[i];
-    result.add(SubString(subject, previous, captures[0]));
-    ExpandReplacement(replace, subject, captures, result);
-    previous = captures[1];  // continue after match
+  if (%StringIndexOf(replace, "$", 0) < 0) {
+    for (var i = 0; i < length; i++) {
+      var captures = matches[i];
+      result.addSpecialSlice(previous, captures[0]);
+      result.add(replace);
+      previous = captures[1];  // continue after match
+    }
+  } else {
+    for (var i = 0; i < length; i++) {
+      var captures = matches[i];
+      result.addSpecialSlice(previous, captures[0]);
+      ExpandReplacement(replace, subject, captures, result);
+      previous = captures[1];  // continue after match
+    }
   }
-  result.add(SubString(subject, previous, subject.length));
+  result.addSpecialSlice(previous, subject.length);
   return result.generate();
 };
 
@@ -272,15 +281,16 @@
       var peek = %StringCharCodeAt(string, position);
       if (peek == 36) {         // $$
         ++position;
+        builder.add('$');
       } else if (peek == 38) {  // $& - match
         ++position;
-        expansion = SubString(subject, captures[0], captures[1]);
+        builder.addSpecialSlice(captures[0], captures[1]);
       } else if (peek == 96) {  // $` - prefix
         ++position;
-        expansion = SubString(subject, 0, captures[0]);
+        builder.addSpecialSlice(0, captures[0]);
       } else if (peek == 39) {  // $' - suffix
         ++position;
-        expansion = SubString(subject, captures[1], subject.length);
+        builder.addSpecialSlice(captures[1], subject.length);
       } else if (peek >= 48 && peek <= 57) {  // $n, 0 <= n <= 9
         ++position;
         var n = peek - 48;
@@ -301,20 +311,21 @@
           }
         }
         if (0 < n && n < m) {
-          expansion = CaptureString(subject, captures, n);
-          if (IS_UNDEFINED(expansion)) expansion = "";
+          addCaptureString(builder, captures, n);
         } else {
           // Because of the captures range check in the parsing of two
           // digit capture references, we can only enter here when a
           // single digit capture reference is outside the range of
           // captures.
+          builder.add('$');
           --position;
         }
       }
+    } else {
+      builder.add('$');
     }
 
-    // Append the $ expansion and go the the next $ in the string.
-    builder.add(expansion);
+    // Go the the next $ in the string.
     next = %StringIndexOf(string, '$', position);
 
     // Return if there are no more $ characters in the string. If we
@@ -345,6 +356,19 @@
 };
 
 
+// Add the string of a given PCRE capture to the ReplaceResultBuilder
+function addCaptureString(builder, captures, index) {
+  // Scale the index.
+  var scaled = index << 1;
+  // Compute start and end.
+  var start = captures[scaled];
+  var end = captures[scaled + 1];
+  // If either start or end is missing return.
+  if (start < 0 || end < 0) return;
+  builder.addSpecialSlice(start, end);
+};
+
+
 // Helper function for replacing regular expressions with the result of a
 // function application in String.prototype.replace.  The function application
 // must be interleaved with the regexp matching (contrary to ECMA-262
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index f5f00ae..3daf357 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -861,7 +861,7 @@
 
 Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
   HandleScope scope;
-  Builtins::Generate_CallIC_DebugBreak(masm());
+  Debug::GenerateCallICDebugBreak(masm());
   Object* result = GetCodeWithFlags(flags);
   if (!result->IsFailure()) {
     Code* code = Code::cast(result);
diff --git a/src/top.cc b/src/top.cc
index 7e239ec..be8c39b 100644
--- a/src/top.cc
+++ b/src/top.cc
@@ -66,6 +66,9 @@
 
 void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
   v->VisitPointer(&(thread->pending_exception_));
+  v->VisitPointer(&(thread->pending_message_obj_));
+  v->VisitPointer(
+      bit_cast<Object**, Script**>(&(thread->pending_message_script_)));
   v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_)));
   v->VisitPointer(&(thread->scheduled_exception_));
 
@@ -99,6 +102,7 @@
   thread_local_.external_caught_exception_ = false;
   thread_local_.failed_access_check_callback_ = NULL;
   clear_pending_exception();
+  clear_pending_message();
   clear_scheduled_exception();
   thread_local_.save_context_ = NULL;
   thread_local_.catcher_ = NULL;
@@ -276,7 +280,15 @@
 // is on the top. Otherwise, it means the C try-catch handler is on the top.
 //
 void Top::RegisterTryCatchHandler(v8::TryCatch* that) {
-  that->js_handler_ = thread_local_.handler_;  // casted to void*
+  StackHandler* handler =
+    reinterpret_cast<StackHandler*>(thread_local_.handler_);
+
+  // Find the top-most try-catch handler.
+  while (handler != NULL && !handler->is_try_catch()) {
+    handler = handler->next();
+  }
+
+  that->js_handler_ = handler;  // casted to void*
   thread_local_.try_catch_handler_ = that;
 }
 
@@ -737,46 +749,31 @@
 
 
 bool Top::ShouldReportException(bool* is_caught_externally) {
+  // Find the top-most try-catch handler.
   StackHandler* handler =
       StackHandler::FromAddress(Top::handler(Top::GetCurrentThread()));
-
-  // Determine if we have an external exception handler and get the
-  // address of the external handler so we can compare the address to
-  // determine which one is closer to the top of the stack.
-  bool has_external_handler = (thread_local_.try_catch_handler_ != NULL);
-  v8::TryCatch* try_catch = thread_local_.try_catch_handler_;
-
-  // NOTE: The stack is assumed to grown towards lower addresses. If
-  // the handler is at a higher address than the external address it
-  // means that it is below it on the stack.
-
-  // Find the top-most try-catch handler.
   while (handler != NULL && !handler->is_try_catch()) {
     handler = handler->next();
   }
 
+  // Get the address of the external handler so we can compare the address to
+  // determine which one is closer to the top of the stack.
+  v8::TryCatch* try_catch = thread_local_.try_catch_handler_;
+
   // The exception has been externally caught if and only if there is
   // an external handler which is on top of the top-most try-catch
   // handler.
   //
   // See comments in RegisterTryCatchHandler for details.
-  *is_caught_externally = has_external_handler &&
+  *is_caught_externally = try_catch != NULL &&
       (handler == NULL || handler == try_catch->js_handler_);
 
-  // If we have a try-catch handler then the exception is caught in
-  // JavaScript code.
-  bool is_uncaught_by_js = (handler == NULL);
-
-  // If there is no external try-catch handler, we report the
-  // exception if it isn't caught by JavaScript code.
-  if (!has_external_handler) return is_uncaught_by_js;
-
-  if (is_uncaught_by_js || handler == try_catch->js_handler_) {
+  if (*is_caught_externally) {
     // Only report the exception if the external handler is verbose.
     return thread_local_.try_catch_handler_->is_verbose_;
   } else {
     // Report the exception if it isn't caught by JavaScript code.
-    return is_uncaught_by_js;
+    return handler == NULL;
   }
 }
 
@@ -791,8 +788,13 @@
 
   // Determine reporting and whether the exception is caught externally.
   bool is_caught_externally = false;
-  bool report_exception = (exception != Failure::OutOfMemoryException()) &&
-      ShouldReportException(&is_caught_externally);
+  bool is_out_of_memory = exception == Failure::OutOfMemoryException();
+  bool should_return_exception =  ShouldReportException(&is_caught_externally);
+  bool report_exception = !is_out_of_memory && should_return_exception;
+
+
+  // Notify debugger of exception.
+  Debugger::OnException(exception_handle, report_exception);
 
   // Generate the message.
   Handle<Object> message_obj;
@@ -812,38 +814,74 @@
         location, HandleVector<Object>(&exception_handle, 1), stack_trace);
   }
 
-  // If the exception is caught externally, we store it in the
-  // try/catch handler. The C code can find it later and process it if
-  // necessary.
-  thread_local_.catcher_ = NULL;
+  // Save the message for reporting if the the exception remains uncaught.
+  thread_local_.has_pending_message_ = report_exception;
+  thread_local_.pending_message_ = message;
+  if (!message_obj.is_null()) {
+    thread_local_.pending_message_obj_ = *message_obj;
+    if (location != NULL) {
+      thread_local_.pending_message_script_ = *location->script();
+      thread_local_.pending_message_start_pos_ = location->start_pos();
+      thread_local_.pending_message_end_pos_ = location->end_pos();
+    }
+  }
+
   if (is_caught_externally) {
     thread_local_.catcher_ = thread_local_.try_catch_handler_;
-    thread_local_.try_catch_handler_->exception_ =
-      reinterpret_cast<void*>(*exception_handle);
-    if (!message_obj.is_null()) {
-      thread_local_.try_catch_handler_->message_ =
-        reinterpret_cast<void*>(*message_obj);
-    }
   }
 
-  // Notify debugger of exception.
-  Debugger::OnException(exception_handle, report_exception);
-
-  if (report_exception) {
-    if (message != NULL) {
-      MessageHandler::ReportMessage(message);
-    } else if (!message_obj.is_null()) {
-      MessageHandler::ReportMessage(location, message_obj);
-    }
-  }
-
-  // NOTE: Notifying the debugger or reporting the exception may have caused
-  // new exceptions. For now, we just ignore that and set the pending exception
-  // to the original one.
+  // NOTE: Notifying the debugger or generating the message
+  // may have caused new exceptions. For now, we just ignore
+  // that and set the pending exception to the original one.
   set_pending_exception(*exception_handle);
 }
 
 
+void Top::ReportPendingMessages() {
+  ASSERT(has_pending_exception());
+  setup_external_caught();
+  // If the pending exception is OutOfMemoryException set out_of_memory in
+  // the global context.  Note: We have to mark the global context here
+  // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to
+  // set it.
+  HandleScope scope;
+  if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) {
+    context()->mark_out_of_memory();
+  } else {
+    Handle<Object> exception(pending_exception());
+    bool external_caught = thread_local_.external_caught_exception_;
+    thread_local_.external_caught_exception_ = false;
+    if (external_caught) {
+      thread_local_.try_catch_handler_->exception_ =
+        thread_local_.pending_exception_;
+      if (!thread_local_.pending_message_obj_->IsTheHole()) {
+        try_catch_handler()->message_ = thread_local_.pending_message_obj_;
+      }
+    }
+    if (thread_local_.has_pending_message_) {
+      thread_local_.has_pending_message_ = false;
+      if (thread_local_.pending_message_ != NULL) {
+        MessageHandler::ReportMessage(thread_local_.pending_message_);
+      } else if (!thread_local_.pending_message_obj_->IsTheHole()) {
+        Handle<Object> message_obj(thread_local_.pending_message_obj_);
+        if (thread_local_.pending_message_script_ != NULL) {
+          Handle<Script> script(thread_local_.pending_message_script_);
+          int start_pos = thread_local_.pending_message_start_pos_;
+          int end_pos = thread_local_.pending_message_end_pos_;
+          MessageLocation location(script, start_pos, end_pos);
+          MessageHandler::ReportMessage(&location, message_obj);
+        } else {
+          MessageHandler::ReportMessage(NULL, message_obj);
+        }
+      }
+    }
+    thread_local_.external_caught_exception_ = external_caught;
+    set_pending_exception(*exception);
+  }
+  clear_pending_message();
+}
+
+
 void Top::TraceException(bool flag) {
   FLAG_trace_exception = flag;
 }
diff --git a/src/top.h b/src/top.h
index 29d46b5..7fe735c 100644
--- a/src/top.h
+++ b/src/top.h
@@ -46,6 +46,12 @@
   // lookups.
   Context* context_;
   Object* pending_exception_;
+  bool has_pending_message_;
+  const char* pending_message_;
+  Object* pending_message_obj_;
+  Script* pending_message_script_;
+  int pending_message_start_pos_;
+  int pending_message_end_pos_;
   // Use a separate value for scheduled exceptions to preserve the
   // invariants that hold about pending_exception.  We may want to
   // unify them later.
@@ -120,6 +126,13 @@
   static bool has_pending_exception() {
     return !thread_local_.pending_exception_->IsTheHole();
   }
+  static void clear_pending_message() {
+    thread_local_.catcher_ = NULL;
+    thread_local_.has_pending_message_ = false;
+    thread_local_.pending_message_ = NULL;
+    thread_local_.pending_message_obj_ = Heap::the_hole_value();
+    thread_local_.pending_message_script_ = NULL;
+  }
   static v8::TryCatch* try_catch_handler() {
     return thread_local_.try_catch_handler_;
   }
@@ -146,6 +159,7 @@
 
   static void setup_external_caught() {
     thread_local_.external_caught_exception_ =
+        (!thread_local_.pending_exception_->IsTheHole()) &&
         (thread_local_.catcher_ != NULL) &&
         (Top::thread_local_.try_catch_handler_ == Top::thread_local_.catcher_);
   }
@@ -207,6 +221,7 @@
   // originally.
   static Failure* ReThrow(Object* exception, MessageLocation* location = NULL);
   static void ScheduleThrow(Object* exception);
+  static void ReportPendingMessages();
 
   // Promote a scheduled exception to pending. Asserts has_scheduled_exception.
   static Object* PromoteScheduledException();
diff --git a/src/utils.h b/src/utils.h
index 34478ba..4a47841 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -540,7 +540,8 @@
 #ifdef CAN_READ_UNALIGNED
   *reinterpret_cast<uint16_t*>(ptr) = value;
 #else
-  ptr[1] = value;
+  // Cast to avoid warning C4244 when compiling with Microsoft Visual C++.
+  ptr[1] = static_cast<byte>(value);
   ptr[0] = value >> 8;
 #endif
 }
diff --git a/src/zone.cc b/src/zone.cc
index cfa161a..c8f9c85 100644
--- a/src/zone.cc
+++ b/src/zone.cc
@@ -163,8 +163,17 @@
   // is to avoid excessive malloc() and free() overhead.
   Segment* head = Segment::head();
   int old_size = (head == NULL) ? 0 : head->size();
-  int new_size = sizeof(Segment) + kAlignment + size + (old_size << 1);
-  if (new_size < kMinimumSegmentSize) new_size = kMinimumSegmentSize;
+  static const int kSegmentOverhead = sizeof(Segment) + kAlignment;
+  int new_size = kSegmentOverhead + size + (old_size << 1);
+  if (new_size < kMinimumSegmentSize) {
+    new_size = kMinimumSegmentSize;
+  } else if (new_size > kMaximumSegmentSize) {
+    // Limit the size of new segments to avoid growing the segment size
+    // exponentially, thus putting pressure on contiguous virtual address space.
+    // All the while making sure to allocate a segment large enough to hold the
+    // requested size.
+    new_size = Max(kSegmentOverhead + size, kMaximumSegmentSize);
+  }
   Segment* segment = Segment::New(new_size);
   if (segment == NULL) V8::FatalProcessOutOfMemory("Zone");
 
diff --git a/src/zone.h b/src/zone.h
index 612819e..5a8b0fe 100644
--- a/src/zone.h
+++ b/src/zone.h
@@ -75,6 +75,9 @@
   // Never allocate segments smaller than this size in bytes.
   static const int kMinimumSegmentSize = 8 * KB;
 
+  // Never allocate segments larger than this size in bytes.
+  static const int kMaximumSegmentSize = 1 * MB;
+
   // Never keep segments larger than this size in bytes around.
   static const int kMaximumKeptSegmentSize = 64 * KB;