Merge WebKit at r59636: Update v8 to r4660.

Will build and run with current webkit.

Change-Id: I57bae621fd894da363ba84e1757ad09eb7c502b9
diff --git a/src/SConscript b/src/SConscript
index 5add999..b68f6d1 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -58,6 +58,7 @@
     debug.cc
     disassembler.cc
     diy-fp.cc
+    dtoa.cc
     execution.cc
     factory.cc
     flags.cc
@@ -68,6 +69,7 @@
     func-name-inferrer.cc
     global-handles.cc
     fast-dtoa.cc
+    fixed-dtoa.cc
     handles.cc
     hashmap.cc
     heap-profiler.cc
diff --git a/src/api.cc b/src/api.cc
index 4709a15..a4c38b7 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1438,7 +1438,7 @@
 
 
 int Message::GetLineNumber() const {
-  ON_BAILOUT("v8::Message::GetLineNumber()", return -1);
+  ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
   ENTER_V8;
   HandleScope scope;
   EXCEPTION_PREAMBLE();
@@ -1470,7 +1470,7 @@
 
 
 int Message::GetStartColumn() const {
-  if (IsDeadCheck("v8::Message::GetStartColumn()")) return 0;
+  if (IsDeadCheck("v8::Message::GetStartColumn()")) return kNoColumnInfo;
   ENTER_V8;
   HandleScope scope;
   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
@@ -1485,7 +1485,7 @@
 
 
 int Message::GetEndColumn() const {
-  if (IsDeadCheck("v8::Message::GetEndColumn()")) return 0;
+  if (IsDeadCheck("v8::Message::GetEndColumn()")) return kNoColumnInfo;
   ENTER_V8;
   HandleScope scope;
   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
@@ -1525,6 +1525,118 @@
 }
 
 
+// --- S t a c k T r a c e ---
+
+Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
+  if (IsDeadCheck("v8::StackTrace::GetFrame()")) return Local<StackFrame>();
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::JSArray> self = Utils::OpenHandle(this);
+  i::Handle<i::JSObject> obj(i::JSObject::cast(self->GetElement(index)));
+  return scope.Close(Utils::StackFrameToLocal(obj));
+}
+
+
+int StackTrace::GetFrameCount() const {
+  if (IsDeadCheck("v8::StackTrace::GetFrameCount()")) return -1;
+  ENTER_V8;
+  return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
+}
+
+
+Local<Array> StackTrace::AsArray() {
+  if (IsDeadCheck("v8::StackTrace::AsArray()")) Local<Array>();
+  ENTER_V8;
+  return Utils::ToLocal(Utils::OpenHandle(this));
+}
+
+
+Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
+    StackTraceOptions options) {
+  if (IsDeadCheck("v8::StackTrace::CurrentStackTrace()")) Local<StackTrace>();
+  ENTER_V8;
+  return i::Top::CaptureCurrentStackTrace(frame_limit, options);
+}
+
+
+// --- S t a c k F r a m e ---
+
+int StackFrame::GetLineNumber() const {
+  if (IsDeadCheck("v8::StackFrame::GetLineNumber()")) {
+    return Message::kNoLineNumberInfo;
+  }
+  ENTER_V8;
+  i::HandleScope scope;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> line = GetProperty(self, "lineNumber");
+  if (!line->IsSmi()) {
+    return Message::kNoLineNumberInfo;
+  }
+  return i::Smi::cast(*line)->value();
+}
+
+
+int StackFrame::GetColumn() const {
+  if (IsDeadCheck("v8::StackFrame::GetColumn()")) {
+    return Message::kNoColumnInfo;
+  }
+  ENTER_V8;
+  i::HandleScope scope;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> column = GetProperty(self, "column");
+  if (!column->IsSmi()) {
+    return Message::kNoColumnInfo;
+  }
+  return i::Smi::cast(*column)->value();
+}
+
+
+Local<String> StackFrame::GetScriptName() const {
+  if (IsDeadCheck("v8::StackFrame::GetScriptName()")) return Local<String>();
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> name = GetProperty(self, "scriptName");
+  if (!name->IsString()) {
+    return Local<String>();
+  }
+  return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
+}
+
+
+Local<String> StackFrame::GetFunctionName() const {
+  if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> name = GetProperty(self, "functionName");
+  if (!name->IsString()) {
+    return Local<String>();
+  }
+  return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
+}
+
+
+bool StackFrame::IsEval() const {
+  if (IsDeadCheck("v8::StackFrame::IsEval()")) return false;
+  ENTER_V8;
+  i::HandleScope scope;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
+  return is_eval->IsTrue();
+}
+
+
+bool StackFrame::IsConstructor() const {
+  if (IsDeadCheck("v8::StackFrame::IsConstructor()")) return false;
+  ENTER_V8;
+  i::HandleScope scope;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
+  return is_constructor->IsTrue();
+}
+
+
 // --- D a t a ---
 
 bool Value::IsUndefined() const {
@@ -2185,10 +2297,10 @@
       int postfix_len = i::StrLength(postfix);
 
       int buf_len = prefix_len + str_len + postfix_len;
-      char* buf = i::NewArray<char>(buf_len);
+      i::ScopedVector<char> buf(buf_len);
 
       // Write prefix.
-      char* ptr = buf;
+      char* ptr = buf.start();
       memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
       ptr += prefix_len;
 
@@ -2200,8 +2312,7 @@
       memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
 
       // Copy the buffer into a heap-allocated string and return it.
-      Local<String> result = v8::String::New(buf, buf_len);
-      i::DeleteArray(buf);
+      Local<String> result = v8::String::New(buf.start(), buf_len);
       return result;
     }
   }
diff --git a/src/api.h b/src/api.h
index 7b88112..e7b1394 100644
--- a/src/api.h
+++ b/src/api.h
@@ -192,6 +192,10 @@
       v8::internal::Handle<v8::internal::Proxy> obj);
   static inline Local<Message> MessageToLocal(
       v8::internal::Handle<v8::internal::Object> obj);
+  static inline Local<StackTrace> StackTraceToLocal(
+      v8::internal::Handle<v8::internal::JSArray> obj);
+  static inline Local<StackFrame> StackFrameToLocal(
+      v8::internal::Handle<v8::internal::JSObject> obj);
   static inline Local<Number> NumberToLocal(
       v8::internal::Handle<v8::internal::Object> obj);
   static inline Local<Integer> IntegerToLocal(
@@ -227,6 +231,10 @@
       OpenHandle(const Function* data);
   static inline v8::internal::Handle<v8::internal::JSObject>
       OpenHandle(const Message* message);
+  static inline v8::internal::Handle<v8::internal::JSArray>
+      OpenHandle(const StackTrace* stack_trace);
+  static inline v8::internal::Handle<v8::internal::JSObject>
+      OpenHandle(const StackFrame* stack_frame);
   static inline v8::internal::Handle<v8::internal::Context>
       OpenHandle(const v8::Context* context);
   static inline v8::internal::Handle<v8::internal::SignatureInfo>
@@ -275,6 +283,8 @@
 MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature)
 MAKE_TO_LOCAL(ToLocal, TypeSwitchInfo, TypeSwitch)
 MAKE_TO_LOCAL(MessageToLocal, Object, Message)
+MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace)
+MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame)
 MAKE_TO_LOCAL(NumberToLocal, Object, Number)
 MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
 MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
@@ -305,6 +315,8 @@
 MAKE_OPEN_HANDLE(Message, JSObject)
 MAKE_OPEN_HANDLE(Context, Context)
 MAKE_OPEN_HANDLE(External, Proxy)
+MAKE_OPEN_HANDLE(StackTrace, JSArray)
+MAKE_OPEN_HANDLE(StackFrame, JSObject)
 
 #undef MAKE_OPEN_HANDLE
 
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 7990368..f1f59ce 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -1157,6 +1157,35 @@
 }
 
 
+void Assembler::ldrd(Register dst, const MemOperand& src, Condition cond) {
+  ASSERT(src.rm().is(no_reg));
+#ifdef CAN_USE_ARMV7_INSTRUCTIONS
+  addrmod3(cond | B7 | B6 | B4, dst, src);
+#else
+  ldr(dst, src, cond);
+  MemOperand src1(src);
+  src1.set_offset(src1.offset() + 4);
+  Register dst1(dst);
+  dst1.code_ = dst1.code_ + 1;
+  ldr(dst1, src1, cond);
+#endif
+}
+
+
+void Assembler::strd(Register src, const MemOperand& dst, Condition cond) {
+  ASSERT(dst.rm().is(no_reg));
+#ifdef CAN_USE_ARMV7_INSTRUCTIONS
+  addrmod3(cond | B7 | B6 | B5 | B4, src, dst);
+#else
+  str(src, dst, cond);
+  MemOperand dst1(dst);
+  dst1.set_offset(dst1.offset() + 4);
+  Register src1(src);
+  src1.code_ = src1.code_ + 1;
+  str(src1, dst1, cond);
+#endif
+}
+
 // Load/Store multiple instructions.
 void Assembler::ldm(BlockAddrMode am,
                     Register base,
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 839ed67..61b84d4 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -448,6 +448,18 @@
   explicit MemOperand(Register rn, Register rm,
                       ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
 
+  void set_offset(int32_t offset) {
+      ASSERT(rm_.is(no_reg));
+      offset_ = offset;
+  }
+
+  uint32_t offset() {
+      ASSERT(rm_.is(no_reg));
+      return offset_;
+  }
+
+  Register rm() const {return rm_;}
+
  private:
   Register rn_;  // base
   Register rm_;  // register offset
@@ -755,6 +767,8 @@
   void strh(Register src, const MemOperand& dst, Condition cond = al);
   void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
   void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
+  void ldrd(Register dst, const MemOperand& src, Condition cond = al);
+  void strd(Register src, const MemOperand& dst, Condition cond = al);
 
   // Load/Store multiple instructions
   void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index 7bb8c46..5718cb3 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -107,7 +107,7 @@
   // Allocate the JSArray object together with space for a fixed array with the
   // requested elements.
   int size = JSArray::kSize + FixedArray::SizeFor(initial_capacity);
-  __ AllocateInNewSpace(size / kPointerSize,
+  __ AllocateInNewSpace(size,
                         result,
                         scratch2,
                         scratch3,
@@ -191,7 +191,7 @@
   // keeps the code below free of special casing for the empty array.
   int size = JSArray::kSize +
              FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
-  __ AllocateInNewSpace(size / kPointerSize,
+  __ AllocateInNewSpace(size,
                         result,
                         elements_array_end,
                         scratch1,
@@ -208,12 +208,13 @@
   __ add(elements_array_end,
          elements_array_end,
          Operand(array_size, ASR, kSmiTagSize));
-  __ AllocateInNewSpace(elements_array_end,
-                        result,
-                        scratch1,
-                        scratch2,
-                        gc_required,
-                        TAG_OBJECT);
+  __ AllocateInNewSpace(
+      elements_array_end,
+      result,
+      scratch1,
+      scratch2,
+      gc_required,
+      static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
 
   // Allocated the JSArray. Now initialize the fields except for the elements
   // array.
@@ -561,7 +562,7 @@
     // r2: initial map
     // r7: undefined
     __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
-    __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, NO_ALLOCATION_FLAGS);
+    __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS);
 
     // Allocated the JSObject, now initialize the fields. Map is set to initial
     // map and properties and elements are set to empty fixed array.
@@ -632,12 +633,13 @@
     // r5: start of next object
     // r7: undefined
     __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize));
-    __ AllocateInNewSpace(r0,
-                          r5,
-                          r6,
-                          r2,
-                          &undo_allocation,
-                          RESULT_CONTAINS_TOP);
+    __ AllocateInNewSpace(
+        r0,
+        r5,
+        r6,
+        r2,
+        &undo_allocation,
+        static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
 
     // Initialize the FixedArray.
     // r1: constructor
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index dea0b63..68ae026 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -33,6 +33,7 @@
 #include "debug.h"
 #include "ic-inl.h"
 #include "jsregexp.h"
+#include "jump-target-light-inl.h"
 #include "parser.h"
 #include "regexp-macro-assembler.h"
 #include "regexp-stack.h"
@@ -40,10 +41,12 @@
 #include "runtime.h"
 #include "scopes.h"
 #include "virtual-frame-inl.h"
+#include "virtual-frame-arm-inl.h"
 
 namespace v8 {
 namespace internal {
 
+
 #define __ ACCESS_MASM(masm_)
 
 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
@@ -191,7 +194,7 @@
       frame_->AllocateStackSlots();
 
       VirtualFrame::SpilledScope spilled_scope(frame_);
-      int heap_slots = scope()->num_heap_slots();
+      int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
       if (heap_slots > 0) {
         // Allocate local context.
         // Get outer context and create a new context based on it.
@@ -274,7 +277,7 @@
 
     // Initialize the function return target after the locals are set
     // up, because it needs the expected frame height from the frame.
-    function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
+    function_return_.SetExpectedHeight();
     function_return_is_shadowed_ = false;
 
     // Generate code to 'execute' declarations and initialize functions
@@ -1143,44 +1146,66 @@
       int shift_value = int_value & 0x1f;  // least significant 5 bits
       DeferredCode* deferred =
         new DeferredInlineSmiOperation(op, shift_value, false, mode, tos);
-      __ tst(tos, Operand(kSmiTagMask));
-      deferred->Branch(ne);
-      __ mov(scratch, Operand(tos, ASR, kSmiTagSize));  // remove tags
+      uint32_t problematic_mask = kSmiTagMask;
+      // For unsigned shift by zero all negative smis are problematic.
+      if (shift_value == 0 && op == Token::SHR) problematic_mask |= 0x80000000;
+      __ tst(tos, Operand(problematic_mask));
+      deferred->Branch(ne);  // Go slow for problematic input.
       switch (op) {
         case Token::SHL: {
           if (shift_value != 0) {
-            __ mov(scratch, Operand(scratch, LSL, shift_value));
+            int adjusted_shift = shift_value - kSmiTagSize;
+            ASSERT(adjusted_shift >= 0);
+            if (adjusted_shift != 0) {
+              __ mov(scratch, Operand(tos, LSL, adjusted_shift));
+              // Check that the *signed* result fits in a smi.
+              __ add(scratch2, scratch, Operand(0x40000000), SetCC);
+              deferred->Branch(mi);
+              __ mov(tos, Operand(scratch, LSL, kSmiTagSize));
+            } else {
+              // Check that the *signed* result fits in a smi.
+              __ add(scratch2, tos, Operand(0x40000000), SetCC);
+              deferred->Branch(mi);
+              __ mov(tos, Operand(tos, LSL, kSmiTagSize));
+            }
           }
-          // check that the *signed* result fits in a smi
-          __ add(scratch2, scratch, Operand(0x40000000), SetCC);
-          deferred->Branch(mi);
           break;
         }
         case Token::SHR: {
-          // LSR by immediate 0 means shifting 32 bits.
           if (shift_value != 0) {
+            __ mov(scratch, Operand(tos, ASR, kSmiTagSize));  // Remove tag.
+            // LSR by immediate 0 means shifting 32 bits.
             __ mov(scratch, Operand(scratch, LSR, shift_value));
+            if (shift_value == 1) {
+              // check that the *unsigned* result fits in a smi
+              // neither of the two high-order bits can be set:
+              // - 0x80000000: high bit would be lost when smi tagging
+              // - 0x40000000: this number would convert to negative when
+              // smi tagging these two cases can only happen with shifts
+              // by 0 or 1 when handed a valid smi
+              __ tst(scratch, Operand(0xc0000000));
+              deferred->Branch(ne);
+            }
+            __ mov(tos, Operand(scratch, LSL, kSmiTagSize));
           }
-          // check that the *unsigned* result fits in a smi
-          // neither of the two high-order bits can be set:
-          // - 0x80000000: high bit would be lost when smi tagging
-          // - 0x40000000: this number would convert to negative when
-          // smi tagging these two cases can only happen with shifts
-          // by 0 or 1 when handed a valid smi
-          __ tst(scratch, Operand(0xc0000000));
-          deferred->Branch(ne);
           break;
         }
         case Token::SAR: {
+          // In the ARM instructions set, ASR by immediate 0 means shifting 32
+          // bits.
           if (shift_value != 0) {
-            // ASR by immediate 0 means shifting 32 bits.
-            __ mov(scratch, Operand(scratch, ASR, shift_value));
+            // Do the shift and the tag removal in one operation.  If the shift
+            // is 31 bits (the highest possible value) then we emit the
+            // instruction as a shift by 0 which means shift arithmetically by
+            // 32.
+            __ mov(tos, Operand(tos, ASR, (kSmiTagSize + shift_value) & 0x1f));
+            // Put tag back.
+            __ mov(tos, Operand(tos, LSL, kSmiTagSize));
           }
           break;
         }
         default: UNREACHABLE();
       }
-      __ mov(tos, Operand(scratch, LSL, kSmiTagSize));
       deferred->BindExit();
       frame_->EmitPush(tos);
       break;
@@ -1486,8 +1511,7 @@
   // Then process it as a normal function call.
   __ ldr(r0, MemOperand(sp, 3 * kPointerSize));
   __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
-  __ str(r0, MemOperand(sp, 2 * kPointerSize));
-  __ str(r1, MemOperand(sp, 3 * kPointerSize));
+  __ strd(r0, MemOperand(sp, 2 * kPointerSize));
 
   CallFunctionStub call_function(2, NOT_IN_LOOP, NO_CALL_FUNCTION_FLAGS);
   frame_->CallStub(&call_function, 3);
@@ -1550,7 +1574,7 @@
   VirtualFrame::SpilledScope spilled_scope(frame_);
   Comment cmnt(masm_, "[ Block");
   CodeForStatementPosition(node);
-  node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
+  node->break_target()->SetExpectedHeight();
   VisitStatementsAndSpill(node->statements());
   if (node->break_target()->is_linked()) {
     node->break_target()->Bind();
@@ -1837,7 +1861,7 @@
   VirtualFrame::SpilledScope spilled_scope(frame_);
   Comment cmnt(masm_, "[ SwitchStatement");
   CodeForStatementPosition(node);
-  node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
+  node->break_target()->SetExpectedHeight();
 
   LoadAndSpill(node->tag());
 
@@ -1926,7 +1950,7 @@
   VirtualFrame::SpilledScope spilled_scope(frame_);
   Comment cmnt(masm_, "[ DoWhileStatement");
   CodeForStatementPosition(node);
-  node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
+  node->break_target()->SetExpectedHeight();
   JumpTarget body(JumpTarget::BIDIRECTIONAL);
   IncrementLoopNesting();
 
@@ -1936,14 +1960,14 @@
   ConditionAnalysis info = AnalyzeCondition(node->cond());
   switch (info) {
     case ALWAYS_TRUE:
-      node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
+      node->continue_target()->SetExpectedHeight();
       node->continue_target()->Bind();
       break;
     case ALWAYS_FALSE:
-      node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
+      node->continue_target()->SetExpectedHeight();
       break;
     case DONT_KNOW:
-      node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
+      node->continue_target()->SetExpectedHeight();
       body.Bind();
       break;
   }
@@ -2007,12 +2031,12 @@
   ConditionAnalysis info = AnalyzeCondition(node->cond());
   if (info == ALWAYS_FALSE) return;
 
-  node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
+  node->break_target()->SetExpectedHeight();
   IncrementLoopNesting();
 
   // Label the top of the loop with the continue target for the backward
   // CFG edge.
-  node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
+  node->continue_target()->SetExpectedHeight();
   node->continue_target()->Bind();
 
   if (info == DONT_KNOW) {
@@ -2061,17 +2085,17 @@
   ConditionAnalysis info = AnalyzeCondition(node->cond());
   if (info == ALWAYS_FALSE) return;
 
-  node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
+  node->break_target()->SetExpectedHeight();
   IncrementLoopNesting();
 
   // If there is no update statement, label the top of the loop with the
   // continue target, otherwise with the loop target.
   JumpTarget loop(JumpTarget::BIDIRECTIONAL);
   if (node->next() == NULL) {
-    node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
+    node->continue_target()->SetExpectedHeight();
     node->continue_target()->Bind();
   } else {
-    node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
+    node->continue_target()->SetExpectedHeight();
     loop.Bind();
   }
 
@@ -2276,11 +2300,11 @@
   // sp[4] : enumerable
   // Grab the current frame's height for the break and continue
   // targets only after all the state is pushed on the frame.
-  node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
-  node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
+  node->break_target()->SetExpectedHeight();
+  node->continue_target()->SetExpectedHeight();
 
-  __ ldr(r0, frame_->ElementAt(0));  // load the current count
-  __ ldr(r1, frame_->ElementAt(1));  // load the length
+  // Load the current count to r0, load the length to r1.
+  __ ldrd(r0, frame_->ElementAt(0));
   __ cmp(r0, r1);  // compare to the array length
   node->break_target()->Branch(hs);
 
@@ -2767,44 +2791,13 @@
     JumpTarget slow;
     JumpTarget done;
 
-    // Generate fast-case code for variables that might be shadowed by
-    // eval-introduced variables.  Eval is used a lot without
-    // introducing variables.  In those cases, we do not want to
-    // perform a runtime call for all variables in the scope
-    // containing the eval.
-    if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
-      LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow);
-      // If there was no control flow to slow, we can exit early.
-      if (!slow.is_linked()) {
-        frame_->EmitPush(r0);
-        return;
-      }
-      frame_->SpillAll();
-
-      done.Jump();
-
-    } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
-      frame_->SpillAll();
-      Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
-      // Only generate the fast case for locals that rewrite to slots.
-      // This rules out argument loads.
-      if (potential_slot != NULL) {
-        __ ldr(r0,
-               ContextSlotOperandCheckExtensions(potential_slot,
-                                                 r1,
-                                                 r2,
-                                                 &slow));
-        if (potential_slot->var()->mode() == Variable::CONST) {
-          __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
-          __ cmp(r0, ip);
-          __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
-        }
-        // There is always control flow to slow from
-        // ContextSlotOperandCheckExtensions so we have to jump around
-        // it.
-        done.Jump();
-      }
-    }
+    // Generate fast case for loading from slots that correspond to
+    // local/global variables or arguments unless they are shadowed by
+    // eval-introduced bindings.
+    EmitDynamicLoadFromSlotFastCase(slot,
+                                    typeof_state,
+                                    &slow,
+                                    &done);
 
     slow.Bind();
     VirtualFrame::SpilledScope spilled_scope(frame_);
@@ -3019,6 +3012,67 @@
 }
 
 
+void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot,
+                                                    TypeofState typeof_state,
+                                                    JumpTarget* slow,
+                                                    JumpTarget* done) {
+  // Generate fast-case code for variables that might be shadowed by
+  // eval-introduced variables.  Eval is used a lot without
+  // introducing variables.  In those cases, we do not want to
+  // perform a runtime call for all variables in the scope
+  // containing the eval.
+  if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
+    LoadFromGlobalSlotCheckExtensions(slot, typeof_state, slow);
+    frame_->SpillAll();
+    done->Jump();
+
+  } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
+    frame_->SpillAll();
+    Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
+    Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
+    if (potential_slot != NULL) {
+      // Generate fast case for locals that rewrite to slots.
+      __ ldr(r0,
+             ContextSlotOperandCheckExtensions(potential_slot,
+                                               r1,
+                                               r2,
+                                               slow));
+      if (potential_slot->var()->mode() == Variable::CONST) {
+        __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+        __ cmp(r0, ip);
+        __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
+      }
+      done->Jump();
+    } else if (rewrite != NULL) {
+      // Generate fast case for argument loads.
+      Property* property = rewrite->AsProperty();
+      if (property != NULL) {
+        VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
+        Literal* key_literal = property->key()->AsLiteral();
+        if (obj_proxy != NULL &&
+            key_literal != NULL &&
+            obj_proxy->IsArguments() &&
+            key_literal->handle()->IsSmi()) {
+          // Load arguments object if there are no eval-introduced
+          // variables. Then load the argument from the arguments
+          // object using keyed load.
+          __ ldr(r0,
+                 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
+                                                   r1,
+                                                   r2,
+                                                   slow));
+          frame_->EmitPush(r0);
+          __ mov(r1, Operand(key_literal->handle()));
+          frame_->EmitPush(r1);
+          EmitKeyedLoad();
+          done->Jump();
+        }
+      }
+    }
+  }
+}
+
+
 void CodeGenerator::VisitSlot(Slot* node) {
 #ifdef DEBUG
   int original_height = frame_->height();
@@ -3473,7 +3527,8 @@
   if (node->is_compound()) {
     // For a compound assignment the right-hand side is a binary operation
     // between the current property value and the actual right-hand side.
-    // Load of the current value leaves receiver and key on the stack.
+    // Duplicate receiver and key for loading the current property value.
+    frame_->Dup2();
     EmitKeyedLoad();
     frame_->EmitPush(r0);
 
@@ -3702,9 +3757,30 @@
   } else if (var != NULL && var->slot() != NULL &&
              var->slot()->type() == Slot::LOOKUP) {
     // ----------------------------------
-    // JavaScript example: 'with (obj) foo(1, 2, 3)'  // foo is in obj
+    // JavaScript examples:
+    //
+    //  with (obj) foo(1, 2, 3)  // foo may be in obj.
+    //
+    //  function f() {};
+    //  function g() {
+    //    eval(...);
+    //    f();  // f could be in extension object.
+    //  }
     // ----------------------------------
 
+    // JumpTargets do not yet support merging frames so the frame must be
+    // spilled when jumping to these targets.
+    JumpTarget slow, done;
+
+    // Generate fast case for loading functions from slots that
+    // correspond to local/global variables or arguments unless they
+    // are shadowed by eval-introduced bindings.
+    EmitDynamicLoadFromSlotFastCase(var->slot(),
+                                    NOT_INSIDE_TYPEOF,
+                                    &slow,
+                                    &done);
+
+    slow.Bind();
     // Load the function
     frame_->EmitPush(cp);
     __ mov(r0, Operand(var->name()));
@@ -3716,7 +3792,20 @@
     frame_->EmitPush(r0);  // function
     frame_->EmitPush(r1);  // receiver
 
-    // Call the function.
+    // If fast case code has been generated, emit code to push the
+    // function and receiver and have the slow path jump around this
+    // code.
+    if (done.is_linked()) {
+      JumpTarget call;
+      call.Jump();
+      done.Bind();
+      frame_->EmitPush(r0);  // function
+      LoadGlobalReceiver(r1);  // receiver
+      call.Bind();
+    }
+
+    // Call the function. At this point, everything is spilled but the
+    // function and receiver are in r0 and r1.
     CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position());
     frame_->EmitPush(r0);
 
@@ -3767,19 +3856,23 @@
       // -------------------------------------------
 
       LoadAndSpill(property->obj());
+      if (!property->is_synthetic()) {
+        // Duplicate receiver for later use.
+        __ ldr(r0, MemOperand(sp, 0));
+        frame_->EmitPush(r0);
+      }
       LoadAndSpill(property->key());
       EmitKeyedLoad();
-      frame_->Drop();  // key
       // Put the function below the receiver.
       if (property->is_synthetic()) {
         // Use the global receiver.
-        frame_->Drop();
-        frame_->EmitPush(r0);
+        frame_->EmitPush(r0);  // Function.
         LoadGlobalReceiver(r0);
       } else {
-        frame_->EmitPop(r1);  // receiver
-        frame_->EmitPush(r0);  // function
-        frame_->EmitPush(r1);  // receiver
+        // Switch receiver and function.
+        frame_->EmitPop(r1);  // Receiver.
+        frame_->EmitPush(r0);  // Function.
+        frame_->EmitPush(r1);  // Receiver.
       }
 
       // Call the function.
@@ -4359,12 +4452,13 @@
         (JSRegExpResult::kSize + FixedArray::kHeaderSize) / kPointerSize;
     __ mov(r5, Operand(r1, LSR, kSmiTagSize + kSmiShiftSize));
     __ add(r2, r5, Operand(objects_size));
-    __ AllocateInNewSpace(r2,  // In: Size, in words.
-                          r0,  // Out: Start of allocation (tagged).
-                          r3,  // Scratch register.
-                          r4,  // Scratch register.
-                          &slowcase,
-                          TAG_OBJECT);
+    __ AllocateInNewSpace(
+        r2,  // In: Size, in words.
+        r0,  // Out: Start of allocation (tagged).
+        r3,  // Scratch register.
+        r4,  // Scratch register.
+        &slowcase,
+        static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
     // r0: Start of allocated area, object-tagged.
     // r1: Number of elements in array, as smi.
     // r5: Number of elements, untagged.
@@ -4837,7 +4931,6 @@
 #ifdef DEBUG
   int original_height = frame_->height();
 #endif
-  VirtualFrame::SpilledScope spilled_scope(frame_);
   Comment cmnt(masm_, "[ CountOperation");
 
   bool is_postfix = node->is_postfix();
@@ -4846,10 +4939,8 @@
   Variable* var = node->expression()->AsVariableProxy()->AsVariable();
   bool is_const = (var != NULL && var->mode() == Variable::CONST);
 
-  // Postfix: Make room for the result.
   if (is_postfix) {
-     __ mov(r0, Operand(0));
-     frame_->EmitPush(r0);
+    frame_->EmitPush(Operand(Smi::FromInt(0)));
   }
 
   // A constant reference is not saved to, so a constant reference is not a
@@ -4859,35 +4950,33 @@
       // Spoof the virtual frame to have the expected height (one higher
       // than on entry).
       if (!is_postfix) {
-        __ mov(r0, Operand(Smi::FromInt(0)));
-        frame_->EmitPush(r0);
+        frame_->EmitPush(Operand(Smi::FromInt(0)));
       }
       ASSERT_EQ(original_height + 1, frame_->height());
       return;
     }
+    // This pushes 0, 1 or 2 words on the object to be used later when updating
+    // the target.  It also pushes the current value of the target.
     target.GetValue();
-    frame_->EmitPop(r0);
 
     JumpTarget slow;
     JumpTarget exit;
 
-    // Load the value (1) into register r1.
-    __ mov(r1, Operand(Smi::FromInt(1)));
-
     // Check for smi operand.
-    __ tst(r0, Operand(kSmiTagMask));
+    Register value = frame_->PopToRegister();
+    __ tst(value, Operand(kSmiTagMask));
     slow.Branch(ne);
 
     // Postfix: Store the old value as the result.
     if (is_postfix) {
-      __ str(r0, frame_->ElementAt(target.size()));
+      frame_->SetElementAt(value, target.size());
     }
 
     // Perform optimistic increment/decrement.
     if (is_increment) {
-      __ add(r0, r0, Operand(r1), SetCC);
+      __ add(value, value, Operand(Smi::FromInt(1)), SetCC);
     } else {
-      __ sub(r0, r0, Operand(r1), SetCC);
+      __ sub(value, value, Operand(Smi::FromInt(1)), SetCC);
     }
 
     // If the increment/decrement didn't overflow, we're done.
@@ -4895,41 +4984,50 @@
 
     // Revert optimistic increment/decrement.
     if (is_increment) {
-      __ sub(r0, r0, Operand(r1));
+      __ sub(value, value, Operand(Smi::FromInt(1)));
     } else {
-      __ add(r0, r0, Operand(r1));
+      __ add(value, value, Operand(Smi::FromInt(1)));
     }
 
-    // Slow case: Convert to number.
+    // Slow case: Convert to number.  At this point the
+    // value to be incremented is in the value register..
     slow.Bind();
+
+    // Convert the operand to a number.
+    frame_->EmitPush(value);
+
     {
-      // Convert the operand to a number.
-      frame_->EmitPush(r0);
+      VirtualFrame::SpilledScope spilled(frame_);
       frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1);
-    }
-    if (is_postfix) {
-      // Postfix: store to result (on the stack).
-      __ str(r0, frame_->ElementAt(target.size()));
+
+      if (is_postfix) {
+        // Postfix: store to result (on the stack).
+        __ str(r0, frame_->ElementAt(target.size()));
+      }
+
+      // Compute the new value.
+      frame_->EmitPush(r0);
+      frame_->EmitPush(Operand(Smi::FromInt(1)));
+      if (is_increment) {
+        frame_->CallRuntime(Runtime::kNumberAdd, 2);
+      } else {
+        frame_->CallRuntime(Runtime::kNumberSub, 2);
+      }
     }
 
-    // Compute the new value.
-    __ mov(r1, Operand(Smi::FromInt(1)));
-    frame_->EmitPush(r0);
-    frame_->EmitPush(r1);
-    if (is_increment) {
-      frame_->CallRuntime(Runtime::kNumberAdd, 2);
-    } else {
-      frame_->CallRuntime(Runtime::kNumberSub, 2);
-    }
-
+    __ Move(value, r0);
     // Store the new value in the target if not const.
+    // At this point the answer is in the value register.
     exit.Bind();
-    frame_->EmitPush(r0);
+    frame_->EmitPush(value);
+    // Set the target with the result, leaving the result on
+    // top of the stack.  Removes the target from the stack if
+    // it has a non-zero size.
     if (!is_const) target.SetValue(NOT_CONST_INIT);
   }
 
   // Postfix: Discard the new value and use the old.
-  if (is_postfix) frame_->EmitPop(r0);
+  if (is_postfix) frame_->Pop();
   ASSERT_EQ(original_height + 1, frame_->height());
 }
 
@@ -5372,24 +5470,37 @@
 
 class DeferredReferenceGetKeyedValue: public DeferredCode {
  public:
-  DeferredReferenceGetKeyedValue() {
+  DeferredReferenceGetKeyedValue(Register key, Register receiver)
+      : key_(key), receiver_(receiver) {
     set_comment("[ DeferredReferenceGetKeyedValue");
   }
 
   virtual void Generate();
+
+ private:
+  Register key_;
+  Register receiver_;
 };
 
 
 void DeferredReferenceGetKeyedValue::Generate() {
+  ASSERT((key_.is(r0) && receiver_.is(r1)) ||
+         (key_.is(r1) && receiver_.is(r0)));
+
   Register scratch1 = VirtualFrame::scratch0();
   Register scratch2 = VirtualFrame::scratch1();
   __ DecrementCounter(&Counters::keyed_load_inline, 1, scratch1, scratch2);
   __ IncrementCounter(&Counters::keyed_load_inline_miss, 1, scratch1, scratch2);
 
+  // Ensure key in r0 and receiver in r1 to match keyed load ic calling
+  // convention.
+  if (key_.is(r1)) {
+    __ Swap(r0, r1, ip);
+  }
+
   // The rest of the instructions in the deferred code must be together.
   { Assembler::BlockConstPoolScope block_const_pool(masm_);
-    // Call keyed load IC. It has all arguments on the stack and the key in r0.
-    __ ldr(r0, MemOperand(sp, 0));
+    // Call keyed load IC. It has the arguments key and receiver in r0 and r1.
     Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
     // The call must be followed by a nop instruction to indicate that the
@@ -5522,14 +5633,14 @@
     __ IncrementCounter(&Counters::keyed_load_inline, 1,
                         frame_->scratch0(), frame_->scratch1());
 
-    // Load the receiver and key from the stack.
-    frame_->SpillAllButCopyTOSToR1R0();
-    Register receiver = r0;
-    Register key = r1;
+    // Load the key and receiver from the stack.
+    Register key = frame_->PopToRegister();
+    Register receiver = frame_->PopToRegister(key);
     VirtualFrame::SpilledScope spilled(frame_);
 
+    // The deferred code expects key and receiver in registers.
     DeferredReferenceGetKeyedValue* deferred =
-        new DeferredReferenceGetKeyedValue();
+        new DeferredReferenceGetKeyedValue(key, receiver);
 
     // Check that the receiver is a heap object.
     __ tst(receiver, Operand(kSmiTagMask));
@@ -5539,17 +5650,16 @@
     // property code which can be patched. Therefore the exact number of
     // instructions generated need to be fixed, so the constant pool is blocked
     // while generating this code.
-#ifdef DEBUG
-    int kInlinedKeyedLoadInstructions = 19;
-    Label check_inlined_codesize;
-    masm_->bind(&check_inlined_codesize);
-#endif
     { Assembler::BlockConstPoolScope block_const_pool(masm_);
       Register scratch1 = VirtualFrame::scratch0();
       Register scratch2 = VirtualFrame::scratch1();
       // Check the map. The null map used below is patched by the inline cache
       // code.
       __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
+#ifdef DEBUG
+    Label check_inlined_codesize;
+    masm_->bind(&check_inlined_codesize);
+#endif
       __ mov(scratch2, Operand(Factory::null_value()));
       __ cmp(scratch1, scratch2);
       deferred->Branch(ne);
@@ -5577,17 +5687,15 @@
       __ add(scratch1,
              scratch1,
              Operand(FixedArray::kHeaderSize - kHeapObjectTag));
-      __ ldr(r0,
+      __ ldr(scratch1,
              MemOperand(scratch1, key, LSL,
                         kPointerSizeLog2 - (kSmiTagSize + kSmiShiftSize)));
-      __ cmp(r0, scratch2);
-      // This is the only branch to deferred where r0 and r1 do not contain the
-      // receiver and key.  We can't just load undefined here because we have to
-      // check the prototype.
+      __ cmp(scratch1, scratch2);
       deferred->Branch(eq);
 
+      __ mov(r0, scratch1);
       // Make sure that the expected number of instructions are generated.
-      ASSERT_EQ(kInlinedKeyedLoadInstructions,
+      ASSERT_EQ(kInlinedKeyedLoadInstructionsAfterPatchSize,
                 masm_->InstructionsGeneratedSince(&check_inlined_codesize));
     }
 
@@ -5721,6 +5829,9 @@
       Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
       ASSERT(slot != NULL);
       cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
+      if (!persist_after_get_) {
+        cgen_->UnloadReference(this);
+      }
       break;
     }
 
@@ -5730,23 +5841,26 @@
       ASSERT(!is_global || var->is_global());
       cgen_->EmitNamedLoad(GetName(), is_global);
       cgen_->frame()->EmitPush(r0);
+      if (!persist_after_get_) {
+        cgen_->UnloadReference(this);
+      }
       break;
     }
 
     case KEYED: {
+      if (persist_after_get_) {
+        cgen_->frame()->Dup2();
+      }
       ASSERT(property != NULL);
       cgen_->EmitKeyedLoad();
       cgen_->frame()->EmitPush(r0);
+      if (!persist_after_get_) set_unloaded();
       break;
     }
 
     default:
       UNREACHABLE();
   }
-
-  if (!persist_after_get_) {
-    cgen_->UnloadReference(this);
-  }
 }
 
 
@@ -5806,7 +5920,7 @@
   __ pop(r3);
 
   // Attempt to allocate new JSFunction in new space.
-  __ AllocateInNewSpace(JSFunction::kSize / kPointerSize,
+  __ AllocateInNewSpace(JSFunction::kSize,
                         r0,
                         r1,
                         r2,
@@ -5847,7 +5961,7 @@
   int length = slots_ + Context::MIN_CONTEXT_SLOTS;
 
   // Attempt to allocate the context in new space.
-  __ AllocateInNewSpace(length + (FixedArray::kHeaderSize / kPointerSize),
+  __ AllocateInNewSpace(FixedArray::SizeFor(length),
                         r0,
                         r1,
                         r2,
@@ -5915,7 +6029,7 @@
 
   // Allocate both the JS array and the elements array in one big
   // allocation. This avoids multiple limit checks.
-  __ AllocateInNewSpace(size / kPointerSize,
+  __ AllocateInNewSpace(size,
                         r0,
                         r1,
                         r2,
@@ -6248,8 +6362,7 @@
     ConvertToDoubleStub stub1(r3, r2, r7, r6);
     __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
     // Load rhs to a double in r0, r1.
-    __ ldr(r1, FieldMemOperand(r0, HeapNumber::kValueOffset + kPointerSize));
-    __ ldr(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
+    __ ldrd(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
     __ pop(lr);
   }
 
@@ -6284,8 +6397,7 @@
   } else {
     __ push(lr);
     // Load lhs to a double in r2, r3.
-    __ ldr(r3, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize));
-    __ ldr(r2, FieldMemOperand(r1, HeapNumber::kValueOffset));
+    __ ldrd(r2, FieldMemOperand(r1, HeapNumber::kValueOffset));
     // Convert rhs to a double in r0, r1.
     __ mov(r7, Operand(r0));
     ConvertToDoubleStub stub2(r1, r0, r7, r6);
@@ -6449,10 +6561,8 @@
     __ sub(r7, r1, Operand(kHeapObjectTag));
     __ vldr(d7, r7, HeapNumber::kValueOffset);
   } else {
-    __ ldr(r2, FieldMemOperand(r1, HeapNumber::kValueOffset));
-    __ ldr(r3, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize));
-    __ ldr(r1, FieldMemOperand(r0, HeapNumber::kValueOffset + kPointerSize));
-    __ ldr(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
+    __ ldrd(r2, FieldMemOperand(r1, HeapNumber::kValueOffset));
+    __ ldrd(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
   }
   __ jmp(both_loaded_as_doubles);
 }
@@ -6829,8 +6939,7 @@
       __ vldr(d7, r7, HeapNumber::kValueOffset);
     } else {
       // Calling convention says that second double is in r2 and r3.
-      __ ldr(r2, FieldMemOperand(r0, HeapNumber::kValueOffset));
-      __ ldr(r3, FieldMemOperand(r0, HeapNumber::kValueOffset + 4));
+      __ ldrd(r2, FieldMemOperand(r0, HeapNumber::kValueOffset));
     }
     __ jmp(&finished_loading_r0);
     __ bind(&r0_is_smi);
@@ -6882,8 +6991,7 @@
       __ vldr(d6, r7, HeapNumber::kValueOffset);
     } else {
       // Calling convention says that first double is in r0 and r1.
-      __ ldr(r0, FieldMemOperand(r1, HeapNumber::kValueOffset));
-      __ ldr(r1, FieldMemOperand(r1, HeapNumber::kValueOffset + 4));
+      __ ldrd(r0, FieldMemOperand(r1, HeapNumber::kValueOffset));
     }
     __ jmp(&finished_loading_r1);
     __ bind(&r1_is_smi);
@@ -6954,8 +7062,7 @@
       __ stc(p1, cr8, MemOperand(r4, HeapNumber::kValueOffset));
   #else
       // Double returned in registers 0 and 1.
-      __ str(r0, FieldMemOperand(r5, HeapNumber::kValueOffset));
-      __ str(r1, FieldMemOperand(r5, HeapNumber::kValueOffset + 4));
+      __ strd(r0, FieldMemOperand(r5, HeapNumber::kValueOffset));
   #endif
       __ mov(r0, Operand(r5));
       // And we are done.
@@ -8206,6 +8313,22 @@
 
   // Get the prototype of the function (r4 is result, r2 is scratch).
   __ ldr(r1, MemOperand(sp, 0));
+  // r1 is function, r3 is map.
+
+  // Look up the function and the map in the instanceof cache.
+  Label miss;
+  __ LoadRoot(ip, Heap::kInstanceofCacheFunctionRootIndex);
+  __ cmp(r1, ip);
+  __ b(ne, &miss);
+  __ LoadRoot(ip, Heap::kInstanceofCacheMapRootIndex);
+  __ cmp(r3, ip);
+  __ b(ne, &miss);
+  __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
+  __ pop();
+  __ pop();
+  __ mov(pc, Operand(lr));
+
+  __ bind(&miss);
   __ TryGetFunctionPrototype(r1, r4, r2, &slow);
 
   // Check that the function prototype is a JS object.
@@ -8215,6 +8338,9 @@
   __ cmp(r5, Operand(LAST_JS_OBJECT_TYPE));
   __ b(gt, &slow);
 
+  __ StoreRoot(r1, Heap::kInstanceofCacheFunctionRootIndex);
+  __ StoreRoot(r3, Heap::kInstanceofCacheMapRootIndex);
+
   // Register mapping: r3 is object map and r4 is function prototype.
   // Get prototype of object into r2.
   __ ldr(r2, FieldMemOperand(r3, Map::kPrototypeOffset));
@@ -8232,12 +8358,14 @@
 
   __ bind(&is_instance);
   __ mov(r0, Operand(Smi::FromInt(0)));
+  __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
   __ pop();
   __ pop();
   __ mov(pc, Operand(lr));  // Return.
 
   __ bind(&is_not_instance);
   __ mov(r0, Operand(Smi::FromInt(1)));
+  __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
   __ pop();
   __ pop();
   __ mov(pc, Operand(lr));  // Return.
@@ -8324,8 +8452,7 @@
   __ str(r3, MemOperand(sp, 1 * kPointerSize));
 
   // Try the new space allocation. Start out with computing the size
-  // of the arguments object and the elements array (in words, not
-  // bytes because AllocateInNewSpace expects words).
+  // of the arguments object and the elements array in words.
   Label add_arguments_object;
   __ bind(&try_allocate);
   __ cmp(r1, Operand(0));
@@ -8336,7 +8463,13 @@
   __ add(r1, r1, Operand(Heap::kArgumentsObjectSize / kPointerSize));
 
   // Do the allocation of both objects in one go.
-  __ AllocateInNewSpace(r1, r0, r2, r3, &runtime, TAG_OBJECT);
+  __ AllocateInNewSpace(
+      r1,
+      r0,
+      r2,
+      r3,
+      &runtime,
+      static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
 
   // Get the arguments boilerplate from the current (global) context.
   int offset = Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX);
@@ -8406,9 +8539,9 @@
   // Just jump directly to runtime if native RegExp is not selected at compile
   // time or if regexp entry in generated code is turned off runtime switch or
   // at compilation.
-#ifndef V8_NATIVE_REGEXP
+#ifdef V8_INTERPRETED_REGEXP
   __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
-#else  // V8_NATIVE_REGEXP
+#else  // V8_INTERPRETED_REGEXP
   if (!FLAG_regexp_entry_native) {
     __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
     return;
@@ -8501,9 +8634,9 @@
   // string length. A negative value will be greater (unsigned comparison).
   __ ldr(r0, MemOperand(sp, kPreviousIndexOffset));
   __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &runtime);
+  __ b(ne, &runtime);
   __ cmp(r3, Operand(r0));
-  __ b(le, &runtime);
+  __ b(ls, &runtime);
 
   // r2: Number of capture registers
   // subject: Subject string
@@ -8518,11 +8651,7 @@
   __ ldr(last_match_info_elements,
          FieldMemOperand(r0, JSArray::kElementsOffset));
   __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
-#if ANDROID
   __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
-#else
-  __ LoadRoot(ip, kFixedArrayMapRootIndex);
-#endif
   __ cmp(r0, ip);
   __ b(ne, &runtime);
   // Check that the last match info has space for the capture registers and the
@@ -8745,7 +8874,7 @@
   // Do the runtime call to execute the regexp.
   __ bind(&runtime);
   __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
-#endif  // V8_NATIVE_REGEXP
+#endif  // V8_INTERPRETED_REGEXP
 }
 
 
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index bb76b63..33a85c4 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -29,6 +29,7 @@
 #define V8_ARM_CODEGEN_ARM_H_
 
 #include "ic-inl.h"
+#include "ast.h"
 
 namespace v8 {
 namespace internal {
@@ -36,6 +37,7 @@
 // Forward declarations
 class CompilationInfo;
 class DeferredCode;
+class JumpTarget;
 class RegisterAllocator;
 class RegisterFile;
 
@@ -217,6 +219,9 @@
   // expected arguments. Otherwise return -1.
   static int InlineRuntimeCallArgumentsCount(Handle<String> name);
 
+  // Constants related to patching of inlined load/store.
+  static const int kInlinedKeyedLoadInstructionsAfterPatchSize = 19;
+
  private:
   // Construction/Destruction
   explicit CodeGenerator(MacroAssembler* masm);
@@ -309,6 +314,7 @@
   // Read a value from a slot and leave it on top of the expression stack.
   void LoadFromSlot(Slot* slot, TypeofState typeof_state);
   void LoadFromSlotCheckForArguments(Slot* slot, TypeofState state);
+
   // Store the value on top of the stack to a slot.
   void StoreToSlot(Slot* slot, InitState init_state);
 
@@ -338,6 +344,15 @@
                                          TypeofState typeof_state,
                                          JumpTarget* slow);
 
+  // Support for loading from local/global variables and arguments
+  // whose location is known unless they are shadowed by
+  // eval-introduced bindings. Generates no code for unsupported slot
+  // types and therefore expects to fall through to the slow jump target.
+  void EmitDynamicLoadFromSlotFastCase(Slot* slot,
+                                       TypeofState typeof_state,
+                                       JumpTarget* slow,
+                                       JumpTarget* done);
+
   // Special code for typeof expressions: Unfortunately, we must
   // be careful when loading the expression in 'typeof'
   // expressions. We are not allowed to throw reference errors for
diff --git a/src/arm/constants-arm.h b/src/arm/constants-arm.h
index 5eed13f..57c5c1c 100644
--- a/src/arm/constants-arm.h
+++ b/src/arm/constants-arm.h
@@ -72,6 +72,10 @@
 # define CAN_USE_THUMB_INSTRUCTIONS 1
 #endif
 
+#if CAN_USE_UNALIGNED_ACCESSES
+#define V8_TARGET_CAN_READ_UNALIGNED 1
+#endif
+
 // Using blx may yield better code, so use it when required or when available
 #if defined(USE_THUMB_INTERWORK) || defined(CAN_USE_ARMV5_INSTRUCTIONS)
 #define USE_BLX 1
diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc
index 4ba3094..4051096 100644
--- a/src/arm/disasm-arm.cc
+++ b/src/arm/disasm-arm.cc
@@ -418,6 +418,12 @@
         ASSERT(STRING_STARTS_WITH(format, "memop"));
         if (instr->HasL()) {
           Print("ldr");
+        } else if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0)) {
+          if (instr->Bits(7, 4) == 0xf) {
+            Print("strd");
+          } else {
+            Print("ldrd");
+          }
         } else {
           Print("str");
         }
@@ -614,6 +620,47 @@
       } else {
         Unknown(instr);  // not used by V8
       }
+    } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) {
+      // ldrd, strd
+      switch (instr->PUField()) {
+        case 0: {
+          if (instr->Bit(22) == 0) {
+            Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
+          } else {
+            Format(instr, "'memop'cond's 'rd, ['rn], #-'off8");
+          }
+          break;
+        }
+        case 1: {
+          if (instr->Bit(22) == 0) {
+            Format(instr, "'memop'cond's 'rd, ['rn], +'rm");
+          } else {
+            Format(instr, "'memop'cond's 'rd, ['rn], #+'off8");
+          }
+          break;
+        }
+        case 2: {
+          if (instr->Bit(22) == 0) {
+            Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w");
+          } else {
+            Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w");
+          }
+          break;
+        }
+        case 3: {
+          if (instr->Bit(22) == 0) {
+            Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w");
+          } else {
+            Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w");
+          }
+          break;
+        }
+        default: {
+          // The PU field is a 2-bit field.
+          UNREACHABLE();
+          break;
+        }
+      }
     } else {
       // extra load/store instructions
       switch (instr->PUField()) {
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index e9bdfe5..6680af9 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -738,15 +738,10 @@
     // Load the key.
     __ mov(r0, Operand(key_literal->handle()));
 
-    // Push both as arguments to ic.
-    __ Push(r1, r0);
-
-    // Call keyed load IC. It has all arguments on the stack and the key in r0.
+    // Call keyed load IC. It has arguments key and receiver in r0 and r1.
     Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
-
-    // Drop key and object left on the stack by IC, and push the result.
-    DropAndApply(2, context, r0);
+    Apply(context, r0);
   }
 }
 
@@ -935,8 +930,16 @@
       }
       break;
     case KEYED_PROPERTY:
-      VisitForValue(prop->obj(), kStack);
-      VisitForValue(prop->key(), kStack);
+      // We need the key and receiver on both the stack and in r0 and r1.
+      if (expr->is_compound()) {
+        VisitForValue(prop->obj(), kStack);
+        VisitForValue(prop->key(), kAccumulator);
+        __ ldr(r1, MemOperand(sp, 0));
+        __ push(r0);
+      } else {
+        VisitForValue(prop->obj(), kStack);
+        VisitForValue(prop->key(), kStack);
+      }
       break;
   }
 
@@ -1005,8 +1008,7 @@
 
 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
-  // Call keyed load IC. It has all arguments on the stack and the key in r0.
-  __ ldr(r0, MemOperand(sp, 0));
+  // Call keyed load IC. It has arguments key and receiver in r0 and r1.
   Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
   __ Call(ic, RelocInfo::CODE_TARGET);
 }
@@ -1171,10 +1173,10 @@
     // Drop receiver left on the stack by IC.
     DropAndApply(1, context_, r0);
   } else {
-    VisitForValue(expr->key(), kStack);
+    VisitForValue(expr->key(), kAccumulator);
+    __ pop(r1);
     EmitKeyedPropertyLoad(expr);
-    // Drop key and receiver left on the stack by IC.
-    DropAndApply(2, context_, r0);
+    Apply(context_, r0);
   }
 }
 
@@ -1246,24 +1248,31 @@
       // Call to a keyed property, use keyed load IC followed by function
       // call.
       VisitForValue(prop->obj(), kStack);
-      VisitForValue(prop->key(), kStack);
+      VisitForValue(prop->key(), kAccumulator);
       // Record source code position for IC call.
       SetSourcePosition(prop->position());
-      // Call keyed load IC. It has all arguments on the stack and the key in
-      // r0.
-      __ ldr(r0, MemOperand(sp, 0));
+      if (prop->is_synthetic()) {
+        __ pop(r1);  // We do not need to keep the receiver.
+      } else {
+        __ ldr(r1, MemOperand(sp, 0));  // Keep receiver, to call function on.
+      }
+
       Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
       __ Call(ic, RelocInfo::CODE_TARGET);
-      // Load receiver object into r1.
       if (prop->is_synthetic()) {
+        // Push result (function).
+        __ push(r0);
+        // Push Global receiver.
         __ ldr(r1, CodeGenerator::GlobalObject());
         __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
+        __ push(r1);
       } else {
-        __ ldr(r1, MemOperand(sp, kPointerSize));
+        // Pop receiver.
+        __ pop(r1);
+        // Push result (function).
+        __ push(r0);
+        __ push(r1);
       }
-      // Overwrite (object, key) with (function, receiver).
-      __ str(r0, MemOperand(sp, kPointerSize));
-      __ str(r1, MemOperand(sp));
       EmitCallWithStub(expr);
     }
   } else {
@@ -1552,7 +1561,9 @@
     if (assign_type == NAMED_PROPERTY) {
       EmitNamedPropertyLoad(prop);
     } else {
-      VisitForValue(prop->key(), kStack);
+      VisitForValue(prop->key(), kAccumulator);
+      __ ldr(r1, MemOperand(sp, 0));
+      __ push(r0);
       EmitKeyedPropertyLoad(prop);
     }
   }
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 5b1915f..c308d69 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -28,6 +28,7 @@
 #include "v8.h"
 
 #include "assembler-arm.h"
+#include "codegen.h"
 #include "codegen-inl.h"
 #include "disasm.h"
 #include "ic-inl.h"
@@ -639,7 +640,9 @@
 
   // Patch the map check.
   Address ldr_map_instr_address =
-      inline_end_address - 18 * Assembler::kInstrSize;
+      inline_end_address -
+      CodeGenerator::kInlinedKeyedLoadInstructionsAfterPatchSize *
+      Assembler::kInstrSize;
   Assembler::set_target_address_at(ldr_map_instr_address,
                                    reinterpret_cast<Address>(map));
   return true;
@@ -683,11 +686,9 @@
   // ---------- S t a t e --------------
   //  -- lr     : return address
   //  -- r0     : key
-  //  -- sp[0]  : key
-  //  -- sp[4]  : receiver
+  //  -- r1     : receiver
   // -----------------------------------
 
-  __ ldr(r1, MemOperand(sp, kPointerSize));
   __ Push(r1, r0);
 
   ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss));
@@ -699,11 +700,9 @@
   // ---------- S t a t e --------------
   //  -- lr     : return address
   //  -- r0     : key
-  //  -- sp[0]  : key
-  //  -- sp[4]  : receiver
+  //  -- r1     : receiver
   // -----------------------------------
 
-  __ ldr(r1, MemOperand(sp, kPointerSize));
   __ Push(r1, r0);
 
   __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
@@ -714,18 +713,17 @@
   // ---------- S t a t e --------------
   //  -- lr     : return address
   //  -- r0     : key
-  //  -- sp[0]  : key
-  //  -- sp[4]  : receiver
+  //  -- r1     : receiver
   // -----------------------------------
   Label slow, fast, check_pixel_array, check_number_dictionary;
 
-  // Get the object from the stack.
-  __ ldr(r1, MemOperand(sp, kPointerSize));
+  Register key = r0;
+  Register receiver = r1;
 
   // Check that the object isn't a smi.
-  __ BranchOnSmi(r1, &slow);
+  __ BranchOnSmi(receiver, &slow);
   // Get the map of the receiver.
-  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset));
   // Check bit field.
   __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
   __ tst(r3, Operand(kSlowCaseBitFieldMask));
@@ -740,60 +738,65 @@
   __ b(lt, &slow);
 
   // Check that the key is a smi.
-  __ BranchOnNotSmi(r0, &slow);
-  // Save key in r2 in case we want it for the number dictionary case.
-  __ mov(r2, r0);
-  __ mov(r0, Operand(r0, ASR, kSmiTagSize));
+  __ BranchOnNotSmi(key, &slow);
+  // Untag key into r2..
+  __ mov(r2, Operand(key, ASR, kSmiTagSize));
 
   // Get the elements array of the object.
-  __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
+  __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
   // Check that the object is in fast mode (not dictionary).
-  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldr(r3, FieldMemOperand(r4, HeapObject::kMapOffset));
   __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
   __ cmp(r3, ip);
   __ b(ne, &check_pixel_array);
   // Check that the key (index) is within bounds.
-  __ ldr(r3, FieldMemOperand(r1, Array::kLengthOffset));
-  __ cmp(r0, r3);
+  __ ldr(r3, FieldMemOperand(r4, Array::kLengthOffset));
+  __ cmp(r2, r3);
   __ b(hs, &slow);
   // Fast case: Do the load.
-  __ add(r3, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
-  __ ldr(r0, MemOperand(r3, r0, LSL, kPointerSizeLog2));
+  __ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2));
   __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
-  __ cmp(r0, ip);
+  __ cmp(r2, ip);
   // In case the loaded value is the_hole we have to consult GetProperty
   // to ensure the prototype chain is searched.
   __ b(eq, &slow);
+  __ mov(r0, r2);
   __ Ret();
 
   // Check whether the elements is a pixel array.
+  // r0: key
+  // r2: untagged index
+  // r3: elements map
+  // r4: elements
   __ bind(&check_pixel_array);
   __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
   __ cmp(r3, ip);
   __ b(ne, &check_number_dictionary);
-  __ ldr(ip, FieldMemOperand(r1, PixelArray::kLengthOffset));
-  __ cmp(r0, ip);
+  __ ldr(ip, FieldMemOperand(r4, PixelArray::kLengthOffset));
+  __ cmp(r2, ip);
   __ b(hs, &slow);
-  __ ldr(ip, FieldMemOperand(r1, PixelArray::kExternalPointerOffset));
-  __ ldrb(r0, MemOperand(ip, r0));
-  __ mov(r0, Operand(r0, LSL, kSmiTagSize));  // Tag result as smi.
+  __ ldr(ip, FieldMemOperand(r4, PixelArray::kExternalPointerOffset));
+  __ ldrb(r2, MemOperand(ip, r2));
+  __ mov(r0, Operand(r2, LSL, kSmiTagSize));  // Tag result as smi.
   __ Ret();
 
   __ bind(&check_number_dictionary);
   // Check whether the elements is a number dictionary.
-  // r0: untagged index
-  // r1: elements
-  // r2: key
+  // r0: key
+  // r2: untagged index
+  // r3: elements map
+  // r4: elements
   __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
   __ cmp(r3, ip);
   __ b(ne, &slow);
-  GenerateNumberDictionaryLoad(masm, &slow, r1, r2, r0, r3, r4);
+  GenerateNumberDictionaryLoad(masm, &slow, r4, r0, r2, r3, r5);
+  __ mov(r0, r2);
   __ Ret();
 
-  // Slow case: Push extra copies of the arguments (2).
+  // Slow case, key and receiver still in r0 and r1.
   __ bind(&slow);
-  __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r0, r1);
-  __ ldr(r0, MemOperand(sp, 0));
+  __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r2, r3);
   GenerateRuntimeGetProperty(masm);
 }
 
@@ -802,8 +805,7 @@
   // ---------- S t a t e --------------
   //  -- lr     : return address
   //  -- r0     : key
-  //  -- sp[0]  : key
-  //  -- sp[4]  : receiver
+  //  -- r1     : receiver
   // -----------------------------------
   Label miss;
   Label index_not_smi;
@@ -811,9 +813,6 @@
   Label slow_char_code;
   Label got_char_code;
 
-  // Get the object from the stack.
-  __ ldr(r1, MemOperand(sp, kPointerSize));
-
   Register object = r1;
   Register index = r0;
   Register code = r2;
@@ -913,25 +912,21 @@
   // ---------- S t a t e --------------
   //  -- lr     : return address
   //  -- r0     : key
-  //  -- sp[0]  : key
-  //  -- sp[4]  : receiver
+  //  -- r1     : receiver
   // -----------------------------------
   Label slow, failed_allocation;
 
-  // Get the object from the stack.
-  __ ldr(r1, MemOperand(sp, kPointerSize));
-
-  // r0: key
-  // r1: receiver object
+  Register key = r0;
+  Register receiver = r1;
 
   // Check that the object isn't a smi
-  __ BranchOnSmi(r1, &slow);
+  __ BranchOnSmi(receiver, &slow);
 
   // Check that the key is a smi.
-  __ BranchOnNotSmi(r0, &slow);
+  __ BranchOnNotSmi(key, &slow);
 
   // Check that the object is a JS object. Load map into r2.
-  __ CompareObjectType(r1, r2, r3, FIRST_JS_OBJECT_TYPE);
+  __ CompareObjectType(receiver, r2, r3, FIRST_JS_OBJECT_TYPE);
   __ b(lt, &slow);
 
   // Check that the receiver does not require access checks.  We need
@@ -943,53 +938,51 @@
 
   // Check that the elements array is the appropriate type of
   // ExternalArray.
-  // r0: index (as a smi)
-  // r1: JSObject
-  __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
-  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
+  __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
   __ LoadRoot(ip, Heap::RootIndexForExternalArrayType(array_type));
   __ cmp(r2, ip);
   __ b(ne, &slow);
 
   // Check that the index is in range.
-  __ ldr(ip, FieldMemOperand(r1, ExternalArray::kLengthOffset));
-  __ cmp(r1, Operand(r0, ASR, kSmiTagSize));
+  __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
+  __ cmp(ip, Operand(key, ASR, kSmiTagSize));
   // Unsigned comparison catches both negative and too-large values.
   __ b(lo, &slow);
 
-  // r0: index (smi)
-  // r1: elements array
-  __ ldr(r1, FieldMemOperand(r1, ExternalArray::kExternalPointerOffset));
-  // r1: base pointer of external storage
+  // r3: elements array
+  __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
+  // r3: base pointer of external storage
 
   // We are not untagging smi key and instead work with it
   // as if it was premultiplied by 2.
   ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
 
+  Register value = r2;
   switch (array_type) {
     case kExternalByteArray:
-      __ ldrsb(r0, MemOperand(r1, r0, LSR, 1));
+      __ ldrsb(value, MemOperand(r3, key, LSR, 1));
       break;
     case kExternalUnsignedByteArray:
-      __ ldrb(r0, MemOperand(r1, r0, LSR, 1));
+      __ ldrb(value, MemOperand(r3, key, LSR, 1));
       break;
     case kExternalShortArray:
-      __ ldrsh(r0, MemOperand(r1, r0, LSL, 0));
+      __ ldrsh(value, MemOperand(r3, key, LSL, 0));
       break;
     case kExternalUnsignedShortArray:
-      __ ldrh(r0, MemOperand(r1, r0, LSL, 0));
+      __ ldrh(value, MemOperand(r3, key, LSL, 0));
       break;
     case kExternalIntArray:
     case kExternalUnsignedIntArray:
-      __ ldr(r0, MemOperand(r1, r0, LSL, 1));
+      __ ldr(value, MemOperand(r3, key, LSL, 1));
       break;
     case kExternalFloatArray:
       if (CpuFeatures::IsSupported(VFP3)) {
         CpuFeatures::Scope scope(VFP3);
-        __ add(r0, r1, Operand(r0, LSL, 1));
-        __ vldr(s0, r0, 0);
+        __ add(r2, r3, Operand(key, LSL, 1));
+        __ vldr(s0, r2, 0);
       } else {
-        __ ldr(r0, MemOperand(r1, r0, LSL, 1));
+        __ ldr(value, MemOperand(r3, key, LSL, 1));
       }
       break;
     default:
@@ -998,37 +991,36 @@
   }
 
   // For integer array types:
-  // r0: value
+  // r2: value
   // For floating-point array type
   // s0: value (if VFP3 is supported)
-  // r0: value (if VFP3 is not supported)
+  // r2: value (if VFP3 is not supported)
 
   if (array_type == kExternalIntArray) {
     // For the Int and UnsignedInt array types, we need to see whether
     // the value can be represented in a Smi. If not, we need to convert
     // it to a HeapNumber.
     Label box_int;
-    __ cmp(r0, Operand(0xC0000000));
+    __ cmp(value, Operand(0xC0000000));
     __ b(mi, &box_int);
-    __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+    // Tag integer as smi and return it.
+    __ mov(r0, Operand(value, LSL, kSmiTagSize));
     __ Ret();
 
     __ bind(&box_int);
-
-    __ mov(r1, r0);
-    // Allocate a HeapNumber for the int and perform int-to-double
-    // conversion.
+    // Allocate a HeapNumber for the result and perform int-to-double
+    // conversion. Use r0 for result as key is not needed any more.
     __ AllocateHeapNumber(r0, r3, r4, &slow);
 
     if (CpuFeatures::IsSupported(VFP3)) {
       CpuFeatures::Scope scope(VFP3);
-      __ vmov(s0, r1);
+      __ vmov(s0, value);
       __ vcvt_f64_s32(d0, s0);
-      __ sub(r1, r0, Operand(kHeapObjectTag));
-      __ vstr(d0, r1, HeapNumber::kValueOffset);
+      __ sub(r3, r0, Operand(kHeapObjectTag));
+      __ vstr(d0, r3, HeapNumber::kValueOffset);
       __ Ret();
     } else {
-      WriteInt32ToHeapNumberStub stub(r1, r0, r3);
+      WriteInt32ToHeapNumberStub stub(value, r0, r3);
       __ TailCallStub(&stub);
     }
   } else if (array_type == kExternalUnsignedIntArray) {
@@ -1038,51 +1030,60 @@
     if (CpuFeatures::IsSupported(VFP3)) {
       CpuFeatures::Scope scope(VFP3);
       Label box_int, done;
-      __ tst(r0, Operand(0xC0000000));
+      __ tst(value, Operand(0xC0000000));
       __ b(ne, &box_int);
-
-      __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+      // Tag integer as smi and return it.
+      __ mov(r0, Operand(value, LSL, kSmiTagSize));
       __ Ret();
 
       __ bind(&box_int);
-      __ vmov(s0, r0);
-      __ AllocateHeapNumber(r0, r1, r2, &slow);
+      __ vmov(s0, value);
+      // Allocate a HeapNumber for the result and perform int-to-double
+      // conversion. Don't use r0 and r1 as AllocateHeapNumber clobbers all
+      // registers - also when jumping due to exhausted young space.
+      __ AllocateHeapNumber(r2, r3, r4, &slow);
 
       __ vcvt_f64_u32(d0, s0);
-      __ sub(r1, r0, Operand(kHeapObjectTag));
+      __ sub(r1, r2, Operand(kHeapObjectTag));
       __ vstr(d0, r1, HeapNumber::kValueOffset);
+
+      __ mov(r0, r2);
       __ Ret();
     } else {
       // Check whether unsigned integer fits into smi.
       Label box_int_0, box_int_1, done;
-      __ tst(r0, Operand(0x80000000));
+      __ tst(value, Operand(0x80000000));
       __ b(ne, &box_int_0);
-      __ tst(r0, Operand(0x40000000));
+      __ tst(value, Operand(0x40000000));
       __ b(ne, &box_int_1);
-
       // Tag integer as smi and return it.
-      __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+      __ mov(r0, Operand(value, LSL, kSmiTagSize));
       __ Ret();
 
+      Register hiword = value;  // r2.
+      Register loword = r3;
+
       __ bind(&box_int_0);
       // Integer does not have leading zeros.
-      GenerateUInt2Double(masm, r0, r1, r2, 0);
+      GenerateUInt2Double(masm, hiword, loword, r4, 0);
       __ b(&done);
 
       __ bind(&box_int_1);
       // Integer has one leading zero.
-      GenerateUInt2Double(masm, r0, r1, r2, 1);
+      GenerateUInt2Double(masm, hiword, loword, r4, 1);
+
 
       __ bind(&done);
-      // Integer was converted to double in registers r0:r1.
-      // Wrap it into a HeapNumber.
-      __ AllocateHeapNumber(r2, r3, r5, &slow);
+      // Integer was converted to double in registers hiword:loword.
+      // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber
+      // clobbers all registers - also when jumping due to exhausted young
+      // space.
+      __ AllocateHeapNumber(r4, r5, r6, &slow);
 
-      __ str(r0, FieldMemOperand(r2, HeapNumber::kExponentOffset));
-      __ str(r1, FieldMemOperand(r2, HeapNumber::kMantissaOffset));
+      __ str(hiword, FieldMemOperand(r4, HeapNumber::kExponentOffset));
+      __ str(loword, FieldMemOperand(r4, HeapNumber::kMantissaOffset));
 
-      __ mov(r0, r2);
-
+      __ mov(r0, r4);
       __ Ret();
     }
   } else if (array_type == kExternalFloatArray) {
@@ -1090,40 +1091,52 @@
     // HeapNumber.
     if (CpuFeatures::IsSupported(VFP3)) {
       CpuFeatures::Scope scope(VFP3);
-      __ AllocateHeapNumber(r0, r1, r2, &slow);
+      // Allocate a HeapNumber for the result. Don't use r0 and r1 as
+      // AllocateHeapNumber clobbers all registers - also when jumping due to
+      // exhausted young space.
+      __ AllocateHeapNumber(r2, r3, r4, &slow);
       __ vcvt_f64_f32(d0, s0);
-      __ sub(r1, r0, Operand(kHeapObjectTag));
+      __ sub(r1, r2, Operand(kHeapObjectTag));
       __ vstr(d0, r1, HeapNumber::kValueOffset);
+
+      __ mov(r0, r2);
       __ Ret();
     } else {
-      __ AllocateHeapNumber(r3, r1, r2, &slow);
+      // Allocate a HeapNumber for the result. Don't use r0 and r1 as
+      // AllocateHeapNumber clobbers all registers - also when jumping due to
+      // exhausted young space.
+      __ AllocateHeapNumber(r3, r4, r5, &slow);
       // VFP is not available, do manual single to double conversion.
 
-      // r0: floating point value (binary32)
+      // r2: floating point value (binary32)
+      // r3: heap number for result
 
-      // Extract mantissa to r1.
-      __ and_(r1, r0, Operand(kBinary32MantissaMask));
+      // Extract mantissa to r0. OK to clobber r0 now as there are no jumps to
+      // the slow case from here.
+      __ and_(r0, value, Operand(kBinary32MantissaMask));
 
-      // Extract exponent to r2.
-      __ mov(r2, Operand(r0, LSR, kBinary32MantissaBits));
-      __ and_(r2, r2, Operand(kBinary32ExponentMask >> kBinary32MantissaBits));
+      // Extract exponent to r1. OK to clobber r1 now as there are no jumps to
+      // the slow case from here.
+      __ mov(r1, Operand(value, LSR, kBinary32MantissaBits));
+      __ and_(r1, r1, Operand(kBinary32ExponentMask >> kBinary32MantissaBits));
 
       Label exponent_rebiased;
-      __ teq(r2, Operand(0x00));
+      __ teq(r1, Operand(0x00));
       __ b(eq, &exponent_rebiased);
 
-      __ teq(r2, Operand(0xff));
-      __ mov(r2, Operand(0x7ff), LeaveCC, eq);
+      __ teq(r1, Operand(0xff));
+      __ mov(r1, Operand(0x7ff), LeaveCC, eq);
       __ b(eq, &exponent_rebiased);
 
       // Rebias exponent.
-      __ add(r2,
-             r2,
+      __ add(r1,
+             r1,
              Operand(-kBinary32ExponentBias + HeapNumber::kExponentBias));
 
       __ bind(&exponent_rebiased);
-      __ and_(r0, r0, Operand(kBinary32SignMask));
-      __ orr(r0, r0, Operand(r2, LSL, HeapNumber::kMantissaBitsInTopWord));
+      __ and_(r2, value, Operand(kBinary32SignMask));
+      value = no_reg;
+      __ orr(r2, r2, Operand(r1, LSL, HeapNumber::kMantissaBitsInTopWord));
 
       // Shift mantissa.
       static const int kMantissaShiftForHiWord =
@@ -1132,24 +1145,25 @@
       static const int kMantissaShiftForLoWord =
           kBitsPerInt - kMantissaShiftForHiWord;
 
-      __ orr(r0, r0, Operand(r1, LSR, kMantissaShiftForHiWord));
-      __ mov(r1, Operand(r1, LSL, kMantissaShiftForLoWord));
+      __ orr(r2, r2, Operand(r0, LSR, kMantissaShiftForHiWord));
+      __ mov(r0, Operand(r0, LSL, kMantissaShiftForLoWord));
 
-      __ str(r0, FieldMemOperand(r3, HeapNumber::kExponentOffset));
-      __ str(r1, FieldMemOperand(r3, HeapNumber::kMantissaOffset));
+      __ str(r2, FieldMemOperand(r3, HeapNumber::kExponentOffset));
+      __ str(r0, FieldMemOperand(r3, HeapNumber::kMantissaOffset));
+
       __ mov(r0, r3);
       __ Ret();
     }
 
   } else {
-    __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+    // Tag integer as smi and return it.
+    __ mov(r0, Operand(value, LSL, kSmiTagSize));
     __ Ret();
   }
 
-  // Slow case: Load name and receiver from stack and jump to runtime.
+  // Slow case, key and receiver still in r0 and r1.
   __ bind(&slow);
-  __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1, r0, r1);
-  __ ldr(r0, MemOperand(sp, 0));
+  __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1, r2, r3);
   GenerateRuntimeGetProperty(masm);
 }
 
@@ -1158,14 +1172,10 @@
   // ---------- S t a t e --------------
   //  -- lr     : return address
   //  -- r0     : key
-  //  -- sp[0]  : key
-  //  -- sp[4]  : receiver
+  //  -- r1     : receiver
   // -----------------------------------
   Label slow;
 
-  // Get the object from the stack.
-  __ ldr(r1, MemOperand(sp, kPointerSize));
-
   // Check that the receiver isn't a smi.
   __ BranchOnSmi(r1, &slow);
 
diff --git a/src/arm/jump-target-arm.cc b/src/arm/jump-target-arm.cc
index a13de0e..8d182be 100644
--- a/src/arm/jump-target-arm.cc
+++ b/src/arm/jump-target-arm.cc
@@ -47,28 +47,15 @@
   // which are still live in the C++ code.
   ASSERT(cgen()->HasValidEntryRegisters());
 
-  if (is_bound()) {
-    // Backward jump.  There already a frame expectation at the target.
-    ASSERT(direction_ == BIDIRECTIONAL);
-    cgen()->frame()->MergeTo(entry_frame_);
+  if (entry_frame_set_) {
+    // There already a frame expectation at the target.
+    cgen()->frame()->MergeTo(&entry_frame_);
     cgen()->DeleteFrame();
   } else {
-    // Use the current frame as the expected one at the target if necessary.
-    if (entry_frame_ == NULL) {
-      entry_frame_ = cgen()->frame();
-      RegisterFile empty;
-      cgen()->SetFrame(NULL, &empty);
-    } else {
-      cgen()->frame()->MergeTo(entry_frame_);
-      cgen()->DeleteFrame();
-    }
-
-    // The predicate is_linked() should be made true.  Its implementation
-    // detects the presence of a frame pointer in the reaching_frames_ list.
-    if (!is_linked()) {
-      reaching_frames_.Add(NULL);
-      ASSERT(is_linked());
-    }
+    // Clone the current frame to use as the expected one at the target.
+    set_entry_frame(cgen()->frame());
+    RegisterFile empty;
+    cgen()->SetFrame(NULL, &empty);
   }
   __ jmp(&entry_label_);
 }
@@ -77,23 +64,19 @@
 void JumpTarget::DoBranch(Condition cc, Hint ignored) {
   ASSERT(cgen()->has_valid_frame());
 
-  if (is_bound()) {
-    ASSERT(direction_ == BIDIRECTIONAL);
+  if (entry_frame_set_) {
     // Backward branch.  We have an expected frame to merge to on the
     // backward edge.
-    cgen()->frame()->MergeTo(entry_frame_);
+    if (cc == al) {
+      cgen()->frame()->MergeTo(&entry_frame_);
+    } else {
+      // We can't do conditional merges yet so you have to ensure that all
+      // conditional branches to the JumpTarget have the same virtual frame.
+      ASSERT(cgen()->frame()->Equals(&entry_frame_));
+    }
   } else {
-    // Clone the current frame to use as the expected one at the target if
-    // necessary.
-    if (entry_frame_ == NULL) {
-      entry_frame_ = new VirtualFrame(cgen()->frame());
-    }
-    // The predicate is_linked() should be made true.  Its implementation
-    // detects the presence of a frame pointer in the reaching_frames_ list.
-    if (!is_linked()) {
-      reaching_frames_.Add(NULL);
-      ASSERT(is_linked());
-    }
+    // Clone the current frame to use as the expected one at the target.
+    set_entry_frame(cgen()->frame());
   }
   __ b(cc, &entry_label_);
 }
@@ -113,15 +96,10 @@
 
   // Calls are always 'forward' so we use a copy of the current frame (plus
   // one for a return address) as the expected frame.
-  ASSERT(entry_frame_ == NULL);
-  VirtualFrame* target_frame = new VirtualFrame(cgen()->frame());
-  target_frame->Adjust(1);
-  entry_frame_ = target_frame;
-
-  // The predicate is_linked() should now be made true.  Its implementation
-  // detects the presence of a frame pointer in the reaching_frames_ list.
-  reaching_frames_.Add(NULL);
-  ASSERT(is_linked());
+  ASSERT(!entry_frame_set_);
+  VirtualFrame target_frame = *cgen()->frame();
+  target_frame.Adjust(1);
+  set_entry_frame(&target_frame);
 
   __ bl(&entry_label_);
 }
@@ -136,76 +114,24 @@
 
   if (cgen()->has_valid_frame()) {
     // If there is a current frame we can use it on the fall through.
-    if (entry_frame_ == NULL) {
-      entry_frame_ = new VirtualFrame(cgen()->frame());
+    if (!entry_frame_set_) {
+      entry_frame_ = *cgen()->frame();
+      entry_frame_set_ = true;
     } else {
-      ASSERT(cgen()->frame()->Equals(entry_frame_));
+      cgen()->frame()->MergeTo(&entry_frame_);
     }
   } else {
     // If there is no current frame we must have an entry frame which we can
     // copy.
-    ASSERT(entry_frame_ != NULL);
+    ASSERT(entry_frame_set_);
     RegisterFile empty;
-    cgen()->SetFrame(new VirtualFrame(entry_frame_), &empty);
-  }
-
-  // The predicate is_linked() should be made false.  Its implementation
-  // detects the presence (or absence) of frame pointers in the
-  // reaching_frames_ list.  If we inserted a bogus frame to make
-  // is_linked() true, remove it now.
-  if (is_linked()) {
-    reaching_frames_.Clear();
+    cgen()->SetFrame(new VirtualFrame(&entry_frame_), &empty);
   }
 
   __ bind(&entry_label_);
 }
 
 
-void BreakTarget::Jump() {
-  // On ARM we do not currently emit merge code for jumps, so we need to do
-  // it explicitly here.  The only merging necessary is to drop extra
-  // statement state from the stack.
-  ASSERT(cgen()->has_valid_frame());
-  int count = cgen()->frame()->height() - expected_height_;
-  cgen()->frame()->Drop(count);
-  DoJump();
-}
-
-
-void BreakTarget::Jump(Result* arg) {
-  UNIMPLEMENTED();
-}
-
-
-void BreakTarget::Bind() {
-#ifdef DEBUG
-  // All the forward-reaching frames should have been adjusted at the
-  // jumps to this target.
-  for (int i = 0; i < reaching_frames_.length(); i++) {
-    ASSERT(reaching_frames_[i] == NULL ||
-           reaching_frames_[i]->height() == expected_height_);
-  }
-#endif
-  // Drop leftover statement state from the frame before merging, even
-  // on the fall through.  This is so we can bind the return target
-  // with state on the frame.
-  if (cgen()->has_valid_frame()) {
-    int count = cgen()->frame()->height() - expected_height_;
-    // On ARM we do not currently emit merge code at binding sites, so we need
-    // to do it explicitly here.  The only merging necessary is to drop extra
-    // statement state from the stack.
-    cgen()->frame()->Drop(count);
-  }
-
-  DoBind();
-}
-
-
-void BreakTarget::Bind(Result* arg) {
-  UNIMPLEMENTED();
-}
-
-
 #undef __
 
 
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index d97f04b..c4b153f 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -232,6 +232,13 @@
 }
 
 
+void MacroAssembler::StoreRoot(Register source,
+                               Heap::RootListIndex index,
+                               Condition cond) {
+  str(source, MemOperand(roots, index << kPointerSizeLog2), cond);
+}
+
+
 void MacroAssembler::RecordWriteHelper(Register object,
                                        Register offset,
                                        Register scratch) {
@@ -926,6 +933,12 @@
   ASSERT(!result.is(scratch1));
   ASSERT(!scratch1.is(scratch2));
 
+  // Make object size into bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    object_size *= kPointerSize;
+  }
+  ASSERT_EQ(0, object_size & kObjectAlignmentMask);
+
   // Load address of new object into result and allocation top address into
   // scratch1.
   ExternalReference new_space_allocation_top =
@@ -948,23 +961,16 @@
       ExternalReference::new_space_allocation_limit_address();
   mov(scratch2, Operand(new_space_allocation_limit));
   ldr(scratch2, MemOperand(scratch2));
-  add(result, result, Operand(object_size * kPointerSize));
+  add(result, result, Operand(object_size));
   cmp(result, Operand(scratch2));
   b(hi, gc_required);
-
-  // Update allocation top. result temporarily holds the new top.
-  if (FLAG_debug_code) {
-    tst(result, Operand(kObjectAlignmentMask));
-    Check(eq, "Unaligned allocation in new space");
-  }
   str(result, MemOperand(scratch1));
 
   // Tag and adjust back to start of new object.
   if ((flags & TAG_OBJECT) != 0) {
-    sub(result, result, Operand((object_size * kPointerSize) -
-                                kHeapObjectTag));
+    sub(result, result, Operand(object_size - kHeapObjectTag));
   } else {
-    sub(result, result, Operand(object_size * kPointerSize));
+    sub(result, result, Operand(object_size));
   }
 }
 
@@ -1001,7 +1007,11 @@
       ExternalReference::new_space_allocation_limit_address();
   mov(scratch2, Operand(new_space_allocation_limit));
   ldr(scratch2, MemOperand(scratch2));
-  add(result, result, Operand(object_size, LSL, kPointerSizeLog2));
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    add(result, result, Operand(object_size, LSL, kPointerSizeLog2));
+  } else {
+    add(result, result, Operand(object_size));
+  }
   cmp(result, Operand(scratch2));
   b(hi, gc_required);
 
@@ -1013,7 +1023,11 @@
   str(result, MemOperand(scratch1));
 
   // Adjust back to start of new object.
-  sub(result, result, Operand(object_size, LSL, kPointerSizeLog2));
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    sub(result, result, Operand(object_size, LSL, kPointerSizeLog2));
+  } else {
+    sub(result, result, Operand(object_size));
+  }
 
   // Tag object if requested.
   if ((flags & TAG_OBJECT) != 0) {
@@ -1054,10 +1068,7 @@
   mov(scratch1, Operand(length, LSL, 1));  // Length in bytes, not chars.
   add(scratch1, scratch1,
       Operand(kObjectAlignmentMask + SeqTwoByteString::kHeaderSize));
-  // AllocateInNewSpace expects the size in words, so we can round down
-  // to kObjectAlignment and divide by kPointerSize in the same shift.
-  ASSERT_EQ(kPointerSize, kObjectAlignmentMask + 1);
-  mov(scratch1, Operand(scratch1, ASR, kPointerSizeLog2));
+  and_(scratch1, scratch1, Operand(~kObjectAlignmentMask));
 
   // Allocate two-byte string in new space.
   AllocateInNewSpace(scratch1,
@@ -1088,10 +1099,7 @@
   ASSERT(kCharSize == 1);
   add(scratch1, length,
       Operand(kObjectAlignmentMask + SeqAsciiString::kHeaderSize));
-  // AllocateInNewSpace expects the size in words, so we can round down
-  // to kObjectAlignment and divide by kPointerSize in the same shift.
-  ASSERT_EQ(kPointerSize, kObjectAlignmentMask + 1);
-  mov(scratch1, Operand(scratch1, ASR, kPointerSizeLog2));
+  and_(scratch1, scratch1, Operand(~kObjectAlignmentMask));
 
   // Allocate ASCII string in new space.
   AllocateInNewSpace(scratch1,
@@ -1115,7 +1123,7 @@
                                                Register scratch1,
                                                Register scratch2,
                                                Label* gc_required) {
-  AllocateInNewSpace(ConsString::kSize / kPointerSize,
+  AllocateInNewSpace(ConsString::kSize,
                      result,
                      scratch1,
                      scratch2,
@@ -1135,7 +1143,7 @@
                                              Register scratch1,
                                              Register scratch2,
                                              Label* gc_required) {
-  AllocateInNewSpace(ConsString::kSize / kPointerSize,
+  AllocateInNewSpace(ConsString::kSize,
                      result,
                      scratch1,
                      scratch2,
@@ -1549,7 +1557,7 @@
                                         Label* gc_required) {
   // Allocate an object in the heap for the heap number and tag it as a heap
   // object.
-  AllocateInNewSpace(HeapNumber::kSize / kPointerSize,
+  AllocateInNewSpace(HeapNumber::kSize,
                      result,
                      scratch1,
                      scratch2,
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 2ec7a39..9cf93da 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -52,6 +52,21 @@
 };
 
 
+// Flags used for the AllocateInNewSpace functions.
+enum AllocationFlags {
+  // No special flags.
+  NO_ALLOCATION_FLAGS = 0,
+  // Return the pointer to the allocated already tagged as a heap object.
+  TAG_OBJECT = 1 << 0,
+  // The content of the result register already contains the allocation top in
+  // new space.
+  RESULT_CONTAINS_TOP = 1 << 1,
+  // Specify that the requested size of the space to allocate is specified in
+  // words instead of bytes.
+  SIZE_IN_WORDS = 1 << 2
+};
+
+
 // MacroAssembler implements a collection of frequently used macros.
 class MacroAssembler: public Assembler {
  public:
@@ -85,6 +100,10 @@
   void LoadRoot(Register destination,
                 Heap::RootListIndex index,
                 Condition cond = al);
+  // Store an object to the root table.
+  void StoreRoot(Register source,
+                 Heap::RootListIndex index,
+                 Condition cond = al);
 
 
   // Check if object is in new space.
@@ -280,7 +299,9 @@
   // Allocate an object in new space. The object_size is specified in words (not
   // bytes). If the new space is exhausted control continues at the gc_required
   // label. The allocated object is returned in result. If the flag
-  // tag_allocated_object is true the result is tagged as as a heap object.
+  // tag_allocated_object is true the result is tagged as as a heap object. All
+  // registers are clobbered also when control continues at the gc_required
+  // label.
   void AllocateInNewSpace(int object_size,
                           Register result,
                           Register scratch1,
@@ -324,8 +345,9 @@
                                Register scratch2,
                                Label* gc_required);
 
-  // Allocates a heap number or jumps to the need_gc label if the young space
-  // is full and a scavenge is needed.
+  // Allocates a heap number or jumps to the gc_required label if the young
+  // space is full and a scavenge is needed. All registers are clobbered also
+  // when control continues at the gc_required label.
   void AllocateHeapNumber(Register result,
                           Register scratch1,
                           Register scratch2,
diff --git a/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
index 2fdba14..64fe5d6 100644
--- a/src/arm/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -1210,14 +1210,31 @@
     __ add(r0, current_input_offset(), Operand(cp_offset * char_size()));
     offset = r0;
   }
-  // We assume that we cannot do unaligned loads on ARM, so this function
-  // must only be used to load a single character at a time.
+  // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU
+  // and the operating system running on the target allow it.
+  // If unaligned load/stores are not supported then this function must only
+  // be used to load a single character at a time.
+#if !V8_TARGET_CAN_READ_UNALIGNED
   ASSERT(characters == 1);
+#endif
+
   if (mode_ == ASCII) {
-    __ ldrb(current_character(), MemOperand(end_of_input_address(), offset));
+    if (characters == 4) {
+      __ ldr(current_character(), MemOperand(end_of_input_address(), offset));
+    } else if (characters == 2) {
+      __ ldrh(current_character(), MemOperand(end_of_input_address(), offset));
+    } else {
+      ASSERT(characters == 1);
+      __ ldrb(current_character(), MemOperand(end_of_input_address(), offset));
+    }
   } else {
     ASSERT(mode_ == UC16);
-    __ ldrh(current_character(), MemOperand(end_of_input_address(), offset));
+    if (characters == 2) {
+      __ ldr(current_character(), MemOperand(end_of_input_address(), offset));
+    } else {
+      ASSERT(characters == 1);
+      __ ldrh(current_character(), MemOperand(end_of_input_address(), offset));
+    }
   }
 }
 
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index 5fe7d5f..e4601f3 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -728,6 +728,13 @@
 }
 
 
+void Simulator::set_dw_register(int dreg, const int* dbl) {
+  ASSERT((dreg >= 0) && (dreg < num_d_registers));
+  registers_[dreg] = dbl[0];
+  registers_[dreg + 1] = dbl[1];
+}
+
+
 // Raw access to the PC register.
 void Simulator::set_pc(int32_t value) {
   pc_modified_ = true;
@@ -864,27 +871,42 @@
   registers_[12] = 0x50Bad4U;
 }
 
-
-// The ARM cannot do unaligned reads and writes.  On some ARM platforms an
-// interrupt is caused.  On others it does a funky rotation thing.  For now we
-// simply disallow unaligned reads, but at some point we may want to move to
-// emulating the rotate behaviour.  Note that simulator runs have the runtime
+// Some Operating Systems allow unaligned access on ARMv7 targets. We
+// assume that unaligned accesses are not allowed unless the v8 build system
+// defines the CAN_USE_UNALIGNED_ACCESSES macro to be non-zero.
+// The following statements below describes the behavior of the ARM CPUs
+// that don't support unaligned access.
+// Some ARM platforms raise an interrupt on detecting unaligned access.
+// On others it does a funky rotation thing.  For now we
+// simply disallow unaligned reads.  Note that simulator runs have the runtime
 // system running directly on the host system and only generated code is
 // executed in the simulator.  Since the host is typically IA32 we will not
-// get the correct ARM-like behaviour on unaligned accesses.
+// get the correct ARM-like behaviour on unaligned accesses for those ARM
+// targets that don't support unaligned loads and stores.
+
 
 int Simulator::ReadW(int32_t addr, Instr* instr) {
+#if V8_TARGET_CAN_READ_UNALIGNED
+  intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
+  return *ptr;
+#else
   if ((addr & 3) == 0) {
     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
     return *ptr;
   }
-  PrintF("Unaligned read at 0x%08x\n", addr);
+  PrintF("Unaligned read at 0x%08x, pc=%p\n", addr, instr);
   UNIMPLEMENTED();
   return 0;
+#endif
 }
 
 
 void Simulator::WriteW(int32_t addr, int value, Instr* instr) {
+#if V8_TARGET_CAN_READ_UNALIGNED
+  intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
+  *ptr = value;
+  return;
+#else
   if ((addr & 3) == 0) {
     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
     *ptr = value;
@@ -892,10 +914,15 @@
   }
   PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
   UNIMPLEMENTED();
+#endif
 }
 
 
 uint16_t Simulator::ReadHU(int32_t addr, Instr* instr) {
+#if V8_TARGET_CAN_READ_UNALIGNED
+  uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
+  return *ptr;
+#else
   if ((addr & 1) == 0) {
     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
     return *ptr;
@@ -903,10 +930,15 @@
   PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr);
   UNIMPLEMENTED();
   return 0;
+#endif
 }
 
 
 int16_t Simulator::ReadH(int32_t addr, Instr* instr) {
+#if V8_TARGET_CAN_READ_UNALIGNED
+  int16_t* ptr = reinterpret_cast<int16_t*>(addr);
+  return *ptr;
+#else
   if ((addr & 1) == 0) {
     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
     return *ptr;
@@ -914,10 +946,16 @@
   PrintF("Unaligned signed halfword read at 0x%08x\n", addr);
   UNIMPLEMENTED();
   return 0;
+#endif
 }
 
 
 void Simulator::WriteH(int32_t addr, uint16_t value, Instr* instr) {
+#if V8_TARGET_CAN_READ_UNALIGNED
+  uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
+  *ptr = value;
+  return;
+#else
   if ((addr & 1) == 0) {
     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
     *ptr = value;
@@ -925,10 +963,16 @@
   }
   PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr, instr);
   UNIMPLEMENTED();
+#endif
 }
 
 
 void Simulator::WriteH(int32_t addr, int16_t value, Instr* instr) {
+#if V8_TARGET_CAN_READ_UNALIGNED
+  int16_t* ptr = reinterpret_cast<int16_t*>(addr);
+  *ptr = value;
+  return;
+#else
   if ((addr & 1) == 0) {
     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
     *ptr = value;
@@ -936,6 +980,7 @@
   }
   PrintF("Unaligned halfword write at 0x%08x, pc=%p\n", addr, instr);
   UNIMPLEMENTED();
+#endif
 }
 
 
@@ -963,6 +1008,41 @@
 }
 
 
+int32_t* Simulator::ReadDW(int32_t addr) {
+#if V8_TARGET_CAN_READ_UNALIGNED
+  int32_t* ptr = reinterpret_cast<int32_t*>(addr);
+  return ptr;
+#else
+  if ((addr & 3) == 0) {
+    int32_t* ptr = reinterpret_cast<int32_t*>(addr);
+    return ptr;
+  }
+  PrintF("Unaligned read at 0x%08x\n", addr);
+  UNIMPLEMENTED();
+  return 0;
+#endif
+}
+
+
+void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
+#if V8_TARGET_CAN_READ_UNALIGNED
+  int32_t* ptr = reinterpret_cast<int32_t*>(addr);
+  *ptr++ = value1;
+  *ptr = value2;
+  return;
+#else
+  if ((addr & 3) == 0) {
+    int32_t* ptr = reinterpret_cast<int32_t*>(addr);
+    *ptr++ = value1;
+    *ptr = value2;
+    return;
+  }
+  PrintF("Unaligned write at 0x%08x\n", addr);
+  UNIMPLEMENTED();
+#endif
+}
+
+
 // Returns the limit of the stack area to enable checking for stack overflows.
 uintptr_t Simulator::StackLimit() const {
   // Leave a safety margin of 256 bytes to prevent overrunning the stack when
@@ -1590,7 +1670,19 @@
           }
         }
       }
-      if (instr->HasH()) {
+      if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
+        ASSERT((rd % 2) == 0);
+        if (instr->HasH()) {
+          // The strd instruction.
+          int32_t value1 = get_register(rd);
+          int32_t value2 = get_register(rd+1);
+          WriteDW(addr, value1, value2);
+        } else {
+          // The ldrd instruction.
+          int* rn_data = ReadDW(addr);
+          set_dw_register(rd, rn_data);
+        }
+      } else if (instr->HasH()) {
         if (instr->HasSign()) {
           if (instr->HasL()) {
             int16_t val = ReadH(addr, instr);
diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
index 91614ea..61af3aa 100644
--- a/src/arm/simulator-arm.h
+++ b/src/arm/simulator-arm.h
@@ -159,6 +159,7 @@
   // instruction.
   void set_register(int reg, int32_t value);
   int32_t get_register(int reg) const;
+  void set_dw_register(int dreg, const int* dbl);
 
   // Support for VFP.
   void set_s_register(int reg, unsigned int value);
@@ -252,6 +253,9 @@
   inline int ReadW(int32_t addr, Instr* instr);
   inline void WriteW(int32_t addr, int value, Instr* instr);
 
+  int32_t* ReadDW(int32_t addr);
+  void WriteDW(int32_t addr, int32_t value1, int32_t value2);
+
   // Executing is handled based on the instruction type.
   void DecodeType01(Instr* instr);  // both type 0 and type 1 rolled into one
   void DecodeType2(Instr* instr);
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 095631d..877354c 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -1121,11 +1121,7 @@
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
@@ -1175,11 +1171,7 @@
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
@@ -1194,9 +1186,9 @@
   // -----------------------------------
   SharedFunctionInfo* function_info = function->shared();
   if (function_info->HasCustomCallGenerator()) {
-    CustomCallGenerator generator =
-        ToCData<CustomCallGenerator>(function_info->function_data());
-    Object* result = generator(this, object, holder, function, name, check);
+    const int id = function_info->custom_call_generator_id();
+    Object* result =
+        CompileCustomCall(id, object, holder, function, name, check);
     // undefined means bail out to regular compiler.
     if (!result->IsUndefined()) {
       return result;
@@ -1334,11 +1326,7 @@
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
@@ -1825,8 +1813,7 @@
   // ----------- S t a t e -------------
   //  -- lr    : return address
   //  -- r0    : key
-  //  -- sp[0] : key
-  //  -- sp[4] : receiver
+  //  -- r1    : receiver
   // -----------------------------------
   Label miss;
 
@@ -1834,7 +1821,6 @@
   __ cmp(r0, Operand(Handle<String>(name)));
   __ b(ne, &miss);
 
-  __ ldr(r1, MemOperand(sp, kPointerSize));  // Receiver.
   GenerateLoadField(receiver, holder, r1, r2, r3, index, name, &miss);
   __ bind(&miss);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
@@ -1850,8 +1836,7 @@
   // ----------- S t a t e -------------
   //  -- lr    : return address
   //  -- r0    : key
-  //  -- sp[0] : key
-  //  -- sp[4] : receiver
+  //  -- r1    : receiver
   // -----------------------------------
   Label miss;
 
@@ -1860,7 +1845,6 @@
   __ b(ne, &miss);
 
   Failure* failure = Failure::InternalError();
-  __ ldr(r1, MemOperand(sp, kPointerSize));  // Receiver.
   bool success = GenerateLoadCallback(receiver, holder, r1, r0, r2, r3,
                                       callback, name, &miss, &failure);
   if (!success) return failure;
@@ -1879,8 +1863,7 @@
   // ----------- S t a t e -------------
   //  -- lr    : return address
   //  -- r0    : key
-  //  -- sp[0] : key
-  //  -- sp[4] : receiver
+  //  -- r1    : receiver
   // -----------------------------------
   Label miss;
 
@@ -1888,7 +1871,6 @@
   __ cmp(r0, Operand(Handle<String>(name)));
   __ b(ne, &miss);
 
-  __ ldr(r1, MemOperand(sp, kPointerSize));  // Receiver.
   GenerateLoadConstant(receiver, holder, r1, r2, r3, value, name, &miss);
   __ bind(&miss);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
@@ -1904,8 +1886,7 @@
   // ----------- S t a t e -------------
   //  -- lr    : return address
   //  -- r0    : key
-  //  -- sp[0] : key
-  //  -- sp[4] : receiver
+  //  -- r1    : receiver
   // -----------------------------------
   Label miss;
 
@@ -1915,7 +1896,6 @@
 
   LookupResult lookup;
   LookupPostInterceptor(holder, name, &lookup);
-  __ ldr(r1, MemOperand(sp, kPointerSize));  // Receiver.
   GenerateLoadInterceptor(receiver,
                           holder,
                           &lookup,
@@ -1936,8 +1916,7 @@
   // ----------- S t a t e -------------
   //  -- lr    : return address
   //  -- r0    : key
-  //  -- sp[0] : key
-  //  -- sp[4] : receiver
+  //  -- r1    : receiver
   // -----------------------------------
   Label miss;
 
@@ -1945,7 +1924,6 @@
   __ cmp(r0, Operand(Handle<String>(name)));
   __ b(ne, &miss);
 
-  __ ldr(r1, MemOperand(sp, kPointerSize));  // Receiver.
   GenerateLoadArrayLength(masm(), r1, r2, &miss);
   __ bind(&miss);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
@@ -1958,8 +1936,7 @@
   // ----------- S t a t e -------------
   //  -- lr    : return address
   //  -- r0    : key
-  //  -- sp[0] : key
-  //  -- sp[4] : receiver
+  //  -- r1    : receiver
   // -----------------------------------
   Label miss;
   __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
@@ -1968,7 +1945,6 @@
   __ cmp(r0, Operand(Handle<String>(name)));
   __ b(ne, &miss);
 
-  __ ldr(r1, MemOperand(sp, kPointerSize));  // Receiver.
   GenerateLoadStringLength(masm(), r1, r2, r3, &miss);
   __ bind(&miss);
   __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
@@ -1984,8 +1960,7 @@
   // ----------- S t a t e -------------
   //  -- lr    : return address
   //  -- r0    : key
-  //  -- sp[0] : key
-  //  -- sp[4] : receiver
+  //  -- r1    : receiver
   // -----------------------------------
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
@@ -2085,7 +2060,7 @@
                         r5,
                         r6,
                         &generic_stub_call,
-                        NO_ALLOCATION_FLAGS);
+                        SIZE_IN_WORDS);
 
   // Allocated the JSObject, now initialize the fields. Map is set to initial
   // map and properties and elements are set to empty fixed array.
diff --git a/src/arm/virtual-frame-arm-inl.h b/src/arm/virtual-frame-arm-inl.h
new file mode 100644
index 0000000..a97cde4
--- /dev/null
+++ b/src/arm/virtual-frame-arm-inl.h
@@ -0,0 +1,53 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_VIRTUAL_FRAME_ARM_INL_H_
+#define V8_VIRTUAL_FRAME_ARM_INL_H_
+
+#include "assembler-arm.h"
+#include "virtual-frame-arm.h"
+
+namespace v8 {
+namespace internal {
+
+// These VirtualFrame methods should actually be in a virtual-frame-arm-inl.h
+// file if such a thing existed.
+MemOperand VirtualFrame::ParameterAt(int index) {
+  // Index -1 corresponds to the receiver.
+  ASSERT(-1 <= index);  // -1 is the receiver.
+  ASSERT(index <= parameter_count());
+  return MemOperand(fp, (1 + parameter_count() - index) * kPointerSize);
+}
+
+  // The receiver frame slot.
+MemOperand VirtualFrame::Receiver() {
+  return ParameterAt(-1);
+}
+
+} }  // namespace v8::internal
+
+#endif  // V8_VIRTUAL_FRAME_ARM_INL_H_
diff --git a/src/arm/virtual-frame-arm.cc b/src/arm/virtual-frame-arm.cc
index bf5cff2..f7b337d 100644
--- a/src/arm/virtual-frame-arm.cc
+++ b/src/arm/virtual-frame-arm.cc
@@ -72,8 +72,15 @@
 
 void VirtualFrame::MergeTo(VirtualFrame* expected) {
   if (Equals(expected)) return;
+  MergeTOSTo(expected->top_of_stack_state_);
+  ASSERT(register_allocation_map_ == expected->register_allocation_map_);
+}
+
+
+void VirtualFrame::MergeTOSTo(
+    VirtualFrame::TopOfStack expected_top_of_stack_state) {
 #define CASE_NUMBER(a, b) ((a) * TOS_STATES + (b))
-  switch (CASE_NUMBER(top_of_stack_state_, expected->top_of_stack_state_)) {
+  switch (CASE_NUMBER(top_of_stack_state_, expected_top_of_stack_state)) {
     case CASE_NUMBER(NO_TOS_REGISTERS, NO_TOS_REGISTERS):
       break;
     case CASE_NUMBER(NO_TOS_REGISTERS, R0_TOS):
@@ -154,7 +161,7 @@
       UNREACHABLE();
 #undef CASE_NUMBER
   }
-  ASSERT(register_allocation_map_ == expected->register_allocation_map_);
+  top_of_stack_state_ = expected_top_of_stack_state;
 }
 
 
@@ -323,7 +330,8 @@
 
 void VirtualFrame::CallKeyedLoadIC() {
   Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
-  SpillAllButCopyTOSToR0();
+  PopToR1R0();
+  SpillAll();
   CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
 }
 
@@ -417,7 +425,7 @@
 
 
 void VirtualFrame::EmitPop(Register reg) {
-  ASSERT(!is_used(reg));
+  ASSERT(!is_used(RegisterAllocator::ToNumber(reg)));
   if (top_of_stack_state_ == NO_TOS_REGISTERS) {
     __ pop(reg);
   } else {
@@ -505,21 +513,25 @@
       break;
     case R0_TOS:
       __ mov(r1, r0);
+      // r0 and r1 contains the same value. Prefer a state with r0 holding TOS.
       top_of_stack_state_ = R0_R1_TOS;
       break;
     case R1_TOS:
       __ mov(r0, r1);
+      // r0 and r1 contains the same value. Prefer a state with r0 holding TOS.
       top_of_stack_state_ = R0_R1_TOS;
       break;
     case R0_R1_TOS:
       __ push(r1);
       __ mov(r1, r0);
-      // No need to change state as r0 and r1 now contains the same value.
+      // r0 and r1 contains the same value. Prefer a state with r0 holding TOS.
+      top_of_stack_state_ = R0_R1_TOS;
       break;
     case R1_R0_TOS:
       __ push(r0);
       __ mov(r0, r1);
-      // No need to change state as r0 and r1 now contains the same value.
+      // r0 and r1 contains the same value. Prefer a state with r0 holding TOS.
+      top_of_stack_state_ = R0_R1_TOS;
       break;
     default:
       UNREACHABLE();
@@ -528,11 +540,49 @@
 }
 
 
+void VirtualFrame::Dup2() {
+  if (SpilledScope::is_spilled()) {
+    __ ldr(ip, MemOperand(sp, kPointerSize));
+    __ push(ip);
+    __ ldr(ip, MemOperand(sp, kPointerSize));
+    __ push(ip);
+  } else {
+    switch (top_of_stack_state_) {
+      case NO_TOS_REGISTERS:
+        __ ldr(r0, MemOperand(sp, 0));
+        __ ldr(r1, MemOperand(sp, kPointerSize));
+        top_of_stack_state_ = R0_R1_TOS;
+        break;
+      case R0_TOS:
+        __ push(r0);
+        __ ldr(r1, MemOperand(sp, kPointerSize));
+        top_of_stack_state_ = R0_R1_TOS;
+        break;
+      case R1_TOS:
+        __ push(r1);
+        __ ldr(r0, MemOperand(sp, kPointerSize));
+        top_of_stack_state_ = R1_R0_TOS;
+        break;
+      case R0_R1_TOS:
+        __ Push(r1, r0);
+        top_of_stack_state_ = R0_R1_TOS;
+        break;
+      case R1_R0_TOS:
+        __ Push(r0, r1);
+        top_of_stack_state_ = R1_R0_TOS;
+        break;
+      default:
+        UNREACHABLE();
+    }
+  }
+  element_count_ += 2;
+}
+
+
 Register VirtualFrame::PopToRegister(Register but_not_to_this_one) {
   ASSERT(but_not_to_this_one.is(r0) ||
          but_not_to_this_one.is(r1) ||
          but_not_to_this_one.is(no_reg));
-  AssertIsNotSpilled();
   element_count_--;
   if (top_of_stack_state_ == NO_TOS_REGISTERS) {
     if (but_not_to_this_one.is(r0)) {
@@ -584,6 +634,39 @@
 }
 
 
+void VirtualFrame::SetElementAt(Register reg, int this_far_down) {
+  if (this_far_down == 0) {
+    Pop();
+    Register dest = GetTOSRegister();
+    if (dest.is(reg)) {
+      // We already popped one item off the top of the stack.  If the only
+      // free register is the one we were asked to push then we have been
+      // asked to push a register that was already in use, which cannot
+      // happen.  It therefore folows that there are two free TOS registers:
+      ASSERT(top_of_stack_state_ == NO_TOS_REGISTERS);
+      dest = dest.is(r0) ? r1 : r0;
+    }
+    __ mov(dest, reg);
+    EmitPush(dest);
+  } else if (this_far_down == 1) {
+    int virtual_elements = kVirtualElements[top_of_stack_state_];
+    if (virtual_elements < 2) {
+      __ str(reg, ElementAt(this_far_down));
+    } else {
+      ASSERT(virtual_elements == 2);
+      ASSERT(!reg.is(r0));
+      ASSERT(!reg.is(r1));
+      Register dest = kBottomRegister[top_of_stack_state_];
+      __ mov(dest, reg);
+    }
+  } else {
+    ASSERT(this_far_down >= 2);
+    ASSERT(kVirtualElements[top_of_stack_state_] <= 2);
+    __ str(reg, ElementAt(this_far_down));
+  }
+}
+
+
 Register VirtualFrame::GetTOSRegister() {
   if (SpilledScope::is_spilled()) return r0;
 
diff --git a/src/arm/virtual-frame-arm.h b/src/arm/virtual-frame-arm.h
index 77bc70e..655194d 100644
--- a/src/arm/virtual-frame-arm.h
+++ b/src/arm/virtual-frame-arm.h
@@ -29,11 +29,14 @@
 #define V8_ARM_VIRTUAL_FRAME_ARM_H_
 
 #include "register-allocator.h"
-#include "scopes.h"
 
 namespace v8 {
 namespace internal {
 
+// This dummy class is only used to create invalid virtual frames.
+extern class InvalidVirtualFrameInitializer {}* kInvalidVirtualFrameInitializer;
+
+
 // -------------------------------------------------------------------------
 // Virtual frames
 //
@@ -82,26 +85,8 @@
     // is not spilled, ie. where register allocation occurs.  Eventually
     // when RegisterAllocationScope is ubiquitous it can be removed
     // along with the (by then unused) SpilledScope class.
-    explicit RegisterAllocationScope(CodeGenerator* cgen)
-      : cgen_(cgen),
-        old_is_spilled_(SpilledScope::is_spilled_) {
-      SpilledScope::is_spilled_ = false;
-      if (old_is_spilled_) {
-        VirtualFrame* frame = cgen->frame();
-        if (frame != NULL) {
-          frame->AssertIsSpilled();
-        }
-      }
-    }
-    ~RegisterAllocationScope() {
-      SpilledScope::is_spilled_ = old_is_spilled_;
-      if (old_is_spilled_) {
-        VirtualFrame* frame = cgen_->frame();
-        if (frame != NULL) {
-          frame->SpillAll();
-        }
-      }
-    }
+    inline explicit RegisterAllocationScope(CodeGenerator* cgen);
+    inline ~RegisterAllocationScope();
 
    private:
     CodeGenerator* cgen_;
@@ -116,19 +101,20 @@
   // Construct an initial virtual frame on entry to a JS function.
   inline VirtualFrame();
 
+  // Construct an invalid virtual frame, used by JumpTargets.
+  inline VirtualFrame(InvalidVirtualFrameInitializer* dummy);
+
   // Construct a virtual frame as a clone of an existing one.
   explicit inline VirtualFrame(VirtualFrame* original);
 
-  CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
-  MacroAssembler* masm() { return cgen()->masm(); }
+  inline CodeGenerator* cgen();
+  inline MacroAssembler* masm();
 
   // The number of elements on the virtual frame.
   int element_count() { return element_count_; }
 
   // The height of the virtual expression stack.
-  int height() {
-    return element_count() - expression_base_index();
-  }
+  inline int height();
 
   bool is_used(int num) {
     switch (num) {
@@ -160,10 +146,6 @@
     }
   }
 
-  bool is_used(Register reg) {
-    return is_used(RegisterAllocator::ToNumber(reg));
-  }
-
   // Add extra in-memory elements to the top of the frame to match an actual
   // frame (eg, the frame after an exception handler is pushed).  No code is
   // emitted.
@@ -247,16 +229,13 @@
 
   // An element of the expression stack as an assembly operand.
   MemOperand ElementAt(int index) {
-    AssertIsSpilled();
-    return MemOperand(sp, index * kPointerSize);
+    int adjusted_index = index - kVirtualElements[top_of_stack_state_];
+    ASSERT(adjusted_index >= 0);
+    return MemOperand(sp, adjusted_index * kPointerSize);
   }
 
   // A frame-allocated local as an assembly operand.
-  MemOperand LocalAt(int index) {
-    ASSERT(0 <= index);
-    ASSERT(index < local_count());
-    return MemOperand(fp, kLocal0Offset - index * kPointerSize);
-  }
+  inline MemOperand LocalAt(int index);
 
   // Push the address of the receiver slot on the frame.
   void PushReceiverSlotAddress();
@@ -268,26 +247,17 @@
   MemOperand Context() { return MemOperand(fp, kContextOffset); }
 
   // A parameter as an assembly operand.
-  MemOperand ParameterAt(int index) {
-    // Index -1 corresponds to the receiver.
-    ASSERT(-1 <= index);  // -1 is the receiver.
-    ASSERT(index <= parameter_count());
-    return MemOperand(fp, (1 + parameter_count() - index) * kPointerSize);
-  }
+  inline MemOperand ParameterAt(int index);
 
   // The receiver frame slot.
-  MemOperand Receiver() { return ParameterAt(-1); }
+  inline MemOperand Receiver();
 
   // Push a try-catch or try-finally handler on top of the virtual frame.
   void PushTryHandler(HandlerType type);
 
   // Call stub given the number of arguments it expects on (and
   // removes from) the stack.
-  void CallStub(CodeStub* stub, int arg_count) {
-    if (arg_count != 0) Forget(arg_count);
-    ASSERT(cgen()->HasValidEntryRegisters());
-    masm()->CallStub(stub);
-  }
+  inline void CallStub(CodeStub* stub, int arg_count);
 
   // Call JS function from top of the stack with arguments
   // taken from the stack.
@@ -316,8 +286,8 @@
   // Result is returned in r0.
   void CallStoreIC(Handle<String> name, bool is_contextual);
 
-  // Call keyed load IC. Key and receiver are on the stack. Result is returned
-  // in r0.
+  // Call keyed load IC. Key and receiver are on the stack. Both are consumed.
+  // Result is returned in r0.
   void CallKeyedLoadIC();
 
   // Call keyed store IC. Key and receiver are on the stack and the value is in
@@ -355,6 +325,9 @@
   // Duplicate the top of stack.
   void Dup();
 
+  // Duplicate the two elements on top of stack.
+  void Dup2();
+
   // Flushes all registers, but it puts a copy of the top-of-stack in r0.
   void SpillAllButCopyTOSToR0();
 
@@ -383,6 +356,12 @@
   void EmitPush(MemOperand operand);
   void EmitPushRoot(Heap::RootListIndex index);
 
+  // Overwrite the nth thing on the stack.  If the nth position is in a
+  // register then this turns into a mov, otherwise an str.  Afterwards
+  // you can still use the register even if it is a register that can be
+  // used for TOS (r0 or r1).
+  void SetElementAt(Register reg, int this_far_down);
+
   // Get a register which is free and which must be immediately used to
   // push on the top of the stack.
   Register GetTOSRegister();
@@ -446,13 +425,13 @@
   int stack_pointer() { return element_count_ - 1; }
 
   // The number of frame-allocated locals and parameters respectively.
-  int parameter_count() { return cgen()->scope()->num_parameters(); }
-  int local_count() { return cgen()->scope()->num_stack_slots(); }
+  inline int parameter_count();
+  inline int local_count();
 
   // The index of the element that is at the processor's frame pointer
   // (the fp register).  The parameters, receiver, function, and context
   // are below the frame pointer.
-  int frame_pointer() { return parameter_count() + 3; }
+  inline int frame_pointer();
 
   // The index of the first parameter.  The receiver lies below the first
   // parameter.
@@ -460,26 +439,22 @@
 
   // The index of the context slot in the frame.  It is immediately
   // below the frame pointer.
-  int context_index() { return frame_pointer() - 1; }
+  inline int context_index();
 
   // The index of the function slot in the frame.  It is below the frame
   // pointer and context slot.
-  int function_index() { return frame_pointer() - 2; }
+  inline int function_index();
 
   // The index of the first local.  Between the frame pointer and the
   // locals lies the return address.
-  int local0_index() { return frame_pointer() + 2; }
+  inline int local0_index();
 
   // The index of the base of the expression stack.
-  int expression_base_index() { return local0_index() + local_count(); }
+  inline int expression_base_index();
 
   // Convert a frame index into a frame pointer relative offset into the
   // actual stack.
-  int fp_relative(int index) {
-    ASSERT(index < element_count());
-    ASSERT(frame_pointer() < element_count());  // FP is on the frame.
-    return (frame_pointer() - index) * kPointerSize;
-  }
+  inline int fp_relative(int index);
 
   // Spill all elements in registers. Spill the top spilled_args elements
   // on the frame.  Sync all other frame elements.
@@ -491,10 +466,13 @@
   // onto the physical stack and made free.
   void EnsureOneFreeTOSRegister();
 
+  // Emit instructions to get the top of stack state from where we are to where
+  // we want to be.
+  void MergeTOSTo(TopOfStack expected_state);
+
   inline bool Equals(VirtualFrame* other);
 
   friend class JumpTarget;
-  friend class DeferredCode;
 };
 
 
diff --git a/src/assembler.cc b/src/assembler.cc
index ac03c20..87f363b 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -670,16 +670,6 @@
 }
 
 
-ExternalReference ExternalReference::compile_array_pop_call() {
-  return ExternalReference(FUNCTION_ADDR(CompileArrayPopCall));
-}
-
-
-ExternalReference ExternalReference::compile_array_push_call() {
-  return ExternalReference(FUNCTION_ADDR(CompileArrayPushCall));
-}
-
-
 #ifndef V8_INTERPRETED_REGEXP
 
 ExternalReference ExternalReference::re_check_stack_guard_state() {
diff --git a/src/assembler.h b/src/assembler.h
index 03a2f8e..5d03c1f 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -444,9 +444,6 @@
 
   static ExternalReference scheduled_exception_address();
 
-  static ExternalReference compile_array_pop_call();
-  static ExternalReference compile_array_push_call();
-
   Address address() const {return reinterpret_cast<Address>(address_);}
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
diff --git a/src/ast-inl.h b/src/ast-inl.h
new file mode 100644
index 0000000..2b5d7c4
--- /dev/null
+++ b/src/ast-inl.h
@@ -0,0 +1,79 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "ast.h"
+
+namespace v8 {
+namespace internal {
+
+BreakableStatement::BreakableStatement(ZoneStringList* labels, Type type)
+    : labels_(labels), type_(type) {
+  ASSERT(labels == NULL || labels->length() > 0);
+}
+
+
+SwitchStatement::SwitchStatement(ZoneStringList* labels)
+    : BreakableStatement(labels, TARGET_FOR_ANONYMOUS),
+      tag_(NULL), cases_(NULL) {
+}
+
+
+IterationStatement::IterationStatement(ZoneStringList* labels)
+    : BreakableStatement(labels, TARGET_FOR_ANONYMOUS), body_(NULL) {
+}
+
+
+Block::Block(ZoneStringList* labels, int capacity, bool is_initializer_block)
+    : BreakableStatement(labels, TARGET_FOR_NAMED_ONLY),
+      statements_(capacity),
+      is_initializer_block_(is_initializer_block) {
+}
+
+
+ForStatement::ForStatement(ZoneStringList* labels)
+    : IterationStatement(labels),
+      init_(NULL),
+      cond_(NULL),
+      next_(NULL),
+      may_have_function_literal_(true),
+      loop_variable_(NULL),
+      peel_this_loop_(false) {
+}
+
+
+ForInStatement::ForInStatement(ZoneStringList* labels)
+    : IterationStatement(labels), each_(NULL), enumerable_(NULL) {
+}
+
+
+DoWhileStatement::DoWhileStatement(ZoneStringList* labels)
+    : IterationStatement(labels), cond_(NULL), condition_position_(-1) {
+}
+
+} }  // namespace v8::internal
diff --git a/src/ast.cc b/src/ast.cc
index 75b2945..92df990 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -32,6 +32,8 @@
 #include "parser.h"
 #include "scopes.h"
 #include "string-stream.h"
+#include "ast-inl.h"
+#include "jump-target-inl.h"
 
 namespace v8 {
 namespace internal {
@@ -786,6 +788,13 @@
 }
 
 
+WhileStatement::WhileStatement(ZoneStringList* labels)
+    : IterationStatement(labels),
+      cond_(NULL),
+      may_have_function_literal_(true) {
+}
+
+
 ExpressionStatement::ExpressionStatement(ExpressionStatement* other,
                                          Expression* expression)
     : Statement(other), expression_(expression) {}
@@ -809,6 +818,11 @@
     : BreakableStatement(other), body_(body) {}
 
 
+CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements)
+    : label_(label), statements_(statements) {
+}
+
+
 ForStatement::ForStatement(ForStatement* other,
                            Statement* init,
                            Expression* cond,
diff --git a/src/ast.h b/src/ast.h
index dfc08ee..a3a9734 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -351,10 +351,7 @@
   bool is_target_for_anonymous() const { return type_ == TARGET_FOR_ANONYMOUS; }
 
  protected:
-  BreakableStatement(ZoneStringList* labels, Type type)
-      : labels_(labels), type_(type) {
-    ASSERT(labels == NULL || labels->length() > 0);
-  }
+  inline BreakableStatement(ZoneStringList* labels, Type type);
 
   explicit BreakableStatement(BreakableStatement* other);
 
@@ -367,10 +364,7 @@
 
 class Block: public BreakableStatement {
  public:
-  Block(ZoneStringList* labels, int capacity, bool is_initializer_block)
-      : BreakableStatement(labels, TARGET_FOR_NAMED_ONLY),
-        statements_(capacity),
-        is_initializer_block_(is_initializer_block) { }
+  inline Block(ZoneStringList* labels, int capacity, bool is_initializer_block);
 
   // Construct a clone initialized from the original block and
   // a deep copy of all statements of the original block.
@@ -437,8 +431,7 @@
   BreakTarget* continue_target()  { return &continue_target_; }
 
  protected:
-  explicit IterationStatement(ZoneStringList* labels)
-      : BreakableStatement(labels, TARGET_FOR_ANONYMOUS), body_(NULL) { }
+  explicit inline IterationStatement(ZoneStringList* labels);
 
   // Construct a clone initialized from  original and
   // a deep copy of the original body.
@@ -456,9 +449,7 @@
 
 class DoWhileStatement: public IterationStatement {
  public:
-  explicit DoWhileStatement(ZoneStringList* labels)
-      : IterationStatement(labels), cond_(NULL), condition_position_(-1) {
-  }
+  explicit inline DoWhileStatement(ZoneStringList* labels);
 
   void Initialize(Expression* cond, Statement* body) {
     IterationStatement::Initialize(body);
@@ -482,11 +473,7 @@
 
 class WhileStatement: public IterationStatement {
  public:
-  explicit WhileStatement(ZoneStringList* labels)
-      : IterationStatement(labels),
-        cond_(NULL),
-        may_have_function_literal_(true) {
-  }
+  explicit WhileStatement(ZoneStringList* labels);
 
   void Initialize(Expression* cond, Statement* body) {
     IterationStatement::Initialize(body);
@@ -511,14 +498,7 @@
 
 class ForStatement: public IterationStatement {
  public:
-  explicit ForStatement(ZoneStringList* labels)
-      : IterationStatement(labels),
-        init_(NULL),
-        cond_(NULL),
-        next_(NULL),
-        may_have_function_literal_(true),
-        loop_variable_(NULL),
-        peel_this_loop_(false) {}
+  explicit inline ForStatement(ZoneStringList* labels);
 
   // Construct a for-statement initialized from another for-statement
   // and deep copies of all parts of the original statement.
@@ -574,8 +554,7 @@
 
 class ForInStatement: public IterationStatement {
  public:
-  explicit ForInStatement(ZoneStringList* labels)
-      : IterationStatement(labels), each_(NULL), enumerable_(NULL) { }
+  explicit inline ForInStatement(ZoneStringList* labels);
 
   void Initialize(Expression* each, Expression* enumerable, Statement* body) {
     IterationStatement::Initialize(body);
@@ -691,8 +670,7 @@
 
 class CaseClause: public ZoneObject {
  public:
-  CaseClause(Expression* label, ZoneList<Statement*>* statements)
-      : label_(label), statements_(statements) { }
+  CaseClause(Expression* label, ZoneList<Statement*>* statements);
 
   bool is_default() const  { return label_ == NULL; }
   Expression* label() const  {
@@ -711,9 +689,7 @@
 
 class SwitchStatement: public BreakableStatement {
  public:
-  explicit SwitchStatement(ZoneStringList* labels)
-      : BreakableStatement(labels, TARGET_FOR_ANONYMOUS),
-        tag_(NULL), cases_(NULL) { }
+  explicit inline SwitchStatement(ZoneStringList* labels);
 
   void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) {
     tag_ = tag;
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 657d0dc..0874131 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -37,6 +37,7 @@
 #include "macro-assembler.h"
 #include "natives.h"
 #include "snapshot.h"
+#include "stub-cache.h"
 
 namespace v8 {
 namespace internal {
@@ -228,6 +229,7 @@
   // Used for creating a context from scratch.
   void InstallNativeFunctions();
   bool InstallNatives();
+  void InstallCustomCallGenerators();
   void InstallJSFunctionResultCaches();
   // Used both for deserialized and from-scratch contexts to add the extensions
   // provided.
@@ -1229,6 +1231,8 @@
 
   InstallNativeFunctions();
 
+  InstallCustomCallGenerators();
+
   // Install Function.prototype.call and apply.
   { Handle<String> key = Factory::function_class_symbol();
     Handle<JSFunction> function =
@@ -1326,6 +1330,29 @@
 }
 
 
+static void InstallCustomCallGenerator(Handle<JSFunction> holder_function,
+                                       const char* function_name,
+                                       int id) {
+  Handle<JSObject> proto(JSObject::cast(holder_function->instance_prototype()));
+  Handle<String> name = Factory::LookupAsciiSymbol(function_name);
+  Handle<JSFunction> function(JSFunction::cast(proto->GetProperty(*name)));
+  function->shared()->set_function_data(Smi::FromInt(id));
+}
+
+
+void Genesis::InstallCustomCallGenerators() {
+  HandleScope scope;
+#define INSTALL_CALL_GENERATOR(holder_fun, fun_name, name)                \
+  {                                                                       \
+    Handle<JSFunction> holder(global_context()->holder_fun##_function()); \
+    const int id = CallStubCompiler::k##name##CallGenerator;              \
+    InstallCustomCallGenerator(holder, #fun_name, id);                    \
+  }
+  CUSTOM_CALL_IC_GENERATORS(INSTALL_CALL_GENERATOR)
+#undef INSTALL_CALL_GENERATOR
+}
+
+
 // Do not forget to update macros.py with named constant
 // of cache id.
 #define JSFUNCTION_RESULT_CACHE_LIST(F) \
@@ -1726,8 +1753,8 @@
         CreateNewGlobals(global_template, global_object, &inner_global);
     HookUpGlobalProxy(inner_global, global_proxy);
     InitializeGlobal(inner_global, empty_function);
-    if (!InstallNatives()) return;
     InstallJSFunctionResultCaches();
+    if (!InstallNatives()) return;
 
     MakeFunctionInstancePrototypeWritable();
 
diff --git a/src/bootstrapper.h b/src/bootstrapper.h
index 66b8ff4..2b789e2 100644
--- a/src/bootstrapper.h
+++ b/src/bootstrapper.h
@@ -80,10 +80,6 @@
   // Tells whether bootstrapping is active.
   static bool IsActive() { return BootstrapperActive::IsActive(); }
 
-  // Encoding/decoding support for fixup flags.
-  class FixupFlagsUseCodeObject: public BitField<bool, 0, 1> {};
-  class FixupFlagsArgumentsCount: public BitField<uint32_t, 1, 32-1> {};
-
   // Support for thread preemption.
   static int ArchiveSpacePerThread();
   static char* ArchiveState(char* to);
diff --git a/src/builtins.cc b/src/builtins.cc
index e6cbd94..9a0fbd2 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -330,22 +330,19 @@
 }
 
 
-static bool ArrayPrototypeHasNoElements() {
+static bool ArrayPrototypeHasNoElements(Context* global_context,
+                                        JSObject* array_proto) {
   // This method depends on non writability of Object and Array prototype
   // fields.
-  Context* global_context = Top::context()->global_context();
-  // Array.prototype
-  JSObject* proto =
-      JSObject::cast(global_context->array_function()->prototype());
-  if (proto->elements() != Heap::empty_fixed_array()) return false;
+  if (array_proto->elements() != Heap::empty_fixed_array()) return false;
   // Hidden prototype
-  proto = JSObject::cast(proto->GetPrototype());
-  ASSERT(proto->elements() == Heap::empty_fixed_array());
+  array_proto = JSObject::cast(array_proto->GetPrototype());
+  ASSERT(array_proto->elements() == Heap::empty_fixed_array());
   // Object.prototype
-  proto = JSObject::cast(proto->GetPrototype());
-  if (proto != global_context->initial_object_prototype()) return false;
-  if (proto->elements() != Heap::empty_fixed_array()) return false;
-  ASSERT(proto->GetPrototype()->IsNull());
+  array_proto = JSObject::cast(array_proto->GetPrototype());
+  if (array_proto != global_context->initial_object_prototype()) return false;
+  if (array_proto->elements() != Heap::empty_fixed_array()) return false;
+  ASSERT(array_proto->GetPrototype()->IsNull());
   return true;
 }
 
@@ -368,6 +365,18 @@
 }
 
 
+static bool IsFastElementMovingAllowed(Object* receiver,
+                                       FixedArray** elements) {
+  if (!IsJSArrayWithFastElements(receiver, elements)) return false;
+
+  Context* global_context = Top::context()->global_context();
+  JSObject* array_proto =
+      JSObject::cast(global_context->array_function()->prototype());
+  if (JSArray::cast(receiver)->GetPrototype() != array_proto) return false;
+  return ArrayPrototypeHasNoElements(global_context, array_proto);
+}
+
+
 static Object* CallJsBuiltin(const char* name,
                              BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
   HandleScope handleScope;
@@ -377,7 +386,7 @@
                   name);
   ASSERT(js_builtin->IsJSFunction());
   Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin));
-  Vector<Object**> argv(Vector<Object**>::New(args.length() - 1));
+  ScopedVector<Object**> argv(args.length() - 1);
   int n_args = args.length() - 1;
   for (int i = 0; i < n_args; i++) {
     argv[i] = args.at<Object>(i + 1).location();
@@ -388,7 +397,6 @@
                                           n_args,
                                           argv.start(),
                                           &pending_exception);
-  argv.Dispose();
   if (pending_exception) return Failure::Exception();
   return *result;
 }
@@ -466,11 +474,7 @@
     return top;
   }
 
-  // Remember to check the prototype chain.
-  JSFunction* array_function =
-      Top::context()->global_context()->array_function();
-  JSObject* prototype = JSObject::cast(array_function->prototype());
-  top = prototype->GetElement(len - 1);
+  top = array->GetPrototype()->GetElement(len - 1);
 
   return top;
 }
@@ -479,8 +483,7 @@
 BUILTIN(ArrayShift) {
   Object* receiver = *args.receiver();
   FixedArray* elms = NULL;
-  if (!IsJSArrayWithFastElements(receiver, &elms)
-      || !ArrayPrototypeHasNoElements()) {
+  if (!IsFastElementMovingAllowed(receiver, &elms)) {
     return CallJsBuiltin("ArrayShift", args);
   }
   JSArray* array = JSArray::cast(receiver);
@@ -516,8 +519,7 @@
 BUILTIN(ArrayUnshift) {
   Object* receiver = *args.receiver();
   FixedArray* elms = NULL;
-  if (!IsJSArrayWithFastElements(receiver, &elms)
-      || !ArrayPrototypeHasNoElements()) {
+  if (!IsFastElementMovingAllowed(receiver, &elms)) {
     return CallJsBuiltin("ArrayUnshift", args);
   }
   JSArray* array = JSArray::cast(receiver);
@@ -566,8 +568,7 @@
 BUILTIN(ArraySlice) {
   Object* receiver = *args.receiver();
   FixedArray* elms = NULL;
-  if (!IsJSArrayWithFastElements(receiver, &elms)
-      || !ArrayPrototypeHasNoElements()) {
+  if (!IsFastElementMovingAllowed(receiver, &elms)) {
     return CallJsBuiltin("ArraySlice", args);
   }
   JSArray* array = JSArray::cast(receiver);
@@ -636,8 +637,7 @@
 BUILTIN(ArraySplice) {
   Object* receiver = *args.receiver();
   FixedArray* elms = NULL;
-  if (!IsJSArrayWithFastElements(receiver, &elms)
-      || !ArrayPrototypeHasNoElements()) {
+  if (!IsFastElementMovingAllowed(receiver, &elms)) {
     return CallJsBuiltin("ArraySplice", args);
   }
   JSArray* array = JSArray::cast(receiver);
@@ -789,7 +789,10 @@
 
 
 BUILTIN(ArrayConcat) {
-  if (!ArrayPrototypeHasNoElements()) {
+  Context* global_context = Top::context()->global_context();
+  JSObject* array_proto =
+      JSObject::cast(global_context->array_function()->prototype());
+  if (!ArrayPrototypeHasNoElements(global_context, array_proto)) {
     return CallJsBuiltin("ArrayConcat", args);
   }
 
@@ -799,7 +802,8 @@
   int result_len = 0;
   for (int i = 0; i < n_arguments; i++) {
     Object* arg = args[i];
-    if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements()) {
+    if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements()
+        || JSArray::cast(arg)->GetPrototype() != array_proto) {
       return CallJsBuiltin("ArrayConcat", args);
     }
 
diff --git a/src/codegen.h b/src/codegen.h
index a5bb31f..667d100 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -28,7 +28,6 @@
 #ifndef V8_CODEGEN_H_
 #define V8_CODEGEN_H_
 
-#include "ast.h"
 #include "code-stubs.h"
 #include "runtime.h"
 #include "type-info.h"
diff --git a/src/conversions.cc b/src/conversions.cc
index 66faae8..1e2bb20 100644
--- a/src/conversions.cc
+++ b/src/conversions.cc
@@ -31,8 +31,8 @@
 #include "v8.h"
 
 #include "conversions-inl.h"
+#include "dtoa.h"
 #include "factory.h"
-#include "fast-dtoa.h"
 #include "scanner.h"
 
 namespace v8 {
@@ -766,15 +766,16 @@
     default: {
       int decimal_point;
       int sign;
-
       char* decimal_rep;
       bool used_gay_dtoa = false;
-      const int kFastDtoaBufferCapacity = kFastDtoaMaximalLength + 1;
-      char fast_dtoa_buffer[kFastDtoaBufferCapacity];
+      const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
+      char v8_dtoa_buffer[kV8DtoaBufferCapacity];
       int length;
-      if (FastDtoa(v, Vector<char>(fast_dtoa_buffer, kFastDtoaBufferCapacity),
-                   &sign, &length, &decimal_point)) {
-        decimal_rep = fast_dtoa_buffer;
+
+      if (DoubleToAscii(v, DTOA_SHORTEST, 0,
+                        Vector<char>(v8_dtoa_buffer, kV8DtoaBufferCapacity),
+                        &sign, &length, &decimal_point)) {
+        decimal_rep = v8_dtoa_buffer;
       } else {
         decimal_rep = dtoa(v, 0, 0, &decimal_point, &sign, NULL);
         used_gay_dtoa = true;
@@ -842,7 +843,11 @@
 
 
 char* DoubleToFixedCString(double value, int f) {
+  const int kMaxDigitsBeforePoint = 20;
+  const double kFirstNonFixed = 1e21;
+  const int kMaxDigitsAfterPoint = 20;
   ASSERT(f >= 0);
+  ASSERT(f <= kMaxDigitsAfterPoint);
 
   bool negative = false;
   double abs_value = value;
@@ -851,7 +856,9 @@
     negative = true;
   }
 
-  if (abs_value >= 1e21) {
+  // If abs_value has more than kMaxDigitsBeforePoint digits before the point
+  // use the non-fixed conversion routine.
+  if (abs_value >= kFirstNonFixed) {
     char arr[100];
     Vector<char> buffer(arr, ARRAY_SIZE(arr));
     return StrDup(DoubleToCString(value, buffer));
@@ -860,8 +867,16 @@
   // Find a sufficiently precise decimal representation of n.
   int decimal_point;
   int sign;
-  char* decimal_rep = dtoa(abs_value, 3, f, &decimal_point, &sign, NULL);
-  int decimal_rep_length = StrLength(decimal_rep);
+  // Add space for the '.' and the '\0' byte.
+  const int kDecimalRepCapacity =
+      kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 2;
+  char decimal_rep[kDecimalRepCapacity];
+  int decimal_rep_length;
+  bool status = DoubleToAscii(value, DTOA_FIXED, f,
+                              Vector<char>(decimal_rep, kDecimalRepCapacity),
+                              &sign, &decimal_rep_length, &decimal_point);
+  USE(status);
+  ASSERT(status);
 
   // Create a representation that is padded with zeros if needed.
   int zero_prefix_length = 0;
@@ -884,7 +899,6 @@
   rep_builder.AddString(decimal_rep);
   rep_builder.AddPadding('0', zero_postfix_length);
   char* rep = rep_builder.Finalize();
-  freedtoa(decimal_rep);
 
   // Create the result string by appending a minus and putting in a
   // decimal point if needed.
diff --git a/src/d8.js b/src/d8.js
index b9ff09c..5c3da13 100644
--- a/src/d8.js
+++ b/src/d8.js
@@ -341,6 +341,11 @@
       this.request_ = this.breakCommandToJSONRequest_(args);
       break;
 
+    case 'breakpoints':
+    case 'bb':
+      this.request_ = this.breakpointsCommandToJSONRequest_(args);
+      break;
+
     case 'clear':
       this.request_ = this.clearCommandToJSONRequest_(args);
       break;
@@ -770,6 +775,15 @@
 };
 
 
+DebugRequest.prototype.breakpointsCommandToJSONRequest_ = function(args) {
+  if (args && args.length > 0) {
+    throw new Error('Unexpected arguments.');
+  }
+  var request = this.createRequest('listbreakpoints');
+  return request.toJSONProtocol();
+};
+
+
 // Create a JSON request for the clear command.
 DebugRequest.prototype.clearCommandToJSONRequest_ = function(args) {
   // Build a evaluate request from the text command.
@@ -947,6 +961,39 @@
         result += body.breakpoint;
         details.text = result;
         break;
+        
+      case 'listbreakpoints':
+        result = 'breakpoints: (' + body.breakpoints.length + ')';
+        for (var i = 0; i < body.breakpoints.length; i++) {
+          var breakpoint = body.breakpoints[i];
+          result += '\n id=' + breakpoint.number;
+          result += ' type=' + breakpoint.type;
+          if (breakpoint.script_id) {
+              result += ' script_id=' + breakpoint.script_id;
+          }
+          if (breakpoint.script_name) {
+              result += ' script_name=' + breakpoint.script_name;
+          }
+          result += ' line=' + breakpoint.line;
+          if (breakpoint.column != null) {
+            result += ' column=' + breakpoint.column;
+          }
+          if (breakpoint.groupId) {
+            result += ' groupId=' + breakpoint.groupId;
+          }
+          if (breakpoint.ignoreCount) {
+              result += ' ignoreCount=' + breakpoint.ignoreCount;
+          }
+          if (breakpoint.active === false) {
+            result += ' inactive';
+          }
+          if (breakpoint.condition) {
+            result += ' condition=' + breakpoint.condition;
+          }
+          result += ' hit_count=' + breakpoint.hit_count;
+        }
+        details.text = result;
+        break;
 
       case 'backtrace':
         if (body.totalFrames == 0) {
@@ -1136,8 +1183,8 @@
 
       default:
         details.text =
-            'Response for unknown command \'' + response.command + '\'' +
-            ' (' + json_response + ')';
+            'Response for unknown command \'' + response.command() + '\'' +
+            ' (' + response.raw_json() + ')';
     }
   } catch (e) {
     details.text = 'Error: "' + e + '" formatting response';
@@ -1153,6 +1200,7 @@
  * @constructor
  */
 function ProtocolPackage(json) {
+  this.raw_json_ = json;
   this.packet_ = JSON.parse(json);
   this.refs_ = [];
   if (this.packet_.refs) {
@@ -1243,6 +1291,11 @@
 }
 
 
+ProtocolPackage.prototype.raw_json = function() {
+  return this.raw_json_;
+}
+
+
 function ProtocolValue(value, packet) {
   this.value_ = value;
   this.packet_ = packet;
diff --git a/src/date.js b/src/date.js
index b9e19d6..e780cb8 100644
--- a/src/date.js
+++ b/src/date.js
@@ -238,7 +238,15 @@
   return time + DaylightSavingsOffset(time) + local_time_offset;
 }
 
+
+var ltcache = {
+  key: null, 
+  val: null
+};
+
 function LocalTimeNoCheck(time) {
+  var ltc = ltcache;
+  if (%_ObjectEquals(time, ltc.key)) return ltc.val;
   if (time < -MAX_TIME_MS || time > MAX_TIME_MS) {
     return $NaN;
   }
@@ -252,7 +260,8 @@
   } else {
     var dst_offset = DaylightSavingsOffset(time);
   }
-  return time + local_time_offset + dst_offset;
+  ltc.key = time;
+  return (ltc.val = time + local_time_offset + dst_offset);
 }
 
 
diff --git a/src/dateparser.cc b/src/dateparser.cc
index e68532f..6d80488 100644
--- a/src/dateparser.cc
+++ b/src/dateparser.cc
@@ -33,14 +33,10 @@
 namespace internal {
 
 bool DateParser::DayComposer::Write(FixedArray* output) {
-  // Set year to 0 by default.
-  if (index_ < 1) {
-    comp_[index_++] = 1;
-  }
-
+  if (index_ < 1) return false;
   // Day and month defaults to 1.
   while (index_ < kSize) {
-      comp_[index_++] = 1;
+    comp_[index_++] = 1;
   }
 
   int year = 0;  // Default year is 0 (=> 2000) for KJS compatibility.
@@ -48,7 +44,6 @@
   int day = kNone;
 
   if (named_month_ == kNone) {
-    if (index_ < 2) return false;
     if (index_ == 3 && !IsDay(comp_[0])) {
       // YMD
       year = comp_[0];
@@ -62,7 +57,6 @@
     }
   } else {
     month = named_month_;
-    if (index_ < 1) return false;
     if (index_ == 1) {
       // MD or DM
       day = comp_[0];
diff --git a/src/debug-agent.cc b/src/debug-agent.cc
index 41151d8..e2d9304 100644
--- a/src/debug-agent.cc
+++ b/src/debug-agent.cc
@@ -181,15 +181,15 @@
       buf.GetNext();
       len++;
     }
-    int16_t* temp = NewArray<int16_t>(len + 1);
+    ScopedVector<int16_t> temp(len + 1);
     buf.Reset(*message, StrLength(*message));
     for (int i = 0; i < len; i++) {
       temp[i] = buf.GetNext();
     }
 
     // Send the request received to the debugger.
-    v8::Debug::SendCommand(reinterpret_cast<const uint16_t *>(temp), len);
-    DeleteArray(temp);
+    v8::Debug::SendCommand(reinterpret_cast<const uint16_t *>(temp.start()),
+                           len);
   }
 }
 
diff --git a/src/debug-debugger.js b/src/debug-debugger.js
index e94cee4..77fa1dd 100644
--- a/src/debug-debugger.js
+++ b/src/debug-debugger.js
@@ -1266,6 +1266,8 @@
         this.clearBreakPointRequest_(request, response);
       } else if (request.command == 'clearbreakpointgroup') {
         this.clearBreakPointGroupRequest_(request, response);
+      } else if (request.command == 'listbreakpoints') {
+        this.listBreakpointsRequest_(request, response);
       } else if (request.command == 'backtrace') {
         this.backtraceRequest_(request, response);
       } else if (request.command == 'frame') {
@@ -1581,6 +1583,35 @@
   response.body = { breakpoint: break_point }
 }
 
+DebugCommandProcessor.prototype.listBreakpointsRequest_ = function(request, response) {
+  var array = [];
+  for (var i = 0; i < script_break_points.length; i++) {
+    var break_point = script_break_points[i];
+
+    var description = {
+      number: break_point.number(),
+      line: break_point.line(),
+      column: break_point.column(),
+      groupId: break_point.groupId(),
+      hit_count: break_point.hit_count(),
+      active: break_point.active(),
+      condition: break_point.condition(),
+      ignoreCount: break_point.ignoreCount()
+    }
+    
+    if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
+      description.type = 'scriptId';
+      description.script_id = break_point.script_id();
+    } else {
+      description.type = 'scriptName';
+      description.script_name = break_point.script_name();
+    }
+    array.push(description);
+  }
+  
+  response.body = { breakpoints: array }
+}
+
 
 DebugCommandProcessor.prototype.backtraceRequest_ = function(request, response) {
   // Get the number of frames.
diff --git a/src/debug.cc b/src/debug.cc
index 729f0ab..bf1f893 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -52,14 +52,13 @@
 #ifdef ENABLE_DEBUGGER_SUPPORT
 static void PrintLn(v8::Local<v8::Value> value) {
   v8::Local<v8::String> s = value->ToString();
-  char* data = NewArray<char>(s->Length() + 1);
-  if (data == NULL) {
+  ScopedVector<char> data(s->Length() + 1);
+  if (data.start() == NULL) {
     V8::FatalProcessOutOfMemory("PrintLn");
     return;
   }
-  s->WriteAscii(data);
-  PrintF("%s\n", data);
-  DeleteArray(data);
+  s->WriteAscii(data.start());
+  PrintF("%s\n", data.start());
 }
 
 
@@ -431,8 +430,13 @@
     // is set the patching performed by the runtime system will take place in
     // the code copy and will therefore have no effect on the running code
     // keeping it from using the inlined code.
-    if (code->is_keyed_load_stub()) KeyedLoadIC::ClearInlinedVersion(pc());
-    if (code->is_keyed_store_stub()) KeyedStoreIC::ClearInlinedVersion(pc());
+    if (code->is_keyed_load_stub()) {
+      KeyedLoadIC::ClearInlinedVersion(pc());
+    } else if (code->is_keyed_store_stub()) {
+      KeyedStoreIC::ClearInlinedVersion(pc());
+    } else if (code->is_load_stub()) {
+      LoadIC::ClearInlinedVersion(pc());
+    }
   }
 }
 
diff --git a/src/dtoa.cc b/src/dtoa.cc
new file mode 100644
index 0000000..e3dcbf2
--- /dev/null
+++ b/src/dtoa.cc
@@ -0,0 +1,77 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <math.h>
+
+#include "v8.h"
+#include "dtoa.h"
+
+#include "double.h"
+#include "fast-dtoa.h"
+#include "fixed-dtoa.h"
+
+namespace v8 {
+namespace internal {
+
+bool DoubleToAscii(double v, DtoaMode mode, int requested_digits,
+                   Vector<char> buffer, int* sign, int* length, int* point) {
+  ASSERT(!Double(v).IsSpecial());
+  ASSERT(mode == DTOA_SHORTEST || requested_digits >= 0);
+
+  if (Double(v).Sign() < 0) {
+    *sign = 1;
+    v = -v;
+  } else {
+    *sign = 0;
+  }
+
+  if (v == 0) {
+    buffer[0] = '0';
+    buffer[1] = '\0';
+    *length = 1;
+    *point = 1;
+    return true;
+  }
+
+  if (mode == DTOA_PRECISION && requested_digits == 0) {
+    buffer[0] = '\0';
+    *length = 0;
+    return true;
+  }
+
+  switch (mode) {
+    case DTOA_SHORTEST:
+      return FastDtoa(v, buffer, length, point);
+    case DTOA_FIXED:
+      return FastFixedDtoa(v, requested_digits, buffer, length, point);
+    default:
+      break;
+  }
+  return false;
+}
+
+} }  // namespace v8::internal
diff --git a/src/dtoa.h b/src/dtoa.h
new file mode 100644
index 0000000..be0d545
--- /dev/null
+++ b/src/dtoa.h
@@ -0,0 +1,81 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_DTOA_H_
+#define V8_DTOA_H_
+
+namespace v8 {
+namespace internal {
+
+enum DtoaMode {
+  // 0.9999999999999999 becomes 0.1
+  DTOA_SHORTEST,
+  // Fixed number of digits after the decimal point.
+  // For instance fixed(0.1, 4) becomes 0.1000
+  // If the input number is big, the output will be big.
+  DTOA_FIXED,
+  // Fixed number of digits (independent of the decimal point).
+  DTOA_PRECISION
+};
+
+// The maximal length of digits a double can have in base 10.
+// Note that DoubleToAscii null-terminates its input. So the given buffer should
+// be at least kBase10MaximalLength + 1 characters long.
+static const int kBase10MaximalLength = 17;
+
+// Converts the given double 'v' to ascii.
+// The result should be interpreted as buffer * 10^(point-length).
+//
+// The output depends on the given mode:
+//  - SHORTEST: produce the least amount of digits for which the internal
+//   identity requirement is still satisfied. If the digits are printed
+//   (together with the correct exponent) then reading this number will give
+//   'v' again. The buffer will choose the representation that is closest to
+//   'v'. If there are two at the same distance, than the one farther away
+//   from 0 is chosen (halfway cases - ending with 5 - are rounded up).
+//   In this mode the 'requested_digits' parameter is ignored.
+//  - FIXED: produces digits necessary to print a given number with
+//   'requested_digits' digits after the decimal point. The produced digits
+//   might be too short in which case the caller has to fill the gaps with '0's.
+//   Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
+//   Halfway cases are rounded towards +/-Infinity (away from 0). The call
+//   toFixed(0.15, 2) thus returns buffer="2", point=0.
+//   The returned buffer may contain digits that would be truncated from the
+//   shortest representation of the input.
+//  - PRECISION: produces 'requested_digits' where the first digit is not '0'.
+//   Even though the length of produced digits usually equals
+//   'requested_digits', the function is allowed to return fewer digits, in
+//   which case the caller has to fill the missing digits with '0's.
+//   Halfway cases are again rounded away from 0.
+// 'DoubleToAscii' expects the given buffer to be big enough to hold all digits
+// and a terminating null-character.
+bool DoubleToAscii(double v, DtoaMode mode, int requested_digits,
+                   Vector<char> buffer, int* sign, int* length, int* point);
+
+} }  // namespace v8::internal
+
+#endif  // V8_DTOA_H_
diff --git a/src/fast-dtoa.cc b/src/fast-dtoa.cc
index 4c0d15d..b4b7be0 100644
--- a/src/fast-dtoa.cc
+++ b/src/fast-dtoa.cc
@@ -314,7 +314,7 @@
 //  w's fractional part is therefore 0x567890abcdef.
 // Printing w's integral part is easy (simply print 0x1234 in decimal).
 // In order to print its fraction we repeatedly multiply the fraction by 10 and
-// get each digit. Example the first digit after the comma would be computed by
+// get each digit. Example the first digit after the point would be computed by
 //   (0x567890abcdef * 10) >> 48. -> 3
 // The whole thing becomes slightly more complicated because we want to stop
 // once we have enough digits. That is, once the digits inside the buffer
@@ -490,18 +490,11 @@
 
 bool FastDtoa(double v,
               Vector<char> buffer,
-              int* sign,
               int* length,
               int* point) {
-  ASSERT(v != 0);
+  ASSERT(v > 0);
   ASSERT(!Double(v).IsSpecial());
 
-  if (v < 0) {
-    v = -v;
-    *sign = 1;
-  } else {
-    *sign = 0;
-  }
   int decimal_exponent;
   bool result = grisu3(v, buffer, length, &decimal_exponent);
   *point = *length + decimal_exponent;
diff --git a/src/fast-dtoa.h b/src/fast-dtoa.h
index 9f1f76a..4403a75 100644
--- a/src/fast-dtoa.h
+++ b/src/fast-dtoa.h
@@ -36,7 +36,7 @@
 static const int kFastDtoaMaximalLength = 17;
 
 // Provides a decimal representation of v.
-// v must not be (positive or negative) zero and it must not be Infinity or NaN.
+// v must be a strictly positive finite double.
 // Returns true if it succeeds, otherwise the result can not be trusted.
 // There will be *length digits inside the buffer followed by a null terminator.
 // If the function returns true then
@@ -50,7 +50,6 @@
 //   otherwise.
 bool FastDtoa(double d,
               Vector<char> buffer,
-              int* sign,
               int* length,
               int* point);
 
diff --git a/src/fixed-dtoa.cc b/src/fixed-dtoa.cc
new file mode 100644
index 0000000..8ad88f6
--- /dev/null
+++ b/src/fixed-dtoa.cc
@@ -0,0 +1,405 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <math.h>
+
+#include "v8.h"
+
+#include "double.h"
+#include "fixed-dtoa.h"
+
+namespace v8 {
+namespace internal {
+
+// Represents a 128bit type. This class should be replaced by a native type on
+// platforms that support 128bit integers.
+class UInt128 {
+ public:
+  UInt128() : high_bits_(0), low_bits_(0) { }
+  UInt128(uint64_t high, uint64_t low) : high_bits_(high), low_bits_(low) { }
+
+  void Multiply(uint32_t multiplicand) {
+    uint64_t accumulator;
+
+    accumulator = (low_bits_ & kMask32) * multiplicand;
+    uint32_t part = static_cast<uint32_t>(accumulator & kMask32);
+    accumulator >>= 32;
+    accumulator = accumulator + (low_bits_ >> 32) * multiplicand;
+    low_bits_ = (accumulator << 32) + part;
+    accumulator >>= 32;
+    accumulator = accumulator + (high_bits_ & kMask32) * multiplicand;
+    part = static_cast<uint32_t>(accumulator & kMask32);
+    accumulator >>= 32;
+    accumulator = accumulator + (high_bits_ >> 32) * multiplicand;
+    high_bits_ = (accumulator << 32) + part;
+    ASSERT((accumulator >> 32) == 0);
+  }
+
+  void Shift(int shift_amount) {
+    ASSERT(-64 <= shift_amount && shift_amount <= 64);
+    if (shift_amount == 0) {
+      return;
+    } else if (shift_amount == -64) {
+      high_bits_ = low_bits_;
+      low_bits_ = 0;
+    } else if (shift_amount == 64) {
+      low_bits_ = high_bits_;
+      high_bits_ = 0;
+    } else if (shift_amount <= 0) {
+      high_bits_ <<= -shift_amount;
+      high_bits_ += low_bits_ >> (64 + shift_amount);
+      low_bits_ <<= -shift_amount;
+    } else {
+      low_bits_ >>= shift_amount;
+      low_bits_ += high_bits_ << (64 - shift_amount);
+      high_bits_ >>= shift_amount;
+    }
+  }
+
+  // Modifies *this to *this MOD (2^power).
+  // Returns *this DIV (2^power).
+  int DivModPowerOf2(int power) {
+    if (power >= 64) {
+      int result = static_cast<int>(high_bits_ >> (power - 64));
+      high_bits_ -= static_cast<uint64_t>(result) << (power - 64);
+      return result;
+    } else {
+      uint64_t part_low = low_bits_ >> power;
+      uint64_t part_high = high_bits_ << (64 - power);
+      int result = static_cast<int>(part_low + part_high);
+      high_bits_ = 0;
+      low_bits_ -= part_low << power;
+      return result;
+    }
+  }
+
+  bool IsZero() const {
+    return high_bits_ == 0 && low_bits_ == 0;
+  }
+
+  int BitAt(int position) {
+    if (position >= 64) {
+      return static_cast<int>(high_bits_ >> (position - 64)) & 1;
+    } else {
+      return static_cast<int>(low_bits_ >> position) & 1;
+    }
+  }
+
+ private:
+  static const uint64_t kMask32 = 0xFFFFFFFF;
+  // Value == (high_bits_ << 64) + low_bits_
+  uint64_t high_bits_;
+  uint64_t low_bits_;
+};
+
+
+static const int kDoubleSignificandSize = 53;  // Includes the hidden bit.
+
+
+static void FillDigits32FixedLength(uint32_t number, int requested_length,
+                                    Vector<char> buffer, int* length) {
+  for (int i = requested_length - 1; i >= 0; --i) {
+    buffer[(*length) + i] = '0' + number % 10;
+    number /= 10;
+  }
+  *length += requested_length;
+}
+
+
+static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) {
+  int number_length = 0;
+  // We fill the digits in reverse order and exchange them afterwards.
+  while (number != 0) {
+    int digit = number % 10;
+    number /= 10;
+    buffer[(*length) + number_length] = '0' + digit;
+    number_length++;
+  }
+  // Exchange the digits.
+  int i = *length;
+  int j = *length + number_length - 1;
+  while (i < j) {
+    char tmp = buffer[i];
+    buffer[i] = buffer[j];
+    buffer[j] = tmp;
+    i++;
+    j--;
+  }
+  *length += number_length;
+}
+
+
+static void FillDigits64FixedLength(uint64_t number, int requested_length,
+                                    Vector<char> buffer, int* length) {
+  const uint32_t kTen7 = 10000000;
+  // For efficiency cut the number into 3 uint32_t parts, and print those.
+  uint32_t part2 = static_cast<uint32_t>(number % kTen7);
+  number /= kTen7;
+  uint32_t part1 = static_cast<uint32_t>(number % kTen7);
+  uint32_t part0 = static_cast<uint32_t>(number / kTen7);
+
+  FillDigits32FixedLength(part0, 3, buffer, length);
+  FillDigits32FixedLength(part1, 7, buffer, length);
+  FillDigits32FixedLength(part2, 7, buffer, length);
+}
+
+
+static void FillDigits64(uint64_t number, Vector<char> buffer, int* length) {
+  const uint32_t kTen7 = 10000000;
+  // For efficiency cut the number into 3 uint32_t parts, and print those.
+  uint32_t part2 = static_cast<uint32_t>(number % kTen7);
+  number /= kTen7;
+  uint32_t part1 = static_cast<uint32_t>(number % kTen7);
+  uint32_t part0 = static_cast<uint32_t>(number / kTen7);
+
+  if (part0 != 0) {
+    FillDigits32(part0, buffer, length);
+    FillDigits32FixedLength(part1, 7, buffer, length);
+    FillDigits32FixedLength(part2, 7, buffer, length);
+  } else if (part1 != 0) {
+    FillDigits32(part1, buffer, length);
+    FillDigits32FixedLength(part2, 7, buffer, length);
+  } else {
+    FillDigits32(part2, buffer, length);
+  }
+}
+
+
+static void RoundUp(Vector<char> buffer, int* length, int* decimal_point) {
+  // An empty buffer represents 0.
+  if (*length == 0) {
+    buffer[0] = '1';
+    *decimal_point = 1;
+    *length = 1;
+    return;
+  }
+  // Round the last digit until we either have a digit that was not '9' or until
+  // we reached the first digit.
+  buffer[(*length) - 1]++;
+  for (int i = (*length) - 1; i > 0; --i) {
+    if (buffer[i] != '0' + 10) {
+      return;
+    }
+    buffer[i] = '0';
+    buffer[i - 1]++;
+  }
+  // If the first digit is now '0' + 10, we would need to set it to '0' and add
+  // a '1' in front. However we reach the first digit only if all following
+  // digits had been '9' before rounding up. Now all trailing digits are '0' and
+  // we simply switch the first digit to '1' and update the decimal-point
+  // (indicating that the point is now one digit to the right).
+  if (buffer[0] == '0' + 10) {
+    buffer[0] = '1';
+    (*decimal_point)++;
+  }
+}
+
+
+// The given fractionals number represents a fixed-point number with binary
+// point at bit (-exponent).
+// Preconditions:
+//   -128 <= exponent <= 0.
+//   0 <= fractionals * 2^exponent < 1
+//   The buffer holds the result.
+// The function will round its result. During the rounding-process digits not
+// generated by this function might be updated, and the decimal-point variable
+// might be updated. If this function generates the digits 99 and the buffer
+// already contained "199" (thus yielding a buffer of "19999") then a
+// rounding-up will change the contents of the buffer to "20000".
+static void FillFractionals(uint64_t fractionals, int exponent,
+                            int fractional_count, Vector<char> buffer,
+                            int* length, int* decimal_point) {
+  ASSERT(-128 <= exponent && exponent <= 0);
+  // 'fractionals' is a fixed-point number, with binary point at bit
+  // (-exponent). Inside the function the non-converted remainder of fractionals
+  // is a fixed-point number, with binary point at bit 'point'.
+  if (-exponent <= 64) {
+    // One 64 bit number is sufficient.
+    ASSERT(fractionals >> 56 == 0);
+    int point = -exponent;
+    for (int i = 0; i < fractional_count; ++i) {
+      if (fractionals == 0) break;
+      // Instead of multiplying by 10 we multiply by 5 and adjust the point
+      // location. This way the fractionals variable will not overflow.
+      // Invariant at the beginning of the loop: fractionals < 2^point.
+      // Initially we have: point <= 64 and fractionals < 2^56
+      // After each iteration the point is decremented by one.
+      // Note that 5^3 = 125 < 128 = 2^7.
+      // Therefore three iterations of this loop will not overflow fractionals
+      // (even without the subtraction at the end of the loop body). At this
+      // time point will satisfy point <= 61 and therefore fractionals < 2^point
+      // and any further multiplication of fractionals by 5 will not overflow.
+      fractionals *= 5;
+      point--;
+      int digit = static_cast<int>(fractionals >> point);
+      buffer[*length] = '0' + digit;
+      (*length)++;
+      fractionals -= static_cast<uint64_t>(digit) << point;
+    }
+    // If the first bit after the point is set we have to round up.
+    if (((fractionals >> (point - 1)) & 1) == 1) {
+      RoundUp(buffer, length, decimal_point);
+    }
+  } else {  // We need 128 bits.
+    ASSERT(64 < -exponent && -exponent <= 128);
+    UInt128 fractionals128 = UInt128(fractionals, 0);
+    fractionals128.Shift(-exponent - 64);
+    int point = 128;
+    for (int i = 0; i < fractional_count; ++i) {
+      if (fractionals128.IsZero()) break;
+      // As before: instead of multiplying by 10 we multiply by 5 and adjust the
+      // point location.
+      // This multiplication will not overflow for the same reasons as before.
+      fractionals128.Multiply(5);
+      point--;
+      int digit = fractionals128.DivModPowerOf2(point);
+      buffer[*length] = '0' + digit;
+      (*length)++;
+    }
+    if (fractionals128.BitAt(point - 1) == 1) {
+      RoundUp(buffer, length, decimal_point);
+    }
+  }
+}
+
+
+// Removes leading and trailing zeros.
+// If leading zeros are removed then the decimal point position is adjusted.
+static void TrimZeros(Vector<char> buffer, int* length, int* decimal_point) {
+  while (*length > 0 && buffer[(*length) - 1] == '0') {
+    (*length)--;
+  }
+  int first_non_zero = 0;
+  while (first_non_zero < *length && buffer[first_non_zero] == '0') {
+    first_non_zero++;
+  }
+  if (first_non_zero != 0) {
+    for (int i = first_non_zero; i < *length; ++i) {
+      buffer[i - first_non_zero] = buffer[i];
+    }
+    *length -= first_non_zero;
+    *decimal_point -= first_non_zero;
+  }
+}
+
+
+bool FastFixedDtoa(double v,
+                   int fractional_count,
+                   Vector<char> buffer,
+                   int* length,
+                   int* decimal_point) {
+  const uint32_t kMaxUInt32 = 0xFFFFFFFF;
+  uint64_t significand = Double(v).Significand();
+  int exponent = Double(v).Exponent();
+  // v = significand * 2^exponent (with significand a 53bit integer).
+  // If the exponent is larger than 20 (i.e. we may have a 73bit number) then we
+  // don't know how to compute the representation. 2^73 ~= 9.5*10^21.
+  // If necessary this limit could probably be increased, but we don't need
+  // more.
+  if (exponent > 20) return false;
+  if (fractional_count > 20) return false;
+  *length = 0;
+  // At most kDoubleSignificandSize bits of the significand are non-zero.
+  // Given a 64 bit integer we have 11 0s followed by 53 potentially non-zero
+  // bits:  0..11*..0xxx..53*..xx
+  if (exponent + kDoubleSignificandSize > 64) {
+    // The exponent must be > 11.
+    //
+    // We know that v = significand * 2^exponent.
+    // And the exponent > 11.
+    // We simplify the task by dividing v by 10^17.
+    // The quotient delivers the first digits, and the remainder fits into a 64
+    // bit number.
+    // Dividing by 10^17 is equivalent to dividing by 5^17*2^17.
+    const uint64_t kFive17 = V8_2PART_UINT64_C(0xB1, A2BC2EC5);  // 5^17
+    uint64_t divisor = kFive17;
+    int divisor_power = 17;
+    uint64_t dividend = significand;
+    uint32_t quotient;
+    uint64_t remainder;
+    // Let v = f * 2^e with f == significand and e == exponent.
+    // Then need q (quotient) and r (remainder) as follows:
+    //   v            = q * 10^17       + r
+    //   f * 2^e      = q * 10^17       + r
+    //   f * 2^e      = q * 5^17 * 2^17 + r
+    // If e > 17 then
+    //   f * 2^(e-17) = q * 5^17        + r/2^17
+    // else
+    //   f  = q * 5^17 * 2^(17-e) + r/2^e
+    if (exponent > divisor_power) {
+      // We only allow exponents of up to 20 and therefore (17 - e) <= 3
+      dividend <<= exponent - divisor_power;
+      quotient = static_cast<uint32_t>(dividend / divisor);
+      remainder = (dividend % divisor) << divisor_power;
+    } else {
+      divisor <<= divisor_power - exponent;
+      quotient = static_cast<uint32_t>(dividend / divisor);
+      remainder = (dividend % divisor) << exponent;
+    }
+    FillDigits32(quotient, buffer, length);
+    FillDigits64FixedLength(remainder, divisor_power, buffer, length);
+    *decimal_point = *length;
+  } else if (exponent >= 0) {
+    // 0 <= exponent <= 11
+    significand <<= exponent;
+    FillDigits64(significand, buffer, length);
+    *decimal_point = *length;
+  } else if (exponent > -kDoubleSignificandSize) {
+    // We have to cut the number.
+    uint64_t integrals = significand >> -exponent;
+    uint64_t fractionals = significand - (integrals << -exponent);
+    if (integrals > kMaxUInt32) {
+      FillDigits64(integrals, buffer, length);
+    } else {
+      FillDigits32(static_cast<uint32_t>(integrals), buffer, length);
+    }
+    *decimal_point = *length;
+    FillFractionals(fractionals, exponent, fractional_count,
+                    buffer, length, decimal_point);
+  } else if (exponent < -128) {
+    // This configuration (with at most 20 digits) means that all digits must be
+    // 0.
+    ASSERT(fractional_count <= 20);
+    buffer[0] = '\0';
+    *length = 0;
+    *decimal_point = -fractional_count;
+  } else {
+    *decimal_point = 0;
+    FillFractionals(significand, exponent, fractional_count,
+                    buffer, length, decimal_point);
+  }
+  TrimZeros(buffer, length, decimal_point);
+  buffer[*length] = '\0';
+  if ((*length) == 0) {
+    // The string is empty and the decimal_point thus has no importance. Mimick
+    // Gay's dtoa and and set it to -fractional_count.
+    *decimal_point = -fractional_count;
+  }
+  return true;
+}
+
+} }  // namespace v8::internal
diff --git a/src/fixed-dtoa.h b/src/fixed-dtoa.h
new file mode 100644
index 0000000..93f826f
--- /dev/null
+++ b/src/fixed-dtoa.h
@@ -0,0 +1,55 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_FIXED_DTOA_H_
+#define V8_FIXED_DTOA_H_
+
+namespace v8 {
+namespace internal {
+
+// Produces digits necessary to print a given number with
+// 'fractional_count' digits after the decimal point.
+// The buffer must be big enough to hold the result plus one terminating null
+// character.
+//
+// The produced digits might be too short in which case the caller has to fill
+// the gaps with '0's.
+// Example: FastFixedDtoa(0.001, 5, ...) is allowed to return buffer = "1", and
+// decimal_point = -2.
+// Halfway cases are rounded towards +/-Infinity (away from 0). The call
+// FastFixedDtoa(0.15, 2, ...) thus returns buffer = "2", decimal_point = 0.
+// The returned buffer may contain digits that would be truncated from the
+// shortest representation of the input.
+//
+// This method only works for some parameters. If it can't handle the input it
+// returns false. The output is null-terminated when the function succeeds.
+bool FastFixedDtoa(double v, int fractional_count,
+                   Vector<char> buffer, int* length, int* decimal_point);
+
+} }  // namespace v8::internal
+
+#endif  // V8_FIXED_DTOA_H_
diff --git a/src/flags.cc b/src/flags.cc
index d444c97..bbe6bb7 100644
--- a/src/flags.cc
+++ b/src/flags.cc
@@ -470,12 +470,12 @@
 // static
 int FlagList::SetFlagsFromString(const char* str, int len) {
   // make a 0-terminated copy of str
-  char* copy0 = NewArray<char>(len + 1);
-  memcpy(copy0, str, len);
+  ScopedVector<char> copy0(len + 1);
+  memcpy(copy0.start(), str, len);
   copy0[len] = '\0';
 
   // strip leading white space
-  char* copy = SkipWhiteSpace(copy0);
+  char* copy = SkipWhiteSpace(copy0.start());
 
   // count the number of 'arguments'
   int argc = 1;  // be compatible with SetFlagsFromCommandLine()
@@ -485,7 +485,7 @@
   }
 
   // allocate argument array
-  char** argv = NewArray<char*>(argc);
+  ScopedVector<char*> argv(argc);
 
   // split the flags string into arguments
   argc = 1;  // be compatible with SetFlagsFromCommandLine()
@@ -497,11 +497,7 @@
   }
 
   // set the flags
-  int result = SetFlagsFromCommandLine(&argc, argv, false);
-
-  // cleanup
-  DeleteArray(argv);
-  DeleteArray(copy0);
+  int result = SetFlagsFromCommandLine(&argc, argv.start(), false);
 
   return result;
 }
diff --git a/src/frames.h b/src/frames.h
index 98aaead..102244c 100644
--- a/src/frames.h
+++ b/src/frames.h
@@ -357,6 +357,7 @@
 
  private:
   friend class StackFrame;
+  friend class StackFrameIterator;
 };
 
 
diff --git a/src/globals.h b/src/globals.h
index bef5e8e..981ea16 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -46,6 +46,12 @@
 #elif defined(__ARMEL__)
 #define V8_HOST_ARCH_ARM 1
 #define V8_HOST_ARCH_32_BIT 1
+// Some CPU-OS combinations allow unaligned access on ARM. We assume
+// that unaligned accesses are not allowed unless the build system
+// defines the CAN_USE_UNALIGNED_ACCESSES macro to be non-zero.
+#if CAN_USE_UNALIGNED_ACCESSES
+#define V8_HOST_CAN_READ_UNALIGNED 1
+#endif
 #elif defined(_MIPS_ARCH_MIPS32R2)
 #define V8_HOST_ARCH_MIPS 1
 #define V8_HOST_ARCH_32_BIT 1
@@ -73,6 +79,12 @@
 #if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_IA32)
 #define V8_TARGET_CAN_READ_UNALIGNED 1
 #elif V8_TARGET_ARCH_ARM
+// Some CPU-OS combinations allow unaligned access on ARM. We assume
+// that unaligned accesses are not allowed unless the build system
+// defines the CAN_USE_UNALIGNED_ACCESSES macro to be non-zero.
+#if CAN_USE_UNALIGNED_ACCESSES
+#define V8_TARGET_CAN_READ_UNALIGNED 1
+#endif
 #elif V8_TARGET_ARCH_MIPS
 #else
 #error Target architecture is not supported by v8
diff --git a/src/heap.cc b/src/heap.cc
index 193f082..0a276ca 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -674,6 +674,8 @@
   Top::MarkCompactPrologue(is_compacting);
   ThreadManager::MarkCompactPrologue(is_compacting);
 
+  CompletelyClearInstanceofCache();
+
   if (is_compacting) FlushNumberStringCache();
 }
 
@@ -1685,6 +1687,10 @@
   if (obj->IsFailure()) return false;
   set_non_monomorphic_cache(NumberDictionary::cast(obj));
 
+  set_instanceof_cache_function(Smi::FromInt(0));
+  set_instanceof_cache_map(Smi::FromInt(0));
+  set_instanceof_cache_answer(Smi::FromInt(0));
+
   CreateFixedStubs();
 
   if (InitializeNumberStringCache()->IsFailure()) return false;
diff --git a/src/heap.h b/src/heap.h
index 902fc77..b4af6d9 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -93,6 +93,9 @@
   V(Map, proxy_map, ProxyMap)                                                  \
   V(Object, nan_value, NanValue)                                               \
   V(Object, minus_zero_value, MinusZeroValue)                                  \
+  V(Object, instanceof_cache_function, InstanceofCacheFunction)                \
+  V(Object, instanceof_cache_map, InstanceofCacheMap)                          \
+  V(Object, instanceof_cache_answer, InstanceofCacheAnswer)                    \
   V(String, empty_string, EmptyString)                                         \
   V(DescriptorArray, empty_descriptor_array, EmptyDescriptorArray)             \
   V(Map, neander_map, NeanderMap)                                              \
@@ -361,6 +364,11 @@
   // Allocates an empty code cache.
   static Object* AllocateCodeCache();
 
+  // Clear the Instanceof cache (used when a prototype changes).
+  static void ClearInstanceofCache() {
+    set_instanceof_cache_function(the_hole_value());
+  }
+
   // Allocates and fully initializes a String.  There are two String
   // encodings: ASCII and two byte. One should choose between the three string
   // allocation functions based on the encoding of the string buffer used to
@@ -971,6 +979,8 @@
 
   static int MaxObjectSizeInNewSpace() { return kMaxObjectSizeInNewSpace; }
 
+  static void ClearJSFunctionResultCaches();
+
  private:
   static int reserved_semispace_size_;
   static int max_semispace_size_;
@@ -1171,6 +1181,13 @@
   static void MarkCompactPrologue(bool is_compacting);
   static void MarkCompactEpilogue(bool is_compacting);
 
+  // Completely clear the Instanceof cache (to stop it keeping objects alive
+  // around a GC).
+  static void CompletelyClearInstanceofCache() {
+    set_instanceof_cache_map(the_hole_value());
+    set_instanceof_cache_function(the_hole_value());
+  }
+
   // Helper function used by CopyObject to copy a source object to an
   // allocated target object and update the forwarding pointer in the source
   // object.  Returns the target object.
@@ -1178,8 +1195,6 @@
                                           HeapObject* target,
                                           int size);
 
-  static void ClearJSFunctionResultCaches();
-
 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
   // Record the copy of an object in the NewSpace's statistics.
   static void RecordCopiedObject(HeapObject* obj);
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index 80e421b..2db21d5 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -1067,7 +1067,7 @@
   //  -- esp[0] : return address
   //  -- esp[4] : last argument
   // -----------------------------------
-  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
+  Label generic_array_code;
 
   // Get the Array function.
   GenerateLoadArrayFunction(masm, edi);
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index 83060c1..4393e44 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -829,14 +829,6 @@
 }
 
 
-void CodeGenerator::UnloadReference(Reference* ref) {
-  // Pop a reference from the stack while preserving TOS.
-  Comment cmnt(masm_, "[ UnloadReference");
-  frame_->Nip(ref->size());
-  ref->set_unloaded();
-}
-
-
 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and
 // convert it to a boolean in the condition code register or jump to
 // 'false_target'/'true_target' as appropriate.
@@ -1426,6 +1418,9 @@
                                                Result* left,
                                                Result* right,
                                                OverwriteMode overwrite_mode) {
+  // Copy the type info because left and right may be overwritten.
+  TypeInfo left_type_info = left->type_info();
+  TypeInfo right_type_info = right->type_info();
   Token::Value op = expr->op();
   Result answer;
   // Special handling of div and mod because they use fixed registers.
@@ -1501,8 +1496,8 @@
                                           (op == Token::DIV) ? eax : edx,
                                           left->reg(),
                                           right->reg(),
-                                          left->type_info(),
-                                          right->type_info(),
+                                          left_type_info,
+                                          right_type_info,
                                           overwrite_mode);
     if (left->reg().is(right->reg())) {
       __ test(left->reg(), Immediate(kSmiTagMask));
@@ -1605,18 +1600,18 @@
                                           answer.reg(),
                                           left->reg(),
                                           ecx,
-                                          left->type_info(),
-                                          right->type_info(),
+                                          left_type_info,
+                                          right_type_info,
                                           overwrite_mode);
 
     Label do_op, left_nonsmi;
     // If right is a smi we make a fast case if left is either a smi
     // or a heapnumber.
-    if (CpuFeatures::IsSupported(SSE2) && right->type_info().IsSmi()) {
+    if (CpuFeatures::IsSupported(SSE2) && right_type_info.IsSmi()) {
       CpuFeatures::Scope use_sse2(SSE2);
       __ mov(answer.reg(), left->reg());
       // Fast case - both are actually smis.
-      if (!left->type_info().IsSmi()) {
+      if (!left_type_info.IsSmi()) {
         __ test(answer.reg(), Immediate(kSmiTagMask));
         __ j(not_zero, &left_nonsmi);
       } else {
@@ -1640,7 +1635,7 @@
       deferred->Branch(negative);
     } else {
       CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(),
-                         left->type_info(), right->type_info(), deferred);
+                         left_type_info, right_type_info, deferred);
 
       // Untag both operands.
       __ mov(answer.reg(), left->reg());
@@ -1713,11 +1708,11 @@
                                         answer.reg(),
                                         left->reg(),
                                         right->reg(),
-                                        left->type_info(),
-                                        right->type_info(),
+                                        left_type_info,
+                                        right_type_info,
                                         overwrite_mode);
   CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(),
-                     left->type_info(), right->type_info(), deferred);
+                     left_type_info, right_type_info, deferred);
 
   __ mov(answer.reg(), left->reg());
   switch (op) {
@@ -1988,18 +1983,13 @@
 }
 
 
-Result CodeGenerator::ConstantSmiBinaryOperation(
-    BinaryOperation* expr,
-    Result* operand,
-    Handle<Object> value,
-    bool reversed,
-    OverwriteMode overwrite_mode) {
-  // 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 constant smi.
-  // Consumes the argument "operand".
-  // TODO(199): Optimize some special cases of operations involving a
-  // smi literal (multiply by 2, shift by 0, etc.).
+Result CodeGenerator::ConstantSmiBinaryOperation(BinaryOperation* expr,
+                                                 Result* operand,
+                                                 Handle<Object> value,
+                                                 bool reversed,
+                                                 OverwriteMode overwrite_mode) {
+  // Generate inline code for a binary operation when one of the
+  // operands is a constant smi.  Consumes the argument "operand".
   if (IsUnsafeSmi(value)) {
     Result unsafe_operand(value);
     if (reversed) {
@@ -2499,7 +2489,9 @@
       // by reconstituting them on the non-fall-through path.
 
       if (left_side.is_smi()) {
-        if (FLAG_debug_code) __ AbortIfNotSmi(left_side.reg());
+        if (FLAG_debug_code) {
+          __ AbortIfNotSmi(left_side.reg());
+        }
       } else {
         JumpTarget is_smi;
         __ test(left_side.reg(), Immediate(kSmiTagMask));
@@ -2528,7 +2520,7 @@
             __ cvtsi2sd(xmm0, Operand(temp.reg()));
             temp.Unuse();
           }
-          __ comisd(xmm1, xmm0);
+          __ ucomisd(xmm1, xmm0);
           // Jump to builtin for NaN.
           not_number.Branch(parity_even, &left_side);
           left_side.Unuse();
@@ -2819,11 +2811,7 @@
       // number comparison in the stub if it was inlined.
       CompareStub stub(cc, strict, nan_info, !inline_number_compare);
       Result answer = frame_->CallStub(&stub, &left_side, &right_side);
-      if (cc == equal) {
-        __ test(answer.reg(), Operand(answer.reg()));
-      } else {
-        __ cmp(answer.reg(), 0);
-      }
+      __ test(answer.reg(), Operand(answer.reg()));
       answer.Unuse();
       dest->true_target()->Branch(cc);
       dest->false_target()->Jump();
@@ -4239,8 +4227,7 @@
 
   // Get the i'th entry of the array.
   __ mov(edx, frame_->ElementAt(2));
-  __ mov(ebx, Operand(edx, eax, times_2,
-                      FixedArray::kHeaderSize - kHeapObjectTag));
+  __ mov(ebx, FixedArrayElementOperand(edx, eax));
 
   // Get the expected map from the stack or a zero map in the
   // permanent slow case eax: current iteration count ebx: i'th entry
@@ -4736,42 +4723,14 @@
     JumpTarget slow;
     JumpTarget done;
 
-    // Generate fast-case code for variables that might be shadowed by
-    // eval-introduced variables.  Eval is used a lot without
-    // introducing variables.  In those cases, we do not want to
-    // perform a runtime call for all variables in the scope
-    // containing the eval.
-    if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
-      result = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow);
-      // If there was no control flow to slow, we can exit early.
-      if (!slow.is_linked()) return result;
-      done.Jump(&result);
-
-    } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
-      Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
-      // Only generate the fast case for locals that rewrite to slots.
-      // This rules out argument loads.
-      if (potential_slot != NULL) {
-        // Allocate a fresh register to use as a temp in
-        // ContextSlotOperandCheckExtensions and to hold the result
-        // value.
-        result = allocator()->Allocate();
-        ASSERT(result.is_valid());
-        __ mov(result.reg(),
-               ContextSlotOperandCheckExtensions(potential_slot,
-                                                 result,
-                                                 &slow));
-        if (potential_slot->var()->mode() == Variable::CONST) {
-          __ cmp(result.reg(), Factory::the_hole_value());
-          done.Branch(not_equal, &result);
-          __ mov(result.reg(), Factory::undefined_value());
-        }
-        // There is always control flow to slow from
-        // ContextSlotOperandCheckExtensions so we have to jump around
-        // it.
-        done.Jump(&result);
-      }
-    }
+    // Generate fast case for loading from slots that correspond to
+    // local/global variables or arguments unless they are shadowed by
+    // eval-introduced bindings.
+    EmitDynamicLoadFromSlotFastCase(slot,
+                                    typeof_state,
+                                    &result,
+                                    &slow,
+                                    &done);
 
     slow.Bind();
     // A runtime call is inevitable.  We eagerly sync frame elements
@@ -4940,6 +4899,68 @@
 }
 
 
+void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot,
+                                                    TypeofState typeof_state,
+                                                    Result* result,
+                                                    JumpTarget* slow,
+                                                    JumpTarget* done) {
+  // Generate fast-case code for variables that might be shadowed by
+  // eval-introduced variables.  Eval is used a lot without
+  // introducing variables.  In those cases, we do not want to
+  // perform a runtime call for all variables in the scope
+  // containing the eval.
+  if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
+    *result = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, slow);
+    done->Jump(result);
+
+  } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
+    Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
+    Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
+    if (potential_slot != NULL) {
+      // Generate fast case for locals that rewrite to slots.
+      // Allocate a fresh register to use as a temp in
+      // ContextSlotOperandCheckExtensions and to hold the result
+      // value.
+      *result = allocator()->Allocate();
+      ASSERT(result->is_valid());
+      __ mov(result->reg(),
+             ContextSlotOperandCheckExtensions(potential_slot, *result, slow));
+      if (potential_slot->var()->mode() == Variable::CONST) {
+        __ cmp(result->reg(), Factory::the_hole_value());
+        done->Branch(not_equal, result);
+        __ mov(result->reg(), Factory::undefined_value());
+      }
+      done->Jump(result);
+    } else if (rewrite != NULL) {
+      // Generate fast case for calls of an argument function.
+      Property* property = rewrite->AsProperty();
+      if (property != NULL) {
+        VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
+        Literal* key_literal = property->key()->AsLiteral();
+        if (obj_proxy != NULL &&
+            key_literal != NULL &&
+            obj_proxy->IsArguments() &&
+            key_literal->handle()->IsSmi()) {
+          // Load arguments object if there are no eval-introduced
+          // variables. Then load the argument from the arguments
+          // object using keyed load.
+          Result arguments = allocator()->Allocate();
+          ASSERT(arguments.is_valid());
+          __ mov(arguments.reg(),
+                 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
+                                                   arguments,
+                                                   slow));
+          frame_->Push(&arguments);
+          frame_->Push(key_literal->handle());
+          *result = EmitKeyedLoad();
+          done->Jump(result);
+        }
+      }
+    }
+  }
+}
+
+
 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
   if (slot->type() == Slot::LOOKUP) {
     ASSERT(slot->var()->is_dynamic());
@@ -5774,11 +5795,33 @@
   } else if (var != NULL && var->slot() != NULL &&
              var->slot()->type() == Slot::LOOKUP) {
     // ----------------------------------
-    // JavaScript example: 'with (obj) foo(1, 2, 3)'  // foo is in obj
+    // JavaScript examples:
+    //
+    //  with (obj) foo(1, 2, 3)  // foo may be in obj.
+    //
+    //  function f() {};
+    //  function g() {
+    //    eval(...);
+    //    f();  // f could be in extension object.
+    //  }
     // ----------------------------------
 
-    // Load the function from the context.  Sync the frame so we can
-    // push the arguments directly into place.
+    JumpTarget slow, done;
+    Result function;
+
+    // Generate fast case for loading functions from slots that
+    // correspond to local/global variables or arguments unless they
+    // are shadowed by eval-introduced bindings.
+    EmitDynamicLoadFromSlotFastCase(var->slot(),
+                                    NOT_INSIDE_TYPEOF,
+                                    &function,
+                                    &slow,
+                                    &done);
+
+    slow.Bind();
+    // Enter the runtime system to load the function from the context.
+    // Sync the frame so we can push the arguments directly into
+    // place.
     frame_->SyncRange(0, frame_->element_count() - 1);
     frame_->EmitPush(esi);
     frame_->EmitPush(Immediate(var->name()));
@@ -5795,6 +5838,18 @@
     ASSERT(!allocator()->is_used(edx));
     frame_->EmitPush(edx);
 
+    // If fast case code has been generated, emit code to push the
+    // function and receiver and have the slow path jump around this
+    // code.
+    if (done.is_linked()) {
+      JumpTarget call;
+      call.Jump();
+      done.Bind(&function);
+      frame_->Push(&function);
+      LoadGlobalReceiver();
+      call.Bind();
+    }
+
     // Call the function.
     CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position());
 
@@ -6582,14 +6637,110 @@
   virtual void Generate();
 
  private:
-  Register dst_, cache_, key_;
+  Register dst_;    // on invocation Smi index of finger, on exit
+                    // holds value being looked up.
+  Register cache_;  // instance of JSFunctionResultCache.
+  Register key_;    // key being looked up.
 };
 
 
 void DeferredSearchCache::Generate() {
-  __ push(cache_);
+  Label first_loop, search_further, second_loop, cache_miss;
+
+  // Smi-tagging is equivalent to multiplying by 2.
+  STATIC_ASSERT(kSmiTag == 0);
+  STATIC_ASSERT(kSmiTagSize == 1);
+
+  Smi* kEntrySizeSmi = Smi::FromInt(JSFunctionResultCache::kEntrySize);
+  Smi* kEntriesIndexSmi = Smi::FromInt(JSFunctionResultCache::kEntriesIndex);
+
+  // Check the cache from finger to start of the cache.
+  __ bind(&first_loop);
+  __ sub(Operand(dst_), Immediate(kEntrySizeSmi));
+  __ cmp(Operand(dst_), Immediate(kEntriesIndexSmi));
+  __ j(less, &search_further);
+
+  __ cmp(key_, CodeGenerator::FixedArrayElementOperand(cache_, dst_));
+  __ j(not_equal, &first_loop);
+
+  __ mov(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), dst_);
+  __ mov(dst_, CodeGenerator::FixedArrayElementOperand(cache_, dst_, 1));
+  __ jmp(exit_label());
+
+  __ bind(&search_further);
+
+  // Check the cache from end of cache up to finger.
+  __ mov(dst_, FieldOperand(cache_, JSFunctionResultCache::kCacheSizeOffset));
+
+  __ bind(&second_loop);
+  __ sub(Operand(dst_), Immediate(kEntrySizeSmi));
+    // Consider prefetching into some reg.
+  __ cmp(dst_, FieldOperand(cache_, JSFunctionResultCache::kFingerOffset));
+  __ j(less_equal, &cache_miss);
+
+  __ cmp(key_, CodeGenerator::FixedArrayElementOperand(cache_, dst_));
+  __ j(not_equal, &second_loop);
+
+  __ mov(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), dst_);
+  __ mov(dst_, CodeGenerator::FixedArrayElementOperand(cache_, dst_, 1));
+  __ jmp(exit_label());
+
+  __ bind(&cache_miss);
+  __ push(cache_);  // store a reference to cache
+  __ push(key_);  // store a key
+  Handle<Object> receiver(Top::global_context()->global());
+  __ push(Immediate(receiver));
   __ push(key_);
-  __ CallRuntime(Runtime::kGetFromCache, 2);
+  // On ia32 function must be in edi.
+  __ mov(edi, FieldOperand(cache_, JSFunctionResultCache::kFactoryOffset));
+  ParameterCount expected(1);
+  __ InvokeFunction(edi, expected, CALL_FUNCTION);
+
+  // Find a place to put new cached value into.
+  Label add_new_entry, update_cache;
+  __ mov(ecx, Operand(esp, kPointerSize));  // restore the cache
+  // Possible optimization: cache size is constant for the given cache
+  // so technically we could use a constant here.  However, if we have
+  // cache miss this optimization would hardly matter much.
+
+  // Check if we could add new entry to cache.
+  __ mov(ebx, FieldOperand(ecx, FixedArray::kLengthOffset));
+  __ SmiTag(ebx);
+  __ cmp(ebx, FieldOperand(ecx, JSFunctionResultCache::kCacheSizeOffset));
+  __ j(greater, &add_new_entry);
+
+  // Check if we could evict entry after finger.
+  __ mov(edx, FieldOperand(ecx, JSFunctionResultCache::kFingerOffset));
+  __ add(Operand(edx), Immediate(kEntrySizeSmi));
+  __ cmp(ebx, Operand(edx));
+  __ j(greater, &update_cache);
+
+  // Need to wrap over the cache.
+  __ mov(edx, Immediate(kEntriesIndexSmi));
+  __ jmp(&update_cache);
+
+  __ bind(&add_new_entry);
+  __ mov(edx, FieldOperand(ecx, JSFunctionResultCache::kCacheSizeOffset));
+  __ lea(ebx, Operand(edx, JSFunctionResultCache::kEntrySize << 1));
+  __ mov(FieldOperand(ecx, JSFunctionResultCache::kCacheSizeOffset), ebx);
+
+  // Update the cache itself.
+  // edx holds the index.
+  __ bind(&update_cache);
+  __ pop(ebx);  // restore the key
+  __ mov(FieldOperand(ecx, JSFunctionResultCache::kFingerOffset), edx);
+  // Store key.
+  __ mov(CodeGenerator::FixedArrayElementOperand(ecx, edx), ebx);
+  __ RecordWrite(ecx, 0, ebx, edx);
+
+  // Store value.
+  __ pop(ecx);  // restore the cache.
+  __ mov(edx, FieldOperand(ecx, JSFunctionResultCache::kFingerOffset));
+  __ add(Operand(edx), Immediate(Smi::FromInt(1)));
+  __ mov(ebx, eax);
+  __ mov(CodeGenerator::FixedArrayElementOperand(ecx, edx), ebx);
+  __ RecordWrite(ecx, 0, ebx, edx);
+
   if (!dst_.is(eax)) {
     __ mov(dst_, eax);
   }
@@ -6631,21 +6782,14 @@
                                                           cache.reg(),
                                                           key.reg());
 
-  const int kFingerOffset =
-      FixedArray::OffsetOfElementAt(JSFunctionResultCache::kFingerIndex);
   // tmp.reg() now holds finger offset as a smi.
   ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
-  __ mov(tmp.reg(), FieldOperand(cache.reg(), kFingerOffset));
-  __ cmp(key.reg(), FieldOperand(cache.reg(),
-                                 tmp.reg(),  // as smi
-                                 times_half_pointer_size,
-                                 FixedArray::kHeaderSize));
+  __ mov(tmp.reg(), FieldOperand(cache.reg(),
+                                 JSFunctionResultCache::kFingerOffset));
+  __ cmp(key.reg(), FixedArrayElementOperand(cache.reg(), tmp.reg()));
   deferred->Branch(not_equal);
 
-  __ mov(tmp.reg(), FieldOperand(cache.reg(),
-                                 tmp.reg(),  // as smi
-                                 times_half_pointer_size,
-                                 kPointerSize + FixedArray::kHeaderSize));
+  __ mov(tmp.reg(), FixedArrayElementOperand(cache.reg(), tmp.reg(), 1));
 
   deferred->BindExit();
   frame_->Push(&tmp);
@@ -6744,14 +6888,8 @@
   deferred->Branch(not_zero);
 
   // Bring addresses into index1 and index2.
-  __ lea(index1.reg(), FieldOperand(tmp1.reg(),
-                                    index1.reg(),
-                                    times_half_pointer_size,  // index1 is Smi
-                                    FixedArray::kHeaderSize));
-  __ lea(index2.reg(), FieldOperand(tmp1.reg(),
-                                    index2.reg(),
-                                    times_half_pointer_size,  // index2 is Smi
-                                    FixedArray::kHeaderSize));
+  __ lea(index1.reg(), FixedArrayElementOperand(tmp1.reg(), index1.reg()));
+  __ lea(index2.reg(), FixedArrayElementOperand(tmp1.reg(), index2.reg()));
 
   // Swap elements.
   __ mov(object.reg(), Operand(index1.reg(), 0));
@@ -8624,11 +8762,7 @@
     deferred->Branch(not_equal);
 
     // Store the value.
-    __ mov(Operand(tmp.reg(),
-                   key.reg(),
-                   times_2,
-                   FixedArray::kHeaderSize - kHeapObjectTag),
-           result.reg());
+    __ mov(FixedArrayElementOperand(tmp.reg(), key.reg()), result.reg());
     __ IncrementCounter(&Counters::keyed_store_inline, 1);
 
     deferred->BindExit();
@@ -8930,7 +9064,7 @@
   __ mov(ecx, Operand(esp, 3 * kPointerSize));
   __ mov(eax, Operand(esp, 2 * kPointerSize));
   ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0));
-  __ mov(ecx, FieldOperand(ecx, eax, times_2, FixedArray::kHeaderSize));
+  __ mov(ecx, CodeGenerator::FixedArrayElementOperand(ecx, eax));
   __ cmp(ecx, Factory::undefined_value());
   __ j(equal, &slow_case);
 
@@ -10152,6 +10286,11 @@
   Label done, right_exponent, normal_exponent;
   Register scratch = ebx;
   Register scratch2 = edi;
+  if (type_info.IsInteger32() && CpuFeatures::IsEnabled(SSE2)) {
+    CpuFeatures::Scope scope(SSE2);
+    __ cvttsd2si(ecx, FieldOperand(source, HeapNumber::kValueOffset));
+    return;
+  }
   if (!type_info.IsInteger32() || !use_sse3) {
     // Get exponent word.
     __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset));
@@ -10958,7 +11097,7 @@
   // string length. A negative value will be greater (unsigned comparison).
   __ mov(eax, Operand(esp, kPreviousIndexOffset));
   __ test(eax, Immediate(kSmiTagMask));
-  __ j(zero, &runtime);
+  __ j(not_zero, &runtime);
   __ cmp(eax, Operand(ebx));
   __ j(above_equal, &runtime);
 
@@ -12128,6 +12267,22 @@
 
   // Get the prototype of the function.
   __ mov(edx, Operand(esp, 1 * kPointerSize));  // 1 ~ return address
+  // edx is function, eax is map.
+
+  // Look up the function and the map in the instanceof cache.
+  Label miss;
+  ExternalReference roots_address = ExternalReference::roots_address();
+  __ mov(ecx, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
+  __ cmp(edx, Operand::StaticArray(ecx, times_pointer_size, roots_address));
+  __ j(not_equal, &miss);
+  __ mov(ecx, Immediate(Heap::kInstanceofCacheMapRootIndex));
+  __ cmp(eax, Operand::StaticArray(ecx, times_pointer_size, roots_address));
+  __ j(not_equal, &miss);
+  __ mov(ecx, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
+  __ mov(eax, Operand::StaticArray(ecx, times_pointer_size, roots_address));
+  __ ret(2 * kPointerSize);
+
+  __ bind(&miss);
   __ TryGetFunctionPrototype(edx, ebx, ecx, &slow);
 
   // Check that the function prototype is a JS object.
@@ -12140,7 +12295,15 @@
   __ cmp(ecx, LAST_JS_OBJECT_TYPE);
   __ j(greater, &slow, not_taken);
 
-  // Register mapping: eax is object map and ebx is function prototype.
+  // Register mapping:
+  //   eax is object map.
+  //   edx is function.
+  //   ebx is function prototype.
+  __ mov(ecx, Immediate(Heap::kInstanceofCacheMapRootIndex));
+  __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), eax);
+  __ mov(ecx, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
+  __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), edx);
+
   __ mov(ecx, FieldOperand(eax, Map::kPrototypeOffset));
 
   // Loop through the prototype chain looking for the function prototype.
@@ -12156,10 +12319,14 @@
 
   __ bind(&is_instance);
   __ Set(eax, Immediate(0));
+  __ mov(ecx, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
+  __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), eax);
   __ ret(2 * kPointerSize);
 
   __ bind(&is_not_instance);
   __ Set(eax, Immediate(Smi::FromInt(1)));
+  __ mov(ecx, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
+  __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), eax);
   __ ret(2 * kPointerSize);
 
   // Slow-case: Go through the JavaScript implementation.
diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h
index 0d3fee5..e00bec7 100644
--- a/src/ia32/codegen-ia32.h
+++ b/src/ia32/codegen-ia32.h
@@ -28,7 +28,9 @@
 #ifndef V8_IA32_CODEGEN_IA32_H_
 #define V8_IA32_CODEGEN_IA32_H_
 
+#include "ast.h"
 #include "ic-inl.h"
+#include "jump-target-heavy.h"
 
 namespace v8 {
 namespace internal {
@@ -48,7 +50,7 @@
 
 // A reference is a C++ stack-allocated object that puts a
 // reference on the virtual frame.  The reference may be consumed
-// by GetValue, TakeValue, SetValue, and Codegen::UnloadReference.
+// by GetValue, TakeValue and SetValue.
 // When the lifetime (scope) of a valid reference ends, it must have
 // been consumed, and be in state UNLOADED.
 class Reference BASE_EMBEDDED {
@@ -343,6 +345,15 @@
   // expected arguments. Otherwise return -1.
   static int InlineRuntimeCallArgumentsCount(Handle<String> name);
 
+  // Return a position of the element at |index_as_smi| + |additional_offset|
+  // in FixedArray pointer to which is held in |array|.  |index_as_smi| is Smi.
+  static Operand FixedArrayElementOperand(Register array,
+                                          Register index_as_smi,
+                                          int additional_offset = 0) {
+    int offset = FixedArray::kHeaderSize + additional_offset * kPointerSize;
+    return FieldOperand(array, index_as_smi, times_half_pointer_size, offset);
+  }
+
  private:
   // Construction/Destruction
   explicit CodeGenerator(MacroAssembler* masm);
@@ -414,7 +425,6 @@
 
   // The following are used by class Reference.
   void LoadReference(Reference* ref);
-  void UnloadReference(Reference* ref);
 
   static Operand ContextOperand(Register context, int index) {
     return Operand(context, Context::SlotOffset(index));
@@ -455,6 +465,16 @@
                                            TypeofState typeof_state,
                                            JumpTarget* slow);
 
+  // Support for loading from local/global variables and arguments
+  // whose location is known unless they are shadowed by
+  // eval-introduced bindings. Generates no code for unsupported slot
+  // types and therefore expects to fall through to the slow jump target.
+  void EmitDynamicLoadFromSlotFastCase(Slot* slot,
+                                       TypeofState typeof_state,
+                                       Result* result,
+                                       JumpTarget* slow,
+                                       JumpTarget* done);
+
   // Store the value on top of the expression stack into a slot, leaving the
   // value in place.
   void StoreToSlot(Slot* slot, InitState init_state);
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index bc7a33c..4929c8a 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -868,7 +868,7 @@
   // ecx: key (a smi)
   // edx: receiver
   // edi: FixedArray receiver->elements
-  __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax);
+  __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax);
   // Update write barrier for the elements array address.
   __ mov(edx, Operand(eax));
   __ RecordWrite(edi, 0, edx, ecx);
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index c3a019b..9c8dfb2 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -33,6 +33,17 @@
 namespace v8 {
 namespace internal {
 
+// Flags used for the AllocateInNewSpace functions.
+enum AllocationFlags {
+  // No special flags.
+  NO_ALLOCATION_FLAGS = 0,
+  // Return the pointer to the allocated already tagged as a heap object.
+  TAG_OBJECT = 1 << 0,
+  // The content of the result register already contains the allocation top in
+  // new space.
+  RESULT_CONTAINS_TOP = 1 << 1
+};
+
 // Convenience for platform-independent signatures.  We do not normally
 // distinguish memory operands from other operands on ia32.
 typedef Operand MemOperand;
diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index fdf3b9f..d9dddd6 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -51,7 +51,7 @@
  * - esp : points to tip of C stack.
  * - ecx : points to tip of backtrack stack
  *
- * The registers eax, ebx and ecx are free to use for computations.
+ * The registers eax and ebx are free to use for computations.
  *
  * Each call to a public method should retain this convention.
  * The stack will have the following structure:
@@ -72,8 +72,6 @@
  *       - backup of caller ebx
  *       - Offset of location before start of input (effectively character
  *         position -1). Used to initialize capture registers to a non-position.
- *       - Boolean at start (if 1, we are starting at the start of the string,
- *         otherwise 0)
  *       - register 0  ebp[-4]  (Only positions must be stored in the first
  *       - register 1  ebp[-8]   num_saved_registers_ registers)
  *       - ...
@@ -178,8 +176,8 @@
 void RegExpMacroAssemblerIA32::CheckAtStart(Label* on_at_start) {
   Label not_at_start;
   // Did we start the match at the start of the string at all?
-  __ cmp(Operand(ebp, kAtStart), Immediate(0));
-  BranchOrBacktrack(equal, &not_at_start);
+  __ cmp(Operand(ebp, kStartIndex), Immediate(0));
+  BranchOrBacktrack(not_equal, &not_at_start);
   // If we did, are we still at the start of the input?
   __ lea(eax, Operand(esi, edi, times_1, 0));
   __ cmp(eax, Operand(ebp, kInputStart));
@@ -190,8 +188,8 @@
 
 void RegExpMacroAssemblerIA32::CheckNotAtStart(Label* on_not_at_start) {
   // Did we start the match at the start of the string at all?
-  __ cmp(Operand(ebp, kAtStart), Immediate(0));
-  BranchOrBacktrack(equal, on_not_at_start);
+  __ cmp(Operand(ebp, kStartIndex), Immediate(0));
+  BranchOrBacktrack(not_equal, on_not_at_start);
   // If we did, are we still at the start of the input?
   __ lea(eax, Operand(esi, edi, times_1, 0));
   __ cmp(eax, Operand(ebp, kInputStart));
@@ -209,6 +207,15 @@
                                                int cp_offset,
                                                Label* on_failure,
                                                bool check_end_of_string) {
+#ifdef DEBUG
+  // If input is ASCII, don't even bother calling here if the string to
+  // match contains a non-ascii character.
+  if (mode_ == ASCII) {
+    for (int i = 0; i < str.length(); i++) {
+      ASSERT(str[i] <= String::kMaxAsciiCharCodeU);
+    }
+  }
+#endif
   int byte_length = str.length() * char_size();
   int byte_offset = cp_offset * char_size();
   if (check_end_of_string) {
@@ -222,14 +229,56 @@
     on_failure = &backtrack_label_;
   }
 
-  for (int i = 0; i < str.length(); i++) {
+  // Do one character test first to minimize loading for the case that
+  // we don't match at all (loading more than one character introduces that
+  // chance of reading unaligned and reading across cache boundaries).
+  // If the first character matches, expect a larger chance of matching the
+  // string, and start loading more characters at a time.
+  if (mode_ == ASCII) {
+    __ cmpb(Operand(esi, edi, times_1, byte_offset),
+            static_cast<int8_t>(str[0]));
+  } else {
+    // Don't use 16-bit immediate. The size changing prefix throws off
+    // pre-decoding.
+    __ movzx_w(eax,
+               Operand(esi, edi, times_1, byte_offset));
+    __ cmp(eax, static_cast<int32_t>(str[0]));
+  }
+  BranchOrBacktrack(not_equal, on_failure);
+
+  __ lea(ebx, Operand(esi, edi, times_1, 0));
+  for (int i = 1, n = str.length(); i < n;) {
     if (mode_ == ASCII) {
-      __ cmpb(Operand(esi, edi, times_1, byte_offset + i),
-              static_cast<int8_t>(str[i]));
+      if (i <= n - 4) {
+        int combined_chars =
+            (static_cast<uint32_t>(str[i + 0]) << 0) |
+            (static_cast<uint32_t>(str[i + 1]) << 8) |
+            (static_cast<uint32_t>(str[i + 2]) << 16) |
+            (static_cast<uint32_t>(str[i + 3]) << 24);
+        __ cmp(Operand(ebx, byte_offset + i), Immediate(combined_chars));
+        i += 4;
+      } else {
+        __ cmpb(Operand(ebx, byte_offset + i),
+                static_cast<int8_t>(str[i]));
+        i += 1;
+      }
     } else {
       ASSERT(mode_ == UC16);
-      __ cmpw(Operand(esi, edi, times_1, byte_offset + i * sizeof(uc16)),
-              Immediate(str[i]));
+      if (i <= n - 2) {
+        __ cmp(Operand(ebx, byte_offset + i * sizeof(uc16)),
+               Immediate(*reinterpret_cast<const int*>(&str[i])));
+        i += 2;
+      } else {
+        // Avoid a 16-bit immediate operation. It uses the length-changing
+        // 0x66 prefix which causes pre-decoder misprediction and pipeline
+        // stalls. See
+        // "Intel(R) 64 and IA-32 Architectures Optimization Reference Manual"
+        // (248966.pdf) section 3.4.2.3 "Length-Changing Prefixes (LCP)"
+        __ movzx_w(eax,
+                   Operand(ebx, byte_offset + i * sizeof(uc16)));
+        __ cmp(eax, static_cast<int32_t>(str[i]));
+        i += 1;
+      }
     }
     BranchOrBacktrack(not_equal, on_failure);
   }
@@ -625,7 +674,6 @@
   __ push(edi);
   __ push(ebx);  // Callee-save on MacOS.
   __ push(Immediate(0));  // Make room for "input start - 1" constant.
-  __ push(Immediate(0));  // Make room for "at start" constant.
 
   // Check if we have space on the stack for registers.
   Label stack_limit_hit;
@@ -677,14 +725,6 @@
   // position registers.
   __ mov(Operand(ebp, kInputStartMinusOne), eax);
 
-  // Determine whether the start index is zero, that is at the start of the
-  // string, and store that value in a local variable.
-  __ xor_(Operand(ecx), ecx);  // setcc only operates on cl (lower byte of ecx).
-  // Register ebx still holds -stringIndex.
-  __ test(ebx, Operand(ebx));
-  __ setcc(zero, ecx);  // 1 if 0 (start of string), 0 if positive.
-  __ mov(Operand(ebp, kAtStart), ecx);
-
   if (num_saved_registers_ > 0) {  // Always is, if generated from a regexp.
     // Fill saved registers with initial value = start offset - 1
     // Fill in stack push order, to avoid accessing across an unwritten
@@ -712,8 +752,8 @@
   __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
   // Load previous char as initial value of current-character.
   Label at_start;
-  __ cmp(Operand(ebp, kAtStart), Immediate(0));
-  __ j(not_equal, &at_start);
+  __ cmp(Operand(ebp, kStartIndex), Immediate(0));
+  __ j(equal, &at_start);
   LoadCurrentCharacterUnchecked(-1, 1);  // Load previous char.
   __ jmp(&start_label_);
   __ bind(&at_start);
diff --git a/src/ia32/regexp-macro-assembler-ia32.h b/src/ia32/regexp-macro-assembler-ia32.h
index 823bc03..8b8eeed 100644
--- a/src/ia32/regexp-macro-assembler-ia32.h
+++ b/src/ia32/regexp-macro-assembler-ia32.h
@@ -132,9 +132,8 @@
   static const int kBackup_edi = kBackup_esi - kPointerSize;
   static const int kBackup_ebx = kBackup_edi - kPointerSize;
   static const int kInputStartMinusOne = kBackup_ebx - kPointerSize;
-  static const int kAtStart = kInputStartMinusOne - kPointerSize;
   // First register address. Following registers are below it on the stack.
-  static const int kRegisterZero = kAtStart - kPointerSize;
+  static const int kRegisterZero = kInputStartMinusOne - kPointerSize;
 
   // Initial size of code buffer.
   static const size_t kRegExpCodeSize = 1024;
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 809228c..189c0e4 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -1264,16 +1264,11 @@
   }
 
   __ bind(&miss);
-
   Handle<Code> ic = ComputeCallMiss(arguments().immediate());
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
@@ -1351,16 +1346,11 @@
                                1);
 
   __ bind(&miss);
-
   Handle<Code> ic = ComputeCallMiss(arguments().immediate());
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
@@ -1379,9 +1369,9 @@
 
   SharedFunctionInfo* function_info = function->shared();
   if (function_info->HasCustomCallGenerator()) {
-    CustomCallGenerator generator =
-        ToCData<CustomCallGenerator>(function_info->function_data());
-    Object* result = generator(this, object, holder, function, name, check);
+    const int id = function_info->custom_call_generator_id();
+    Object* result =
+        CompileCustomCall(id, object, holder, function, name, check);
     // undefined means bail out to regular compiler.
     if (!result->IsUndefined()) {
       return result;
@@ -1518,11 +1508,7 @@
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
diff --git a/src/ia32/virtual-frame-ia32.h b/src/ia32/virtual-frame-ia32.h
index 14fe466..51a802c 100644
--- a/src/ia32/virtual-frame-ia32.h
+++ b/src/ia32/virtual-frame-ia32.h
@@ -28,9 +28,10 @@
 #ifndef V8_IA32_VIRTUAL_FRAME_IA32_H_
 #define V8_IA32_VIRTUAL_FRAME_IA32_H_
 
-#include "type-info.h"
+#include "codegen.h"
 #include "register-allocator.h"
 #include "scopes.h"
+#include "type-info.h"
 
 namespace v8 {
 namespace internal {
@@ -97,23 +98,16 @@
     return register_locations_[num];
   }
 
-  int register_location(Register reg) {
-    return register_locations_[RegisterAllocator::ToNumber(reg)];
-  }
+  inline int register_location(Register reg);
 
-  void set_register_location(Register reg, int index) {
-    register_locations_[RegisterAllocator::ToNumber(reg)] = index;
-  }
+  inline void set_register_location(Register reg, int index);
 
   bool is_used(int num) {
     ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
     return register_locations_[num] != kIllegalIndex;
   }
 
-  bool is_used(Register reg) {
-    return register_locations_[RegisterAllocator::ToNumber(reg)]
-        != kIllegalIndex;
-  }
+  inline bool is_used(Register reg);
 
   // Add extra in-memory elements to the top of the frame to match an actual
   // frame (eg, the frame after an exception handler is pushed).  No code is
@@ -217,10 +211,7 @@
   void SetElementAt(int index, Result* value);
 
   // Set a frame element to a constant.  The index is frame-top relative.
-  void SetElementAt(int index, Handle<Object> value) {
-    Result temp(value);
-    SetElementAt(index, &temp);
-  }
+  inline void SetElementAt(int index, Handle<Object> value);
 
   void PushElementAt(int index) {
     PushFrameSlotAt(element_count() - index - 1);
@@ -315,10 +306,7 @@
 
   // Call stub given the number of arguments it expects on (and
   // removes from) the stack.
-  Result CallStub(CodeStub* stub, int arg_count) {
-    PrepareForCall(arg_count, arg_count);
-    return RawCallStub(stub);
-  }
+  inline Result CallStub(CodeStub* stub, int arg_count);
 
   // Call stub that takes a single argument passed in eax.  The
   // argument is given as a result which does not have to be eax or
@@ -473,12 +461,9 @@
   int register_locations_[RegisterAllocator::kNumRegisters];
 
   // The number of frame-allocated locals and parameters respectively.
-  int parameter_count() {
-    return cgen()->scope()->num_parameters();
-  }
-  int local_count() {
-    return cgen()->scope()->num_stack_slots();
-  }
+  inline int parameter_count();
+
+  inline int local_count();
 
   // The index of the element that is at the processor's frame pointer
   // (the ebp register).  The parameters, receiver, and return address
diff --git a/src/ic.cc b/src/ic.cc
index 64c3ec1..678876d 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -596,10 +596,16 @@
 #ifdef DEBUG
       if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
 #endif
+      Map* map = HeapObject::cast(*object)->map();
+      if (object->IsString()) {
+        const int offset = String::kLengthOffset;
+        PatchInlinedLoad(address(), map, offset);
+      }
+
       Code* target = NULL;
       target = Builtins::builtin(Builtins::LoadIC_StringLength);
       set_target(target);
-      StubCache::Set(*name, HeapObject::cast(*object)->map(), target);
+      StubCache::Set(*name, map, target);
       return Smi::FromInt(String::cast(*object)->length());
     }
 
@@ -608,9 +614,13 @@
 #ifdef DEBUG
       if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
 #endif
+      Map* map = HeapObject::cast(*object)->map();
+      const int offset = JSArray::kLengthOffset;
+      PatchInlinedLoad(address(), map, offset);
+
       Code* target = Builtins::builtin(Builtins::LoadIC_ArrayLength);
       set_target(target);
-      StubCache::Set(*name, HeapObject::cast(*object)->map(), target);
+      StubCache::Set(*name, map, target);
       return JSArray::cast(*object)->length();
     }
 
diff --git a/src/ic.h b/src/ic.h
index 6aae096..a7ff6e6 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -239,6 +239,9 @@
   static void GenerateStringLength(MacroAssembler* masm);
   static void GenerateFunctionPrototype(MacroAssembler* masm);
 
+  // Clear the use of the inlined version.
+  static void ClearInlinedVersion(Address address);
+
   // The offset from the inlined patch site to the start of the
   // inlined load instruction.  It is architecture-dependent, and not
   // used on ARM.
@@ -265,9 +268,6 @@
 
   static void Clear(Address address, Code* target);
 
-  // Clear the use of the inlined version.
-  static void ClearInlinedVersion(Address address);
-
   static bool PatchInlinedLoad(Address address, Object* map, int index);
 
   friend class IC;
diff --git a/src/jump-target-heavy.cc b/src/jump-target-heavy.cc
index 85620a2..468cf4a 100644
--- a/src/jump-target-heavy.cc
+++ b/src/jump-target-heavy.cc
@@ -35,6 +35,9 @@
 namespace internal {
 
 
+bool JumpTarget::compiling_deferred_code_ = false;
+
+
 void JumpTarget::Jump(Result* arg) {
   ASSERT(cgen()->has_valid_frame());
 
@@ -360,4 +363,64 @@
   }
 }
 
+
+void JumpTarget::Unuse() {
+  reaching_frames_.Clear();
+  merge_labels_.Clear();
+  entry_frame_ = NULL;
+  entry_label_.Unuse();
+}
+
+
+void JumpTarget::AddReachingFrame(VirtualFrame* frame) {
+  ASSERT(reaching_frames_.length() == merge_labels_.length());
+  ASSERT(entry_frame_ == NULL);
+  Label fresh;
+  merge_labels_.Add(fresh);
+  reaching_frames_.Add(frame);
+}
+
+
+// -------------------------------------------------------------------------
+// BreakTarget implementation.
+
+void BreakTarget::set_direction(Directionality direction) {
+  JumpTarget::set_direction(direction);
+  ASSERT(cgen()->has_valid_frame());
+  expected_height_ = cgen()->frame()->height();
+}
+
+
+void BreakTarget::CopyTo(BreakTarget* destination) {
+  ASSERT(destination != NULL);
+  destination->direction_ = direction_;
+  destination->reaching_frames_.Rewind(0);
+  destination->reaching_frames_.AddAll(reaching_frames_);
+  destination->merge_labels_.Rewind(0);
+  destination->merge_labels_.AddAll(merge_labels_);
+  destination->entry_frame_ = entry_frame_;
+  destination->entry_label_ = entry_label_;
+  destination->expected_height_ = expected_height_;
+}
+
+
+void BreakTarget::Branch(Condition cc, Hint hint) {
+  ASSERT(cgen()->has_valid_frame());
+
+  int count = cgen()->frame()->height() - expected_height_;
+  if (count > 0) {
+    // We negate and branch here rather than using DoBranch's negate
+    // and branch.  This gives us a hook to remove statement state
+    // from the frame.
+    JumpTarget fall_through;
+    // Branch to fall through will not negate, because it is a
+    // forward-only target.
+    fall_through.Branch(NegateCondition(cc), NegateHint(hint));
+    Jump();  // May emit merge code here.
+    fall_through.Bind();
+  } else {
+    DoBranch(cc, hint);
+  }
+}
+
 } }  // namespace v8::internal
diff --git a/src/jump-target-heavy.h b/src/jump-target-heavy.h
new file mode 100644
index 0000000..b923fe5
--- /dev/null
+++ b/src/jump-target-heavy.h
@@ -0,0 +1,242 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_JUMP_TARGET_HEAVY_H_
+#define V8_JUMP_TARGET_HEAVY_H_
+
+#include "macro-assembler.h"
+#include "zone-inl.h"
+
+namespace v8 {
+namespace internal {
+
+// Forward declarations.
+class FrameElement;
+class Result;
+class VirtualFrame;
+
+// -------------------------------------------------------------------------
+// Jump targets
+//
+// A jump target is an abstraction of a basic-block entry in generated
+// code.  It collects all the virtual frames reaching the block by
+// forward jumps and pairs them with labels for the merge code along
+// all forward-reaching paths.  When bound, an expected frame for the
+// block is determined and code is generated to merge to the expected
+// frame.  For backward jumps, the merge code is generated at the edge
+// leaving the predecessor block.
+//
+// A jump target must have been reached via control flow (either by
+// jumping, branching, or falling through) at the time it is bound.
+// In particular, this means that at least one of the control-flow
+// graph edges reaching the target must be a forward edge.
+
+class JumpTarget : public ZoneObject {  // Shadows are dynamically allocated.
+ public:
+  // Forward-only jump targets can only be reached by forward CFG edges.
+  enum Directionality { FORWARD_ONLY, BIDIRECTIONAL };
+
+  // Construct a jump target used to generate code and to provide
+  // access to a current frame.
+  explicit JumpTarget(Directionality direction)
+      : direction_(direction),
+        reaching_frames_(0),
+        merge_labels_(0),
+        entry_frame_(NULL) {
+  }
+
+  // Construct a jump target.
+  JumpTarget()
+      : direction_(FORWARD_ONLY),
+        reaching_frames_(0),
+        merge_labels_(0),
+        entry_frame_(NULL) {
+  }
+
+  virtual ~JumpTarget() {}
+
+  // Set the direction of the jump target.
+  virtual void set_direction(Directionality direction) {
+    direction_ = direction;
+  }
+
+  // Treat the jump target as a fresh one.  The state is reset.
+  void Unuse();
+
+  inline CodeGenerator* cgen();
+
+  Label* entry_label() { return &entry_label_; }
+
+  VirtualFrame* entry_frame() const { return entry_frame_; }
+  void set_entry_frame(VirtualFrame* frame) {
+    entry_frame_ = frame;
+  }
+
+  // Predicates testing the state of the encapsulated label.
+  bool is_bound() const { return entry_label_.is_bound(); }
+  bool is_linked() const {
+    return !is_bound() && !reaching_frames_.is_empty();
+  }
+  bool is_unused() const {
+    // This is !is_bound() && !is_linked().
+    return !is_bound() && reaching_frames_.is_empty();
+  }
+
+  // Emit a jump to the target.  There must be a current frame at the
+  // jump and there will be no current frame after the jump.
+  virtual void Jump();
+  virtual void Jump(Result* arg);
+
+  // Emit a conditional branch to the target.  There must be a current
+  // frame at the branch.  The current frame will fall through to the
+  // code after the branch.  The arg is a result that is live both at
+  // the target and the fall-through.
+  virtual void Branch(Condition cc, Hint hint = no_hint);
+  virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
+  virtual void Branch(Condition cc,
+                      Result* arg0,
+                      Result* arg1,
+                      Hint hint = no_hint);
+
+  // Bind a jump target.  If there is no current frame at the binding
+  // site, there must be at least one frame reaching via a forward
+  // jump.
+  virtual void Bind();
+  virtual void Bind(Result* arg);
+  virtual void Bind(Result* arg0, Result* arg1);
+
+  // Emit a call to a jump target.  There must be a current frame at
+  // the call.  The frame at the target is the same as the current
+  // frame except for an extra return address on top of it.  The frame
+  // after the call is the same as the frame before the call.
+  void Call();
+
+  static void set_compiling_deferred_code(bool flag) {
+    compiling_deferred_code_ = flag;
+  }
+
+ protected:
+  // Directionality flag set at initialization time.
+  Directionality direction_;
+
+  // A list of frames reaching this block via forward jumps.
+  ZoneList<VirtualFrame*> reaching_frames_;
+
+  // A parallel list of labels for merge code.
+  ZoneList<Label> merge_labels_;
+
+  // The frame used on entry to the block and expected at backward
+  // jumps to the block.  Set when the jump target is bound, but may
+  // or may not be set for forward-only blocks.
+  VirtualFrame* entry_frame_;
+
+  // The actual entry label of the block.
+  Label entry_label_;
+
+  // Implementations of Jump, Branch, and Bind with all arguments and
+  // return values using the virtual frame.
+  void DoJump();
+  void DoBranch(Condition cc, Hint hint);
+  void DoBind();
+
+ private:
+  static bool compiling_deferred_code_;
+
+  // Add a virtual frame reaching this labeled block via a forward jump,
+  // and a corresponding merge code label.
+  void AddReachingFrame(VirtualFrame* frame);
+
+  // Perform initialization required during entry frame computation
+  // after setting the virtual frame element at index in frame to be
+  // target.
+  inline void InitializeEntryElement(int index, FrameElement* target);
+
+  // Compute a frame to use for entry to this block.
+  void ComputeEntryFrame();
+
+  DISALLOW_COPY_AND_ASSIGN(JumpTarget);
+};
+
+
+// -------------------------------------------------------------------------
+// Break targets
+//
+// A break target is a jump target that can be used to break out of a
+// statement that keeps extra state on the stack (eg, for/in or
+// try/finally).  They know the expected stack height at the target
+// and will drop state from nested statements as part of merging.
+//
+// Break targets are used for return, break, and continue targets.
+
+class BreakTarget : public JumpTarget {
+ public:
+  // Construct a break target.
+  BreakTarget() {}
+
+  virtual ~BreakTarget() {}
+
+  // Set the direction of the break target.
+  virtual void set_direction(Directionality direction);
+
+  // Copy the state of this break target to the destination.  The
+  // lists of forward-reaching frames and merge-point labels are
+  // copied.  All virtual frame pointers are copied, not the
+  // pointed-to frames.  The previous state of the destination is
+  // overwritten, without deallocating pointed-to virtual frames.
+  void CopyTo(BreakTarget* destination);
+
+  // Emit a jump to the target.  There must be a current frame at the
+  // jump and there will be no current frame after the jump.
+  virtual void Jump();
+  virtual void Jump(Result* arg);
+
+  // Emit a conditional branch to the target.  There must be a current
+  // frame at the branch.  The current frame will fall through to the
+  // code after the branch.
+  virtual void Branch(Condition cc, Hint hint = no_hint);
+  virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
+
+  // Bind a break target.  If there is no current frame at the binding
+  // site, there must be at least one frame reaching via a forward
+  // jump.
+  virtual void Bind();
+  virtual void Bind(Result* arg);
+
+  // Setter for expected height.
+  void set_expected_height(int expected) { expected_height_ = expected; }
+
+ private:
+  // The expected height of the expression stack where the target will
+  // be bound, statically known at initialization time.
+  int expected_height_;
+
+  DISALLOW_COPY_AND_ASSIGN(BreakTarget);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_JUMP_TARGET_HEAVY_H_
diff --git a/src/jump-target-light-inl.h b/src/jump-target-light-inl.h
index 8d6c3ac..0b4eee4 100644
--- a/src/jump-target-light-inl.h
+++ b/src/jump-target-light-inl.h
@@ -33,10 +33,20 @@
 namespace v8 {
 namespace internal {
 
-void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
-  UNIMPLEMENTED();
+// Construct a jump target.
+JumpTarget::JumpTarget(Directionality direction)
+    : entry_frame_set_(false),
+      entry_frame_(kInvalidVirtualFrameInitializer) {
 }
 
+JumpTarget::JumpTarget()
+    : entry_frame_set_(false),
+      entry_frame_(kInvalidVirtualFrameInitializer) {
+}
+
+
+BreakTarget::BreakTarget() { }
+
 } }  // namespace v8::internal
 
 #endif  // V8_JUMP_TARGET_LIGHT_INL_H_
diff --git a/src/jump-target-light.cc b/src/jump-target-light.cc
index befb430..76c3cb7 100644
--- a/src/jump-target-light.cc
+++ b/src/jump-target-light.cc
@@ -34,41 +34,6 @@
 namespace internal {
 
 
-void JumpTarget::Jump(Result* arg) {
-  UNIMPLEMENTED();
-}
-
-
-void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) {
-  UNIMPLEMENTED();
-}
-
-
-void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) {
-  UNIMPLEMENTED();
-}
-
-
-void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
-  UNIMPLEMENTED();
-}
-
-
-void JumpTarget::Bind(Result* arg) {
-  UNIMPLEMENTED();
-}
-
-
-void JumpTarget::Bind(Result* arg0, Result* arg1) {
-  UNIMPLEMENTED();
-}
-
-
-void JumpTarget::ComputeEntryFrame() {
-  UNIMPLEMENTED();
-}
-
-
 DeferredCode::DeferredCode()
     : masm_(CodeGeneratorScope::Current()->masm()),
       statement_position_(masm_->current_statement_position()),
@@ -83,4 +48,62 @@
 #endif
 }
 
+
+// -------------------------------------------------------------------------
+// BreakTarget implementation.
+
+
+void BreakTarget::SetExpectedHeight() {
+  expected_height_ = cgen()->frame()->height();
+}
+
+
+void BreakTarget::Jump() {
+  ASSERT(cgen()->has_valid_frame());
+
+  int count = cgen()->frame()->height() - expected_height_;
+  if (count > 0) {
+    cgen()->frame()->Drop(count);
+  }
+  DoJump();
+}
+
+
+void BreakTarget::Branch(Condition cc, Hint hint) {
+  if (cc == al) {
+    Jump();
+    return;
+  }
+
+  ASSERT(cgen()->has_valid_frame());
+
+  int count = cgen()->frame()->height() - expected_height_;
+  if (count > 0) {
+    // We negate and branch here rather than using DoBranch's negate
+    // and branch.  This gives us a hook to remove statement state
+    // from the frame.
+    JumpTarget fall_through;
+    // Branch to fall through will not negate, because it is a
+    // forward-only target.
+    fall_through.Branch(NegateCondition(cc), NegateHint(hint));
+    // Emit merge code.
+    cgen()->frame()->Drop(count);
+    DoJump();
+    fall_through.Bind();
+  } else {
+    DoBranch(cc, hint);
+  }
+}
+
+
+void BreakTarget::Bind() {
+  if (cgen()->has_valid_frame()) {
+    int count = cgen()->frame()->height() - expected_height_;
+    if (count > 0) {
+      cgen()->frame()->Drop(count);
+    }
+  }
+  DoBind();
+}
+
 } }  // namespace v8::internal
diff --git a/src/jump-target-light.h b/src/jump-target-light.h
new file mode 100644
index 0000000..656ec75
--- /dev/null
+++ b/src/jump-target-light.h
@@ -0,0 +1,187 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_JUMP_TARGET_LIGHT_H_
+#define V8_JUMP_TARGET_LIGHT_H_
+
+#include "macro-assembler.h"
+#include "zone-inl.h"
+#include "virtual-frame.h"
+
+namespace v8 {
+namespace internal {
+
+// Forward declarations.
+class FrameElement;
+class Result;
+
+// -------------------------------------------------------------------------
+// Jump targets
+//
+// A jump target is an abstraction of a basic-block entry in generated
+// code.  It collects all the virtual frames reaching the block by
+// forward jumps and pairs them with labels for the merge code along
+// all forward-reaching paths.  When bound, an expected frame for the
+// block is determined and code is generated to merge to the expected
+// frame.  For backward jumps, the merge code is generated at the edge
+// leaving the predecessor block.
+//
+// A jump target must have been reached via control flow (either by
+// jumping, branching, or falling through) at the time it is bound.
+// In particular, this means that at least one of the control-flow
+// graph edges reaching the target must be a forward edge.
+
+class JumpTarget : public ZoneObject {  // Shadows are dynamically allocated.
+ public:
+  // Forward-only jump targets can only be reached by forward CFG edges.
+  enum Directionality { FORWARD_ONLY, BIDIRECTIONAL };
+
+  // Construct a jump target.
+  explicit inline JumpTarget(Directionality direction);
+
+  inline JumpTarget();
+
+  virtual ~JumpTarget() {}
+
+  void Unuse() {
+    entry_frame_set_ = false;
+    entry_label_.Unuse();
+  }
+
+  inline CodeGenerator* cgen();
+
+  const VirtualFrame* entry_frame() const {
+    return entry_frame_set_ ? &entry_frame_ : NULL;
+  }
+
+  void set_entry_frame(VirtualFrame* frame) {
+    entry_frame_ = *frame;
+    entry_frame_set_ = true;
+  }
+
+  // Predicates testing the state of the encapsulated label.
+  bool is_bound() const { return entry_label_.is_bound(); }
+  bool is_linked() const { return entry_label_.is_linked(); }
+  bool is_unused() const { return entry_label_.is_unused(); }
+
+  // Copy the state of this jump target to the destination.
+  inline void CopyTo(JumpTarget* destination) {
+    *destination = *this;
+  }
+
+  // Emit a jump to the target.  There must be a current frame at the
+  // jump and there will be no current frame after the jump.
+  virtual void Jump();
+
+  // Emit a conditional branch to the target.  There must be a current
+  // frame at the branch.  The current frame will fall through to the
+  // code after the branch.  The arg is a result that is live both at
+  // the target and the fall-through.
+  virtual void Branch(Condition cc, Hint hint = no_hint);
+
+  // Bind a jump target.  If there is no current frame at the binding
+  // site, there must be at least one frame reaching via a forward
+  // jump.
+  virtual void Bind();
+
+  // Emit a call to a jump target.  There must be a current frame at
+  // the call.  The frame at the target is the same as the current
+  // frame except for an extra return address on top of it.  The frame
+  // after the call is the same as the frame before the call.
+  void Call();
+
+ protected:
+  // Has an entry frame been found?
+  bool entry_frame_set_;
+
+  // The frame used on entry to the block and expected at backward
+  // jumps to the block.  Set the first time something branches to this
+  // jump target.
+  VirtualFrame entry_frame_;
+
+  // The actual entry label of the block.
+  Label entry_label_;
+
+  // Implementations of Jump, Branch, and Bind with all arguments and
+  // return values using the virtual frame.
+  void DoJump();
+  void DoBranch(Condition cc, Hint hint);
+  void DoBind();
+};
+
+
+// -------------------------------------------------------------------------
+// Break targets
+//
+// A break target is a jump target that can be used to break out of a
+// statement that keeps extra state on the stack (eg, for/in or
+// try/finally).  They know the expected stack height at the target
+// and will drop state from nested statements as part of merging.
+//
+// Break targets are used for return, break, and continue targets.
+
+class BreakTarget : public JumpTarget {
+ public:
+  // Construct a break target.
+  inline BreakTarget();
+
+  virtual ~BreakTarget() {}
+
+  // Copy the state of this jump target to the destination.
+  inline void CopyTo(BreakTarget* destination) {
+    *destination = *this;
+  }
+
+  // Emit a jump to the target.  There must be a current frame at the
+  // jump and there will be no current frame after the jump.
+  virtual void Jump();
+
+  // Emit a conditional branch to the target.  There must be a current
+  // frame at the branch.  The current frame will fall through to the
+  // code after the branch.
+  virtual void Branch(Condition cc, Hint hint = no_hint);
+
+  // Bind a break target.  If there is no current frame at the binding
+  // site, there must be at least one frame reaching via a forward
+  // jump.
+  virtual void Bind();
+
+  // Setter for expected height.
+  void set_expected_height(int expected) { expected_height_ = expected; }
+
+  // Uses the current frame to set the expected height.
+  void SetExpectedHeight();
+
+ private:
+  // The expected height of the expression stack where the target will
+  // be bound, statically known at initialization time.
+  int expected_height_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_JUMP_TARGET_LIGHT_H_
diff --git a/src/jump-target.cc b/src/jump-target.cc
index 8b29995..72aada8 100644
--- a/src/jump-target.cc
+++ b/src/jump-target.cc
@@ -37,17 +37,6 @@
 // -------------------------------------------------------------------------
 // JumpTarget implementation.
 
-bool JumpTarget::compiling_deferred_code_ = false;
-
-
-void JumpTarget::Unuse() {
-  reaching_frames_.Clear();
-  merge_labels_.Clear();
-  entry_frame_ = NULL;
-  entry_label_.Unuse();
-}
-
-
 void JumpTarget::Jump() {
   DoJump();
 }
@@ -63,58 +52,6 @@
 }
 
 
-void JumpTarget::AddReachingFrame(VirtualFrame* frame) {
-  ASSERT(reaching_frames_.length() == merge_labels_.length());
-  ASSERT(entry_frame_ == NULL);
-  Label fresh;
-  merge_labels_.Add(fresh);
-  reaching_frames_.Add(frame);
-}
-
-
-// -------------------------------------------------------------------------
-// BreakTarget implementation.
-
-void BreakTarget::set_direction(Directionality direction) {
-  JumpTarget::set_direction(direction);
-  ASSERT(cgen()->has_valid_frame());
-  expected_height_ = cgen()->frame()->height();
-}
-
-
-void BreakTarget::CopyTo(BreakTarget* destination) {
-  ASSERT(destination != NULL);
-  destination->direction_ = direction_;
-  destination->reaching_frames_.Rewind(0);
-  destination->reaching_frames_.AddAll(reaching_frames_);
-  destination->merge_labels_.Rewind(0);
-  destination->merge_labels_.AddAll(merge_labels_);
-  destination->entry_frame_ = entry_frame_;
-  destination->entry_label_ = entry_label_;
-  destination->expected_height_ = expected_height_;
-}
-
-
-void BreakTarget::Branch(Condition cc, Hint hint) {
-  ASSERT(cgen()->has_valid_frame());
-
-  int count = cgen()->frame()->height() - expected_height_;
-  if (count > 0) {
-    // We negate and branch here rather than using DoBranch's negate
-    // and branch.  This gives us a hook to remove statement state
-    // from the frame.
-    JumpTarget fall_through;
-    // Branch to fall through will not negate, because it is a
-    // forward-only target.
-    fall_through.Branch(NegateCondition(cc), NegateHint(hint));
-    Jump();  // May emit merge code here.
-    fall_through.Bind();
-  } else {
-    DoBranch(cc, hint);
-  }
-}
-
-
 // -------------------------------------------------------------------------
 // ShadowTarget implementation.
 
@@ -151,5 +88,4 @@
 #endif
 }
 
-
 } }  // namespace v8::internal
diff --git a/src/jump-target.h b/src/jump-target.h
index db523b5..a0d2686 100644
--- a/src/jump-target.h
+++ b/src/jump-target.h
@@ -28,216 +28,21 @@
 #ifndef V8_JUMP_TARGET_H_
 #define V8_JUMP_TARGET_H_
 
-#include "macro-assembler.h"
-#include "zone-inl.h"
+#if V8_TARGET_ARCH_IA32
+#include "jump-target-heavy.h"
+#elif V8_TARGET_ARCH_X64
+#include "jump-target-heavy.h"
+#elif V8_TARGET_ARCH_ARM
+#include "jump-target-light.h"
+#elif V8_TARGET_ARCH_MIPS
+#include "jump-target-light.h"
+#else
+#error Unsupported target architecture.
+#endif
 
 namespace v8 {
 namespace internal {
 
-// Forward declarations.
-class FrameElement;
-class Result;
-class VirtualFrame;
-
-// -------------------------------------------------------------------------
-// Jump targets
-//
-// A jump target is an abstraction of a basic-block entry in generated
-// code.  It collects all the virtual frames reaching the block by
-// forward jumps and pairs them with labels for the merge code along
-// all forward-reaching paths.  When bound, an expected frame for the
-// block is determined and code is generated to merge to the expected
-// frame.  For backward jumps, the merge code is generated at the edge
-// leaving the predecessor block.
-//
-// A jump target must have been reached via control flow (either by
-// jumping, branching, or falling through) at the time it is bound.
-// In particular, this means that at least one of the control-flow
-// graph edges reaching the target must be a forward edge.
-
-class JumpTarget : public ZoneObject {  // Shadows are dynamically allocated.
- public:
-  // Forward-only jump targets can only be reached by forward CFG edges.
-  enum Directionality { FORWARD_ONLY, BIDIRECTIONAL };
-
-  // Construct a jump target used to generate code and to provide
-  // access to a current frame.
-  explicit JumpTarget(Directionality direction)
-      : direction_(direction),
-        reaching_frames_(0),
-        merge_labels_(0),
-        entry_frame_(NULL) {
-  }
-
-  // Construct a jump target.
-  JumpTarget()
-      : direction_(FORWARD_ONLY),
-        reaching_frames_(0),
-        merge_labels_(0),
-        entry_frame_(NULL) {
-  }
-
-  virtual ~JumpTarget() {}
-
-  // Set the direction of the jump target.
-  virtual void set_direction(Directionality direction) {
-    direction_ = direction;
-  }
-
-  // Treat the jump target as a fresh one.  The state is reset.
-  void Unuse();
-
-  inline CodeGenerator* cgen();
-
-  Label* entry_label() { return &entry_label_; }
-
-  VirtualFrame* entry_frame() const { return entry_frame_; }
-  void set_entry_frame(VirtualFrame* frame) {
-    entry_frame_ = frame;
-  }
-
-  // Predicates testing the state of the encapsulated label.
-  bool is_bound() const { return entry_label_.is_bound(); }
-  bool is_linked() const {
-    return !is_bound() && !reaching_frames_.is_empty();
-  }
-  bool is_unused() const {
-    // This is !is_bound() && !is_linked().
-    return !is_bound() && reaching_frames_.is_empty();
-  }
-
-  // Emit a jump to the target.  There must be a current frame at the
-  // jump and there will be no current frame after the jump.
-  virtual void Jump();
-  virtual void Jump(Result* arg);
-
-  // Emit a conditional branch to the target.  There must be a current
-  // frame at the branch.  The current frame will fall through to the
-  // code after the branch.  The arg is a result that is live both at
-  // the target and the fall-through.
-  virtual void Branch(Condition cc, Hint hint = no_hint);
-  virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
-  virtual void Branch(Condition cc,
-                      Result* arg0,
-                      Result* arg1,
-                      Hint hint = no_hint);
-
-  // Bind a jump target.  If there is no current frame at the binding
-  // site, there must be at least one frame reaching via a forward
-  // jump.
-  virtual void Bind();
-  virtual void Bind(Result* arg);
-  virtual void Bind(Result* arg0, Result* arg1);
-
-  // Emit a call to a jump target.  There must be a current frame at
-  // the call.  The frame at the target is the same as the current
-  // frame except for an extra return address on top of it.  The frame
-  // after the call is the same as the frame before the call.
-  void Call();
-
-  static void set_compiling_deferred_code(bool flag) {
-    compiling_deferred_code_ = flag;
-  }
-
- protected:
-  // Directionality flag set at initialization time.
-  Directionality direction_;
-
-  // A list of frames reaching this block via forward jumps.
-  ZoneList<VirtualFrame*> reaching_frames_;
-
-  // A parallel list of labels for merge code.
-  ZoneList<Label> merge_labels_;
-
-  // The frame used on entry to the block and expected at backward
-  // jumps to the block.  Set when the jump target is bound, but may
-  // or may not be set for forward-only blocks.
-  VirtualFrame* entry_frame_;
-
-  // The actual entry label of the block.
-  Label entry_label_;
-
-  // Implementations of Jump, Branch, and Bind with all arguments and
-  // return values using the virtual frame.
-  void DoJump();
-  void DoBranch(Condition cc, Hint hint);
-  void DoBind();
-
- private:
-  static bool compiling_deferred_code_;
-
-  // Add a virtual frame reaching this labeled block via a forward jump,
-  // and a corresponding merge code label.
-  void AddReachingFrame(VirtualFrame* frame);
-
-  // Perform initialization required during entry frame computation
-  // after setting the virtual frame element at index in frame to be
-  // target.
-  inline void InitializeEntryElement(int index, FrameElement* target);
-
-  // Compute a frame to use for entry to this block.
-  void ComputeEntryFrame();
-
-  DISALLOW_COPY_AND_ASSIGN(JumpTarget);
-};
-
-
-// -------------------------------------------------------------------------
-// Break targets
-//
-// A break target is a jump target that can be used to break out of a
-// statement that keeps extra state on the stack (eg, for/in or
-// try/finally).  They know the expected stack height at the target
-// and will drop state from nested statements as part of merging.
-//
-// Break targets are used for return, break, and continue targets.
-
-class BreakTarget : public JumpTarget {
- public:
-  // Construct a break target.
-  BreakTarget() {}
-
-  virtual ~BreakTarget() {}
-
-  // Set the direction of the break target.
-  virtual void set_direction(Directionality direction);
-
-  // Copy the state of this break target to the destination.  The
-  // lists of forward-reaching frames and merge-point labels are
-  // copied.  All virtual frame pointers are copied, not the
-  // pointed-to frames.  The previous state of the destination is
-  // overwritten, without deallocating pointed-to virtual frames.
-  void CopyTo(BreakTarget* destination);
-
-  // Emit a jump to the target.  There must be a current frame at the
-  // jump and there will be no current frame after the jump.
-  virtual void Jump();
-  virtual void Jump(Result* arg);
-
-  // Emit a conditional branch to the target.  There must be a current
-  // frame at the branch.  The current frame will fall through to the
-  // code after the branch.
-  virtual void Branch(Condition cc, Hint hint = no_hint);
-  virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
-
-  // Bind a break target.  If there is no current frame at the binding
-  // site, there must be at least one frame reaching via a forward
-  // jump.
-  virtual void Bind();
-  virtual void Bind(Result* arg);
-
-  // Setter for expected height.
-  void set_expected_height(int expected) { expected_height_ = expected; }
-
- private:
-  // The expected height of the expression stack where the target will
-  // be bound, statically known at initialization time.
-  int expected_height_;
-
-  DISALLOW_COPY_AND_ASSIGN(BreakTarget);
-};
-
-
 // -------------------------------------------------------------------------
 // Shadow break targets
 //
@@ -280,7 +85,6 @@
   DISALLOW_COPY_AND_ASSIGN(ShadowTarget);
 };
 
-
 } }  // namespace v8::internal
 
 #endif  // V8_JUMP_TARGET_H_
diff --git a/src/log.cc b/src/log.cc
index e1ebc87..891b0e2 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -1313,9 +1313,8 @@
 void Logger::LogCompiledFunctions() {
   HandleScope scope;
   const int compiled_funcs_count = EnumerateCompiledFunctions(NULL);
-  Handle<SharedFunctionInfo>* sfis =
-      NewArray< Handle<SharedFunctionInfo> >(compiled_funcs_count);
-  EnumerateCompiledFunctions(sfis);
+  ScopedVector< Handle<SharedFunctionInfo> > sfis(compiled_funcs_count);
+  EnumerateCompiledFunctions(sfis.start());
 
   // During iteration, there can be heap allocation due to
   // GetScriptLineNumber call.
@@ -1360,8 +1359,6 @@
           Logger::LAZY_COMPILE_TAG, shared->code(), *func_name));
     }
   }
-
-  DeleteArray(sfis);
 }
 
 
diff --git a/src/macro-assembler.h b/src/macro-assembler.h
index 81e5bf7..a21e960 100644
--- a/src/macro-assembler.h
+++ b/src/macro-assembler.h
@@ -50,17 +50,6 @@
 };
 
 
-// Flags used for the AllocateInNewSpace functions.
-enum AllocationFlags {
-  // No special flags.
-  NO_ALLOCATION_FLAGS = 0,
-  // Return the pointer to the allocated already tagged as a heap object.
-  TAG_OBJECT = 1 << 0,
-  // The content of the result register already contains the allocation top in
-  // new space.
-  RESULT_CONTAINS_TOP = 1 << 1
-};
-
 // Invalid depth in prototype chain.
 const int kInvalidProtoDepth = -1;
 
diff --git a/src/macros.py b/src/macros.py
index d6ba2ca..1533741 100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -112,6 +112,11 @@
 macro IS_UNDETECTABLE(arg)      = (%_IsUndetectableObject(arg));
 macro FLOOR(arg)                = $floor(arg);
 
+# Macro for ECMAScript 5 queries of the type:
+# "Type(O) is object."
+# This is the same as being either a function or an object in V8 terminology.
+macro IS_SPEC_OBJECT_OR_NULL(arg) = (%_IsObject(arg) || %_IsFunction(arg));
+
 # Inline macros. Use %IS_VAR to make sure arg is evaluated only once.
 macro NUMBER_IS_NAN(arg) = (!%_IsSmi(%IS_VAR(arg)) && !(arg == arg));
 macro TO_INTEGER(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : ToInteger(arg));
diff --git a/src/messages.js b/src/messages.js
index de6a362..a46af4a 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -42,6 +42,9 @@
 var kVowelSounds = 0;
 var kCapitalVowelSounds = 0;
 
+// Matches Messages::kNoLineNumberInfo from v8.h
+var kNoLineNumberInfo = 0;
+
 // If this object gets passed to an error constructor the error will
 // get an accessor for .message that constructs a descriptive error
 // message on access.
@@ -203,9 +206,9 @@
 
 
 function GetLineNumber(message) {
-  if (message.startPos == -1) return -1;
+  if (message.startPos == -1) return kNoLineNumberInfo;
   var location = message.script.locationFromPosition(message.startPos, true);
-  if (location == null) return -1;
+  if (location == null) return kNoLineNumberInfo;
   return location.line + 1;
 }
 
diff --git a/src/objects-inl.h b/src/objects-inl.h
index ae7d2c2..ad15104 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -2530,7 +2530,13 @@
 
 
 bool SharedFunctionInfo::HasCustomCallGenerator() {
-  return function_data()->IsProxy();
+  return function_data()->IsSmi();
+}
+
+
+int SharedFunctionInfo::custom_call_generator_id() {
+  ASSERT(HasCustomCallGenerator());
+  return Smi::cast(function_data())->value();
 }
 
 
diff --git a/src/objects.cc b/src/objects.cc
index 459c8aa..c8acb47 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -682,11 +682,11 @@
   if (FLAG_enable_slow_asserts) {
     // Assert that the resource and the string are equivalent.
     ASSERT(static_cast<size_t>(this->length()) == resource->length());
-    SmartPointer<uc16> smart_chars(NewArray<uc16>(this->length()));
-    String::WriteToFlat(this, *smart_chars, 0, this->length());
-    ASSERT(memcmp(*smart_chars,
+    ScopedVector<uc16> smart_chars(this->length());
+    String::WriteToFlat(this, smart_chars.start(), 0, this->length());
+    ASSERT(memcmp(smart_chars.start(),
                   resource->data(),
-                  resource->length() * sizeof(**smart_chars)) == 0);
+                  resource->length() * sizeof(smart_chars[0])) == 0);
   }
 #endif  // DEBUG
 
@@ -728,11 +728,11 @@
   if (FLAG_enable_slow_asserts) {
     // Assert that the resource and the string are equivalent.
     ASSERT(static_cast<size_t>(this->length()) == resource->length());
-    SmartPointer<char> smart_chars(NewArray<char>(this->length()));
-    String::WriteToFlat(this, *smart_chars, 0, this->length());
-    ASSERT(memcmp(*smart_chars,
+    ScopedVector<char> smart_chars(this->length());
+    String::WriteToFlat(this, smart_chars.start(), 0, this->length());
+    ASSERT(memcmp(smart_chars.start(),
                   resource->data(),
-                  resource->length()*sizeof(**smart_chars)) == 0);
+                  resource->length() * sizeof(smart_chars[0])) == 0);
   }
 #endif  // DEBUG
 
@@ -4900,6 +4900,7 @@
     // prototype is put into the initial map where it belongs.
     set_prototype_or_initial_map(value);
   }
+  Heap::ClearInstanceofCache();
   return value;
 }
 
@@ -5601,6 +5602,8 @@
   Map::cast(new_map)->set_prototype(value);
   real_receiver->set_map(Map::cast(new_map));
 
+  Heap::ClearInstanceofCache();
+
   return value;
 }
 
diff --git a/src/objects.h b/src/objects.h
index dcfb2ee..8b114a6 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -2328,6 +2328,10 @@
 
   static const int kEntrySize = 2;  // key + value
 
+  static const int kFactoryOffset = kHeaderSize;
+  static const int kFingerOffset = kFactoryOffset + kPointerSize;
+  static const int kCacheSizeOffset = kFingerOffset + kPointerSize;
+
   inline void MakeZeroSize();
   inline void Clear();
 
@@ -3200,7 +3204,7 @@
 
   // [function data]: This field holds some additional data for function.
   // Currently it either has FunctionTemplateInfo to make benefit the API
-  // or Proxy wrapping CustomCallGenerator.
+  // or Smi identifying a custom call generator.
   // In the long run we don't want all functions to have this field but
   // we can fix that when we have a better model for storing hidden data
   // on objects.
@@ -3209,6 +3213,7 @@
   inline bool IsApiFunction();
   inline FunctionTemplateInfo* get_api_func_data();
   inline bool HasCustomCallGenerator();
+  inline int custom_call_generator_id();
 
   // [script info]: Script from which the function originates.
   DECL_ACCESSORS(script, Object)
diff --git a/src/parser.cc b/src/parser.cc
index 089eeee..c482fdf 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -33,12 +33,15 @@
 #include "codegen.h"
 #include "compiler.h"
 #include "messages.h"
+#include "parser.h"
 #include "platform.h"
 #include "runtime.h"
-#include "parser.h"
 #include "scopes.h"
 #include "string-stream.h"
 
+#include "ast-inl.h"
+#include "jump-target-inl.h"
+
 namespace v8 {
 namespace internal {
 
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 67e52ce..b1075cf 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -286,14 +286,12 @@
 
 int OS::StackWalk(Vector<OS::StackFrame> frames) {
   int frames_size = frames.length();
-  void** addresses = NewArray<void*>(frames_size);
+  ScopedVector<void*> addresses(frames_size);
 
-  int frames_count = backtrace(addresses, frames_size);
+  int frames_count = backtrace(addresses.start(), frames_size);
 
-  char** symbols;
-  symbols = backtrace_symbols(addresses, frames_count);
+  char** symbols = backtrace_symbols(addresses, frames_count);
   if (symbols == NULL) {
-    DeleteArray(addresses);
     return kStackWalkError;
   }
 
@@ -308,7 +306,6 @@
     frames[i].text[kStackWalkMaxTextLen - 1] = '\0';
   }
 
-  DeleteArray(addresses);
   free(symbols);
 
   return frames_count;
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index b28597d..fca218f 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -376,14 +376,12 @@
   // backtrace is a glibc extension.
 #ifdef __GLIBC__
   int frames_size = frames.length();
-  void** addresses = NewArray<void*>(frames_size);
+  ScopedVector<void*> addresses(frames_size);
 
-  int frames_count = backtrace(addresses, frames_size);
+  int frames_count = backtrace(addresses.start(), frames_size);
 
-  char** symbols;
-  symbols = backtrace_symbols(addresses, frames_count);
+  char** symbols = backtrace_symbols(addresses.start(), frames_count);
   if (symbols == NULL) {
-    DeleteArray(addresses);
     return kStackWalkError;
   }
 
@@ -398,7 +396,6 @@
     frames[i].text[kStackWalkMaxTextLen - 1] = '\0';
   }
 
-  DeleteArray(addresses);
   free(symbols);
 
   return frames_count;
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index 5516909..23747c3 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -283,13 +283,12 @@
     return 0;
 
   int frames_size = frames.length();
-  void** addresses = NewArray<void*>(frames_size);
-  int frames_count = backtrace(addresses, frames_size);
+  ScopedVector<void*> addresses(frames_size);
 
-  char** symbols;
-  symbols = backtrace_symbols(addresses, frames_count);
+  int frames_count = backtrace(addresses.start(), frames_size);
+
+  char** symbols = backtrace_symbols(addresses.start(), frames_count);
   if (symbols == NULL) {
-    DeleteArray(addresses);
     return kStackWalkError;
   }
 
@@ -305,7 +304,6 @@
     frames[i].text[kStackWalkMaxTextLen - 1] = '\0';
   }
 
-  DeleteArray(addresses);
   free(symbols);
 
   return frames_count;
diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc
index 1fa652d..0d9547b 100644
--- a/src/platform-solaris.cc
+++ b/src/platform-solaris.cc
@@ -233,14 +233,12 @@
 
 int OS::StackWalk(Vector<OS::StackFrame> frames) {
   int frames_size = frames.length();
-  void** addresses = NewArray<void*>(frames_size);
+  ScopedVector<void*> addresses(frames_size);
 
-  int frames_count = backtrace(addresses, frames_size);
+  int frames_count = backtrace(addresses.start(), frames_size);
 
-  char** symbols;
-  symbols = backtrace_symbols(addresses, frames_count);
+  char** symbols = backtrace_symbols(addresses.start(), frames_count);
   if (symbols == NULL) {
-    DeleteArray(addresses);
     return kStackWalkError;
   }
 
@@ -255,7 +253,6 @@
     frames[i].text[kStackWalkMaxTextLen - 1] = '\0';
   }
 
-  DeleteArray(addresses);
   free(symbols);
 
   return frames_count;
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index d03a0a9..bee5173 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -1249,16 +1249,16 @@
 
     // Try to locate a symbol for this frame.
     DWORD64 symbol_displacement;
-    IMAGEHLP_SYMBOL64* symbol = NULL;
-    symbol = NewArray<IMAGEHLP_SYMBOL64>(kStackWalkMaxNameLen);
-    if (!symbol) return kStackWalkError;  // Out of memory.
-    memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + kStackWalkMaxNameLen);
-    symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
-    symbol->MaxNameLength = kStackWalkMaxNameLen;
+    SmartPointer<IMAGEHLP_SYMBOL64> symbol(
+        NewArray<IMAGEHLP_SYMBOL64>(kStackWalkMaxNameLen));
+    if (symbol.is_empty()) return kStackWalkError;  // Out of memory.
+    memset(*symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + kStackWalkMaxNameLen);
+    (*symbol)->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+    (*symbol)->MaxNameLength = kStackWalkMaxNameLen;
     ok = _SymGetSymFromAddr64(process_handle,             // hProcess
                               stack_frame.AddrPC.Offset,  // Address
                               &symbol_displacement,       // Displacement
-                              symbol);                    // Symbol
+                              *symbol);                   // Symbol
     if (ok) {
       // Try to locate more source information for the symbol.
       IMAGEHLP_LINE64 Line;
@@ -1276,13 +1276,13 @@
         SNPrintF(MutableCStrVector(frames[frames_count].text,
                                    kStackWalkMaxTextLen),
                  "%s %s:%d:%d",
-                 symbol->Name, Line.FileName, Line.LineNumber,
+                 (*symbol)->Name, Line.FileName, Line.LineNumber,
                  line_displacement);
       } else {
         SNPrintF(MutableCStrVector(frames[frames_count].text,
                                    kStackWalkMaxTextLen),
                  "%s",
-                 symbol->Name);
+                 (*symbol)->Name);
       }
       // Make sure line termination is in place.
       frames[frames_count].text[kStackWalkMaxTextLen - 1] = '\0';
@@ -1294,11 +1294,9 @@
       // module will never be found).
       int err = GetLastError();
       if (err != ERROR_MOD_NOT_FOUND) {
-        DeleteArray(symbol);
         break;
       }
     }
-    DeleteArray(symbol);
 
     frames_count++;
   }
diff --git a/src/platform.h b/src/platform.h
index 82e2e3c..7156441 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -44,12 +44,6 @@
 #ifndef V8_PLATFORM_H_
 #define V8_PLATFORM_H_
 
-#ifdef __sun
-// On Solaris, to get isinf, INFINITY, fpclassify and other macros one needs
-// to define this symbol
-#define __C99FEATURES__ 1
-#endif
-
 #define V8_INFINITY INFINITY
 
 // Windows specific stuff.
diff --git a/src/register-allocator.cc b/src/register-allocator.cc
index b9989a5..31d0a49 100644
--- a/src/register-allocator.cc
+++ b/src/register-allocator.cc
@@ -84,15 +84,16 @@
 
 Result RegisterAllocator::Allocate(Register target) {
   // If the target is not referenced, it can simply be allocated.
-  if (!is_used(target)) {
+  if (!is_used(RegisterAllocator::ToNumber(target))) {
     return Result(target);
   }
   // If the target is only referenced in the frame, it can be spilled and
   // then allocated.
   ASSERT(cgen_->has_valid_frame());
-  if (cgen_->frame()->is_used(target) && count(target) == 1)  {
+  if (cgen_->frame()->is_used(RegisterAllocator::ToNumber(target)) &&
+      count(target) == 1)  {
     cgen_->frame()->Spill(target);
-    ASSERT(!is_used(target));
+    ASSERT(!is_used(RegisterAllocator::ToNumber(target)));
     return Result(target);
   }
   // Otherwise (if it's referenced outside the frame) we cannot allocate it.
diff --git a/src/runtime.cc b/src/runtime.cc
index 823889a..b421ac7 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -1325,18 +1325,9 @@
 }
 
 
-static void SetCustomCallGenerator(Handle<JSFunction> function,
-                                   ExternalReference* generator) {
-  if (function->shared()->function_data()->IsUndefined()) {
-    function->shared()->set_function_data(*FromCData(generator->address()));
-  }
-}
-
-
 static Handle<JSFunction> InstallBuiltin(Handle<JSObject> holder,
                                          const char* name,
-                                         Builtins::Name builtin_name,
-                                         ExternalReference* generator = NULL) {
+                                         Builtins::Name builtin_name) {
   Handle<String> key = Factory::LookupAsciiSymbol(name);
   Handle<Code> code(Builtins::builtin(builtin_name));
   Handle<JSFunction> optimized = Factory::NewFunction(key,
@@ -1345,44 +1336,18 @@
                                                       code,
                                                       false);
   optimized->shared()->DontAdaptArguments();
-  if (generator != NULL) {
-    SetCustomCallGenerator(optimized, generator);
-  }
   SetProperty(holder, key, optimized, NONE);
   return optimized;
 }
 
 
-Object* CompileArrayPushCall(CallStubCompiler* compiler,
-                             Object* object,
-                             JSObject* holder,
-                             JSFunction* function,
-                             String* name,
-                             StubCompiler::CheckType check) {
-  return compiler->CompileArrayPushCall(object, holder, function, name, check);
-}
-
-
-Object* CompileArrayPopCall(CallStubCompiler* compiler,
-                            Object* object,
-                            JSObject* holder,
-                            JSFunction* function,
-                            String* name,
-                            StubCompiler::CheckType check) {
-  return compiler->CompileArrayPopCall(object, holder, function, name, check);
-}
-
-
 static Object* Runtime_SpecialArrayFunctions(Arguments args) {
   HandleScope scope;
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(JSObject, holder, 0);
 
-  ExternalReference pop = ExternalReference::compile_array_pop_call();
-  ExternalReference push = ExternalReference::compile_array_push_call();
-
-  InstallBuiltin(holder, "pop", Builtins::ArrayPop, &pop);
-  InstallBuiltin(holder, "push", Builtins::ArrayPush, &push);
+  InstallBuiltin(holder, "pop", Builtins::ArrayPop);
+  InstallBuiltin(holder, "push", Builtins::ArrayPush);
   InstallBuiltin(holder, "shift", Builtins::ArrayShift);
   InstallBuiltin(holder, "unshift", Builtins::ArrayUnshift);
   InstallBuiltin(holder, "slice", Builtins::ArraySlice);
diff --git a/src/runtime.js b/src/runtime.js
index be93c4f..8e3883f 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -80,10 +80,7 @@
     } else {
       // x is not a number, boolean, null or undefined.
       if (y == null) return 1;  // not equal
-      if (IS_OBJECT(y)) {
-        return %_ObjectEquals(x, y) ? 0 : 1;
-      }
-      if (IS_FUNCTION(y)) {
+      if (IS_SPEC_OBJECT_OR_NULL(y)) {
         return %_ObjectEquals(x, y) ? 0 : 1;
       }
 
@@ -344,7 +341,7 @@
 
 // ECMA-262, section 11.8.7, page 54.
 function IN(x) {
-  if (x == null || (!IS_OBJECT(x) && !IS_FUNCTION(x))) {
+  if (x == null || !IS_SPEC_OBJECT_OR_NULL(x)) {
     throw %MakeTypeError('invalid_in_operator_use', [this, x]);
   }
   return %_IsNonNegativeSmi(this) ? %HasElement(x, this) : %HasProperty(x, %ToString(this));
@@ -362,13 +359,13 @@
   }
 
   // If V is not an object, return false.
-  if (IS_NULL(V) || (!IS_OBJECT(V) && !IS_FUNCTION(V))) {
+  if (IS_NULL(V) || !IS_SPEC_OBJECT_OR_NULL(V)) {
     return 1;
   }
 
   // Get the prototype of F; if it is not an object, throw an error.
   var O = F.prototype;
-  if (IS_NULL(O) || (!IS_OBJECT(O) && !IS_FUNCTION(O))) {
+  if (IS_NULL(O) || !IS_SPEC_OBJECT_OR_NULL(O)) {
     throw %MakeTypeError('instanceof_nonobject_proto', [O]);
   }
 
@@ -482,7 +479,7 @@
   // Fast case check.
   if (IS_STRING(x)) return x;
   // Normal behavior.
-  if (!IS_OBJECT(x) && !IS_FUNCTION(x)) return x;
+  if (!IS_SPEC_OBJECT_OR_NULL(x)) return x;
   if (x == null) return x;  // check for null, undefined
   if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
   return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x);
@@ -587,7 +584,7 @@
 // Returns if the given x is a primitive value - not an object or a
 // function.
 function IsPrimitive(x) {
-  if (!IS_OBJECT(x) && !IS_FUNCTION(x)) {
+  if (!IS_SPEC_OBJECT_OR_NULL(x)) {
     return true;
   } else {
     // Even though the type of null is "object", null is still
diff --git a/src/serialize.cc b/src/serialize.cc
index 6841267..dcaa101 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -414,44 +414,36 @@
       UNCLASSIFIED,
       19,
       "compare_doubles");
-  Add(ExternalReference::compile_array_pop_call().address(),
-      UNCLASSIFIED,
-      20,
-      "compile_array_pop");
-  Add(ExternalReference::compile_array_push_call().address(),
-      UNCLASSIFIED,
-      21,
-      "compile_array_push");
 #ifndef V8_INTERPRETED_REGEXP
   Add(ExternalReference::re_case_insensitive_compare_uc16().address(),
       UNCLASSIFIED,
-      22,
+      20,
       "NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()");
   Add(ExternalReference::re_check_stack_guard_state().address(),
       UNCLASSIFIED,
-      23,
+      21,
       "RegExpMacroAssembler*::CheckStackGuardState()");
   Add(ExternalReference::re_grow_stack().address(),
       UNCLASSIFIED,
-      24,
+      22,
       "NativeRegExpMacroAssembler::GrowStack()");
   Add(ExternalReference::re_word_character_map().address(),
       UNCLASSIFIED,
-      25,
+      23,
       "NativeRegExpMacroAssembler::word_character_map");
 #endif  // V8_INTERPRETED_REGEXP
   // Keyed lookup cache.
   Add(ExternalReference::keyed_lookup_cache_keys().address(),
       UNCLASSIFIED,
-      26,
+      24,
       "KeyedLookupCache::keys()");
   Add(ExternalReference::keyed_lookup_cache_field_offsets().address(),
       UNCLASSIFIED,
-      27,
+      25,
       "KeyedLookupCache::field_offsets()");
   Add(ExternalReference::transcendental_cache_array_address().address(),
       UNCLASSIFIED,
-      28,
+      26,
       "TranscendentalCache::caches()");
 }
 
diff --git a/src/string.js b/src/string.js
index 9433249..59a501f 100644
--- a/src/string.js
+++ b/src/string.js
@@ -241,7 +241,13 @@
     %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]);
     if (IS_FUNCTION(replace)) {
       regExpCache.type = 'none';
-      return StringReplaceRegExpWithFunction(subject, search, replace);
+      if (search.global) {
+        return StringReplaceGlobalRegExpWithFunction(subject, search, replace);
+      } else {
+        return StringReplaceNonGlobalRegExpWithFunction(subject,
+                                                        search,
+                                                        replace);
+      }
     } else {
       return StringReplaceRegExp(subject, search, replace);
     }
@@ -396,9 +402,9 @@
   var scaled = index << 1;
   // Compute start and end.
   var start = lastCaptureInfo[CAPTURE(scaled)];
+  // If start isn't valid, return undefined.
+  if (start < 0) return;
   var end = lastCaptureInfo[CAPTURE(scaled + 1)];
-  // If either start or end is missing return undefined.
-  if (start < 0 || end < 0) return;
   return SubString(string, start, end);
 };
 
@@ -410,9 +416,8 @@
   var scaled = index << 1;
   // Compute start and end.
   var start = matchInfo[CAPTURE(scaled)];
+  if (start < 0) return;
   var end = matchInfo[CAPTURE(scaled + 1)];
-  // If either start or end is missing return.
-  if (start < 0 || end <= start) return;
   builder.addSpecialSlice(start, end);
 };
 
@@ -423,112 +428,116 @@
 
 // Helper function for replacing regular expressions with the result of a
 // function application in String.prototype.replace.
-function StringReplaceRegExpWithFunction(subject, regexp, replace) {
-  if (regexp.global) {
-    var resultArray = reusableReplaceArray;
-    if (resultArray) {
-      reusableReplaceArray = null;
-    } else {
-      // Inside a nested replace (replace called from the replacement function
-      // of another replace) or we have failed to set the reusable array
-      // back due to an exception in a replacement function. Create a new
-      // array to use in the future, or until the original is written back.
-      resultArray = $Array(16);
-    }
-
-    var res = %RegExpExecMultiple(regexp,
-                                  subject,
-                                  lastMatchInfo,
-                                  resultArray);
-    regexp.lastIndex = 0;
-    if (IS_NULL(res)) {
-      // No matches at all.
-      return subject;
-    }
-    var len = res.length;
-    var i = 0;
-    if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) {
-      var match_start = 0;
-      var override = [null, 0, subject];
-      while (i < len) {
-        var elem = res[i];
-        if (%_IsSmi(elem)) {
-          if (elem > 0) {
-            match_start = (elem >> 11) + (elem & 0x7ff);
-          } else {
-            match_start = res[++i] - elem;
-          }
-        } else {
-          override[0] = elem;
-          override[1] = match_start;
-          lastMatchInfoOverride = override;
-          var func_result = replace.call(null, elem, match_start, subject);
-          if (!IS_STRING(func_result)) {
-            func_result = NonStringToString(func_result);
-          }
-          res[i] = func_result;
-          match_start += elem.length;
-        }
-        i++;
-      }
-    } else {
-      while (i < len) {
-        var elem = res[i];
-        if (!%_IsSmi(elem)) {
-          // elem must be an Array.
-          // Use the apply argument as backing for global RegExp properties.
-          lastMatchInfoOverride = elem;
-          var func_result = replace.apply(null, elem);
-          if (!IS_STRING(func_result)) {
-            func_result = NonStringToString(func_result);
-          }
-          res[i] = func_result;
-        }
-        i++;
-      }
-    }
-    var resultBuilder = new ReplaceResultBuilder(subject, res);
-    var result = resultBuilder.generate();
-    resultArray.length = 0;
-    reusableReplaceArray = resultArray;
-    return result;
-  } else { // Not a global regexp, no need to loop.
-    var matchInfo = DoRegExpExec(regexp, subject, 0);
-    if (IS_NULL(matchInfo)) return subject;
-
-    var result = new ReplaceResultBuilder(subject);
-    result.addSpecialSlice(0, matchInfo[CAPTURE0]);
-    var endOfMatch = matchInfo[CAPTURE1];
-    result.add(ApplyReplacementFunction(replace, matchInfo, subject));
-    // Can't use matchInfo any more from here, since the function could
-    // overwrite it.
-    result.addSpecialSlice(endOfMatch, subject.length);
-    return result.generate();
+function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) {
+  var resultArray = reusableReplaceArray;
+  if (resultArray) {
+    reusableReplaceArray = null;
+  } else {
+    // Inside a nested replace (replace called from the replacement function
+    // of another replace) or we have failed to set the reusable array
+    // back due to an exception in a replacement function. Create a new
+    // array to use in the future, or until the original is written back.
+    resultArray = $Array(16);
   }
+  var res = %RegExpExecMultiple(regexp,
+                                subject,
+                                lastMatchInfo,
+                                resultArray);
+  regexp.lastIndex = 0;
+  if (IS_NULL(res)) {
+    // No matches at all.
+    reusableReplaceArray = resultArray;
+    return subject;
+  }
+  var len = res.length;
+  var i = 0;
+  if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) {
+    var match_start = 0;
+    var override = [null, 0, subject];
+    var receiver = %GetGlobalReceiver();
+    while (i < len) {
+      var elem = res[i];
+      if (%_IsSmi(elem)) {
+        if (elem > 0) {
+          match_start = (elem >> 11) + (elem & 0x7ff);
+        } else {
+          match_start = res[++i] - elem;
+        }
+      } else {
+        override[0] = elem;
+        override[1] = match_start;
+        lastMatchInfoOverride = override;
+        var func_result =
+            %_CallFunction(receiver, elem, match_start, subject, replace);
+        if (!IS_STRING(func_result)) {
+          func_result = NonStringToString(func_result);
+        }
+        res[i] = func_result;
+        match_start += elem.length;
+      }
+      i++;
+    }
+  } else {
+    while (i < len) {
+      var elem = res[i];
+      if (!%_IsSmi(elem)) {
+        // elem must be an Array.
+        // Use the apply argument as backing for global RegExp properties.
+        lastMatchInfoOverride = elem;
+        var func_result = replace.apply(null, elem);
+        if (!IS_STRING(func_result)) {
+          func_result = NonStringToString(func_result);
+        }
+        res[i] = func_result;
+      }
+      i++;
+    }
+  }
+  var resultBuilder = new ReplaceResultBuilder(subject, res);
+  var result = resultBuilder.generate();
+  resultArray.length = 0;
+  reusableReplaceArray = resultArray;
+  return result;
 }
 
 
-// Helper function to apply a string replacement function once.
-function ApplyReplacementFunction(replace, matchInfo, subject) {
+function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) {
+  var matchInfo = DoRegExpExec(regexp, subject, 0);
+  if (IS_NULL(matchInfo)) return subject;
+  var result = new ReplaceResultBuilder(subject);
+  var index = matchInfo[CAPTURE0];
+  result.addSpecialSlice(0, index);
+  var endOfMatch = matchInfo[CAPTURE1];
   // Compute the parameter list consisting of the match, captures, index,
   // and subject for the replace function invocation.
-  var index = matchInfo[CAPTURE0];
   // The number of captures plus one for the match.
   var m = NUMBER_OF_CAPTURES(matchInfo) >> 1;
+  var replacement;
   if (m == 1) {
-    var s = CaptureString(subject, matchInfo, 0);
+    // No captures, only the match, which is always valid.
+    var s = SubString(subject, index, endOfMatch);
     // Don't call directly to avoid exposing the built-in global object.
-    return replace.call(null, s, index, subject);
+    replacement =
+        %_CallFunction(%GetGlobalReceiver(), s, index, subject, replace);
+  } else {
+    var parameters = $Array(m + 2);
+    for (var j = 0; j < m; j++) {
+      parameters[j] = CaptureString(subject, matchInfo, j);
+    }
+    parameters[j] = index;
+    parameters[j + 1] = subject;
+
+    replacement = replace.apply(null, parameters);
   }
-  var parameters = $Array(m + 2);
-  for (var j = 0; j < m; j++) {
-    parameters[j] = CaptureString(subject, matchInfo, j);
-  }
-  parameters[j] = index;
-  parameters[j + 1] = subject;
-  return replace.apply(null, parameters);
+
+  result.add(replacement);  // The add method converts to string if necessary.
+  // Can't use matchInfo any more from here, since the function could
+  // overwrite it.
+  result.addSpecialSlice(endOfMatch, subject.length);
+  return result.generate();
 }
 
+
 // ECMA-262 section 15.5.4.12
 function StringSearch(re) {
   var regexp;
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index f353253..6ebe495 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -1142,6 +1142,29 @@
 }
 
 
+Object* CallStubCompiler::CompileCustomCall(int generator_id,
+                                            Object* object,
+                                            JSObject* holder,
+                                            JSFunction* function,
+                                            String* fname,
+                                            CheckType check) {
+    ASSERT(generator_id >= 0 && generator_id < kNumCallGenerators);
+    switch (generator_id) {
+#define CALL_GENERATOR_CASE(ignored1, ignored2, name)          \
+      case k##name##CallGenerator:                             \
+        return CallStubCompiler::Compile##name##Call(object,   \
+                                                     holder,   \
+                                                     function, \
+                                                     fname,    \
+                                                     check);
+      CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
+#undef CALL_GENERATOR_CASE
+    }
+    UNREACHABLE();
+    return Heap::undefined_value();
+}
+
+
 Object* CallStubCompiler::GetCode(PropertyType type, String* name) {
   int argc = arguments_.immediate();
   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
@@ -1152,6 +1175,15 @@
 }
 
 
+Object* CallStubCompiler::GetCode(JSFunction* function) {
+  String* function_name = NULL;
+  if (function->shared()->name()->IsString()) {
+    function_name = String::cast(function->shared()->name());
+  }
+  return GetCode(CONSTANT_FUNCTION, function_name);
+}
+
+
 Object* ConstructStubCompiler::GetCode() {
   Code::Flags flags = Code::ComputeFlags(Code::STUB);
   Object* result = GetCodeWithFlags(flags, "ConstructStub");
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 2e0faf6..45aaf75 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -559,8 +559,30 @@
 };
 
 
+// List of functions with custom constant call IC stubs.
+//
+// Installation of custom call generators for the selected builtins is
+// handled by the bootstrapper.
+//
+// Each entry has a name of a global function (lowercased), a name of
+// a builtin function on its instance prototype (the one the generator
+// is set for), and a name of a generator itself (used to build ids
+// and generator function names).
+#define CUSTOM_CALL_IC_GENERATORS(V) \
+  V(array, push, ArrayPush) \
+  V(array, pop, ArrayPop)
+
+
 class CallStubCompiler: public StubCompiler {
  public:
+  enum {
+#define DECLARE_CALL_GENERATOR_ID(ignored1, ignored2, name) \
+    k##name##CallGenerator,
+    CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
+#undef DECLARE_CALL_GENERATOR_ID
+    kNumCallGenerators
+  };
+
   CallStubCompiler(int argc, InLoopFlag in_loop)
       : arguments_(argc), in_loop_(in_loop) { }
 
@@ -582,17 +604,22 @@
                             JSFunction* function,
                             String* name);
 
-  Object* CompileArrayPushCall(Object* object,
-                               JSObject* holder,
-                               JSFunction* function,
-                               String* name,
-                               CheckType check);
+  // Compiles a custom call constant IC using the generator with given id.
+  Object* CompileCustomCall(int generator_id,
+                            Object* object,
+                            JSObject* holder,
+                            JSFunction* function,
+                            String* name,
+                            CheckType check);
 
-  Object* CompileArrayPopCall(Object* object,
-                              JSObject* holder,
-                              JSFunction* function,
-                              String* name,
+#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
+  Object* Compile##name##Call(Object* object,            \
+                              JSObject* holder,          \
+                              JSFunction* function,      \
+                              String* fname,             \
                               CheckType check);
+  CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
+#undef DECLARE_CALL_GENERATOR
 
  private:
   const ParameterCount arguments_;
@@ -601,6 +628,10 @@
   const ParameterCount& arguments() { return arguments_; }
 
   Object* GetCode(PropertyType type, String* name);
+
+  // Convenience function. Calls GetCode above passing
+  // CONSTANT_FUNCTION type and the name of the given function.
+  Object* GetCode(JSFunction* function);
 };
 
 
@@ -663,31 +694,6 @@
   CallHandlerInfo* api_call_info_;
 };
 
-
-typedef Object* (*CustomCallGenerator)(CallStubCompiler* compiler,
-                                       Object* object,
-                                       JSObject* holder,
-                                       JSFunction* function,
-                                       String* name,
-                                       StubCompiler::CheckType check);
-
-
-Object* CompileArrayPushCall(CallStubCompiler* compiler,
-                             Object* object,
-                             JSObject* holder,
-                             JSFunction* function,
-                             String* name,
-                             StubCompiler::CheckType check);
-
-
-Object* CompileArrayPopCall(CallStubCompiler* compiler,
-                            Object* object,
-                            JSObject* holder,
-                            JSFunction* function,
-                            String* name,
-                            StubCompiler::CheckType check);
-
-
 } }  // namespace v8::internal
 
 #endif  // V8_STUB_CACHE_H_
diff --git a/src/top.cc b/src/top.cc
index 2f75c8f..87dc1f6 100644
--- a/src/top.cc
+++ b/src/top.cc
@@ -337,7 +337,7 @@
 static StringStream* incomplete_message = NULL;
 
 
-Handle<String> Top::StackTrace() {
+Handle<String> Top::StackTraceString() {
   if (stack_trace_nesting_level == 0) {
     stack_trace_nesting_level++;
     HeapStringAllocator allocator;
@@ -365,6 +365,89 @@
 }
 
 
+Local<StackTrace> Top::CaptureCurrentStackTrace(
+    int frame_limit, StackTrace::StackTraceOptions options) {
+  v8::HandleScope scope;
+  // Ensure no negative values.
+  int limit = Max(frame_limit, 0);
+  Handle<JSArray> stackTrace = Factory::NewJSArray(frame_limit);
+  FixedArray* frames = FixedArray::cast(stackTrace->elements());
+
+  Handle<String> column_key =  Factory::LookupAsciiSymbol("column");
+  Handle<String> line_key =  Factory::LookupAsciiSymbol("lineNumber");
+  Handle<String> script_key =  Factory::LookupAsciiSymbol("scriptName");
+  Handle<String> function_key =  Factory::LookupAsciiSymbol("functionName");
+  Handle<String> eval_key =  Factory::LookupAsciiSymbol("isEval");
+  Handle<String> constructor_key =  Factory::LookupAsciiSymbol("isConstructor");
+
+  StackTraceFrameIterator it;
+  int frames_seen = 0;
+  while (!it.done() && (frames_seen < limit)) {
+    // Create a JSObject to hold the information for the StackFrame.
+    Handle<JSObject> stackFrame = Factory::NewJSObject(object_function());
+
+    JavaScriptFrame* frame = it.frame();
+    JSFunction* fun(JSFunction::cast(frame->function()));
+    Script* script = Script::cast(fun->shared()->script());
+
+    if (options & StackTrace::kLineNumber) {
+      int script_line_offset = script->line_offset()->value();
+      int position = frame->code()->SourcePosition(frame->pc());
+      int line_number = GetScriptLineNumber(Handle<Script>(script), position);
+      // line_number is already shifted by the script_line_offset.
+      int relative_line_number = line_number - script_line_offset;
+      if (options & StackTrace::kColumnOffset && relative_line_number >= 0) {
+        Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
+        int start = (relative_line_number == 0) ? 0 :
+            Smi::cast(line_ends->get(relative_line_number - 1))->value() + 1;
+        int column_offset = position - start;
+        if (relative_line_number == 0) {
+          // For the case where the code is on the same line as the script tag.
+          column_offset += script->column_offset()->value();
+        }
+        SetProperty(stackFrame, column_key,
+                    Handle<Smi>(Smi::FromInt(column_offset + 1)), NONE);
+      }
+      SetProperty(stackFrame, line_key,
+                  Handle<Smi>(Smi::FromInt(line_number + 1)), NONE);
+    }
+
+    if (options & StackTrace::kScriptName) {
+      Handle<Object> script_name(script->name());
+      SetProperty(stackFrame, script_key, script_name, NONE);
+    }
+
+    if (options & StackTrace::kFunctionName) {
+      Handle<Object> fun_name(fun->shared()->name());
+      if (fun_name->ToBoolean()->IsFalse()) {
+        fun_name = Handle<Object>(fun->shared()->inferred_name());
+      }
+      SetProperty(stackFrame, function_key, fun_name, NONE);
+    }
+
+    if (options & StackTrace::kIsEval) {
+      int type = Smi::cast(script->compilation_type())->value();
+      Handle<Object> is_eval = (type == Script::COMPILATION_TYPE_EVAL) ?
+          Factory::true_value() : Factory::false_value();
+      SetProperty(stackFrame, eval_key, is_eval, NONE);
+    }
+
+    if (options & StackTrace::kIsConstructor) {
+      Handle<Object> is_constructor = (frame->IsConstructor()) ?
+          Factory::true_value() : Factory::false_value();
+      SetProperty(stackFrame, constructor_key, is_constructor, NONE);
+    }
+
+    frames->set(frames_seen, *stackFrame);
+    frames_seen++;
+    it.Advance();
+  }
+
+  stackTrace->set_length(Smi::FromInt(frames_seen));
+  return scope.Close(Utils::StackTraceToLocal(stackTrace));
+}
+
+
 void Top::PrintStack() {
   if (stack_trace_nesting_level == 0) {
     stack_trace_nesting_level++;
@@ -786,7 +869,7 @@
       // traces while the bootstrapper is active since the infrastructure
       // may not have been properly initialized.
       Handle<String> stack_trace;
-      if (FLAG_trace_exception) stack_trace = StackTrace();
+      if (FLAG_trace_exception) stack_trace = StackTraceString();
       message_obj = MessageHandler::MakeMessageObject("uncaught_exception",
           location, HandleVector<Object>(&exception_handle, 1), stack_trace);
     }
diff --git a/src/top.h b/src/top.h
index d263777..4a76a7f 100644
--- a/src/top.h
+++ b/src/top.h
@@ -265,7 +265,10 @@
   static void PrintStackTrace(FILE* out, char* thread_data);
   static void PrintStack(StringStream* accumulator);
   static void PrintStack();
-  static Handle<String> StackTrace();
+  static Handle<String> StackTraceString();
+  static Local<StackTrace> CaptureCurrentStackTrace(
+      int frame_limit,
+      StackTrace::StackTraceOptions options);
 
   // Returns if the top context may access the given global object. If
   // the result is false, the pending exception is guaranteed to be
diff --git a/src/utils.h b/src/utils.h
index fa24947..7c81867 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -412,6 +412,9 @@
   ~ScopedVector() {
     DeleteArray(this->start());
   }
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedVector);
 };
 
 
diff --git a/src/v8natives.js b/src/v8natives.js
index fd86dda..531bd0e 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -225,7 +225,7 @@
 
 // ECMA-262 - 15.2.4.6
 function ObjectIsPrototypeOf(V) {
-  if (!IS_OBJECT(V) && !IS_FUNCTION(V) && !IS_UNDETECTABLE(V)) return false;
+  if (!IS_SPEC_OBJECT_OR_NULL(V) && !IS_UNDETECTABLE(V)) return false;
   return %IsInPrototypeChain(this, V);
 }
 
@@ -233,7 +233,7 @@
 // ECMA-262 - 15.2.4.6
 function ObjectPropertyIsEnumerable(V) {
   if (this == null) return false;
-  if (!IS_OBJECT(this) && !IS_FUNCTION(this)) return false;
+  if (!IS_SPEC_OBJECT_OR_NULL(this)) return false;
   return %IsPropertyEnumerable(this, ToString(V));
 }
 
@@ -279,7 +279,7 @@
 
 
 function ObjectKeys(obj) {
-  if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj) &&
+  if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
       !IS_UNDETECTABLE(obj))
     throw MakeTypeError("obj_ctor_property_non_object", ["keys"]);
   return %LocalKeys(obj);
@@ -329,7 +329,7 @@
 
 // ES5 8.10.5.
 function ToPropertyDescriptor(obj) {
-  if (!IS_OBJECT(obj)) {
+  if (!IS_SPEC_OBJECT_OR_NULL(obj)) {
     throw MakeTypeError("property_desc_object", [obj]);
   }
   var desc = new PropertyDescriptor();
@@ -599,7 +599,7 @@
 
 // ES5 section 15.2.3.2.
 function ObjectGetPrototypeOf(obj) {
-  if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj) &&
+  if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
       !IS_UNDETECTABLE(obj))
     throw MakeTypeError("obj_ctor_property_non_object", ["getPrototypeOf"]);
   return obj.__proto__;
@@ -608,7 +608,7 @@
 
 // ES5 section 15.2.3.3
 function ObjectGetOwnPropertyDescriptor(obj, p) {
-  if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj) &&
+  if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
       !IS_UNDETECTABLE(obj))
     throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyDescriptor"]);
   var desc = GetOwnProperty(obj, p);
@@ -618,7 +618,7 @@
 
 // ES5 section 15.2.3.4.
 function ObjectGetOwnPropertyNames(obj) {
-  if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj) &&
+  if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
       !IS_UNDETECTABLE(obj))
     throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyNames"]);
 
@@ -660,7 +660,7 @@
 
 // ES5 section 15.2.3.5.
 function ObjectCreate(proto, properties) {
-  if (!IS_OBJECT(proto) && !IS_NULL(proto)) {
+  if (!IS_SPEC_OBJECT_OR_NULL(proto)) {
     throw MakeTypeError("proto_object_or_null", [proto]);
   }
   var obj = new $Object();
@@ -672,7 +672,7 @@
 
 // ES5 section 15.2.3.6.
 function ObjectDefineProperty(obj, p, attributes) {
-  if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj) &&
+  if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
       !IS_UNDETECTABLE(obj))
     throw MakeTypeError("obj_ctor_property_non_object", ["defineProperty"]);
   var name = ToString(p);
@@ -684,7 +684,7 @@
 
 // ES5 section 15.2.3.7.
 function ObjectDefineProperties(obj, properties) {
- if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj) &&
+ if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
      !IS_UNDETECTABLE(obj))
     throw MakeTypeError("obj_ctor_property_non_object", ["defineProperties"]);
   var props = ToObject(properties);
diff --git a/src/version.cc b/src/version.cc
index 7563c69..1bf543d 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     2
 #define MINOR_VERSION     2
-#define BUILD_NUMBER      8
+#define BUILD_NUMBER      10
 #define PATCH_LEVEL       0
 #define CANDIDATE_VERSION false
 
diff --git a/src/virtual-frame-heavy-inl.h b/src/virtual-frame-heavy-inl.h
index 6381d01..2755eee 100644
--- a/src/virtual-frame-heavy-inl.h
+++ b/src/virtual-frame-heavy-inl.h
@@ -31,6 +31,8 @@
 #include "type-info.h"
 #include "register-allocator.h"
 #include "scopes.h"
+#include "register-allocator-inl.h"
+#include "codegen-inl.h"
 
 namespace v8 {
 namespace internal {
@@ -147,6 +149,44 @@
   Push(Handle<Object> (value));
 }
 
+
+int VirtualFrame::register_location(Register reg) {
+  return register_locations_[RegisterAllocator::ToNumber(reg)];
+}
+
+
+void VirtualFrame::set_register_location(Register reg, int index) {
+  register_locations_[RegisterAllocator::ToNumber(reg)] = index;
+}
+
+
+bool VirtualFrame::is_used(Register reg) {
+  return register_locations_[RegisterAllocator::ToNumber(reg)]
+      != kIllegalIndex;
+}
+
+
+void VirtualFrame::SetElementAt(int index, Handle<Object> value) {
+  Result temp(value);
+  SetElementAt(index, &temp);
+}
+
+
+Result VirtualFrame::CallStub(CodeStub* stub, int arg_count) {
+  PrepareForCall(arg_count, arg_count);
+  return RawCallStub(stub);
+}
+
+
+int VirtualFrame::parameter_count() {
+  return cgen()->scope()->num_parameters();
+}
+
+
+int VirtualFrame::local_count() {
+  return cgen()->scope()->num_stack_slots();
+}
+
 } }  // namespace v8::internal
 
 #endif  // V8_VIRTUAL_FRAME_HEAVY_INL_H_
diff --git a/src/virtual-frame-light-inl.h b/src/virtual-frame-light-inl.h
index c50e6c8..17b1c50 100644
--- a/src/virtual-frame-light-inl.h
+++ b/src/virtual-frame-light-inl.h
@@ -28,13 +28,23 @@
 #ifndef V8_VIRTUAL_FRAME_LIGHT_INL_H_
 #define V8_VIRTUAL_FRAME_LIGHT_INL_H_
 
-#include "type-info.h"
+#include "codegen.h"
 #include "register-allocator.h"
 #include "scopes.h"
+#include "type-info.h"
+
+#include "codegen-inl.h"
+#include "jump-target-light-inl.h"
 
 namespace v8 {
 namespace internal {
 
+VirtualFrame::VirtualFrame(InvalidVirtualFrameInitializer* dummy)
+    : element_count_(0),
+      top_of_stack_state_(NO_TOS_REGISTERS),
+      register_allocation_map_(0) { }
+
+
 // On entry to a function, the virtual frame already contains the receiver,
 // the parameters, and a return address.  All frame elements are in memory.
 VirtualFrame::VirtualFrame()
@@ -64,6 +74,87 @@
 }
 
 
+VirtualFrame::RegisterAllocationScope::RegisterAllocationScope(
+    CodeGenerator* cgen)
+  : cgen_(cgen),
+    old_is_spilled_(SpilledScope::is_spilled_) {
+  SpilledScope::is_spilled_ = false;
+  if (old_is_spilled_) {
+    VirtualFrame* frame = cgen->frame();
+    if (frame != NULL) {
+      frame->AssertIsSpilled();
+    }
+  }
+}
+
+
+VirtualFrame::RegisterAllocationScope::~RegisterAllocationScope() {
+  SpilledScope::is_spilled_ = old_is_spilled_;
+  if (old_is_spilled_) {
+    VirtualFrame* frame = cgen_->frame();
+    if (frame != NULL) {
+      frame->SpillAll();
+    }
+  }
+}
+
+
+CodeGenerator* VirtualFrame::cgen() { return CodeGeneratorScope::Current(); }
+
+
+MacroAssembler* VirtualFrame::masm() { return cgen()->masm(); }
+
+
+void VirtualFrame::CallStub(CodeStub* stub, int arg_count) {
+  if (arg_count != 0) Forget(arg_count);
+  ASSERT(cgen()->HasValidEntryRegisters());
+  masm()->CallStub(stub);
+}
+
+
+int VirtualFrame::parameter_count() {
+  return cgen()->scope()->num_parameters();
+}
+
+
+int VirtualFrame::local_count() { return cgen()->scope()->num_stack_slots(); }
+
+
+int VirtualFrame::frame_pointer() { return parameter_count() + 3; }
+
+
+int VirtualFrame::context_index() { return frame_pointer() - 1; }
+
+
+int VirtualFrame::function_index() { return frame_pointer() - 2; }
+
+
+int VirtualFrame::local0_index() { return frame_pointer() + 2; }
+
+
+int VirtualFrame::fp_relative(int index) {
+  ASSERT(index < element_count());
+  ASSERT(frame_pointer() < element_count());  // FP is on the frame.
+  return (frame_pointer() - index) * kPointerSize;
+}
+
+
+int VirtualFrame::expression_base_index() {
+  return local0_index() + local_count();
+}
+
+
+int VirtualFrame::height() {
+  return element_count() - expression_base_index();
+}
+
+
+MemOperand VirtualFrame::LocalAt(int index) {
+  ASSERT(0 <= index);
+  ASSERT(index < local_count());
+  return MemOperand(fp, kLocal0Offset - index * kPointerSize);
+}
+
 } }  // namespace v8::internal
 
 #endif  // V8_VIRTUAL_FRAME_LIGHT_INL_H_
diff --git a/src/virtual-frame-light.cc b/src/virtual-frame-light.cc
index 27c48a5..9c019cf 100644
--- a/src/virtual-frame-light.cc
+++ b/src/virtual-frame-light.cc
@@ -46,4 +46,7 @@
   return no_reg;
 }
 
+
+InvalidVirtualFrameInitializer* kInvalidVirtualFrameInitializer = NULL;
+
 } }  // namespace v8::internal
diff --git a/src/x64/assembler-x64-inl.h b/src/x64/assembler-x64-inl.h
index c9ab627..be7cfe0 100644
--- a/src/x64/assembler-x64-inl.h
+++ b/src/x64/assembler-x64-inl.h
@@ -34,7 +34,7 @@
 namespace v8 {
 namespace internal {
 
-Condition NegateCondition(Condition cc) {
+inline Condition NegateCondition(Condition cc) {
   return static_cast<Condition>(cc ^ 1);
 }
 
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 1c00ebc..fcfa8d0 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -2510,6 +2510,17 @@
 }
 
 
+void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0xF2);
+  emit_rex_64(dst, src);
+  emit(0x0F);
+  emit(0x2C);
+  emit_sse_operand(dst, src);
+}
+
+
 void Assembler::cvtlsi2sd(XMMRegister dst, const Operand& src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index d077865..0f06c3c 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -606,6 +606,14 @@
     immediate_arithmetic_op(0x0, dst, src);
   }
 
+  void sbbl(Register dst, Register src) {
+    if (dst.low_bits() == 4) {  // Forces SIB byte if dst is base register.
+      arithmetic_op_32(0x19, src, dst);
+    } else {
+      arithmetic_op_32(0x1b, dst, src);
+    }
+  }
+
   void cmpb(Register dst, Immediate src) {
     immediate_arithmetic_op_8(0x7, dst, src);
   }
@@ -1092,6 +1100,7 @@
 
   void cvttss2si(Register dst, const Operand& src);
   void cvttsd2si(Register dst, const Operand& src);
+  void cvttsd2siq(Register dst, XMMRegister src);
 
   void cvtlsi2sd(XMMRegister dst, const Operand& src);
   void cvtlsi2sd(XMMRegister dst, Register src);
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index 39f543d..d9586cc 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -277,7 +277,6 @@
   // Takes the operands in rdx and rax and loads them as integers in rax
   // and rcx.
   static void LoadAsIntegers(MacroAssembler* masm,
-                             bool use_sse3,
                              Label* operand_conversion_failure);
 };
 
@@ -360,7 +359,7 @@
       frame_->AllocateStackSlots();
 
       // Allocate the local context if needed.
-      int heap_slots = scope()->num_heap_slots();
+      int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
       if (heap_slots > 0) {
         Comment cmnt(masm_, "[ allocate local context");
         // Allocate local context.
@@ -2866,9 +2865,30 @@
   } else if (var != NULL && var->slot() != NULL &&
              var->slot()->type() == Slot::LOOKUP) {
     // ----------------------------------
-    // JavaScript example: 'with (obj) foo(1, 2, 3)'  // foo is in obj
+    // JavaScript examples:
+    //
+    //  with (obj) foo(1, 2, 3)  // foo may be in obj.
+    //
+    //  function f() {};
+    //  function g() {
+    //    eval(...);
+    //    f();  // f could be in extension object.
+    //  }
     // ----------------------------------
 
+    JumpTarget slow, done;
+    Result function;
+
+    // Generate fast case for loading functions from slots that
+    // correspond to local/global variables or arguments unless they
+    // are shadowed by eval-introduced bindings.
+    EmitDynamicLoadFromSlotFastCase(var->slot(),
+                                    NOT_INSIDE_TYPEOF,
+                                    &function,
+                                    &slow,
+                                    &done);
+
+    slow.Bind();
     // Load the function from the context.  Sync the frame so we can
     // push the arguments directly into place.
     frame_->SyncRange(0, frame_->element_count() - 1);
@@ -2887,6 +2907,18 @@
     ASSERT(!allocator()->is_used(rdx));
     frame_->EmitPush(rdx);
 
+    // If fast case code has been generated, emit code to push the
+    // function and receiver and have the slow path jump around this
+    // code.
+    if (done.is_linked()) {
+      JumpTarget call;
+      call.Jump();
+      done.Bind(&function);
+      frame_->Push(&function);
+      LoadGlobalReceiver();
+      call.Bind();
+    }
+
     // Call the function.
     CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position());
 
@@ -4392,7 +4424,7 @@
     __ Move(FieldOperand(rcx, HeapObject::kMapOffset),
             Factory::fixed_array_map());
     // Set length.
-    __ movq(FieldOperand(rcx, FixedArray::kLengthOffset), rbx);
+    __ movl(FieldOperand(rcx, FixedArray::kLengthOffset), rbx);
     // Fill contents of fixed-array with the-hole.
     __ Move(rdx, Factory::the_hole_value());
     __ lea(rcx, FieldOperand(rcx, FixedArray::kHeaderSize));
@@ -4421,22 +4453,142 @@
 
 class DeferredSearchCache: public DeferredCode {
  public:
-  DeferredSearchCache(Register dst, Register cache, Register key)
-      : dst_(dst), cache_(cache), key_(key) {
+  DeferredSearchCache(Register dst,
+                      Register cache,
+                      Register key,
+                      Register scratch)
+      : dst_(dst), cache_(cache), key_(key), scratch_(scratch) {
     set_comment("[ DeferredSearchCache");
   }
 
   virtual void Generate();
 
  private:
-  Register dst_, cache_, key_;
+  Register dst_;    // on invocation index of finger (as Smi), on exit
+                    // holds value being looked up.
+  Register cache_;  // instance of JSFunctionResultCache.
+  Register key_;    // key being looked up.
+  Register scratch_;
 };
 
 
+// Return a position of the element at |index| + |additional_offset|
+// in FixedArray pointer to which is held in |array|.  |index| is int32.
+static Operand ArrayElement(Register array,
+                            Register index,
+                            int additional_offset = 0) {
+  int offset = FixedArray::kHeaderSize + additional_offset * kPointerSize;
+  return FieldOperand(array, index, times_pointer_size, offset);
+}
+
+
 void DeferredSearchCache::Generate() {
-  __ push(cache_);
+  Label first_loop, search_further, second_loop, cache_miss;
+
+  Immediate kEntriesIndexImm = Immediate(JSFunctionResultCache::kEntriesIndex);
+  Immediate kEntrySizeImm = Immediate(JSFunctionResultCache::kEntrySize);
+
+  __ SmiToInteger32(dst_, dst_);
+  // Check the cache from finger to start of the cache.
+  __ bind(&first_loop);
+  __ subq(dst_, kEntrySizeImm);
+  __ cmpq(dst_, kEntriesIndexImm);
+  __ j(less, &search_further);
+
+  __ cmpq(ArrayElement(cache_, dst_), key_);
+  __ j(not_equal, &first_loop);
+
+  __ Integer32ToSmi(scratch_, dst_);
+  __ movq(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), scratch_);
+  __ movq(dst_, ArrayElement(cache_, dst_, 1));
+  __ jmp(exit_label());
+
+  __ bind(&search_further);
+
+  // Check the cache from end of cache up to finger.
+  __ movq(dst_, FieldOperand(cache_, JSFunctionResultCache::kCacheSizeOffset));
+  __ movq(scratch_, FieldOperand(cache_, JSFunctionResultCache::kFingerOffset));
+  __ SmiToInteger32(dst_, dst_);
+  __ SmiToInteger32(scratch_, scratch_);
+
+  __ bind(&second_loop);
+  __ subq(dst_, kEntrySizeImm);
+  __ cmpq(dst_, scratch_);
+  __ j(less_equal, &cache_miss);
+
+  __ cmpq(ArrayElement(cache_, dst_), key_);
+  __ j(not_equal, &second_loop);
+
+  __ Integer32ToSmi(scratch_, dst_);
+  __ movq(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), scratch_);
+  __ movq(dst_, ArrayElement(cache_, dst_, 1));
+  __ jmp(exit_label());
+
+  __ bind(&cache_miss);
+  __ push(cache_);  // store a reference to cache
+  __ push(key_);  // store a key
+  Handle<Object> receiver(Top::global_context()->global());
+  __ Push(receiver);
   __ push(key_);
-  __ CallRuntime(Runtime::kGetFromCache, 2);
+  // On x64 function must be in rdi.
+  __ movq(rdi, FieldOperand(cache_, JSFunctionResultCache::kFactoryOffset));
+  ParameterCount expected(1);
+  __ InvokeFunction(rdi, expected, CALL_FUNCTION);
+
+  // Find a place to put new cached value into.
+  Label add_new_entry, update_cache;
+  __ movq(rcx, Operand(rsp, kPointerSize));  // restore the cache
+  // Possible optimization: cache size is constant for the given cache
+  // so technically we could use a constant here.  However, if we have
+  // cache miss this optimization would hardly matter much.
+
+  // Check if we could add new entry to cache.
+  __ movl(rbx, FieldOperand(rcx, FixedArray::kLengthOffset));
+  __ movq(r9, FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset));
+  __ SmiToInteger32(r9, r9);
+  __ cmpq(rbx, r9);
+  __ j(greater, &add_new_entry);
+
+  // Check if we could evict entry after finger.
+  __ movq(rdx, FieldOperand(rcx, JSFunctionResultCache::kFingerOffset));
+  __ SmiToInteger32(rdx, rdx);
+  __ addq(rdx, kEntrySizeImm);
+  Label forward;
+  __ cmpq(rbx, rdx);
+  __ j(greater, &forward);
+  // Need to wrap over the cache.
+  __ movq(rdx, kEntriesIndexImm);
+  __ bind(&forward);
+  __ Integer32ToSmi(r9, rdx);
+  __ jmp(&update_cache);
+
+  __ bind(&add_new_entry);
+  // r9 holds cache size as int.
+  __ movq(rdx, r9);
+  __ Integer32ToSmi(r9, r9);
+  __ SmiAddConstant(rbx, r9, Smi::FromInt(JSFunctionResultCache::kEntrySize));
+  __ movq(FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset), rbx);
+
+  // Update the cache itself.
+  // rdx holds the index as int.
+  // r9 holds the index as smi.
+  __ bind(&update_cache);
+  __ pop(rbx);  // restore the key
+  __ movq(FieldOperand(rcx, JSFunctionResultCache::kFingerOffset), r9);
+  // Store key.
+  __ movq(ArrayElement(rcx, rdx), rbx);
+  __ RecordWrite(rcx, 0, rbx, r9);
+
+  // Store value.
+  __ pop(rcx);  // restore the cache.
+  __ movq(rdx, FieldOperand(rcx, JSFunctionResultCache::kFingerOffset));
+  __ SmiAddConstant(rdx, rdx, Smi::FromInt(1));
+  __ movq(r9, rdx);
+  __ SmiToInteger32(rdx, rdx);
+  __ movq(rbx, rax);
+  __ movq(ArrayElement(rcx, rdx), rbx);
+  __ RecordWrite(rcx, 0, rbx, r9);
+
   if (!dst_.is(rax)) {
     __ movq(dst_, rax);
   }
@@ -4474,27 +4626,28 @@
   Result tmp = allocator()->Allocate();
   ASSERT(tmp.is_valid());
 
+  Result scratch = allocator()->Allocate();
+  ASSERT(scratch.is_valid());
+
   DeferredSearchCache* deferred = new DeferredSearchCache(tmp.reg(),
                                                           cache.reg(),
-                                                          key.reg());
+                                                          key.reg(),
+                                                          scratch.reg());
 
   const int kFingerOffset =
       FixedArray::OffsetOfElementAt(JSFunctionResultCache::kFingerIndex);
   // tmp.reg() now holds finger offset as a smi.
-  ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
   __ movq(tmp.reg(), FieldOperand(cache.reg(), kFingerOffset));
   SmiIndex index =
       masm()->SmiToIndex(kScratchRegister, tmp.reg(), kPointerSizeLog2);
   __ cmpq(key.reg(), FieldOperand(cache.reg(),
-                                  index.reg,
-                                  index.scale,
+                                  index.reg, index.scale,
                                   FixedArray::kHeaderSize));
+  // Do NOT alter index.reg or tmp.reg() before cmpq below.
   deferred->Branch(not_equal);
-
   __ movq(tmp.reg(), FieldOperand(cache.reg(),
-                                  index.reg,
-                                  index.scale,
-                                  kPointerSize + FixedArray::kHeaderSize));
+                                  index.reg, index.scale,
+                                  FixedArray::kHeaderSize + kPointerSize));
 
   deferred->BindExit();
   frame_->Push(&tmp);
@@ -5049,6 +5202,11 @@
     // The expression is a variable proxy that does not rewrite to a
     // property.  Global variables are treated as named property references.
     if (var->is_global()) {
+      // If rax is free, the register allocator prefers it.  Thus the code
+      // generator will load the global object into rax, which is where
+      // LoadIC wants it.  Most uses of Reference call LoadIC directly
+      // after the reference is created.
+      frame_->Spill(rax);
       LoadGlobal();
       ref->set_type(Reference::NAMED);
     } else {
@@ -5160,46 +5318,14 @@
     JumpTarget done;
     Result value;
 
-    // Generate fast-case code for variables that might be shadowed by
-    // eval-introduced variables.  Eval is used a lot without
-    // introducing variables.  In those cases, we do not want to
-    // perform a runtime call for all variables in the scope
-    // containing the eval.
-    if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
-      value = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow);
-      // If there was no control flow to slow, we can exit early.
-      if (!slow.is_linked()) {
-        frame_->Push(&value);
-        return;
-      }
-
-      done.Jump(&value);
-
-    } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
-      Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
-      // Only generate the fast case for locals that rewrite to slots.
-      // This rules out argument loads.
-      if (potential_slot != NULL) {
-        // Allocate a fresh register to use as a temp in
-        // ContextSlotOperandCheckExtensions and to hold the result
-        // value.
-        value = allocator_->Allocate();
-        ASSERT(value.is_valid());
-        __ movq(value.reg(),
-               ContextSlotOperandCheckExtensions(potential_slot,
-                                                 value,
-                                                 &slow));
-        if (potential_slot->var()->mode() == Variable::CONST) {
-          __ CompareRoot(value.reg(), Heap::kTheHoleValueRootIndex);
-          done.Branch(not_equal, &value);
-          __ LoadRoot(value.reg(), Heap::kUndefinedValueRootIndex);
-        }
-        // There is always control flow to slow from
-        // ContextSlotOperandCheckExtensions so we have to jump around
-        // it.
-        done.Jump(&value);
-      }
-    }
+    // Generate fast case for loading from slots that correspond to
+    // local/global variables or arguments unless they are shadowed by
+    // eval-introduced bindings.
+    EmitDynamicLoadFromSlotFastCase(slot,
+                                    typeof_state,
+                                    &value,
+                                    &slow,
+                                    &done);
 
     slow.Bind();
     // A runtime call is inevitable.  We eagerly sync frame elements
@@ -5465,6 +5591,71 @@
 }
 
 
+void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot,
+                                                    TypeofState typeof_state,
+                                                    Result* result,
+                                                    JumpTarget* slow,
+                                                    JumpTarget* done) {
+  // Generate fast-case code for variables that might be shadowed by
+  // eval-introduced variables.  Eval is used a lot without
+  // introducing variables.  In those cases, we do not want to
+  // perform a runtime call for all variables in the scope
+  // containing the eval.
+  if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
+    *result = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, slow);
+    done->Jump(result);
+
+  } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
+    Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
+    Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
+    if (potential_slot != NULL) {
+      // Generate fast case for locals that rewrite to slots.
+      // Allocate a fresh register to use as a temp in
+      // ContextSlotOperandCheckExtensions and to hold the result
+      // value.
+      *result = allocator_->Allocate();
+      ASSERT(result->is_valid());
+      __ movq(result->reg(),
+              ContextSlotOperandCheckExtensions(potential_slot,
+                                                *result,
+                                                slow));
+      if (potential_slot->var()->mode() == Variable::CONST) {
+        __ CompareRoot(result->reg(), Heap::kTheHoleValueRootIndex);
+        done->Branch(not_equal, result);
+        __ LoadRoot(result->reg(), Heap::kUndefinedValueRootIndex);
+      }
+      done->Jump(result);
+    } else if (rewrite != NULL) {
+      // Generate fast case for argument loads.
+      Property* property = rewrite->AsProperty();
+      if (property != NULL) {
+        VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
+        Literal* key_literal = property->key()->AsLiteral();
+        if (obj_proxy != NULL &&
+            key_literal != NULL &&
+            obj_proxy->IsArguments() &&
+            key_literal->handle()->IsSmi()) {
+          // Load arguments object if there are no eval-introduced
+          // variables. Then load the argument from the arguments
+          // object using keyed load.
+          Result arguments = allocator()->Allocate();
+          ASSERT(arguments.is_valid());
+          __ movq(arguments.reg(),
+                  ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
+                                                    arguments,
+                                                    slow));
+          frame_->Push(&arguments);
+          frame_->Push(key_literal->handle());
+          *result = EmitKeyedLoad(false);
+          frame_->Drop(2);  // Drop key and receiver.
+          done->Jump(result);
+        }
+      }
+    }
+  }
+}
+
+
 void CodeGenerator::LoadGlobal() {
   if (in_spilled_code()) {
     frame_->EmitPush(GlobalObject());
@@ -5683,48 +5874,55 @@
       // by reconstituting them on the non-fall-through path.
       JumpTarget is_smi;
 
-      Condition left_is_smi = masm_->CheckSmi(left_side.reg());
-      is_smi.Branch(left_is_smi);
-
-      bool is_loop_condition = (node->AsExpression() != NULL) &&
-          node->AsExpression()->is_loop_condition();
-      if (!is_loop_condition && right_val->IsSmi()) {
-        // Right side is a constant smi and left side has been checked
-        // not to be a smi.
-        JumpTarget not_number;
-        __ Cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
-               Factory::heap_number_map());
-        not_number.Branch(not_equal, &left_side);
-        __ movsd(xmm1,
-                 FieldOperand(left_reg, HeapNumber::kValueOffset));
-        int value = Smi::cast(*right_val)->value();
-        if (value == 0) {
-          __ xorpd(xmm0, xmm0);
-        } else {
-          Result temp = allocator()->Allocate();
-          __ movl(temp.reg(), Immediate(value));
-          __ cvtlsi2sd(xmm0, temp.reg());
-          temp.Unuse();
+      if (left_side.is_smi()) {
+        if (FLAG_debug_code) {
+          __ AbortIfNotSmi(left_side.reg(), "Non-smi value inferred as smi.");
         }
-        __ ucomisd(xmm1, xmm0);
-        // Jump to builtin for NaN.
-        not_number.Branch(parity_even, &left_side);
-        left_side.Unuse();
-        dest->true_target()->Branch(DoubleCondition(cc));
+      } else {
+        Condition left_is_smi = masm_->CheckSmi(left_side.reg());
+        is_smi.Branch(left_is_smi);
+
+        bool is_loop_condition = (node->AsExpression() != NULL) &&
+            node->AsExpression()->is_loop_condition();
+        if (!is_loop_condition && right_val->IsSmi()) {
+          // Right side is a constant smi and left side has been checked
+          // not to be a smi.
+          JumpTarget not_number;
+          __ Cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
+                 Factory::heap_number_map());
+          not_number.Branch(not_equal, &left_side);
+          __ movsd(xmm1,
+              FieldOperand(left_reg, HeapNumber::kValueOffset));
+          int value = Smi::cast(*right_val)->value();
+          if (value == 0) {
+            __ xorpd(xmm0, xmm0);
+          } else {
+            Result temp = allocator()->Allocate();
+            __ movl(temp.reg(), Immediate(value));
+            __ cvtlsi2sd(xmm0, temp.reg());
+            temp.Unuse();
+          }
+          __ ucomisd(xmm1, xmm0);
+          // Jump to builtin for NaN.
+          not_number.Branch(parity_even, &left_side);
+          left_side.Unuse();
+          dest->true_target()->Branch(DoubleCondition(cc));
+          dest->false_target()->Jump();
+          not_number.Bind(&left_side);
+        }
+
+        // Setup and call the compare stub.
+        CompareStub stub(cc, strict, kCantBothBeNaN);
+        Result result = frame_->CallStub(&stub, &left_side, &right_side);
+        result.ToRegister();
+        __ testq(result.reg(), result.reg());
+        result.Unuse();
+        dest->true_target()->Branch(cc);
         dest->false_target()->Jump();
-        not_number.Bind(&left_side);
+
+        is_smi.Bind();
       }
 
-      // Setup and call the compare stub.
-      CompareStub stub(cc, strict, kCantBothBeNaN);
-      Result result = frame_->CallStub(&stub, &left_side, &right_side);
-      result.ToRegister();
-      __ testq(result.reg(), result.reg());
-      result.Unuse();
-      dest->true_target()->Branch(cc);
-      dest->false_target()->Jump();
-
-      is_smi.Bind();
       left_side = Result(left_reg);
       right_side = Result(right_val);
       // Test smi equality and comparison by signed int comparison.
@@ -5896,7 +6094,7 @@
         // If the first character is the same then the long string sorts after
         // the short one.
         __ SmiCompare(FieldOperand(left_side.reg(), String::kLengthOffset),
-               Smi::FromInt(1));
+                      Smi::FromInt(1));
         __ bind(&characters_were_different);
       }
       temp2.Unuse();
@@ -6404,10 +6602,8 @@
                                                  Handle<Object> value,
                                                  bool reversed,
                                                  OverwriteMode overwrite_mode) {
-  // 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 constant smi.
-  // Consumes the argument "operand".
+  // Generate inline code for a binary operation when one of the
+  // operands is a constant smi.  Consumes the argument "operand".
   if (IsUnsafeSmi(value)) {
     Result unsafe_operand(value);
     if (reversed) {
@@ -6528,43 +6724,37 @@
 
     case Token::SHL:
       if (reversed) {
-        // Move operand into rcx and also into a second register.
-        // If operand is already in a register, take advantage of that.
-        // This lets us modify rcx, but still bail out to deferred code.
-        Result right;
-        Result right_copy_in_rcx;
-        TypeInfo right_type_info = operand->type_info();
         operand->ToRegister();
-        if (operand->reg().is(rcx)) {
-          right = allocator()->Allocate();
-          __ movq(right.reg(), rcx);
-          frame_->Spill(rcx);
-          right_copy_in_rcx = *operand;
-        } else {
-          right_copy_in_rcx = allocator()->Allocate(rcx);
-          __ movq(rcx, operand->reg());
-          right = *operand;
-        }
-        operand->Unuse();
 
-        answer = allocator()->Allocate();
+        // We need rcx to be available to hold operand, and to be spilled.
+        // SmiShiftLeft implicitly modifies rcx.
+        if (operand->reg().is(rcx)) {
+          frame_->Spill(operand->reg());
+          answer = allocator()->Allocate();
+        } else {
+          Result rcx_reg = allocator()->Allocate(rcx);
+          // answer must not be rcx.
+          answer = allocator()->Allocate();
+          // rcx_reg goes out of scope.
+        }
+
         DeferredInlineSmiOperationReversed* deferred =
             new DeferredInlineSmiOperationReversed(op,
                                                    answer.reg(),
                                                    smi_value,
-                                                   right.reg(),
+                                                   operand->reg(),
                                                    overwrite_mode);
-        __ movq(answer.reg(), Immediate(int_value));
-        __ SmiToInteger32(rcx, rcx);
-        if (!right_type_info.IsSmi()) {
-          Condition is_smi = masm_->CheckSmi(right.reg());
+        if (!operand->type_info().IsSmi()) {
+          Condition is_smi = masm_->CheckSmi(operand->reg());
           deferred->Branch(NegateCondition(is_smi));
         } else if (FLAG_debug_code) {
-          __ AbortIfNotSmi(right.reg(),
+          __ AbortIfNotSmi(operand->reg(),
               "Static type info claims non-smi is smi in (const SHL smi).");
         }
-        __ shl_cl(answer.reg());
-        __ Integer32ToSmi(answer.reg(), answer.reg());
+
+        __ Move(answer.reg(), smi_value);
+        __ SmiShiftLeft(answer.reg(), answer.reg(), operand->reg());
+        operand->Unuse();
 
         deferred->BindExit();
       } else {
@@ -6597,8 +6787,7 @@
           __ JumpIfNotSmi(operand->reg(), deferred->entry_label());
           __ SmiShiftLeftConstant(answer.reg(),
                                   operand->reg(),
-                                  shift_value,
-                                  deferred->entry_label());
+                                  shift_value);
           deferred->BindExit();
           operand->Unuse();
         }
@@ -6685,10 +6874,19 @@
   return answer;
 }
 
+
+// Implements a binary operation using a deferred code object and some
+// inline code to operate on smis quickly.
 Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr,
                                                Result* left,
                                                Result* right,
                                                OverwriteMode overwrite_mode) {
+  // Copy the type info because left and right may be overwritten.
+  TypeInfo left_type_info = left->type_info();
+  TypeInfo right_type_info = right->type_info();
+  USE(left_type_info);
+  USE(right_type_info);
+  // TODO(X64): Use type information in calculations.
   Token::Value op = expr->op();
   Result answer;
   // Special handling of div and mod because they use fixed registers.
@@ -6813,9 +7011,7 @@
                                           left->reg(),
                                           rcx,
                                           overwrite_mode);
-    __ movq(answer.reg(), left->reg());
-    __ or_(answer.reg(), rcx);
-    __ JumpIfNotSmi(answer.reg(), deferred->entry_label());
+    __ JumpIfNotBothSmi(left->reg(), rcx, deferred->entry_label());
 
     // Perform the operation.
     switch (op) {
@@ -6832,8 +7028,7 @@
       case Token::SHL: {
         __ SmiShiftLeft(answer.reg(),
                         left->reg(),
-                        rcx,
-                        deferred->entry_label());
+                        rcx);
         break;
       }
       default:
@@ -7834,138 +8029,71 @@
 }
 
 
-// Get the integer part of a heap number.  Surprisingly, all this bit twiddling
-// is faster than using the built-in instructions on floating point registers.
-// Trashes rdi and rbx.  Dest is rcx.  Source cannot be rcx or one of the
-// trashed registers.
+// Get the integer part of a heap number.
+// Overwrites the contents of rdi, rbx and rcx. Result cannot be rdi or rbx.
 void IntegerConvert(MacroAssembler* masm,
-                    Register source,
-                    bool use_sse3,
-                    Label* conversion_failure) {
-  ASSERT(!source.is(rcx) && !source.is(rdi) && !source.is(rbx));
-  Label done, right_exponent, normal_exponent;
-  Register scratch = rbx;
-  Register scratch2 = rdi;
-  // Get exponent word.
-  __ movl(scratch, FieldOperand(source, HeapNumber::kExponentOffset));
-  // Get exponent alone in scratch2.
-  __ movl(scratch2, scratch);
-  __ and_(scratch2, Immediate(HeapNumber::kExponentMask));
-  if (use_sse3) {
-    CpuFeatures::Scope scope(SSE3);
-    // Check whether the exponent is too big for a 64 bit signed integer.
-    static const uint32_t kTooBigExponent =
-        (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
-    __ cmpl(scratch2, Immediate(kTooBigExponent));
-    __ j(greater_equal, conversion_failure);
-    // Load x87 register with heap number.
-    __ fld_d(FieldOperand(source, HeapNumber::kValueOffset));
-    // Reserve space for 64 bit answer.
-    __ subq(rsp, Immediate(sizeof(uint64_t)));  // Nolint.
-    // Do conversion, which cannot fail because we checked the exponent.
-    __ fisttp_d(Operand(rsp, 0));
-    __ movl(rcx, Operand(rsp, 0));  // Load low word of answer into rcx.
-    __ addq(rsp, Immediate(sizeof(uint64_t)));  // Nolint.
+                    Register result,
+                    Register source) {
+  // Result may be rcx. If result and source are the same register, source will
+  // be overwritten.
+  ASSERT(!result.is(rdi) && !result.is(rbx));
+  // TODO(lrn): When type info reaches here, if value is a 32-bit integer, use
+  // cvttsd2si (32-bit version) directly.
+  Register double_exponent = rbx;
+  Register double_value = rdi;
+  Label done, exponent_63_plus;
+  // Get double and extract exponent.
+  __ movq(double_value, FieldOperand(source, HeapNumber::kValueOffset));
+  // Clear result preemptively, in case we need to return zero.
+  __ xorl(result, result);
+  __ movq(xmm0, double_value);  // Save copy in xmm0 in case we need it there.
+  // Double to remove sign bit, shift exponent down to least significant bits.
+  // and subtract bias to get the unshifted, unbiased exponent.
+  __ lea(double_exponent, Operand(double_value, double_value, times_1, 0));
+  __ shr(double_exponent, Immediate(64 - HeapNumber::KExponentBits));
+  __ subl(double_exponent, Immediate(HeapNumber::kExponentBias));
+  // Check whether the exponent is too big for a 63 bit unsigned integer.
+  __ cmpl(double_exponent, Immediate(63));
+  __ j(above_equal, &exponent_63_plus);
+  // Handle exponent range 0..62.
+  __ cvttsd2siq(result, xmm0);
+  __ jmp(&done);
+
+  __ bind(&exponent_63_plus);
+  // Exponent negative or 63+.
+  __ cmpl(double_exponent, Immediate(83));
+  // If exponent negative or above 83, number contains no significant bits in
+  // the range 0..2^31, so result is zero, and rcx already holds zero.
+  __ j(above, &done);
+
+  // Exponent in rage 63..83.
+  // Mantissa * 2^exponent contains bits in the range 2^0..2^31, namely
+  // the least significant exponent-52 bits.
+
+  // Negate low bits of mantissa if value is negative.
+  __ addq(double_value, double_value);  // Move sign bit to carry.
+  __ sbbl(result, result);  // And convert carry to -1 in result register.
+  // if scratch2 is negative, do (scratch2-1)^-1, otherwise (scratch2-0)^0.
+  __ addl(double_value, result);
+  // Do xor in opposite directions depending on where we want the result
+  // (depending on whether result is rcx or not).
+
+  if (result.is(rcx)) {
+    __ xorl(double_value, result);
+    // Left shift mantissa by (exponent - mantissabits - 1) to save the
+    // bits that have positional values below 2^32 (the extra -1 comes from the
+    // doubling done above to move the sign bit into the carry flag).
+    __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1));
+    __ shll_cl(double_value);
+    __ movl(result, double_value);
   } else {
-    // Load rcx with zero.  We use this either for the final shift or
-    // for the answer.
-    __ xor_(rcx, rcx);
-    // Check whether the exponent matches a 32 bit signed int that cannot be
-    // represented by a Smi.  A non-smi 32 bit integer is 1.xxx * 2^30 so the
-    // exponent is 30 (biased).  This is the exponent that we are fastest at and
-    // also the highest exponent we can handle here.
-    const uint32_t non_smi_exponent =
-        (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift;
-    __ cmpl(scratch2, Immediate(non_smi_exponent));
-    // If we have a match of the int32-but-not-Smi exponent then skip some
-    // logic.
-    __ j(equal, &right_exponent);
-    // If the exponent is higher than that then go to slow case.  This catches
-    // numbers that don't fit in a signed int32, infinities and NaNs.
-    __ j(less, &normal_exponent);
-
-    {
-      // Handle a big exponent.  The only reason we have this code is that the
-      // >>> operator has a tendency to generate numbers with an exponent of 31.
-      const uint32_t big_non_smi_exponent =
-          (HeapNumber::kExponentBias + 31) << HeapNumber::kExponentShift;
-      __ cmpl(scratch2, Immediate(big_non_smi_exponent));
-      __ j(not_equal, conversion_failure);
-      // We have the big exponent, typically from >>>.  This means the number is
-      // in the range 2^31 to 2^32 - 1.  Get the top bits of the mantissa.
-      __ movl(scratch2, scratch);
-      __ and_(scratch2, Immediate(HeapNumber::kMantissaMask));
-      // Put back the implicit 1.
-      __ or_(scratch2, Immediate(1 << HeapNumber::kExponentShift));
-      // Shift up the mantissa bits to take up the space the exponent used to
-      // take. We just orred in the implicit bit so that took care of one and
-      // we want to use the full unsigned range so we subtract 1 bit from the
-      // shift distance.
-      const int big_shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 1;
-      __ shl(scratch2, Immediate(big_shift_distance));
-      // Get the second half of the double.
-      __ movl(rcx, FieldOperand(source, HeapNumber::kMantissaOffset));
-      // Shift down 21 bits to get the most significant 11 bits or the low
-      // mantissa word.
-      __ shr(rcx, Immediate(32 - big_shift_distance));
-      __ or_(rcx, scratch2);
-      // We have the answer in rcx, but we may need to negate it.
-      __ testl(scratch, scratch);
-      __ j(positive, &done);
-      __ neg(rcx);
-      __ jmp(&done);
-    }
-
-    __ bind(&normal_exponent);
-    // Exponent word in scratch, exponent part of exponent word in scratch2.
-    // Zero in rcx.
-    // We know the exponent is smaller than 30 (biased).  If it is less than
-    // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, ie
-    // it rounds to zero.
-    const uint32_t zero_exponent =
-        (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift;
-    __ subl(scratch2, Immediate(zero_exponent));
-    // rcx already has a Smi zero.
-    __ j(less, &done);
-
-    // We have a shifted exponent between 0 and 30 in scratch2.
-    __ shr(scratch2, Immediate(HeapNumber::kExponentShift));
-    __ movl(rcx, Immediate(30));
-    __ subl(rcx, scratch2);
-
-    __ bind(&right_exponent);
-    // Here rcx is the shift, scratch is the exponent word.
-    // Get the top bits of the mantissa.
-    __ and_(scratch, Immediate(HeapNumber::kMantissaMask));
-    // Put back the implicit 1.
-    __ or_(scratch, Immediate(1 << HeapNumber::kExponentShift));
-    // Shift up the mantissa bits to take up the space the exponent used to
-    // take. We have kExponentShift + 1 significant bits int he low end of the
-    // word.  Shift them to the top bits.
-    const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2;
-    __ shl(scratch, Immediate(shift_distance));
-    // Get the second half of the double. For some exponents we don't
-    // actually need this because the bits get shifted out again, but
-    // it's probably slower to test than just to do it.
-    __ movl(scratch2, FieldOperand(source, HeapNumber::kMantissaOffset));
-    // Shift down 22 bits to get the most significant 10 bits or the low
-    // mantissa word.
-    __ shr(scratch2, Immediate(32 - shift_distance));
-    __ or_(scratch2, scratch);
-    // Move down according to the exponent.
-    __ shr_cl(scratch2);
-    // Now the unsigned answer is in scratch2.  We need to move it to rcx and
-    // we may need to fix the sign.
-    Label negative;
-    __ xor_(rcx, rcx);
-    __ cmpl(rcx, FieldOperand(source, HeapNumber::kExponentOffset));
-    __ j(greater, &negative);
-    __ movl(rcx, scratch2);
-    __ jmp(&done);
-    __ bind(&negative);
-    __ subl(rcx, scratch2);
-    __ bind(&done);
+    // As the then-branch, but move double-value to result before shifting.
+    __ xorl(result, double_value);
+    __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1));
+    __ shll_cl(result);
   }
+
+  __ bind(&done);
 }
 
 
@@ -8015,14 +8143,11 @@
     __ j(not_equal, &slow);
 
     // Convert the heap number in rax to an untagged integer in rcx.
-    IntegerConvert(masm, rax, CpuFeatures::IsSupported(SSE3), &slow);
+    IntegerConvert(masm, rax, rax);
 
-    // Do the bitwise operation and check if the result fits in a smi.
-    Label try_float;
-    __ not_(rcx);
-    // Tag the result as a smi and we're done.
-    ASSERT(kSmiTagSize == 1);
-    __ Integer32ToSmi(rax, rcx);
+    // Do the bitwise operation and smi tag the result.
+    __ notl(rax);
+    __ Integer32ToSmi(rax, rax);
   }
 
   // Return from the stub.
@@ -8795,6 +8920,9 @@
   //   rsp[0] : return address
   //   rsp[1] : function pointer
   //   rsp[2] : value
+  // Returns a bitwise zero to indicate that the value
+  // is and instance of the function and anything else to
+  // indicate that the value is not an instance.
 
   // Get the object - go slow case if it's a smi.
   Label slow;
@@ -8809,6 +8937,18 @@
 
   // Get the prototype of the function.
   __ movq(rdx, Operand(rsp, 1 * kPointerSize));
+  // rdx is function, rax is map.
+
+  // Look up the function and the map in the instanceof cache.
+  Label miss;
+  __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
+  __ j(not_equal, &miss);
+  __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex);
+  __ j(not_equal, &miss);
+  __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
+  __ ret(2 * kPointerSize);
+
+  __ bind(&miss);
   __ TryGetFunctionPrototype(rdx, rbx, &slow);
 
   // Check that the function prototype is a JS object.
@@ -8818,7 +8958,13 @@
   __ CmpInstanceType(kScratchRegister, LAST_JS_OBJECT_TYPE);
   __ j(above, &slow);
 
-  // Register mapping: rax is object map and rbx is function prototype.
+  // Register mapping:
+  //   rax is object map.
+  //   rdx is function.
+  //   rbx is function prototype.
+  __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
+  __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex);
+
   __ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset));
 
   // Loop through the prototype chain looking for the function prototype.
@@ -8828,6 +8974,8 @@
   __ cmpq(rcx, rbx);
   __ j(equal, &is_instance);
   __ cmpq(rcx, kScratchRegister);
+  // The code at is_not_instance assumes that kScratchRegister contains a
+  // non-zero GCable value (the null object in this case).
   __ j(equal, &is_not_instance);
   __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
   __ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset));
@@ -8835,10 +8983,14 @@
 
   __ bind(&is_instance);
   __ xorl(rax, rax);
+  // Store bitwise zero in the cache.  This is a Smi in GC terms.
+  ASSERT_EQ(0, kSmiTag);
+  __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
   __ ret(2 * kPointerSize);
 
   __ bind(&is_not_instance);
-  __ movl(rax, Immediate(1));
+  // We have to store a non-zero value in the cache.
+  __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex);
   __ ret(2 * kPointerSize);
 
   // Slow-case: Go through the JavaScript implementation.
@@ -8930,7 +9082,7 @@
   __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi);
   __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex);
   __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
-  __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
+  __ movl(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
 
   // Copy the fixed array slots.
   Label loop;
@@ -9569,7 +9721,6 @@
 // Input: rdx, rax are the left and right objects of a bit op.
 // Output: rax, rcx are left and right integers for a bit op.
 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
-                                         bool use_sse3,
                                          Label* conversion_failure) {
   // Check float operands.
   Label arg1_is_object, check_undefined_arg1;
@@ -9592,10 +9743,9 @@
   __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex);
   __ j(not_equal, &check_undefined_arg1);
   // Get the untagged integer version of the edx heap number in rcx.
-  IntegerConvert(masm, rdx, use_sse3, conversion_failure);
-  __ movl(rdx, rcx);
+  IntegerConvert(masm, rdx, rdx);
 
-  // Here edx has the untagged integer, eax has a Smi or a heap number.
+  // Here rdx has the untagged integer, rax has a Smi or a heap number.
   __ bind(&load_arg2);
   // Test if arg2 is a Smi.
   __ JumpIfNotSmi(rax, &arg2_is_object);
@@ -9615,7 +9765,7 @@
   __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex);
   __ j(not_equal, &check_undefined_arg2);
   // Get the untagged integer version of the eax heap number in ecx.
-  IntegerConvert(masm, rax, use_sse3, conversion_failure);
+  IntegerConvert(masm, rcx, rax);
   __ bind(&done);
   __ movl(rax, rdx);
 }
@@ -9684,13 +9834,12 @@
   }
 
   OS::SNPrintF(Vector<char>(name_, len),
-               "GenericBinaryOpStub_%s_%s%s_%s%s_%s%s_%s",
+               "GenericBinaryOpStub_%s_%s%s_%s%s_%s_%s",
                op_name,
                overwrite_name,
                (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "",
                args_in_registers_ ? "RegArgs" : "StackArgs",
                args_reversed_ ? "_R" : "",
-               use_sse3_ ? "SSE3" : "SSE2",
                static_operands_type_.ToString(),
                BinaryOpIC::GetName(runtime_operands_type_));
   return name_;
@@ -9860,12 +10009,27 @@
     __ movq(left, Operand(rsp, 2 * kPointerSize));
   }
 
-  // 2. Smi check both operands. Skip the check for OR as it is better combined
-  // with the actual operation.
   Label not_smis;
-  if (op_ != Token::BIT_OR) {
-    Comment smi_check_comment(masm, "-- Smi check arguments");
-    __ JumpIfNotBothSmi(left, right, &not_smis);
+  // 2. Smi check both operands.
+  if (static_operands_type_.IsSmi()) {
+    // Skip smi check if we know that both arguments are smis.
+    if (FLAG_debug_code) {
+      __ AbortIfNotSmi(left, "Static type check claimed non-smi is smi.");
+      __ AbortIfNotSmi(right, "Static type check claimed non-smi is smi.");
+    }
+    if (op_ == Token::BIT_OR) {
+      // Handle OR here, since we do extra smi-checking in the or code below.
+      __ SmiOr(right, right, left);
+      GenerateReturn(masm);
+      return;
+    }
+  } else {
+    if (op_ != Token::BIT_OR) {
+      // Skip the check for OR as it is better combined with the
+      // actual operation.
+      Comment smi_check_comment(masm, "-- Smi check arguments");
+      __ JumpIfNotBothSmi(left, right, &not_smis);
+    }
   }
 
   // 3. Operands are both smis (except for OR), perform the operation leaving
@@ -9929,7 +10093,7 @@
           __ SmiShiftLogicalRight(left, left, right, slow);
           break;
         case Token::SHL:
-          __ SmiShiftLeft(left, left, right, slow);
+          __ SmiShiftLeft(left, left, right);
           break;
         default:
           UNREACHABLE();
@@ -9953,6 +10117,7 @@
     case Token::SUB:
     case Token::MUL:
     case Token::DIV: {
+      ASSERT(use_fp_on_smis.is_linked());
       __ bind(&use_fp_on_smis);
       if (op_ == Token::DIV) {
         __ movq(rdx, rax);
@@ -10107,7 +10272,7 @@
       case Token::SHL:
       case Token::SHR: {
         Label skip_allocation, non_smi_result;
-        FloatingPointHelper::LoadAsIntegers(masm, use_sse3_, &call_runtime);
+        FloatingPointHelper::LoadAsIntegers(masm, &call_runtime);
         switch (op_) {
           case Token::BIT_OR:  __ orl(rax, rcx); break;
           case Token::BIT_AND: __ andl(rax, rcx); break;
@@ -10118,7 +10283,7 @@
           default: UNREACHABLE();
         }
         if (op_ == Token::SHR) {
-          // Check if result is non-negative. This can only happen for a shift
+          // Check if result is negative. This can only happen for a shift
           // by zero, which also doesn't update the sign flag.
           __ testl(rax, rax);
           __ j(negative, &non_smi_result);
diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h
index 5d9861b..01bbd20 100644
--- a/src/x64/codegen-x64.h
+++ b/src/x64/codegen-x64.h
@@ -28,7 +28,9 @@
 #ifndef V8_X64_CODEGEN_X64_H_
 #define V8_X64_CODEGEN_X64_H_
 
+#include "ast.h"
 #include "ic-inl.h"
+#include "jump-target-heavy.h"
 
 namespace v8 {
 namespace internal {
@@ -433,6 +435,16 @@
                                            TypeofState typeof_state,
                                            JumpTarget* slow);
 
+  // Support for loading from local/global variables and arguments
+  // whose location is known unless they are shadowed by
+  // eval-introduced bindings. Generates no code for unsupported slot
+  // types and therefore expects to fall through to the slow jump target.
+  void EmitDynamicLoadFromSlotFastCase(Slot* slot,
+                                       TypeofState typeof_state,
+                                       Result* result,
+                                       JumpTarget* slow,
+                                       JumpTarget* done);
+
   // Store the value on top of the expression stack into a slot, leaving the
   // value in place.
   void StoreToSlot(Slot* slot, InitState init_state);
@@ -711,7 +723,6 @@
         static_operands_type_(operands_type),
         runtime_operands_type_(BinaryOpIC::DEFAULT),
         name_(NULL) {
-    use_sse3_ = CpuFeatures::IsSupported(SSE3);
     ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
   }
 
@@ -721,7 +732,6 @@
         flags_(FlagBits::decode(key)),
         args_in_registers_(ArgsInRegistersBits::decode(key)),
         args_reversed_(ArgsReversedBits::decode(key)),
-        use_sse3_(SSE3Bits::decode(key)),
         static_operands_type_(TypeInfo::ExpandedRepresentation(
             StaticTypeInfoBits::decode(key))),
         runtime_operands_type_(type_info),
@@ -746,7 +756,6 @@
   GenericBinaryFlags flags_;
   bool args_in_registers_;  // Arguments passed in registers not on the stack.
   bool args_reversed_;  // Left and right argument are swapped.
-  bool use_sse3_;
 
   // Number type information of operands, determined by code generator.
   TypeInfo static_operands_type_;
@@ -772,15 +781,14 @@
   }
 #endif
 
-  // Minor key encoding in 18 bits TTNNNFRASOOOOOOOMM.
+  // Minor key encoding in 17 bits TTNNNFRAOOOOOOOMM.
   class ModeBits: public BitField<OverwriteMode, 0, 2> {};
   class OpBits: public BitField<Token::Value, 2, 7> {};
-  class SSE3Bits: public BitField<bool, 9, 1> {};
-  class ArgsInRegistersBits: public BitField<bool, 10, 1> {};
-  class ArgsReversedBits: public BitField<bool, 11, 1> {};
-  class FlagBits: public BitField<GenericBinaryFlags, 12, 1> {};
-  class StaticTypeInfoBits: public BitField<int, 13, 3> {};
-  class RuntimeTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 16, 2> {};
+  class ArgsInRegistersBits: public BitField<bool, 9, 1> {};
+  class ArgsReversedBits: public BitField<bool, 10, 1> {};
+  class FlagBits: public BitField<GenericBinaryFlags, 11, 1> {};
+  class StaticTypeInfoBits: public BitField<int, 12, 3> {};
+  class RuntimeTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 15, 2> {};
 
   Major MajorKey() { return GenericBinaryOp; }
   int MinorKey() {
@@ -788,7 +796,6 @@
     return OpBits::encode(op_)
            | ModeBits::encode(mode_)
            | FlagBits::encode(flags_)
-           | SSE3Bits::encode(use_sse3_)
            | ArgsInRegistersBits::encode(args_in_registers_)
            | ArgsReversedBits::encode(args_reversed_)
            | StaticTypeInfoBits::encode(
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index a1976ec..f9b444b 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -50,6 +50,11 @@
 }
 
 
+void MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) {
+  movq(Operand(kRootRegister, index << kPointerSizeLog2), source);
+}
+
+
 void MacroAssembler::PushRoot(Heap::RootListIndex index) {
   push(Operand(kRootRegister, index << kPointerSizeLog2));
 }
@@ -1227,8 +1232,7 @@
 
 void MacroAssembler::SmiShiftLeftConstant(Register dst,
                                           Register src,
-                                          int shift_value,
-                                          Label* on_not_smi_result) {
+                                          int shift_value) {
   if (!dst.is(src)) {
     movq(dst, src);
   }
@@ -1240,8 +1244,7 @@
 
 void MacroAssembler::SmiShiftLeft(Register dst,
                                   Register src1,
-                                  Register src2,
-                                  Label* on_not_smi_result) {
+                                  Register src2) {
   ASSERT(!dst.is(rcx));
   Label result_ok;
   // Untag shift amount.
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 32e1f49..2eeb1fd 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -33,6 +33,17 @@
 namespace v8 {
 namespace internal {
 
+// Flags used for the AllocateInNewSpace functions.
+enum AllocationFlags {
+  // No special flags.
+  NO_ALLOCATION_FLAGS = 0,
+  // Return the pointer to the allocated already tagged as a heap object.
+  TAG_OBJECT = 1 << 0,
+  // The content of the result register already contains the allocation top in
+  // new space.
+  RESULT_CONTAINS_TOP = 1 << 1
+};
+
 // Default scratch register used by MacroAssembler (and other code that needs
 // a spare register). The register isn't callee save, and not used by the
 // function calling convention.
@@ -62,6 +73,7 @@
   void CompareRoot(Register with, Heap::RootListIndex index);
   void CompareRoot(Operand with, Heap::RootListIndex index);
   void PushRoot(Heap::RootListIndex index);
+  void StoreRoot(Register source, Heap::RootListIndex index);
 
   // ---------------------------------------------------------------------------
   // GC Support
@@ -374,8 +386,7 @@
 
   void SmiShiftLeftConstant(Register dst,
                             Register src,
-                            int shift_value,
-                            Label* on_not_smi_result);
+                            int shift_value);
   void SmiShiftLogicalRightConstant(Register dst,
                                   Register src,
                                   int shift_value,
@@ -388,8 +399,7 @@
   // Uses and clobbers rcx, so dst may not be rcx.
   void SmiShiftLeft(Register dst,
                     Register src1,
-                    Register src2,
-                    Label* on_not_smi_result);
+                    Register src2);
   // Shifts a smi value to the right, shifting in zero bits at the top, and
   // returns the unsigned intepretation of the result if that is a smi.
   // Uses and clobbers rcx, so dst may not be rcx.
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index 50b4120..d9b75b1 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -188,8 +188,8 @@
 void RegExpMacroAssemblerX64::CheckAtStart(Label* on_at_start) {
   Label not_at_start;
   // Did we start the match at the start of the string at all?
-  __ cmpb(Operand(rbp, kAtStart), Immediate(0));
-  BranchOrBacktrack(equal, &not_at_start);
+  __ cmpb(Operand(rbp, kStartIndex), Immediate(0));
+  BranchOrBacktrack(not_equal, &not_at_start);
   // If we did, are we still at the start of the input?
   __ lea(rax, Operand(rsi, rdi, times_1, 0));
   __ cmpq(rax, Operand(rbp, kInputStart));
@@ -200,8 +200,8 @@
 
 void RegExpMacroAssemblerX64::CheckNotAtStart(Label* on_not_at_start) {
   // Did we start the match at the start of the string at all?
-  __ cmpb(Operand(rbp, kAtStart), Immediate(0));
-  BranchOrBacktrack(equal, on_not_at_start);
+  __ cmpb(Operand(rbp, kStartIndex), Immediate(0));
+  BranchOrBacktrack(not_equal, on_not_at_start);
   // If we did, are we still at the start of the input?
   __ lea(rax, Operand(rsi, rdi, times_1, 0));
   __ cmpq(rax, Operand(rbp, kInputStart));
@@ -219,6 +219,15 @@
                                               int cp_offset,
                                               Label* on_failure,
                                               bool check_end_of_string) {
+#ifdef DEBUG
+  // If input is ASCII, don't even bother calling here if the string to
+  // match contains a non-ascii character.
+  if (mode_ == ASCII) {
+    for (int i = 0; i < str.length(); i++) {
+      ASSERT(str[i] <= String::kMaxAsciiCharCodeU);
+    }
+  }
+#endif
   int byte_length = str.length() * char_size();
   int byte_offset = cp_offset * char_size();
   if (check_end_of_string) {
@@ -232,16 +241,71 @@
     on_failure = &backtrack_label_;
   }
 
-  // TODO(lrn): Test multiple characters at a time by loading 4 or 8 bytes
-  // at a time.
-  for (int i = 0; i < str.length(); i++) {
+  // Do one character test first to minimize loading for the case that
+  // we don't match at all (loading more than one character introduces that
+  // chance of reading unaligned and reading across cache boundaries).
+  // If the first character matches, expect a larger chance of matching the
+  // string, and start loading more characters at a time.
+  if (mode_ == ASCII) {
+    __ cmpb(Operand(rsi, rdi, times_1, byte_offset),
+            Immediate(static_cast<int8_t>(str[0])));
+  } else {
+    // Don't use 16-bit immediate. The size changing prefix throws off
+    // pre-decoding.
+    __ movzxwl(rax,
+               Operand(rsi, rdi, times_1, byte_offset));
+    __ cmpl(rax, Immediate(static_cast<int32_t>(str[0])));
+  }
+  BranchOrBacktrack(not_equal, on_failure);
+
+  __ lea(rbx, Operand(rsi, rdi, times_1, 0));
+  for (int i = 1, n = str.length(); i < n; ) {
     if (mode_ == ASCII) {
-      __ cmpb(Operand(rsi, rdi, times_1, byte_offset + i),
-              Immediate(static_cast<int8_t>(str[i])));
+      if (i + 8 <= n) {
+        uint64_t combined_chars =
+            (static_cast<uint64_t>(str[i + 0]) << 0) ||
+            (static_cast<uint64_t>(str[i + 1]) << 8) ||
+            (static_cast<uint64_t>(str[i + 2]) << 16) ||
+            (static_cast<uint64_t>(str[i + 3]) << 24) ||
+            (static_cast<uint64_t>(str[i + 4]) << 32) ||
+            (static_cast<uint64_t>(str[i + 5]) << 40) ||
+            (static_cast<uint64_t>(str[i + 6]) << 48) ||
+            (static_cast<uint64_t>(str[i + 7]) << 56);
+        __ movq(rax, combined_chars, RelocInfo::NONE);
+        __ cmpq(rax, Operand(rbx, byte_offset + i));
+        i += 8;
+      } else if (i + 4 <= n) {
+        uint32_t combined_chars =
+            (static_cast<uint32_t>(str[i + 0]) << 0) ||
+            (static_cast<uint32_t>(str[i + 1]) << 8) ||
+            (static_cast<uint32_t>(str[i + 2]) << 16) ||
+            (static_cast<uint32_t>(str[i + 3]) << 24);
+        __ cmpl(Operand(rbx, byte_offset + i), Immediate(combined_chars));
+        i += 4;
+      } else {
+        __ cmpb(Operand(rbx, byte_offset + i),
+                Immediate(static_cast<int8_t>(str[i])));
+        i++;
+      }
     } else {
       ASSERT(mode_ == UC16);
-      __ cmpw(Operand(rsi, rdi, times_1, byte_offset + i * sizeof(uc16)),
-              Immediate(str[i]));
+      if (i + 4 <= n) {
+        uint64_t combined_chars = *reinterpret_cast<const uint64_t*>(&str[i]);
+        __ movq(rax, combined_chars, RelocInfo::NONE);
+        __ cmpq(rax,
+                Operand(rsi, rdi, times_1, byte_offset + i * sizeof(uc16)));
+        i += 4;
+      } else if (i + 2 <= n) {
+        uint32_t combined_chars = *reinterpret_cast<const uint32_t*>(&str[i]);
+        __ cmpl(Operand(rsi, rdi, times_1, byte_offset + i * sizeof(uc16)),
+                Immediate(combined_chars));
+        i += 2;
+      } else {
+        __ movzxwl(rax,
+                   Operand(rsi, rdi, times_1, byte_offset + i * sizeof(uc16)));
+        __ cmpl(rax, Immediate(str[i]));
+        i++;
+      }
     }
     BranchOrBacktrack(not_equal, on_failure);
   }
@@ -671,7 +735,6 @@
   __ push(rbx);  // Callee-save
 #endif
 
-  __ push(Immediate(0));  // Make room for "input start - 1" constant.
   __ push(Immediate(0));  // Make room for "at start" constant.
 
   // Check if we have space on the stack for registers.
@@ -724,14 +787,6 @@
   // position registers.
   __ movq(Operand(rbp, kInputStartMinusOne), rax);
 
-  // Determine whether the start index is zero, that is at the start of the
-  // string, and store that value in a local variable.
-  __ movq(rbx, Operand(rbp, kStartIndex));
-  __ xor_(rcx, rcx);  // setcc only operates on cl (lower byte of rcx).
-  __ testq(rbx, rbx);
-  __ setcc(zero, rcx);  // 1 if 0 (start of string), 0 if positive.
-  __ movq(Operand(rbp, kAtStart), rcx);
-
   if (num_saved_registers_ > 0) {
     // Fill saved registers with initial value = start offset - 1
     // Fill in stack push order, to avoid accessing across an unwritten
@@ -761,8 +816,8 @@
   __ Move(code_object_pointer(), masm_->CodeObject());
   // Load previous char as initial value of current-character.
   Label at_start;
-  __ cmpb(Operand(rbp, kAtStart), Immediate(0));
-  __ j(not_equal, &at_start);
+  __ cmpb(Operand(rbp, kStartIndex), Immediate(0));
+  __ j(equal, &at_start);
   LoadCurrentCharacterUnchecked(-1, 1);  // Load previous char.
   __ jmp(&start_label_);
   __ bind(&at_start);
diff --git a/src/x64/regexp-macro-assembler-x64.h b/src/x64/regexp-macro-assembler-x64.h
index 4903269..3bcc3ac 100644
--- a/src/x64/regexp-macro-assembler-x64.h
+++ b/src/x64/regexp-macro-assembler-x64.h
@@ -173,10 +173,9 @@
   // the frame in GetCode.
   static const int kInputStartMinusOne =
       kLastCalleeSaveRegister - kPointerSize;
-  static const int kAtStart = kInputStartMinusOne - kPointerSize;
 
   // First register address. Following registers are below it on the stack.
-  static const int kRegisterZero = kAtStart - kPointerSize;
+  static const int kRegisterZero = kInputStartMinusOne - kPointerSize;
 
   // Initial size of code buffer.
   static const size_t kRegExpCodeSize = 1024;
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 7d4410c..384bca1 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -870,9 +870,9 @@
 
   SharedFunctionInfo* function_info = function->shared();
   if (function_info->HasCustomCallGenerator()) {
-    CustomCallGenerator generator =
-        ToCData<CustomCallGenerator>(function_info->function_data());
-    Object* result = generator(this, object, holder, function, name, check);
+    const int id = function_info->custom_call_generator_id();
+    Object* result =
+        CompileCustomCall(id, object, holder, function, name, check);
     // undefined means bail out to regular compiler.
     if (!result->IsUndefined()) {
       return result;
@@ -1007,11 +1007,7 @@
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
@@ -1198,7 +1194,7 @@
       __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
 
       // Increment element's and array's sizes.
-      __ addq(FieldOperand(rbx, FixedArray::kLengthOffset),
+      __ addl(FieldOperand(rbx, FixedArray::kLengthOffset),
               Immediate(kAllocationDelta));
       __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax);
 
@@ -1219,11 +1215,7 @@
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
@@ -1308,11 +1300,7 @@
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  String* function_name = NULL;
-  if (function->shared()->name()->IsString()) {
-    function_name = String::cast(function->shared()->name());
-  }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCode(function);
 }
 
 
diff --git a/src/x64/virtual-frame-x64.h b/src/x64/virtual-frame-x64.h
index 7cda181..529f47a 100644
--- a/src/x64/virtual-frame-x64.h
+++ b/src/x64/virtual-frame-x64.h
@@ -31,6 +31,7 @@
 #include "type-info.h"
 #include "register-allocator.h"
 #include "scopes.h"
+#include "codegen.h"
 
 namespace v8 {
 namespace internal {
@@ -98,23 +99,16 @@
     return register_locations_[num];
   }
 
-  int register_location(Register reg) {
-    return register_locations_[RegisterAllocator::ToNumber(reg)];
-  }
+  inline int register_location(Register reg);
 
-  void set_register_location(Register reg, int index) {
-    register_locations_[RegisterAllocator::ToNumber(reg)] = index;
-  }
+  inline void set_register_location(Register reg, int index);
 
   bool is_used(int num) {
     ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
     return register_locations_[num] != kIllegalIndex;
   }
 
-  bool is_used(Register reg) {
-    return register_locations_[RegisterAllocator::ToNumber(reg)]
-        != kIllegalIndex;
-  }
+  inline bool is_used(Register reg);
 
   // Add extra in-memory elements to the top of the frame to match an actual
   // frame (eg, the frame after an exception handler is pushed).  No code is
@@ -218,10 +212,7 @@
   void SetElementAt(int index, Result* value);
 
   // Set a frame element to a constant.  The index is frame-top relative.
-  void SetElementAt(int index, Handle<Object> value) {
-    Result temp(value);
-    SetElementAt(index, &temp);
-  }
+  inline void SetElementAt(int index, Handle<Object> value);
 
   void PushElementAt(int index) {
     PushFrameSlotAt(element_count() - index - 1);
@@ -302,10 +293,7 @@
 
   // Call stub given the number of arguments it expects on (and
   // removes from) the stack.
-  Result CallStub(CodeStub* stub, int arg_count) {
-    PrepareForCall(arg_count, arg_count);
-    return RawCallStub(stub);
-  }
+  inline Result CallStub(CodeStub* stub, int arg_count);
 
   // Call stub that takes a single argument passed in eax.  The
   // argument is given as a result which does not have to be eax or
@@ -446,8 +434,8 @@
   int register_locations_[RegisterAllocator::kNumRegisters];
 
   // The number of frame-allocated locals and parameters respectively.
-  int parameter_count() { return cgen()->scope()->num_parameters(); }
-  int local_count() { return cgen()->scope()->num_stack_slots(); }
+  inline int parameter_count();
+  inline int local_count();
 
   // The index of the element that is at the processor's frame pointer
   // (the ebp register).  The parameters, receiver, and return address