Reduced code size by using shorter instruction encoding when possible.

Added a --help option to the shell sample and to the d8 shell.

Added visual studio project files for building the ARM simulator.

Fixed a number of ARM simulator issues.

Fixed bug in out-of-memory handling on ARM.

Implemented shell support for passing arguments to a script from the command line.

Fixed bug in date code that made certain date functions return -0 instead of 0 for dates before the epoch.

Restricted applications of eval so it can only be used in the context of the associated global object.

Treat byte-order marks as whitespace characters.


git-svn-id: http://v8.googlecode.com/svn/trunk@768 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 1b8bdc4..e44ae59 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2008-11-17: Version 0.4.4
+
+        Reduced code size by using shorter instruction encoding when
+        possible.
+
+        Added a --help option to the shell sample and to the d8 shell.
+
+        Added visual studio project files for building the ARM simulator.
+
+        Fixed a number of ARM simulator issues.
+
+        Fixed bug in out-of-memory handling on ARM.
+
+        Implemented shell support for passing arguments to a script from
+        the command line.
+
+        Fixed bug in date code that made certain date functions return -0
+        instead of 0 for dates before the epoch.
+
+        Restricted applications of eval so it can only be used in the
+        context of the associated global object.
+
+        Treat byte-order marks as whitespace characters.
+        
+        
 2008-11-04: Version 0.4.3
 
         Added support for API accessors that prohibit overwriting by
diff --git a/SConstruct b/SConstruct
index c1a6ec2..9dd9268 100644
--- a/SConstruct
+++ b/SConstruct
@@ -106,7 +106,10 @@
       'CPPDEFINES':   ['BUILDING_V8_SHARED']
     },
     'arch:arm': {
-      'CPPDEFINES':   ['ARM']
+      'CPPDEFINES':   ['ARM'],
+      # /wd4996 is to silence the warning about sscanf
+      # used by the arm simulator.
+      'WARNINGFLAGS': ['/wd4996']
     },
     'disassembler:on': {
       'CPPDEFINES':   ['ENABLE_DISASSEMBLER']
diff --git a/include/v8-debug.h b/include/v8-debug.h
index f537d7d..c12c086 100644
--- a/include/v8-debug.h
+++ b/include/v8-debug.h
@@ -82,8 +82,8 @@
 /**
  * Debug event callback function.
  *
- * \param event the debug event from which occoured (from the DebugEvent
- *              enumeration)
+ * \param event the type of the debug event that triggered the callback
+ *   (enum DebugEvent)
  * \param exec_state execution state (JavaScript object)
  * \param event_data event specific data (JavaScript object)
  * \param data value passed by the user to AddDebugEventListener
@@ -122,9 +122,6 @@
   // Remove a JavaScript debug event listener.
   static void RemoveDebugEventListener(v8::Handle<v8::Function> that);
 
-  // Generate a stack dump.
-  static void StackDump();
-
   // Break execution of JavaScript.
   static void DebugBreak();
 
diff --git a/include/v8.h b/include/v8.h
index ec51ce6..c99dc5a 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -2052,6 +2052,7 @@
   void* message_;
   bool is_verbose_;
   bool capture_message_;
+  void* js_handler_;
 };
 
 
diff --git a/samples/shell.cc b/samples/shell.cc
index 0209410..39236a9 100644
--- a/samples/shell.cc
+++ b/samples/shell.cc
@@ -72,7 +72,7 @@
       // alone JavaScript engines.
       continue;
     } else if (strncmp(str, "--", 2) == 0) {
-      printf("Warning: unknown flag %s.\n", str);
+      printf("Warning: unknown flag %s.\nTry --help for options\n", str);
     } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
       // Execute argument given to -e option directly
       v8::HandleScope handle_scope;
diff --git a/src/api.cc b/src/api.cc
index ba204ce..9fd5fb3 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1081,7 +1081,8 @@
       exception_(i::Heap::the_hole_value()),
       message_(i::Smi::FromInt(0)),
       is_verbose_(false),
-      capture_message_(true) {
+      capture_message_(true),
+      js_handler_(NULL) {
   i::Top::RegisterTryCatchHandler(this);
 }
 
@@ -2202,7 +2203,7 @@
 
 
 const char* v8::V8::GetVersion() {
-  return "0.4.3.1";
+  return "0.4.4";
 }
 
 
diff --git a/src/assembler-ia32.cc b/src/assembler-ia32.cc
index fbe63de..264ef42 100644
--- a/src/assembler-ia32.cc
+++ b/src/assembler-ia32.cc
@@ -597,6 +597,14 @@
 }
 
 
+void Assembler::mov(Register dst, const Immediate& x) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xB8 | dst.code());
+  emit(x);
+}
+
+
 void Assembler::mov(Register dst, Handle<Object> handle) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
@@ -613,6 +621,14 @@
 }
 
 
+void Assembler::mov(Register dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x89);
+  EMIT(0xC0 | src.code() << 3 | dst.code());
+}
+
+
 void Assembler::mov(const Operand& dst, const Immediate& x) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
@@ -781,7 +797,7 @@
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x21);
-  emit_operand(dst, src);
+  emit_operand(src, dst);
 }
 
 
@@ -949,7 +965,7 @@
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x09);
-  emit_operand(dst, src);
+  emit_operand(src, dst);
 }
 
 
@@ -1077,7 +1093,7 @@
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x29);
-  emit_operand(dst, src);
+  emit_operand(src, dst);
 }
 
 
@@ -2017,18 +2033,6 @@
 }
 
 
-void Assembler::emit_operand(const Operand& adr, Register reg) {
-  adr.set_reg(reg);
-  memmove(pc_, adr.buf_, adr.len_);
-  pc_ += adr.len_;
-  if (adr.len_ >= sizeof(int32_t) && adr.rmode_ != RelocInfo::NONE) {
-    pc_ -= sizeof(int32_t);  // pc_ must be *at* disp32
-    RecordRelocInfo(adr.rmode_);
-    pc_ += sizeof(int32_t);
-  }
-}
-
-
 void Assembler::emit_farith(int b1, int b2, int i) {
   ASSERT(is_uint8(b1) && is_uint8(b2));  // wrong opcode
   ASSERT(0 <= i &&  i < 8);  // illegal stack offset
diff --git a/src/assembler-ia32.h b/src/assembler-ia32.h
index 8413104..9647446 100644
--- a/src/assembler-ia32.h
+++ b/src/assembler-ia32.h
@@ -453,8 +453,10 @@
   void mov_w(const Operand& dst, Register src);
 
   void mov(Register dst, int32_t imm32);
+  void mov(Register dst, const Immediate& x);
   void mov(Register dst, Handle<Object> handle);
   void mov(Register dst, const Operand& src);
+  void mov(Register dst, Register src);
   void mov(const Operand& dst, const Immediate& x);
   void mov(const Operand& dst, Handle<Object> handle);
   void mov(const Operand& dst, Register src);
@@ -757,7 +759,6 @@
   void emit_arith(int sel, Operand dst, const Immediate& x);
 
   void emit_operand(Register reg, const Operand& adr);
-  void emit_operand(const Operand& adr, Register reg);
 
   void emit_farith(int b1, int b2, int i);
 
diff --git a/src/ast.h b/src/ast.h
index 4344535..b383f76 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1125,6 +1125,7 @@
         start_position_(start_position),
         end_position_(end_position),
         is_expression_(is_expression),
+        loop_nesting_(0),
         function_token_position_(RelocInfo::kNoPosition) {
   }
 
@@ -1149,6 +1150,9 @@
 
   bool AllowsLazyCompilation();
 
+  bool loop_nesting() const { return loop_nesting_; }
+  void set_loop_nesting(int nesting) { loop_nesting_ = nesting; }
+
  private:
   Handle<String> name_;
   Scope* scope_;
@@ -1160,6 +1164,7 @@
   int start_position_;
   int end_position_;
   bool is_expression_;
+  int loop_nesting_;
   int function_token_position_;
 };
 
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index d08baa1..ce25d00 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -205,11 +205,20 @@
     Code* code = Code::cast(code_[i]);
     Address pc = code->instruction_start() + pc_[i];
     bool is_pc_relative = Bootstrapper::FixupFlagsIsPCRelative::decode(flags);
-    if (is_pc_relative) {
-      Assembler::set_target_address_at(pc, f->code()->instruction_start());
+    bool use_code_object = Bootstrapper::FixupFlagsUseCodeObject::decode(flags);
+
+    if (use_code_object) {
+      if (is_pc_relative) {
+        Assembler::set_target_address_at(
+            pc, reinterpret_cast<Address>(f->code()));
+      } else {
+        *reinterpret_cast<Object**>(pc) = f->code();
+      }
     } else {
-      *reinterpret_cast<Object**>(pc) = f->code();
+      ASSERT(is_pc_relative);
+      Assembler::set_target_address_at(pc, f->code()->instruction_start());
     }
+
     LOG(StringEvent("resolved", name));
   }
   Clear();
diff --git a/src/bootstrapper.h b/src/bootstrapper.h
index 0b0784e..908217d 100644
--- a/src/bootstrapper.h
+++ b/src/bootstrapper.h
@@ -66,7 +66,8 @@
 
   // Encoding/decoding support for fixup flags.
   class FixupFlagsIsPCRelative: public BitField<bool, 0, 1> {};
-  class FixupFlagsArgumentsCount: public BitField<uint32_t, 1, 32-1> {};
+  class FixupFlagsUseCodeObject: public BitField<bool, 1, 1> {};
+  class FixupFlagsArgumentsCount: public BitField<uint32_t, 2, 32-2> {};
 };
 
 }}  // namespace v8::internal
diff --git a/src/builtins-ia32.cc b/src/builtins-ia32.cc
index 0de381c..55e10f3 100644
--- a/src/builtins-ia32.cc
+++ b/src/builtins-ia32.cc
@@ -129,7 +129,7 @@
     // ebx: JSObject
     // edi: start of next object
     __ mov(Operand(ebx, JSObject::kMapOffset), eax);
-    __ mov(Operand(ecx), Factory::empty_fixed_array());
+    __ mov(ecx, Factory::empty_fixed_array());
     __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx);
     __ mov(Operand(ebx, JSObject::kElementsOffset), ecx);
     // Set extra fields in the newly allocated object.
@@ -137,7 +137,7 @@
     // ebx: JSObject
     // edi: start of next object
     { Label loop, entry;
-      __ mov(Operand(edx), Factory::undefined_value());
+      __ mov(edx, Factory::undefined_value());
       __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
       __ jmp(&entry);
       __ bind(&loop);
@@ -198,7 +198,7 @@
     // edi: FixedArray
     // ecx: start of next object
     { Label loop, entry;
-      __ mov(Operand(edx), Factory::undefined_value());
+      __ mov(edx, Factory::undefined_value());
       __ lea(eax, Operand(edi, FixedArray::kHeaderSize));
       __ jmp(&entry);
       __ bind(&loop);
@@ -440,7 +440,7 @@
     __ push(edi);  // save edi across the call
     __ push(ebx);
     __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
-    __ mov(Operand(ebx), eax);
+    __ mov(ebx, eax);
     __ pop(edi);  // restore edi after the call
 
     // Get the arguments count and untag it.
@@ -657,7 +657,7 @@
   // arguments and the receiver.
   ASSERT(kSmiTagSize == 1);
   __ lea(ecx, Operand(eax, eax, times_1, kSmiTag));
-  __ push(Operand(ecx));
+  __ push(ecx);
 }
 
 
@@ -778,7 +778,7 @@
   __ RecordComment("// Calling from debug break to runtime - come in - over");
 #endif
   __ Set(eax, Immediate(0));  // no arguments
-  __ mov(Operand(ebx), Immediate(ExternalReference::debug_break()));
+  __ mov(ebx, Immediate(ExternalReference::debug_break()));
 
   CEntryDebugBreakStub ceb;
   __ CallStub(&ceb);
diff --git a/src/codegen-arm.cc b/src/codegen-arm.cc
index 4c2f465..e5120ae 100644
--- a/src/codegen-arm.cc
+++ b/src/codegen-arm.cc
@@ -35,6 +35,84 @@
 
 namespace v8 { namespace internal {
 
+#define __ masm_->
+
+// -------------------------------------------------------------------------
+// VirtualFrame implementation.
+
+VirtualFrame::VirtualFrame(CodeGenerator* cgen) {
+  ASSERT(cgen->scope() != NULL);
+
+  masm_ = cgen->masm();
+  frame_local_count_ = cgen->scope()->num_stack_slots();
+  parameter_count_ = cgen->scope()->num_parameters();
+}
+
+
+void VirtualFrame::Enter() {
+  Comment cmnt(masm_, "[ Enter JS frame");
+#ifdef DEBUG
+  { Label done, fail;
+    __ tst(r1, Operand(kSmiTagMask));
+    __ b(eq, &fail);
+    __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+    __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+    __ cmp(r2, Operand(JS_FUNCTION_TYPE));
+    __ b(eq, &done);
+    __ bind(&fail);
+    __ stop("CodeGenerator::EnterJSFrame - r1 not a function");
+    __ bind(&done);
+  }
+#endif  // DEBUG
+
+  __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
+  // Adjust FP to point to saved FP.
+  __ add(fp, sp, Operand(2 * kPointerSize));
+}
+
+
+void VirtualFrame::Exit() {
+  Comment cmnt(masm_, "[ Exit JS frame");
+  // Drop the execution stack down to the frame pointer and restore the caller
+  // frame pointer and return address.
+  __ mov(sp, fp);
+  __ ldm(ia_w, sp, fp.bit() | lr.bit());
+}
+
+
+void VirtualFrame::AllocateLocals() {
+  if (frame_local_count_ > 0) {
+    Comment cmnt(masm_, "[ Allocate space for locals");
+      // Initialize stack slots with 'undefined' value.
+    __ mov(ip, Operand(Factory::undefined_value()));
+    for (int i = 0; i < frame_local_count_; i++) {
+      __ push(ip);
+    }
+  }
+}
+
+
+void VirtualFrame::Drop(int count) {
+  ASSERT(count >= 0);
+  if (count > 0) {
+    __ add(sp, sp, Operand(count * kPointerSize));
+  }
+}
+
+
+void VirtualFrame::Pop() { Drop(1); }
+
+
+void VirtualFrame::Pop(Register reg) {
+  __ pop(reg);
+}
+
+
+void VirtualFrame::Push(Register reg) {
+  __ push(reg);
+}
+
+
 // -------------------------------------------------------------------------
 // CodeGenState implementation.
 
@@ -67,11 +145,9 @@
 }
 
 
-// -----------------------------------------------------------------------------
+// -------------------------------------------------------------------------
 // CodeGenerator implementation
 
-#define __ masm_->
-
 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script,
                              bool is_eval)
     : is_eval_(is_eval),
@@ -79,6 +155,7 @@
       deferred_(8),
       masm_(new MacroAssembler(NULL, buffer_size)),
       scope_(NULL),
+      frame_(NULL),
       cc_reg_(al),
       state_(NULL),
       break_stack_height_(0) {
@@ -86,7 +163,6 @@
 
 
 // Calling conventions:
-
 // r0: the number of arguments
 // fp: frame pointer
 // sp: stack pointer
@@ -94,13 +170,17 @@
 // cp: callee's context
 
 void CodeGenerator::GenCode(FunctionLiteral* fun) {
-  Scope* scope = fun->scope();
   ZoneList<Statement*>* body = fun->body();
 
   // Initialize state.
-  { CodeGenState state(this);
-    scope_ = scope;
-    cc_reg_ = al;
+  ASSERT(scope_ == NULL);
+  scope_ = fun->scope();
+  ASSERT(frame_ == NULL);
+  VirtualFrame virtual_frame(this);
+  frame_ = &virtual_frame;
+  cc_reg_ = al;
+  {
+    CodeGenState state(this);
 
     // Entry
     // stack: function, receiver, arguments, return address
@@ -110,9 +190,7 @@
     // pp: caller's parameter pointer
     // cp: callee's context
 
-    { Comment cmnt(masm_, "[ enter JS frame");
-      EnterJSFrame();
-    }
+    frame_->Enter();
     // tos: code slot
 #ifdef DEBUG
     if (strlen(FLAG_stop_at) > 0 &&
@@ -122,20 +200,13 @@
 #endif
 
     // Allocate space for locals and initialize them.
-    if (scope->num_stack_slots() > 0) {
-      Comment cmnt(masm_, "[ allocate space for locals");
-      // Initialize stack slots with 'undefined' value.
-      __ mov(ip, Operand(Factory::undefined_value()));
-      for (int i = 0; i < scope->num_stack_slots(); i++) {
-        __ push(ip);
-      }
-    }
+    frame_->AllocateLocals();
 
-    if (scope->num_heap_slots() > 0) {
+    if (scope_->num_heap_slots() > 0) {
       // Allocate local context.
       // Get outer context and create a new context based on it.
-      __ ldr(r0, FunctionOperand());
-      __ push(r0);
+      __ ldr(r0, frame_->Function());
+      frame_->Push(r0);
       __ CallRuntime(Runtime::kNewContext, 1);  // r0 holds the result
 
       if (kDebug) {
@@ -146,10 +217,10 @@
         __ bind(&verified_true);
       }
       // Update context local.
-      __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+      __ str(cp, frame_->Context());
     }
 
-    // TODO(1241774): Improve this code!!!
+    // TODO(1241774): Improve this code:
     // 1) only needed if we have a context
     // 2) no need to recompute context ptr every single time
     // 3) don't copy parameter operand code from SlotOperand!
@@ -164,12 +235,12 @@
       // order: such a parameter is copied repeatedly into the same
       // context location and thus the last value is what is seen inside
       // the function.
-      for (int i = 0; i < scope->num_parameters(); i++) {
-        Variable* par = scope->parameter(i);
+      for (int i = 0; i < scope_->num_parameters(); i++) {
+        Variable* par = scope_->parameter(i);
         Slot* slot = par->slot();
         if (slot != NULL && slot->type() == Slot::CONTEXT) {
-          ASSERT(!scope->is_global_scope());  // no parameters in global scope
-          __ ldr(r1, ParameterOperand(i));
+          ASSERT(!scope_->is_global_scope());  // no parameters in global scope
+          __ ldr(r1, frame_->Parameter(i));
           // Loads r2 with context; used below in RecordWrite.
           __ str(r1, SlotOperand(slot, r2));
           // Load the offset into r3.
@@ -181,59 +252,55 @@
       }
     }
 
-    // Store the arguments object.
-    // This must happen after context initialization because
-    // the arguments array may be stored in the context!
-    if (scope->arguments() != NULL) {
-      ASSERT(scope->arguments_shadow() != NULL);
+    // Store the arguments object.  This must happen after context
+    // initialization because the arguments object may be stored in the
+    // context.
+    if (scope_->arguments() != NULL) {
+      ASSERT(scope_->arguments_shadow() != NULL);
       Comment cmnt(masm_, "[ allocate arguments object");
-      { Reference shadow_ref(this, scope->arguments_shadow());
-        { Reference arguments_ref(this, scope->arguments());
+      { Reference shadow_ref(this, scope_->arguments_shadow());
+        { Reference arguments_ref(this, scope_->arguments());
           ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
-          __ ldr(r2, FunctionOperand());
+          __ ldr(r2, frame_->Function());
           // The receiver is below the arguments, the return address,
           // and the frame pointer on the stack.
-          const int kReceiverDisplacement = 2 + scope->num_parameters();
+          const int kReceiverDisplacement = 2 + scope_->num_parameters();
           __ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize));
-          __ mov(r0, Operand(Smi::FromInt(scope->num_parameters())));
+          __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
           __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit());
           __ CallStub(&stub);
-          __ push(r0);
+          frame_->Push(r0);
           arguments_ref.SetValue(NOT_CONST_INIT);
         }
         shadow_ref.SetValue(NOT_CONST_INIT);
       }
-      __ pop(r0);  // Value is no longer needed.
+      frame_->Pop();  // Value is no longer needed.
     }
 
-    // Generate code to 'execute' declarations and initialize
-    // functions (source elements). In case of an illegal
-    // redeclaration we need to handle that instead of processing the
-    // declarations.
-    if (scope->HasIllegalRedeclaration()) {
+    // Generate code to 'execute' declarations and initialize functions
+    // (source elements). In case of an illegal redeclaration we need to
+    // handle that instead of processing the declarations.
+    if (scope_->HasIllegalRedeclaration()) {
       Comment cmnt(masm_, "[ illegal redeclarations");
-      scope->VisitIllegalRedeclaration(this);
+      scope_->VisitIllegalRedeclaration(this);
     } else {
       Comment cmnt(masm_, "[ declarations");
-      // ProcessDeclarations calls DeclareGlobals indirectly
-      ProcessDeclarations(scope->declarations());
-
-      // Bail out if a stack-overflow exception occurred when
-      // processing declarations.
+      ProcessDeclarations(scope_->declarations());
+      // Bail out if a stack-overflow exception occurred when processing
+      // declarations.
       if (HasStackOverflow()) return;
     }
 
     if (FLAG_trace) {
-      // Push a valid value as the parameter. The runtime call only uses
-      // it as the return value to indicate non-failure.
       __ CallRuntime(Runtime::kTraceEnter, 0);
+      // Ignore the return value.
     }
     CheckStack();
 
     // Compile the body of the function in a vanilla state. Don't
     // bother compiling all the code if the scope has an illegal
     // redeclaration.
-    if (!scope->HasIllegalRedeclaration()) {
+    if (!scope_->HasIllegalRedeclaration()) {
       Comment cmnt(masm_, "[ function body");
 #ifdef DEBUG
       bool is_builtin = Bootstrapper::IsActive();
@@ -241,6 +308,7 @@
           is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
       if (should_trace) {
         __ CallRuntime(Runtime::kDebugTrace, 0);
+        // Ignore the return value.
       }
 #endif
       VisitStatements(body);
@@ -259,19 +327,20 @@
   if (FLAG_trace) {
     // Push the return value on the stack as the parameter.
     // Runtime::TraceExit returns the parameter as it is.
-    __ push(r0);
+    frame_->Push(r0);
     __ CallRuntime(Runtime::kTraceExit, 1);
   }
 
   // Tear down the frame which will restore the caller's frame pointer and the
   // link register.
-  ExitJSFrame();
+  frame_->Exit();
 
   __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize));
   __ mov(pc, lr);
 
   // Code generation state must be reset.
   scope_ = NULL;
+  frame_ = NULL;
   ASSERT(!has_cc());
   ASSERT(state_ == NULL);
 }
@@ -290,13 +359,10 @@
   int index = slot->index();
   switch (slot->type()) {
     case Slot::PARAMETER:
-      return ParameterOperand(index);
+      return frame_->Parameter(index);
 
-    case Slot::LOCAL: {
-      ASSERT(0 <= index && index < scope()->num_stack_slots());
-      const int kLocalOffset = JavaScriptFrameConstants::kLocal0Offset;
-      return MemOperand(fp, kLocalOffset - index * kPointerSize);
-    }
+    case Slot::LOCAL:
+      return frame_->Local(index);
 
     case Slot::CONTEXT: {
       // Follow the context chain if necessary.
@@ -331,16 +397,17 @@
 }
 
 
-// Loads a value on the stack. If it is a boolean value, the result may have
-// been (partially) translated into branches, or it may have set the condition
-// code register. If force_cc is set, the value is forced to set the condition
-// code register and no value is pushed. If the condition code register was set,
-// has_cc() is true and cc_reg_ contains the condition to test for 'true'.
+// Loads a value on TOS. If it is a boolean value, the result may have been
+// (partially) translated into branches, or it may have set the condition
+// code register. If force_cc is set, the value is forced to set the
+// condition code register and no value is pushed. If the condition code
+// register was set, has_cc() is true and cc_reg_ contains the condition to
+// test for 'true'.
 void CodeGenerator::LoadCondition(Expression* x,
-                                     TypeofState typeof_state,
-                                     Label* true_target,
-                                     Label* false_target,
-                                     bool force_cc) {
+                                  TypeofState typeof_state,
+                                  Label* true_target,
+                                  Label* false_target,
+                                  bool force_cc) {
   ASSERT(!has_cc());
 
   { CodeGenState new_state(this, typeof_state, true_target, false_target);
@@ -348,6 +415,13 @@
   }
   if (force_cc && !has_cc()) {
     // Convert the TOS value to a boolean in the condition code register.
+    // Visiting an expression may possibly choose neither (a) to leave a
+    // value in the condition code register nor (b) to leave a value in TOS
+    // (eg, by compiling to only jumps to the targets).  In that case the
+    // code generated by ToBoolean is wrong because it assumes the value of
+    // the expression in TOS.  So long as there is always a value in TOS or
+    // the condition code register when control falls through to here (there
+    // is), the code generated by ToBoolean is dead and therefore safe.
     ToBoolean(true_target, false_target);
   }
   ASSERT(has_cc() || !force_cc);
@@ -364,11 +438,11 @@
     Label loaded, materialize_true;
     __ b(cc_reg_, &materialize_true);
     __ mov(r0, Operand(Factory::false_value()));
-    __ push(r0);
+    frame_->Push(r0);
     __ b(&loaded);
     __ bind(&materialize_true);
     __ mov(r0, Operand(Factory::true_value()));
-    __ push(r0);
+    frame_->Push(r0);
     __ bind(&loaded);
     cc_reg_ = al;
   }
@@ -384,7 +458,7 @@
     if (true_target.is_linked()) {
       __ bind(&true_target);
       __ mov(r0, Operand(Factory::true_value()));
-      __ push(r0);
+      frame_->Push(r0);
     }
     // if both "true" and "false" need to be reincarnated,
     // jump across code for "false"
@@ -394,7 +468,7 @@
     if (false_target.is_linked()) {
       __ bind(&false_target);
       __ mov(r0, Operand(Factory::false_value()));
-      __ push(r0);
+      frame_->Push(r0);
     }
     // everything is loaded at this point
     __ bind(&loaded);
@@ -405,14 +479,15 @@
 
 void CodeGenerator::LoadGlobal() {
   __ ldr(r0, GlobalObject());
-  __ push(r0);
+  frame_->Push(r0);
 }
 
 
-void CodeGenerator::LoadGlobalReceiver(Register s) {
-  __ ldr(s, ContextOperand(cp, Context::GLOBAL_INDEX));
-  __ ldr(s, FieldMemOperand(s, GlobalObject::kGlobalReceiverOffset));
-  __ push(s);
+void CodeGenerator::LoadGlobalReceiver(Register scratch) {
+  __ ldr(scratch, ContextOperand(cp, Context::GLOBAL_INDEX));
+  __ ldr(scratch,
+         FieldMemOperand(scratch, GlobalObject::kGlobalReceiverOffset));
+  frame_->Push(scratch);
 }
 
 
@@ -450,7 +525,6 @@
 
 void CodeGenerator::LoadReference(Reference* ref) {
   Comment cmnt(masm_, "[ LoadReference");
-
   Expression* e = ref->expression();
   Property* property = e->AsProperty();
   Variable* var = e->AsVariableProxy()->AsVariable();
@@ -492,15 +566,13 @@
 
 
 void CodeGenerator::UnloadReference(Reference* ref) {
+  // Pop a reference from the stack while preserving TOS.
   Comment cmnt(masm_, "[ UnloadReference");
-
   int size = ref->size();
-  if (size <= 0) {
-    // Do nothing. No popping is necessary.
-  } else {
-    __ pop(r0);
-    __ add(sp, sp, Operand(size * kPointerSize));
-    __ push(r0);
+  if (size > 0) {
+    frame_->Pop(r0);
+    frame_->Drop(size);
+    frame_->Push(r0);
   }
 }
 
@@ -509,10 +581,10 @@
 // register to a boolean in the condition code register. The code
 // may jump to 'false_target' in case the register converts to 'false'.
 void CodeGenerator::ToBoolean(Label* true_target,
-                                 Label* false_target) {
+                              Label* false_target) {
   // Note: The generated code snippet does not change stack variables.
   //       Only the condition code should be set.
-  __ pop(r0);
+  frame_->Pop(r0);
 
   // Fast case checks
 
@@ -535,10 +607,9 @@
   __ b(eq, true_target);
 
   // Slow case: call the runtime.
-  __ push(r0);
+  frame_->Push(r0);
   __ CallRuntime(Runtime::kToBool, 1);
-
-  // Convert result (r0) to condition code
+  // Convert the result (r0) to a condition code.
   __ cmp(r0, Operand(Factory::false_value()));
 
   cc_reg_ = ne;
@@ -639,8 +710,8 @@
     case Token::SHL:
     case Token::SHR:
     case Token::SAR: {
-      __ pop(r0);  // r0 : y
-      __ pop(r1);  // r1 : x
+      frame_->Pop(r0);  // r0 : y
+      frame_->Pop(r1);  // r1 : x
       GenericBinaryOpStub stub(op);
       __ CallStub(&stub);
       break;
@@ -659,9 +730,9 @@
     }
 
     case Token::COMMA:
-      __ pop(r0);
+      frame_->Pop(r0);
       // simply discard left value
-      __ pop();
+      frame_->Pop();
       break;
 
     default:
@@ -749,8 +820,8 @@
 
 
 void CodeGenerator::SmiOperation(Token::Value op,
-                                    Handle<Object> value,
-                                    bool reversed) {
+                                 Handle<Object> value,
+                                 bool reversed) {
   // NOTE: This is an attempt to inline (a bit) more of the code for
   // some possible smi operations (like + and -) when (at least) one
   // of the operands is a literal smi. With this optimization, the
@@ -763,7 +834,7 @@
   int int_value = Smi::cast(*value)->value();
 
   Label exit;
-  __ pop(r0);
+  frame_->Pop(r0);
 
   switch (op) {
     case Token::ADD: {
@@ -816,8 +887,8 @@
     case Token::SAR: {
       if (reversed) {
         __ mov(ip, Operand(value));
-        __ push(ip);
-        __ push(r0);
+        frame_->Push(ip);
+        frame_->Push(r0);
         GenericBinaryOperation(op);
 
       } else {
@@ -867,13 +938,13 @@
 
     default:
       if (!reversed) {
-        __ push(r0);
+        frame_->Push(r0);
         __ mov(r0, Operand(value));
-        __ push(r0);
+        frame_->Push(r0);
       } else {
         __ mov(ip, Operand(value));
-        __ push(ip);
-        __ push(r0);
+        frame_->Push(ip);
+        frame_->Push(r0);
       }
       GenericBinaryOperation(op);
       break;
@@ -895,18 +966,18 @@
   // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
   if (cc == gt || cc == le) {
     cc = ReverseCondition(cc);
-    __ pop(r1);
-    __ pop(r0);
+    frame_->Pop(r1);
+    frame_->Pop(r0);
   } else {
-    __ pop(r0);
-    __ pop(r1);
+    frame_->Pop(r0);
+    frame_->Pop(r1);
   }
   __ orr(r2, r0, Operand(r1));
   __ tst(r2, Operand(kSmiTagMask));
   __ b(eq, &smi);
 
   // Perform non-smi comparison by runtime call.
-  __ push(r1);
+  frame_->Push(r1);
 
   // Figure out which native to call and setup the arguments.
   Builtins::JavaScript native;
@@ -923,14 +994,14 @@
       ASSERT(cc == gt || cc == ge);  // remaining cases
       ncr = LESS;
     }
-    __ push(r0);
+    frame_->Push(r0);
     __ mov(r0, Operand(Smi::FromInt(ncr)));
     argc = 2;
   }
 
   // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
   // tagged as a small integer.
-  __ push(r0);
+  frame_->Push(r0);
   __ mov(r0, Operand(argc));
   __ InvokeBuiltin(native, CALL_JS);
   __ cmp(r0, Operand(0));
@@ -979,8 +1050,8 @@
   __ CallStub(&call_function);
 
   // Restore context and pop function from the stack.
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
-  __ pop();  // discard the TOS
+  __ ldr(cp, frame_->Context());
+  frame_->Pop();  // discard the TOS
 }
 
 
@@ -1012,10 +1083,10 @@
 
 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
   __ mov(r0, Operand(pairs));
-  __ push(r0);
-  __ push(cp);
+  frame_->Push(r0);
+  frame_->Push(cp);
   __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
-  __ push(r0);
+  frame_->Push(r0);
   __ CallRuntime(Runtime::kDeclareGlobals, 3);
   // The result is discarded.
 }
@@ -1035,26 +1106,26 @@
     // during variable resolution and must have mode DYNAMIC.
     ASSERT(var->mode() == Variable::DYNAMIC);
     // For now, just do a runtime call.
-    __ push(cp);
+    frame_->Push(cp);
     __ mov(r0, Operand(var->name()));
-    __ push(r0);
+    frame_->Push(r0);
     // Declaration nodes are always declared in only two modes.
     ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
     PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
     __ mov(r0, Operand(Smi::FromInt(attr)));
-    __ push(r0);
+    frame_->Push(r0);
     // Push initial value, if any.
     // Note: For variables we must not push an initial value (such as
     // 'undefined') because we may have a (legal) redeclaration and we
     // must not destroy the current value.
     if (node->mode() == Variable::CONST) {
       __ mov(r0, Operand(Factory::the_hole_value()));
-      __ push(r0);
+      frame_->Push(r0);
     } else if (node->fun() != NULL) {
       Load(node->fun());
     } else {
       __ mov(r0, Operand(0));  // no initial value!
-      __ push(r0);
+      frame_->Push(r0);
     }
     __ CallRuntime(Runtime::kDeclareContextSlot, 4);
     // Ignore the return value (declarations are statements).
@@ -1081,7 +1152,7 @@
     // safe to pop the value lying on top of the reference before unloading
     // the reference itself (which preserves the top of stack) because we
     // know it is a zero-sized reference.
-    __ pop();
+    frame_->Pop();
   }
 }
 
@@ -1092,7 +1163,7 @@
   Expression* expression = node->expression();
   expression->MarkAsStatement();
   Load(expression);
-  __ pop();
+  frame_->Pop();
 }
 
 
@@ -1157,7 +1228,7 @@
     if (has_cc()) {
       cc_reg_ = al;
     } else {
-      __ pop(r0);  // __ Pop(no_reg)
+      frame_->Pop();
     }
   }
 
@@ -1167,10 +1238,8 @@
 
 
 void CodeGenerator::CleanStack(int num_bytes) {
-  ASSERT(num_bytes >= 0);
-  if (num_bytes > 0) {
-    __ add(sp, sp, Operand(num_bytes));
-  }
+  ASSERT(num_bytes % kPointerSize == 0);
+  frame_->Drop(num_bytes / kPointerSize);
 }
 
 
@@ -1195,7 +1264,7 @@
   if (FLAG_debug_info) RecordStatementPosition(node);
   Load(node->expression());
   // Move the function result into r0.
-  __ pop(r0);
+  frame_->Pop(r0);
 
   __ b(&function_return_);
 }
@@ -1214,7 +1283,7 @@
     __ bind(&verified_true);
   }
   // Update context local.
-  __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  __ str(cp, frame_->Context());
 }
 
 
@@ -1223,7 +1292,7 @@
   // Pop context.
   __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX));
   // Update context local.
-  __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  __ str(cp, frame_->Context());
 }
 
 
@@ -1246,7 +1315,7 @@
 
   ASSERT(kSmiTag == 0 && kSmiTagSize <= 2);
 
-  __ pop(r0);
+  frame_->Pop(r0);
 
   // Test for a Smi value in a HeapNumber.
   Label is_smi;
@@ -1256,7 +1325,7 @@
   __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag));
   __ cmp(r1, Operand(HEAP_NUMBER_TYPE));
   __ b(ne, fail_label);
-  __ push(r0);
+  frame_->Push(r0);
   __ CallRuntime(Runtime::kNumberToSmi, 1);
   __ bind(&is_smi);
 
@@ -1324,8 +1393,8 @@
     } else {
       __ bind(&next);
       next.Unuse();
-      __ ldr(r0, MemOperand(sp, 0));
-      __ push(r0);  // duplicate TOS
+      __ ldr(r0, frame_->Top());
+      frame_->Push(r0);  // duplicate TOS
       Load(clause->label());
       Comparison(eq, true);
       Branch(false, &next);
@@ -1333,7 +1402,7 @@
 
     // Entering the case statement for the first time. Remove the switch value
     // from the stack.
-    __ pop(r0);
+    frame_->Pop();
 
     // Generate code for the body.
     // This is also the target for the fall through from the previous case's
@@ -1352,7 +1421,7 @@
     __ b(&default_case);
   } else {
     // Remove the switch value from the stack.
-    __ pop(r0);
+    frame_->Pop();
   }
 
   __ bind(&fall_through);
@@ -1448,7 +1517,7 @@
 
   // Get the object to enumerate over (converted to JSObject).
   Load(node->enumerable());
-  __ pop(r0);
+  frame_->Pop(r0);
 
   // Both SpiderMonkey and kjs ignore null and undefined in contrast
   // to the specification.  12.6.4 mandates a call to ToObject.
@@ -1473,7 +1542,7 @@
   __ b(hs, &jsobject);
 
   __ bind(&primitive);
-  __ push(r0);
+  frame_->Push(r0);
   __ mov(r0, Operand(0));
   __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
 
@@ -1481,8 +1550,8 @@
   __ bind(&jsobject);
 
   // Get the set of properties (as a FixedArray or Map).
-  __ push(r0);  // duplicate the object being enumerated
-  __ push(r0);
+  frame_->Push(r0);  // duplicate the object being enumerated
+  frame_->Push(r0);
   __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
 
   // If we got a Map, we can do a fast modification check.
@@ -1499,28 +1568,28 @@
   __ ldr(r2,
          FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
 
-  __ push(r0);  // map
-  __ push(r2);  // enum cache bridge cache
+  frame_->Push(r0);  // map
+  frame_->Push(r2);  // enum cache bridge cache
   __ ldr(r0, FieldMemOperand(r2, FixedArray::kLengthOffset));
   __ mov(r0, Operand(r0, LSL, kSmiTagSize));
-  __ push(r0);
+  frame_->Push(r0);
   __ mov(r0, Operand(Smi::FromInt(0)));
-  __ push(r0);
+  frame_->Push(r0);
   __ b(&entry);
 
 
   __ bind(&fixed_array);
 
   __ mov(r1, Operand(Smi::FromInt(0)));
-  __ push(r1);  // insert 0 in place of Map
-  __ push(r0);
+  frame_->Push(r1);  // insert 0 in place of Map
+  frame_->Push(r0);
 
   // Push the length of the array and the initial index onto the stack.
   __ ldr(r0, FieldMemOperand(r0, FixedArray::kLengthOffset));
   __ mov(r0, Operand(r0, LSL, kSmiTagSize));
-  __ push(r0);
+  frame_->Push(r0);
   __ mov(r0, Operand(Smi::FromInt(0)));  // init index
-  __ push(r0);
+  frame_->Push(r0);
 
   __ b(&entry);
 
@@ -1531,9 +1600,9 @@
   // Next.
   __ bind(node->continue_target());
   __ bind(&next);
-  __ pop(r0);
+  frame_->Pop(r0);
   __ add(r0, r0, Operand(Smi::FromInt(1)));
-  __ push(r0);
+  frame_->Push(r0);
 
   // Condition.
   __ bind(&entry);
@@ -1543,31 +1612,31 @@
   // sp[2] : array or enum cache
   // sp[3] : 0 or map
   // sp[4] : enumerable
-  __ ldr(r0, MemOperand(sp, 0 * kPointerSize));  // load the current count
-  __ ldr(r1, MemOperand(sp, 1 * kPointerSize));  // load the length
+  __ ldr(r0, frame_->Element(0));  // load the current count
+  __ ldr(r1, frame_->Element(1));  // load the length
   __ cmp(r0, Operand(r1));  // compare to the array length
   __ b(hs, &cleanup);
 
-  __ ldr(r0, MemOperand(sp, 0 * kPointerSize));
+  __ ldr(r0, frame_->Element(0));
 
   // Get the i'th entry of the array.
-  __ ldr(r2, MemOperand(sp, 2 * kPointerSize));
+  __ ldr(r2, frame_->Element(2));
   __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
 
   // Get Map or 0.
-  __ ldr(r2, MemOperand(sp, 3 * kPointerSize));
+  __ ldr(r2, frame_->Element(3));
   // Check if this (still) matches the map of the enumerable.
   // If not, we have to filter the key.
-  __ ldr(r1, MemOperand(sp, 4 * kPointerSize));
+  __ ldr(r1, frame_->Element(4));
   __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
   __ cmp(r1, Operand(r2));
   __ b(eq, &end_del_check);
 
   // Convert the entry to a string (or null if it isn't a property anymore).
-  __ ldr(r0, MemOperand(sp, 4 * kPointerSize));  // push enumerable
-  __ push(r0);
-  __ push(r3);  // push entry
+  __ ldr(r0, frame_->Element(4));  // push enumerable
+  frame_->Push(r0);
+  frame_->Push(r3);  // push entry
   __ mov(r0, Operand(1));
   __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS);
   __ mov(r3, Operand(r0));
@@ -1581,12 +1650,12 @@
 
   // Store the entry in the 'each' expression and take another spin in the loop.
   // r3: i'th entry of the enum cache (or string there of)
-  __ push(r3);  // push entry
+  frame_->Push(r3);  // push entry
   { Reference each(this, node->each());
     if (!each.is_illegal()) {
       if (each.size() > 0) {
-        __ ldr(r0, MemOperand(sp, kPointerSize * each.size()));
-        __ push(r0);
+        __ ldr(r0, frame_->Element(each.size()));
+        frame_->Push(r0);
       }
       // If the reference was to a slot we rely on the convenient property
       // that it doesn't matter whether a value (eg, r3 pushed above) is
@@ -1598,20 +1667,20 @@
         // ie, now the topmost value of the non-zero sized reference), since
         // we will discard the top of stack after unloading the reference
         // anyway.
-        __ pop(r0);
+        frame_->Pop(r0);
       }
     }
   }
   // Discard the i'th entry pushed above or else the remainder of the
   // reference, whichever is currently on top of the stack.
-  __ pop();
+  frame_->Pop();
   CheckStack();  // TODO(1222600): ignore if body contains calls.
   __ jmp(&loop);
 
   // Cleanup.
   __ bind(&cleanup);
   __ bind(node->break_target());
-  __ add(sp, sp, Operand(5 * kPointerSize));
+  frame_->Drop(5);
 
   // Exit.
   __ bind(&exit);
@@ -1626,11 +1695,10 @@
   Label try_block, exit;
 
   __ bl(&try_block);
-
   // --- Catch block ---
+  frame_->Push(r0);
 
   // Store the caught exception in the catch variable.
-  __ push(r0);
   { Reference ref(this, node->catch_var());
     ASSERT(ref.is_slot());
     // Here we make use of the convenient property that it doesn't matter
@@ -1640,7 +1708,7 @@
   }
 
   // Remove the exception from the stack.
-  __ pop();
+  frame_->Pop();
 
   VisitStatements(node->catch_block()->statements());
   __ b(&exit);
@@ -1667,7 +1735,7 @@
 
   // Generate code for the statements in the try block.
   VisitStatements(node->try_block()->statements());
-  __ pop(r0);  // Discard the result.
+  frame_->Pop();  // Discard the result.
 
   // Stop the introduced shadowing and count the number of required unlinks.
   // After shadowing stops, the original labels are unshadowed and the
@@ -1680,13 +1748,14 @@
 
   // Unlink from try chain.
   // TOS contains code slot
-  const int kNextOffset = StackHandlerConstants::kNextOffset +
-      StackHandlerConstants::kAddressDisplacement;
-  __ ldr(r1, MemOperand(sp, kNextOffset));  // read next_sp
+  const int kNextIndex = (StackHandlerConstants::kNextOffset
+                          + StackHandlerConstants::kAddressDisplacement)
+                       / kPointerSize;
+  __ ldr(r1, frame_->Element(kNextIndex));  // read next_sp
   __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
   __ str(r1, MemOperand(r3));
   ASSERT(StackHandlerConstants::kCodeOffset == 0);  // first field is code
-  __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
+  frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
   // Code slot popped.
   if (nof_unlinks > 0) __ b(&exit);
 
@@ -1702,10 +1771,10 @@
       __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
       __ ldr(sp, MemOperand(r3));
 
-      __ ldr(r1, MemOperand(sp, kNextOffset));
+      __ ldr(r1, frame_->Element(kNextIndex));
       __ str(r1, MemOperand(r3));
       ASSERT(StackHandlerConstants::kCodeOffset == 0);  // first field is code
-      __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
+      frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
       // Code slot popped.
 
       __ b(shadows[i]->original_label());
@@ -1728,7 +1797,7 @@
 
   __ bl(&try_block);
 
-  __ push(r0);  // save exception object on the stack
+  frame_->Push(r0);  // save exception object on the stack
   // In case of thrown exceptions, this is where we continue.
   __ mov(r2, Operand(Smi::FromInt(THROWING)));
   __ b(&finally_block);
@@ -1766,7 +1835,7 @@
 
   // Set the state on the stack to FALLING.
   __ mov(r0, Operand(Factory::undefined_value()));  // fake TOS
-  __ push(r0);
+  frame_->Push(r0);
   __ mov(r2, Operand(Smi::FromInt(FALLING)));
   if (nof_unlinks > 0) __ b(&unlink);
 
@@ -1778,11 +1847,11 @@
       if (shadows[i]->original_label() == &function_return_) {
         // If this label shadowed the function return, materialize the
         // return value on the stack.
-        __ push(r0);
+        frame_->Push(r0);
       } else {
         // Fake TOS for labels that shadowed breaks and continues.
         __ mov(r0, Operand(Factory::undefined_value()));
-        __ push(r0);
+        frame_->Push(r0);
       }
       __ mov(r2, Operand(Smi::FromInt(JUMPING + i)));
       __ b(&unlink);
@@ -1792,25 +1861,26 @@
   // Unlink from try chain;
   __ bind(&unlink);
 
-  __ pop(r0);  // Store TOS in r0 across stack manipulation
+  frame_->Pop(r0);  // Store TOS in r0 across stack manipulation
   // Reload sp from the top handler, because some statements that we
   // break from (eg, for...in) may have left stuff on the stack.
   __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
   __ ldr(sp, MemOperand(r3));
-  const int kNextOffset = StackHandlerConstants::kNextOffset +
-      StackHandlerConstants::kAddressDisplacement;
-  __ ldr(r1, MemOperand(sp, kNextOffset));
+  const int kNextIndex = (StackHandlerConstants::kNextOffset
+                          + StackHandlerConstants::kAddressDisplacement)
+                       / kPointerSize;
+  __ ldr(r1, frame_->Element(kNextIndex));
   __ str(r1, MemOperand(r3));
   ASSERT(StackHandlerConstants::kCodeOffset == 0);  // first field is code
-  __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
+  frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
   // Code slot popped.
-  __ push(r0);
+  frame_->Push(r0);
 
   // --- Finally block ---
   __ bind(&finally_block);
 
   // Push the state on the stack.
-  __ push(r2);
+  frame_->Push(r2);
 
   // We keep two elements on the stack - the (possibly faked) result
   // and the state - while evaluating the finally block. Record it, so
@@ -1823,8 +1893,8 @@
   VisitStatements(node->finally_block()->statements());
 
   // Restore state and return value or faked TOS.
-  __ pop(r2);
-  __ pop(r0);
+  frame_->Pop(r2);
+  frame_->Pop(r0);
   break_stack_height_ -= kFinallyStackSize;
 
   // Generate code to jump to the right destination for all used (formerly)
@@ -1848,7 +1918,7 @@
   __ b(ne, &exit);
 
   // Rethrow exception.
-  __ push(r0);
+  frame_->Push(r0);
   __ CallRuntime(Runtime::kReThrow, 1);
 
   // Done.
@@ -1869,12 +1939,12 @@
 
   // Push the boilerplate on the stack.
   __ mov(r0, Operand(boilerplate));
-  __ push(r0);
+  frame_->Push(r0);
 
   // Create a new closure.
-  __ push(cp);
+  frame_->Push(cp);
   __ CallRuntime(Runtime::kNewClosure, 2);
-  __ push(r0);
+  frame_->Push(r0);
 }
 
 
@@ -1915,16 +1985,16 @@
     ASSERT(slot->var()->mode() == Variable::DYNAMIC);
 
     // For now, just do a runtime call.
-    __ push(cp);
+    frame_->Push(cp);
     __ mov(r0, Operand(slot->var()->name()));
-    __ push(r0);
+    frame_->Push(r0);
 
     if (typeof_state == INSIDE_TYPEOF) {
       __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
     } else {
       __ CallRuntime(Runtime::kLoadContextSlot, 2);
     }
-    __ push(r0);
+    frame_->Push(r0);
 
   } else {
     // Note: We would like to keep the assert below, but it fires because of
@@ -1933,16 +2003,16 @@
 
     // Special handling for locals allocated in registers.
     __ ldr(r0, SlotOperand(slot, r2));
-    __ push(r0);
+    frame_->Push(r0);
     if (slot->var()->mode() == Variable::CONST) {
       // Const slots may contain 'the hole' value (the constant hasn't been
       // initialized yet) which needs to be converted into the 'undefined'
       // value.
       Comment cmnt(masm_, "[ Unhole const");
-      __ pop(r0);
+      frame_->Pop(r0);
       __ cmp(r0, Operand(Factory::the_hole_value()));
       __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq);
-      __ push(r0);
+      frame_->Push(r0);
     }
   }
 }
@@ -1972,7 +2042,7 @@
 void CodeGenerator::VisitLiteral(Literal* node) {
   Comment cmnt(masm_, "[ Literal");
   __ mov(r0, Operand(node->handle()));
-  __ push(r0);
+  frame_->Push(r0);
 }
 
 
@@ -1982,7 +2052,7 @@
   // Retrieve the literal array and check the allocated entry.
 
   // Load the function of this activation.
-  __ ldr(r1, FunctionOperand());
+  __ ldr(r1, frame_->Function());
 
   // Load the literals array of the function.
   __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
@@ -1998,19 +2068,19 @@
 
   // If the entry is undefined we call the runtime system to computed
   // the literal.
-  __ push(r1);  // literal array  (0)
+  frame_->Push(r1);  // literal array  (0)
   __ mov(r0, Operand(Smi::FromInt(node->literal_index())));
-  __ push(r0);  // literal index  (1)
+  frame_->Push(r0);  // literal index  (1)
   __ mov(r0, Operand(node->pattern()));  // RegExp pattern (2)
-  __ push(r0);
+  frame_->Push(r0);
   __ mov(r0, Operand(node->flags()));  // RegExp flags   (3)
-  __ push(r0);
+  frame_->Push(r0);
   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
   __ mov(r2, Operand(r0));
 
   __ bind(&done);
   // Push the literal.
-  __ push(r2);
+  frame_->Push(r2);
 }
 
 
@@ -2055,7 +2125,7 @@
   // Retrieve the literal array and check the allocated entry.
 
   // Load the function of this activation.
-  __ ldr(r1, FunctionOperand());
+  __ ldr(r1, frame_->Function());
 
   // Load the literals array of the function.
   __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
@@ -2072,11 +2142,11 @@
   __ bind(deferred->exit());
 
   // Push the object literal boilerplate.
-  __ push(r2);
+  frame_->Push(r2);
 
   // Clone the boilerplate object.
   __ CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1);
-  __ push(r0);  // save the result
+  frame_->Push(r0);  // save the result
   // r0: cloned object literal
 
   for (int i = 0; i < node->properties()->length(); i++) {
@@ -2087,32 +2157,32 @@
       case ObjectLiteral::Property::CONSTANT: break;
       case ObjectLiteral::Property::COMPUTED:  // fall through
       case ObjectLiteral::Property::PROTOTYPE: {
-        __ push(r0);  // dup the result
+        frame_->Push(r0);  // dup the result
         Load(key);
         Load(value);
         __ CallRuntime(Runtime::kSetProperty, 3);
         // restore r0
-        __ ldr(r0, MemOperand(sp, 0));
+        __ ldr(r0, frame_->Top());
         break;
       }
       case ObjectLiteral::Property::SETTER: {
-        __ push(r0);
+        frame_->Push(r0);
         Load(key);
         __ mov(r0, Operand(Smi::FromInt(1)));
-        __ push(r0);
+        frame_->Push(r0);
         Load(value);
         __ CallRuntime(Runtime::kDefineAccessor, 4);
-        __ ldr(r0, MemOperand(sp, 0));
+        __ ldr(r0, frame_->Top());
         break;
       }
       case ObjectLiteral::Property::GETTER: {
-        __ push(r0);
+        frame_->Push(r0);
         Load(key);
         __ mov(r0, Operand(Smi::FromInt(0)));
-        __ push(r0);
+        frame_->Push(r0);
         Load(value);
         __ CallRuntime(Runtime::kDefineAccessor, 4);
-        __ ldr(r0, MemOperand(sp, 0));
+        __ ldr(r0, frame_->Top());
         break;
       }
     }
@@ -2125,15 +2195,15 @@
 
   // Call runtime to create the array literal.
   __ mov(r0, Operand(node->literals()));
-  __ push(r0);
+  frame_->Push(r0);
   // Load the function of this frame.
-  __ ldr(r0, FunctionOperand());
+  __ ldr(r0, frame_->Function());
   __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
-  __ push(r0);
+  frame_->Push(r0);
   __ CallRuntime(Runtime::kCreateArrayLiteral, 2);
 
   // Push the resulting array literal on the stack.
-  __ push(r0);
+  frame_->Push(r0);
 
   // Generate code to set the elements in the array that are not
   // literals.
@@ -2145,10 +2215,10 @@
     if (value->AsLiteral() == NULL) {
       // The property must be set by generated code.
       Load(value);
-      __ pop(r0);
+      frame_->Pop(r0);
 
       // Fetch the object literal
-      __ ldr(r1, MemOperand(sp, 0));
+      __ ldr(r1, frame_->Top());
         // Get the elements array.
       __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
 
@@ -2181,12 +2251,12 @@
     Literal* literal = node->value()->AsLiteral();
     if (literal != NULL && literal->handle()->IsSmi()) {
       SmiOperation(node->binary_op(), literal->handle(), false);
-      __ push(r0);
+      frame_->Push(r0);
 
     } else {
       Load(node->value());
       GenericBinaryOperation(node->binary_op());
-      __ push(r0);
+      frame_->Push(r0);
     }
   }
 
@@ -2216,7 +2286,7 @@
   Load(node->exception());
   __ RecordPosition(node->position());
   __ CallRuntime(Runtime::kThrow, 1);
-  __ push(r0);
+  frame_->Push(r0);
 }
 
 
@@ -2257,7 +2327,7 @@
 
     // Push the name of the function and the receiver onto the stack.
     __ mov(r0, Operand(var->name()));
-    __ push(r0);
+    frame_->Push(r0);
 
     // Pass the global object as the receiver and let the IC stub
     // patch the stack to use the global proxy as 'this' in the
@@ -2271,10 +2341,10 @@
     Handle<Code> stub = ComputeCallInitialize(args->length());
     __ RecordPosition(node->position());
     __ Call(stub, RelocInfo::CODE_TARGET_CONTEXT);
-    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+    __ ldr(cp, frame_->Context());
     // Remove the function from the stack.
-    __ pop();
-    __ push(r0);
+    frame_->Pop();
+    frame_->Push(r0);
 
   } else if (var != NULL && var->slot() != NULL &&
              var->slot()->type() == Slot::LOOKUP) {
@@ -2283,19 +2353,19 @@
     // ----------------------------------
 
     // Load the function
-    __ push(cp);
+    frame_->Push(cp);
     __ mov(r0, Operand(var->name()));
-    __ push(r0);
+    frame_->Push(r0);
     __ CallRuntime(Runtime::kLoadContextSlot, 2);
     // r0: slot value; r1: receiver
 
     // Load the receiver.
-    __ push(r0);  // function
-    __ push(r1);  // receiver
+    frame_->Push(r0);  // function
+    frame_->Push(r1);  // receiver
 
     // Call the function.
     CallWithArguments(args, node->position());
-    __ push(r0);
+    frame_->Push(r0);
 
   } else if (property != NULL) {
     // Check if the key is a literal string.
@@ -2308,7 +2378,7 @@
 
       // Push the name of the function and the receiver onto the stack.
       __ mov(r0, Operand(literal->handle()));
-      __ push(r0);
+      frame_->Push(r0);
       Load(property->obj());
 
       // Load the arguments.
@@ -2318,12 +2388,12 @@
       Handle<Code> stub = ComputeCallInitialize(args->length());
       __ RecordPosition(node->position());
       __ Call(stub, RelocInfo::CODE_TARGET);
-      __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+      __ ldr(cp, frame_->Context());
 
       // Remove the function from the stack.
-      __ pop();
+      frame_->Pop();
 
-      __ push(r0);  // push after get rid of function from the stack
+      frame_->Push(r0);  // push after get rid of function from the stack
 
     } else {
       // -------------------------------------------
@@ -2335,11 +2405,11 @@
       ref.GetValue(NOT_INSIDE_TYPEOF);  // receiver
 
       // Pass receiver to called function.
-      __ ldr(r0, MemOperand(sp, ref.size() * kPointerSize));
-      __ push(r0);
+      __ ldr(r0, frame_->Element(ref.size()));
+      frame_->Push(r0);
       // Call the function.
       CallWithArguments(args, node->position());
-      __ push(r0);
+      frame_->Push(r0);
     }
 
   } else {
@@ -2355,7 +2425,7 @@
 
     // Call the function.
     CallWithArguments(args, node->position());
-    __ push(r0);
+    frame_->Push(r0);
   }
 }
 
@@ -2383,7 +2453,7 @@
   __ mov(r0, Operand(args->length()));
 
   // Load the function into r1 as per calling convention.
-  __ ldr(r1, MemOperand(sp, (args->length() + 1) * kPointerSize));
+  __ ldr(r1, frame_->Element(args->length() + 1));
 
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
@@ -2392,7 +2462,7 @@
           RelocInfo::CONSTRUCT_CALL);
 
   // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)).
-  __ str(r0, MemOperand(sp, 0 * kPointerSize));
+  __ str(r0, frame_->Top());
 }
 
 
@@ -2400,7 +2470,7 @@
   ASSERT(args->length() == 1);
   Label leave;
   Load(args->at(0));
-  __ pop(r0);  // r0 contains object.
+  frame_->Pop(r0);  // r0 contains object.
   // if (object->IsSmi()) return the object.
   __ tst(r0, Operand(kSmiTagMask));
   __ b(eq, &leave);
@@ -2413,7 +2483,7 @@
   // Load the value.
   __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
   __ bind(&leave);
-  __ push(r0);
+  frame_->Push(r0);
 }
 
 
@@ -2422,8 +2492,8 @@
   Label leave;
   Load(args->at(0));  // Load the object.
   Load(args->at(1));  // Load the value.
-  __ pop(r0);  // r0 contains value
-  __ pop(r1);  // r1 contains object
+  frame_->Pop(r0);  // r0 contains value
+  frame_->Pop(r1);  // r1 contains object
   // if (object->IsSmi()) return object.
   __ tst(r1, Operand(kSmiTagMask));
   __ b(eq, &leave);
@@ -2440,14 +2510,14 @@
   __ RecordWrite(r1, r2, r3);
   // Leave.
   __ bind(&leave);
-  __ push(r0);
+  frame_->Push(r0);
 }
 
 
 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
   ASSERT(args->length() == 1);
   Load(args->at(0));
-  __ pop(r0);
+  frame_->Pop(r0);
   __ tst(r0, Operand(kSmiTagMask));
   cc_reg_ = eq;
 }
@@ -2456,7 +2526,7 @@
 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
   ASSERT(args->length() == 1);
   Load(args->at(0));
-  __ pop(r0);
+  frame_->Pop(r0);
   __ tst(r0, Operand(kSmiTagMask | 0x80000000));
   cc_reg_ = eq;
 }
@@ -2468,7 +2538,7 @@
 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
   ASSERT(args->length() == 2);
   __ mov(r0, Operand(Factory::undefined_value()));
-  __ push(r0);
+  frame_->Push(r0);
 }
 
 
@@ -2479,7 +2549,7 @@
   // We need the CC bits to come out as not_equal in the case where the
   // object is a smi.  This can't be done with the usual test opcode so
   // we use XOR to get the right CC bits.
-  __ pop(r0);
+  frame_->Pop(r0);
   __ and_(r1, r0, Operand(kSmiTagMask));
   __ eor(r1, r1, Operand(kSmiTagMask), SetCC);
   __ b(ne, &answer);
@@ -2503,7 +2573,7 @@
   // Call the shared stub to get to the arguments.length.
   ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
   __ CallStub(&stub);
-  __ push(r0);
+  frame_->Push(r0);
 }
 
 
@@ -2513,13 +2583,13 @@
   // Satisfy contract with ArgumentsAccessStub:
   // Load the key into r1 and the formal parameters count into r0.
   Load(args->at(0));
-  __ pop(r1);
+  frame_->Pop(r1);
   __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
 
   // Call the shared stub to get to arguments[key].
   ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
   __ CallStub(&stub);
-  __ push(r0);
+  frame_->Push(r0);
 }
 
 
@@ -2529,8 +2599,8 @@
   // Load the two objects into registers and perform the comparison.
   Load(args->at(0));
   Load(args->at(1));
-  __ pop(r0);
-  __ pop(r1);
+  frame_->Pop(r0);
+  frame_->Pop(r1);
   __ cmp(r0, Operand(r1));
   cc_reg_ = eq;
 }
@@ -2549,25 +2619,25 @@
 
     // Call the C runtime function.
     __ CallRuntime(function, args->length());
-    __ push(r0);
+    frame_->Push(r0);
 
   } else {
     // Prepare stack for calling JS runtime function.
     __ mov(r0, Operand(node->name()));
-    __ push(r0);
+    frame_->Push(r0);
     // Push the builtins object found in the current global object.
     __ ldr(r1, GlobalObject());
     __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));
-    __ push(r0);
+    frame_->Push(r0);
 
     for (int i = 0; i < args->length(); i++) Load(args->at(i));
 
     // Call the JS runtime function.
     Handle<Code> stub = ComputeCallInitialize(args->length());
     __ Call(stub, RelocInfo::CODE_TARGET);
-    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
-    __ pop();
-    __ push(r0);
+    __ ldr(cp, frame_->Context());
+    frame_->Pop();
+    frame_->Push(r0);
   }
 }
 
@@ -2599,20 +2669,20 @@
       if (variable->is_global()) {
         LoadGlobal();
         __ mov(r0, Operand(variable->name()));
-        __ push(r0);
+        frame_->Push(r0);
         __ mov(r0, Operand(1));  // not counting receiver
         __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
 
       } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
         // lookup the context holding the named variable
-        __ push(cp);
+        frame_->Push(cp);
         __ mov(r0, Operand(variable->name()));
-        __ push(r0);
+        frame_->Push(r0);
         __ CallRuntime(Runtime::kLookupContext, 2);
         // r0: context
-        __ push(r0);
+        frame_->Push(r0);
         __ mov(r0, Operand(variable->name()));
-        __ push(r0);
+        frame_->Push(r0);
         __ mov(r0, Operand(1));  // not counting receiver
         __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
 
@@ -2625,21 +2695,21 @@
     } else {
       // Default: Result of deleting expressions is true.
       Load(node->expression());  // may have side-effects
-      __ pop();
+      frame_->Pop();
       __ mov(r0, Operand(Factory::true_value()));
     }
-    __ push(r0);
+    frame_->Push(r0);
 
   } else if (op == Token::TYPEOF) {
     // Special case for loading the typeof expression; see comment on
     // LoadTypeofExpression().
     LoadTypeofExpression(node->expression());
     __ CallRuntime(Runtime::kTypeof, 1);
-    __ push(r0);  // r0 has result
+    frame_->Push(r0);  // r0 has result
 
   } else {
     Load(node->expression());
-    __ pop(r0);
+    frame_->Pop(r0);
     switch (op) {
       case Token::NOT:
       case Token::DELETE:
@@ -2660,7 +2730,7 @@
         __ tst(r0, Operand(kSmiTagMask));
         __ b(eq, &smi_label);
 
-        __ push(r0);
+        frame_->Push(r0);
         __ mov(r0, Operand(0));  // not counting receiver
         __ InvokeBuiltin(Builtins::BIT_NOT, CALL_JS);
 
@@ -2683,7 +2753,7 @@
         Label continue_label;
         __ tst(r0, Operand(kSmiTagMask));
         __ b(eq, &continue_label);
-        __ push(r0);
+        frame_->Push(r0);
         __ mov(r0, Operand(0));  // not counting receiver
         __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
         __ bind(&continue_label);
@@ -2692,7 +2762,7 @@
       default:
         UNREACHABLE();
     }
-    __ push(r0);  // r0 has result
+    frame_->Push(r0);  // r0 has result
   }
 }
 
@@ -2709,13 +2779,13 @@
   // Postfix: Make room for the result.
   if (is_postfix) {
      __ mov(r0, Operand(0));
-     __ push(r0);
+     frame_->Push(r0);
   }
 
   { Reference target(this, node->expression());
     if (target.is_illegal()) return;
     target.GetValue(NOT_INSIDE_TYPEOF);
-    __ pop(r0);
+    frame_->Pop(r0);
 
     Label slow, exit;
 
@@ -2727,7 +2797,9 @@
     __ b(ne, &slow);
 
     // Postfix: Store the old value as the result.
-    if (is_postfix) __ str(r0, MemOperand(sp, target.size() * kPointerSize));
+    if (is_postfix) {
+      __ str(r0, frame_->Element(target.size()));
+    }
 
     // Perform optimistic increment/decrement.
     if (is_increment) {
@@ -2754,7 +2826,7 @@
       InvokeBuiltinStub stub(InvokeBuiltinStub::ToNumber, 2);
       __ CallStub(&stub);
       // Store to result (on the stack).
-      __ str(r0, MemOperand(sp, target.size() * kPointerSize));
+      __ str(r0, frame_->Element(target.size()));
     }
 
     // Compute the new value by calling the right JavaScript native.
@@ -2768,12 +2840,12 @@
 
     // Store the new value in the target if not const.
     __ bind(&exit);
-    __ push(r0);
+    frame_->Push(r0);
     if (!is_const) target.SetValue(NOT_CONST_INIT);
   }
 
   // Postfix: Discard the new value and use the old.
-  if (is_postfix) __ pop(r0);
+  if (is_postfix) frame_->Pop(r0);
 }
 
 
@@ -2814,8 +2886,8 @@
     } else {
       Label pop_and_continue, exit;
 
-      __ ldr(r0, MemOperand(sp, 0));  // dup the stack top
-      __ push(r0);
+      __ ldr(r0, frame_->Top());  // dup the stack top
+      frame_->Push(r0);
       // Avoid popping the result if it converts to 'false' using the
       // standard ToBoolean() conversion as described in ECMA-262,
       // section 9.2, page 30.
@@ -2824,7 +2896,7 @@
 
       // Pop the result of evaluating the first part.
       __ bind(&pop_and_continue);
-      __ pop(r0);
+      frame_->Pop(r0);
 
       // Evaluate right side expression.
       __ bind(&is_true);
@@ -2855,8 +2927,8 @@
     } else {
       Label pop_and_continue, exit;
 
-      __ ldr(r0, MemOperand(sp, 0));
-      __ push(r0);
+      __ ldr(r0, frame_->Top());
+      frame_->Push(r0);
       // Avoid popping the result if it converts to 'true' using the
       // standard ToBoolean() conversion as described in ECMA-262,
       // section 9.2, page 30.
@@ -2865,7 +2937,7 @@
 
       // Pop the result of evaluating the first part.
       __ bind(&pop_and_continue);
-      __ pop(r0);
+      frame_->Pop(r0);
 
       // Evaluate right side expression.
       __ bind(&is_false);
@@ -2894,14 +2966,14 @@
       Load(node->right());
       GenericBinaryOperation(node->op());
     }
-    __ push(r0);
+    frame_->Push(r0);
   }
 }
 
 
 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
-  __ ldr(r0, FunctionOperand());
-  __ push(r0);
+  __ ldr(r0, frame_->Function());
+  frame_->Push(r0);
 }
 
 
@@ -2913,55 +2985,47 @@
   Expression* right = node->right();
   Token::Value op = node->op();
 
-  // NOTE: To make null checks efficient, we check if either left or
-  // right is the literal 'null'. If so, we optimize the code by
-  // inlining a null check instead of calling the (very) general
-  // runtime routine for checking equality.
-
+  // To make null checks efficient, we check if either left or right is the
+  // literal 'null'. If so, we optimize the code by inlining a null check
+  // instead of calling the (very) general runtime routine for checking
+  // equality.
   if (op == Token::EQ || op == Token::EQ_STRICT) {
     bool left_is_null =
-      left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
+        left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
     bool right_is_null =
-      right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
-    // The 'null' value is only equal to 'null' or 'undefined'.
+        right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
+    // The 'null' value can only be equal to 'null' or 'undefined'.
     if (left_is_null || right_is_null) {
       Load(left_is_null ? right : left);
-      Label exit, undetectable;
-      __ pop(r0);
+      frame_->Pop(r0);
       __ cmp(r0, Operand(Factory::null_value()));
 
-      // The 'null' value is only equal to 'undefined' if using
-      // non-strict comparisons.
+      // The 'null' value is only equal to 'undefined' if using non-strict
+      // comparisons.
       if (op != Token::EQ_STRICT) {
-        __ b(eq, &exit);
+        __ b(eq, true_target());
+
         __ cmp(r0, Operand(Factory::undefined_value()));
+        __ b(eq, true_target());
 
-        // NOTE: it can be undetectable object.
-        __ b(eq, &exit);
         __ tst(r0, Operand(kSmiTagMask));
+        __ b(eq, false_target());
 
-        __ b(ne, &undetectable);
-        __ b(false_target());
-
-        __ bind(&undetectable);
-        __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
-        __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
-        __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
-        __ cmp(r2, Operand(1 << Map::kIsUndetectable));
+        // It can be an undetectable object.
+        __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
+        __ ldrb(r0, FieldMemOperand(r0, Map::kBitFieldOffset));
+        __ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
+        __ cmp(r0, Operand(1 << Map::kIsUndetectable));
       }
 
-      __ bind(&exit);
-
       cc_reg_ = eq;
       return;
     }
   }
 
-
-  // NOTE: To make typeof testing for natives implemented in
-  // JavaScript really efficient, we generate special code for
-  // expressions of the form: 'typeof <expression> == <string>'.
-
+  // To make typeof testing for natives implemented in JavaScript really
+  // efficient, we generate special code for expressions of the form:
+  // 'typeof <expression> == <string>'.
   UnaryOperation* operation = left->AsUnaryOperation();
   if ((op == Token::EQ || op == Token::EQ_STRICT) &&
       (operation != NULL && operation->op() == Token::TYPEOF) &&
@@ -2971,7 +3035,7 @@
 
     // Load the operand, move it to register r1.
     LoadTypeofExpression(operation->expression());
-    __ pop(r1);
+    frame_->Pop(r1);
 
     if (check->Equals(Heap::number_symbol())) {
       __ tst(r1, Operand(kSmiTagMask));
@@ -2986,7 +3050,7 @@
 
       __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
 
-      // NOTE: it might be an undetectable string object
+      // It can be an undetectable string object.
       __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
       __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
       __ cmp(r2, Operand(1 << Map::kIsUndetectable));
@@ -3009,7 +3073,7 @@
       __ tst(r1, Operand(kSmiTagMask));
       __ b(eq, false_target());
 
-      // NOTE: it can be undetectable object.
+      // It can be an undetectable object.
       __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
       __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
       __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
@@ -3033,7 +3097,7 @@
       __ cmp(r1, Operand(Factory::null_value()));
       __ b(eq, true_target());
 
-      // NOTE: it might be an undetectable object.
+      // It can be an undetectable object.
       __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
       __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
       __ cmp(r1, Operand(1 << Map::kIsUndetectable));
@@ -3046,8 +3110,8 @@
       cc_reg_ = le;
 
     } else {
-      // Uncommon case: Typeof testing against a string literal that
-      // is never returned from the typeof operator.
+      // Uncommon case: typeof testing against a string literal that is
+      // never returned from the typeof operator.
       __ b(false_target());
     }
     return;
@@ -3083,7 +3147,7 @@
     case Token::IN:
       __ mov(r0, Operand(1));  // not counting receiver
       __ InvokeBuiltin(Builtins::IN, CALL_JS);
-      __ push(r0);
+      frame_->Push(r0);
       break;
 
     case Token::INSTANCEOF:
@@ -3108,34 +3172,6 @@
 }
 
 
-void CodeGenerator::EnterJSFrame() {
-#if defined(DEBUG)
-  { Label done, fail;
-    __ tst(r1, Operand(kSmiTagMask));
-    __ b(eq, &fail);
-    __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
-    __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
-    __ cmp(r2, Operand(JS_FUNCTION_TYPE));
-    __ b(eq, &done);
-    __ bind(&fail);
-    __ stop("CodeGenerator::EnterJSFrame - r1 not a function");
-    __ bind(&done);
-  }
-#endif  // DEBUG
-
-  __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
-  __ add(fp, sp, Operand(2 * kPointerSize));  // Adjust FP to point to saved FP.
-}
-
-
-void CodeGenerator::ExitJSFrame() {
-  // Drop the execution stack down to the frame pointer and restore the caller
-  // frame pointer and return address.
-  __ mov(sp, fp);
-  __ ldm(ia_w, sp, fp.bit() | lr.bit());
-}
-
-
 #undef __
 #define __ masm->
 
@@ -3160,6 +3196,7 @@
   ASSERT(!is_illegal());
   ASSERT(!cgen_->has_cc());
   MacroAssembler* masm = cgen_->masm();
+  VirtualFrame* frame = cgen_->frame();
   Property* property = expression_->AsProperty();
   if (property != NULL) {
     __ RecordPosition(property->position());
@@ -3193,7 +3230,7 @@
       } else {
         __ Call(ic, RelocInfo::CODE_TARGET);
       }
-      __ push(r0);
+      frame->Push(r0);
       break;
     }
 
@@ -3202,10 +3239,16 @@
       // distinction between expressions in a typeof and not in a typeof.
       Comment cmnt(masm, "[ Load from keyed Property");
       ASSERT(property != NULL);
-      // TODO(1224671): Implement inline caching for keyed loads as on ia32.
-      GetPropertyStub stub;
-      __ CallStub(&stub);
-      __ push(r0);
+      Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+
+      Variable* var = expression_->AsVariableProxy()->AsVariable();
+      if (var != NULL) {
+        ASSERT(var->is_global());
+        __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+      } else {
+        __ Call(ic, RelocInfo::CODE_TARGET);
+      }
+      frame->Push(r0);
       break;
     }
 
@@ -3219,6 +3262,7 @@
   ASSERT(!is_illegal());
   ASSERT(!cgen_->has_cc());
   MacroAssembler* masm = cgen_->masm();
+  VirtualFrame* frame = cgen_->frame();
   Property* property = expression_->AsProperty();
   if (property != NULL) {
     __ RecordPosition(property->position());
@@ -3233,9 +3277,9 @@
         ASSERT(slot->var()->mode() == Variable::DYNAMIC);
 
         // For now, just do a runtime call.
-        __ push(cp);
+        frame->Push(cp);
         __ mov(r0, Operand(slot->var()->name()));
-        __ push(r0);
+        frame->Push(r0);
 
         if (init_state == CONST_INIT) {
           // Same as the case for a normal store, but ignores attribute
@@ -3259,7 +3303,7 @@
         }
         // Storing a variable must keep the (new) value on the expression
         // stack. This is necessary for compiling assignment expressions.
-        __ push(r0);
+        frame->Push(r0);
 
       } else {
         ASSERT(slot->var()->mode() != Variable::DYNAMIC);
@@ -3285,9 +3329,9 @@
         // initialize consts to 'the hole' value and by doing so, end up
         // calling this code.  r2 may be loaded with context; used below in
         // RecordWrite.
-        __ pop(r0);
+        frame->Pop(r0);
         __ str(r0, cgen_->SlotOperand(slot, r2));
-        __ push(r0);
+        frame->Push(r0);
         if (slot->type() == Slot::CONTEXT) {
           // Skip write barrier if the written value is a smi.
           __ tst(r0, Operand(kSmiTagMask));
@@ -3310,13 +3354,13 @@
     case NAMED: {
       Comment cmnt(masm, "[ Store to named Property");
       // Call the appropriate IC code.
-      __ pop(r0);  // value
+      frame->Pop(r0);  // value
       // Setup the name register.
       Handle<String> name(GetName());
       __ mov(r2, Operand(name));
       Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
       __ Call(ic, RelocInfo::CODE_TARGET);
-      __ push(r0);
+      frame->Push(r0);
       break;
     }
 
@@ -3325,10 +3369,13 @@
       Property* property = expression_->AsProperty();
       ASSERT(property != NULL);
       __ RecordPosition(property->position());
-      __ pop(r0);  // value
-      SetPropertyStub stub;
-      __ CallStub(&stub);
-      __ push(r0);
+
+      // Call IC code.
+      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      // TODO(1222589): Make the IC grab the values from the stack.
+      frame->Pop(r0);  // value
+      __ Call(ic, RelocInfo::CODE_TARGET);
+      frame->Push(r0);
       break;
     }
 
@@ -3813,8 +3860,16 @@
   // Restore the stack to the address of the ENTRY handler
   __ mov(sp, Operand(r3));
 
-  // restore parameter- and frame-pointer and pop state.
-  __ ldm(ia_w, sp, r3.bit() | pp.bit() | fp.bit());
+  // Stack layout at this point. See also PushTryHandler
+  // r3, sp ->   next handler
+  //             state (ENTRY)
+  //             pp
+  //             fp
+  //             lr
+
+  // Discard ENTRY state (r2 is not used), and restore parameter-
+  // and frame-pointer and pop state.
+  __ ldm(ia_w, sp, r2.bit() | r3.bit() | pp.bit() | fp.bit());
   // Before returning we restore the context from the frame pointer if not NULL.
   // The frame pointer is NULL in the exception handler of a JS entry frame.
   __ cmp(fp, Operand(0));
@@ -4044,7 +4099,7 @@
   // sets it to 0 to signal the existence of the JSEntry frame.
   __ mov(ip, Operand(Top::pending_exception_address()));
   __ str(r0, MemOperand(ip));
-  __ mov(r0, Operand(Handle<Failure>(Failure::Exception())));
+  __ mov(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
   __ b(&exit);
 
   // Invoke: Link this frame into the handler chain.
@@ -4229,7 +4284,10 @@
   // Slow-case: Non-function called.
   __ bind(&slow);
   __ mov(r0, Operand(argc_));  // Setup the number of arguments.
-  __ InvokeBuiltin(Builtins::CALL_NON_FUNCTION, JUMP_JS);
+  __ mov(r2, Operand(0));
+  __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
+  __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)),
+          RelocInfo::CODE_TARGET);
 }
 
 
diff --git a/src/codegen-arm.h b/src/codegen-arm.h
index 8058138..2b889cd 100644
--- a/src/codegen-arm.h
+++ b/src/codegen-arm.h
@@ -38,8 +38,62 @@
 // Mode to overwrite BinaryExpression values.
 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
 
+enum InitState { CONST_INIT, NOT_CONST_INIT };
+enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
 
-// -----------------------------------------------------------------------------
+
+// -------------------------------------------------------------------------
+// Virtual frame
+
+class VirtualFrame BASE_EMBEDDED {
+ public:
+  explicit VirtualFrame(CodeGenerator* cgen);
+
+  void Enter();
+  void Exit();
+
+  void AllocateLocals();
+
+  MemOperand Top() const { return MemOperand(sp, 0); }
+
+  MemOperand Element(int index) const {
+    return MemOperand(sp, index * kPointerSize);
+  }
+
+  MemOperand Local(int index) const {
+    ASSERT(0 <= index && index < frame_local_count_);
+    return MemOperand(fp, kLocal0Offset - index * kPointerSize);
+  }
+
+  MemOperand Function() const { return MemOperand(fp, kFunctionOffset); }
+
+  MemOperand Context() const { return MemOperand(fp, kContextOffset); }
+
+  MemOperand Parameter(int index) const {
+    // Index -1 corresponds to the receiver.
+    ASSERT(-1 <= index && index <= parameter_count_);
+    return MemOperand(fp, (1 + parameter_count_ - index) * kPointerSize);
+  }
+
+  inline void Drop(int count);
+
+  inline void Pop();
+  inline void Pop(Register reg);
+
+  inline void Push(Register reg);
+
+ private:
+  static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
+  static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;
+  static const int kContextOffset = StandardFrameConstants::kContextOffset;
+
+  MacroAssembler* masm_;
+  int frame_local_count_;
+  int parameter_count_;
+};
+
+
+// -------------------------------------------------------------------------
 // Reference support
 
 // A reference is a C++ stack-allocated object that keeps an ECMA
@@ -49,9 +103,6 @@
 // For properties, we keep either one (named) or two (indexed) values
 // on the execution stack to represent the reference.
 
-enum InitState { CONST_INIT, NOT_CONST_INIT };
-enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
-
 class Reference BASE_EMBEDDED {
  public:
   // The values of the types is important, see size().
@@ -66,8 +117,8 @@
     type_ = value;
   }
 
-  // The size of the reference or -1 if the reference is illegal.
-  int size() const { return type_; }
+  // The size the reference takes up on the stack.
+  int size() const { return (type_ == ILLEGAL) ? 0 : type_; }
 
   bool is_illegal() const { return type_ == ILLEGAL; }
   bool is_slot() const { return type_ == SLOT; }
@@ -133,7 +184,7 @@
 };
 
 
-// -----------------------------------------------------------------------------
+// -------------------------------------------------------------------------
 // CodeGenerator
 
 class CodeGenerator: public Visitor {
@@ -156,6 +207,8 @@
   // Accessors
   MacroAssembler* masm() { return masm_; }
 
+  VirtualFrame* frame() const { return frame_; }
+
   CodeGenState* state() { return state_; }
   void set_state(CodeGenState* state) { state_ = state; }
 
@@ -193,20 +246,6 @@
   void LoadReference(Reference* ref);
   void UnloadReference(Reference* ref);
 
-  // Support functions for accessing parameters and other operands.
-  MemOperand ParameterOperand(int index) const {
-    int num_parameters = scope()->num_parameters();
-    // index -2 corresponds to the activated closure, -1 corresponds
-    // to the receiver
-    ASSERT(-2 <= index && index < num_parameters);
-    int offset = (1 + num_parameters - index) * kPointerSize;
-    return MemOperand(fp, offset);
-  }
-
-  MemOperand FunctionOperand() const {
-    return MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset);
-  }
-
   MemOperand ContextOperand(Register context, int index) const {
     return MemOperand(context, Context::SlotOffset(index));
   }
@@ -257,6 +296,7 @@
   void ProcessDeclarations(ZoneList<Declaration*>* declarations);
 
   Handle<Code> ComputeCallInitialize(int argc);
+  Handle<Code> ComputeCallInitializeInLoop(int argc);
 
   // Declare global variables and functions in the given array of
   // name/value pairs.
@@ -341,11 +381,6 @@
   // should be generated or not.
   void RecordStatementPosition(Node* node);
 
-  // Activation frames.
-  void EnterJSFrame();
-  void ExitJSFrame();
-
-
   bool is_eval_;  // Tells whether code is generated for eval.
   Handle<Script> script_;
   List<DeferredCode*> deferred_;
@@ -355,6 +390,7 @@
 
   // Code generation state
   Scope* scope_;
+  VirtualFrame* frame_;
   Condition cc_reg_;
   CodeGenState* state_;
   bool is_inside_try_;
@@ -363,10 +399,8 @@
   // Labels
   Label function_return_;
 
+  friend class VirtualFrame;
   friend class Reference;
-  friend class Property;
-  friend class VariableProxy;
-  friend class Slot;
 
   DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
 };
diff --git a/src/codegen-ia32.cc b/src/codegen-ia32.cc
index cac0f44..230dc17 100644
--- a/src/codegen-ia32.cc
+++ b/src/codegen-ia32.cc
@@ -99,9 +99,7 @@
 }
 
 
-void VirtualFrame::Pop() {
-  __ add(Operand(esp), Immediate(kPointerSize));
-}
+void VirtualFrame::Pop() { Drop(1); }
 
 
 void VirtualFrame::Pop(Register reg) {
@@ -199,6 +197,10 @@
   VirtualFrame virtual_frame(this);
   frame_ = &virtual_frame;
   cc_reg_ = no_condition;
+
+  // Adjust for function-level loop nesting.
+  loop_nesting_ += fun->loop_nesting();
+
   {
     CodeGenState state(this);
 
@@ -267,10 +269,8 @@
         __ int3();
         __ bind(&verified_true);
       }
-
       // Update context local.
       __ mov(frame_->Context(), esi);
-      // Restore the arguments array pointer, if any.
     }
 
     // TODO(1241774): Improve this code:
@@ -310,10 +310,10 @@
     // This section stores the pointer to the arguments object that
     // was allocated and copied into above. If the address was not
     // saved to TOS, we push ecx onto the stack.
-
-    // Store the arguments object.
-    // This must happen after context initialization because
-    // the arguments object may be stored in the context
+    //
+    // Store the arguments object.  This must happen after context
+    // initialization because the arguments object may be stored in the
+    // context.
     if (arguments_object_allocated) {
       ASSERT(scope_->arguments() != NULL);
       ASSERT(scope_->arguments_shadow() != NULL);
@@ -341,18 +341,17 @@
       frame_->Pop();  // Value is no longer needed.
     }
 
-    // Generate code to 'execute' declarations and initialize
-    // functions (source elements). In case of an illegal
-    // redeclaration we need to handle that instead of processing the
-    // declarations.
+    // Generate code to 'execute' declarations and initialize functions
+    // (source elements). In case of an illegal redeclaration we need to
+    // handle that instead of processing the declarations.
     if (scope_->HasIllegalRedeclaration()) {
       Comment cmnt(masm_, "[ illegal redeclarations");
       scope_->VisitIllegalRedeclaration(this);
     } else {
       Comment cmnt(masm_, "[ declarations");
       ProcessDeclarations(scope_->declarations());
-      // Bail out if a stack-overflow exception occurred when
-      // processing declarations.
+      // Bail out if a stack-overflow exception occurred when processing
+      // declarations.
       if (HasStackOverflow()) return;
     }
 
@@ -388,11 +387,15 @@
     }
   }
 
+  // Adjust for function-level loop nesting.
+  loop_nesting_ -= fun->loop_nesting();
+
   // Code generation state must be reset.
   scope_ = NULL;
   frame_ = NULL;
   ASSERT(!has_cc());
   ASSERT(state_ == NULL);
+  ASSERT(loop_nesting() == 0);
 }
 
 
@@ -448,10 +451,11 @@
 
 
 // Loads a value on TOS. If it is a boolean value, the result may have been
-// (partially) translated into branches, or it may have set the condition code
-// register. If force_cc is set, the value is forced to set the condition code
-// register and no value is pushed. If the condition code register was set,
-// has_cc() is true and cc_reg_ contains the condition to test for 'true'.
+// (partially) translated into branches, or it may have set the condition
+// code register. If force_cc is set, the value is forced to set the
+// condition code register and no value is pushed. If the condition code
+// register was set, has_cc() is true and cc_reg_ contains the condition to
+// test for 'true'.
 void CodeGenerator::LoadCondition(Expression* x,
                                   TypeofState typeof_state,
                                   Label* true_target,
@@ -463,6 +467,14 @@
     Visit(x);
   }
   if (force_cc && !has_cc()) {
+    // Convert the TOS value to a boolean in the condition code register.
+    // Visiting an expression may possibly choose neither (a) to leave a
+    // value in the condition code register nor (b) to leave a value in TOS
+    // (eg, by compiling to only jumps to the targets).  In that case the
+    // code generated by ToBoolean is wrong because it assumes the value of
+    // the expression in TOS.  So long as there is always a value in TOS or
+    // the condition code register when control falls through to here (there
+    // is), the code generated by ToBoolean is dead and therefore safe.
     ToBoolean(true_target, false_target);
   }
   ASSERT(has_cc() || !force_cc);
@@ -476,7 +488,6 @@
 
   if (has_cc()) {
     // convert cc_reg_ into a bool
-
     Label loaded, materialize_true;
     __ j(cc_reg_, &materialize_true);
     frame_->Push(Immediate(Factory::false_value()));
@@ -604,12 +615,10 @@
   // Pop a reference from the stack while preserving TOS.
   Comment cmnt(masm_, "[ UnloadReference");
   int size = ref->size();
-  if (size <= 0) {
-    // Do nothing. No popping is necessary.
-  } else if (size == 1) {
+  if (size == 1) {
     frame_->Pop(eax);
     __ mov(frame_->Top(), eax);
-  } else {
+  } else if (size > 1) {
     frame_->Pop(eax);
     frame_->Drop(size);
     frame_->Push(eax);
@@ -663,7 +672,7 @@
   frame_->Push(eax);  // Undo the pop(eax) from above.
   ToBooleanStub stub;
   __ CallStub(&stub);
-  // Convert result (eax) to condition code.
+  // Convert the result (eax) to condition code.
   __ test(eax, Operand(eax));
 
   ASSERT(not_equal == not_zero);
@@ -1040,7 +1049,7 @@
       } else {
         deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode);
         __ mov(edx, Operand(eax));
-        __ mov(Operand(eax), Immediate(value));
+        __ mov(eax, Immediate(value));
         __ sub(eax, Operand(edx));
       }
       __ j(overflow, deferred->enter(), not_taken);
@@ -1094,7 +1103,7 @@
         __ j(not_zero, deferred->enter(), not_taken);
         // tag result and store it in TOS (eax)
         ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
-        __ lea(eax, Operand(ebx, times_2, kSmiTag));
+        __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag));
         __ bind(deferred->exit());
         frame_->Push(eax);
       }
@@ -1123,7 +1132,7 @@
         __ j(not_zero, deferred->enter(), not_taken);
         // tag result and store it in TOS (eax)
         ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
-        __ lea(eax, Operand(ebx, times_2, kSmiTag));
+        __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag));
         __ bind(deferred->exit());
         frame_->Push(eax);
       }
@@ -1264,7 +1273,7 @@
   CompareStub stub(cc_, strict_);
   // Setup parameters and call stub.
   __ mov(edx, Operand(eax));
-  __ mov(Operand(eax), Immediate(Smi::FromInt(value_)));
+  __ Set(eax, Immediate(Smi::FromInt(value_)));
   __ CallStub(&stub);
   __ cmp(eax, 0);
   // "result" is returned in the flags
@@ -1650,7 +1659,7 @@
   __ j(greater_equal, fail_label, not_taken);
 
   // 0 is placeholder.
-  __ jmp(Operand(eax, times_2, 0x0, RelocInfo::INTERNAL_REFERENCE));
+  __ jmp(Operand(eax, eax, times_1, 0x0, RelocInfo::INTERNAL_REFERENCE));
   // calculate address to overwrite later with actual address of table.
   int32_t jump_table_ref = __ pc_offset() - sizeof(int32_t);
 
@@ -2198,7 +2207,6 @@
   frame_->Pop(Operand::StaticVariable(handler_address));
   frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
   // Next_sp popped.
-  // Preserve the TOS in a register across stack manipulation.
   frame_->Push(eax);
 
   // --- Finally block ---
@@ -2694,14 +2702,15 @@
     // patch the stack to use the global proxy as 'this' in the
     // invoked function.
     LoadGlobal();
-
     // Load the arguments.
     for (int i = 0; i < args->length(); i++) {
       Load(args->at(i));
     }
 
     // Setup the receiver register and call the IC initialization code.
-    Handle<Code> stub = ComputeCallInitialize(args->length());
+    Handle<Code> stub = (loop_nesting() > 0)
+        ? ComputeCallInitializeInLoop(args->length())
+        : ComputeCallInitialize(args->length());
     __ RecordPosition(node->position());
     __ call(stub, RelocInfo::CODE_TARGET_CONTEXT);
     __ mov(esi, frame_->Context());
@@ -2745,7 +2754,9 @@
       for (int i = 0; i < args->length(); i++) Load(args->at(i));
 
       // Call the IC initialization code.
-      Handle<Code> stub = ComputeCallInitialize(args->length());
+      Handle<Code> stub = (loop_nesting() > 0)
+        ? ComputeCallInitializeInLoop(args->length())
+        : ComputeCallInitialize(args->length());
       __ RecordPosition(node->position());
       __ call(stub, RelocInfo::CODE_TARGET);
       __ mov(esi, frame_->Context());
@@ -3522,54 +3533,47 @@
   Expression* right = node->right();
   Token::Value op = node->op();
 
-  // NOTE: To make null checks efficient, we check if either left or
-  // right is the literal 'null'. If so, we optimize the code by
-  // inlining a null check instead of calling the (very) general
-  // runtime routine for checking equality.
-
+  // To make null checks efficient, we check if either left or right is the
+  // literal 'null'. If so, we optimize the code by inlining a null check
+  // instead of calling the (very) general runtime routine for checking
+  // equality.
   if (op == Token::EQ || op == Token::EQ_STRICT) {
     bool left_is_null =
-      left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
+        left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
     bool right_is_null =
-      right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
-    // The 'null' value is only equal to 'null' or 'undefined'.
+        right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
+    // The 'null' value can only be equal to 'null' or 'undefined'.
     if (left_is_null || right_is_null) {
       Load(left_is_null ? right : left);
-      Label exit, undetectable;
       frame_->Pop(eax);
       __ cmp(eax, Factory::null_value());
 
-      // The 'null' value is only equal to 'undefined' if using
-      // non-strict comparisons.
+      // The 'null' value is only equal to 'undefined' if using non-strict
+      // comparisons.
       if (op != Token::EQ_STRICT) {
-        __ j(equal, &exit);
+        __ j(equal, true_target());
+
         __ cmp(eax, Factory::undefined_value());
+        __ j(equal, true_target());
 
-        // NOTE: it can be an undetectable object.
-        __ j(equal, &exit);
         __ test(eax, Immediate(kSmiTagMask));
+        __ j(equal, false_target());
 
-        __ j(not_equal, &undetectable);
-        __ jmp(false_target());
-
-        __ bind(&undetectable);
-        __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
-        __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
-        __ and_(ecx, 1 << Map::kIsUndetectable);
-        __ cmp(ecx, 1 << Map::kIsUndetectable);
+        // It can be an undetectable object.
+        __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
+        __ movzx_b(eax, FieldOperand(eax, Map::kBitFieldOffset));
+        __ and_(eax, 1 << Map::kIsUndetectable);
+        __ cmp(eax, 1 << Map::kIsUndetectable);
       }
 
-      __ bind(&exit);
-
       cc_reg_ = equal;
       return;
     }
   }
 
-  // NOTE: To make typeof testing for natives implemented in
-  // JavaScript really efficient, we generate special code for
-  // expressions of the form: 'typeof <expression> == <string>'.
-
+  // To make typeof testing for natives implemented in JavaScript really
+  // efficient, we generate special code for expressions of the form:
+  // 'typeof <expression> == <string>'.
   UnaryOperation* operation = left->AsUnaryOperation();
   if ((op == Token::EQ || op == Token::EQ_STRICT) &&
       (operation != NULL && operation->op() == Token::TYPEOF) &&
@@ -3577,7 +3581,7 @@
        right->AsLiteral()->handle()->IsString())) {
     Handle<String> check(String::cast(*right->AsLiteral()->handle()));
 
-    // Load the operand, move it to register edx, and restore TOS.
+    // Load the operand and move it to register edx.
     LoadTypeofExpression(operation->expression());
     frame_->Pop(edx);
 
@@ -3594,7 +3598,7 @@
 
       __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
 
-      // NOTE: it might be an undetectable string object
+      // It can be an undetectable string object.
       __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
       __ and_(ecx, 1 << Map::kIsUndetectable);
       __ cmp(ecx, 1 << Map::kIsUndetectable);
@@ -3617,7 +3621,7 @@
       __ test(edx, Immediate(kSmiTagMask));
       __ j(zero, false_target());
 
-      // NOTE: it can be an undetectable object.
+      // It can be an undetectable object.
       __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
       __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
       __ and_(ecx, 1 << Map::kIsUndetectable);
@@ -3641,7 +3645,7 @@
       __ cmp(edx, Factory::null_value());
       __ j(equal, true_target());
 
-      // NOTE: it might be an undetectable object
+      // It can be an undetectable object.
       __ movzx_b(edx, FieldOperand(ecx, Map::kBitFieldOffset));
       __ and_(edx, 1 << Map::kIsUndetectable);
       __ cmp(edx, 1 << Map::kIsUndetectable);
@@ -3654,8 +3658,8 @@
       cc_reg_ = less_equal;
 
     } else {
-      // Uncommon case: Typeof testing against a string literal that
-      // is never returned from the typeof operator.
+      // Uncommon case: typeof testing against a string literal that is
+      // never returned from the typeof operator.
       __ jmp(false_target());
     }
     return;
@@ -4062,7 +4066,7 @@
       __ j(not_zero, slow);
       // Tag the result and store it in register eax.
       ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
-      __ lea(eax, Operand(eax, times_2, kSmiTag));
+      __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
       break;
 
     case Token::MOD:
@@ -4123,7 +4127,7 @@
       }
       // Tag the result and store it in register eax.
       ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
-      __ lea(eax, Operand(eax, times_2, kSmiTag));
+      __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
       break;
 
     default:
@@ -4250,7 +4254,7 @@
 
       // Tag smi result and return.
       ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
-      __ lea(eax, Operand(eax, times_2, kSmiTag));
+      __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
       __ ret(2 * kPointerSize);
 
       // All ops except SHR return a signed int32 that we load in a HeapNumber.
@@ -4984,7 +4988,7 @@
   // running with --gc-greedy set.
   if (FLAG_gc_greedy) {
     Failure* failure = Failure::RetryAfterGC(0);
-    __ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(failure)));
+    __ mov(eax, Immediate(reinterpret_cast<int32_t>(failure)));
   }
   GenerateCore(masm, &throw_normal_exception,
                &throw_out_of_memory_exception,
@@ -5002,7 +5006,7 @@
 
   // Do full GC and retry runtime call one final time.
   Failure* failure = Failure::InternalError();
-  __ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(failure)));
+  __ mov(eax, Immediate(reinterpret_cast<int32_t>(failure)));
   GenerateCore(masm,
                &throw_normal_exception,
                &throw_out_of_memory_exception,
@@ -5046,7 +5050,7 @@
   // exception field in the JSEnv and return a failure sentinel.
   ExternalReference pending_exception(Top::k_pending_exception_address);
   __ mov(Operand::StaticVariable(pending_exception), eax);
-  __ mov(eax, Handle<Failure>(Failure::Exception()));
+  __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception()));
   __ jmp(&exit);
 
   // Invoke: Link this frame into the handler chain.
@@ -5068,10 +5072,10 @@
   // stub, because the builtin stubs may not have been generated yet.
   if (is_construct) {
     ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline);
-    __ mov(Operand(edx), Immediate(construct_entry));
+    __ mov(edx, Immediate(construct_entry));
   } else {
     ExternalReference entry(Builtins::JSEntryTrampoline);
-    __ mov(Operand(edx), Immediate(entry));
+    __ mov(edx, Immediate(entry));
   }
   __ mov(edx, Operand(edx, 0));  // deref address
   __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
diff --git a/src/codegen-ia32.h b/src/codegen-ia32.h
index 39eea1b..ee6df47 100644
--- a/src/codegen-ia32.h
+++ b/src/codegen-ia32.h
@@ -121,8 +121,8 @@
     type_ = value;
   }
 
-  // The size of the reference or -1 if the reference is illegal.
-  int size() const { return type_; }
+  // The size the reference takes up on the stack.
+  int size() const { return (type_ == ILLEGAL) ? 0 : type_; }
 
   bool is_illegal() const { return type_ == ILLEGAL; }
   bool is_slot() const { return type_ == SLOT; }
@@ -320,6 +320,7 @@
   void ProcessDeclarations(ZoneList<Declaration*>* declarations);
 
   Handle<Code> ComputeCallInitialize(int argc);
+  Handle<Code> ComputeCallInitializeInLoop(int argc);
 
   // Declare global variables and functions in the given array of
   // name/value pairs.
diff --git a/src/codegen.cc b/src/codegen.cc
index 70acf65..14c20dc 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -242,6 +242,15 @@
 }
 
 
+Handle<Code> CodeGenerator::ComputeCallInitializeInLoop(int argc) {
+  // Force the creation of the corresponding stub outside loops,
+  // because it will be used when clearing the ICs later - when we
+  // don't know if we're inside a loop or not.
+  ComputeCallInitialize(argc);
+  CALL_HEAP_FUNCTION(StubCache::ComputeCallInitializeInLoop(argc), Code);
+}
+
+
 void CodeGenerator::ProcessDeclarations(ZoneList<Declaration*>* declarations) {
   int length = declarations->length();
   int globals = 0;
diff --git a/src/codegen.h b/src/codegen.h
index ca11c34..6b543eb 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -48,6 +48,7 @@
 // CodeGenerator::GenCode
 // CodeGenerator::BuildBoilerplate
 // CodeGenerator::ComputeCallInitialize
+// CodeGenerator::ComputeCallInitializeInLoop
 // CodeGenerator::ProcessDeclarations
 // CodeGenerator::DeclareGlobals
 // CodeGenerator::CheckForInlineRuntimeCall
diff --git a/src/compiler.cc b/src/compiler.cc
index 2a2bb87..eb76d38 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -66,7 +66,11 @@
 #endif
 
   // Optimize the AST.
-  Rewriter::Optimize(literal);
+  if (!Rewriter::Optimize(literal)) {
+    // Signal a stack overflow by returning a null handle.  The stack
+    // overflow exception will be thrown by the caller.
+    return Handle<Code>::null();
+  }
 
   // Generate code and return it.
   Handle<Code> result = CodeGenerator::MakeCode(literal, script, is_eval);
@@ -235,7 +239,8 @@
 }
 
 
-bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared) {
+bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
+                           int loop_nesting) {
   ZoneScope zone_scope(DELETE_ON_EXIT);
 
   // The VM is in the COMPILER state until exiting this function.
@@ -267,6 +272,9 @@
     return false;
   }
 
+  // Update the loop nesting in the function literal.
+  lit->set_loop_nesting(loop_nesting);
+
   // Measure how long it takes to do the lazy compilation; only take
   // the rest of the function into account to avoid overlap with the
   // lazy parsing statistics.
diff --git a/src/compiler.h b/src/compiler.h
index 3bbc9aa..0f4143c 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -64,7 +64,7 @@
   // Compile from function info (used for lazy compilation). Returns
   // true on success and false if the compilation resulted in a stack
   // overflow.
-  static bool CompileLazy(Handle<SharedFunctionInfo> shared);
+  static bool CompileLazy(Handle<SharedFunctionInfo> shared, int loop_nesting);
 };
 
 } }  // namespace v8::internal
diff --git a/src/constants-arm.h b/src/constants-arm.h
index a388009..c74708b 100644
--- a/src/constants-arm.h
+++ b/src/constants-arm.h
@@ -33,62 +33,74 @@
 // Defines constants and accessor classes to assemble, disassemble and
 // simulate ARM instructions.
 //
+// Section references in the code refer to the "ARM Architecture Reference
+// Manual" from July 2005 (available at http://www.arm.com/miscPDFs/14128.pdf)
+//
 // Constants for specific fields are defined in their respective named enums.
 // General constants are in an anonymous enum in class Instr.
 
 typedef unsigned char byte;
 
+// Values for the condition field as defined in section A3.2
 enum Condition {
   no_condition = -1,
-  EQ =  0,
-  NE =  1,
-  CS =  2,
-  CC =  3,
-  MI =  4,
-  PL =  5,
-  VS =  6,
-  VC =  7,
-  HI =  8,
-  LS =  9,
-  GE = 10,
-  LT = 11,
-  GT = 12,
-  LE = 13,
-  AL = 14,
-  special_condition = 15
+  EQ =  0,  // equal
+  NE =  1,  // not equal
+  CS =  2,  // carry set/unsigned higher or same
+  CC =  3,  // carry clear/unsigned lower
+  MI =  4,  // minus/negative
+  PL =  5,  // plus/positive or zero
+  VS =  6,  // overflow
+  VC =  7,  // no overflow
+  HI =  8,  // unsigned higher
+  LS =  9,  // unsigned lower or same
+  GE = 10,  // signed greater than or equal
+  LT = 11,  // signed less than
+  GT = 12,  // signed greater than
+  LE = 13,  // signed less than or equal
+  AL = 14,  // always (unconditional)
+  special_condition = 15,  // special condition (refer to section A3.2.1)
+  max_condition = 16
 };
 
 
+// Opcodes for Data-processing instructions (instructions with a type 0 and 1)
+// as defined in section A3.4
 enum Opcode {
   no_operand = -1,
-  AND =  0,
-  EOR =  1,
-  SUB =  2,
-  RSB =  3,
-  ADD =  4,
-  ADC =  5,
-  SBC =  6,
-  RSC =  7,
-  TST =  8,
-  TEQ =  9,
-  CMP = 10,
-  CMN = 11,
-  ORR = 12,
-  MOV = 13,
-  BIC = 14,
-  MVN = 15
+  AND =  0,  // Logical AND
+  EOR =  1,  // Logical Exclusive OR
+  SUB =  2,  // Subtract
+  RSB =  3,  // Reverse Subtract
+  ADD =  4,  // Add
+  ADC =  5,  // Add with Carry
+  SBC =  6,  // Subtract with Carry
+  RSC =  7,  // Reverse Subtract with Carry
+  TST =  8,  // Test
+  TEQ =  9,  // Test Equivalence
+  CMP = 10,  // Compare
+  CMN = 11,  // Compare Negated
+  ORR = 12,  // Logical (inclusive) OR
+  MOV = 13,  // Move
+  BIC = 14,  // Bit Clear
+  MVN = 15,  // Move Not
+  max_operand = 16
 };
 
 
+// Shifter types for Data-processing operands as defined in section A5.1.2.
 enum Shift {
   no_shift = -1,
-  LSL = 0,
-  LSR = 1,
-  ASR = 2,
-  ROR = 3
+  LSL = 0,  // Logical shift left
+  LSR = 1,  // Logical shift right
+  ASR = 2,  // Arithmetic shift right
+  ROR = 3,  // Rotate right
+  max_shift = 4
 };
 
 
+// Special Software Interrupt codes when used in the presence of the ARM
+// simulator.
 enum SoftwareInterruptCodes {
   // transition to C code
   call_rt_r5 = 0x10,
@@ -102,7 +114,17 @@
 
 
 // The class Instr enables access to individual fields defined in the ARM
-// architecture.
+// architecture instruction set encoding as described in figure A3-1.
+//
+// Example: Test whether the instruction at ptr does set the condition code
+// bits.
+//
+// bool InstructionSetsConditionCodes(byte* ptr) {
+//   Instr *instr = Instr::At(ptr);
+//   int type = instr->TypeField();
+//   return ((type == 0) || (type == 1)) && instr->HasS();
+// }
+//
 class Instr {
  public:
   enum {
@@ -110,25 +132,29 @@
     kPCReadOffset = 8
   };
 
-  // Get the raw instruction bits
+  // Get the raw instruction bits.
   inline instr_t InstructionBits() const {
     return *reinterpret_cast<const instr_t*>(this);
   }
 
+  // Set the raw instruction bits to value.
   inline void SetInstructionBits(instr_t value) {
     *reinterpret_cast<instr_t*>(this) = value;
   }
 
+  // Read one particular bit out of the instruction bits.
   inline int Bit(int nr) const {
     return (InstructionBits() >> nr) & 1;
   }
 
+  // Read a bit field out of the instruction bits.
   inline int Bits(int hi, int lo) const {
     return (InstructionBits() >> lo) & ((2 << (hi - lo)) - 1);
   }
 
 
   // Accessors for the different named fields used in the ARM encoding.
+  // The naming of these accessor corresponds to figure A3-1.
   // Generally applicable fields
   inline Condition ConditionField() const {
     return static_cast<Condition>(Bits(31, 28));
diff --git a/src/d8.cc b/src/d8.cc
index af6eb4c..480d4ae 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -235,6 +235,19 @@
   utility_context_->SetSecurityToken(Undefined());
   Context::Scope utility_scope(utility_context_);
 
+  i::JSArguments js_args = i::FLAG_js_arguments;
+  i::Handle<i::FixedArray> arguments_array =
+      i::Factory::NewFixedArray(js_args.argc());
+  for (int j = 0; j < js_args.argc(); j++) {
+    i::Handle<i::String> arg =
+        i::Factory::NewStringFromUtf8(i::CStrVector(js_args[j]));
+    arguments_array->set(j, *arg);
+  }
+  i::Handle<i::JSArray> arguments_jsarray =
+      i::Factory::NewJSArrayWithElements(arguments_array);
+  global_template->Set(String::New("arguments"),
+                       Utils::ToLocal(arguments_jsarray));
+
   // Install the debugger object in the utility scope
   i::Debug::Load();
   i::Debug::debug_context()->set_security_token(i::Heap::undefined_value());
@@ -318,6 +331,9 @@
 
 int Shell::Main(int argc, char* argv[]) {
   i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
+  if (i::FLAG_help) {
+    return 1;
+  }
   Initialize();
   bool run_shell = (argc == 1);
   Context::Scope context_scope(evaluation_context_);
diff --git a/src/date-delay.js b/src/date-delay.js
index 3531266..c1b19e5 100644
--- a/src/date-delay.js
+++ b/src/date-delay.js
@@ -50,6 +50,8 @@
 // ECMA 262 - 5.2
 function Modulo(value, remainder) {
   var mod = value % remainder;
+  // Guard against returning -0.
+  if (mod == 0) return 0;
   return mod >= 0 ? mod : mod + remainder;
 }
 
diff --git a/src/debug-delay.js b/src/debug-delay.js
index 783e4b7..4d583b7 100644
--- a/src/debug-delay.js
+++ b/src/debug-delay.js
@@ -357,15 +357,6 @@
 }
 
 
-// Function called from the runtime to handle a debug request receiced from the
-// debugger. When this function is called the debugger is in the broken state
-// reflected by the exec_state parameter. When pending requests are handled the
-// parameter stopping indicate the expected running state.
-function ProcessDebugRequest(exec_state, request, stopping) {
-  return exec_state.debugCommandProcessor().processDebugJSONRequest(request, stopping);
-}
-
-
 Debug.addListener = function(listener, opt_data) {
   if (!IS_FUNCTION(listener)) throw new Error('Parameters have wrong types.');
   %AddDebugEventListener(listener, opt_data);
diff --git a/src/debug.cc b/src/debug.cc
index 33fafe7..7acc117 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -1135,7 +1135,7 @@
 
 bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) {
   if (shared->is_compiled()) return true;
-  return CompileLazyShared(shared, CLEAR_EXCEPTION);
+  return CompileLazyShared(shared, CLEAR_EXCEPTION, 0);
 }
 
 
@@ -1371,35 +1371,6 @@
 }
 
 
-Handle<String> Debugger::ProcessRequest(Handle<Object> exec_state,
-                                        Handle<Object> request,
-                                        bool stopped) {
-  // Get the function ProcessDebugRequest (declared in debug.js).
-  Handle<JSFunction> process_denbug_request =
-    Handle<JSFunction>(JSFunction::cast(
-    Debug::debug_context()->global()->GetProperty(
-        *Factory::LookupAsciiSymbol("ProcessDebugRequest"))));
-
-  // Call ProcessDebugRequest expect String result. The ProcessDebugRequest
-  // will never throw an exception (see debug.js).
-  bool caught_exception;
-  const int argc = 3;
-  Object** argv[argc] = { exec_state.location(),
-                          request.location(),
-                          stopped ? Factory::true_value().location() :
-                                    Factory::false_value().location()};
-  Handle<Object> result = Execution::TryCall(process_denbug_request,
-                                             Factory::undefined_value(),
-                                             argc, argv,
-                                             &caught_exception);
-  if (caught_exception) {
-    return Factory::empty_symbol();
-  }
-
-  return Handle<String>::cast(result);
-}
-
-
 void Debugger::OnException(Handle<Object> exception, bool uncaught) {
   HandleScope scope;
 
diff --git a/src/debug.h b/src/debug.h
index 69e2aaa..6833982 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -346,9 +346,6 @@
   static Handle<Object> MakeCompileEvent(Handle<Script> script,
                                          Handle<Object> script_function,
                                          bool* caught_exception);
-  static Handle<String> ProcessRequest(Handle<Object> exec_state,
-                                       Handle<Object> request,
-                                       bool stopped);
   static void OnDebugBreak(Handle<Object> break_points_hit);
   static void OnException(Handle<Object> exception, bool uncaught);
   static void OnBeforeCompile(Handle<Script> script);
diff --git a/src/disasm-arm.cc b/src/disasm-arm.cc
index 4aa9b78..ff7b9ad 100644
--- a/src/disasm-arm.cc
+++ b/src/disasm-arm.cc
@@ -25,6 +25,28 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// A Disassembler object is used to disassemble a block of code instruction by
+// instruction. The default implementation of the NameConverter object can be
+// overriden to modify register names or to do symbol lookup on addresses.
+//
+// The example below will disassemble a block of code and print it to stdout.
+//
+//   NameConverter converter;
+//   Disassembler d(converter);
+//   for (byte* pc = begin; pc < end;) {
+//     char buffer[128];
+//     buffer[0] = '\0';
+//     byte* prev_pc = pc;
+//     pc += d.InstructionDecode(buffer, sizeof buffer, pc);
+//     printf("%p    %08x      %s\n",
+//            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
+//   }
+//
+// The Disassembler class also has a convenience method to disassemble a block
+// of code into a FILE*, meaning that the above functionality could also be
+// achieved by just calling Disassembler::Disassemble(stdout, begin, end);
+
+
 #include <assert.h>
 #include <stdio.h>
 #include <stdarg.h>
@@ -39,6 +61,7 @@
 #include "macro-assembler.h"
 #include "platform.h"
 
+
 namespace assembler { namespace arm {
 
 namespace v8i = v8::internal;
@@ -66,33 +89,49 @@
   int InstructionDecode(byte* instruction);
 
  private:
-  const disasm::NameConverter& converter_;
-  v8::internal::Vector<char> out_buffer_;
-  int out_buffer_pos_;
-
+  // Bottleneck functions to print into the out_buffer.
   void PrintChar(const char ch);
   void Print(const char* str);
 
+  // Printing of common values.
   void PrintRegister(int reg);
   void PrintCondition(Instr* instr);
   void PrintShiftRm(Instr* instr);
   void PrintShiftImm(Instr* instr);
+  void PrintPU(Instr* instr);
+  void PrintSoftwareInterrupt(SoftwareInterruptCodes swi);
 
+  // Handle formatting of instructions and their options.
+  int FormatRegister(Instr* instr, const char* option);
   int FormatOption(Instr* instr, const char* option);
   void Format(Instr* instr, const char* format);
   void Unknown(Instr* instr);
 
-  void DecodeType0(Instr* instr);
-  void DecodeType1(Instr* instr);
+  // Each of these functions decodes one particular instruction type, a 3-bit
+  // field in the instruction encoding.
+  // Types 0 and 1 are combined as they are largely the same except for the way
+  // they interpret the shifter operand.
+  void DecodeType01(Instr* instr);
   void DecodeType2(Instr* instr);
   void DecodeType3(Instr* instr);
   void DecodeType4(Instr* instr);
   void DecodeType5(Instr* instr);
   void DecodeType6(Instr* instr);
   void DecodeType7(Instr* instr);
+
+  const disasm::NameConverter& converter_;
+  v8::internal::Vector<char> out_buffer_;
+  int out_buffer_pos_;
+
+  DISALLOW_COPY_AND_ASSIGN(Decoder);
 };
 
 
+// Support for assertions in the Decoder formatting functions.
+#define STRING_STARTS_WITH(string, compare_string) \
+  (strncmp(string, compare_string, strlen(compare_string)) == 0)
+
+
 // Append the ch to the output buffer.
 void Decoder::PrintChar(const char ch) {
   out_buffer_[out_buffer_pos_++] = ch;
@@ -102,7 +141,7 @@
 // Append the str to the output buffer.
 void Decoder::Print(const char* str) {
   char cur = *str++;
-  while (cur != 0 && (out_buffer_pos_ < (out_buffer_.length()-1))) {
+  while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
     PrintChar(cur);
     cur = *str++;
   }
@@ -110,9 +149,11 @@
 }
 
 
-static const char* cond_names[16] = {
-"eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
-"hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
+// These condition names are defined in a way to match the native disassembler
+// formatting. See for example the command "objdump -d <binary file>".
+static const char* cond_names[max_condition] = {
+  "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
+  "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
 };
 
 
@@ -128,7 +169,9 @@
 }
 
 
-static const char* shift_names[4] = {
+// These shift names are defined in a way to match the native disassembler
+// formatting. See for example the command "objdump -d <binary file>".
+static const char* shift_names[max_shift] = {
   "lsl", "lsr", "asr", "ror"
 };
 
@@ -178,6 +221,100 @@
 }
 
 
+// Print PU formatting to reduce complexity of FormatOption.
+void Decoder::PrintPU(Instr* instr) {
+  switch (instr->PUField()) {
+    case 0: {
+      Print("da");
+      break;
+    }
+    case 1: {
+      Print("ia");
+      break;
+    }
+    case 2: {
+      Print("db");
+      break;
+    }
+    case 3: {
+      Print("ib");
+      break;
+    }
+    default: {
+      UNREACHABLE();
+      break;
+    }
+  }
+}
+
+
+// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
+// the FormatOption method.
+void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) {
+  switch (swi) {
+    case call_rt_r5:
+      Print("call_rt_r5");
+      return;
+    case call_rt_r2:
+      Print("call_rt_r2");
+      return;
+    case break_point:
+      Print("break_point");
+      return;
+    default:
+      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                           "%d",
+                                           swi);
+      return;
+  }
+}
+
+
+// Handle all register based formatting in this function to reduce the
+// complexity of FormatOption.
+int Decoder::FormatRegister(Instr* instr, const char* format) {
+  ASSERT(format[0] == 'r');
+  if (format[1] == 'n') {  // 'rn: Rn register
+    int reg = instr->RnField();
+    PrintRegister(reg);
+    return 2;
+  } else if (format[1] == 'd') {  // 'rd: Rd register
+    int reg = instr->RdField();
+    PrintRegister(reg);
+    return 2;
+  } else if (format[1] == 's') {  // 'rs: Rs register
+    int reg = instr->RsField();
+    PrintRegister(reg);
+    return 2;
+  } else if (format[1] == 'm') {  // 'rm: Rm register
+    int reg = instr->RmField();
+    PrintRegister(reg);
+    return 2;
+  } else if (format[1] == 'l') {
+    // 'rlist: register list for load and store multiple instructions
+    ASSERT(STRING_STARTS_WITH(format, "rlist"));
+    int rlist = instr->RlistField();
+    int reg = 0;
+    Print("{");
+    // Print register list in ascending order, by scanning the bit mask.
+    while (rlist != 0) {
+      if ((rlist & 1) != 0) {
+        PrintRegister(reg);
+        if ((rlist >> 1) != 0) {
+          Print(", ");
+        }
+      }
+      reg++;
+      rlist >>= 1;
+    }
+    Print("}");
+    return 5;
+  }
+  UNREACHABLE();
+  return -1;
+}
+
+
 // FormatOption takes a formatting string and interprets it based on
 // the current instructions. The format string points to the first
 // character of the option string (the option escape has already been
@@ -192,20 +329,17 @@
         Print("la");
       }
       return 1;
-      break;
     }
     case 'b': {  // 'b: byte loads or stores
       if (instr->HasB()) {
         Print("b");
       }
       return 1;
-      break;
     }
     case 'c': {  // 'cond: conditional execution
-      ASSERT((format[1] == 'o') && (format[2] == 'n') && (format[3] =='d'));
+      ASSERT(STRING_STARTS_WITH(format, "cond"));
       PrintCondition(instr);
       return 4;
-      break;
     }
     case 'h': {  // 'h: halfword operation for extra loads and stores
       if (instr->HasH()) {
@@ -214,172 +348,89 @@
         Print("b");
       }
       return 1;
-      break;
-    }
-    case 'i': {  // 'imm: immediate value for data processing instructions
-      ASSERT((format[1] == 'm') && (format[2] == 'm'));
-      PrintShiftImm(instr);
-      return 3;
-      break;
     }
     case 'l': {  // 'l: branch and link
       if (instr->HasLink()) {
         Print("l");
       }
       return 1;
-      break;
     }
-    case 'm': {  // 'msg: for simulator break instructions
-      if (format[1] == 'e') {
-        ASSERT((format[2] == 'm') && (format[3] == 'o') && (format[4] == 'p'));
+    case 'm': {
+      if (format[1] == 'e') {  // 'memop: load/store instructions
+        ASSERT(STRING_STARTS_WITH(format, "memop"));
         if (instr->HasL()) {
           Print("ldr");
         } else {
           Print("str");
         }
         return 5;
-      } else {
-        ASSERT(format[1] == 's' && format[2] == 'g');
-        byte* str =
-            reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
-        out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                             "%s", converter_.NameInCode(str));
-        return 3;
       }
-      break;
+      // 'msg: for simulator break instructions
+      ASSERT(STRING_STARTS_WITH(format, "msg"));
+      byte* str =
+          reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
+      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                           "%s", converter_.NameInCode(str));
+      return 3;
     }
     case 'o': {
-      ASSERT(format[1] == 'f' && format[2] == 'f');
       if (format[3] == '1') {
         // 'off12: 12-bit offset for load and store instructions
-        ASSERT(format[4] == '2');
+        ASSERT(STRING_STARTS_WITH(format, "off12"));
         out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
                                              "%d", instr->Offset12Field());
         return 5;
-      } else {
-        // 'off8: 8-bit offset for extra load and store instructions
-        ASSERT(format[3] == '8');
-        int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
-        out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                             "%d", offs8);
-        return 4;
       }
-      break;
+      // 'off8: 8-bit offset for extra load and store instructions
+      ASSERT(STRING_STARTS_WITH(format, "off8"));
+      int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
+      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                           "%d", offs8);
+      return 4;
     }
     case 'p': {  // 'pu: P and U bits for load and store instructions
-      ASSERT(format[1] == 'u');
-      switch (instr->PUField()) {
-        case 0: {
-          Print("da");
-          break;
-        }
-        case 1: {
-          Print("ia");
-          break;
-        }
-        case 2: {
-          Print("db");
-          break;
-        }
-        case 3: {
-          Print("ib");
-          break;
-        }
-        default: {
-          UNREACHABLE();
-          break;
-        }
-      }
+      ASSERT(STRING_STARTS_WITH(format, "pu"));
+      PrintPU(instr);
       return 2;
-      break;
     }
     case 'r': {
-      if (format[1] == 'n') {  // 'rn: Rn register
-        int reg = instr->RnField();
-        PrintRegister(reg);
-        return 2;
-      } else if (format[1] == 'd') {  // 'rd: Rd register
-        int reg = instr->RdField();
-        PrintRegister(reg);
-        return 2;
-      } else if (format[1] == 's') {  // 'rs: Rs register
-        int reg = instr->RsField();
-        PrintRegister(reg);
-        return 2;
-      } else if (format[1] == 'm') {  // 'rm: Rm register
-        int reg = instr->RmField();
-        PrintRegister(reg);
-        return 2;
-      } else if (format[1] == 'l') {
-        // 'rlist: register list for load and store multiple instructions
-        ASSERT(format[2] == 'i' && format[3] == 's' && format[4] == 't');
-        int rlist = instr->RlistField();
-        int reg = 0;
-        Print("{");
-        while (rlist != 0) {
-          if ((rlist & 1) != 0) {
-            PrintRegister(reg);
-            if ((rlist >> 1) != 0) {
-              Print(", ");
-            }
-          }
-          reg++;
-          rlist >>= 1;
-        }
-        Print("}");
-        return 5;
-      } else {
-        UNREACHABLE();
-      }
-      UNREACHABLE();
-      return -1;
-      break;
+      return FormatRegister(instr, format);
     }
     case 's': {
-      if (format[1] == 'h') {  // 'shift_rm: register shift operands
-        ASSERT(format[2] == 'i' && format[3] == 'f' && format[4] == 't'
-               && format[5] == '_' && format[6] == 'r' && format[7] == 'm');
-        PrintShiftRm(instr);
-        return 8;
-      } else if (format[1] == 'w') {
-        ASSERT(format[2] == 'i');
-        SoftwareInterruptCodes swi = instr->SwiField();
-        switch (swi) {
-          case call_rt_r5:
-            Print("call_rt_r5");
-            break;
-          case call_rt_r2:
-            Print("call_rt_r2");
-            break;
-          case break_point:
-            Print("break_point");
-            break;
-          default:
-            out_buffer_pos_ += v8i::OS::SNPrintF(
-                out_buffer_ + out_buffer_pos_,
-                "%d",
-                swi);
-            break;
+      if (format[1] == 'h') {  // 'shift_op or 'shift_rm
+        if (format[6] == 'o') {  // 'shift_op
+          ASSERT(STRING_STARTS_WITH(format, "shift_op"));
+          if (instr->TypeField() == 0) {
+            PrintShiftRm(instr);
+          } else {
+            ASSERT(instr->TypeField() == 1);
+            PrintShiftImm(instr);
+          }
+          return 8;
+        } else {  // 'shift_rm
+          ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
+          PrintShiftRm(instr);
+          return 8;
         }
+      } else if (format[1] == 'w') {  // 'swi
+        ASSERT(STRING_STARTS_WITH(format, "swi"));
+        PrintSoftwareInterrupt(instr->SwiField());
         return 3;
       } else if (format[1] == 'i') {  // 'sign: signed extra loads and stores
-        ASSERT(format[2] == 'g' && format[3] == 'n');
+        ASSERT(STRING_STARTS_WITH(format, "sign"));
         if (instr->HasSign()) {
           Print("s");
         }
         return 4;
-        break;
-      } else {  // 's: S field of data processing instructions
-        if (instr->HasS()) {
-          Print("s");
-        }
-        return 1;
       }
-      break;
+      // 's: S field of data processing instructions
+      if (instr->HasS()) {
+        Print("s");
+      }
+      return 1;
     }
     case 't': {  // 'target: target of branch instructions
-      ASSERT(format[1] == 'a' && format[2] == 'r' && format[3] == 'g'
-             && format[4] == 'e' && format[5] == 't');
+      ASSERT(STRING_STARTS_WITH(format, "target"));
       int off = (instr->SImmed24Field() << 2) + 8;
       out_buffer_pos_ += v8i::OS::SNPrintF(
           out_buffer_ + out_buffer_pos_,
@@ -387,7 +438,6 @@
           off,
           converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
       return 6;
-      break;
     }
     case 'u': {  // 'u: signed or unsigned multiplies
       if (instr->Bit(22) == 0) {
@@ -396,14 +446,12 @@
         Print("s");
       }
       return 1;
-      break;
     }
     case 'w': {  // 'w: W field of load and store instructions
       if (instr->HasW()) {
         Print("!");
       }
       return 1;
-      break;
     }
     default: {
       UNREACHABLE();
@@ -439,8 +487,9 @@
 }
 
 
-void Decoder::DecodeType0(Instr* instr) {
-  if (instr->IsSpecialType0()) {
+void Decoder::DecodeType01(Instr* instr) {
+  int type = instr->TypeField();
+  if ((type == 0) && instr->IsSpecialType0()) {
     // multiply instruction or extra loads and stores
     if (instr->Bits(7, 4) == 9) {
       if (instr->Bit(24) == 0) {
@@ -503,87 +552,83 @@
   } else {
     switch (instr->OpcodeField()) {
       case AND: {
-        Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
+        Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
         break;
       }
       case EOR: {
-        Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm");
+        Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
         break;
       }
       case SUB: {
-        Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
+        Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
         break;
       }
       case RSB: {
-        Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
+        Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
         break;
       }
       case ADD: {
-        Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
+        Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
         break;
       }
       case ADC: {
-        Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
+        Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
         break;
       }
       case SBC: {
-        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
+        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
         break;
       }
       case RSC: {
-        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
+        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
         break;
       }
       case TST: {
         if (instr->HasS()) {
-          Format(instr, "tst'cond 'rn, 'shift_rm");
+          Format(instr, "tst'cond 'rn, 'shift_op");
         } else {
           Unknown(instr);  // not used by V8
-          return;
         }
         break;
       }
       case TEQ: {
         if (instr->HasS()) {
-          Format(instr, "teq'cond 'rn, 'shift_rm");
+          Format(instr, "teq'cond 'rn, 'shift_op");
         } else {
           Unknown(instr);  // not used by V8
-          return;
         }
         break;
       }
       case CMP: {
         if (instr->HasS()) {
-          Format(instr, "cmp'cond 'rn, 'shift_rm");
+          Format(instr, "cmp'cond 'rn, 'shift_op");
         } else {
           Unknown(instr);  // not used by V8
-          return;
         }
         break;
       }
       case CMN: {
         if (instr->HasS()) {
-          Format(instr, "cmn'cond 'rn, 'shift_rm");
+          Format(instr, "cmn'cond 'rn, 'shift_op");
         } else {
           Unknown(instr);  // not used by V8
-          return;
         }
         break;
       }
       case ORR: {
-        Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
+        Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
         break;
       }
       case MOV: {
-        Format(instr, "mov'cond's 'rd, 'shift_rm");
+        Format(instr, "mov'cond's 'rd, 'shift_op");
         break;
       }
       case BIC: {
-        Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm");
+        Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
         break;
       }
       case MVN: {
-        Format(instr, "mvn'cond's 'rd, 'shift_rm");
+        Format(instr, "mvn'cond's 'rd, 'shift_op");
         break;
       }
       default: {
@@ -596,107 +641,11 @@
 }
 
 
-void Decoder::DecodeType1(Instr* instr) {
-  switch (instr->OpcodeField()) {
-    case AND: {
-      Format(instr, "and'cond's 'rd, 'rn, 'imm");
-      break;
-    }
-    case EOR: {
-      Format(instr, "eor'cond's 'rd, 'rn, 'imm");
-      break;
-    }
-    case SUB: {
-      Format(instr, "sub'cond's 'rd, 'rn, 'imm");
-      break;
-    }
-    case RSB: {
-      Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
-      break;
-    }
-    case ADD: {
-      Format(instr, "add'cond's 'rd, 'rn, 'imm");
-      break;
-    }
-    case ADC: {
-      Format(instr, "adc'cond's 'rd, 'rn, 'imm");
-      break;
-    }
-    case SBC: {
-      Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
-      break;
-    }
-    case RSC: {
-      Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
-      break;
-    }
-    case TST: {
-      if (instr->HasS()) {
-        Format(instr, "tst'cond 'rn, 'imm");
-      } else {
-        Unknown(instr);  // not used by V8
-        return;
-      }
-      break;
-    }
-    case TEQ: {
-      if (instr->HasS()) {
-        Format(instr, "teq'cond 'rn, 'imm");
-      } else {
-        Unknown(instr);  // not used by V8
-        return;
-      }
-      break;
-    }
-    case CMP: {
-      if (instr->HasS()) {
-        Format(instr, "cmp'cond 'rn, 'imm");
-      } else {
-        Unknown(instr);  // not used by V8
-        return;
-      }
-      break;
-    }
-    case CMN: {
-      if (instr->HasS()) {
-        Format(instr, "cmn'cond 'rn, 'imm");
-      } else {
-        Unknown(instr);  // not used by V8
-        return;
-      }
-      break;
-    }
-    case ORR: {
-      Format(instr, "orr'cond's 'rd, 'rn, 'imm");
-      break;
-    }
-    case MOV: {
-      Format(instr, "mov'cond's 'rd, 'imm");
-      break;
-    }
-    case BIC: {
-      Format(instr, "bic'cond's 'rd, 'rn, 'imm");
-      break;
-    }
-    case MVN: {
-      Format(instr, "mvn'cond's 'rd, 'imm");
-      break;
-    }
-    default: {
-      // The Opcode field is a 4-bit field.
-      UNREACHABLE();
-      break;
-    }
-  }
-}
-
-
 void Decoder::DecodeType2(Instr* instr) {
   switch (instr->PUField()) {
     case 0: {
       if (instr->HasW()) {
         Unknown(instr);  // not used in V8
-        return;
       }
       Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
       break;
@@ -704,7 +653,6 @@
     case 1: {
       if (instr->HasW()) {
         Unknown(instr);  // not used in V8
-        return;
       }
       Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
       break;
@@ -798,12 +746,9 @@
     return Instr::kInstrSize;
   }
   switch (instr->TypeField()) {
-    case 0: {
-      DecodeType0(instr);
-      break;
-    }
+    case 0:
     case 1: {
-      DecodeType1(instr);
+      DecodeType01(instr);
       break;
     }
     case 2: {
@@ -848,8 +793,15 @@
 
 namespace disasm {
 
-static const char* reg_names[16] = {
-  "r0", "r1", "r2" , "r3" , "r4" , "r5" , "r6" , "r7" ,
+namespace v8i = v8::internal;
+
+
+static const int kMaxRegisters = 16;
+
+// These register names are defined in a way to match the native disassembler
+// formatting. See for example the command "objdump -d <binary file>".
+static const char* reg_names[kMaxRegisters] = {
+  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
   "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc",
 };
 
@@ -868,7 +820,7 @@
 
 const char* NameConverter::NameOfCPURegister(int reg) const {
   const char* result;
-  if ((0 <= reg) && (reg < 16)) {
+  if ((0 <= reg) && (reg < kMaxRegisters)) {
     result = reg_names[reg];
   } else {
     result = "noreg";
@@ -892,11 +844,6 @@
 
 //------------------------------------------------------------------------------
 
-static NameConverter defaultConverter;
-
-Disassembler::Disassembler() : converter_(defaultConverter) {}
-
-
 Disassembler::Disassembler(const NameConverter& converter)
     : converter_(converter) {}
 
@@ -922,7 +869,8 @@
 
 
 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
-  Disassembler d;
+  NameConverter converter;
+  Disassembler d(converter);
   for (byte* pc = begin; pc < end;) {
     v8::internal::EmbeddedVector<char, 128> buffer;
     buffer[0] = '\0';
diff --git a/src/disasm-ia32.cc b/src/disasm-ia32.cc
index 1648d69..1764e52 100644
--- a/src/disasm-ia32.cc
+++ b/src/disasm-ia32.cc
@@ -1095,11 +1095,6 @@
 
 //------------------------------------------------------------------------------
 
-static NameConverter defaultConverter;
-
-Disassembler::Disassembler() : converter_(defaultConverter) {}
-
-
 Disassembler::Disassembler(const NameConverter& converter)
     : converter_(converter) {}
 
@@ -1119,7 +1114,8 @@
 
 
 /*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
-  Disassembler d;
+  NameConverter converter;
+  Disassembler d(converter);
   for (byte* pc = begin; pc < end;) {
     v8::internal::EmbeddedVector<char, 128> buffer;
     buffer[0] = '\0';
diff --git a/src/disasm.h b/src/disasm.h
index 1b72ee1..1fd5519 100644
--- a/src/disasm.h
+++ b/src/disasm.h
@@ -49,9 +49,6 @@
 // A generic Disassembler interface
 class Disassembler {
  public:
-  // Uses default NameConverter.
-  Disassembler();
-
   // Caller deallocates converter.
   explicit Disassembler(const NameConverter& converter);
 
@@ -70,6 +67,8 @@
   static void Disassemble(FILE* f, byte* begin, byte* end);
  private:
   const NameConverter& converter_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Disassembler);
 };
 
 }  // namespace disasm
diff --git a/src/disassembler.cc b/src/disassembler.cc
index 12183d5..53f594f 100644
--- a/src/disassembler.cc
+++ b/src/disassembler.cc
@@ -217,7 +217,7 @@
         HeapStringAllocator allocator;
         StringStream accumulator(&allocator);
         relocinfo.target_object()->ShortPrint(&accumulator);
-        SmartPointer<char> obj_name = accumulator.ToCString();
+        SmartPointer<const char> obj_name = accumulator.ToCString();
         out.AddFormatted("    ;; object: %s", *obj_name);
       } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
         const char* reference_name =
diff --git a/src/execution.cc b/src/execution.cc
index 0598ad7..9f5bd83 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -96,16 +96,14 @@
   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 (*has_pending_exception) {
+    // 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();
     }
+    return Handle<Object>();
   }
 
   return Handle<Object>(value);
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index c082a78..5c96429 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -69,10 +69,27 @@
 #error No mode supplied when including flags.defs
 #endif
 
+#ifdef FLAG_MODE_DECLARE
+// Structure used to hold a collection of arguments to the JavaScript code.
+struct JSArguments {
+public:
+  JSArguments();
+  JSArguments(int argc, const char** argv);
+  int argc() const;
+  const char** argv();
+  const char*& operator[](int idx);
+  JSArguments& operator=(JSArguments args);
+private:
+  int argc_;
+  const char** argv_;
+};
+#endif
+
 #define DEFINE_bool(nam, def, cmt) FLAG(BOOL, bool, nam, def, cmt)
 #define DEFINE_int(nam, def, cmt) FLAG(INT, int, nam, def, cmt)
 #define DEFINE_float(nam, def, cmt) FLAG(FLOAT, double, nam, def, cmt)
 #define DEFINE_string(nam, def, cmt) FLAG(STRING, const char*, nam, def, cmt)
+#define DEFINE_args(nam, def, cmt) FLAG(ARGS, JSArguments, nam, def, cmt)
 
 //
 // Flags in all modes.
@@ -200,7 +217,10 @@
 // Dev shell flags
 //
 
+DEFINE_bool(help, false, "Print usage message, including flags, on console")
 DEFINE_bool(dump_counters, false, "Dump counters on exit")
+DEFINE_args(js_arguments, JSArguments(),
+            "Pass all remaining arguments to the script. Alias for \"--\".")
 
 //
 // Debug only flags
diff --git a/src/flags.cc b/src/flags.cc
index 73bb855..48b4ef7 100644
--- a/src/flags.cc
+++ b/src/flags.cc
@@ -31,6 +31,9 @@
 #include "v8.h"
 
 #include "platform.h"
+#include "smart-pointer.h"
+#include "string-stream.h"
+
 
 namespace v8 { namespace internal {
 
@@ -48,7 +51,7 @@
 // to the actual flag, default value, comment, etc.  This is designed to be POD
 // initialized as to avoid requiring static constructors.
 struct Flag {
-  enum FlagType { TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING };
+  enum FlagType { TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARGS };
 
   FlagType type_;           // What type of flag, bool, int, or string.
   const char* name_;        // Name of the flag, ex "my_flag".
@@ -82,6 +85,11 @@
     return reinterpret_cast<const char**>(valptr_);
   }
 
+  JSArguments* args_variable() const {
+    ASSERT(type_ == TYPE_ARGS);
+    return reinterpret_cast<JSArguments*>(valptr_);
+  }
+
   bool bool_default() const {
     ASSERT(type_ == TYPE_BOOL);
     return *reinterpret_cast<const bool*>(defptr_);
@@ -102,6 +110,11 @@
     return *reinterpret_cast<const char* const *>(defptr_);
   }
 
+  JSArguments args_default() const {
+    ASSERT(type_ == TYPE_ARGS);
+    return *reinterpret_cast<const JSArguments*>(defptr_);
+  }
+
   // Compare this flag's current value against the default.
   bool IsDefault() const {
     switch (type_) {
@@ -111,12 +124,15 @@
         return *int_variable() == int_default();
       case TYPE_FLOAT:
         return *float_variable() == float_default();
-      case TYPE_STRING:
+      case TYPE_STRING: {
         const char* str1 = *string_variable();
         const char* str2 = string_default();
         if (str2 == NULL) return str1 == NULL;
         if (str1 == NULL) return str2 == NULL;
         return strcmp(str1, str2) == 0;
+      }
+      case TYPE_ARGS:
+        return args_variable()->argc() == 0;
     }
     UNREACHABLE();
     return true;
@@ -137,6 +153,9 @@
       case TYPE_STRING:
         *string_variable() = string_default();
         break;
+      case TYPE_ARGS:
+        *args_variable() = args_default();
+        break;
     }
   }
 };
@@ -157,67 +176,81 @@
     case Flag::TYPE_INT: return "int";
     case Flag::TYPE_FLOAT: return "float";
     case Flag::TYPE_STRING: return "string";
+    case Flag::TYPE_ARGS: return "arguments";
   }
   UNREACHABLE();
   return NULL;
 }
 
 
-static char* ToString(Flag* flag) {
-  Vector<char> value;
+static SmartPointer<const char> ToString(Flag* flag) {
+  HeapStringAllocator string_allocator;
+  StringStream buffer(&string_allocator);
   switch (flag->type()) {
     case Flag::TYPE_BOOL:
-      value = Vector<char>::New(6);
-      OS::SNPrintF(value, "%s", (*flag->bool_variable() ? "true" : "false"));
+      buffer.Add("%s", (*flag->bool_variable() ? "true" : "false"));
       break;
     case Flag::TYPE_INT:
-      value = Vector<char>::New(12);
-      OS::SNPrintF(value, "%d", *flag->int_variable());
+      buffer.Add("%d", *flag->int_variable());
       break;
     case Flag::TYPE_FLOAT:
-      value = Vector<char>::New(20);
-      OS::SNPrintF(value, "%f", *flag->float_variable());
+      buffer.Add("%f", FmtElm(*flag->float_variable()));
       break;
-    case Flag::TYPE_STRING:
+    case Flag::TYPE_STRING: {
       const char* str = *flag->string_variable();
-      if (str) {
-        int length = strlen(str) + 1;
-        value = Vector<char>::New(length);
-        OS::SNPrintF(value, "%s", str);
-      } else {
-        value = Vector<char>::New(5);
-        OS::SNPrintF(value, "NULL");
+      buffer.Add("%s", str ? str : "NULL");
+      break;
+    }
+    case Flag::TYPE_ARGS: {
+      JSArguments args = *flag->args_variable();
+      if (args.argc() > 0) {
+        buffer.Add("%s",  args[0]);
+        for (int i = 1; i < args.argc(); i++) {
+          buffer.Add(" %s", args[i]);
+        }
       }
       break;
+    }
   }
-  ASSERT(!value.is_empty());
-  return value.start();
+  return buffer.ToCString();
 }
 
 
 // static
-List<char *>* FlagList::argv() {
-  List<char *>* args = new List<char*>(8);
+List<const char*>* FlagList::argv() {
+  List<const char*>* args = new List<const char*>(8);
+  Flag* args_flag = NULL;
   for (size_t i = 0; i < num_flags; ++i) {
     Flag* f = &flags[i];
     if (!f->IsDefault()) {
-      Vector<char> cmdline_flag;
-      if (f->type() != Flag::TYPE_BOOL || *(f->bool_variable())) {
-        int length = strlen(f->name()) + 2 + 1;
-        cmdline_flag = Vector<char>::New(length);
-        OS::SNPrintF(cmdline_flag, "--%s", f->name());
-      } else {
-        int length = strlen(f->name()) + 4 + 1;
-        cmdline_flag = Vector<char>::New(length);
-        OS::SNPrintF(cmdline_flag, "--no%s", f->name());
+      if (f->type() == Flag::TYPE_ARGS) {
+        ASSERT(args_flag == NULL);
+        args_flag = f;  // Must be last in arguments.
+        continue;
       }
-      args->Add(cmdline_flag.start());
+      HeapStringAllocator string_allocator;
+      StringStream buffer(&string_allocator);
+      if (f->type() != Flag::TYPE_BOOL || *(f->bool_variable())) {
+        buffer.Add("--%s", f->name());
+      } else {
+        buffer.Add("--no%s", f->name());
+      }
+      args->Add(buffer.ToCString().Detach());
       if (f->type() != Flag::TYPE_BOOL) {
-        args->Add(ToString(f));
+        args->Add(ToString(f).Detach());
       }
     }
   }
-
+  if (args_flag != NULL) {
+    HeapStringAllocator string_allocator;
+    StringStream buffer(&string_allocator);
+    buffer.Add("--%s", args_flag->name());
+    args->Add(buffer.ToCString().Detach());
+    JSArguments jsargs = *args_flag->args_variable();
+    for (int j = 0; j < jsargs.argc(); j++) {
+      args->Add(OS::StrDup(jsargs[j]));
+    }
+  }
   return args;
 }
 
@@ -239,8 +272,14 @@
   if (*arg == '-') {
     // find the begin of the flag name
     arg++;  // remove 1st '-'
-    if (*arg == '-')
+    if (*arg == '-') {
       arg++;  // remove 2nd '-'
+      if (arg[0] == '\0') {
+        const char* kJSArgumentsFlagName = "js_arguments";
+        *name = kJSArgumentsFlagName;
+        return;
+      }
+    }
     if (arg[0] == 'n' && arg[1] == 'o') {
       arg += 2;  // remove "no"
       *is_bool = true;
@@ -317,17 +356,21 @@
           // sense there.
           continue;
         } else {
-          fprintf(stderr, "Error: unrecognized flag %s\n", arg);
+          fprintf(stderr, "Error: unrecognized flag %s\n"
+                  "Try --help for options\n", arg);
           return j;
         }
       }
 
       // if we still need a flag value, use the next argument if available
-      if (flag->type() != Flag::TYPE_BOOL && value == NULL) {
+      if (flag->type() != Flag::TYPE_BOOL &&
+          flag->type() != Flag::TYPE_ARGS &&
+          value == NULL) {
         if (i < *argc) {
           value = argv[i++];
         } else {
-          fprintf(stderr, "Error: missing value for flag %s of type %s\n",
+          fprintf(stderr, "Error: missing value for flag %s of type %s\n"
+                  "Try --help for options\n",
                   arg, Type2String(flag->type()));
           return j;
         }
@@ -348,21 +391,38 @@
         case Flag::TYPE_STRING:
           *flag->string_variable() = value;
           break;
+        case Flag::TYPE_ARGS: {
+          int start_pos = (value == NULL) ? i : i - 1;
+          int js_argc = *argc - start_pos;
+          const char** js_argv = NewArray<const char*>(js_argc);
+          if (value != NULL) {
+            js_argv[0] = value;
+          }
+          for (int k = i; k < *argc; k++) {
+            js_argv[k - start_pos] = argv[k];
+          }
+          *flag->args_variable() = JSArguments(js_argc, js_argv);
+          i = *argc;  // Consume all arguments
+          break;
+        }
       }
 
       // handle errors
       if ((flag->type() == Flag::TYPE_BOOL && value != NULL) ||
           (flag->type() != Flag::TYPE_BOOL && is_bool) ||
           *endp != '\0') {
-        fprintf(stderr, "Error: illegal value for flag %s of type %s\n",
+        fprintf(stderr, "Error: illegal value for flag %s of type %s\n"
+                "Try --help for options\n",
                 arg, Type2String(flag->type()));
         return j;
       }
 
       // remove the flag & value from the command
-      if (remove_flags)
-        while (j < i)
+      if (remove_flags) {
+        while (j < i) {
           argv[j++] = NULL;
+        }
+      }
     }
   }
 
@@ -376,6 +436,9 @@
     *argc = j;
   }
 
+  if (FLAG_help) {
+    PrintHelp();
+  }
   // parsed all flags successfully
   return 0;
 }
@@ -447,13 +510,38 @@
 
 // static
 void FlagList::PrintHelp() {
+  printf("Usage:\n");
+  printf("  shell [options] -e string\n");
+  printf("    execute string in V8\n");
+  printf("  shell [options] file1 file2 ... filek\n");
+  printf("    run JavaScript scripts in file1, file2, ..., filek\n");
+  printf("  shell [options]\n");
+  printf("  shell [options] --shell\n");
+  printf("    run an interactive JavaScript shell");
+  printf("  d8 [options] file\n");
+  printf("  d8 [options]\n");
+  printf("    run the new debugging shell\n\n");
+  printf("Options:\n");
   for (size_t i = 0; i < num_flags; ++i) {
     Flag* f = &flags[i];
-    char* value = ToString(f);
-    printf("  --%s (%s)  type: %s  default: %s\n",
-           f->name(), f->comment(), Type2String(f->type()), value);
-    DeleteArray(value);
+    SmartPointer<const char> value = ToString(f);
+    printf("  --%s (%s)\n        type: %s  default: %s\n",
+           f->name(), f->comment(), Type2String(f->type()), *value);
   }
 }
 
+JSArguments::JSArguments()
+    : argc_(0), argv_(NULL) {}
+JSArguments::JSArguments(int argc, const char** argv)
+    : argc_(argc), argv_(argv) {}
+int JSArguments::argc() const { return argc_; }
+const char** JSArguments::argv() { return argv_; }
+const char*& JSArguments::operator[](int idx) { return argv_[idx]; }
+JSArguments& JSArguments::operator=(JSArguments args) {
+    argc_ = args.argc_;
+    argv_ = args.argv_;
+    return *this;
+}
+
+
 } }  // namespace v8::internal
diff --git a/src/flags.h b/src/flags.h
index 813ea95..e6cbe3c 100644
--- a/src/flags.h
+++ b/src/flags.h
@@ -43,14 +43,15 @@
   // argv array passed to the main function, e.g.
   // ("--prof", "--log-file", "v8.prof", "--nolazy").
   //
-  // The caller is responsible for disposing the list.
-  static List<char *>* argv();
+  // The caller is responsible for disposing the list, as well
+  // as every element of it.
+  static List<const char*>* argv();
 
   // Set the flag values by parsing the command line. If remove_flags is
   // set, the flags and associated values are removed from (argc,
   // argv). Returns 0 if no error occurred. Otherwise, returns the argv
   // index > 0 for the argument where an error occurred. In that case,
-  // (argc, argv) will remain unchanged indepdendent of the remove_flags
+  // (argc, argv) will remain unchanged independent of the remove_flags
   // value, and no assumptions about flag settings should be made.
   //
   // The following syntax for flags is accepted (both '-' and '--' are ok):
@@ -59,6 +60,7 @@
   //   --noflag      (bool flags only)
   //   --flag=value  (non-bool flags only, no spaces around '=')
   //   --flag value  (non-bool flags only)
+  //   --            (equivalent to --js_arguments, captures all remaining args)
   static int SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags);
 
   // Set the flag values by parsing the string str. Splits string into argc
diff --git a/src/global-handles.cc b/src/global-handles.cc
index bb36e35..29ad86e 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -96,6 +96,7 @@
   // Make this handle weak.
   void MakeWeak(void* parameter, WeakReferenceCallback callback) {
     LOG(HandleEvent("GlobalHandle::MakeWeak", handle().location()));
+    ASSERT(state_ != DESTROYED);
     if (state_ != WEAK && !IsNearDeath()) {
       GlobalHandles::number_of_weak_handles_++;
       if (object_->IsJSGlobalObject()) {
@@ -109,6 +110,7 @@
 
   void ClearWeakness() {
     LOG(HandleEvent("GlobalHandle::ClearWeakness", handle().location()));
+    ASSERT(state_ != DESTROYED);
     if (state_ == WEAK || IsNearDeath()) {
       GlobalHandles::number_of_weak_handles_--;
       if (object_->IsJSGlobalObject()) {
diff --git a/src/globals.h b/src/globals.h
index cc0dbde..387ed88 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -25,6 +25,9 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#ifndef V8_GLOBALS_H_
+#define V8_GLOBALS_H_
+
 // -----------------------------------------------------------------------------
 // Types
 // Windows is missing the stdint.h header file. Instead we define standard
@@ -58,9 +61,6 @@
 // defined here because the platform code uses bool, and platform.h is
 // include very early in the main include file.
 
-#ifndef V8_GLOBALS_H_
-#define V8_GLOBALS_H_
-
 #ifdef USE_MYBOOL
 typedef unsigned int __my_bool__;
 #define bool __my_bool__  // use 'indirection' to avoid name clashes
@@ -282,6 +282,8 @@
 enum InlineCacheState {
   // Has never been executed.
   UNINITIALIZED,
+  // Has never been executed, but is in a loop.
+  UNINITIALIZED_IN_LOOP,
   // Has been executed but monomorhic state has been delayed.
   PREMONOMORPHIC,
   // Has been executed and only one receiver type has been seen.
diff --git a/src/handles-inl.h b/src/handles-inl.h
index 502aeab..0f804d7 100644
--- a/src/handles-inl.h
+++ b/src/handles-inl.h
@@ -36,6 +36,7 @@
 
 template<class T>
 Handle<T>::Handle(T* obj) {
+  ASSERT(!obj->IsFailure());
   location_ = reinterpret_cast<T**>(HandleScope::CreateHandle(obj));
 }
 
diff --git a/src/handles.cc b/src/handles.cc
index ada10f1..a33cbfc 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -422,10 +422,11 @@
 
 
 bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
-                       ClearExceptionFlag flag) {
+                       ClearExceptionFlag flag,
+                       int loop_nesting) {
   // Compile the source information to a code object.
   ASSERT(!shared->is_compiled());
-  bool result = Compiler::CompileLazy(shared);
+  bool result = Compiler::CompileLazy(shared, loop_nesting);
   ASSERT(result != Top::has_pending_exception());
   if (!result && flag == CLEAR_EXCEPTION) Top::clear_pending_exception();
   return result;
@@ -435,10 +436,16 @@
 bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag) {
   // Compile the source information to a code object.
   Handle<SharedFunctionInfo> shared(function->shared());
-  return CompileLazyShared(shared, flag);
+  return CompileLazyShared(shared, flag, 0);
 }
 
 
+bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag flag) {
+  // Compile the source information to a code object.
+  Handle<SharedFunctionInfo> shared(function->shared());
+  return CompileLazyShared(shared, flag, 1);
+}
+
 OptimizedObjectForAddingMultipleProperties::
 OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
                                            bool condition) {
diff --git a/src/handles.h b/src/handles.h
index a9adf3d..6d75c77 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -194,9 +194,13 @@
 // Do lazy compilation of the given function. Returns true on success
 // and false if the compilation resulted in a stack overflow.
 enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
+
 bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
-                       ClearExceptionFlag flag);
+                       ClearExceptionFlag flag,
+                       int loop_nesting);
+
 bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag);
+bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag flag);
 
 // These deal with lazily loaded properties.
 void SetupLazy(Handle<JSFunction> fun,
diff --git a/src/ic-arm.cc b/src/ic-arm.cc
index ccaf277..92eb5d3 100644
--- a/src/ic-arm.cc
+++ b/src/ic-arm.cc
@@ -136,24 +136,9 @@
 
   __ ldr(r0, MemOperand(sp, 0));
 
-  // Check that the receiver isn't a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &miss);
-
-  // Check that the object is a JS array.
-  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
-  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
-  __ cmp(r1, Operand(JS_ARRAY_TYPE));
-  __ b(ne, &miss);
-
-  // Load length directly from the JS array.
-  __ ldr(r0, FieldMemOperand(r0, JSArray::kLengthOffset));
-  __ Ret();
-
-  // Cache miss: Jump to runtime.
+  StubCompiler::GenerateLoadArrayLength(masm, r0, r3, &miss);
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
+  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
 }
 
 
@@ -185,7 +170,6 @@
   //  -- lr    : return address
   //  -- [sp]  : receiver
   // -----------------------------------
-
   Label miss, load_length, check_wrapper;
 
   __ ldr(r0, MemOperand(sp, 0));
@@ -216,8 +200,7 @@
 
   // Cache miss: Jump to runtime.
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
+  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
 }
 
 
@@ -509,33 +492,87 @@
   //  -- [sp]  : receiver
   // -----------------------------------
 
-  __ ldr(r0, MemOperand(sp, 0));
-  __ push(r0);
-  __ push(r2);
+  __ ldr(r3, MemOperand(sp, 0));
+  __ stm(db_w, sp, r2.bit() | r3.bit());
 
   // Perform tail call to the entry.
   __ TailCallRuntime(f, 2);
 }
 
 
-// TODO(1224671): ICs for keyed load/store is not implemented on ARM.
+// TODO(1224671): ICs for keyed load/store is not completed on ARM.
+Object* KeyedLoadIC_Miss(Arguments args);
+
+
 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
+  Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
 }
 
+
 void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[4]  : receiver
+  __ ldm(ia, sp, r2.bit() | r3.bit());
+  __ stm(db_w, sp, r2.bit() | r3.bit());
+
+  __ TailCallRuntime(f, 2);
 }
 
+
+// TODO(1224671): implement the fast case.
 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[4]  : receiver
+
+  KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty));
 }
 
+
 void KeyedStoreIC::Generate(MacroAssembler* masm,
                             const ExternalReference& f) {
+  // ---------- S t a t e --------------
+  //  -- r0     : value
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[1]  : receiver
+
+  __ ldm(ia, sp, r2.bit() | r3.bit());
+  __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
+
+  __ TailCallRuntime(f, 3);
 }
 
+
+// TODO(1224671): implement the fast case.
 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- r0     : value
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[1]  : receiver
+
+  KeyedStoreIC::Generate(masm, ExternalReference(Runtime::kSetProperty));
 }
 
+
 void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- r0     : value
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[1]  : receiver
+  // ----------- S t a t e -------------
+
+  __ ldm(ia, sp, r2.bit() | r3.bit());
+  __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
+
+  // Perform tail call to the entry.
+  __ TailCallRuntime(
+      ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3);
 }
 
 
diff --git a/src/ic-ia32.cc b/src/ic-ia32.cc
index 82eb14d..11e55a9 100644
--- a/src/ic-ia32.cc
+++ b/src/ic-ia32.cc
@@ -538,17 +538,17 @@
   __ EnterInternalFrame();
 
   // Push the receiver and the name of the function.
-  __ push(Operand(edx));
-  __ push(Operand(ebx));
+  __ push(edx);
+  __ push(ebx);
 
   // Call the entry.
   CEntryStub stub;
-  __ mov(Operand(eax), Immediate(2));
-  __ mov(Operand(ebx), Immediate(f));
+  __ mov(eax, Immediate(2));
+  __ mov(ebx, Immediate(f));
   __ CallStub(&stub);
 
   // Move result to edi and exit the internal frame.
-  __ mov(Operand(edi), eax);
+  __ mov(edi, eax);
   __ LeaveInternalFrame();
 
   // Check if the receiver is a global object of some sort.
diff --git a/src/ic.cc b/src/ic.cc
index 2ec7b09..c0b7624 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -41,6 +41,7 @@
 static char TransitionMarkFromState(IC::State state) {
   switch (state) {
     case UNINITIALIZED: return '0';
+    case UNINITIALIZED_IN_LOOP: return 'L';
     case PREMONOMORPHIC: return '0';
     case MONOMORPHIC: return '1';
     case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
@@ -223,7 +224,8 @@
 
 
 void CallIC::Clear(Address address, Code* target) {
-  if (target->ic_state() == UNINITIALIZED) return;
+  State state = target->ic_state();
+  if (state == UNINITIALIZED || state == UNINITIALIZED_IN_LOOP) return;
   Code* code = StubCache::FindCallInitialize(target->arguments_count());
   SetTargetAtAddress(address, code);
 }
@@ -434,8 +436,9 @@
   if (code->IsFailure()) return;
 
   // Patch the call site depending on the state of the cache.
-  if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
-      state == MONOMORPHIC || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
+  if (state == UNINITIALIZED || state == UNINITIALIZED_IN_LOOP ||
+      state == PREMONOMORPHIC || state == MONOMORPHIC ||
+      state == MONOMORPHIC_PROTOTYPE_FAILURE) {
     set_target(Code::cast(code));
   }
 
@@ -1044,7 +1047,17 @@
   ASSERT(args.length() == 2);
   CallIC ic;
   IC::State state = IC::StateFrom(ic.target(), args[0]);
-  return ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
+  Object* result =
+      ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
+  if (state != UNINITIALIZED_IN_LOOP || !result->IsJSFunction())
+    return result;
+
+  // Compile the function with the knowledge that it's called from
+  // within a loop. This enables further optimization of the function.
+  HandleScope scope;
+  Handle<JSFunction> function = Handle<JSFunction>(JSFunction::cast(result));
+  if (!function->is_compiled()) CompileLazyInLoop(function, CLEAR_EXCEPTION);
+  return *function;
 }
 
 
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index c747020..2dd21bd 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -383,7 +383,8 @@
         (error_message == NULL) ? "Unknown regexp error" : error_message)));
     Handle<Object> regexp_err =
         Factory::NewSyntaxError("malformed_regexp", array);
-    return Handle<Object>(Top::Throw(*regexp_err));
+    Top::Throw(*regexp_err);
+    return Handle<Object>();
   }
 
   // Convert the return address to a ByteArray pointer.
diff --git a/src/log.cc b/src/log.cc
index bd85fea..803dfe8 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -728,7 +728,7 @@
           stream.Put(*p);
         }
       }
-      SmartPointer<char> expanded = stream.ToCString();
+      SmartPointer<const char> expanded = stream.ToCString();
       logfile_ = OS::FOpen(*expanded, "w");
     } else {
       logfile_ = OS::FOpen(FLAG_logfile, "w");
diff --git a/src/log.h b/src/log.h
index 1fd2b75..eb082da 100644
--- a/src/log.h
+++ b/src/log.h
@@ -113,7 +113,6 @@
   // snapshot.
   static void Preamble(const char* content);
 
-  // ==== Events that are always logged. ====
   // Emits an event with a string value -> (name, value).
   static void StringEvent(const char* name, const char* value);
 
diff --git a/src/macro-assembler-arm.cc b/src/macro-assembler-arm.cc
index 2e957e4..616a9bf 100644
--- a/src/macro-assembler-arm.cc
+++ b/src/macro-assembler-arm.cc
@@ -818,7 +818,8 @@
     int argc = Builtins::GetArgumentsCount(id);
     uint32_t flags =
         Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
-        Bootstrapper::FixupFlagsIsPCRelative::encode(true);
+        Bootstrapper::FixupFlagsIsPCRelative::encode(true) |
+        Bootstrapper::FixupFlagsUseCodeObject::encode(false);
     Unresolved entry = { pc_offset() - sizeof(Instr), flags, name };
     unresolved_.Add(entry);
   }
@@ -835,10 +836,13 @@
     int argc = Builtins::GetArgumentsCount(id);
     uint32_t flags =
         Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
-        Bootstrapper::FixupFlagsIsPCRelative::encode(true);
+        Bootstrapper::FixupFlagsIsPCRelative::encode(true) |
+        Bootstrapper::FixupFlagsUseCodeObject::encode(true);
     Unresolved entry = { pc_offset() - sizeof(Instr), flags, name };
     unresolved_.Add(entry);
   }
+
+  add(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
 }
 
 
diff --git a/src/macro-assembler-ia32.cc b/src/macro-assembler-ia32.cc
index 72808de..fd7e4d9 100644
--- a/src/macro-assembler-ia32.cc
+++ b/src/macro-assembler-ia32.cc
@@ -293,7 +293,7 @@
   if (x.is_zero()) {
     xor_(dst, Operand(dst));  // shorter than mov
   } else {
-    mov(Operand(dst), x);
+    mov(dst, x);
   }
 }
 
@@ -695,7 +695,7 @@
   if (num_arguments > 0) {
     add(Operand(esp), Immediate(num_arguments * kPointerSize));
   }
-  mov(Operand(eax), Immediate(Factory::undefined_value()));
+  mov(eax, Immediate(Factory::undefined_value()));
 }
 
 
@@ -726,14 +726,14 @@
   // arguments passed in because it is constant. At some point we
   // should remove this need and make the runtime routine entry code
   // smarter.
-  mov(Operand(eax), Immediate(num_arguments));
+  Set(eax, Immediate(num_arguments));
   JumpToBuiltin(ext);
 }
 
 
 void MacroAssembler::JumpToBuiltin(const ExternalReference& ext) {
   // Set the entry point and jump to the C entry runtime stub.
-  mov(Operand(ebx), Immediate(ext));
+  mov(ebx, Immediate(ext));
   CEntryStub ces;
   jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
 }
@@ -787,7 +787,7 @@
     Handle<Code> adaptor =
         Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
     if (!code_constant.is_null()) {
-      mov(Operand(edx), Immediate(code_constant));
+      mov(edx, Immediate(code_constant));
       add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag));
     } else if (!code_operand.is_reg(edx)) {
       mov(edx, code_operand);
@@ -873,7 +873,8 @@
   if (!resolved) {
     uint32_t flags =
         Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
-        Bootstrapper::FixupFlagsIsPCRelative::encode(true);
+        Bootstrapper::FixupFlagsIsPCRelative::encode(true) |
+        Bootstrapper::FixupFlagsUseCodeObject::encode(false);
     Unresolved entry = { pc_offset() - sizeof(int32_t), flags, name };
     unresolved_.Add(entry);
   }
@@ -891,7 +892,8 @@
   if (!resolved) {
     uint32_t flags =
         Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
-        Bootstrapper::FixupFlagsIsPCRelative::encode(false);
+        Bootstrapper::FixupFlagsIsPCRelative::encode(false) |
+        Bootstrapper::FixupFlagsUseCodeObject::encode(true);
     Unresolved entry = { pc_offset() - sizeof(int32_t), flags, name };
     unresolved_.Add(entry);
   }
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 0ec6bd0..de05339 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -152,8 +152,6 @@
     space->PrepareForMarkCompact(compacting_collection_);
   }
 
-  Counters::global_objects.Set(0);
-
 #ifdef DEBUG
   live_bytes_ = 0;
   live_young_objects_ = 0;
@@ -327,12 +325,10 @@
   void VisitUnmarkedObject(HeapObject* obj) {
 #ifdef DEBUG
     ASSERT(Heap::Contains(obj));
-    MarkCompactCollector::UpdateLiveObjectCount(obj);
     ASSERT(!obj->IsMarked());
 #endif
     Map* map = obj->map();
-    obj->SetMark();
-    MarkCompactCollector::tracer()->increment_marked_count();
+    MarkCompactCollector::SetMark(obj);
     // Mark the map pointer and the body.
     MarkCompactCollector::MarkObject(map);
     obj->IterateBody(map->instance_type(), obj->SizeFromMap(map), this);
@@ -380,13 +376,9 @@
     HeapObject* object = ShortCircuitConsString(p);
     if (object->IsMarked()) return;
 
-#ifdef DEBUG
-    MarkCompactCollector::UpdateLiveObjectCount(object);
-#endif
     Map* map = object->map();
     // Mark the object.
-    object->SetMark();
-    MarkCompactCollector::tracer()->increment_marked_count();
+    MarkCompactCollector::SetMark(object);
     // Mark the map pointer and body, and push them on the marking stack.
     MarkCompactCollector::MarkObject(map);
     object->IterateBody(map->instance_type(), object->SizeFromMap(map),
@@ -423,20 +415,14 @@
 
 
 void MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) {
-#ifdef DEBUG
-  UpdateLiveObjectCount(object);
-#endif
   ASSERT(!object->IsMarked());
-  if (object->IsJSGlobalObject()) Counters::global_objects.Increment();
-
-  tracer_->increment_marked_count();
   ASSERT(Heap::Contains(object));
   if (object->IsMap()) {
     Map* map = Map::cast(object);
     if (FLAG_cleanup_caches_in_maps_at_gc) {
       map->ClearCodeCache();
     }
-    map->SetMark();
+    SetMark(map);
     if (FLAG_collect_maps &&
         map->instance_type() >= FIRST_JS_OBJECT_TYPE &&
         map->instance_type() <= JS_FUNCTION_TYPE) {
@@ -445,7 +431,7 @@
       marking_stack.Push(map);
     }
   } else {
-    object->SetMark();
+    SetMark(object);
     marking_stack.Push(object);
   }
 }
@@ -469,12 +455,7 @@
   if (descriptors->IsMarked()) return;
   // Empty descriptor array is marked as a root before any maps are marked.
   ASSERT(descriptors != Heap::empty_descriptor_array());
-
-  tracer_->increment_marked_count();
-#ifdef DEBUG
-  UpdateLiveObjectCount(descriptors);
-#endif
-  descriptors->SetMark();
+  SetMark(descriptors);
 
   FixedArray* contents = reinterpret_cast<FixedArray*>(
       descriptors->get(DescriptorArray::kContentArrayIndex));
@@ -482,11 +463,7 @@
   ASSERT(!contents->IsMarked());
   ASSERT(contents->IsFixedArray());
   ASSERT(contents->length() >= 2);
-  tracer_->increment_marked_count();
-#ifdef DEBUG
-  UpdateLiveObjectCount(contents);
-#endif
-  contents->SetMark();
+  SetMark(contents);
   // Contents contains (value, details) pairs.  If the details say
   // that the type of descriptor is MAP_TRANSITION, CONSTANT_TRANSITION,
   // or NULL_DESCRIPTOR, we don't mark the value as live.  Only for
@@ -498,11 +475,7 @@
     if (details.type() < FIRST_PHANTOM_PROPERTY_TYPE) {
       HeapObject* object = reinterpret_cast<HeapObject*>(contents->get(i));
       if (object->IsHeapObject() && !object->IsMarked()) {
-        tracer_->increment_marked_count();
-#ifdef DEBUG
-        UpdateLiveObjectCount(object);
-#endif
-        object->SetMark();
+        SetMark(object);
         marking_stack.Push(object);
       }
     }
@@ -578,13 +551,9 @@
   SymbolTable* symbol_table = SymbolTable::cast(Heap::symbol_table());
   // 1. Mark the prefix of the symbol table gray.
   symbol_table->IteratePrefix(visitor);
-#ifdef DEBUG
-  UpdateLiveObjectCount(symbol_table);
-#endif
   // 2. Mark the symbol table black (ie, do not push it on the marking stack
   // or mark it overflowed).
-  symbol_table->SetMark();
-  tracer_->increment_marked_count();
+  SetMark(symbol_table);
 
   // There may be overflowed objects in the heap.  Visit them now.
   while (marking_stack.overflowed()) {
diff --git a/src/mark-compact.h b/src/mark-compact.h
index 2dcf433..22dd890 100644
--- a/src/mark-compact.h
+++ b/src/mark-compact.h
@@ -152,7 +152,15 @@
   static void MarkUnmarkedObject(HeapObject* obj);
 
   static inline void MarkObject(HeapObject* obj) {
-     if (!obj->IsMarked()) MarkUnmarkedObject(obj);
+    if (!obj->IsMarked()) MarkUnmarkedObject(obj);
+  }
+
+  static inline void SetMark(HeapObject* obj) {
+    tracer_->increment_marked_count();
+#ifdef DEBUG
+    UpdateLiveObjectCount(obj);
+#endif
+    obj->SetMark();
   }
 
   // Creates back pointers for all map transitions, stores them in
diff --git a/src/messages.cc b/src/messages.cc
index 7edb07f..e6a5084 100644
--- a/src/messages.cc
+++ b/src/messages.cc
@@ -108,13 +108,12 @@
   Handle<Object> message =
       Execution::Call(fun, Factory::undefined_value(), argc, argv,
                       &caught_exception);
-  if (caught_exception) {
-    // If creating the message (in JS code) resulted in an exception, we
-    // skip doing the callback. This usually only happens in case of
-    // stack overflow exceptions being thrown by the parser when the
-    // stack is almost full.
-    if (caught_exception) return Handle<Object>();
-  }
+
+  // If creating the message (in JS code) resulted in an exception, we
+  // skip doing the callback. This usually only happens in case of
+  // stack overflow exceptions being thrown by the parser when the
+  // stack is almost full.
+  if (caught_exception) return Handle<Object>();
 
   return message.EscapeFrom(&scope);
 }
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
index 275fb47..7fb4490 100644
--- a/src/mksnapshot.cc
+++ b/src/mksnapshot.cc
@@ -150,10 +150,10 @@
   // Print the usage if an error occurs when parsing the command line
   // flags or if the help flag is set.
   int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
-  if (result > 0 || argc != 2 || i::FLAG_h) {
+  if (result > 0 || argc != 2 || i::FLAG_help) {
     ::printf("Usage: %s [flag] ... outfile\n", argv[0]);
     i::FlagList::PrintHelp();
-    return !i::FLAG_h;
+    return !i::FLAG_help;
   }
 
   v8::V8::SetCounterFunction(counter_callback);
diff --git a/src/objects.cc b/src/objects.cc
index 66be1db..511f9f7 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -199,11 +199,11 @@
       Handle<JSFunction> fun(JSFunction::cast(getter));
       Handle<Object> self(receiver);
       bool has_pending_exception;
-      Object* result =
-          *Execution::Call(fun, self, 0, NULL, &has_pending_exception);
+      Handle<Object> result =
+          Execution::Call(fun, self, 0, NULL, &has_pending_exception);
       // Check for pending exception and return the result.
       if (has_pending_exception) return Failure::Exception();
-      return result;
+      return *result;
     }
     // Getter is not a function.
     return Heap::undefined_value();
@@ -3848,7 +3848,7 @@
   const int kAlignmentMask = sizeof(uint32_t) - 1;  // NOLINT
   uint32_t pa_addr = reinterpret_cast<uint32_t>(pa);
   uint32_t pb_addr = reinterpret_cast<uint32_t>(pb);
-  if ((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask) == 0) {
+  if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
 #endif
     const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
     int endpoint = length - kStepSize;
@@ -4603,6 +4603,7 @@
 const char* Code::ICState2String(InlineCacheState state) {
   switch (state) {
     case UNINITIALIZED: return "UNINITIALIZED";
+    case UNINITIALIZED_IN_LOOP: return "UNINITIALIZED_IN_LOOP";
     case PREMONOMORPHIC: return "PREMONOMORPHIC";
     case MONOMORPHIC: return "MONOMORPHIC";
     case MONOMORPHIC_PROTOTYPE_FAILURE: return "MONOMORPHIC_PROTOTYPE_FAILURE";
diff --git a/src/rewriter.cc b/src/rewriter.cc
index d391d5d..c5ca7cd 100644
--- a/src/rewriter.cc
+++ b/src/rewriter.cc
@@ -761,17 +761,20 @@
 }
 
 
-void Rewriter::Optimize(FunctionLiteral* function) {
+bool Rewriter::Optimize(FunctionLiteral* function) {
   ZoneList<Statement*>* body = function->body();
-  if (body->is_empty()) return;
 
-  if (FLAG_optimize_ast) {
+  if (FLAG_optimize_ast && !body->is_empty()) {
     Scope* scope = function->scope();
     if (!scope->is_global_scope()) {
       AstOptimizer optimizer;
       optimizer.Optimize(body);
+      if (optimizer.HasStackOverflow()) {
+        return false;
+      }
     }
   }
+  return true;
 }
 
 
diff --git a/src/rewriter.h b/src/rewriter.h
index d69ad5a..aa2f981 100644
--- a/src/rewriter.h
+++ b/src/rewriter.h
@@ -44,7 +44,7 @@
 class Rewriter {
  public:
   static bool Process(FunctionLiteral* function);
-  static void Optimize(FunctionLiteral* function);
+  static bool Optimize(FunctionLiteral* function);
 };
 
 
diff --git a/src/runtime.cc b/src/runtime.cc
index 6fe7cc6..1d40e4c 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -296,7 +296,9 @@
   Handle<String> pattern(raw_pattern);
   CONVERT_CHECKED(String, raw_flags, args[2]);
   Handle<String> flags(raw_flags);
-  return *RegExpImpl::Compile(re, pattern, flags);
+  Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
+  if (result.is_null()) return Failure::Exception();
+  return *result;
 }
 
 
@@ -5086,7 +5088,7 @@
     if (!done) {
       // If the candidate is not compiled compile it to reveal any inner
       // functions which might contain the requested source position.
-      CompileLazyShared(target, KEEP_EXCEPTION);
+      CompileLazyShared(target, KEEP_EXCEPTION, 0);
     }
   }
 
@@ -5392,6 +5394,7 @@
   Handle<Object> evaluation_function =
       Execution::Call(compiled_function, receiver, 0, NULL,
                       &has_pending_exception);
+  if (has_pending_exception) return Failure::Exception();
 
   Handle<Object> arguments = GetArgumentsObject(frame, function, code, &sinfo,
                                                 function_context);
@@ -5403,6 +5406,7 @@
   Handle<Object> result =
       Execution::Call(Handle<JSFunction>::cast(evaluation_function), receiver,
                       argc, argv, &has_pending_exception);
+  if (has_pending_exception) return Failure::Exception();
   return *result;
 }
 
@@ -5448,6 +5452,7 @@
   Handle<Object> result =
     Execution::Call(compiled_function, receiver, 0, NULL,
                     &has_pending_exception);
+  if (has_pending_exception) return Failure::Exception();
   return *result;
 }
 
diff --git a/src/scanner.cc b/src/scanner.cc
index a6cc74a..3ae6936 100644
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -234,11 +234,25 @@
 }
 
 
+static inline bool IsByteOrderMark(uc32 c) {
+  // The Unicode value U+FFFE is guaranteed never to be assigned as a
+  // Unicode character; this implies that in a Unicode context the
+  // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF
+  // character expressed in little-endian byte order (since it could
+  // not be a U+FFFE character expressed in big-endian byte
+  // order). Nevertheless, we check for it to be compatible with
+  // Spidermonkey.
+  return c == 0xFEFF || c == 0xFFFE;
+}
+
+
 void Scanner::SkipWhiteSpace(bool initial) {
   has_line_terminator_before_next_ = initial;
 
   while (true) {
-    while (kIsWhiteSpace.get(c0_)) {
+    // We treat byte-order marks (BOMs) as whitespace for better
+    // compatibility with Spidermonkey and other JavaScript engines.
+    while (kIsWhiteSpace.get(c0_) || IsByteOrderMark(c0_)) {
       // IsWhiteSpace() includes line terminators!
       if (kIsLineTerminator.get(c0_))
         // Ignore line terminators, but remember them. This is necessary
diff --git a/src/serialize.cc b/src/serialize.cc
index cd7a323..359d627 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -966,7 +966,7 @@
 
 void Serializer::PutFlags() {
   writer_->PutC('F');
-  List<char*>* argv = FlagList::argv();
+  List<const char*>* argv = FlagList::argv();
   writer_->PutInt(argv->length());
   writer_->PutC('[');
   for (int i = 0; i < argv->length(); i++) {
diff --git a/src/simulator-arm.cc b/src/simulator-arm.cc
index 37a8237..4203ad3 100644
--- a/src/simulator-arm.cc
+++ b/src/simulator-arm.cc
@@ -48,11 +48,7 @@
 // SScanF not beeing implemented in a platform independent was through
 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
 // Library does not provide vsscanf.
-#ifdef WIN32
-#define SScanF sscanf_s
-#else
 #define SScanF sscanf  // NOLINT
-#endif
 
 // The Debugger class is used by the simulator while debugging simulated ARM
 // code.
@@ -210,7 +206,8 @@
 
   while (!done) {
     if (last_pc != sim_->get_pc()) {
-      disasm::Disassembler dasm;
+      disasm::NameConverter converter;
+      disasm::Disassembler dasm(converter);
       // use a reasonably large buffer
       v8::internal::EmbeddedVector<char, 256> buffer;
       dasm.InstructionDecode(buffer,
@@ -265,7 +262,8 @@
           PrintF("printobject value\n");
         }
       } else if (strcmp(cmd, "disasm") == 0) {
-        disasm::Disassembler dasm;
+        disasm::NameConverter converter;
+        disasm::Disassembler dasm(converter);
         // use a reasonably large buffer
         v8::internal::EmbeddedVector<char, 256> buffer;
 
@@ -380,19 +378,20 @@
 }
 
 
-// This is the Simulator singleton. Currently only one thread is supported by
-// V8. If we had multiple threads, then we should have a Simulator instance on
-// a per thread basis.
-static Simulator* the_sim = NULL;
+// Create one simulator per thread and keep it in thread local storage.
+static v8::internal::Thread::LocalStorageKey simulator_key =
+    v8::internal::Thread::CreateThreadLocalKey();
 
-
-// Get the active Simulator for the current thread. See comment above about
-// using a singleton currently.
+// Get the active Simulator for the current thread.
 Simulator* Simulator::current() {
-  if (the_sim == NULL) {
-    the_sim = new Simulator();
+  Simulator* sim = reinterpret_cast<Simulator*>(
+      v8::internal::Thread::GetThreadLocal(simulator_key));
+  if (sim == NULL) {
+    // TODO(146): delete the simulator object when a thread goes away.
+    sim = new Simulator();
+    v8::internal::Thread::SetThreadLocal(simulator_key, sim);
   }
-  return the_sim;
+  return sim;
 }
 
 
@@ -1441,7 +1440,8 @@
     return;
   }
   if (::v8::internal::FLAG_trace_sim) {
-    disasm::Disassembler dasm;
+    disasm::NameConverter converter;
+    disasm::Disassembler dasm(converter);
     // use a reasonably large buffer
     v8::internal::EmbeddedVector<char, 256> buffer;
     dasm.InstructionDecode(buffer,
@@ -1492,7 +1492,7 @@
 
 
 //
-void Simulator::execute() {
+void Simulator::Execute() {
   // Get the PC to simulate. Cannot use the accessor here as we need the
   // raw PC value and not the one used as input to arithmetic instructions.
   int program_counter = get_pc();
@@ -1524,7 +1524,7 @@
 }
 
 
-Object* Simulator::call(int32_t entry, int32_t p0, int32_t p1, int32_t p2,
+Object* Simulator::Call(int32_t entry, int32_t p0, int32_t p1, int32_t p2,
                            int32_t p3, int32_t p4) {
   // Setup parameters
   set_register(r0, p0);
@@ -1567,7 +1567,7 @@
   set_register(r11, callee_saved_value);
 
   // Start the simulation
-  execute();
+  Execute();
 
   // Check that the callee-saved registers have been preserved.
   CHECK_EQ(get_register(r4), callee_saved_value);
diff --git a/src/simulator-arm.h b/src/simulator-arm.h
index baefa5d..ccb3e80 100644
--- a/src/simulator-arm.h
+++ b/src/simulator-arm.h
@@ -54,7 +54,7 @@
 // When running with the simulator transition into simulated execution at this
 // point.
 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
-  assembler::arm::Simulator::current()->call((int32_t)entry, (int32_t)p0, \
+  assembler::arm::Simulator::current()->Call((int32_t)entry, (int32_t)p0, \
     (int32_t)p1, (int32_t)p2, (int32_t)p3, (int32_t)p4)
 
 // The simulator has its own stack. Thus it has a different stack limit from
@@ -103,12 +103,12 @@
   uintptr_t StackLimit() const;
 
   // Executes ARM instructions until the PC reaches end_sim_pc.
-  void execute();
+  void Execute();
 
   // V8 generally calls into generated code with 5 parameters. This is a
   // convenience funtion, which sets up the simulator state and grabs the
   // result on return.
-  v8::internal::Object* call(int32_t entry, int32_t p0, int32_t p1,
+  v8::internal::Object* Call(int32_t entry, int32_t p0, int32_t p1,
                              int32_t p2, int32_t p3, int32_t p4);
 
  private:
diff --git a/src/string-stream.cc b/src/string-stream.cc
index 81cbea5..6a3737b 100644
--- a/src/string-stream.cc
+++ b/src/string-stream.cc
@@ -141,6 +141,13 @@
       Add(formatted.start());
       break;
     }
+    case 'f': case 'g': case 'G': case 'e': case 'E': {
+      double value = current.data_.u_double_;
+      EmbeddedVector<char, 28> formatted;
+      OS::SNPrintF(formatted, temp.start(), value);
+      Add(formatted.start());
+      break;
+    }
     default:
       UNREACHABLE();
       break;
@@ -207,11 +214,11 @@
 }
 
 
-SmartPointer<char> StringStream::ToCString() {
+SmartPointer<const char> StringStream::ToCString() {
   char* str = NewArray<char>(length_ + 1);
   memcpy(str, buffer_, length_);
   str[length_] = '\0';
-  return SmartPointer<char>(str);
+  return SmartPointer<const char>(str);
 }
 
 
diff --git a/src/string-stream.h b/src/string-stream.h
index 9cff319..2fb29af 100644
--- a/src/string-stream.h
+++ b/src/string-stream.h
@@ -73,16 +73,18 @@
 class FmtElm {
  public:
   FmtElm(int value) : type_(INT) { data_.u_int_ = value; }  // NOLINT
+  explicit FmtElm(double value) : type_(DOUBLE) { data_.u_double_ = value; }  // NOLINT
   FmtElm(const char* value) : type_(C_STR) { data_.u_c_str_ = value; }  // NOLINT
   FmtElm(Object* value) : type_(OBJ) { data_.u_obj_ = value; }  // NOLINT
   FmtElm(Handle<Object> value) : type_(HANDLE) { data_.u_handle_ = value.location(); }  // NOLINT
   FmtElm(void* value) : type_(INT) { data_.u_int_ = reinterpret_cast<int>(value); }  // NOLINT
  private:
   friend class StringStream;
-  enum Type { INT, C_STR, OBJ, HANDLE };
+  enum Type { INT, DOUBLE, C_STR, OBJ, HANDLE };
   Type type_;
   union {
     int u_int_;
+    double u_double_;
     const char* u_c_str_;
     Object* u_obj_;
     Object** u_handle_;
@@ -116,7 +118,7 @@
   void OutputToStdOut();
   void Log();
   Handle<String> ToString();
-  SmartPointer<char> ToCString();
+  SmartPointer<const char> ToCString();
 
   // Object printing support.
   void PrintName(Object* o);
diff --git a/src/stub-cache-arm.cc b/src/stub-cache-arm.cc
index 2ef657e..e7fe0b9 100644
--- a/src/stub-cache-arm.cc
+++ b/src/stub-cache-arm.cc
@@ -169,6 +169,141 @@
 }
 
 
+void StubCompiler::GenerateLoadField(MacroAssembler* masm,
+                                     JSObject* object,
+                                     JSObject* holder,
+                                     Register receiver,
+                                     Register scratch1,
+                                     Register scratch2,
+                                     int index,
+                                     Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+  GenerateFastPropertyLoad(masm, r0, reg, holder, index);
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
+                                        JSObject* object,
+                                        JSObject* holder,
+                                        Register receiver,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Object* value,
+                                        Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+
+  // Return the constant value.
+  __ mov(r0, Operand(Handle<Object>(value)));
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
+                                        JSObject* object,
+                                        JSObject* holder,
+                                        Register receiver,
+                                        Register name,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        AccessorInfo* callback,
+                                        Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+
+  // Push the arguments on the JS stack of the caller.
+  __ push(receiver);  // receiver
+  __ mov(ip, Operand(Handle<AccessorInfo>(callback)));  // callback data
+  __ push(ip);
+  __ push(name);  // name
+  __ push(reg);  // holder
+
+  // Do tail-call to the runtime system.
+  ExternalReference load_callback_property =
+      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+  __ TailCallRuntime(load_callback_property, 4);
+}
+
+
+void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
+                                           JSObject* object,
+                                           JSObject* holder,
+                                           Register receiver,
+                                           Register name,
+                                           Register scratch1,
+                                           Register scratch2,
+                                           Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+
+  // Push the arguments on the JS stack of the caller.
+  __ push(receiver);  // receiver
+  __ push(reg);  // holder
+  __ push(name);  // name
+
+  // Do tail-call to the runtime system.
+  ExternalReference load_ic_property =
+      ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
+  __ TailCallRuntime(load_ic_property, 3);
+}
+
+
+void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
+                                           Register receiver,
+                                           Register scratch,
+                                           Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the object is a JS array.
+  __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+  __ cmp(scratch, Operand(JS_ARRAY_TYPE));
+  __ b(ne, miss_label);
+
+  // Load length directly from the JS array.
+  __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
+  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
+  Code* code = NULL;
+  if (kind == Code::LOAD_IC) {
+    code = Builtins::builtin(Builtins::LoadIC_Miss);
+  } else {
+    code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
+  }
+
+  Handle<Code> ic(code);
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+}
+
+
 #undef __
 
 #define __ masm()->
@@ -633,20 +768,9 @@
 
   __ ldr(r0, MemOperand(sp, 0));
 
-  // Check that the receiver isn't a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &miss);
-
-  // Check that the maps haven't changed.
-  Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
-  GenerateFastPropertyLoad(masm(), r0, reg, holder, index);
-  __ Ret();
-
-  // Handle load cache miss.
+  GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
   __ bind(&miss);
-  __ ldr(r0, MemOperand(sp));  // restore receiver
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
 
   // Return the generated code.
   return GetCode(FIELD);
@@ -666,29 +790,9 @@
   Label miss;
 
   __ ldr(r0, MemOperand(sp, 0));
-  // Check that the receiver isn't a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &miss);
-
-  // Check that the maps haven't changed.
-  Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
-
-  // Push the arguments on the JS stack of the caller.
-  __ push(r0);  // receiver
-  __ mov(ip, Operand(Handle<AccessorInfo>(callback)));  // callback data
-  __ push(ip);
-  __ push(r2);  // name
-  __ push(reg);  // holder
-
-  // Do tail-call to the runtime system.
-  ExternalReference load_callback_property =
-      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
-  __ TailCallRuntime(load_callback_property, 4);
-
-  // Handle load cache miss.
+  GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback, &miss);
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
 
   // Return the generated code.
   return GetCode(CALLBACKS);
@@ -708,21 +812,10 @@
   Label miss;
 
   __ ldr(r0, MemOperand(sp, 0));
-  // Check that the receiver isn't a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &miss);
 
-  // Check that the maps haven't changed.
-  Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
-
-  // Return the constant value.
-  __ mov(r0, Operand(Handle<Object>(value)));
-  __ Ret();
-
-  // Handle load cache miss.
+  GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
 
   // Return the generated code.
   return GetCode(CONSTANT_FUNCTION);
@@ -742,27 +835,10 @@
   Label miss;
 
   __ ldr(r0, MemOperand(sp, 0));
-  // Check that the receiver isn't a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &miss);
 
-  // Check that the maps haven't changed.
-  Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
-
-  // Push the arguments on the JS stack of the caller.
-  __ push(r0);  // receiver
-  __ push(reg);  // holder
-  __ push(r2);  // name
-
-  // Do tail-call to the runtime system.
-  ExternalReference load_ic_property =
-      ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
-  __ TailCallRuntime(load_ic_property, 3);
-
-  // Handle load cache miss.
+  GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss);
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
 
   // Return the generated code.
   return GetCode(INTERCEPTOR);
@@ -775,8 +851,25 @@
                                                 JSObject* receiver,
                                                 JSObject* holder,
                                                 int index) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  Label miss;
+
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(FIELD);
 }
 
 
@@ -784,8 +877,26 @@
                                                    JSObject* receiver,
                                                    JSObject* holder,
                                                    AccessorInfo* callback) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  Label miss;
+
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
+                       r1, callback, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(CALLBACKS);
 }
 
 
@@ -793,45 +904,126 @@
                                                    JSObject* receiver,
                                                    JSObject* holder,
                                                    Object* value) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  Label miss;
+
+  // Check the key is the cached one
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(CONSTANT_FUNCTION);
 }
 
 
 Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
                                                       JSObject* holder,
                                                       String* name) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  Label miss;
+
+  // Check the key is the cached one
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(INTERCEPTOR);
 }
 
 
 Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  Label miss;
+
+  // Check the key is the cached one
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadArrayLength(masm(), r0, r3, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(CALLBACKS);
 }
 
 
+// TODO(1224671): implement the fast case.
 Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(CALLBACKS);
 }
 
 
+// TODO(1224671): implement the fast case.
 Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(CALLBACKS);
 }
 
 
+// TODO(1224671): implement the fast case.
 Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
                                                   int index,
                                                   Map* transition,
                                                   String* name) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
-}
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  HandleScope scope;
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+  __ Jump(ic, RelocInfo::CODE_TARGET);
 
+  // Return the generated code.
+  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
+}
 
 
 #undef __
diff --git a/src/stub-cache-ia32.cc b/src/stub-cache-ia32.cc
index 66e12d4..d15b19d 100644
--- a/src/stub-cache-ia32.cc
+++ b/src/stub-cache-ia32.cc
@@ -395,7 +395,7 @@
   if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
     // The properties must be extended before we can store the value.
     // We jump to a runtime call that extends the propeties array.
-    __ mov(Operand(ecx), Immediate(Handle<Map>(transition)));
+    __ mov(ecx, Immediate(Handle<Map>(transition)));
     Handle<Code> ic(Builtins::builtin(storage_extend));
     __ jmp(ic, RelocInfo::CODE_TARGET);
     return;
@@ -628,7 +628,7 @@
   }
 
   // Get the function and setup the context.
-  __ mov(Operand(edi), Immediate(Handle<JSFunction>(function)));
+  __ mov(edi, Immediate(Handle<JSFunction>(function)));
   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
 
   // Jump to the cached code (tail call).
@@ -681,14 +681,14 @@
   // Perform call.
   ExternalReference load_interceptor =
       ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
-  __ mov(Operand(eax), Immediate(3));
-  __ mov(Operand(ebx), Immediate(load_interceptor));
+  __ mov(eax, Immediate(3));
+  __ mov(ebx, Immediate(load_interceptor));
 
   CEntryStub stub;
   __ CallStub(&stub);
 
   // Move result to edi and restore receiver.
-  __ mov(Operand(edi), eax);
+  __ mov(edi, eax);
   __ mov(edx, Operand(ebp, (argc + 2) * kPointerSize));  // receiver
 
   // Exit frame.
@@ -750,7 +750,7 @@
 
   // Handle store cache miss.
   __ bind(&miss);
-  __ mov(Operand(ecx), Immediate(Handle<String>(name)));  // restore name
+  __ mov(ecx, Immediate(Handle<String>(name)));  // restore name
   Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
@@ -807,7 +807,7 @@
 
   // Handle store cache miss.
   __ bind(&miss);
-  __ mov(Operand(ecx), Immediate(Handle<String>(name)));  // restore name
+  __ mov(ecx, Immediate(Handle<String>(name)));  // restore name
   Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
@@ -862,7 +862,7 @@
 
   // Handle store cache miss.
   __ bind(&miss);
-  __ mov(Operand(ecx), Immediate(Handle<String>(name)));  // restore name
+  __ mov(ecx, Immediate(Handle<String>(name)));  // restore name
   Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 2904889..3ee1b9e 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -543,6 +543,17 @@
 }
 
 
+Object* StubCache::ComputeCallInitializeInLoop(int argc) {
+  Code::Flags flags =
+      Code::ComputeFlags(Code::CALL_IC, UNINITIALIZED_IN_LOOP, NORMAL, argc);
+  Object* probe = ProbeCache(flags);
+  if (!probe->IsUndefined()) return probe;
+  StubCompiler compiler;
+  return FillCache(compiler.CompileCallInitialize(flags));
+}
+
+
+
 Object* StubCache::ComputeCallPreMonomorphic(int argc) {
   Code::Flags flags =
       Code::ComputeFlags(Code::CALL_IC, PREMONOMORPHIC, NORMAL, argc);
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 5d67afe..66d03fe 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -148,6 +148,7 @@
   // ---
 
   static Object* ComputeCallInitialize(int argc);
+  static Object* ComputeCallInitializeInLoop(int argc);
   static Object* ComputeCallPreMonomorphic(int argc);
   static Object* ComputeCallNormal(int argc);
   static Object* ComputeCallMegamorphic(int argc);
diff --git a/src/top.cc b/src/top.cc
index 29b7861..ace79a9 100644
--- a/src/top.cc
+++ b/src/top.cc
@@ -253,7 +253,30 @@
 }
 
 
+// There are cases where the C stack is separated from JS stack (ARM simulator).
+// To figure out the order of top-most JS try-catch handler and the top-most C
+// try-catch handler, the C try-catch handler keeps a reference to the top-most
+// JS try_catch handler when it was created.
+//
+// Here is a picture to explain the idea:
+//   Top::thread_local_.handler_       Top::thread_local_.try_catch_handler_
+//
+//             |                                         |
+//             v                                         v
+//
+//      | JS handler  |                        | C try_catch handler |
+//      |    next     |--+           +-------- |    js_handler_      |
+//                       |           |         |      next_          |--+
+//                       |           |                                  |
+//      | JS handler  |--+ <---------+                                  |
+//      |    next     |
+//
+// If the top-most JS try-catch handler is not equal to
+// Top::thread_local_.try_catch_handler_.js_handler_, it means the JS handler
+// 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*
   thread_local_.try_catch_handler_ = that;
 }
 
@@ -719,8 +742,7 @@
   // 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);
-  Address external_handler_address =
-      reinterpret_cast<Address>(thread_local_.try_catch_handler_);
+  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
@@ -732,10 +754,12 @@
   }
 
   // The exception has been externally caught if and only if there is
-  // an external handler which is above any JavaScript try-catch but NOT
-  // try-finally handlers.
+  // 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 &&
-      (handler == NULL || handler->address() > external_handler_address);
+      (handler == NULL || handler == try_catch->js_handler_);
 
   // If we have a try-catch handler then the exception is caught in
   // JavaScript code.
@@ -745,7 +769,7 @@
   // exception if it isn't caught by JavaScript code.
   if (!has_external_handler) return is_uncaught_by_js;
 
-  if (is_uncaught_by_js || handler->address() > external_handler_address) {
+  if (is_uncaught_by_js || handler == try_catch->js_handler_) {
     // Only report the exception if the external handler is verbose.
     return thread_local_.try_catch_handler_->is_verbose_;
   } else {
diff --git a/src/v8-counters.h b/src/v8-counters.h
index 0505d20..0f5af8a 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -50,8 +50,6 @@
 #define STATS_COUNTER_LIST_1(SC)                                 \
   /* Global Handle Count*/                                       \
   SC(global_handles, V8.GlobalHandles)                           \
-  /* Global Object Count */                                      \
-  SC(global_objects, V8.GlobalObjects)                           \
   /* Mallocs from PCRE */                                        \
   SC(pcre_mallocs, V8.PcreMallocCount)                           \
   /* OS Memory allocated */                                      \
diff --git a/src/v8.h b/src/v8.h
index 328c88c..3d84158 100644
--- a/src/v8.h
+++ b/src/v8.h
@@ -38,6 +38,10 @@
 // If both are defined in Google3, then we are building an optimized v8 with
 // assertions enabled.
 #undef NDEBUG
+#elif !defined(DEBUG) && !defined(NDEBUG)
+// If neither is defined in Google3, then we are building a debug v8. Mark it
+// as such.
+#define DEBUG
 #endif
 #endif  // defined(GOOGLE3)
 
diff --git a/src/v8natives.js b/src/v8natives.js
index 094d5ea..f3c98a5 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -105,6 +105,11 @@
 function GlobalEval(x) {
   if (!IS_STRING(x)) return x;
 
+  if (this !== %GlobalReceiver(global)) {
+    throw new $EvalError('The "this" object passed to eval must ' + 
+                         'be the global object from which eval originated');
+  }
+  
   var f = %CompileString(x, 0, true);
   if (!IS_FUNCTION(f)) return f;
 
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index b3f71d9..fc7cd6a 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -34,7 +34,6 @@
 
 test-debug: SKIP
 test-serialize: SKIP
-test-api: SKIP
 
 # BUG(113): Test seems flaky on ARM.
 test-spaces/LargeObjectSpace: PASS || FAIL
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 0e8a508..f3b018d 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -4078,6 +4078,14 @@
                                       "with({x:2}){other.eval('x+y')}"));
   result = script->Run();
   CHECK_EQ(3, result->Int32Value());
+
+  // Check that you cannot use 'eval.call' with another object than the
+  // current global object.
+  v8::TryCatch try_catch;
+  script =
+      Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
+  result = script->Run();
+  CHECK(try_catch.HasCaught());
 }
 
 
diff --git a/test/cctest/test-disasm-arm.cc b/test/cctest/test-disasm-arm.cc
index 7df292a..316b93a 100644
--- a/test/cctest/test-disasm-arm.cc
+++ b/test/cctest/test-disasm-arm.cc
@@ -50,7 +50,8 @@
 
 
 bool DisassembleAndCompare(byte* pc, const char* compare_string) {
-  disasm::Disassembler disasm;
+  disasm::NameConverter converter;
+  disasm::Disassembler disasm(converter);
   EmbeddedVector<char, 128> disasm_buffer;
 
   disasm.InstructionDecode(disasm_buffer, pc);
@@ -68,6 +69,9 @@
 }
 
 
+// Setup V8 to a state where we can at least run the assembler and
+// disassembler. Declare the variables and allocate the data structures used
+// in the rest of the macros.
 #define SETUP() \
   InitializeVM(); \
   Serializer::disable(); \
@@ -77,6 +81,10 @@
   bool failure = false;
 
 
+// This macro assembles one instruction using the preallocated assembler and
+// disassembles the generated instruction, comparing the output to the expected
+// value. If the comparison fails an error message is printed, but the test
+// continues to run until the end.
 #define COMPARE(asm_, compare_string) \
   { \
     int pc_offset = assm.pc_offset(); \
@@ -86,8 +94,10 @@
   }
 
 
-#define OUTPUT() \
-  if (failure) { \
+// Verify that all invocations of the COMPARE macro passed successfully.
+// Exit with a failure if at least one of the tests failed.
+#define VERIFY_RUN() \
+if (failure) { \
     V8_Fatal(__FILE__, __LINE__, "ARM Disassembler tests failed.\n"); \
   }
 
@@ -239,7 +249,7 @@
   COMPARE(mvn(r5, Operand(r4), SetCC, cc),
           "31f05004       mvnccs r5, r4");
 
-  OUTPUT();
+  VERIFY_RUN();
 }
 
 
@@ -268,5 +278,5 @@
   COMPARE(eor(r4, r1, Operand(0x10000000), SetCC, cc),
           "32314201       eorccs r4, r1, #268435456");
 
-  OUTPUT();
+  VERIFY_RUN();
 }
diff --git a/test/cctest/test-flags.cc b/test/cctest/test-flags.cc
index a3aa4b2..9019a89 100644
--- a/test/cctest/test-flags.cc
+++ b/test/cctest/test-flags.cc
@@ -168,3 +168,67 @@
   const char* str = "       --testing-int-flag 0      --testing_float_flag    ";
   CHECK_EQ(3, FlagList::SetFlagsFromString(str, strlen(str)));
 }
+
+
+TEST(FlagsJSArguments1) {
+  SetFlagsToDefault();
+  int argc = 6;
+  const char* argv[] = {"TestJSArgs1",
+                        "--testing-int-flag", "42",
+                        "--", "testing-float-flag", "7"};
+  CHECK_EQ(0, FlagList::SetFlagsFromCommandLine(&argc,
+                                                const_cast<char **>(argv),
+                                                true));
+  CHECK_EQ(42, FLAG_testing_int_flag);
+  CHECK_EQ(2.5, FLAG_testing_float_flag);
+  CHECK_EQ(2, FLAG_js_arguments.argc());
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[0], "testing-float-flag"));
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[1], "7"));
+  CHECK_EQ(1, argc);
+}
+
+
+TEST(FlagsJSArguments1b) {
+  SetFlagsToDefault();
+  const char* str = "--testing-int-flag 42 -- testing-float-flag 7";
+  CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+  CHECK_EQ(42, FLAG_testing_int_flag);
+  CHECK_EQ(2.5, FLAG_testing_float_flag);
+  CHECK_EQ(2, FLAG_js_arguments.argc());
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[0], "testing-float-flag"));
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[1], "7"));
+}
+
+
+TEST(FlagsJSArguments2) {
+  SetFlagsToDefault();
+  const char* str = "--testing-int-flag 42 --js-arguments testing-float-flag 7";
+  CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+  CHECK_EQ(42, FLAG_testing_int_flag);
+  CHECK_EQ(2.5, FLAG_testing_float_flag);
+  CHECK_EQ(2, FLAG_js_arguments.argc());
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[0], "testing-float-flag"));
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[1], "7"));
+}
+
+
+TEST(FlagsJSArguments3) {
+  SetFlagsToDefault();
+  const char* str = "--testing-int-flag 42 --js-arguments=testing-float-flag 7";
+  CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+  CHECK_EQ(42, FLAG_testing_int_flag);
+  CHECK_EQ(2.5, FLAG_testing_float_flag);
+  CHECK_EQ(2, FLAG_js_arguments.argc());
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[0], "testing-float-flag"));
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[1], "7"));
+}
+
+
+TEST(FlagsJSArguments4) {
+  SetFlagsToDefault();
+  const char* str = "--testing-int-flag 42 --";
+  CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+  CHECK_EQ(42, FLAG_testing_int_flag);
+  CHECK_EQ(0, FLAG_js_arguments.argc());
+}
+
diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status
index a5448c4..6a6b379 100644
--- a/test/mozilla/mozilla.status
+++ b/test/mozilla/mozilla.status
@@ -570,10 +570,7 @@
 js1_5/Regress/regress-303213: FAIL
 
 
-# Bug 1193440: Ignore Unicode BOM characters when scanning.
-ecma_3/extensions/regress-368516: FAIL
-
-# Bug 1202592:New ecma_3/String/15.5.4.11 is failing.
+# Bug 1202592: New ecma_3/String/15.5.4.11 is failing.
 ecma_3/String/15.5.4.11: FAIL
 
 # Bug 1202597: New js1_5/Expressions/regress-394673 is failing.
diff --git a/tools/visual_studio/arm.vsprops b/tools/visual_studio/arm.vsprops
new file mode 100644
index 0000000..0e37d41
--- /dev/null
+++ b/tools/visual_studio/arm.vsprops
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="arm"
+	>
+	<Tool
+		Name="VCCLCompilerTool"
+		PreprocessorDefinitions="ARM"
+		DisableSpecificWarnings="4996"
+	/>
+</VisualStudioPropertySheet>
diff --git a/tools/visual_studio/v8_arm.sln b/tools/visual_studio/v8_arm.sln
new file mode 100644
index 0000000..2dc6cf5
--- /dev/null
+++ b/tools/visual_studio/v8_arm.sln
@@ -0,0 +1,74 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8", "v8.vcproj", "{21E22961-22BF-4493-BD3A-868F93DA5179}"
+	ProjectSection(ProjectDependencies) = postProject
+		{EC8B7909-62AF-470D-A75D-E1D89C837142} = {EC8B7909-62AF-470D-A75D-E1D89C837142}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_shell_sample", "v8_shell_sample.vcproj", "{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}"
+	ProjectSection(ProjectDependencies) = postProject
+		{EC8B7909-62AF-470D-A75D-E1D89C837142} = {EC8B7909-62AF-470D-A75D-E1D89C837142}
+		{21E22961-22BF-4493-BD3A-868F93DA5179} = {21E22961-22BF-4493-BD3A-868F93DA5179}
+	EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{E131F77D-B713-48F3-B86D-097ECDCC4C3A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_process_sample", "v8_process_sample.vcproj", "{EF019874-D38A-40E3-B17C-DB5923F0A79C}"
+	ProjectSection(ProjectDependencies) = postProject
+		{21E22961-22BF-4493-BD3A-868F93DA5179} = {21E22961-22BF-4493-BD3A-868F93DA5179}
+	EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{AD933CE2-1303-448E-89C8-60B1FDD18EC3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d8", "d8.vcproj", "{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}"
+	ProjectSection(ProjectDependencies) = postProject
+		{21E22961-22BF-4493-BD3A-868F93DA5179} = {21E22961-22BF-4493-BD3A-868F93DA5179}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_base", "v8_base_arm.vcproj", "{EC8B7909-62AF-470D-A75D-E1D89C837142}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_cctest", "v8_cctest_arm.vcproj", "{97ECC711-7430-4FC4-90FD-004DA880E72A}"
+	ProjectSection(ProjectDependencies) = postProject
+		{21E22961-22BF-4493-BD3A-868F93DA5179} = {21E22961-22BF-4493-BD3A-868F93DA5179}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{21E22961-22BF-4493-BD3A-868F93DA5179}.Debug|Win32.ActiveCfg = Debug|Win32
+		{21E22961-22BF-4493-BD3A-868F93DA5179}.Debug|Win32.Build.0 = Debug|Win32
+		{21E22961-22BF-4493-BD3A-868F93DA5179}.Release|Win32.ActiveCfg = Release|Win32
+		{21E22961-22BF-4493-BD3A-868F93DA5179}.Release|Win32.Build.0 = Release|Win32
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Debug|Win32.ActiveCfg = Debug|Win32
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Debug|Win32.Build.0 = Debug|Win32
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Release|Win32.ActiveCfg = Release|Win32
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Release|Win32.Build.0 = Release|Win32
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C}.Debug|Win32.ActiveCfg = Debug|Win32
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C}.Debug|Win32.Build.0 = Debug|Win32
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C}.Release|Win32.ActiveCfg = Release|Win32
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C}.Release|Win32.Build.0 = Release|Win32
+		{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Debug|Win32.ActiveCfg = Debug|Win32
+		{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Debug|Win32.Build.0 = Debug|Win32
+		{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Release|Win32.ActiveCfg = Release|Win32
+		{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Release|Win32.Build.0 = Release|Win32
+		{EC8B7909-62AF-470D-A75D-E1D89C837142}.Debug|Win32.ActiveCfg = Debug|Win32
+		{EC8B7909-62AF-470D-A75D-E1D89C837142}.Debug|Win32.Build.0 = Debug|Win32
+		{EC8B7909-62AF-470D-A75D-E1D89C837142}.Release|Win32.ActiveCfg = Release|Win32
+		{EC8B7909-62AF-470D-A75D-E1D89C837142}.Release|Win32.Build.0 = Release|Win32
+		{97ECC711-7430-4FC4-90FD-004DA880E72A}.Debug|Win32.ActiveCfg = Debug|Win32
+		{97ECC711-7430-4FC4-90FD-004DA880E72A}.Debug|Win32.Build.0 = Debug|Win32
+		{97ECC711-7430-4FC4-90FD-004DA880E72A}.Release|Win32.ActiveCfg = Release|Win32
+		{97ECC711-7430-4FC4-90FD-004DA880E72A}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119} = {E131F77D-B713-48F3-B86D-097ECDCC4C3A}
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C} = {E131F77D-B713-48F3-B86D-097ECDCC4C3A}
+		{97ECC711-7430-4FC4-90FD-004DA880E72A} = {AD933CE2-1303-448E-89C8-60B1FDD18EC3}
+	EndGlobalSection
+EndGlobal
diff --git a/tools/visual_studio/v8_base.vcproj b/tools/visual_studio/v8_base.vcproj
index 37e604d..f1d6d07 100644
--- a/tools/visual_studio/v8_base.vcproj
+++ b/tools/visual_studio/v8_base.vcproj
@@ -285,14 +285,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\src\assembler-arm-inl.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\src\assembler-arm.h"
-				>
-			</File>
-			<File
 				RelativePath="..\..\src\assembler-ia32-inl.h"
 				>
 			</File>
@@ -369,10 +361,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\src\codegen-arm.h"
-				>
-			</File>
-			<File
 				RelativePath="..\..\src\codegen-ia32.cc"
 				>
 			</File>
@@ -493,14 +481,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\src\frames-arm-inl.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\src\frames-arm.h"
-				>
-			</File>
-			<File
 				RelativePath="..\..\src\frames-ia32-inl.h"
 				>
 			</File>
@@ -613,10 +593,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\src\macro-assembler-arm.h"
-				>
-			</File>
-			<File
 				RelativePath="..\..\src\macro-assembler-ia32.cc"
 				>
 			</File>
diff --git a/tools/visual_studio/v8_base_arm.vcproj b/tools/visual_studio/v8_base_arm.vcproj
new file mode 100644
index 0000000..ca9dc95
--- /dev/null
+++ b/tools/visual_studio/v8_base_arm.vcproj
@@ -0,0 +1,916 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="v8_base"
+	ProjectGUID="{EC8B7909-62AF-470D-A75D-E1D89C837142}"
+	RootNamespace="v8_base"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="4"
+			InheritedPropertySheets=".\common.vsprops;.\debug.vsprops;.\arm.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\lib\v8_base.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="4"
+			InheritedPropertySheets=".\common.vsprops;.\release.vsprops;.\arm.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="jscre"
+			>
+			<File
+				RelativePath="..\..\src\third_party\jscre\pcre_compile.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UndefinePreprocessorDefinitions="DEBUG"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UndefinePreprocessorDefinitions="DEBUG"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\src\third_party\jscre\pcre_exec.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UndefinePreprocessorDefinitions="DEBUG"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UndefinePreprocessorDefinitions="DEBUG"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\src\third_party\jscre\pcre_internal.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\third_party\jscre\pcre_tables.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UndefinePreprocessorDefinitions="DEBUG"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UndefinePreprocessorDefinitions="DEBUG"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\src\third_party\jscre\pcre_ucp_searchfuncs.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UndefinePreprocessorDefinitions="DEBUG"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UndefinePreprocessorDefinitions="DEBUG"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\src\third_party\jscre\pcre_xclass.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UndefinePreprocessorDefinitions="DEBUG"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UndefinePreprocessorDefinitions="DEBUG"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="dtoa"
+			>
+			<File
+				RelativePath="..\..\src\dtoa-config.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						DisableSpecificWarnings="4018;4244"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						DisableSpecificWarnings="4018;4244"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="src"
+			>
+			<File
+				RelativePath="..\..\src\accessors.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\accessors.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\allocation.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\allocation.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\api.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\api.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\arguments.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler-arm-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ast.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ast.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bootstrapper.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bootstrapper.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\builtins-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\builtins.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\builtins.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\char-predicates-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\char-predicates.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\checks.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\checks.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\code-stubs.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\code-stubs.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\code.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\compilation-cache.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\compilation-cache.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\compiler.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\compiler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\constants-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\contexts.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\contexts.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\conversions-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\conversions.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\conversions.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\counters.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\counters.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\cpu-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\cpu.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\dateparser.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\dateparser.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\debug.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\debug.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\disassembler.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\disassembler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\execution.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\execution.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\factory.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\factory.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\flags.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\flags.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\global-handles.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\global-handles.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\globals.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\handles-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\handles.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\handles.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\hashmap.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\hashmap.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\heap-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\heap.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\heap.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ic-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ic-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ic.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ic.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\interceptors.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jsregexp.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jsregexp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\list-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\list.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\log.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\log.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\macro-assembler-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\macro-assembler-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\macro-assembler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\mark-compact.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\mark-compact.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\memory.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\messages.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\messages.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\natives.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\objects-debug.cc"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\src\objects-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\objects.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\objects.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\parser.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\parser.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\platform-win32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\platform.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\prettyprinter.cc"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\src\prettyprinter.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\property.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\property.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\rewriter.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\rewriter.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\runtime.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\runtime.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scanner.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scanner.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scopeinfo.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scopeinfo.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scopes.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scopes.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\serialize.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\serialize.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\shell.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\snapshot-common.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\snapshot.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\simulator-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\simulator-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\spaces-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\spaces.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\spaces.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\string-stream.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\string-stream.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\stub-cache-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\stub-cache.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\stub-cache.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\token.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\token.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\top.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\top.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\unicode-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\unicode.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\usage-analyzer.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\usage-analyzer.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\utils.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\utils.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8-counters.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8-counters.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8threads.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8threads.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\variables.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\variables.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\zone-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\zone.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\zone.h"
+				>
+			</File>
+			<Filter
+				Name="third party"
+				>
+				<File
+					RelativePath="..\..\src\disasm-arm.cc"
+					>
+				</File>
+				<File
+					RelativePath="..\..\src\disasm.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="generated files"
+				>
+				<File
+					RelativePath="..\..\src\unicode.cc"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="include"
+			>
+			<File
+				RelativePath="..\..\include\debug.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\v8.h"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/tools/visual_studio/v8_cctest_arm.vcproj b/tools/visual_studio/v8_cctest_arm.vcproj
new file mode 100644
index 0000000..44812f0
--- /dev/null
+++ b/tools/visual_studio/v8_cctest_arm.vcproj
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="v8_cctest"
+	ProjectGUID="{97ECC711-7430-4FC4-90FD-004DA880E72A}"
+	RootNamespace="v8_cctest"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\debug.vsprops;.\arm.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\release.vsprops;.\arm.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath="..\..\test\cctest\cctest.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-alloc.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-api.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-assembler-arm.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-ast.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-compiler.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-conversions.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-debug.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-decls.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-disasm-arm.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-flags.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-hashmap.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-heap.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-lock.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-mark-compact.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-platform-win32.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-serialize.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-spaces.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-strings.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-utils.cc"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>