Update V8 to r5091 as required by WebKit r63859.

Change-Id: I8e35d765e6f6c7f89eccff900e1cabe2d5dd6110
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index f5ff43a..0dc6b77 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -1801,11 +1801,119 @@
 }
 
 
+static void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
+  uint64_t i;
+  memcpy(&i, &d, 8);
+
+  *lo = i & 0xffffffff;
+  *hi = i >> 32;
+}
+
+// Only works for little endian floating point formats.
+// We don't support VFP on the mixed endian floating point platform.
+static bool FitsVMOVDoubleImmediate(double d, uint32_t *encoding) {
+  ASSERT(CpuFeatures::IsEnabled(VFP3));
+
+  // VMOV can accept an immediate of the form:
+  //
+  //  +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7
+  //
+  // The immediate is encoded using an 8-bit quantity, comprised of two
+  // 4-bit fields. For an 8-bit immediate of the form:
+  //
+  //  [abcdefgh]
+  //
+  // where a is the MSB and h is the LSB, an immediate 64-bit double can be
+  // created of the form:
+  //
+  //  [aBbbbbbb,bbcdefgh,00000000,00000000,
+  //      00000000,00000000,00000000,00000000]
+  //
+  // where B = ~b.
+  //
+
+  uint32_t lo, hi;
+  DoubleAsTwoUInt32(d, &lo, &hi);
+
+  // The most obvious constraint is the long block of zeroes.
+  if ((lo != 0) || ((hi & 0xffff) != 0)) {
+    return false;
+  }
+
+  // Bits 62:55 must be all clear or all set.
+  if (((hi & 0x3fc00000) != 0) && ((hi & 0x3fc00000) != 0x3fc00000)) {
+    return false;
+  }
+
+  // Bit 63 must be NOT bit 62.
+  if (((hi ^ (hi << 1)) & (0x40000000)) == 0) {
+    return false;
+  }
+
+  // Create the encoded immediate in the form:
+  //  [00000000,0000abcd,00000000,0000efgh]
+  *encoding  = (hi >> 16) & 0xf;      // Low nybble.
+  *encoding |= (hi >> 4) & 0x70000;   // Low three bits of the high nybble.
+  *encoding |= (hi >> 12) & 0x80000;  // Top bit of the high nybble.
+
+  return true;
+}
+
+
+void Assembler::vmov(const DwVfpRegister dst,
+                     double imm,
+                     const Condition cond) {
+  // Dd = immediate
+  // Instruction details available in ARM DDI 0406B, A8-640.
+  ASSERT(CpuFeatures::IsEnabled(VFP3));
+
+  uint32_t enc;
+  if (FitsVMOVDoubleImmediate(imm, &enc)) {
+    // The double can be encoded in the instruction.
+    emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | 0xB*B8 | enc);
+  } else {
+    // Synthesise the double from ARM immediates. This could be implemented
+    // using vldr from a constant pool.
+    uint32_t lo, hi;
+    DoubleAsTwoUInt32(imm, &lo, &hi);
+
+    if (lo == hi) {
+      // If the lo and hi parts of the double are equal, the literal is easier
+      // to create. This is the case with 0.0.
+      mov(ip, Operand(lo));
+      vmov(dst, ip, ip);
+    } else {
+      // Move the low part of the double into the lower of the corresponsing S
+      // registers of D register dst.
+      mov(ip, Operand(lo));
+      vmov(dst.low(), ip, cond);
+
+      // Move the high part of the double into the higher of the corresponsing S
+      // registers of D register dst.
+      mov(ip, Operand(hi));
+      vmov(dst.high(), ip, cond);
+    }
+  }
+}
+
+
+void Assembler::vmov(const SwVfpRegister dst,
+                     const SwVfpRegister src,
+                     const Condition cond) {
+  // Sd = Sm
+  // Instruction details available in ARM DDI 0406B, A8-642.
+  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  emit(cond | 0xE*B24 | 0xB*B20 |
+       dst.code()*B12 | 0x5*B9 | B6 | src.code());
+}
+
+
 void Assembler::vmov(const DwVfpRegister dst,
                      const DwVfpRegister src,
                      const Condition cond) {
   // Dd = Dm
   // Instruction details available in ARM DDI 0406B, A8-642.
+  ASSERT(CpuFeatures::IsEnabled(VFP3));
   emit(cond | 0xE*B24 | 0xB*B20 |
        dst.code()*B12 | 0x5*B9 | B8 | B6 | src.code());
 }
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 6a4fb23..226fb87 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -130,6 +130,20 @@
   // Supporting d0 to d15, can be later extended to d31.
   bool is_valid() const  { return 0 <= code_ && code_ < 16; }
   bool is(DwVfpRegister reg) const  { return code_ == reg.code_; }
+  SwVfpRegister low() const  {
+    SwVfpRegister reg;
+    reg.code_ = code_ * 2;
+
+    ASSERT(reg.is_valid());
+    return reg;
+  }
+  SwVfpRegister high() const  {
+    SwVfpRegister reg;
+    reg.code_ = (code_ * 2) + 1;
+
+    ASSERT(reg.is_valid());
+    return reg;
+  }
   int code() const  {
     ASSERT(is_valid());
     return code_;
@@ -932,6 +946,12 @@
             const Condition cond = al);
 
   void vmov(const DwVfpRegister dst,
+            double imm,
+            const Condition cond = al);
+  void vmov(const SwVfpRegister dst,
+            const SwVfpRegister src,
+            const Condition cond = al);
+  void vmov(const DwVfpRegister dst,
             const DwVfpRegister src,
             const Condition cond = al);
   void vmov(const DwVfpRegister dst,
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index fa6efcd..0b2081b 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -54,11 +54,15 @@
                                           Condition cc,
                                           bool never_nan_nan);
 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
+                                    Register lhs,
+                                    Register rhs,
                                     Label* lhs_not_nan,
                                     Label* slow,
                                     bool strict);
 static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc);
-static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm);
+static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
+                                           Register lhs,
+                                           Register rhs);
 static void MultiplyByKnownInt(MacroAssembler* masm,
                                Register source,
                                Register destination,
@@ -1404,11 +1408,7 @@
     // Perform non-smi comparison by stub.
     // CompareStub takes arguments in r0 and r1, returns <0, >0 or 0 in r0.
     // We call with 0 args because there are 0 on the stack.
-    if (!rhs.is(r0)) {
-      __ Swap(rhs, lhs, ip);
-    }
-
-    CompareStub stub(cc, strict);
+    CompareStub stub(cc, strict, kBothCouldBeNaN, true, lhs, rhs);
     frame_->CallStub(&stub, 0);
     __ cmp(r0, Operand(0));
     exit.Jump();
@@ -4343,9 +4343,7 @@
     __ bind(&powi);
 
     // Load 1.0 into d0.
-    __ mov(scratch2, Operand(0x3ff00000));
-    __ mov(scratch1, Operand(0));
-    __ vmov(d0, scratch1, scratch2);
+    __ vmov(d0, 1.0);
 
     // Get the absolute untagged value of the exponent and use that for the
     // calculation.
@@ -4405,9 +4403,7 @@
                                  AVOID_NANS_AND_INFINITIES);
 
     // Load 1.0 into d2.
-    __ mov(scratch2, Operand(0x3ff00000));
-    __ mov(scratch1, Operand(0));
-    __ vmov(d2, scratch1, scratch2);
+    __ vmov(d2, 1.0);
 
     // Calculate the reciprocal of the square root. 1/sqrt(x) = sqrt(1/x).
     __ vdiv(d0, d2, d0);
@@ -4764,6 +4760,24 @@
 }
 
 
+void CodeGenerator::GenerateIsSpecObject(ZoneList<Expression*>* args) {
+  // This generates a fast version of:
+  // (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp' ||
+  // typeof(arg) == function).
+  // It includes undetectable objects (as opposed to IsObject).
+  ASSERT(args->length() == 1);
+  Load(args->at(0));
+  Register value = frame_->PopToRegister();
+  __ tst(value, Operand(kSmiTagMask));
+  false_target()->Branch(eq);
+  // Check that this is an object.
+  __ ldr(value, FieldMemOperand(value, HeapObject::kMapOffset));
+  __ ldrb(value, FieldMemOperand(value, Map::kInstanceTypeOffset));
+  __ cmp(value, Operand(FIRST_JS_OBJECT_TYPE));
+  cc_reg_ = ge;
+}
+
+
 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
   // This generates a fast version of:
   // (%_ClassOf(arg) === 'Function')
@@ -4874,12 +4888,8 @@
   __ jmp(&heapnumber_allocated);
 
   __ bind(&slow_allocate_heapnumber);
-  // To allocate a heap number, and ensure that it is not a smi, we
-  // call the runtime function FUnaryMinus on 0, returning the double
-  // -0.0. A new, distinct heap number is returned each time.
-  __ mov(r0, Operand(Smi::FromInt(0)));
-  __ push(r0);
-  __ CallRuntime(Runtime::kNumberUnaryMinus, 1);
+  // Allocate a heap number.
+  __ CallRuntime(Runtime::kNumberAlloc, 0);
   __ mov(r4, Operand(r0));
 
   __ bind(&heapnumber_allocated);
@@ -6976,7 +6986,7 @@
             // undefined >= undefined should fail.
             __ mov(r0, Operand(LESS));
           }
-          __ mov(pc, Operand(lr));       // Return.
+          __ Ret();
         }
       }
     }
@@ -6990,7 +7000,7 @@
   } else {
     __ mov(r0, Operand(EQUAL));    // Things are <=, >=, ==, === themselves.
   }
-  __ mov(pc, Operand(lr));  // Return.
+  __ Ret();
 
   if (cc != eq || !never_nan_nan) {
     // For less and greater we don't have to check for NaN since the result of
@@ -7022,14 +7032,14 @@
       // value if it's a NaN.
       if (cc != eq) {
         // All-zero means Infinity means equal.
-        __ mov(pc, Operand(lr), LeaveCC, eq);  // Return equal
+        __ Ret(eq);
         if (cc == le) {
           __ mov(r0, Operand(GREATER));  // NaN <= NaN should fail.
         } else {
           __ mov(r0, Operand(LESS));     // NaN >= NaN should fail.
         }
       }
-      __ mov(pc, Operand(lr));  // Return.
+      __ Ret();
     }
     // No fall through here.
   }
@@ -7040,43 +7050,50 @@
 
 // See comment at call site.
 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
+                                    Register lhs,
+                                    Register rhs,
                                     Label* lhs_not_nan,
                                     Label* slow,
                                     bool strict) {
+  ASSERT((lhs.is(r0) && rhs.is(r1)) ||
+         (lhs.is(r1) && rhs.is(r0)));
+
   Label rhs_is_smi;
-  __ tst(r0, Operand(kSmiTagMask));
+  __ tst(rhs, Operand(kSmiTagMask));
   __ b(eq, &rhs_is_smi);
 
   // Lhs is a Smi.  Check whether the rhs is a heap number.
-  __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
+  __ CompareObjectType(rhs, r4, r4, HEAP_NUMBER_TYPE);
   if (strict) {
     // If rhs is not a number and lhs is a Smi then strict equality cannot
-    // succeed.  Return non-equal (r0 is already not zero)
-    __ mov(pc, Operand(lr), LeaveCC, ne);  // Return.
+    // succeed.  Return non-equal
+    // If rhs is r0 then there is already a non zero value in it.
+    if (!rhs.is(r0)) {
+      __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne);
+    }
+    __ Ret(ne);
   } else {
     // Smi compared non-strictly with a non-Smi non-heap-number.  Call
     // the runtime.
     __ b(ne, slow);
   }
 
-  // Lhs (r1) is a smi, rhs (r0) is a number.
+  // Lhs is a smi, rhs is a number.
   if (CpuFeatures::IsSupported(VFP3)) {
-    // Convert lhs to a double in d7              .
+    // Convert lhs to a double in d7.
     CpuFeatures::Scope scope(VFP3);
-    __ mov(r7, Operand(r1, ASR, kSmiTagSize));
-    __ vmov(s15, r7);
-    __ vcvt_f64_s32(d7, s15);
+    __ SmiToDoubleVFPRegister(lhs, d7, r7, s15);
     // Load the double from rhs, tagged HeapNumber r0, to d6.
-    __ sub(r7, r0, Operand(kHeapObjectTag));
+    __ sub(r7, rhs, Operand(kHeapObjectTag));
     __ vldr(d6, r7, HeapNumber::kValueOffset);
   } else {
     __ push(lr);
     // Convert lhs to a double in r2, r3.
-    __ mov(r7, Operand(r1));
+    __ mov(r7, Operand(lhs));
     ConvertToDoubleStub stub1(r3, r2, r7, r6);
     __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
     // Load rhs to a double in r0, r1.
-    __ Ldrd(r0, r1, FieldMemOperand(r0, HeapNumber::kValueOffset));
+    __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset));
     __ pop(lr);
   }
 
@@ -7086,34 +7103,35 @@
 
   __ bind(&rhs_is_smi);
   // Rhs is a smi.  Check whether the non-smi lhs is a heap number.
-  __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE);
+  __ CompareObjectType(lhs, r4, r4, HEAP_NUMBER_TYPE);
   if (strict) {
     // If lhs is not a number and rhs is a smi then strict equality cannot
     // succeed.  Return non-equal.
-    __ mov(r0, Operand(1), LeaveCC, ne);  // Non-zero indicates not equal.
-    __ mov(pc, Operand(lr), LeaveCC, ne);  // Return.
+    // If lhs is r0 then there is already a non zero value in it.
+    if (!lhs.is(r0)) {
+      __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne);
+    }
+    __ Ret(ne);
   } else {
     // Smi compared non-strictly with a non-smi non-heap-number.  Call
     // the runtime.
     __ b(ne, slow);
   }
 
-  // Rhs (r0) is a smi, lhs (r1) is a heap number.
+  // Rhs is a smi, lhs is a heap number.
   if (CpuFeatures::IsSupported(VFP3)) {
-    // Convert rhs to a double in d6              .
     CpuFeatures::Scope scope(VFP3);
     // Load the double from lhs, tagged HeapNumber r1, to d7.
-    __ sub(r7, r1, Operand(kHeapObjectTag));
+    __ sub(r7, lhs, Operand(kHeapObjectTag));
     __ vldr(d7, r7, HeapNumber::kValueOffset);
-    __ mov(r7, Operand(r0, ASR, kSmiTagSize));
-    __ vmov(s13, r7);
-    __ vcvt_f64_s32(d6, s13);
+    // Convert rhs to a double in d6              .
+    __ SmiToDoubleVFPRegister(rhs, d6, r7, s13);
   } else {
     __ push(lr);
     // Load lhs to a double in r2, r3.
-    __ Ldrd(r2, r3, FieldMemOperand(r1, HeapNumber::kValueOffset));
+    __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset));
     // Convert rhs to a double in r0, r1.
-    __ mov(r7, Operand(r0));
+    __ mov(r7, Operand(rhs));
     ConvertToDoubleStub stub2(r1, r0, r7, r6);
     __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET);
     __ pop(lr);
@@ -7167,7 +7185,7 @@
   } else {
     __ mov(r0, Operand(LESS));
   }
-  __ mov(pc, Operand(lr));  // Return.
+  __ Ret();
 
   __ bind(&neither_is_nan);
 }
@@ -7188,11 +7206,11 @@
     __ cmp(rhs_mantissa, Operand(lhs_mantissa));
     __ orr(r0, rhs_mantissa, Operand(lhs_mantissa), LeaveCC, ne);
     // Return non-zero if the numbers are unequal.
-    __ mov(pc, Operand(lr), LeaveCC, ne);
+    __ Ret(ne);
 
     __ sub(r0, rhs_exponent, Operand(lhs_exponent), SetCC);
     // If exponents are equal then return 0.
-    __ mov(pc, Operand(lr), LeaveCC, eq);
+    __ Ret(eq);
 
     // Exponents are unequal.  The only way we can return that the numbers
     // are equal is if one is -0 and the other is 0.  We already dealt
@@ -7202,11 +7220,11 @@
     // equal.
     __ orr(r4, lhs_mantissa, Operand(lhs_exponent, LSL, kSmiTagSize), SetCC);
     __ mov(r0, Operand(r4), LeaveCC, ne);
-    __ mov(pc, Operand(lr), LeaveCC, ne);  // Return conditionally.
+    __ Ret(ne);
     // Now they are equal if and only if the lhs exponent is zero in its
     // low 31 bits.
     __ mov(r0, Operand(rhs_exponent, LSL, kSmiTagSize));
-    __ mov(pc, Operand(lr));
+    __ Ret();
   } else {
     // Call a native function to do a comparison between two non-NaNs.
     // Call C routine that may not cause GC or other trouble.
@@ -7219,7 +7237,12 @@
 
 
 // See comment at call site.
-static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm) {
+static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
+                                           Register lhs,
+                                           Register rhs) {
+    ASSERT((lhs.is(r0) && rhs.is(r1)) ||
+           (lhs.is(r1) && rhs.is(r0)));
+
     // If either operand is a JSObject or an oddball value, then they are
     // not equal since their pointers are different.
     // There is no test for undetectability in strict equality.
@@ -7227,20 +7250,20 @@
     Label first_non_object;
     // Get the type of the first operand into r2 and compare it with
     // FIRST_JS_OBJECT_TYPE.
-    __ CompareObjectType(r0, r2, r2, FIRST_JS_OBJECT_TYPE);
+    __ CompareObjectType(rhs, r2, r2, FIRST_JS_OBJECT_TYPE);
     __ b(lt, &first_non_object);
 
     // Return non-zero (r0 is not zero)
     Label return_not_equal;
     __ bind(&return_not_equal);
-    __ mov(pc, Operand(lr));  // Return.
+    __ Ret();
 
     __ bind(&first_non_object);
     // Check for oddballs: true, false, null, undefined.
     __ cmp(r2, Operand(ODDBALL_TYPE));
     __ b(eq, &return_not_equal);
 
-    __ CompareObjectType(r1, r3, r3, FIRST_JS_OBJECT_TYPE);
+    __ CompareObjectType(lhs, r3, r3, FIRST_JS_OBJECT_TYPE);
     __ b(ge, &return_not_equal);
 
     // Check for oddballs: true, false, null, undefined.
@@ -7259,12 +7282,17 @@
 
 // See comment at call site.
 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
+                                       Register lhs,
+                                       Register rhs,
                                        Label* both_loaded_as_doubles,
                                        Label* not_heap_numbers,
                                        Label* slow) {
-  __ CompareObjectType(r0, r3, r2, HEAP_NUMBER_TYPE);
+  ASSERT((lhs.is(r0) && rhs.is(r1)) ||
+         (lhs.is(r1) && rhs.is(r0)));
+
+  __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE);
   __ b(ne, not_heap_numbers);
-  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset));
   __ cmp(r2, r3);
   __ b(ne, slow);  // First was a heap number, second wasn't.  Go slow case.
 
@@ -7272,13 +7300,13 @@
   // for that.
   if (CpuFeatures::IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
-    __ sub(r7, r0, Operand(kHeapObjectTag));
+    __ sub(r7, rhs, Operand(kHeapObjectTag));
     __ vldr(d6, r7, HeapNumber::kValueOffset);
-    __ sub(r7, r1, Operand(kHeapObjectTag));
+    __ sub(r7, lhs, Operand(kHeapObjectTag));
     __ vldr(d7, r7, HeapNumber::kValueOffset);
   } else {
-    __ Ldrd(r2, r3, FieldMemOperand(r1, HeapNumber::kValueOffset));
-    __ Ldrd(r0, r1, FieldMemOperand(r0, HeapNumber::kValueOffset));
+    __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset));
+    __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset));
   }
   __ jmp(both_loaded_as_doubles);
 }
@@ -7286,9 +7314,14 @@
 
 // Fast negative check for symbol-to-symbol equality.
 static void EmitCheckForSymbolsOrObjects(MacroAssembler* masm,
+                                         Register lhs,
+                                         Register rhs,
                                          Label* possible_strings,
                                          Label* not_both_strings) {
-  // r2 is object type of r0.
+  ASSERT((lhs.is(r0) && rhs.is(r1)) ||
+         (lhs.is(r1) && rhs.is(r0)));
+
+  // r2 is object type of rhs.
   // Ensure that no non-strings have the symbol bit set.
   Label object_test;
   ASSERT(kSymbolTag != 0);
@@ -7296,31 +7329,31 @@
   __ b(ne, &object_test);
   __ tst(r2, Operand(kIsSymbolMask));
   __ b(eq, possible_strings);
-  __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
+  __ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE);
   __ b(ge, not_both_strings);
   __ tst(r3, Operand(kIsSymbolMask));
   __ b(eq, possible_strings);
 
   // Both are symbols.  We already checked they weren't the same pointer
   // so they are not equal.
-  __ mov(r0, Operand(1));   // Non-zero indicates not equal.
-  __ mov(pc, Operand(lr));  // Return.
+  __ mov(r0, Operand(NOT_EQUAL));
+  __ Ret();
 
   __ bind(&object_test);
   __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));
   __ b(lt, not_both_strings);
-  __ CompareObjectType(r1, r2, r3, FIRST_JS_OBJECT_TYPE);
+  __ CompareObjectType(lhs, r2, r3, FIRST_JS_OBJECT_TYPE);
   __ b(lt, not_both_strings);
-  // If both objects are undetectable, they are equal.  Otherwise, they
+  // If both objects are undetectable, they are equal. Otherwise, they
   // are not equal, since they are different objects and an object is not
   // equal to undefined.
-  __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
+  __ ldr(r3, FieldMemOperand(rhs, HeapObject::kMapOffset));
   __ ldrb(r2, FieldMemOperand(r2, Map::kBitFieldOffset));
   __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
   __ and_(r0, r2, Operand(r3));
   __ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
   __ eor(r0, r0, Operand(1 << Map::kIsUndetectable));
-  __ mov(pc, Operand(lr));  // Return.
+  __ Ret();
 }
 
 
@@ -7442,10 +7475,13 @@
 }
 
 
-// On entry r0 (rhs) and r1 (lhs) are the values to be compared.
+// On entry lhs_ and rhs_ are the values to be compared.
 // On exit r0 is 0, positive or negative to indicate the result of
 // the comparison.
 void CompareStub::Generate(MacroAssembler* masm) {
+  ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
+         (lhs_.is(r1) && rhs_.is(r0)));
+
   Label slow;  // Call builtin.
   Label not_smis, both_loaded_as_doubles, lhs_not_nan;
 
@@ -7460,7 +7496,7 @@
   // be strictly equal if the other is a HeapNumber.
   ASSERT_EQ(0, kSmiTag);
   ASSERT_EQ(0, Smi::FromInt(0));
-  __ and_(r2, r0, Operand(r1));
+  __ and_(r2, lhs_, Operand(rhs_));
   __ tst(r2, Operand(kSmiTagMask));
   __ b(ne, &not_smis);
   // One operand is a smi.  EmitSmiNonsmiComparison generates code that can:
@@ -7472,7 +7508,7 @@
   // comparison.  If VFP3 is supported the double values of the numbers have
   // been loaded into d7 and d6.  Otherwise, the double values have been loaded
   // into r0, r1, r2, and r3.
-  EmitSmiNonsmiComparison(masm, &lhs_not_nan, &slow, strict_);
+  EmitSmiNonsmiComparison(masm, lhs_, rhs_, &lhs_not_nan, &slow, strict_);
 
   __ bind(&both_loaded_as_doubles);
   // The arguments have been converted to doubles and stored in d6 and d7, if
@@ -7489,7 +7525,7 @@
     __ mov(r0, Operand(EQUAL), LeaveCC, eq);
     __ mov(r0, Operand(LESS), LeaveCC, lt);
     __ mov(r0, Operand(GREATER), LeaveCC, gt);
-    __ mov(pc, Operand(lr));
+    __ Ret();
 
     __ bind(&nan);
     // If one of the sides was a NaN then the v flag is set.  Load r0 with
@@ -7500,7 +7536,7 @@
     } else {
       __ mov(r0, Operand(LESS));
     }
-    __ mov(pc, Operand(lr));
+    __ Ret();
   } else {
     // Checks for NaN in the doubles we have loaded.  Can return the answer or
     // fall through if neither is a NaN.  Also binds lhs_not_nan.
@@ -7512,11 +7548,11 @@
 
   __ bind(&not_smis);
   // At this point we know we are dealing with two different objects,
-  // and neither of them is a Smi.  The objects are in r0 and r1.
+  // and neither of them is a Smi.  The objects are in rhs_ and lhs_.
   if (strict_) {
     // This returns non-equal for some object types, or falls through if it
     // was not lucky.
-    EmitStrictTwoHeapObjectCompare(masm);
+    EmitStrictTwoHeapObjectCompare(masm, lhs_, rhs_);
   }
 
   Label check_for_symbols;
@@ -7524,8 +7560,10 @@
   // Check for heap-number-heap-number comparison.  Can jump to slow case,
   // or load both doubles into r0, r1, r2, r3 and jump to the code that handles
   // that case.  If the inputs are not doubles then jumps to check_for_symbols.
-  // In this case r2 will contain the type of r0.  Never falls through.
+  // In this case r2 will contain the type of rhs_.  Never falls through.
   EmitCheckForTwoHeapNumbers(masm,
+                             lhs_,
+                             rhs_,
                              &both_loaded_as_doubles,
                              &check_for_symbols,
                              &flat_string_check);
@@ -7536,20 +7574,20 @@
   if (cc_ == eq && !strict_) {
     // Returns an answer for two symbols or two detectable objects.
     // Otherwise jumps to string case or not both strings case.
-    // Assumes that r2 is the type of r0 on entry.
-    EmitCheckForSymbolsOrObjects(masm, &flat_string_check, &slow);
+    // Assumes that r2 is the type of rhs_ on entry.
+    EmitCheckForSymbolsOrObjects(masm, lhs_, rhs_, &flat_string_check, &slow);
   }
 
   // Check for both being sequential ASCII strings, and inline if that is the
   // case.
   __ bind(&flat_string_check);
 
-  __ JumpIfNonSmisNotBothSequentialAsciiStrings(r0, r1, r2, r3, &slow);
+  __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, r2, r3, &slow);
 
   __ IncrementCounter(&Counters::string_compare_native, 1, r2, r3);
   StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
-                                                     r1,
-                                                     r0,
+                                                     lhs_,
+                                                     rhs_,
                                                      r2,
                                                      r3,
                                                      r4,
@@ -7558,7 +7596,7 @@
 
   __ bind(&slow);
 
-  __ Push(r1, r0);
+  __ Push(lhs_, rhs_);
   // Figure out which native to call and setup the arguments.
   Builtins::JavaScript native;
   if (cc_ == eq) {
@@ -10059,6 +10097,9 @@
 // Unfortunately you have to run without snapshots to see most of these
 // names in the profile since most compare stubs end up in the snapshot.
 const char* CompareStub::GetName() {
+  ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
+         (lhs_.is(r1) && rhs_.is(r0)));
+
   if (name_ != NULL) return name_;
   const int kMaxNameLength = 100;
   name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
@@ -10075,6 +10116,9 @@
     default: cc_name = "UnknownCondition"; break;
   }
 
+  const char* lhs_name = lhs_.is(r0) ? "_r0" : "_r1";
+  const char* rhs_name = rhs_.is(r0) ? "_r0" : "_r1";
+
   const char* strict_name = "";
   if (strict_ && (cc_ == eq || cc_ == ne)) {
     strict_name = "_STRICT";
@@ -10091,8 +10135,10 @@
   }
 
   OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
-               "CompareStub_%s%s%s%s",
+               "CompareStub_%s%s%s%s%s%s",
                cc_name,
+               lhs_name,
+               rhs_name,
                strict_name,
                never_nan_nan_name,
                include_number_compare_name);
@@ -10104,8 +10150,11 @@
   // Encode the three parameters in a unique 16 bit value. To avoid duplicate
   // stubs the never NaN NaN condition is only taken into account if the
   // condition is equals.
-  ASSERT((static_cast<unsigned>(cc_) >> 28) < (1 << 13));
+  ASSERT((static_cast<unsigned>(cc_) >> 28) < (1 << 12));
+  ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
+         (lhs_.is(r1) && rhs_.is(r0)));
   return ConditionField::encode(static_cast<unsigned>(cc_) >> 28)
+         | RegisterField::encode(lhs_.is(r0))
          | StrictField::encode(strict_)
          | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false)
          | IncludeNumberCompareField::encode(include_number_compare_);
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 855723d..83685d8 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -475,6 +475,7 @@
   void GenerateIsArray(ZoneList<Expression*>* args);
   void GenerateIsRegExp(ZoneList<Expression*>* args);
   void GenerateIsObject(ZoneList<Expression*>* args);
+  void GenerateIsSpecObject(ZoneList<Expression*>* args);
   void GenerateIsFunction(ZoneList<Expression*>* args);
   void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
 
diff --git a/src/arm/constants-arm.cc b/src/arm/constants-arm.cc
index 002e4c1..3df7b4e 100644
--- a/src/arm/constants-arm.cc
+++ b/src/arm/constants-arm.cc
@@ -37,6 +37,26 @@
 
 namespace v8i = v8::internal;
 
+double Instr::DoubleImmedVmov() const {
+  // Reconstruct a double from the immediate encoded in the vmov instruction.
+  //
+  //   instruction: [xxxxxxxx,xxxxabcd,xxxxxxxx,xxxxefgh]
+  //   double: [aBbbbbbb,bbcdefgh,00000000,00000000,
+  //            00000000,00000000,00000000,00000000]
+  //
+  // where B = ~b. Only the high 16 bits are affected.
+  uint64_t high16;
+  high16  = (Bits(17, 16) << 4) | Bits(3, 0);   // xxxxxxxx,xxcdefgh.
+  high16 |= (0xff * Bit(18)) << 6;              // xxbbbbbb,bbxxxxxx.
+  high16 |= (Bit(18) ^ 1) << 14;                // xBxxxxxx,xxxxxxxx.
+  high16 |= Bit(19) << 15;                      // axxxxxxx,xxxxxxxx.
+
+  uint64_t imm = high16 << 48;
+  double d;
+  memcpy(&d, &imm, 8);
+  return d;
+}
+
 
 // These register names are defined in a way to match the native disassembler
 // formatting. See for example the command "objdump -d <binary file>".
diff --git a/src/arm/constants-arm.h b/src/arm/constants-arm.h
index fa9adbd..2ac9a41 100644
--- a/src/arm/constants-arm.h
+++ b/src/arm/constants-arm.h
@@ -333,6 +333,9 @@
   inline bool HasH()    const { return HField() == 1; }
   inline bool HasLink() const { return LinkField() == 1; }
 
+  // Decoding the double immediate in the vmov instruction.
+  double DoubleImmedVmov() const;
+
   // Instructions are read of out a code stream. The only way to get a
   // reference to an instruction is to convert a pointer. There is no way
   // to allocate or create instances of class Instr.
diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc
index a52417b..37401ed 100644
--- a/src/arm/disasm-arm.cc
+++ b/src/arm/disasm-arm.cc
@@ -412,6 +412,12 @@
       PrintCondition(instr);
       return 4;
     }
+    case 'd': {  // 'd: vmov double immediate.
+      double d = instr->DoubleImmedVmov();
+      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                           "#%g", d);
+      return 1;
+    }
     case 'f': {  // 'f: bitfield instructions - v7 and above.
       uint32_t lsbit = instr->Bits(11, 7);
       uint32_t width = instr->Bits(20, 16) + 1;
@@ -1052,7 +1058,7 @@
         if (instr->SzField() == 0x1) {
           Format(instr, "vmov.f64'cond 'Dd, 'Dm");
         } else {
-          Unknown(instr);  // Not used by V8.
+          Format(instr, "vmov.f32'cond 'Sd, 'Sm");
         }
       } else if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)) {
         DecodeVCVTBetweenDoubleAndSingle(instr);
@@ -1066,6 +1072,12 @@
         DecodeVCMP(instr);
       } else if (((instr->Opc2Field() == 0x1)) && (instr->Opc3Field() == 0x3)) {
         Format(instr, "vsqrt.f64'cond 'Dd, 'Dm");
+      } else if (instr->Opc3Field() == 0x0) {
+        if (instr->SzField() == 0x1) {
+          Format(instr, "vmov.f64'cond 'Dd, 'd");
+        } else {
+          Unknown(instr);  // Not used by V8.
+        }
       } else {
         Unknown(instr);  // Not used by V8.
       }
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 080cb83..7d90ed9 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -822,8 +822,7 @@
     // the smi vs. smi case to be handled before it is called.
     Label slow_case;
     __ ldr(r1, MemOperand(sp, 0));  // Switch value.
-    __ mov(r2, r1);
-    __ orr(r2, r2, r0);
+    __ orr(r2, r1, r0);
     __ tst(r2, Operand(kSmiTagMask));
     __ b(ne, &slow_case);
     __ cmp(r1, r0);
@@ -832,9 +831,9 @@
     __ b(clause->body_target()->entry_label());
 
     __ bind(&slow_case);
-    CompareStub stub(eq, true);
+    CompareStub stub(eq, true, kBothCouldBeNaN, true, r1, r0);
     __ CallStub(&stub);
-    __ tst(r0, r0);
+    __ cmp(r0, Operand(0));
     __ b(ne, &next_test);
     __ Drop(1);  // Switch value is no longer needed.
     __ b(clause->body_target()->entry_label());
@@ -1909,6 +1908,25 @@
 }
 
 
+void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 1);
+
+  VisitForValue(args->at(0), kAccumulator);
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
+
+  __ BranchOnSmi(r0, if_false);
+  __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
+  __ b(ge, if_true);
+  __ b(if_false);
+
+  Apply(context_, if_true, if_false);
+}
+
+
 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
   ASSERT(args->length() == 1);
 
@@ -2161,12 +2179,8 @@
   __ jmp(&heapnumber_allocated);
 
   __ bind(&slow_allocate_heapnumber);
-  // To allocate a heap number, and ensure that it is not a smi, we
-  // call the runtime function FUnaryMinus on 0, returning the double
-  // -0.0. A new, distinct heap number is returned each time.
-  __ mov(r0, Operand(Smi::FromInt(0)));
-  __ push(r0);
-  __ CallRuntime(Runtime::kNumberUnaryMinus, 1);
+  // Allocate a heap number.
+  __ CallRuntime(Runtime::kNumberAlloc, 0);
   __ mov(r4, Operand(r0));
 
   __ bind(&heapnumber_allocated);
@@ -3092,7 +3106,7 @@
       __ jmp(if_false);
 
       __ bind(&slow_case);
-      CompareStub stub(cc, strict);
+      CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0);
       __ CallStub(&stub);
       __ cmp(r0, Operand(0));
       __ b(cc, if_true);
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 2896cc9..f251b31 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -873,88 +873,6 @@
 }
 
 
-Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg,
-                                   JSObject* holder, Register holder_reg,
-                                   Register scratch,
-                                   int save_at_depth,
-                                   Label* miss) {
-  // Make sure there's no overlap between scratch and the other
-  // registers.
-  ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg));
-
-  // Keep track of the current object in register reg.
-  Register reg = object_reg;
-  int depth = 0;
-
-  if (save_at_depth == depth) {
-    str(reg, MemOperand(sp));
-  }
-
-  // Check the maps in the prototype chain.
-  // Traverse the prototype chain from the object and do map checks.
-  while (object != holder) {
-    depth++;
-
-    // Only global objects and objects that do not require access
-    // checks are allowed in stubs.
-    ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
-
-    // Get the map of the current object.
-    ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
-    cmp(scratch, Operand(Handle<Map>(object->map())));
-
-    // Branch on the result of the map check.
-    b(ne, miss);
-
-    // Check access rights to the global object.  This has to happen
-    // after the map check so that we know that the object is
-    // actually a global object.
-    if (object->IsJSGlobalProxy()) {
-      CheckAccessGlobalProxy(reg, scratch, miss);
-      // Restore scratch register to be the map of the object.  In the
-      // new space case below, we load the prototype from the map in
-      // the scratch register.
-      ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
-    }
-
-    reg = holder_reg;  // from now the object is in holder_reg
-    JSObject* prototype = JSObject::cast(object->GetPrototype());
-    if (Heap::InNewSpace(prototype)) {
-      // The prototype is in new space; we cannot store a reference
-      // to it in the code. Load it from the map.
-      ldr(reg, FieldMemOperand(scratch, Map::kPrototypeOffset));
-    } else {
-      // The prototype is in old space; load it directly.
-      mov(reg, Operand(Handle<JSObject>(prototype)));
-    }
-
-    if (save_at_depth == depth) {
-      str(reg, MemOperand(sp));
-    }
-
-    // Go to the next object in the prototype chain.
-    object = prototype;
-  }
-
-  // Check the holder map.
-  ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
-  cmp(scratch, Operand(Handle<Map>(object->map())));
-  b(ne, miss);
-
-  // Log the check depth.
-  LOG(IntEvent("check-maps-depth", depth + 1));
-
-  // Perform security check for access to the global object and return
-  // the holder register.
-  ASSERT(object == holder);
-  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
-  if (object->IsJSGlobalProxy()) {
-    CheckAccessGlobalProxy(reg, scratch, miss);
-  }
-  return reg;
-}
-
-
 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
                                             Register scratch,
                                             Label* miss) {
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index f1f7de7..156e132 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -316,24 +316,6 @@
   // ---------------------------------------------------------------------------
   // Inline caching support
 
-  // Generates code that verifies that the maps of objects in the
-  // prototype chain of object hasn't changed since the code was
-  // generated and branches to the miss label if any map has. If
-  // necessary the function also generates code for security check
-  // in case of global object holders. The scratch and holder
-  // registers are always clobbered, but the object register is only
-  // clobbered if it the same as the holder register. The function
-  // returns a register containing the holder - either object_reg or
-  // holder_reg.
-  // The function can optionally (when save_at_depth !=
-  // kInvalidProtoDepth) save the object at the given depth by moving
-  // it to [sp].
-  Register CheckMaps(JSObject* object, Register object_reg,
-                     JSObject* holder, Register holder_reg,
-                     Register scratch,
-                     int save_at_depth,
-                     Label* miss);
-
   // Generate code for checking access rights - used for security checks
   // on access to global objects across environments. The holder register
   // is left untouched, whereas both scratch registers are clobbered.
diff --git a/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
index e8910f4..c67c7aa 100644
--- a/src/arm/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -799,7 +799,6 @@
   CodeDesc code_desc;
   masm_->GetCode(&code_desc);
   Handle<Code> code = Factory::NewCode(code_desc,
-                                       NULL,
                                        Code::ComputeFlags(Code::REGEXP),
                                        masm_->CodeObject());
   PROFILE(RegExpCodeCreateEvent(*code, *source));
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index f09ce00..3345e45 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -2281,7 +2281,7 @@
         if (instr->SzField() == 0x1) {
           set_d_register_from_double(vd, get_double_from_d_register(vm));
         } else {
-          UNREACHABLE();  // Not used by V8.
+          set_s_register_from_float(vd, get_float_from_s_register(vm));
         }
       } else if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)) {
         DecodeVCVTBetweenDoubleAndSingle(instr);
@@ -2298,6 +2298,13 @@
         double dm_value = get_double_from_d_register(vm);
         double dd_value = sqrt(dm_value);
         set_d_register_from_double(vd, dd_value);
+      } else if (instr->Opc3Field() == 0x0) {
+        // vmov immediate.
+        if (instr->SzField() == 0x1) {
+          set_d_register_from_double(vd, instr->DoubleImmedVmov());
+        } else {
+          UNREACHABLE();  // Not used by v8.
+        }
       } else {
         UNREACHABLE();  // Not used by V8.
       }
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 0e649cc..ff3007c 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -83,6 +83,119 @@
 }
 
 
+// Helper function used to check that the dictionary doesn't contain
+// the property. This function may return false negatives, so miss_label
+// must always call a backup property check that is complete.
+// This function is safe to call if the receiver has fast properties.
+// Name must be a symbol and receiver must be a heap object.
+static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
+                                             Label* miss_label,
+                                             Register receiver,
+                                             String* name,
+                                             Register scratch0,
+                                             Register scratch1) {
+  ASSERT(name->IsSymbol());
+  __ IncrementCounter(&Counters::negative_lookups, 1, scratch0, scratch1);
+  __ IncrementCounter(&Counters::negative_lookups_miss, 1, scratch0, scratch1);
+
+  Label done;
+
+  const int kInterceptorOrAccessCheckNeededMask =
+      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
+
+  // Bail out if the receiver has a named interceptor or requires access checks.
+  Register map = scratch1;
+  __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
+  __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
+  __ b(ne, miss_label);
+
+  // Check that receiver is a JSObject.
+  __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  __ cmp(scratch0, Operand(FIRST_JS_OBJECT_TYPE));
+  __ b(lt, miss_label);
+
+  // Load properties array.
+  Register properties = scratch0;
+  __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+  // Check that the properties array is a dictionary.
+  __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset));
+  Register tmp = properties;
+  __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
+  __ cmp(map, tmp);
+  __ b(ne, miss_label);
+
+  // Restore the temporarily used register.
+  __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+
+  // Compute the capacity mask.
+  const int kCapacityOffset =
+      StringDictionary::kHeaderSize +
+      StringDictionary::kCapacityIndex * kPointerSize;
+
+  // Generate an unrolled loop that performs a few probes before
+  // giving up.
+  static const int kProbes = 4;
+  const int kElementsStartOffset =
+      StringDictionary::kHeaderSize +
+      StringDictionary::kElementsStartIndex * kPointerSize;
+
+  // If names of slots in range from 1 to kProbes - 1 for the hash value are
+  // not equal to the name and kProbes-th slot is not used (its name is the
+  // undefined value), it guarantees the hash table doesn't contain the
+  // property. It's true even if some slots represent deleted properties
+  // (their names are the null value).
+  for (int i = 0; i < kProbes; i++) {
+    // scratch0 points to properties hash.
+    // Compute the masked index: (hash + i + i * i) & mask.
+    Register index = scratch1;
+    // Capacity is smi 2^n.
+    __ ldr(index, FieldMemOperand(properties, kCapacityOffset));
+    __ sub(index, index, Operand(1));
+    __ and_(index, index, Operand(
+        Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i))));
+
+    // Scale the index by multiplying by the entry size.
+    ASSERT(StringDictionary::kEntrySize == 3);
+    __ add(index, index, Operand(index, LSL, 1));  // index *= 3.
+
+    Register entity_name = scratch1;
+    // Having undefined at this place means the name is not contained.
+    ASSERT_EQ(kSmiTagSize, 1);
+    Register tmp = properties;
+    __ add(tmp, properties, Operand(index, LSL, 1));
+    __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
+
+    ASSERT(!tmp.is(entity_name));
+    __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
+    __ cmp(entity_name, tmp);
+    if (i != kProbes - 1) {
+      __ b(eq, &done);
+
+      // Stop if found the property.
+      __ cmp(entity_name, Operand(Handle<String>(name)));
+      __ b(eq, miss_label);
+
+      // Check if the entry name is not a symbol.
+      __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
+      __ ldrb(entity_name,
+              FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
+      __ tst(entity_name, Operand(kIsSymbolMask));
+      __ b(eq, miss_label);
+
+      // Restore the properties.
+      __ ldr(properties,
+             FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+    } else {
+      // Give up probing if still not found the undefined value.
+      __ b(ne, miss_label);
+    }
+  }
+  __ bind(&done);
+  __ DecrementCounter(&Counters::negative_lookups_miss, 1, scratch0, scratch1);
+}
+
+
 void StubCache::GenerateProbe(MacroAssembler* masm,
                               Code::Flags flags,
                               Register receiver,
@@ -517,6 +630,7 @@
                Register receiver,
                Register scratch1,
                Register scratch2,
+               Register scratch3,
                Label* miss) {
     ASSERT(holder->HasNamedInterceptor());
     ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
@@ -532,6 +646,7 @@
                        receiver,
                        scratch1,
                        scratch2,
+                       scratch3,
                        holder,
                        lookup,
                        name,
@@ -543,6 +658,7 @@
                      receiver,
                      scratch1,
                      scratch2,
+                     scratch3,
                      name,
                      holder,
                      miss);
@@ -555,6 +671,7 @@
                        Register receiver,
                        Register scratch1,
                        Register scratch2,
+                       Register scratch3,
                        JSObject* interceptor_holder,
                        LookupResult* lookup,
                        String* name,
@@ -596,7 +713,7 @@
     Register holder =
         stub_compiler_->CheckPrototypes(object, receiver,
                                         interceptor_holder, scratch1,
-                                        scratch2, name, depth1, miss);
+                                        scratch2, scratch3, name, depth1, miss);
 
     // Invoke an interceptor and if it provides a value,
     // branch to |regular_invoke|.
@@ -612,7 +729,7 @@
     if (interceptor_holder != lookup->holder()) {
       stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
                                       lookup->holder(), scratch1,
-                                      scratch2, name, depth2, miss);
+                                      scratch2, scratch3, name, depth2, miss);
     } else {
       // CheckPrototypes has a side effect of fetching a 'holder'
       // for API (object which is instanceof for the signature).  It's
@@ -648,12 +765,13 @@
                       Register receiver,
                       Register scratch1,
                       Register scratch2,
+                      Register scratch3,
                       String* name,
                       JSObject* interceptor_holder,
                       Label* miss_label) {
     Register holder =
         stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
-                                        scratch1, scratch2, name,
+                                        scratch1, scratch2, scratch3, name,
                                         miss_label);
 
     // Call a runtime function to load the interceptor property.
@@ -738,36 +856,134 @@
                                        Register object_reg,
                                        JSObject* holder,
                                        Register holder_reg,
-                                       Register scratch,
+                                       Register scratch1,
+                                       Register scratch2,
                                        String* name,
                                        int save_at_depth,
-                                       Label* miss,
-                                       Register extra) {
-  // Check that the maps haven't changed.
-  Register result =
-      masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch,
-                        save_at_depth, miss);
+                                       Label* miss) {
+  // Make sure there's no overlap between holder and object registers.
+  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
+  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
+         && !scratch2.is(scratch1));
+
+  // Keep track of the current object in register reg.
+  Register reg = object_reg;
+  int depth = 0;
+
+  if (save_at_depth == depth) {
+    __ str(reg, MemOperand(sp));
+  }
+
+  // Check the maps in the prototype chain.
+  // Traverse the prototype chain from the object and do map checks.
+  JSObject* current = object;
+  while (current != holder) {
+    depth++;
+
+    // Only global objects and objects that do not require access
+    // checks are allowed in stubs.
+    ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
+
+    JSObject* prototype = JSObject::cast(current->GetPrototype());
+    if (!current->HasFastProperties() &&
+        !current->IsJSGlobalObject() &&
+        !current->IsJSGlobalProxy()) {
+      if (!name->IsSymbol()) {
+        Object* lookup_result = Heap::LookupSymbol(name);
+        if (lookup_result->IsFailure()) {
+          set_failure(Failure::cast(lookup_result));
+          return reg;
+        } else {
+          name = String::cast(lookup_result);
+        }
+      }
+      ASSERT(current->property_dictionary()->FindEntry(name) ==
+             StringDictionary::kNotFound);
+
+      GenerateDictionaryNegativeLookup(masm(),
+                                       miss,
+                                       reg,
+                                       name,
+                                       scratch1,
+                                       scratch2);
+      __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
+      reg = holder_reg;  // from now the object is in holder_reg
+      __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
+    } else {
+      // Get the map of the current object.
+      __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
+      __ cmp(scratch1, Operand(Handle<Map>(current->map())));
+
+      // Branch on the result of the map check.
+      __ b(ne, miss);
+
+      // Check access rights to the global object.  This has to happen
+      // after the map check so that we know that the object is
+      // actually a global object.
+      if (current->IsJSGlobalProxy()) {
+        __ CheckAccessGlobalProxy(reg, scratch1, miss);
+        // Restore scratch register to be the map of the object.  In the
+        // new space case below, we load the prototype from the map in
+        // the scratch register.
+        __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
+      }
+
+      reg = holder_reg;  // from now the object is in holder_reg
+      if (Heap::InNewSpace(prototype)) {
+        // The prototype is in new space; we cannot store a reference
+        // to it in the code. Load it from the map.
+        __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
+      } else {
+        // The prototype is in old space; load it directly.
+        __ mov(reg, Operand(Handle<JSObject>(prototype)));
+      }
+    }
+
+    if (save_at_depth == depth) {
+      __ str(reg, MemOperand(sp));
+    }
+
+    // Go to the next object in the prototype chain.
+    current = prototype;
+  }
+
+  // Check the holder map.
+  __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
+  __ cmp(scratch1, Operand(Handle<Map>(current->map())));
+  __ b(ne, miss);
+
+  // Log the check depth.
+  LOG(IntEvent("check-maps-depth", depth + 1));
+
+  // Perform security check for access to the global object and return
+  // the holder register.
+  ASSERT(current == holder);
+  ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
+  if (current->IsJSGlobalProxy()) {
+    __ CheckAccessGlobalProxy(reg, scratch1, miss);
+  }
 
   // If we've skipped any global objects, it's not enough to verify
   // that their maps haven't changed.  We also need to check that the
   // property cell for the property is still empty.
-  while (object != holder) {
-    if (object->IsGlobalObject()) {
+  current = object;
+  while (current != holder) {
+    if (current->IsGlobalObject()) {
       Object* cell = GenerateCheckPropertyCell(masm(),
-                                               GlobalObject::cast(object),
+                                               GlobalObject::cast(current),
                                                name,
-                                               scratch,
+                                               scratch1,
                                                miss);
       if (cell->IsFailure()) {
         set_failure(Failure::cast(cell));
-        return result;
+        return reg;
       }
     }
-    object = JSObject::cast(object->GetPrototype());
+    current = JSObject::cast(current->GetPrototype());
   }
 
   // Return the register containing the holder.
-  return result;
+  return reg;
 }
 
 
@@ -776,6 +992,7 @@
                                      Register receiver,
                                      Register scratch1,
                                      Register scratch2,
+                                     Register scratch3,
                                      int index,
                                      String* name,
                                      Label* miss) {
@@ -785,7 +1002,8 @@
 
   // Check that the maps haven't changed.
   Register reg =
-      CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss);
+      CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3,
+                      name, miss);
   GenerateFastPropertyLoad(masm(), r0, reg, holder, index);
   __ Ret();
 }
@@ -796,6 +1014,7 @@
                                         Register receiver,
                                         Register scratch1,
                                         Register scratch2,
+                                        Register scratch3,
                                         Object* value,
                                         String* name,
                                         Label* miss) {
@@ -805,7 +1024,8 @@
 
   // Check that the maps haven't changed.
   Register reg =
-      CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss);
+      CheckPrototypes(object, receiver, holder,
+                      scratch1, scratch2, scratch3, name, miss);
 
   // Return the constant value.
   __ mov(r0, Operand(Handle<Object>(value)));
@@ -819,6 +1039,7 @@
                                         Register name_reg,
                                         Register scratch1,
                                         Register scratch2,
+                                        Register scratch3,
                                         AccessorInfo* callback,
                                         String* name,
                                         Label* miss,
@@ -829,7 +1050,8 @@
 
   // Check that the maps haven't changed.
   Register reg =
-      CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss);
+      CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3,
+                      name, miss);
 
   // Push the arguments on the JS stack of the caller.
   __ push(receiver);  // Receiver.
@@ -854,6 +1076,7 @@
                                            Register name_reg,
                                            Register scratch1,
                                            Register scratch2,
+                                           Register scratch3,
                                            String* name,
                                            Label* miss) {
   ASSERT(interceptor_holder->HasNamedInterceptor());
@@ -881,7 +1104,8 @@
     // property from further up the prototype chain if the call fails.
     // Check that the maps haven't changed.
     Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
-                                          scratch1, scratch2, name, miss);
+                                          scratch1, scratch2, scratch3,
+                                          name, miss);
     ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
 
     // Save necessary data before invoking an interceptor.
@@ -930,6 +1154,7 @@
                                    lookup->holder(),
                                    scratch1,
                                    scratch2,
+                                   scratch3,
                                    name,
                                    miss);
     }
@@ -975,7 +1200,8 @@
     // Call the runtime system to load the interceptor.
     // Check that the maps haven't changed.
     Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
-                                          scratch1, scratch2, name, miss);
+                                          scratch1, scratch2, scratch3,
+                                          name, miss);
     PushInterceptorArguments(masm(), receiver, holder_reg,
                              name_reg, interceptor_holder);
 
@@ -1053,7 +1279,7 @@
   __ b(eq, &miss);
 
   // Do the right check and compute the holder register.
-  Register reg = CheckPrototypes(object, r0, holder, r1, r3, name, &miss);
+  Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss);
   GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
 
   GenerateCallFunction(masm(), object, arguments(), &miss);
@@ -1098,7 +1324,7 @@
   __ b(eq, &miss);
 
   // Check that the maps haven't changed.
-  CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss);
+  CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, r4, name, &miss);
 
   if (object->IsGlobalObject()) {
     __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
@@ -1149,7 +1375,7 @@
   __ b(eq, &miss);
 
   // Check that the maps haven't changed.
-  CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss);
+  CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, r4, name, &miss);
 
   if (object->IsGlobalObject()) {
     __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
@@ -1246,7 +1472,7 @@
       }
 
       // Check that the maps haven't changed.
-      CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, name,
+      CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
                       depth, &miss);
 
       // Patch the receiver on the stack with the global proxy if
@@ -1270,7 +1496,7 @@
         GenerateDirectLoadGlobalFunctionPrototype(
             masm(), Context::STRING_FUNCTION_INDEX, r0);
         CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
-                        r1, name, &miss);
+                        r1, r4, name, &miss);
       }
       break;
 
@@ -1290,7 +1516,7 @@
         GenerateDirectLoadGlobalFunctionPrototype(
             masm(), Context::NUMBER_FUNCTION_INDEX, r0);
         CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
-                        r1, name, &miss);
+                        r1, r4, name, &miss);
       }
       break;
     }
@@ -1313,7 +1539,7 @@
         GenerateDirectLoadGlobalFunctionPrototype(
             masm(), Context::BOOLEAN_FUNCTION_INDEX, r0);
         CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
-                        r1, name, &miss);
+                        r1, r4, name, &miss);
       }
       break;
     }
@@ -1372,6 +1598,7 @@
                    r1,
                    r3,
                    r4,
+                   r0,
                    &miss);
 
   // Move returned value, the function to call, to r1.
@@ -1418,7 +1645,7 @@
   }
 
   // Check that the maps haven't changed.
-  CheckPrototypes(object, r0, holder, r3, r1, name, &miss);
+  CheckPrototypes(object, r0, holder, r3, r1, r4, name, &miss);
 
   // Get the value from the cell.
   __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
@@ -1642,7 +1869,7 @@
   __ b(eq, &miss);
 
   // Check the maps of the full prototype chain.
-  CheckPrototypes(object, r0, last, r3, r1, name, &miss);
+  CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss);
 
   // If the last object in the prototype chain is a global object,
   // check that the global property cell is empty.
@@ -1679,7 +1906,7 @@
   // -----------------------------------
   Label miss;
 
-  GenerateLoadField(object, holder, r0, r3, r1, index, name, &miss);
+  GenerateLoadField(object, holder, r0, r3, r1, r4, index, name, &miss);
   __ bind(&miss);
   GenerateLoadMiss(masm(), Code::LOAD_IC);
 
@@ -1700,7 +1927,7 @@
   Label miss;
 
   Failure* failure = Failure::InternalError();
-  bool success = GenerateLoadCallback(object, holder, r0, r2, r3, r1,
+  bool success = GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4,
                                       callback, name, &miss, &failure);
   if (!success) return failure;
 
@@ -1723,7 +1950,7 @@
   // -----------------------------------
   Label miss;
 
-  GenerateLoadConstant(object, holder, r0, r3, r1, value, name, &miss);
+  GenerateLoadConstant(object, holder, r0, r3, r1, r4, value, name, &miss);
   __ bind(&miss);
   GenerateLoadMiss(masm(), Code::LOAD_IC);
 
@@ -1751,6 +1978,7 @@
                           r2,
                           r3,
                           r1,
+                          r4,
                           name,
                           &miss);
   __ bind(&miss);
@@ -1782,7 +2010,7 @@
   }
 
   // Check that the map of the global has not changed.
-  CheckPrototypes(object, r0, holder, r3, r4, name, &miss);
+  CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss);
 
   // Get the value from the cell.
   __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
@@ -1823,7 +2051,7 @@
   __ cmp(r0, Operand(Handle<String>(name)));
   __ b(ne, &miss);
 
-  GenerateLoadField(receiver, holder, r1, r2, r3, index, name, &miss);
+  GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss);
   __ bind(&miss);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
@@ -1847,7 +2075,7 @@
   __ b(ne, &miss);
 
   Failure* failure = Failure::InternalError();
-  bool success = GenerateLoadCallback(receiver, holder, r1, r0, r2, r3,
+  bool success = GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, r4,
                                       callback, name, &miss, &failure);
   if (!success) return failure;
 
@@ -1873,7 +2101,7 @@
   __ cmp(r0, Operand(Handle<String>(name)));
   __ b(ne, &miss);
 
-  GenerateLoadConstant(receiver, holder, r1, r2, r3, value, name, &miss);
+  GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss);
   __ bind(&miss);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
@@ -1905,6 +2133,7 @@
                           r0,
                           r2,
                           r3,
+                          r4,
                           name,
                           &miss);
   __ bind(&miss);