Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / v8 / src / arm / lithium-codegen-arm.cc
index 0c280c0..e945a13 100644 (file)
@@ -1158,7 +1158,7 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
     __ and_(dividend, dividend, Operand(mask));
     __ rsb(dividend, dividend, Operand::Zero(), SetCC);
     if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
-      DeoptimizeIf(eq, instr);
+      DeoptimizeIf(eq, instr, "minus zero");
     }
     __ b(&done);
   }
@@ -1176,7 +1176,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
   DCHECK(!dividend.is(result));
 
   if (divisor == 0) {
-    DeoptimizeIf(al, instr);
+    DeoptimizeIf(al, instr, "division by zero");
     return;
   }
 
@@ -1191,7 +1191,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
     Label remainder_not_zero;
     __ b(ne, &remainder_not_zero);
     __ cmp(dividend, Operand::Zero());
-    DeoptimizeIf(lt, instr);
+    DeoptimizeIf(lt, instr, "minus zero");
     __ bind(&remainder_not_zero);
   }
 }
@@ -1211,7 +1211,7 @@ void LCodeGen::DoModI(LModI* instr) {
     // case because we can't return a NaN.
     if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
       __ cmp(right_reg, Operand::Zero());
-      DeoptimizeIf(eq, instr);
+      DeoptimizeIf(eq, instr, "division by zero");
     }
 
     // Check for kMinInt % -1, sdiv will return kMinInt, which is not what we
@@ -1222,7 +1222,7 @@ void LCodeGen::DoModI(LModI* instr) {
       __ b(ne, &no_overflow_possible);
       __ cmp(right_reg, Operand(-1));
       if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
-        DeoptimizeIf(eq, instr);
+        DeoptimizeIf(eq, instr, "minus zero");
       } else {
         __ b(ne, &no_overflow_possible);
         __ mov(result_reg, Operand::Zero());
@@ -1243,7 +1243,7 @@ void LCodeGen::DoModI(LModI* instr) {
       __ cmp(result_reg, Operand::Zero());
       __ b(ne, &done);
       __ cmp(left_reg, Operand::Zero());
-      DeoptimizeIf(lt, instr);
+      DeoptimizeIf(lt, instr, "minus zero");
     }
     __ bind(&done);
 
@@ -1268,7 +1268,7 @@ void LCodeGen::DoModI(LModI* instr) {
     // NaN.
     if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
       __ cmp(right_reg, Operand::Zero());
-      DeoptimizeIf(eq, instr);
+      DeoptimizeIf(eq, instr, "division by zero");
     }
 
     __ Move(result_reg, left_reg);
@@ -1298,7 +1298,7 @@ void LCodeGen::DoModI(LModI* instr) {
     if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
       __ b(ne, &done);
       __ cmp(left_reg, Operand::Zero());
-      DeoptimizeIf(mi, instr);
+      DeoptimizeIf(mi, instr, "minus zero");
     }
     __ bind(&done);
   }
@@ -1316,19 +1316,19 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
   HDiv* hdiv = instr->hydrogen();
   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
     __ cmp(dividend, Operand::Zero());
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "minus zero");
   }
   // Check for (kMinInt / -1).
   if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
     __ cmp(dividend, Operand(kMinInt));
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "overflow");
   }
   // Deoptimize if remainder will not be 0.
   if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
       divisor != 1 && divisor != -1) {
     int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
     __ tst(dividend, Operand(mask));
-    DeoptimizeIf(ne, instr);
+    DeoptimizeIf(ne, instr, "lost precision");
   }
 
   if (divisor == -1) {  // Nice shortcut, not needed for correctness.
@@ -1356,7 +1356,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
   DCHECK(!dividend.is(result));
 
   if (divisor == 0) {
-    DeoptimizeIf(al, instr);
+    DeoptimizeIf(al, instr, "division by zero");
     return;
   }
 
@@ -1364,7 +1364,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
   HDiv* hdiv = instr->hydrogen();
   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
     __ cmp(dividend, Operand::Zero());
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "minus zero");
   }
 
   __ TruncatingDiv(result, dividend, Abs(divisor));
@@ -1374,7 +1374,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
     __ mov(ip, Operand(divisor));
     __ smull(scratch0(), ip, result, ip);
     __ sub(scratch0(), scratch0(), dividend, SetCC);
-    DeoptimizeIf(ne, instr);
+    DeoptimizeIf(ne, instr, "lost precision");
   }
 }
 
@@ -1389,7 +1389,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
   // Check for x / 0.
   if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
     __ cmp(divisor, Operand::Zero());
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "division by zero");
   }
 
   // Check for (0 / -x) that will produce negative zero.
@@ -1401,7 +1401,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
     }
     __ b(pl, &positive);
     __ cmp(dividend, Operand::Zero());
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "minus zero");
     __ bind(&positive);
   }
 
@@ -1413,7 +1413,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
     // support because, on ARM, sdiv kMinInt, -1 -> kMinInt.
     __ cmp(dividend, Operand(kMinInt));
     __ cmp(divisor, Operand(-1), eq);
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "overflow");
   }
 
   if (CpuFeatures::IsSupported(SUDIV)) {
@@ -1436,7 +1436,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
     Register remainder = scratch0();
     __ Mls(remainder, result, divisor, dividend);
     __ cmp(remainder, Operand::Zero());
-    DeoptimizeIf(ne, instr);
+    DeoptimizeIf(ne, instr, "lost precision");
   }
 }
 
@@ -1487,13 +1487,13 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
   // If the divisor is negative, we have to negate and handle edge cases.
   __ rsb(result, dividend, Operand::Zero(), SetCC);
   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "minus zero");
   }
 
   // Dividing by -1 is basically negation, unless we overflow.
   if (divisor == -1) {
     if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
-      DeoptimizeIf(vs, instr);
+      DeoptimizeIf(vs, instr, "overflow");
     }
     return;
   }
@@ -1516,7 +1516,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
   DCHECK(!dividend.is(result));
 
   if (divisor == 0) {
-    DeoptimizeIf(al, instr);
+    DeoptimizeIf(al, instr, "division by zero");
     return;
   }
 
@@ -1524,7 +1524,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
   HMathFloorOfDiv* hdiv = instr->hydrogen();
   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
     __ cmp(dividend, Operand::Zero());
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "minus zero");
   }
 
   // Easy case: We need no dynamic check for the dividend and the flooring
@@ -1565,7 +1565,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
   // Check for x / 0.
   if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
     __ cmp(right, Operand::Zero());
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "division by zero");
   }
 
   // Check for (0 / -x) that will produce negative zero.
@@ -1577,7 +1577,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
     }
     __ b(pl, &positive);
     __ cmp(left, Operand::Zero());
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "minus zero");
     __ bind(&positive);
   }
 
@@ -1589,7 +1589,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
     // support because, on ARM, sdiv kMinInt, -1 -> kMinInt.
     __ cmp(left, Operand(kMinInt));
     __ cmp(right, Operand(-1), eq);
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "overflow");
   }
 
   if (CpuFeatures::IsSupported(SUDIV)) {
@@ -1635,14 +1635,14 @@ void LCodeGen::DoMulI(LMulI* instr) {
       // The case of a null constant will be handled separately.
       // If constant is negative and left is null, the result should be -0.
       __ cmp(left, Operand::Zero());
-      DeoptimizeIf(eq, instr);
+      DeoptimizeIf(eq, instr, "minus zero");
     }
 
     switch (constant) {
       case -1:
         if (overflow) {
           __ rsb(result, left, Operand::Zero(), SetCC);
-          DeoptimizeIf(vs, instr);
+          DeoptimizeIf(vs, instr, "overflow");
         } else {
           __ rsb(result, left, Operand::Zero());
         }
@@ -1652,7 +1652,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
           // If left is strictly negative and the constant is null, the
           // result is -0. Deoptimize if required, otherwise return 0.
           __ cmp(left, Operand::Zero());
-          DeoptimizeIf(mi, instr);
+          DeoptimizeIf(mi, instr, "minus zero");
         }
         __ mov(result, Operand::Zero());
         break;
@@ -1702,7 +1702,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
         __ smull(result, scratch, left, right);
       }
       __ cmp(scratch, Operand(result, ASR, 31));
-      DeoptimizeIf(ne, instr);
+      DeoptimizeIf(ne, instr, "overflow");
     } else {
       if (instr->hydrogen()->representation().IsSmi()) {
         __ SmiUntag(result, left);
@@ -1718,7 +1718,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
       __ b(pl, &done);
       // Bail out if the result is minus zero.
       __ cmp(result, Operand::Zero());
-      DeoptimizeIf(eq, instr);
+      DeoptimizeIf(eq, instr, "minus zero");
       __ bind(&done);
     }
   }
@@ -1781,7 +1781,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
       case Token::SHR:
         if (instr->can_deopt()) {
           __ mov(result, Operand(left, LSR, scratch), SetCC);
-          DeoptimizeIf(mi, instr);
+          DeoptimizeIf(mi, instr, "negative value");
         } else {
           __ mov(result, Operand(left, LSR, scratch));
         }
@@ -1818,7 +1818,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
         } else {
           if (instr->can_deopt()) {
             __ tst(left, Operand(0x80000000));
-            DeoptimizeIf(ne, instr);
+            DeoptimizeIf(ne, instr, "negative value");
           }
           __ Move(result, left);
         }
@@ -1833,7 +1833,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
             } else {
               __ SmiTag(result, left, SetCC);
             }
-            DeoptimizeIf(vs, instr);
+            DeoptimizeIf(vs, instr, "overflow");
           } else {
             __ mov(result, Operand(left, LSL, shift_count));
           }
@@ -1865,7 +1865,7 @@ void LCodeGen::DoSubI(LSubI* instr) {
   }
 
   if (can_overflow) {
-    DeoptimizeIf(vs, instr);
+    DeoptimizeIf(vs, instr, "overflow");
   }
 }
 
@@ -1886,7 +1886,7 @@ void LCodeGen::DoRSubI(LRSubI* instr) {
   }
 
   if (can_overflow) {
-    DeoptimizeIf(vs, instr);
+    DeoptimizeIf(vs, instr, "overflow");
   }
 }
 
@@ -1940,9 +1940,9 @@ void LCodeGen::DoDateField(LDateField* instr) {
   DCHECK(!scratch.is(object));
 
   __ SmiTst(object);
-  DeoptimizeIf(eq, instr);
+  DeoptimizeIf(eq, instr, "Smi");
   __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE);
-  DeoptimizeIf(ne, instr);
+  DeoptimizeIf(ne, instr, "not a date object");
 
   if (index->value() == 0) {
     __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
@@ -2059,7 +2059,7 @@ void LCodeGen::DoAddI(LAddI* instr) {
   }
 
   if (can_overflow) {
-    DeoptimizeIf(vs, instr);
+    DeoptimizeIf(vs, instr, "overflow");
   }
 }
 
@@ -2285,7 +2285,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
       } else if (expected.NeedsMap()) {
         // If we need a map later and have a Smi -> deopt.
         __ SmiTst(reg);
-        DeoptimizeIf(eq, instr);
+        DeoptimizeIf(eq, instr, "Smi");
       }
 
       const Register map = scratch0();
@@ -2341,7 +2341,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
       if (!expected.IsGeneric()) {
         // We've seen something for the first time -> deopt.
         // This can only happen if we are not generic already.
-        DeoptimizeIf(al, instr);
+        DeoptimizeIf(al, instr, "unexpected object");
       }
     }
   }
@@ -2986,7 +2986,7 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
   if (instr->hydrogen()->RequiresHoleCheck()) {
     __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
     __ cmp(result, ip);
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "hole");
   }
 }
 
@@ -2994,13 +2994,14 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
 template <class T>
 void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
   DCHECK(FLAG_vector_ics);
-  Register vector = ToRegister(instr->temp_vector());
-  DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister()));
-  __ Move(vector, instr->hydrogen()->feedback_vector());
+  Register vector_register = ToRegister(instr->temp_vector());
+  DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister()));
+  Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector();
+  __ Move(vector_register, vector);
   // No need to allocate this register.
   DCHECK(VectorLoadICDescriptor::SlotRegister().is(r0));
-  __ mov(VectorLoadICDescriptor::SlotRegister(),
-         Operand(Smi::FromInt(instr->hydrogen()->slot())));
+  int index = vector->GetIndex(instr->hydrogen()->slot());
+  __ mov(VectorLoadICDescriptor::SlotRegister(), Operand(Smi::FromInt(index)));
 }
 
 
@@ -3015,7 +3016,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
     EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
   }
   ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
-  Handle<Code> ic = CodeFactory::LoadIC(isolate(), mode).code();
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3036,7 +3037,7 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
     Register payload = ToRegister(instr->temp());
     __ ldr(payload, FieldMemOperand(cell, Cell::kValueOffset));
     __ CompareRoot(payload, Heap::kTheHoleValueRootIndex);
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "hole");
   }
 
   // Store the value.
@@ -3053,7 +3054,7 @@ void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
     __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
     __ cmp(result, ip);
     if (instr->hydrogen()->DeoptimizesOnHole()) {
-      DeoptimizeIf(eq, instr);
+      DeoptimizeIf(eq, instr, "hole");
     } else {
       __ mov(result, Operand(factory()->undefined_value()), LeaveCC, eq);
     }
@@ -3074,7 +3075,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
     __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
     __ cmp(scratch, ip);
     if (instr->hydrogen()->DeoptimizesOnHole()) {
-      DeoptimizeIf(eq, instr);
+      DeoptimizeIf(eq, instr, "hole");
     } else {
       __ b(ne, &skip_assignment);
     }
@@ -3137,7 +3138,8 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
   if (FLAG_vector_ics) {
     EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
   }
-  Handle<Code> ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code();
+  Handle<Code> ic =
+      CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
 }
 
@@ -3154,7 +3156,7 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
   // Check that the function has a prototype or an initial map.
   __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
   __ cmp(result, ip);
-  DeoptimizeIf(eq, instr);
+  DeoptimizeIf(eq, instr, "hole");
 
   // If the function does not have an initial map, we're done.
   Label done;
@@ -3211,93 +3213,6 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
 }
 
 
-void LCodeGen::DoDeferredSIMD128ToTagged(LInstruction* instr,
-                                         Runtime::FunctionId id) {
-  // TODO(3095996): Get rid of this. For now, we need to make the
-  // result register contain a valid pointer because it is already
-  // contained in the register pointer map.
-  Register reg = ToRegister(instr->result());
-  __ mov(reg, Operand::Zero());
-
-  PushSafepointRegistersScope scope(this);
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
-  __ CallRuntimeSaveDoubles(id);
-  RecordSafepointWithRegisters(
-      instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
-  __ sub(r0, r0, Operand(kHeapObjectTag));
-  __ StoreToSafepointRegisterSlot(r0, reg);
-}
-
-
-template<class T>
-void LCodeGen::DoLoadKeyedSIMD128ExternalArray(LLoadKeyed* instr) {
-  class DeferredSIMD128ToTagged FINAL : public LDeferredCode {
-   public:
-    DeferredSIMD128ToTagged(LCodeGen* codegen, LInstruction* instr,
-                            Runtime::FunctionId id)
-        : LDeferredCode(codegen), instr_(instr), id_(id) { }
-    virtual void Generate() OVERRIDE {
-      codegen()->DoDeferredSIMD128ToTagged(instr_, id_);
-    }
-    virtual LInstruction* instr() OVERRIDE { return instr_; }
-   private:
-    LInstruction* instr_;
-    Runtime::FunctionId id_;
-  };
-
-  // Allocate a SIMD128 object on the heap.
-  Register reg = ToRegister(instr->result());
-  Register temp = ToRegister(instr->temp());
-  Register temp2 = ToRegister(instr->temp2());
-  Register scratch = scratch0();
-
-  DeferredSIMD128ToTagged* deferred = new(zone()) DeferredSIMD128ToTagged(
-      this, instr, static_cast<Runtime::FunctionId>(T::kRuntimeAllocatorId()));
-  __ jmp(deferred->entry());
-  __ bind(deferred->exit());
-
-  // Copy the SIMD128 value from the external array to the heap object.
-  STATIC_ASSERT(T::kValueSize % kPointerSize == 0);
-  Register external_pointer = ToRegister(instr->elements());
-  Register key = no_reg;
-  ElementsKind elements_kind = instr->elements_kind();
-  bool key_is_constant = instr->key()->IsConstantOperand();
-  int constant_key = 0;
-  if (key_is_constant) {
-    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
-    if (constant_key & 0xF0000000) {
-      Abort(kArrayIndexConstantValueTooBig);
-    }
-  } else {
-    key = ToRegister(instr->key());
-  }
-  int element_size_shift = ElementsKindToShiftSize(elements_kind);
-  int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
-      ? (element_size_shift - kSmiTagSize) : element_size_shift;
-  int base_offset = instr->base_offset();
-  Operand operand = key_is_constant
-      ? Operand(constant_key << element_size_shift)
-      : Operand(key, LSL, shift_size);
-
-  __ add(scratch, external_pointer, operand);
-
-  // Load the inner FixedTypedArray.
-  __ ldr(temp2, MemOperand(reg, T::kValueOffset));
-
-  for (int offset = 0; offset < T::kValueSize; offset += kPointerSize) {
-    __ ldr(temp, MemOperand(scratch, base_offset + offset));
-    __ str(
-        temp,
-        MemOperand(
-            temp2,
-            FixedTypedArrayBase::kDataOffset - kHeapObjectTag + offset));
-  }
-
-  // Now that we have finished with the object's real address tag it
-  __ add(reg, reg, Operand(kHeapObjectTag));
-}
-
-
 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
   Register external_pointer = ToRegister(instr->elements());
   Register key = no_reg;
@@ -3334,12 +3249,6 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
     } else  {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
       __ vldr(result, scratch0(), base_offset);
     }
-  } else if (IsFloat32x4ElementsKind(elements_kind)) {
-    DoLoadKeyedSIMD128ExternalArray<Float32x4>(instr);
-  } else if (IsFloat64x2ElementsKind(elements_kind)) {
-    DoLoadKeyedSIMD128ExternalArray<Float64x2>(instr);
-  } else if (IsInt32x4ElementsKind(elements_kind)) {
-    DoLoadKeyedSIMD128ExternalArray<Int32x4>(instr);
   } else {
     Register result = ToRegister(instr->result());
     MemOperand mem_operand = PrepareKeyedOperand(
@@ -3373,19 +3282,13 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
         __ ldr(result, mem_operand);
         if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
           __ cmp(result, Operand(0x80000000));
-          DeoptimizeIf(cs, instr);
+          DeoptimizeIf(cs, instr, "negative value");
         }
         break;
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
       case EXTERNAL_FLOAT32_ELEMENTS:
       case EXTERNAL_FLOAT64_ELEMENTS:
-      case FLOAT32x4_ELEMENTS:
-      case FLOAT64x2_ELEMENTS:
-      case INT32x4_ELEMENTS:
-      case EXTERNAL_FLOAT32x4_ELEMENTS:
-      case EXTERNAL_FLOAT64x2_ELEMENTS:
-      case EXTERNAL_INT32x4_ELEMENTS:
       case FAST_HOLEY_DOUBLE_ELEMENTS:
       case FAST_HOLEY_ELEMENTS:
       case FAST_HOLEY_SMI_ELEMENTS:
@@ -3432,7 +3335,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
   if (instr->hydrogen()->RequiresHoleCheck()) {
     __ ldr(scratch, MemOperand(scratch, sizeof(kHoleNanLower32)));
     __ cmp(scratch, Operand(kHoleNanUpper32));
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "hole");
   }
 }
 
@@ -3466,11 +3369,11 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
   if (instr->hydrogen()->RequiresHoleCheck()) {
     if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
       __ SmiTst(result);
-      DeoptimizeIf(ne, instr);
+      DeoptimizeIf(ne, instr, "not a Smi");
     } else {
       __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
       __ cmp(result, scratch);
-      DeoptimizeIf(eq, instr);
+      DeoptimizeIf(eq, instr, "hole");
     }
   }
 }
@@ -3527,7 +3430,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
     EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
   }
 
-  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
 }
 
@@ -3612,9 +3515,9 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
 
   // Deoptimize if the receiver is not a JS object.
   __ SmiTst(receiver);
-  DeoptimizeIf(eq, instr);
+  DeoptimizeIf(eq, instr, "Smi");
   __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
-  DeoptimizeIf(lt, instr);
+  DeoptimizeIf(lt, instr, "not a JavaScript object");
 
   __ b(&result_in_receiver);
   __ bind(&global_object);
@@ -3649,7 +3552,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
   // adaptor frame below it.
   const uint32_t kArgumentsLimit = 1 * KB;
   __ cmp(length, Operand(kArgumentsLimit));
-  DeoptimizeIf(hi, instr);
+  DeoptimizeIf(hi, instr, "too many arguments");
 
   // Push the receiver and use the register to keep the original
   // number of arguments.
@@ -3779,7 +3682,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
   __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
   __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
   __ cmp(scratch, Operand(ip));
-  DeoptimizeIf(ne, instr);
+  DeoptimizeIf(ne, instr, "not a heap number");
 
   Label done;
   Register exponent = scratch0();
@@ -3847,7 +3750,7 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
   // if input is positive.
   __ rsb(result, input, Operand::Zero(), SetCC, mi);
   // Deoptimize on overflow.
-  DeoptimizeIf(vs, instr);
+  DeoptimizeIf(vs, instr, "overflow");
 }
 
 
@@ -3893,7 +3796,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
   Label done, exact;
 
   __ TryInt32Floor(result, input, input_high, double_scratch0(), &done, &exact);
-  DeoptimizeIf(al, instr);
+  DeoptimizeIf(al, instr, "lost precision or NaN");
 
   __ bind(&exact);
   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@@ -3901,7 +3804,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
     __ cmp(result, Operand::Zero());
     __ b(ne, &done);
     __ cmp(input_high, Operand::Zero());
-    DeoptimizeIf(mi, instr);
+    DeoptimizeIf(mi, instr, "minus zero");
   }
   __ bind(&done);
 }
@@ -3926,7 +3829,8 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
     __ VmovHigh(input_high, input);
     __ cmp(input_high, Operand::Zero());
-    DeoptimizeIf(mi, instr);  // [-0.5, -0].
+    // [-0.5, -0].
+    DeoptimizeIf(mi, instr, "minus zero");
   }
   __ VFPCompareAndSetFlags(input, dot_five);
   __ mov(result, Operand(1), LeaveCC, eq);  // +0.5.
@@ -3940,7 +3844,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
   // Reuse dot_five (double_scratch0) as we no longer need this value.
   __ TryInt32Floor(result, input_plus_dot_five, input_high, double_scratch0(),
                    &done, &done);
-  DeoptimizeIf(al, instr);
+  DeoptimizeIf(al, instr, "lost precision or NaN");
   __ bind(&done);
 }
 
@@ -4004,7 +3908,7 @@ void LCodeGen::DoPower(LPower* instr) {
     __ ldr(r6, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset));
     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
     __ cmp(r6, Operand(ip));
-    DeoptimizeIf(ne, instr);
+    DeoptimizeIf(ne, instr, "not a heap number");
     __ bind(&no_deopt);
     MathPowStub stub(isolate(), MathPowStub::TAGGED);
     __ CallStub(&stub);
@@ -4356,59 +4260,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
     __ stop("eliminated bounds check failed");
     __ bind(&done);
   } else {
-    DeoptimizeIf(cc, instr);
-  }
-}
-
-
-template<class T>
-void LCodeGen::DoStoreKeyedSIMD128ExternalArray(LStoreKeyed* instr) {
-  DCHECK(instr->value()->IsRegister());
-  Register temp = ToRegister(instr->temp());
-  Register temp2 = ToRegister(instr->temp2());
-  Register input_reg = ToRegister(instr->value());
-  __ SmiTst(input_reg);
-  DeoptimizeIf(eq, instr);
-  __ CompareObjectType(input_reg, temp, no_reg, T::kInstanceType);
-  DeoptimizeIf(ne, instr);
-
-  STATIC_ASSERT(T::kValueSize % kPointerSize == 0);
-  Register external_pointer = ToRegister(instr->elements());
-  Register key = no_reg;
-  ElementsKind elements_kind = instr->elements_kind();
-  bool key_is_constant = instr->key()->IsConstantOperand();
-  int constant_key = 0;
-  if (key_is_constant) {
-    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
-    if (constant_key & 0xF0000000) {
-      Abort(kArrayIndexConstantValueTooBig);
-    }
-  } else {
-    key = ToRegister(instr->key());
-  }
-  int element_size_shift = ElementsKindToShiftSize(elements_kind);
-  int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
-      ? (element_size_shift - kSmiTagSize) : element_size_shift;
-  int base_offset = instr->base_offset();
-  Register address = scratch0();
-  if (key_is_constant) {
-    if (constant_key != 0) {
-      __ add(address, external_pointer,
-          Operand(constant_key << element_size_shift));
-    } else {
-      address = external_pointer;
-    }
-  } else {
-    __ add(address, external_pointer, Operand(key, LSL, shift_size));
-  }
-
-  // Load the inner FixedTypedArray.
-  __ ldr(temp2, MemOperand(input_reg, T::kValueOffset - kHeapObjectTag));
-
-  for (int offset = 0; offset < T::kValueSize; offset += kPointerSize) {
-    __ ldr(temp, MemOperand(temp2,
-           FixedTypedArrayBase::kDataOffset - kHeapObjectTag + offset));
-    __ str(temp, MemOperand(address, base_offset + offset));
+    DeoptimizeIf(cc, instr, "out of bounds");
   }
 }
 
@@ -4455,12 +4307,6 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
     } else {  // Storing doubles, not floats.
       __ vstr(value, address, base_offset);
     }
-  } else if (IsFloat32x4ElementsKind(elements_kind)) {
-    DoStoreKeyedSIMD128ExternalArray<Float32x4>(instr);
-  } else if (IsFloat64x2ElementsKind(elements_kind)) {
-    DoStoreKeyedSIMD128ExternalArray<Float64x2>(instr);
-  } else if (IsInt32x4ElementsKind(elements_kind)) {
-    DoStoreKeyedSIMD128ExternalArray<Int32x4>(instr);
   } else {
     Register value(ToRegister(instr->value()));
     MemOperand mem_operand = PrepareKeyedOperand(
@@ -4492,12 +4338,6 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
       case FLOAT64_ELEMENTS:
       case EXTERNAL_FLOAT32_ELEMENTS:
       case EXTERNAL_FLOAT64_ELEMENTS:
-      case FLOAT32x4_ELEMENTS:
-      case FLOAT64x2_ELEMENTS:
-      case INT32x4_ELEMENTS:
-      case EXTERNAL_FLOAT32x4_ELEMENTS:
-      case EXTERNAL_FLOAT64x2_ELEMENTS:
-      case EXTERNAL_INT32x4_ELEMENTS:
       case FAST_DOUBLE_ELEMENTS:
       case FAST_ELEMENTS:
       case FAST_SMI_ELEMENTS:
@@ -4668,7 +4508,7 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
   Register temp = ToRegister(instr->temp());
   Label no_memento_found;
   __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
-  DeoptimizeIf(eq, instr);
+  DeoptimizeIf(eq, instr, "memento found");
   __ bind(&no_memento_found);
 }
 
@@ -5002,12 +4842,12 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) {
   if (hchange->CheckFlag(HValue::kCanOverflow) &&
       hchange->value()->CheckFlag(HValue::kUint32)) {
     __ tst(input, Operand(0xc0000000));
-    DeoptimizeIf(ne, instr);
+    DeoptimizeIf(ne, instr, "overflow");
   }
   if (hchange->CheckFlag(HValue::kCanOverflow) &&
       !hchange->value()->CheckFlag(HValue::kUint32)) {
     __ SmiTag(output, input, SetCC);
-    DeoptimizeIf(vs, instr);
+    DeoptimizeIf(vs, instr, "overflow");
   } else {
     __ SmiTag(output, input);
   }
@@ -5021,7 +4861,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
     STATIC_ASSERT(kHeapObjectTag == 1);
     // If the input is a HeapObject, SmiUntag will set the carry flag.
     __ SmiUntag(result, input, SetCC);
-    DeoptimizeIf(cs, instr);
+    DeoptimizeIf(cs, instr, "not a Smi");
   } else {
     __ SmiUntag(result, input);
   }
@@ -5049,7 +4889,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
     if (can_convert_undefined_to_nan) {
       __ b(ne, &convert);
     } else {
-      DeoptimizeIf(ne, instr);
+      DeoptimizeIf(ne, instr, "not a heap number");
     }
     // load heap number
     __ vldr(result_reg, input_reg, HeapNumber::kValueOffset - kHeapObjectTag);
@@ -5059,7 +4899,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
       __ b(ne, &done);
       __ VmovHigh(scratch, result_reg);
       __ cmp(scratch, Operand(HeapNumber::kSignMask));
-      DeoptimizeIf(eq, instr);
+      DeoptimizeIf(eq, instr, "minus zero");
     }
     __ jmp(&done);
     if (can_convert_undefined_to_nan) {
@@ -5067,7 +4907,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
       // Convert undefined (and hole) to NaN.
       __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
       __ cmp(input_reg, Operand(ip));
-      DeoptimizeIf(ne, instr);
+      DeoptimizeIf(ne, instr, "not a heap number/undefined");
       __ LoadRoot(scratch, Heap::kNanValueRootIndex);
       __ vldr(result_reg, scratch, HeapNumber::kValueOffset - kHeapObjectTag);
       __ jmp(&done);
@@ -5135,7 +4975,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
     __ bind(&check_false);
     __ LoadRoot(ip, Heap::kFalseValueRootIndex);
     __ cmp(scratch2, Operand(ip));
-    DeoptimizeIf(ne, instr, "cannot truncate");
+    DeoptimizeIf(ne, instr, "not a heap number/undefined/true/false");
     __ mov(input_reg, Operand::Zero());
   } else {
     DeoptimizeIf(ne, instr, "not a heap number");
@@ -5220,14 +5060,14 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
   } else {
     __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch);
     // Deoptimize if the input wasn't a int32 (inside a double).
-    DeoptimizeIf(ne, instr);
+    DeoptimizeIf(ne, instr, "lost precision or NaN");
     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
       Label done;
       __ cmp(result_reg, Operand::Zero());
       __ b(ne, &done);
       __ VmovHigh(scratch1, double_input);
       __ tst(scratch1, Operand(HeapNumber::kSignMask));
-      DeoptimizeIf(ne, instr);
+      DeoptimizeIf(ne, instr, "minus zero");
       __ bind(&done);
     }
   }
@@ -5245,26 +5085,26 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
   } else {
     __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch);
     // Deoptimize if the input wasn't a int32 (inside a double).
-    DeoptimizeIf(ne, instr);
+    DeoptimizeIf(ne, instr, "lost precision or NaN");
     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
       Label done;
       __ cmp(result_reg, Operand::Zero());
       __ b(ne, &done);
       __ VmovHigh(scratch1, double_input);
       __ tst(scratch1, Operand(HeapNumber::kSignMask));
-      DeoptimizeIf(ne, instr);
+      DeoptimizeIf(ne, instr, "minus zero");
       __ bind(&done);
     }
   }
   __ SmiTag(result_reg, SetCC);
-  DeoptimizeIf(vs, instr);
+  DeoptimizeIf(vs, instr, "overflow");
 }
 
 
 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
   LOperand* input = instr->value();
   __ SmiTst(ToRegister(input));
-  DeoptimizeIf(ne, instr);
+  DeoptimizeIf(ne, instr, "not a Smi");
 }
 
 
@@ -5272,7 +5112,7 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
     LOperand* input = instr->value();
     __ SmiTst(ToRegister(input));
-    DeoptimizeIf(eq, instr);
+    DeoptimizeIf(eq, instr, "Smi");
   }
 }
 
@@ -5293,13 +5133,13 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
 
     // If there is only one type in the interval check for equality.
     if (first == last) {
-      DeoptimizeIf(ne, instr);
+      DeoptimizeIf(ne, instr, "wrong instance type");
     } else {
-      DeoptimizeIf(lo, instr);
+      DeoptimizeIf(lo, instr, "wrong instance type");
       // Omit check for the last type.
       if (last != LAST_TYPE) {
         __ cmp(scratch, Operand(last));
-        DeoptimizeIf(hi, instr);
+        DeoptimizeIf(hi, instr, "wrong instance type");
       }
     }
   } else {
@@ -5310,11 +5150,11 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
     if (base::bits::IsPowerOfTwo32(mask)) {
       DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
       __ tst(scratch, Operand(mask));
-      DeoptimizeIf(tag == 0 ? ne : eq, instr);
+      DeoptimizeIf(tag == 0 ? ne : eq, instr, "wrong instance type");
     } else {
       __ and_(scratch, scratch, Operand(mask));
       __ cmp(scratch, Operand(tag));
-      DeoptimizeIf(ne, instr);
+      DeoptimizeIf(ne, instr, "wrong instance type");
     }
   }
 }
@@ -5333,7 +5173,7 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
   } else {
     __ cmp(reg, Operand(object));
   }
-  DeoptimizeIf(ne, instr);
+  DeoptimizeIf(ne, instr, "value mismatch");
 }
 
 
@@ -5348,7 +5188,7 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
     __ StoreToSafepointRegisterSlot(r0, scratch0());
   }
   __ tst(scratch0(), Operand(kSmiTagMask));
-  DeoptimizeIf(eq, instr);
+  DeoptimizeIf(eq, instr, "instance migration failed");
 }
 
 
@@ -5405,7 +5245,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
   if (instr->hydrogen()->HasMigrationTarget()) {
     __ b(ne, deferred->entry());
   } else {
-    DeoptimizeIf(ne, instr);
+    DeoptimizeIf(ne, instr, "wrong map");
   }
 
   __ bind(&success);
@@ -5444,7 +5284,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
   // Check for undefined. Undefined is converted to zero for clamping
   // conversions.
   __ cmp(input_reg, Operand(factory()->undefined_value()));
-  DeoptimizeIf(ne, instr);
+  DeoptimizeIf(ne, instr, "not a heap number/undefined");
   __ mov(result_reg, Operand::Zero());
   __ jmp(&done);
 
@@ -5914,19 +5754,19 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
   __ cmp(r0, ip);
-  DeoptimizeIf(eq, instr);
+  DeoptimizeIf(eq, instr, "undefined");
 
   Register null_value = r5;
   __ LoadRoot(null_value, Heap::kNullValueRootIndex);
   __ cmp(r0, null_value);
-  DeoptimizeIf(eq, instr);
+  DeoptimizeIf(eq, instr, "null");
 
   __ SmiTst(r0);
-  DeoptimizeIf(eq, instr);
+  DeoptimizeIf(eq, instr, "Smi");
 
   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
   __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE);
-  DeoptimizeIf(le, instr);
+  DeoptimizeIf(le, instr, "wrong instance type");
 
   Label use_cache, call_runtime;
   __ CheckEnumCache(null_value, &call_runtime);
@@ -5942,7 +5782,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
   __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
   __ LoadRoot(ip, Heap::kMetaMapRootIndex);
   __ cmp(r1, ip);
-  DeoptimizeIf(ne, instr);
+  DeoptimizeIf(ne, instr, "wrong map");
   __ bind(&use_cache);
 }
 
@@ -5964,7 +5804,7 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
   __ ldr(result,
          FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
   __ cmp(result, Operand::Zero());
-  DeoptimizeIf(eq, instr);
+  DeoptimizeIf(eq, instr, "no cache");
 
   __ bind(&done);
 }
@@ -5975,7 +5815,7 @@ void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
   Register map = ToRegister(instr->map());
   __ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
   __ cmp(map, scratch0());
-  DeoptimizeIf(ne, instr);
+  DeoptimizeIf(ne, instr, "wrong map");
 }