Externalize deoptimization reasons.

1) The hardcoded strings were converted into DeoptReason enum.

2) Deopt comment were converted into a pair location and deopt reason entries so
the deopt reason tracking mode would less affect the size of the RelocInfo table and heap.

3) DeoptReason entry in RelocInfo reuses kCommentTag value and generates short entry in RelocInfo table.

BUG=452067
LOG=n

Committed: https://crrev.com/c49820e45b57f128a98690940875c049f612dde6
Cr-Commit-Position: refs/heads/master@{#26434}

Committed: https://crrev.com/ec42e002da03adb2db968dd5b7453341ddc59a5c
Cr-Commit-Position: refs/heads/master@{#26448}

Review URL: https://codereview.chromium.org/874323003

Cr-Commit-Position: refs/heads/master@{#26463}
This commit is contained in:
loislo 2015-02-05 06:51:45 -08:00 committed by Commit bot
parent 197ed66714
commit 2491a639bf
34 changed files with 1236 additions and 921 deletions

View File

@ -3377,6 +3377,15 @@ void Assembler::RecordComment(const char* msg) {
}
void Assembler::RecordDeoptReason(const int reason, const int raw_position) {
if (FLAG_trace_deopt) {
EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::POSITION, raw_position);
RecordRelocInfo(RelocInfo::DEOPT_REASON, reason);
}
}
void Assembler::RecordConstPool(int size) {
// We only need this for debugger support, to correctly compute offsets in the
// code.

View File

@ -1398,6 +1398,10 @@ class Assembler : public AssemblerBase {
// Use --code-comments to enable.
void RecordComment(const char* msg);
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(const int reason, const int raw_position);
// Record the emission of a constant pool.
//
// The emission of constant pool depends on the size of the code generated and

View File

@ -840,7 +840,7 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
const char* detail,
Deoptimizer::DeoptReason deopt_reason,
Deoptimizer::BailoutType bailout_type) {
LEnvironment* environment = instr->environment();
RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
@ -894,7 +894,7 @@ void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
}
Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(),
instr->Mnemonic(), detail);
instr->Mnemonic(), deopt_reason);
DCHECK(info()->IsStub() || frame_is_built_);
// Go through jump table if we need to handle condition, build frame, or
// restore caller doubles.
@ -917,11 +917,11 @@ void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
const char* detail) {
Deoptimizer::DeoptReason deopt_reason) {
Deoptimizer::BailoutType bailout_type = info()->IsStub()
? Deoptimizer::LAZY
: Deoptimizer::EAGER;
DeoptimizeIf(condition, instr, detail, bailout_type);
DeoptimizeIf(condition, instr, deopt_reason, bailout_type);
}
@ -1157,7 +1157,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, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
__ b(&done);
}
@ -1175,7 +1175,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
DCHECK(!dividend.is(result));
if (divisor == 0) {
DeoptimizeIf(al, instr, "division by zero");
DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1190,7 +1190,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
Label remainder_not_zero;
__ b(ne, &remainder_not_zero);
__ cmp(dividend, Operand::Zero());
DeoptimizeIf(lt, instr, "minus zero");
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
__ bind(&remainder_not_zero);
}
}
@ -1210,7 +1210,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, "division by zero");
DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero);
}
// Check for kMinInt % -1, sdiv will return kMinInt, which is not what we
@ -1221,7 +1221,7 @@ void LCodeGen::DoModI(LModI* instr) {
__ b(ne, &no_overflow_possible);
__ cmp(right_reg, Operand(-1));
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
} else {
__ b(ne, &no_overflow_possible);
__ mov(result_reg, Operand::Zero());
@ -1242,7 +1242,7 @@ void LCodeGen::DoModI(LModI* instr) {
__ cmp(result_reg, Operand::Zero());
__ b(ne, &done);
__ cmp(left_reg, Operand::Zero());
DeoptimizeIf(lt, instr, "minus zero");
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
}
__ bind(&done);
@ -1267,7 +1267,7 @@ void LCodeGen::DoModI(LModI* instr) {
// NaN.
if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
__ cmp(right_reg, Operand::Zero());
DeoptimizeIf(eq, instr, "division by zero");
DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero);
}
__ Move(result_reg, left_reg);
@ -1297,7 +1297,7 @@ void LCodeGen::DoModI(LModI* instr) {
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ b(ne, &done);
__ cmp(left_reg, Operand::Zero());
DeoptimizeIf(mi, instr, "minus zero");
DeoptimizeIf(mi, instr, Deoptimizer::kMinusZero);
}
__ bind(&done);
}
@ -1315,19 +1315,19 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ cmp(dividend, Operand::Zero());
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
// Check for (kMinInt / -1).
if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
__ cmp(dividend, Operand(kMinInt));
DeoptimizeIf(eq, instr, "overflow");
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow);
}
// 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, "lost precision");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision);
}
if (divisor == -1) { // Nice shortcut, not needed for correctness.
@ -1355,7 +1355,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
DCHECK(!dividend.is(result));
if (divisor == 0) {
DeoptimizeIf(al, instr, "division by zero");
DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1363,7 +1363,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ cmp(dividend, Operand::Zero());
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
__ TruncatingDiv(result, dividend, Abs(divisor));
@ -1373,7 +1373,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
__ mov(ip, Operand(divisor));
__ smull(scratch0(), ip, result, ip);
__ sub(scratch0(), scratch0(), dividend, SetCC);
DeoptimizeIf(ne, instr, "lost precision");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision);
}
}
@ -1388,7 +1388,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ cmp(divisor, Operand::Zero());
DeoptimizeIf(eq, instr, "division by zero");
DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero);
}
// Check for (0 / -x) that will produce negative zero.
@ -1400,7 +1400,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
}
__ b(pl, &positive);
__ cmp(dividend, Operand::Zero());
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
__ bind(&positive);
}
@ -1412,7 +1412,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, "overflow");
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow);
}
if (CpuFeatures::IsSupported(SUDIV)) {
@ -1435,7 +1435,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
Register remainder = scratch0();
__ Mls(remainder, result, divisor, dividend);
__ cmp(remainder, Operand::Zero());
DeoptimizeIf(ne, instr, "lost precision");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision);
}
}
@ -1486,13 +1486,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, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
// Dividing by -1 is basically negation, unless we overflow.
if (divisor == -1) {
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
}
return;
}
@ -1515,7 +1515,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
DCHECK(!dividend.is(result));
if (divisor == 0) {
DeoptimizeIf(al, instr, "division by zero");
DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1523,7 +1523,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
HMathFloorOfDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ cmp(dividend, Operand::Zero());
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
// Easy case: We need no dynamic check for the dividend and the flooring
@ -1564,7 +1564,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ cmp(right, Operand::Zero());
DeoptimizeIf(eq, instr, "division by zero");
DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero);
}
// Check for (0 / -x) that will produce negative zero.
@ -1576,7 +1576,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
}
__ b(pl, &positive);
__ cmp(left, Operand::Zero());
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
__ bind(&positive);
}
@ -1588,7 +1588,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, "overflow");
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow);
}
if (CpuFeatures::IsSupported(SUDIV)) {
@ -1634,14 +1634,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, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
switch (constant) {
case -1:
if (overflow) {
__ rsb(result, left, Operand::Zero(), SetCC);
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
} else {
__ rsb(result, left, Operand::Zero());
}
@ -1651,7 +1651,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, "minus zero");
DeoptimizeIf(mi, instr, Deoptimizer::kMinusZero);
}
__ mov(result, Operand::Zero());
break;
@ -1701,7 +1701,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ smull(result, scratch, left, right);
}
__ cmp(scratch, Operand(result, ASR, 31));
DeoptimizeIf(ne, instr, "overflow");
DeoptimizeIf(ne, instr, Deoptimizer::kOverflow);
} else {
if (instr->hydrogen()->representation().IsSmi()) {
__ SmiUntag(result, left);
@ -1717,7 +1717,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ b(pl, &done);
// Bail out if the result is minus zero.
__ cmp(result, Operand::Zero());
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
__ bind(&done);
}
}
@ -1780,7 +1780,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
case Token::SHR:
if (instr->can_deopt()) {
__ mov(result, Operand(left, LSR, scratch), SetCC);
DeoptimizeIf(mi, instr, "negative value");
DeoptimizeIf(mi, instr, Deoptimizer::kNegativeValue);
} else {
__ mov(result, Operand(left, LSR, scratch));
}
@ -1817,7 +1817,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
} else {
if (instr->can_deopt()) {
__ tst(left, Operand(0x80000000));
DeoptimizeIf(ne, instr, "negative value");
DeoptimizeIf(ne, instr, Deoptimizer::kNegativeValue);
}
__ Move(result, left);
}
@ -1832,7 +1832,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
} else {
__ SmiTag(result, left, SetCC);
}
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
} else {
__ mov(result, Operand(left, LSL, shift_count));
}
@ -1864,7 +1864,7 @@ void LCodeGen::DoSubI(LSubI* instr) {
}
if (can_overflow) {
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
}
}
@ -1885,7 +1885,7 @@ void LCodeGen::DoRSubI(LRSubI* instr) {
}
if (can_overflow) {
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
}
}
@ -1953,9 +1953,9 @@ void LCodeGen::DoDateField(LDateField* instr) {
DCHECK(!scratch.is(object));
__ SmiTst(object);
DeoptimizeIf(eq, instr, "Smi");
DeoptimizeIf(eq, instr, Deoptimizer::kSmi);
__ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE);
DeoptimizeIf(ne, instr, "not a date object");
DeoptimizeIf(ne, instr, Deoptimizer::kNotADateObject);
if (index->value() == 0) {
__ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
@ -2072,7 +2072,7 @@ void LCodeGen::DoAddI(LAddI* instr) {
}
if (can_overflow) {
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
}
}
@ -2297,7 +2297,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, "Smi");
DeoptimizeIf(eq, instr, Deoptimizer::kSmi);
}
const Register map = scratch0();
@ -2353,7 +2353,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, "unexpected object");
DeoptimizeIf(al, instr, Deoptimizer::kUnexpectedObject);
}
}
}
@ -2999,7 +2999,7 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(result, ip);
DeoptimizeIf(eq, instr, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
}
}
@ -3054,7 +3054,7 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
Register payload = ToRegister(instr->temp());
__ ldr(payload, FieldMemOperand(cell, Cell::kValueOffset));
__ CompareRoot(payload, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
}
// Store the value.
@ -3071,7 +3071,7 @@ void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(result, ip);
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(eq, instr, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
} else {
__ mov(result, Operand(factory()->undefined_value()), LeaveCC, eq);
}
@ -3092,7 +3092,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(scratch, ip);
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(eq, instr, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
} else {
__ b(ne, &skip_assignment);
}
@ -3173,7 +3173,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, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
// If the function does not have an initial map, we're done.
Label done;
@ -3299,7 +3299,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
__ ldr(result, mem_operand);
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
__ cmp(result, Operand(0x80000000));
DeoptimizeIf(cs, instr, "negative value");
DeoptimizeIf(cs, instr, Deoptimizer::kNegativeValue);
}
break;
case FLOAT32_ELEMENTS:
@ -3352,7 +3352,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
__ ldr(scratch, MemOperand(scratch, sizeof(kHoleNanLower32)));
__ cmp(scratch, Operand(kHoleNanUpper32));
DeoptimizeIf(eq, instr, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
}
}
@ -3386,11 +3386,11 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
__ SmiTst(result);
DeoptimizeIf(ne, instr, "not a Smi");
DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi);
} else {
__ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
__ cmp(result, scratch);
DeoptimizeIf(eq, instr, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
}
}
}
@ -3532,9 +3532,9 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
// Deoptimize if the receiver is not a JS object.
__ SmiTst(receiver);
DeoptimizeIf(eq, instr, "Smi");
DeoptimizeIf(eq, instr, Deoptimizer::kSmi);
__ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
DeoptimizeIf(lt, instr, "not a JavaScript object");
DeoptimizeIf(lt, instr, Deoptimizer::kNotAJavaScriptObject);
__ b(&result_in_receiver);
__ bind(&global_object);
@ -3569,7 +3569,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// adaptor frame below it.
const uint32_t kArgumentsLimit = 1 * KB;
__ cmp(length, Operand(kArgumentsLimit));
DeoptimizeIf(hi, instr, "too many arguments");
DeoptimizeIf(hi, instr, Deoptimizer::kTooManyArguments);
// Push the receiver and use the register to keep the original
// number of arguments.
@ -3695,7 +3695,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
__ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
__ cmp(scratch, Operand(ip));
DeoptimizeIf(ne, instr, "not a heap number");
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
Label done;
Register exponent = scratch0();
@ -3763,7 +3763,7 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
// if input is positive.
__ rsb(result, input, Operand::Zero(), SetCC, mi);
// Deoptimize on overflow.
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
}
@ -3810,7 +3810,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
Label done, exact;
__ TryInt32Floor(result, input, input_high, double_scratch0(), &done, &exact);
DeoptimizeIf(al, instr, "lost precision or NaN");
DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN);
__ bind(&exact);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -3818,7 +3818,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ cmp(result, Operand::Zero());
__ b(ne, &done);
__ cmp(input_high, Operand::Zero());
DeoptimizeIf(mi, instr, "minus zero");
DeoptimizeIf(mi, instr, Deoptimizer::kMinusZero);
}
__ bind(&done);
}
@ -3844,7 +3844,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
__ VmovHigh(input_high, input);
__ cmp(input_high, Operand::Zero());
// [-0.5, -0].
DeoptimizeIf(mi, instr, "minus zero");
DeoptimizeIf(mi, instr, Deoptimizer::kMinusZero);
}
__ VFPCompareAndSetFlags(input, dot_five);
__ mov(result, Operand(1), LeaveCC, eq); // +0.5.
@ -3858,7 +3858,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, "lost precision or NaN");
DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN);
__ bind(&done);
}
@ -3922,7 +3922,7 @@ void LCodeGen::DoPower(LPower* instr) {
__ ldr(r6, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
__ cmp(r6, Operand(ip));
DeoptimizeIf(ne, instr, "not a heap number");
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
__ bind(&no_deopt);
MathPowStub stub(isolate(), MathPowStub::TAGGED);
__ CallStub(&stub);
@ -4331,7 +4331,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
__ stop("eliminated bounds check failed");
__ bind(&done);
} else {
DeoptimizeIf(cc, instr, "out of bounds");
DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds);
}
}
@ -4579,7 +4579,7 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
Register temp = ToRegister(instr->temp());
Label no_memento_found;
__ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
DeoptimizeIf(eq, instr, "memento found");
DeoptimizeIf(eq, instr, Deoptimizer::kMementoFound);
__ bind(&no_memento_found);
}
@ -4914,12 +4914,12 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) {
if (hchange->CheckFlag(HValue::kCanOverflow) &&
hchange->value()->CheckFlag(HValue::kUint32)) {
__ tst(input, Operand(0xc0000000));
DeoptimizeIf(ne, instr, "overflow");
DeoptimizeIf(ne, instr, Deoptimizer::kOverflow);
}
if (hchange->CheckFlag(HValue::kCanOverflow) &&
!hchange->value()->CheckFlag(HValue::kUint32)) {
__ SmiTag(output, input, SetCC);
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
} else {
__ SmiTag(output, input);
}
@ -4933,7 +4933,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, "not a Smi");
DeoptimizeIf(cs, instr, Deoptimizer::kNotASmi);
} else {
__ SmiUntag(result, input);
}
@ -4961,7 +4961,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
if (can_convert_undefined_to_nan) {
__ b(ne, &convert);
} else {
DeoptimizeIf(ne, instr, "not a heap number");
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
}
// load heap number
__ vldr(result_reg, input_reg, HeapNumber::kValueOffset - kHeapObjectTag);
@ -4971,7 +4971,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
__ b(ne, &done);
__ VmovHigh(scratch, result_reg);
__ cmp(scratch, Operand(HeapNumber::kSignMask));
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
__ jmp(&done);
if (can_convert_undefined_to_nan) {
@ -4979,7 +4979,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, "not a heap number/undefined");
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined);
__ LoadRoot(scratch, Heap::kNanValueRootIndex);
__ vldr(result_reg, scratch, HeapNumber::kValueOffset - kHeapObjectTag);
__ jmp(&done);
@ -5047,22 +5047,22 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
__ bind(&check_false);
__ LoadRoot(ip, Heap::kFalseValueRootIndex);
__ cmp(scratch2, Operand(ip));
DeoptimizeIf(ne, instr, "not a heap number/undefined/true/false");
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedBoolean);
__ mov(input_reg, Operand::Zero());
} else {
DeoptimizeIf(ne, instr, "not a heap number");
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
__ sub(ip, scratch2, Operand(kHeapObjectTag));
__ vldr(double_scratch2, ip, HeapNumber::kValueOffset);
__ TryDoubleToInt32Exact(input_reg, double_scratch2, double_scratch);
DeoptimizeIf(ne, instr, "lost precision or NaN");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ cmp(input_reg, Operand::Zero());
__ b(ne, &done);
__ VmovHigh(scratch1, double_scratch2);
__ tst(scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr, "minus zero");
DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero);
}
}
__ bind(&done);
@ -5131,14 +5131,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, "lost precision or NaN");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
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, "minus zero");
DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero);
__ bind(&done);
}
}
@ -5156,26 +5156,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, "lost precision or NaN");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
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, "minus zero");
DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero);
__ bind(&done);
}
}
__ SmiTag(result_reg, SetCC);
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
}
void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
LOperand* input = instr->value();
__ SmiTst(ToRegister(input));
DeoptimizeIf(ne, instr, "not a Smi");
DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi);
}
@ -5183,7 +5183,7 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
if (!instr->hydrogen()->value()->type().IsHeapObject()) {
LOperand* input = instr->value();
__ SmiTst(ToRegister(input));
DeoptimizeIf(eq, instr, "Smi");
DeoptimizeIf(eq, instr, Deoptimizer::kSmi);
}
}
@ -5204,13 +5204,13 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
// If there is only one type in the interval check for equality.
if (first == last) {
DeoptimizeIf(ne, instr, "wrong instance type");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType);
} else {
DeoptimizeIf(lo, instr, "wrong instance type");
DeoptimizeIf(lo, instr, Deoptimizer::kWrongInstanceType);
// Omit check for the last type.
if (last != LAST_TYPE) {
__ cmp(scratch, Operand(last));
DeoptimizeIf(hi, instr, "wrong instance type");
DeoptimizeIf(hi, instr, Deoptimizer::kWrongInstanceType);
}
}
} else {
@ -5221,11 +5221,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, "wrong instance type");
DeoptimizeIf(tag == 0 ? ne : eq, instr, Deoptimizer::kWrongInstanceType);
} else {
__ and_(scratch, scratch, Operand(mask));
__ cmp(scratch, Operand(tag));
DeoptimizeIf(ne, instr, "wrong instance type");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType);
}
}
}
@ -5244,7 +5244,7 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
} else {
__ cmp(reg, Operand(object));
}
DeoptimizeIf(ne, instr, "value mismatch");
DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch);
}
@ -5259,7 +5259,7 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
__ StoreToSafepointRegisterSlot(r0, scratch0());
}
__ tst(scratch0(), Operand(kSmiTagMask));
DeoptimizeIf(eq, instr, "instance migration failed");
DeoptimizeIf(eq, instr, Deoptimizer::kInstanceMigrationFailed);
}
@ -5317,7 +5317,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
if (instr->hydrogen()->HasMigrationTarget()) {
__ b(ne, deferred->entry());
} else {
DeoptimizeIf(ne, instr, "wrong map");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
}
__ bind(&success);
@ -5356,7 +5356,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, "not a heap number/undefined");
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined);
__ mov(result_reg, Operand::Zero());
__ jmp(&done);
@ -5824,19 +5824,19 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(r0, ip);
DeoptimizeIf(eq, instr, "undefined");
DeoptimizeIf(eq, instr, Deoptimizer::kUndefined);
Register null_value = r5;
__ LoadRoot(null_value, Heap::kNullValueRootIndex);
__ cmp(r0, null_value);
DeoptimizeIf(eq, instr, "null");
DeoptimizeIf(eq, instr, Deoptimizer::kNull);
__ SmiTst(r0);
DeoptimizeIf(eq, instr, "Smi");
DeoptimizeIf(eq, instr, Deoptimizer::kSmi);
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
__ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE);
DeoptimizeIf(le, instr, "wrong instance type");
DeoptimizeIf(le, instr, Deoptimizer::kWrongInstanceType);
Label use_cache, call_runtime;
__ CheckEnumCache(null_value, &call_runtime);
@ -5852,7 +5852,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kMetaMapRootIndex);
__ cmp(r1, ip);
DeoptimizeIf(ne, instr, "wrong map");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
__ bind(&use_cache);
}
@ -5874,7 +5874,7 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
__ ldr(result,
FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
__ cmp(result, Operand::Zero());
DeoptimizeIf(eq, instr, "no cache");
DeoptimizeIf(eq, instr, Deoptimizer::kNoCache);
__ bind(&done);
}
@ -5885,7 +5885,7 @@ void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
Register map = ToRegister(instr->map());
__ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
__ cmp(map, scratch0());
DeoptimizeIf(ne, instr, "wrong map");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
}

View File

@ -228,9 +228,10 @@ class LCodeGen: public LCodeGenBase {
void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
Safepoint::DeoptMode mode);
void DeoptimizeIf(Condition condition, LInstruction* instr,
const char* detail, Deoptimizer::BailoutType bailout_type);
Deoptimizer::DeoptReason deopt_reason,
Deoptimizer::BailoutType bailout_type);
void DeoptimizeIf(Condition condition, LInstruction* instr,
const char* detail);
Deoptimizer::DeoptReason deopt_reason);
void AddToTranslation(LEnvironment* environment,
Translation* translation,

View File

@ -3077,6 +3077,15 @@ void Assembler::RecordComment(const char* msg) {
}
void Assembler::RecordDeoptReason(const int reason, const int raw_position) {
if (FLAG_trace_deopt) {
EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::POSITION, raw_position);
RecordRelocInfo(RelocInfo::DEOPT_REASON, reason);
}
}
int Assembler::buffer_space() const {
return reloc_info_writer.pos() - reinterpret_cast<byte*>(pc_);
}

View File

@ -1007,6 +1007,11 @@ class Assembler : public AssemblerBase {
// Debugging ----------------------------------------------------------------
PositionsRecorder* positions_recorder() { return &positions_recorder_; }
void RecordComment(const char* msg);
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(const int reason, const int raw_position);
int buffer_space() const;
// Mark address of the ExitJSFrame code.

View File

@ -1005,8 +1005,9 @@ void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() {
void LCodeGen::DeoptimizeBranch(
LInstruction* instr, const char* detail, BranchType branch_type,
Register reg, int bit, Deoptimizer::BailoutType* override_bailout_type) {
LInstruction* instr, Deoptimizer::DeoptReason deopt_reason,
BranchType branch_type, Register reg, int bit,
Deoptimizer::BailoutType* override_bailout_type) {
LEnvironment* environment = instr->environment();
RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
Deoptimizer::BailoutType bailout_type =
@ -1057,7 +1058,7 @@ void LCodeGen::DeoptimizeBranch(
}
Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(),
instr->Mnemonic(), detail);
instr->Mnemonic(), deopt_reason);
DCHECK(info()->IsStub() || frame_is_built_);
// Go through jump table if we need to build frame, or restore caller doubles.
if (branch_type == always &&
@ -1079,85 +1080,89 @@ void LCodeGen::DeoptimizeBranch(
}
void LCodeGen::Deoptimize(LInstruction* instr, const char* detail,
void LCodeGen::Deoptimize(LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason,
Deoptimizer::BailoutType* override_bailout_type) {
DeoptimizeBranch(instr, detail, always, NoReg, -1, override_bailout_type);
DeoptimizeBranch(instr, deopt_reason, always, NoReg, -1,
override_bailout_type);
}
void LCodeGen::DeoptimizeIf(Condition cond, LInstruction* instr,
const char* detail) {
DeoptimizeBranch(instr, detail, static_cast<BranchType>(cond));
Deoptimizer::DeoptReason deopt_reason) {
DeoptimizeBranch(instr, deopt_reason, static_cast<BranchType>(cond));
}
void LCodeGen::DeoptimizeIfZero(Register rt, LInstruction* instr,
const char* detail) {
DeoptimizeBranch(instr, detail, reg_zero, rt);
Deoptimizer::DeoptReason deopt_reason) {
DeoptimizeBranch(instr, deopt_reason, reg_zero, rt);
}
void LCodeGen::DeoptimizeIfNotZero(Register rt, LInstruction* instr,
const char* detail) {
DeoptimizeBranch(instr, detail, reg_not_zero, rt);
Deoptimizer::DeoptReason deopt_reason) {
DeoptimizeBranch(instr, deopt_reason, reg_not_zero, rt);
}
void LCodeGen::DeoptimizeIfNegative(Register rt, LInstruction* instr,
const char* detail) {
Deoptimizer::DeoptReason deopt_reason) {
int sign_bit = rt.Is64Bits() ? kXSignBit : kWSignBit;
DeoptimizeIfBitSet(rt, sign_bit, instr, detail);
DeoptimizeIfBitSet(rt, sign_bit, instr, deopt_reason);
}
void LCodeGen::DeoptimizeIfSmi(Register rt, LInstruction* instr,
const char* detail) {
DeoptimizeIfBitClear(rt, MaskToBit(kSmiTagMask), instr, detail);
Deoptimizer::DeoptReason deopt_reason) {
DeoptimizeIfBitClear(rt, MaskToBit(kSmiTagMask), instr, deopt_reason);
}
void LCodeGen::DeoptimizeIfNotSmi(Register rt, LInstruction* instr,
const char* detail) {
DeoptimizeIfBitSet(rt, MaskToBit(kSmiTagMask), instr, detail);
Deoptimizer::DeoptReason deopt_reason) {
DeoptimizeIfBitSet(rt, MaskToBit(kSmiTagMask), instr, deopt_reason);
}
void LCodeGen::DeoptimizeIfRoot(Register rt, Heap::RootListIndex index,
LInstruction* instr, const char* detail) {
LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason) {
__ CompareRoot(rt, index);
DeoptimizeIf(eq, instr, detail);
DeoptimizeIf(eq, instr, deopt_reason);
}
void LCodeGen::DeoptimizeIfNotRoot(Register rt, Heap::RootListIndex index,
LInstruction* instr, const char* detail) {
LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason) {
__ CompareRoot(rt, index);
DeoptimizeIf(ne, instr, detail);
DeoptimizeIf(ne, instr, deopt_reason);
}
void LCodeGen::DeoptimizeIfMinusZero(DoubleRegister input, LInstruction* instr,
const char* detail) {
Deoptimizer::DeoptReason deopt_reason) {
__ TestForMinusZero(input);
DeoptimizeIf(vs, instr, detail);
DeoptimizeIf(vs, instr, deopt_reason);
}
void LCodeGen::DeoptimizeIfNotHeapNumber(Register object, LInstruction* instr) {
__ CompareObjectMap(object, Heap::kHeapNumberMapRootIndex);
DeoptimizeIf(ne, instr, "not heap number");
DeoptimizeIf(ne, instr, Deoptimizer::kNotHeapNumber);
}
void LCodeGen::DeoptimizeIfBitSet(Register rt, int bit, LInstruction* instr,
const char* detail) {
DeoptimizeBranch(instr, detail, reg_bit_set, rt, bit);
Deoptimizer::DeoptReason deopt_reason) {
DeoptimizeBranch(instr, deopt_reason, reg_bit_set, rt, bit);
}
void LCodeGen::DeoptimizeIfBitClear(Register rt, int bit, LInstruction* instr,
const char* detail) {
DeoptimizeBranch(instr, detail, reg_bit_clear, rt, bit);
Deoptimizer::DeoptReason deopt_reason) {
DeoptimizeBranch(instr, deopt_reason, reg_bit_clear, rt, bit);
}
@ -1531,7 +1536,7 @@ void LCodeGen::DoAddI(LAddI* instr) {
if (can_overflow) {
__ Adds(result, left, right);
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
} else {
__ Add(result, left, right);
}
@ -1545,7 +1550,7 @@ void LCodeGen::DoAddS(LAddS* instr) {
Operand right = ToOperand(instr->right());
if (can_overflow) {
__ Adds(result, left, right);
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
} else {
__ Add(result, left, right);
}
@ -1671,7 +1676,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// adaptor frame below it.
const uint32_t kArgumentsLimit = 1 * KB;
__ Cmp(length, kArgumentsLimit);
DeoptimizeIf(hi, instr, "too many arguments");
DeoptimizeIf(hi, instr, Deoptimizer::kTooManyArguments);
// Push the receiver and use the register to keep the original
// number of arguments.
@ -1852,7 +1857,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck *instr) {
if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
__ Assert(NegateCondition(cond), kEliminatedBoundsCheckFailed);
} else {
DeoptimizeIf(cond, instr, "out of bounds");
DeoptimizeIf(cond, instr, Deoptimizer::kOutOfBounds);
}
}
@ -1931,7 +1936,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
__ JumpIfSmi(value, true_label);
} else if (expected.NeedsMap()) {
// If we need a map later and have a smi, deopt.
DeoptimizeIfSmi(value, instr, "Smi");
DeoptimizeIfSmi(value, instr, Deoptimizer::kSmi);
}
Register map = NoReg;
@ -1992,7 +1997,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.
Deoptimize(instr, "unexpected object");
Deoptimize(instr, Deoptimizer::kUnexpectedObject);
}
}
}
@ -2198,7 +2203,7 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
__ StoreToSafepointRegisterSlot(x0, temp);
}
DeoptimizeIfSmi(temp, instr, "instance migration failed");
DeoptimizeIfSmi(temp, instr, Deoptimizer::kInstanceMigrationFailed);
}
@ -2253,7 +2258,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
if (instr->hydrogen()->HasMigrationTarget()) {
__ B(ne, deferred->entry());
} else {
DeoptimizeIf(ne, instr, "wrong map");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
}
__ Bind(&success);
@ -2262,7 +2267,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
if (!instr->hydrogen()->value()->type().IsHeapObject()) {
DeoptimizeIfSmi(ToRegister(instr->value()), instr, "Smi");
DeoptimizeIfSmi(ToRegister(instr->value()), instr, Deoptimizer::kSmi);
}
}
@ -2270,7 +2275,7 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
Register value = ToRegister(instr->value());
DCHECK(!instr->result() || ToRegister(instr->result()).Is(value));
DeoptimizeIfNotSmi(value, instr, "not a Smi");
DeoptimizeIfNotSmi(value, instr, Deoptimizer::kNotASmi);
}
@ -2288,15 +2293,15 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
__ Cmp(scratch, first);
if (first == last) {
// If there is only one type in the interval check for equality.
DeoptimizeIf(ne, instr, "wrong instance type");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType);
} else if (last == LAST_TYPE) {
// We don't need to compare with the higher bound of the interval.
DeoptimizeIf(lo, instr, "wrong instance type");
DeoptimizeIf(lo, instr, Deoptimizer::kWrongInstanceType);
} else {
// If we are below the lower bound, set the C flag and clear the Z flag
// to force a deopt.
__ Ccmp(scratch, last, CFlag, hs);
DeoptimizeIf(hi, instr, "wrong instance type");
DeoptimizeIf(hi, instr, Deoptimizer::kWrongInstanceType);
}
} else {
uint8_t mask;
@ -2307,10 +2312,10 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
DCHECK((tag == 0) || (tag == mask));
if (tag == 0) {
DeoptimizeIfBitSet(scratch, MaskToBit(mask), instr,
"wrong instance type");
Deoptimizer::kWrongInstanceType);
} else {
DeoptimizeIfBitClear(scratch, MaskToBit(mask), instr,
"wrong instance type");
Deoptimizer::kWrongInstanceType);
}
} else {
if (tag == 0) {
@ -2319,7 +2324,7 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
__ And(scratch, scratch, mask);
__ Cmp(scratch, tag);
}
DeoptimizeIf(ne, instr, "wrong instance type");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType);
}
}
}
@ -2359,7 +2364,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
// Check for undefined. Undefined is coverted to zero for clamping conversion.
DeoptimizeIfNotRoot(input, Heap::kUndefinedValueRootIndex, instr,
"not a heap number/undefined");
Deoptimizer::kNotAHeapNumberUndefined);
__ Mov(result, 0);
__ B(&done);
@ -2664,7 +2669,7 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
} else {
__ Cmp(reg, Operand(object));
}
DeoptimizeIf(ne, instr, "value mismatch");
DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch);
}
@ -2688,9 +2693,9 @@ void LCodeGen::DoDateField(LDateField* instr) {
DCHECK(object.is(result) && object.Is(x0));
DCHECK(instr->IsMarkedAsCall());
DeoptimizeIfSmi(object, instr, "Smi");
DeoptimizeIfSmi(object, instr, Deoptimizer::kSmi);
__ CompareObjectType(object, temp1, temp1, JS_DATE_TYPE);
DeoptimizeIf(ne, instr, "not a date object");
DeoptimizeIf(ne, instr, Deoptimizer::kNotADateObject);
if (index->value() == 0) {
__ Ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
@ -2740,21 +2745,21 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
DeoptimizeIfZero(dividend, instr, "division by zero");
DeoptimizeIfZero(dividend, instr, Deoptimizer::kDivisionByZero);
}
// Check for (kMinInt / -1).
if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
// Test dividend for kMinInt by subtracting one (cmp) and checking for
// overflow.
__ Cmp(dividend, 1);
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
}
// 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, mask);
DeoptimizeIf(ne, instr, "lost precision");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision);
}
if (divisor == -1) { // Nice shortcut, not needed for correctness.
@ -2782,14 +2787,14 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
DCHECK(!AreAliased(dividend, result));
if (divisor == 0) {
Deoptimize(instr, "division by zero");
Deoptimize(instr, Deoptimizer::kDivisionByZero);
return;
}
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
DeoptimizeIfZero(dividend, instr, "minus zero");
DeoptimizeIfZero(dividend, instr, Deoptimizer::kMinusZero);
}
__ TruncatingDiv(result, dividend, Abs(divisor));
@ -2801,7 +2806,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
__ Sxtw(dividend.X(), dividend);
__ Mov(temp, divisor);
__ Smsubl(temp.X(), result, temp, dividend.X());
DeoptimizeIfNotZero(temp, instr, "lost precision");
DeoptimizeIfNotZero(temp, instr, Deoptimizer::kLostPrecision);
}
}
@ -2824,7 +2829,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
DeoptimizeIfZero(divisor, instr, "division by zero");
DeoptimizeIfZero(divisor, instr, Deoptimizer::kDivisionByZero);
}
// Check for (0 / -x) as that will produce negative zero.
@ -2836,7 +2841,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
// If the divisor >= 0 (pl, the opposite of mi) set the flags to
// condition ne, so we don't deopt, ie. positive divisor doesn't deopt.
__ Ccmp(dividend, 0, NoFlag, mi);
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
// Check for (kMinInt / -1).
@ -2848,13 +2853,13 @@ void LCodeGen::DoDivI(LDivI* instr) {
// -1. If overflow is clear, set the flags for condition ne, as the
// dividend isn't -1, and thus we shouldn't deopt.
__ Ccmp(divisor, -1, NoFlag, vs);
DeoptimizeIf(eq, instr, "overflow");
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow);
}
// Compute remainder and deopt if it's not zero.
Register remainder = ToRegister32(instr->temp());
__ Msub(remainder, result, divisor, dividend);
DeoptimizeIfNotZero(remainder, instr, "lost precision");
DeoptimizeIfNotZero(remainder, instr, Deoptimizer::kLostPrecision);
}
@ -2863,11 +2868,11 @@ void LCodeGen::DoDoubleToIntOrSmi(LDoubleToIntOrSmi* instr) {
Register result = ToRegister32(instr->result());
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIfMinusZero(input, instr, "minus zero");
DeoptimizeIfMinusZero(input, instr, Deoptimizer::kMinusZero);
}
__ TryRepresentDoubleAsInt32(result, input, double_scratch());
DeoptimizeIf(ne, instr, "lost precision or NaN");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
if (instr->tag_result()) {
__ SmiTag(result.X());
@ -2928,7 +2933,7 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
__ LoadInstanceDescriptors(map, result);
__ Ldr(result, FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
__ Ldr(result, FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
DeoptimizeIfZero(result, instr, "no cache");
DeoptimizeIfZero(result, instr, Deoptimizer::kNoCache);
__ Bind(&done);
}
@ -2941,17 +2946,18 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
DCHECK(instr->IsMarkedAsCall());
DCHECK(object.Is(x0));
DeoptimizeIfRoot(object, Heap::kUndefinedValueRootIndex, instr, "undefined");
DeoptimizeIfRoot(object, Heap::kUndefinedValueRootIndex, instr,
Deoptimizer::kUndefined);
__ LoadRoot(null_value, Heap::kNullValueRootIndex);
__ Cmp(object, null_value);
DeoptimizeIf(eq, instr, "null");
DeoptimizeIf(eq, instr, Deoptimizer::kNull);
DeoptimizeIfSmi(object, instr, "Smi");
DeoptimizeIfSmi(object, instr, Deoptimizer::kSmi);
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
__ CompareObjectType(object, x1, x1, LAST_JS_PROXY_TYPE);
DeoptimizeIf(le, instr, "not a JavaScript object");
DeoptimizeIf(le, instr, Deoptimizer::kNotAJavaScriptObject);
Label use_cache, call_runtime;
__ CheckEnumCache(object, null_value, x1, x2, x3, x4, &call_runtime);
@ -2965,7 +2971,8 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
__ Ldr(x1, FieldMemOperand(object, HeapObject::kMapOffset));
DeoptimizeIfNotRoot(x1, Heap::kMetaMapRootIndex, instr, "wrong map");
DeoptimizeIfNotRoot(x1, Heap::kMetaMapRootIndex, instr,
Deoptimizer::kWrongMap);
__ Bind(&use_cache);
}
@ -3356,7 +3363,8 @@ void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
__ Ldr(result, ContextMemOperand(context, instr->slot_index()));
if (instr->hydrogen()->RequiresHoleCheck()) {
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex, instr, "hole");
DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex, instr,
Deoptimizer::kHole);
} else {
Label not_the_hole;
__ JumpIfNotRoot(result, Heap::kTheHoleValueRootIndex, &not_the_hole);
@ -3377,7 +3385,8 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
JSFunction::kPrototypeOrInitialMapOffset));
// Check that the function has a prototype or an initial map.
DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex, instr, "hole");
DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex, instr,
Deoptimizer::kHole);
// If the function does not have an initial map, we're done.
Label done;
@ -3397,7 +3406,8 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
__ Mov(result, Operand(Handle<Object>(instr->hydrogen()->cell().handle())));
__ Ldr(result, FieldMemOperand(result, Cell::kValueOffset));
if (instr->hydrogen()->RequiresHoleCheck()) {
DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex, instr, "hole");
DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex, instr,
Deoptimizer::kHole);
}
}
@ -3533,7 +3543,7 @@ void LCodeGen::DoLoadKeyedExternal(LLoadKeyedExternal* instr) {
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
// Deopt if value > 0x80000000.
__ Tst(result, 0xFFFFFFFF80000000);
DeoptimizeIf(ne, instr, "negative value");
DeoptimizeIf(ne, instr, Deoptimizer::kNegativeValue);
}
break;
case FLOAT32_ELEMENTS:
@ -3627,7 +3637,7 @@ void LCodeGen::DoLoadKeyedFixedDouble(LLoadKeyedFixedDouble* instr) {
Register scratch = ToRegister(instr->temp());
__ Fmov(scratch, result);
__ Eor(scratch, scratch, kHoleNanInt64);
DeoptimizeIfZero(scratch, instr, "hole");
DeoptimizeIfZero(scratch, instr, Deoptimizer::kHole);
}
}
@ -3665,9 +3675,10 @@ void LCodeGen::DoLoadKeyedFixed(LLoadKeyedFixed* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
DeoptimizeIfNotSmi(result, instr, "not a Smi");
DeoptimizeIfNotSmi(result, instr, Deoptimizer::kNotASmi);
} else {
DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex, instr, "hole");
DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex, instr,
Deoptimizer::kHole);
}
}
}
@ -3771,7 +3782,7 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
Register result = r.IsSmi() ? ToRegister(instr->result())
: ToRegister32(instr->result());
__ Abs(result, input);
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
}
}
@ -3923,7 +3934,7 @@ void LCodeGen::DoMathFloorI(LMathFloorI* instr) {
Register result = ToRegister(instr->result());
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIfMinusZero(input, instr, "minus zero");
DeoptimizeIfMinusZero(input, instr, Deoptimizer::kMinusZero);
}
__ Fcvtms(result, input);
@ -3933,7 +3944,7 @@ void LCodeGen::DoMathFloorI(LMathFloorI* instr) {
__ Cmp(result, Operand(result, SXTW));
// - The input was not NaN.
__ Fccmp(input, input, NoFlag, eq);
DeoptimizeIf(ne, instr, "lost precision or NaN");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
}
@ -3959,13 +3970,13 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
// If the divisor is negative, we have to negate and handle edge cases.
__ Negs(result, dividend);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
// Dividing by -1 is basically negation, unless we overflow.
if (divisor == -1) {
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
}
return;
}
@ -3988,14 +3999,14 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
DCHECK(!AreAliased(dividend, result));
if (divisor == 0) {
Deoptimize(instr, "division by zero");
Deoptimize(instr, Deoptimizer::kDivisionByZero);
return;
}
// Check for (0 / -x) that will produce negative zero.
HMathFloorOfDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
DeoptimizeIfZero(dividend, instr, "minus zero");
DeoptimizeIfZero(dividend, instr, Deoptimizer::kMinusZero);
}
// Easy case: We need no dynamic check for the dividend and the flooring
@ -4038,14 +4049,14 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
__ Sdiv(result, dividend, divisor);
// Check for x / 0.
DeoptimizeIfZero(divisor, instr, "division by zero");
DeoptimizeIfZero(divisor, instr, Deoptimizer::kDivisionByZero);
// Check for (kMinInt / -1).
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
// The V flag will be set iff dividend == kMinInt.
__ Cmp(dividend, 1);
__ Ccmp(divisor, -1, NoFlag, vs);
DeoptimizeIf(eq, instr, "overflow");
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow);
}
// Check for (0 / -x) that will produce negative zero.
@ -4055,7 +4066,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
// "divisor" can't be null because the code would have already been
// deoptimized. The Z flag is set only if (divisor < 0) and (dividend == 0).
// In this case we need to deoptimize to produce a -0.
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
Label done;
@ -4214,18 +4225,18 @@ void LCodeGen::DoMathRoundI(LMathRoundI* instr) {
// Deoptimize if the result > 1, as it must be larger than 32 bits.
__ Cmp(result, 1);
DeoptimizeIf(hi, instr, "overflow");
DeoptimizeIf(hi, instr, Deoptimizer::kOverflow);
// Deoptimize for negative inputs, which at this point are only numbers in
// the range [-0.5, -0.0]
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ Fmov(result, input);
DeoptimizeIfNegative(result, instr, "minus zero");
DeoptimizeIfNegative(result, instr, Deoptimizer::kMinusZero);
}
// Deoptimize if the input was NaN.
__ Fcmp(input, dot_five);
DeoptimizeIf(vs, instr, "NaN");
DeoptimizeIf(vs, instr, Deoptimizer::kNaN);
// Now, the only unhandled inputs are in the range [0.0, 1.5[ (or [-0.5, 1.5[
// if we didn't generate a -0.0 bailout). If input >= 0.5 then return 1,
@ -4303,7 +4314,7 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
__ And(dividend, dividend, mask);
__ Negs(dividend, dividend);
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
__ B(&done);
}
@ -4322,7 +4333,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
DCHECK(!AreAliased(dividend, result, temp));
if (divisor == 0) {
Deoptimize(instr, "division by zero");
Deoptimize(instr, Deoptimizer::kDivisionByZero);
return;
}
@ -4336,7 +4347,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label remainder_not_zero;
__ Cbnz(result, &remainder_not_zero);
DeoptimizeIfNegative(dividend, instr, "minus zero");
DeoptimizeIfNegative(dividend, instr, Deoptimizer::kMinusZero);
__ bind(&remainder_not_zero);
}
}
@ -4351,12 +4362,12 @@ void LCodeGen::DoModI(LModI* instr) {
// modulo = dividend - quotient * divisor
__ Sdiv(result, dividend, divisor);
if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
DeoptimizeIfZero(divisor, instr, "division by zero");
DeoptimizeIfZero(divisor, instr, Deoptimizer::kDivisionByZero);
}
__ Msub(result, result, divisor, dividend);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ Cbnz(result, &done);
DeoptimizeIfNegative(dividend, instr, "minus zero");
DeoptimizeIfNegative(dividend, instr, Deoptimizer::kMinusZero);
}
__ Bind(&done);
}
@ -4379,10 +4390,10 @@ void LCodeGen::DoMulConstIS(LMulConstIS* instr) {
if (bailout_on_minus_zero) {
if (right < 0) {
// The result is -0 if right is negative and left is zero.
DeoptimizeIfZero(left, instr, "minus zero");
DeoptimizeIfZero(left, instr, Deoptimizer::kMinusZero);
} else if (right == 0) {
// The result is -0 if the right is zero and the left is negative.
DeoptimizeIfNegative(left, instr, "minus zero");
DeoptimizeIfNegative(left, instr, Deoptimizer::kMinusZero);
}
}
@ -4392,7 +4403,7 @@ void LCodeGen::DoMulConstIS(LMulConstIS* instr) {
if (can_overflow) {
// Only 0x80000000 can overflow here.
__ Negs(result, left);
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
} else {
__ Neg(result, left);
}
@ -4408,7 +4419,7 @@ void LCodeGen::DoMulConstIS(LMulConstIS* instr) {
case 2:
if (can_overflow) {
__ Adds(result, left, left);
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
} else {
__ Add(result, left, left);
}
@ -4427,7 +4438,7 @@ void LCodeGen::DoMulConstIS(LMulConstIS* instr) {
DCHECK(!AreAliased(scratch, left));
__ Cls(scratch, left);
__ Cmp(scratch, right_log2);
DeoptimizeIf(lt, instr, "overflow");
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow);
}
if (right >= 0) {
@ -4437,7 +4448,7 @@ void LCodeGen::DoMulConstIS(LMulConstIS* instr) {
// result = -left << log2(-right)
if (can_overflow) {
__ Negs(result, Operand(left, LSL, right_log2));
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
} else {
__ Neg(result, Operand(left, LSL, right_log2));
}
@ -4495,13 +4506,13 @@ void LCodeGen::DoMulI(LMulI* instr) {
// - If so (eq), set N (mi) if left + right is negative.
// - Otherwise, clear N.
__ Ccmn(left, right, NoFlag, eq);
DeoptimizeIf(mi, instr, "minus zero");
DeoptimizeIf(mi, instr, Deoptimizer::kMinusZero);
}
if (can_overflow) {
__ Smull(result.X(), left, right);
__ Cmp(result.X(), Operand(result, SXTW));
DeoptimizeIf(ne, instr, "overflow");
DeoptimizeIf(ne, instr, Deoptimizer::kOverflow);
} else {
__ Mul(result, left, right);
}
@ -4525,7 +4536,7 @@ void LCodeGen::DoMulS(LMulS* instr) {
// - If so (eq), set N (mi) if left + right is negative.
// - Otherwise, clear N.
__ Ccmn(left, right, NoFlag, eq);
DeoptimizeIf(mi, instr, "minus zero");
DeoptimizeIf(mi, instr, Deoptimizer::kMinusZero);
}
STATIC_ASSERT((kSmiShift == 32) && (kSmiTag == 0));
@ -4533,7 +4544,7 @@ void LCodeGen::DoMulS(LMulS* instr) {
__ Smulh(result, left, right);
__ Cmp(result, Operand(result.W(), SXTW));
__ SmiTag(result);
DeoptimizeIf(ne, instr, "overflow");
DeoptimizeIf(ne, instr, Deoptimizer::kOverflow);
} else {
if (AreAliased(result, left, right)) {
// All three registers are the same: half untag the input and then
@ -4709,14 +4720,14 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
// Load heap number.
__ Ldr(result, FieldMemOperand(input, HeapNumber::kValueOffset));
if (instr->hydrogen()->deoptimize_on_minus_zero()) {
DeoptimizeIfMinusZero(result, instr, "minus zero");
DeoptimizeIfMinusZero(result, instr, Deoptimizer::kMinusZero);
}
__ B(&done);
if (can_convert_undefined_to_nan) {
__ Bind(&convert_undefined);
DeoptimizeIfNotRoot(input, Heap::kUndefinedValueRootIndex, instr,
"not a heap number/undefined");
Deoptimizer::kNotAHeapNumberUndefined);
__ LoadRoot(scratch, Heap::kNanValueRootIndex);
__ Ldr(result, FieldMemOperand(scratch, HeapNumber::kValueOffset));
@ -4910,7 +4921,7 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) {
Register output = ToRegister(instr->result());
if (hchange->CheckFlag(HValue::kCanOverflow) &&
hchange->value()->CheckFlag(HValue::kUint32)) {
DeoptimizeIfNegative(input.W(), instr, "overflow");
DeoptimizeIfNegative(input.W(), instr, Deoptimizer::kOverflow);
}
__ SmiTag(output, input);
}
@ -4922,7 +4933,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
Label done, untag;
if (instr->needs_check()) {
DeoptimizeIfNotSmi(input, instr, "not a Smi");
DeoptimizeIfNotSmi(input, instr, Deoptimizer::kNotASmi);
}
__ Bind(&untag);
@ -4947,7 +4958,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
if (instr->can_deopt()) {
// If `left >>> right` >= 0x80000000, the result is not representable
// in a signed 32-bit smi.
DeoptimizeIfNegative(result, instr, "negative value");
DeoptimizeIfNegative(result, instr, Deoptimizer::kNegativeValue);
}
break;
default: UNREACHABLE();
@ -4957,7 +4968,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
int shift_count = JSShiftAmountFromLConstant(right_op);
if (shift_count == 0) {
if ((instr->op() == Token::SHR) && instr->can_deopt()) {
DeoptimizeIfNegative(left, instr, "negative value");
DeoptimizeIfNegative(left, instr, Deoptimizer::kNegativeValue);
}
__ Mov(result, left, kDiscardForSameWReg);
} else {
@ -5010,7 +5021,7 @@ void LCodeGen::DoShiftS(LShiftS* instr) {
if (instr->can_deopt()) {
// If `left >>> right` >= 0x80000000, the result is not representable
// in a signed 32-bit smi.
DeoptimizeIfNegative(result, instr, "negative value");
DeoptimizeIfNegative(result, instr, Deoptimizer::kNegativeValue);
}
break;
default: UNREACHABLE();
@ -5020,7 +5031,7 @@ void LCodeGen::DoShiftS(LShiftS* instr) {
int shift_count = JSShiftAmountFromLConstant(right_op);
if (shift_count == 0) {
if ((instr->op() == Token::SHR) && instr->can_deopt()) {
DeoptimizeIfNegative(left, instr, "negative value");
DeoptimizeIfNegative(left, instr, Deoptimizer::kNegativeValue);
}
__ Mov(result, left);
} else {
@ -5148,7 +5159,8 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
__ Ldr(scratch, target);
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIfRoot(scratch, Heap::kTheHoleValueRootIndex, instr, "hole");
DeoptimizeIfRoot(scratch, Heap::kTheHoleValueRootIndex, instr,
Deoptimizer::kHole);
} else {
__ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, &skip_assignment);
}
@ -5186,7 +5198,8 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
Register payload = ToRegister(instr->temp2());
__ Ldr(payload, FieldMemOperand(cell, Cell::kValueOffset));
DeoptimizeIfRoot(payload, Heap::kTheHoleValueRootIndex, instr, "hole");
DeoptimizeIfRoot(payload, Heap::kTheHoleValueRootIndex, instr,
Deoptimizer::kHole);
}
// Store the value.
@ -5608,7 +5621,7 @@ void LCodeGen::DoSubI(LSubI* instr) {
if (can_overflow) {
__ Subs(result, left, right);
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
} else {
__ Sub(result, left, right);
}
@ -5622,7 +5635,7 @@ void LCodeGen::DoSubS(LSubS* instr) {
Operand right = ToOperand(instr->right());
if (can_overflow) {
__ Subs(result, left, right);
DeoptimizeIf(vs, instr, "overflow");
DeoptimizeIf(vs, instr, Deoptimizer::kOverflow);
} else {
__ Sub(result, left, right);
}
@ -5663,7 +5676,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr,
// Output contains zero, undefined is converted to zero for truncating
// conversions.
DeoptimizeIfNotRoot(input, Heap::kUndefinedValueRootIndex, instr,
"not a heap number/undefined/true/false");
Deoptimizer::kNotAHeapNumberUndefinedBoolean);
} else {
Register output = ToRegister32(instr->result());
DoubleRegister dbl_scratch2 = ToDoubleRegister(temp2);
@ -5674,13 +5687,13 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr,
// function. If the result is out of range, branch to deoptimize.
__ Ldr(dbl_scratch1, FieldMemOperand(input, HeapNumber::kValueOffset));
__ TryRepresentDoubleAsInt32(output, dbl_scratch1, dbl_scratch2);
DeoptimizeIf(ne, instr, "lost precision or NaN");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ Cmp(output, 0);
__ B(ne, &done);
__ Fmov(scratch1, dbl_scratch1);
DeoptimizeIfNegative(scratch1, instr, "minus zero");
DeoptimizeIfNegative(scratch1, instr, Deoptimizer::kMinusZero);
}
}
__ Bind(&done);
@ -5821,7 +5834,7 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
Label no_memento_found;
__ TestJSArrayForAllocationMemento(object, temp1, temp2, &no_memento_found);
DeoptimizeIf(eq, instr, "memento found");
DeoptimizeIf(eq, instr, Deoptimizer::kMementoFound);
__ Bind(&no_memento_found);
}
@ -5946,7 +5959,7 @@ void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
Register temp = ToRegister(instr->temp());
__ Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset));
__ Cmp(map, temp);
DeoptimizeIf(ne, instr, "wrong map");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
}
@ -5980,10 +5993,10 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
__ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex, &global_object);
// Deoptimize if the receiver is not a JS object.
DeoptimizeIfSmi(receiver, instr, "Smi");
DeoptimizeIfSmi(receiver, instr, Deoptimizer::kSmi);
__ CompareObjectType(receiver, result, result, FIRST_SPEC_OBJECT_TYPE);
__ B(ge, &copy_receiver);
Deoptimize(instr, "not a JavaScript object");
Deoptimize(instr, Deoptimizer::kNotAJavaScriptObject);
__ Bind(&global_object);
__ Ldr(result, FieldMemOperand(function, JSFunction::kContextOffset));

View File

@ -213,31 +213,38 @@ class LCodeGen: public LCodeGenBase {
Register temp,
LOperand* index,
String::Encoding encoding);
void DeoptimizeBranch(LInstruction* instr, const char* detail,
void DeoptimizeBranch(LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason,
BranchType branch_type, Register reg = NoReg,
int bit = -1,
Deoptimizer::BailoutType* override_bailout_type = NULL);
void Deoptimize(LInstruction* instr, const char* detail,
void Deoptimize(LInstruction* instr, Deoptimizer::DeoptReason deopt_reason,
Deoptimizer::BailoutType* override_bailout_type = NULL);
void DeoptimizeIf(Condition cond, LInstruction* instr, const char* detail);
void DeoptimizeIfZero(Register rt, LInstruction* instr, const char* detail);
void DeoptimizeIf(Condition cond, LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason);
void DeoptimizeIfZero(Register rt, LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason);
void DeoptimizeIfNotZero(Register rt, LInstruction* instr,
const char* detail);
Deoptimizer::DeoptReason deopt_reason);
void DeoptimizeIfNegative(Register rt, LInstruction* instr,
const char* detail);
void DeoptimizeIfSmi(Register rt, LInstruction* instr, const char* detail);
void DeoptimizeIfNotSmi(Register rt, LInstruction* instr, const char* detail);
Deoptimizer::DeoptReason deopt_reason);
void DeoptimizeIfSmi(Register rt, LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason);
void DeoptimizeIfNotSmi(Register rt, LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason);
void DeoptimizeIfRoot(Register rt, Heap::RootListIndex index,
LInstruction* instr, const char* detail);
LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason);
void DeoptimizeIfNotRoot(Register rt, Heap::RootListIndex index,
LInstruction* instr, const char* detail);
LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason);
void DeoptimizeIfNotHeapNumber(Register object, LInstruction* instr);
void DeoptimizeIfMinusZero(DoubleRegister input, LInstruction* instr,
const char* detail);
Deoptimizer::DeoptReason deopt_reason);
void DeoptimizeIfBitSet(Register rt, int bit, LInstruction* instr,
const char* detail);
Deoptimizer::DeoptReason deopt_reason);
void DeoptimizeIfBitClear(Register rt, int bit, LInstruction* instr,
const char* detail);
Deoptimizer::DeoptReason deopt_reason);
MemOperand PrepareKeyedExternalArrayOperand(Register key,
Register base,

View File

@ -256,6 +256,7 @@ int Label::pos() const {
// position: 01
// statement_position: 10
// comment: 11 (not used in short_data_record)
// deopt_reason: 11 (not used in long_data_record)
//
// Long record format:
// 4-bit middle_tag:
@ -328,6 +329,10 @@ const int kNonstatementPositionTag = 1;
const int kStatementPositionTag = 2;
const int kCommentTag = 3;
// Reuse the same value for deopt reason tag in short record format.
// It is possible because we use kCommentTag only for the long record format.
const int kDeoptReasonTag = 3;
const int kPoolExtraTag = kPCJumpExtraTag - 2;
const int kConstPoolTag = 0;
const int kVeneerPoolTag = 1;
@ -442,6 +447,10 @@ void RelocInfoWriter::Write(const RelocInfo* rinfo) {
WriteExtraTaggedIntData(id_delta, kCodeWithIdTag);
}
last_id_ = static_cast<int>(rinfo->data());
} else if (rmode == RelocInfo::DEOPT_REASON) {
DCHECK(rinfo->data() < (1 << kSmallDataBits));
WriteTaggedPC(pc_delta, kLocatableTag);
WriteTaggedData(rinfo->data(), kDeoptReasonTag);
} else if (RelocInfo::IsPosition(rmode)) {
// Use signed delta-encoding for position.
DCHECK(static_cast<int>(rinfo->data()) == rinfo->data());
@ -473,7 +482,7 @@ void RelocInfoWriter::Write(const RelocInfo* rinfo) {
int saved_mode = rmode - RelocInfo::LAST_COMPACT_ENUM;
// For all other modes we simply use the mode as the extra tag.
// None of these modes need a data component.
DCHECK(saved_mode < kPCJumpExtraTag && saved_mode < kDataJumpExtraTag);
DCHECK(saved_mode < kPoolExtraTag);
WriteExtraTaggedPC(pc_delta, saved_mode);
}
last_pc_ = rinfo->pc();
@ -583,6 +592,12 @@ inline void RelocIterator::ReadTaggedPosition() {
}
inline void RelocIterator::ReadTaggedData() {
uint8_t unsigned_b = *pos_;
rinfo_.data_ = unsigned_b >> kTagBits;
}
static inline RelocInfo::Mode GetPositionModeFromTag(int tag) {
DCHECK(tag == kNonstatementPositionTag ||
tag == kStatementPositionTag);
@ -616,9 +631,10 @@ void RelocIterator::next() {
ReadTaggedId();
return;
}
} else if (locatable_tag == kDeoptReasonTag) {
ReadTaggedData();
if (SetMode(RelocInfo::DEOPT_REASON)) return;
} else {
// Compact encoding is never used for comments,
// so it must be a position.
DCHECK(locatable_tag == kNonstatementPositionTag ||
locatable_tag == kStatementPositionTag);
if (mode_mask_ & RelocInfo::kPositionMask) {
@ -783,6 +799,8 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
return "external reference";
case RelocInfo::INTERNAL_REFERENCE:
return "internal reference";
case RelocInfo::DEOPT_REASON:
return "deopt reason";
case RelocInfo::CONST_POOL:
return "constant pool";
case RelocInfo::VENEER_POOL:
@ -803,6 +821,9 @@ void RelocInfo::Print(Isolate* isolate, std::ostream& os) { // NOLINT
os << static_cast<const void*>(pc_) << " " << RelocModeName(rmode_);
if (IsComment(rmode_)) {
os << " (" << reinterpret_cast<char*>(data_) << ")";
} else if (rmode_ == DEOPT_REASON) {
os << " (" << Deoptimizer::GetDeoptReason(
static_cast<Deoptimizer::DeoptReason>(data_)) << ")";
} else if (rmode_ == EMBEDDED_OBJECT) {
os << " (" << Brief(target_object()) << ")";
} else if (rmode_ == EXTERNAL_REFERENCE) {
@ -863,6 +884,7 @@ void RelocInfo::Verify(Isolate* isolate) {
case STATEMENT_POSITION:
case EXTERNAL_REFERENCE:
case INTERNAL_REFERENCE:
case DEOPT_REASON:
case CONST_POOL:
case VENEER_POOL:
case DEBUG_BREAK_SLOT:

View File

@ -384,6 +384,8 @@ class RelocInfo {
CONST_POOL,
VENEER_POOL,
DEOPT_REASON, // Deoptimization reason index.
// add more as needed
// Pseudo-types
NUMBER_OF_MODES, // There are at most 15 modes with noncompact encoding.
@ -733,6 +735,7 @@ class RelocIterator: public Malloced {
int GetLocatableTypeTag();
void ReadTaggedId();
void ReadTaggedPosition();
void ReadTaggedData();
// If the given mode is wanted, set it in rinfo_ and return true.
// Else return false. Used for efficiently skipping unwanted modes.

View File

@ -228,7 +228,7 @@ class CodeStubGraphBuilder: public CodeStubGraphBuilderBase {
IfBuilder builder(this);
builder.IfNot<HCompareObjectEqAndBranch, HValue*>(undefined, undefined);
builder.Then();
builder.ElseDeopt("Forced deopt to runtime");
builder.ElseDeopt(Deoptimizer::kForcedDeoptToRuntime);
return undefined;
}
@ -369,7 +369,7 @@ HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() {
if_fixed_cow.End();
zero_capacity.End();
checker.ElseDeopt("Uninitialized boilerplate literals");
checker.ElseDeopt(Deoptimizer::kUninitializedBoilerplateLiterals);
checker.End();
return environment()->Pop();
@ -436,7 +436,7 @@ HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
}
environment()->Push(object);
checker.ElseDeopt("Uninitialized boilerplate in fast clone");
checker.ElseDeopt(Deoptimizer::kUninitializedBoilerplateInFastClone);
checker.End();
return environment()->Pop();
@ -669,7 +669,7 @@ HValue* CodeStubGraphBuilderBase::UnmappedCase(HValue* elements, HValue* key) {
result = Add<HLoadKeyed>(backing_store, key, nullptr, FAST_HOLEY_ELEMENTS,
NEVER_RETURN_HOLE);
}
in_unmapped_range.ElseDeopt("Outside of range");
in_unmapped_range.ElseDeopt(Deoptimizer::kOutsideOfRange);
in_unmapped_range.End();
return result;
}
@ -710,7 +710,7 @@ HValue* CodeStubGraphBuilder<KeyedLoadSloppyArgumentsStub>::BuildCodeStub() {
IfBuilder positive_smi(this);
positive_smi.If<HCompareNumericAndBranch>(key, graph()->GetConstant0(),
Token::LT);
positive_smi.ThenDeopt("key is negative");
positive_smi.ThenDeopt(Deoptimizer::kKeyIsNegative);
positive_smi.End();
HValue* constant_two = Add<HConstant>(2);
@ -1346,7 +1346,7 @@ HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() {
Add<HLoadNamedField>(global, nullptr, HObjectAccess::ForMap());
IfBuilder map_check(this);
map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map);
map_check.ThenDeopt("Unknown map");
map_check.ThenDeopt(Deoptimizer::kUnknownMap);
map_check.End();
}
@ -1361,7 +1361,8 @@ HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() {
IfBuilder builder(this);
builder.If<HCompareObjectEqAndBranch>(cell_contents, value);
builder.Then();
builder.ElseDeopt("Unexpected cell contents in constant global store");
builder.ElseDeopt(
Deoptimizer::kUnexpectedCellContentsInConstantGlobalStore);
builder.End();
} else {
// Load the payload of the global parameter cell. A hole indicates that the
@ -1371,7 +1372,7 @@ HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() {
HValue* hole_value = graph()->GetConstantHole();
builder.If<HCompareObjectEqAndBranch>(cell_contents, hole_value);
builder.Then();
builder.Deopt("Unexpected cell contents in global store");
builder.Deopt(Deoptimizer::kUnexpectedCellContentsInGlobalStore);
builder.Else();
HStoreNamedField* store = Add<HStoreNamedField>(cell, access, value);
store->MarkReceiverAsCell();
@ -1396,7 +1397,8 @@ HValue* CodeStubGraphBuilder<ElementsTransitionAndStoreStub>::BuildCodeStub() {
if (FLAG_trace_elements_transitions) {
// Tracing elements transitions is the job of the runtime.
Add<HDeoptimize>("Tracing elements transitions", Deoptimizer::EAGER);
Add<HDeoptimize>(Deoptimizer::kTracingElementsTransitions,
Deoptimizer::EAGER);
} else {
info()->MarkAsSavesCallerDoubles();
@ -1859,7 +1861,7 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
BuildElementsKindLimitCheck(&kind_if, bit_field2,
SLOPPY_ARGUMENTS_ELEMENTS);
// Non-strict elements are not handled.
Add<HDeoptimize>("non-strict elements in KeyedLoadGenericStub",
Add<HDeoptimize>(Deoptimizer::kNonStrictElementsInKeyedLoadGenericStub,
Deoptimizer::EAGER);
Push(graph()->GetConstant0());
@ -1899,7 +1901,8 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
EXTERNAL_UINT8_CLAMPED_ELEMENTS);
kind_if.ElseDeopt("ElementsKind unhandled in KeyedLoadGenericStub");
kind_if.ElseDeopt(
Deoptimizer::kElementsKindUnhandledInKeyedLoadGenericStub);
kind_if.End();
}

View File

@ -3628,4 +3628,13 @@ void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) {
v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
}
const char* Deoptimizer::GetDeoptReason(DeoptReason deopt_reason) {
DCHECK(deopt_reason < kLastDeoptReason);
#define DEOPT_MESSAGES_TEXTS(C, T) T,
static const char* deopt_messages_[] = {
DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_TEXTS)};
#undef DEOPT_MESSAGES_TEXTS
return deopt_messages_[deopt_reason];
}
} } // namespace v8::internal

View File

@ -87,6 +87,83 @@ class OptimizedFunctionVisitor BASE_EMBEDDED {
};
#define DEOPT_MESSAGES_LIST(V) \
V(kNoReason, "no reason") \
V(kConstantGlobalVariableAssignment, "Constant global variable assignment") \
V(kConversionOverflow, "conversion overflow") \
V(kDivisionByZero, "division by zero") \
V(kElementsKindUnhandledInKeyedLoadGenericStub, \
"ElementsKind unhandled in KeyedLoadGenericStub") \
V(kExpectedHeapNumber, "Expected heap number") \
V(kExpectedSmi, "Expected smi") \
V(kForcedDeoptToRuntime, "Forced deopt to runtime") \
V(kHole, "hole") \
V(kHoleyArrayDespitePackedElements_kindFeedback, \
"Holey array despite packed elements_kind feedback") \
V(kInstanceMigrationFailed, "instance migration failed") \
V(kInsufficientTypeFeedbackForCallWithArguments, \
"Insufficient type feedback for call with arguments") \
V(kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation, \
"Insufficient type feedback for combined type of binary operation") \
V(kInsufficientTypeFeedbackForGenericNamedAccess, \
"Insufficient type feedback for generic named access") \
V(kInsufficientTypeFeedbackForKeyedLoad, \
"Insufficient type feedback for keyed load") \
V(kInsufficientTypeFeedbackForKeyedStore, \
"Insufficient type feedback for keyed store") \
V(kInsufficientTypeFeedbackForLHSOfBinaryOperation, \
"Insufficient type feedback for LHS of binary operation") \
V(kInsufficientTypeFeedbackForRHSOfBinaryOperation, \
"Insufficient type feedback for RHS of binary operation") \
V(kKeyIsNegative, "key is negative") \
V(kLostPrecision, "lost precision") \
V(kLostPrecisionOrNaN, "lost precision or NaN") \
V(kMementoFound, "memento found") \
V(kMinusZero, "minus zero") \
V(kNaN, "NaN") \
V(kNegativeKeyEncountered, "Negative key encountered") \
V(kNegativeValue, "negative value") \
V(kNoCache, "no cache") \
V(kNonStrictElementsInKeyedLoadGenericStub, \
"non-strict elements in KeyedLoadGenericStub") \
V(kNotADateObject, "not a date object") \
V(kNotAHeapNumber, "not a heap number") \
V(kNotAHeapNumberUndefinedBoolean, "not a heap number/undefined/true/false") \
V(kNotAHeapNumberUndefined, "not a heap number/undefined") \
V(kNotAJavaScriptObject, "not a JavaScript object") \
V(kNotASmi, "not a Smi") \
V(kNotHeapNumber, "not heap number") \
V(kNull, "null") \
V(kOutOfBounds, "out of bounds") \
V(kOutsideOfRange, "Outside of range") \
V(kOverflow, "overflow") \
V(kReceiverWasAGlobalObject, "receiver was a global object") \
V(kSmi, "Smi") \
V(kTooManyArguments, "too many arguments") \
V(kTooManyUndetectableTypes, "Too many undetectable types") \
V(kTracingElementsTransitions, "Tracing elements transitions") \
V(kTypeMismatchBetweenFeedbackAndConstant, \
"Type mismatch between feedback and constant") \
V(kUndefined, "undefined") \
V(kUnexpectedCellContentsInConstantGlobalStore, \
"Unexpected cell contents in constant global store") \
V(kUnexpectedCellContentsInGlobalStore, \
"Unexpected cell contents in global store") \
V(kUnexpectedObject, "unexpected object") \
V(kUnexpectedRHSOfBinaryOperation, "Unexpected RHS of binary operation") \
V(kUninitializedBoilerplateInFastClone, \
"Uninitialized boilerplate in fast clone") \
V(kUninitializedBoilerplateLiterals, "Uninitialized boilerplate literals") \
V(kUnknownMapInPolymorphicAccess, "Unknown map in polymorphic access") \
V(kUnknownMapInPolymorphicCall, "Unknown map in polymorphic call") \
V(kUnknownMapInPolymorphicElementAccess, \
"Unknown map in polymorphic element access") \
V(kUnknownMap, "Unknown map") \
V(kValueMismatch, "value mismatch") \
V(kWrongInstanceType, "wrong instance type") \
V(kWrongMap, "wrong map")
class Deoptimizer : public Malloced {
public:
enum BailoutType {
@ -99,21 +176,29 @@ class Deoptimizer : public Malloced {
kBailoutTypesWithCodeEntry = SOFT + 1
};
#define DEOPT_MESSAGES_CONSTANTS(C, T) C,
enum DeoptReason {
DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_CONSTANTS) kLastDeoptReason
};
#undef DEOPT_MESSAGES_CONSTANTS
static const char* GetDeoptReason(DeoptReason deopt_reason);
struct Reason {
Reason(int r, const char* m, const char* d)
: raw_position(r), mnemonic(m), detail(d) {}
Reason(int r, const char* m, DeoptReason d)
: raw_position(r), mnemonic(m), deopt_reason(d) {}
bool operator==(const Reason& other) const {
return raw_position == other.raw_position &&
CStringEquals(mnemonic, other.mnemonic) &&
CStringEquals(detail, other.detail);
deopt_reason == other.deopt_reason;
}
bool operator!=(const Reason& other) const { return !(*this == other); }
int raw_position;
const char* mnemonic;
const char* detail;
DeoptReason deopt_reason;
};
struct JumpTableEntry : public ZoneObject {

View File

@ -195,6 +195,11 @@ static int DecodeIt(Isolate* isolate, std::ostream* os,
} else {
out.AddFormatted(" ;; debug: position %d", relocinfo.data());
}
} else if (rmode == RelocInfo::DEOPT_REASON) {
Deoptimizer::DeoptReason reason =
static_cast<Deoptimizer::DeoptReason>(relocinfo.data());
out.AddFormatted(" ;; debug: deopt reason '%s'",
Deoptimizer::GetDeoptReason(reason));
} else if (rmode == RelocInfo::EMBEDDED_OBJECT) {
HeapStringAllocator allocator;
StringStream accumulator(&allocator);

View File

@ -1363,7 +1363,8 @@ class HGoto FINAL : public HTemplateControlInstruction<1, 0> {
class HDeoptimize FINAL : public HTemplateControlInstruction<1, 0> {
public:
static HDeoptimize* New(Isolate* isolate, Zone* zone, HValue* context,
const char* reason, Deoptimizer::BailoutType type,
Deoptimizer::DeoptReason reason,
Deoptimizer::BailoutType type,
HBasicBlock* unreachable_continuation) {
return new(zone) HDeoptimize(reason, type, unreachable_continuation);
}
@ -1377,20 +1378,20 @@ class HDeoptimize FINAL : public HTemplateControlInstruction<1, 0> {
return Representation::None();
}
const char* reason() const { return reason_; }
Deoptimizer::DeoptReason reason() const { return reason_; }
Deoptimizer::BailoutType type() { return type_; }
DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
private:
explicit HDeoptimize(const char* reason,
explicit HDeoptimize(Deoptimizer::DeoptReason reason,
Deoptimizer::BailoutType type,
HBasicBlock* unreachable_continuation)
: reason_(reason), type_(type) {
SetSuccessorAt(0, unreachable_continuation);
}
const char* reason_;
Deoptimizer::DeoptReason reason_;
Deoptimizer::BailoutType type_;
};

View File

@ -931,7 +931,7 @@ void HGraphBuilder::IfBuilder::Else() {
}
void HGraphBuilder::IfBuilder::Deopt(const char* reason) {
void HGraphBuilder::IfBuilder::Deopt(Deoptimizer::DeoptReason reason) {
DCHECK(did_then_);
builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
AddMergeAtJoinBlock(true);
@ -1273,7 +1273,8 @@ HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
}
void HGraphBuilder::FinishExitWithHardDeoptimization(const char* reason) {
void HGraphBuilder::FinishExitWithHardDeoptimization(
Deoptimizer::DeoptReason reason) {
Add<HDeoptimize>(reason, Deoptimizer::EAGER);
FinishExitCurrentBlock(New<HAbnormalExit>());
}
@ -1589,7 +1590,7 @@ void HGraphBuilder::BuildNonGlobalObjectCheck(HValue* receiver) {
if_global_object.If<HCompareNumericAndBranch>(instance_type,
min_global_type,
Token::GTE);
if_global_object.ThenDeopt("receiver was a global object");
if_global_object.ThenDeopt(Deoptimizer::kReceiverWasAGlobalObject);
if_global_object.End();
}
@ -1919,7 +1920,7 @@ HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
if_objectissmi.Else();
{
if (type->Is(Type::SignedSmall())) {
if_objectissmi.Deopt("Expected smi");
if_objectissmi.Deopt(Deoptimizer::kExpectedSmi);
} else {
// Check if the object is a heap number.
IfBuilder if_objectisnumber(this);
@ -1974,7 +1975,7 @@ HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
if_objectisnumber.Else();
{
if (type->Is(Type::Number())) {
if_objectisnumber.Deopt("Expected heap number");
if_objectisnumber.Deopt(Deoptimizer::kExpectedHeapNumber);
}
}
if_objectisnumber.JoinContinuation(&found);
@ -2447,7 +2448,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
negative_checker.Then();
HInstruction* result = AddElementAccess(
backing_store, key, val, bounds_check, elements_kind, access_type);
negative_checker.ElseDeopt("Negative key encountered");
negative_checker.ElseDeopt(Deoptimizer::kNegativeKeyEncountered);
negative_checker.End();
length_checker.End();
return result;
@ -2532,7 +2533,8 @@ HValue* HGraphBuilder::BuildAllocateArrayFromLength(
if (!(top_info()->IsStub()) &&
IsFastPackedElementsKind(array_builder->kind())) {
// We'll come back later with better (holey) feedback.
if_builder.Deopt("Holey array despite packed elements_kind feedback");
if_builder.Deopt(
Deoptimizer::kHoleyArrayDespitePackedElements_kindFeedback);
} else {
Push(checked_length); // capacity
Push(checked_length); // length
@ -3071,14 +3073,14 @@ void HGraphBuilder::BuildCompareNil(HValue* value, Type* type,
Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap());
IfBuilder map_check(this);
map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map);
map_check.ThenDeopt("Unknown map");
map_check.ThenDeopt(Deoptimizer::kUnknownMap);
map_check.End();
} else {
DCHECK(map_embedding == kEmbedMapsDirectly);
Add<HCheckMaps>(value, type->Classes().Current());
}
} else {
if_nil.Deopt("Too many undetectable types");
if_nil.Deopt(Deoptimizer::kTooManyUndetectableTypes);
}
}
@ -6408,7 +6410,8 @@ void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
// know about and do not want to handle ones we've never seen. Otherwise
// use a generic IC.
if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
FinishExitWithHardDeoptimization("Unknown map in polymorphic access");
FinishExitWithHardDeoptimization(
Deoptimizer::kUnknownMapInPolymorphicAccess);
} else {
HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name,
value);
@ -6555,7 +6558,7 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
if (value->IsConstant()) {
HConstant* c_value = HConstant::cast(value);
if (!constant.is_identical_to(c_value->handle(isolate()))) {
Add<HDeoptimize>("Constant global variable assignment",
Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment,
Deoptimizer::EAGER);
}
} else {
@ -6568,7 +6571,7 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
}
builder.Then();
builder.Else();
Add<HDeoptimize>("Constant global variable assignment",
Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment,
Deoptimizer::EAGER);
builder.End();
}
@ -6888,7 +6891,8 @@ HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
HValue* value,
bool is_uninitialized) {
if (is_uninitialized) {
Add<HDeoptimize>("Insufficient type feedback for generic named access",
Add<HDeoptimize>(
Deoptimizer::kInsufficientTypeFeedbackForGenericNamedAccess,
Deoptimizer::SOFT);
}
if (access_type == LOAD) {
@ -7191,7 +7195,8 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
DCHECK(join->predecessors()->length() > 0);
// Deopt if none of the cases matched.
NoObservableSideEffectsScope scope(this);
FinishExitWithHardDeoptimization("Unknown map in polymorphic element access");
FinishExitWithHardDeoptimization(
Deoptimizer::kUnknownMapInPolymorphicElementAccess);
set_current_block(join);
return access_type == STORE ? val : Pop();
}
@ -7286,12 +7291,12 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
if (access_type == STORE) {
if (expr->IsAssignment() &&
expr->AsAssignment()->HasNoTypeInformation()) {
Add<HDeoptimize>("Insufficient type feedback for keyed store",
Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore,
Deoptimizer::SOFT);
}
} else {
if (expr->AsProperty()->HasNoTypeInformation()) {
Add<HDeoptimize>("Insufficient type feedback for keyed load",
Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad,
Deoptimizer::SOFT);
}
}
@ -7736,7 +7741,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
// know about and do not want to handle ones we've never seen. Otherwise
// use a generic IC.
if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
FinishExitWithHardDeoptimization("Unknown map in polymorphic call");
FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall);
} else {
Property* prop = expr->expression()->AsProperty();
HInstruction* function = BuildNamedGeneric(
@ -9243,7 +9248,8 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) {
// We have to use EAGER deoptimization here because Deoptimizer::SOFT
// gets ignored by the always-opt flag, which leads to incorrect code.
Add<HDeoptimize>("Insufficient type feedback for call with arguments",
Add<HDeoptimize>(
Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments,
Deoptimizer::EAGER);
arguments_flag = ARGUMENTS_FAKED;
}
@ -10475,7 +10481,8 @@ HValue* HGraphBuilder::BuildBinaryOperation(
right_type->Maybe(Type::Receiver()));
if (!left_type->IsInhabited()) {
Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation",
Add<HDeoptimize>(
Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation,
Deoptimizer::SOFT);
// TODO(rossberg): we should be able to get rid of non-continuous
// defaults.
@ -10486,7 +10493,8 @@ HValue* HGraphBuilder::BuildBinaryOperation(
}
if (!right_type->IsInhabited()) {
Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation",
Add<HDeoptimize>(
Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation,
Deoptimizer::SOFT);
right_type = Type::Any(zone());
} else {
@ -10607,7 +10615,7 @@ HValue* HGraphBuilder::BuildBinaryOperation(
IfBuilder if_same(this);
if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ);
if_same.Then();
if_same.ElseDeopt("Unexpected RHS of binary operation");
if_same.ElseDeopt(Deoptimizer::kUnexpectedRHSOfBinaryOperation);
right = fixed_right;
}
instr = AddUncasted<HMod>(left, right);
@ -10981,8 +10989,8 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
// Cases handled below depend on collected type feedback. They should
// soft deoptimize when there is no type feedback.
if (!combined_type->IsInhabited()) {
Add<HDeoptimize>("Insufficient type feedback for combined type "
"of binary operation",
Add<HDeoptimize>(
Deoptimizer::kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation,
Deoptimizer::SOFT);
combined_type = left_type = right_type = Type::Any(zone());
}
@ -10999,7 +11007,7 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
HConstant::cast(left)->HasNumberValue()) ||
(right->IsConstant() &&
HConstant::cast(right)->HasNumberValue())) {
Add<HDeoptimize>("Type mismatch between feedback and constant",
Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant,
Deoptimizer::SOFT);
// The caller expects a branch instruction, so make it happy.
return New<HBranch>(graph()->GetConstantTrue());
@ -11037,7 +11045,7 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
!HConstant::cast(left)->HasInternalizedStringValue()) ||
(right->IsConstant() &&
!HConstant::cast(right)->HasInternalizedStringValue())) {
Add<HDeoptimize>("Type mismatch between feedback and constant",
Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant,
Deoptimizer::SOFT);
// The caller expects a branch instruction, so make it happy.
return New<HBranch>(graph()->GetConstantTrue());

View File

@ -1475,7 +1475,7 @@ class HGraphBuilder {
HValue* EnforceNumberType(HValue* number, Type* expected);
HValue* TruncateToNumber(HValue* value, Type** expected);
void FinishExitWithHardDeoptimization(const char* reason);
void FinishExitWithHardDeoptimization(Deoptimizer::DeoptReason reason);
void AddIncrementCounter(StatsCounter* counter);
@ -1623,12 +1623,12 @@ class HGraphBuilder {
void Else();
void End();
void Deopt(const char* reason);
void ThenDeopt(const char* reason) {
void Deopt(Deoptimizer::DeoptReason reason);
void ThenDeopt(Deoptimizer::DeoptReason reason) {
Then();
Deopt(reason);
}
void ElseDeopt(const char* reason) {
void ElseDeopt(Deoptimizer::DeoptReason reason) {
Else();
Deopt(reason);
}
@ -1938,9 +1938,9 @@ class HGraphBuilder {
};
template<>
template <>
inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>(
const char* reason, Deoptimizer::BailoutType type) {
Deoptimizer::DeoptReason reason, Deoptimizer::BailoutType type) {
if (type == Deoptimizer::SOFT) {
isolate()->counters()->soft_deopts_requested()->Increment();
if (FLAG_always_opt) return NULL;
@ -1958,9 +1958,9 @@ inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>(
}
template<>
template <>
inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>(
const char* reason, Deoptimizer::BailoutType type) {
Deoptimizer::DeoptReason reason, Deoptimizer::BailoutType type) {
return Add<HDeoptimize>(reason, type);
}

View File

@ -2640,6 +2640,15 @@ void Assembler::RecordComment(const char* msg, bool force) {
}
void Assembler::RecordDeoptReason(const int reason, const int raw_position) {
if (FLAG_trace_deopt) {
EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::POSITION, raw_position);
RecordRelocInfo(RelocInfo::DEOPT_REASON, reason);
}
}
void Assembler::GrowBuffer() {
DCHECK(buffer_overflow());
if (!own_buffer_) FATAL("external code buffer is too small");

View File

@ -1260,6 +1260,10 @@ class Assembler : public AssemblerBase {
// write a comment.
void RecordComment(const char* msg, bool force = false);
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(const int reason, const int raw_position);
// Writes a single byte or word of data in the code stream. Used for
// inline tables, e.g., jump-tables.
void db(uint8_t data);

View File

@ -819,7 +819,7 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(
void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
const char* detail,
Deoptimizer::DeoptReason deopt_reason,
Deoptimizer::BailoutType bailout_type) {
LEnvironment* environment = instr->environment();
RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
@ -862,7 +862,7 @@ void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
}
Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(),
instr->Mnemonic(), detail);
instr->Mnemonic(), deopt_reason);
DCHECK(info()->IsStub() || frame_is_built_);
if (cc == no_condition && frame_is_built_) {
DeoptComment(reason);
@ -886,11 +886,11 @@ void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
const char* detail) {
Deoptimizer::DeoptReason deopt_reason) {
Deoptimizer::BailoutType bailout_type = info()->IsStub()
? Deoptimizer::LAZY
: Deoptimizer::EAGER;
DeoptimizeIf(cc, instr, detail, bailout_type);
DeoptimizeIf(cc, instr, deopt_reason, bailout_type);
}
@ -1120,7 +1120,7 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
__ and_(dividend, mask);
__ neg(dividend);
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
__ jmp(&done, Label::kNear);
}
@ -1137,7 +1137,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
DCHECK(ToRegister(instr->result()).is(eax));
if (divisor == 0) {
DeoptimizeIf(no_condition, instr, "division by zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1152,7 +1152,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
Label remainder_not_zero;
__ j(not_zero, &remainder_not_zero, Label::kNear);
__ cmp(dividend, Immediate(0));
DeoptimizeIf(less, instr, "minus zero");
DeoptimizeIf(less, instr, Deoptimizer::kMinusZero);
__ bind(&remainder_not_zero);
}
}
@ -1174,7 +1174,7 @@ void LCodeGen::DoModI(LModI* instr) {
// deopt in this case because we can't return a NaN.
if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
__ test(right_reg, Operand(right_reg));
DeoptimizeIf(zero, instr, "division by zero");
DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero);
}
// Check for kMinInt % -1, idiv would signal a divide error. We
@ -1185,7 +1185,7 @@ void LCodeGen::DoModI(LModI* instr) {
__ j(not_equal, &no_overflow_possible, Label::kNear);
__ cmp(right_reg, -1);
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(equal, instr, "minus zero");
DeoptimizeIf(equal, instr, Deoptimizer::kMinusZero);
} else {
__ j(not_equal, &no_overflow_possible, Label::kNear);
__ Move(result_reg, Immediate(0));
@ -1204,7 +1204,7 @@ void LCodeGen::DoModI(LModI* instr) {
__ j(not_sign, &positive_left, Label::kNear);
__ idiv(right_reg);
__ test(result_reg, Operand(result_reg));
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
__ jmp(&done, Label::kNear);
__ bind(&positive_left);
}
@ -1224,19 +1224,19 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ test(dividend, dividend);
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
// Check for (kMinInt / -1).
if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
__ cmp(dividend, kMinInt);
DeoptimizeIf(zero, instr, "overflow");
DeoptimizeIf(zero, instr, Deoptimizer::kOverflow);
}
// 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);
__ test(dividend, Immediate(mask));
DeoptimizeIf(not_zero, instr, "lost precision");
DeoptimizeIf(not_zero, instr, Deoptimizer::kLostPrecision);
}
__ Move(result, dividend);
int32_t shift = WhichPowerOf2Abs(divisor);
@ -1257,7 +1257,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
DCHECK(ToRegister(instr->result()).is(edx));
if (divisor == 0) {
DeoptimizeIf(no_condition, instr, "division by zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1265,7 +1265,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ test(dividend, dividend);
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
__ TruncatingDiv(dividend, Abs(divisor));
@ -1275,7 +1275,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
__ mov(eax, edx);
__ imul(eax, eax, divisor);
__ sub(eax, dividend);
DeoptimizeIf(not_equal, instr, "lost precision");
DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision);
}
}
@ -1295,7 +1295,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ test(divisor, divisor);
DeoptimizeIf(zero, instr, "division by zero");
DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero);
}
// Check for (0 / -x) that will produce negative zero.
@ -1304,7 +1304,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
__ test(dividend, dividend);
__ j(not_zero, &dividend_not_zero, Label::kNear);
__ test(divisor, divisor);
DeoptimizeIf(sign, instr, "minus zero");
DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero);
__ bind(&dividend_not_zero);
}
@ -1314,7 +1314,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
__ cmp(dividend, kMinInt);
__ j(not_zero, &dividend_not_min_int, Label::kNear);
__ cmp(divisor, -1);
DeoptimizeIf(zero, instr, "overflow");
DeoptimizeIf(zero, instr, Deoptimizer::kOverflow);
__ bind(&dividend_not_min_int);
}
@ -1325,7 +1325,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
// Deoptimize if remainder is not 0.
__ test(remainder, remainder);
DeoptimizeIf(not_zero, instr, "lost precision");
DeoptimizeIf(not_zero, instr, Deoptimizer::kLostPrecision);
}
}
@ -1347,13 +1347,13 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
// If the divisor is negative, we have to negate and handle edge cases.
__ neg(dividend);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
// Dividing by -1 is basically negation, unless we overflow.
if (divisor == -1) {
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
return;
}
@ -1380,7 +1380,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
DCHECK(ToRegister(instr->result()).is(edx));
if (divisor == 0) {
DeoptimizeIf(no_condition, instr, "division by zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1388,7 +1388,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
HMathFloorOfDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ test(dividend, dividend);
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
// Easy case: We need no dynamic check for the dividend and the flooring
@ -1435,7 +1435,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ test(divisor, divisor);
DeoptimizeIf(zero, instr, "division by zero");
DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero);
}
// Check for (0 / -x) that will produce negative zero.
@ -1444,7 +1444,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
__ test(dividend, dividend);
__ j(not_zero, &dividend_not_zero, Label::kNear);
__ test(divisor, divisor);
DeoptimizeIf(sign, instr, "minus zero");
DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero);
__ bind(&dividend_not_zero);
}
@ -1454,7 +1454,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
__ cmp(dividend, kMinInt);
__ j(not_zero, &dividend_not_min_int, Label::kNear);
__ cmp(divisor, -1);
DeoptimizeIf(zero, instr, "overflow");
DeoptimizeIf(zero, instr, Deoptimizer::kOverflow);
__ bind(&dividend_not_min_int);
}
@ -1532,7 +1532,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
}
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -1542,15 +1542,15 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ j(not_zero, &done, Label::kNear);
if (right->IsConstantOperand()) {
if (ToInteger32(LConstantOperand::cast(right)) < 0) {
DeoptimizeIf(no_condition, instr, "minus zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero);
} else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
__ cmp(ToRegister(instr->temp()), Immediate(0));
DeoptimizeIf(less, instr, "minus zero");
DeoptimizeIf(less, instr, Deoptimizer::kMinusZero);
}
} else {
// Test the non-zero operand for negative sign.
__ or_(ToRegister(instr->temp()), ToOperand(right));
DeoptimizeIf(sign, instr, "minus zero");
DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero);
}
__ bind(&done);
}
@ -1623,7 +1623,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
__ shr_cl(ToRegister(left));
if (instr->can_deopt()) {
__ test(ToRegister(left), ToRegister(left));
DeoptimizeIf(sign, instr, "negative value");
DeoptimizeIf(sign, instr, Deoptimizer::kNegativeValue);
}
break;
case Token::SHL:
@ -1640,7 +1640,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
case Token::ROR:
if (shift_count == 0 && instr->can_deopt()) {
__ test(ToRegister(left), ToRegister(left));
DeoptimizeIf(sign, instr, "negative value");
DeoptimizeIf(sign, instr, Deoptimizer::kNegativeValue);
} else {
__ ror(ToRegister(left), shift_count);
}
@ -1655,7 +1655,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
__ shr(ToRegister(left), shift_count);
} else if (instr->can_deopt()) {
__ test(ToRegister(left), ToRegister(left));
DeoptimizeIf(sign, instr, "negative value");
DeoptimizeIf(sign, instr, Deoptimizer::kNegativeValue);
}
break;
case Token::SHL:
@ -1666,7 +1666,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
__ shl(ToRegister(left), shift_count - 1);
}
__ SmiTag(ToRegister(left));
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
} else {
__ shl(ToRegister(left), shift_count);
}
@ -1692,7 +1692,7 @@ void LCodeGen::DoSubI(LSubI* instr) {
__ sub(ToRegister(left), ToOperand(right));
}
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
}
@ -1775,9 +1775,9 @@ void LCodeGen::DoDateField(LDateField* instr) {
DCHECK(object.is(eax));
__ test(object, Immediate(kSmiTagMask));
DeoptimizeIf(zero, instr, "Smi");
DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
__ CmpObjectType(object, JS_DATE_TYPE, scratch);
DeoptimizeIf(not_equal, instr, "not a date object");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotADateObject);
if (index->value() == 0) {
__ mov(result, FieldOperand(object, JSDate::kValueOffset));
@ -1907,7 +1907,7 @@ void LCodeGen::DoAddI(LAddI* instr) {
__ add(ToRegister(left), ToOperand(right));
}
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
}
}
@ -2154,7 +2154,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
} else if (expected.NeedsMap()) {
// If we need a map later and have a Smi -> deopt.
__ test(reg, Immediate(kSmiTagMask));
DeoptimizeIf(zero, instr, "Smi");
DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
}
Register map = no_reg; // Keep the compiler happy.
@ -2211,7 +2211,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(no_condition, instr, "unexpected object");
DeoptimizeIf(no_condition, instr, Deoptimizer::kUnexpectedObject);
}
}
}
@ -2843,7 +2843,7 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
__ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle()));
if (instr->hydrogen()->RequiresHoleCheck()) {
__ cmp(result, factory()->the_hole_value());
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
}
}
@ -2892,7 +2892,7 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
// it as no longer deleted. We deoptimize in that case.
if (instr->hydrogen()->RequiresHoleCheck()) {
__ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value());
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
}
// Store the value.
@ -2909,7 +2909,7 @@ void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
__ cmp(result, factory()->the_hole_value());
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
} else {
Label is_not_hole;
__ j(not_equal, &is_not_hole, Label::kNear);
@ -2930,7 +2930,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
__ cmp(target, factory()->the_hole_value());
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
} else {
__ j(not_equal, &skip_assignment, Label::kNear);
}
@ -3030,7 +3030,7 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
// Check that the function has a prototype or an initial map.
__ cmp(Operand(result), Immediate(factory()->the_hole_value()));
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
// If the function does not have an initial map, we're done.
Label done;
@ -3123,7 +3123,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
__ mov(result, operand);
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
__ test(result, Operand(result));
DeoptimizeIf(negative, instr, "negative value");
DeoptimizeIf(negative, instr, Deoptimizer::kNegativeValue);
}
break;
case EXTERNAL_FLOAT32_ELEMENTS:
@ -3153,7 +3153,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
FAST_DOUBLE_ELEMENTS,
instr->base_offset() + sizeof(kHoleNanLower32));
__ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
}
Operand double_load_operand = BuildFastArrayOperand(
@ -3180,10 +3180,10 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
__ test(result, Immediate(kSmiTagMask));
DeoptimizeIf(not_equal, instr, "not a Smi");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotASmi);
} else {
__ cmp(result, factory()->the_hole_value());
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
}
}
}
@ -3330,9 +3330,9 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
// The receiver should be a JS object.
__ test(receiver, Immediate(kSmiTagMask));
DeoptimizeIf(equal, instr, "Smi");
DeoptimizeIf(equal, instr, Deoptimizer::kSmi);
__ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
DeoptimizeIf(below, instr, "not a JavaScript object");
DeoptimizeIf(below, instr, Deoptimizer::kNotAJavaScriptObject);
__ jmp(&receiver_ok, Label::kNear);
__ bind(&global_object);
@ -3358,7 +3358,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// adaptor frame below it.
const uint32_t kArgumentsLimit = 1 * KB;
__ cmp(length, kArgumentsLimit);
DeoptimizeIf(above, instr, "too many arguments");
DeoptimizeIf(above, instr, Deoptimizer::kTooManyArguments);
__ push(receiver);
__ mov(receiver, length);
@ -3583,7 +3583,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
Register input_reg = ToRegister(instr->value());
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
factory()->heap_number_map());
DeoptimizeIf(not_equal, instr, "not a heap number");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
Label slow, allocated, done;
Register tmp = input_reg.is(eax) ? ecx : eax;
@ -3630,7 +3630,7 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
Label is_positive;
__ j(not_sign, &is_positive, Label::kNear);
__ neg(input_reg); // Sets flags.
DeoptimizeIf(negative, instr, "overflow");
DeoptimizeIf(negative, instr, Deoptimizer::kOverflow);
__ bind(&is_positive);
}
@ -3689,20 +3689,20 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ j(not_equal, &non_zero, Label::kNear);
__ movmskpd(output_reg, input_reg);
__ test(output_reg, Immediate(1));
DeoptimizeIf(not_zero, instr, "minus zero");
DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
__ bind(&non_zero);
}
__ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
__ cvttsd2si(output_reg, Operand(xmm_scratch));
// Overflow is signalled with minint.
__ cmp(output_reg, 0x1);
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
} else {
Label negative_sign, done;
// Deoptimize on unordered.
__ xorps(xmm_scratch, xmm_scratch); // Zero the register.
__ ucomisd(input_reg, xmm_scratch);
DeoptimizeIf(parity_even, instr, "NaN");
DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN);
__ j(below, &negative_sign, Label::kNear);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -3711,7 +3711,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ j(above, &positive_sign, Label::kNear);
__ movmskpd(output_reg, input_reg);
__ test(output_reg, Immediate(1));
DeoptimizeIf(not_zero, instr, "minus zero");
DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
__ Move(output_reg, Immediate(0));
__ jmp(&done, Label::kNear);
__ bind(&positive_sign);
@ -3721,7 +3721,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ cvttsd2si(output_reg, Operand(input_reg));
// Overflow is signalled with minint.
__ cmp(output_reg, 0x1);
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
__ jmp(&done, Label::kNear);
// Non-zero negative reaches here.
@ -3732,7 +3732,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ ucomisd(input_reg, xmm_scratch);
__ j(equal, &done, Label::kNear);
__ sub(output_reg, Immediate(1));
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
__ bind(&done);
}
@ -3760,7 +3760,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
__ cvttsd2si(output_reg, Operand(xmm_scratch));
// Overflow is signalled with minint.
__ cmp(output_reg, 0x1);
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
__ jmp(&done, dist);
__ bind(&below_one_half);
@ -3775,7 +3775,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
__ cvttsd2si(output_reg, Operand(input_temp));
// Catch minint due to overflow, and to prevent overflow when compensating.
__ cmp(output_reg, 0x1);
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
__ Cvtsi2sd(xmm_scratch, output_reg);
__ ucomisd(xmm_scratch, input_temp);
@ -3791,7 +3791,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
// If the sign is positive, we return +0.
__ movmskpd(output_reg, input_reg);
__ test(output_reg, Immediate(1));
DeoptimizeIf(not_zero, instr, "minus zero");
DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
}
__ Move(output_reg, Immediate(0));
__ bind(&done);
@ -3867,7 +3867,7 @@ void LCodeGen::DoPower(LPower* instr) {
__ JumpIfSmi(tagged_exponent, &no_deopt);
DCHECK(!ecx.is(tagged_exponent));
__ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, ecx);
DeoptimizeIf(not_equal, instr, "not a heap number");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
__ bind(&no_deopt);
MathPowStub stub(isolate(), MathPowStub::TAGGED);
__ CallStub(&stub);
@ -4197,7 +4197,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
__ int3();
__ bind(&done);
} else {
DeoptimizeIf(cc, instr, "out of bounds");
DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds);
}
}
@ -4360,7 +4360,7 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
Register temp = ToRegister(instr->temp());
Label no_memento_found;
__ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
DeoptimizeIf(equal, instr, "memento found");
DeoptimizeIf(equal, instr, Deoptimizer::kMementoFound);
__ bind(&no_memento_found);
}
@ -4706,12 +4706,12 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) {
if (hchange->CheckFlag(HValue::kCanOverflow) &&
hchange->value()->CheckFlag(HValue::kUint32)) {
__ test(input, Immediate(0xc0000000));
DeoptimizeIf(not_zero, instr, "overflow");
DeoptimizeIf(not_zero, instr, Deoptimizer::kOverflow);
}
__ SmiTag(input);
if (hchange->CheckFlag(HValue::kCanOverflow) &&
!hchange->value()->CheckFlag(HValue::kUint32)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
}
@ -4722,7 +4722,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
DCHECK(input->IsRegister() && input->Equals(instr->result()));
if (instr->needs_check()) {
__ test(result, Immediate(kSmiTagMask));
DeoptimizeIf(not_zero, instr, "not a Smi");
DeoptimizeIf(not_zero, instr, Deoptimizer::kNotASmi);
} else {
__ AssertSmi(result);
}
@ -4749,7 +4749,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
if (can_convert_undefined_to_nan) {
__ j(not_equal, &convert, Label::kNear);
} else {
DeoptimizeIf(not_equal, instr, "not a heap number");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
}
// Heap number to XMM conversion.
@ -4762,7 +4762,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
__ j(not_zero, &done, Label::kNear);
__ movmskpd(temp_reg, result_reg);
__ test_b(temp_reg, 1);
DeoptimizeIf(not_zero, instr, "minus zero");
DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
}
__ jmp(&done, Label::kNear);
@ -4771,7 +4771,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
// Convert undefined to NaN.
__ cmp(input_reg, factory()->undefined_value());
DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumberUndefined);
__ pcmpeqd(result_reg, result_reg);
__ jmp(&done, Label::kNear);
@ -4823,26 +4823,27 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
__ bind(&check_false);
__ cmp(input_reg, factory()->false_value());
DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false");
DeoptimizeIf(not_equal, instr,
Deoptimizer::kNotAHeapNumberUndefinedBoolean);
__ Move(input_reg, Immediate(0));
} else {
XMMRegister scratch = ToDoubleRegister(instr->temp());
DCHECK(!scratch.is(xmm0));
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
isolate()->factory()->heap_number_map());
DeoptimizeIf(not_equal, instr, "not a heap number");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
__ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
__ cvttsd2si(input_reg, Operand(xmm0));
__ Cvtsi2sd(scratch, Operand(input_reg));
__ ucomisd(xmm0, scratch);
DeoptimizeIf(not_equal, instr, "lost precision");
DeoptimizeIf(parity_even, instr, "NaN");
DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision);
DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN);
if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
__ test(input_reg, Operand(input_reg));
__ j(not_zero, done);
__ movmskpd(input_reg, xmm0);
__ and_(input_reg, 1);
DeoptimizeIf(not_zero, instr, "minus zero");
DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
}
}
}
@ -4922,11 +4923,11 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
&is_nan, &minus_zero, dist);
__ jmp(&done, dist);
__ bind(&lost_precision);
DeoptimizeIf(no_condition, instr, "lost precision");
DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision);
__ bind(&is_nan);
DeoptimizeIf(no_condition, instr, "NaN");
DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN);
__ bind(&minus_zero);
DeoptimizeIf(no_condition, instr, "minus zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero);
__ bind(&done);
}
}
@ -4948,21 +4949,21 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
&minus_zero, dist);
__ jmp(&done, dist);
__ bind(&lost_precision);
DeoptimizeIf(no_condition, instr, "lost precision");
DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision);
__ bind(&is_nan);
DeoptimizeIf(no_condition, instr, "NaN");
DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN);
__ bind(&minus_zero);
DeoptimizeIf(no_condition, instr, "minus zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero);
__ bind(&done);
__ SmiTag(result_reg);
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
LOperand* input = instr->value();
__ test(ToOperand(input), Immediate(kSmiTagMask));
DeoptimizeIf(not_zero, instr, "not a Smi");
DeoptimizeIf(not_zero, instr, Deoptimizer::kNotASmi);
}
@ -4970,7 +4971,7 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
if (!instr->hydrogen()->value()->type().IsHeapObject()) {
LOperand* input = instr->value();
__ test(ToOperand(input), Immediate(kSmiTagMask));
DeoptimizeIf(zero, instr, "Smi");
DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
}
}
@ -4991,14 +4992,14 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
// If there is only one type in the interval check for equality.
if (first == last) {
DeoptimizeIf(not_equal, instr, "wrong instance type");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongInstanceType);
} else {
DeoptimizeIf(below, instr, "wrong instance type");
DeoptimizeIf(below, instr, Deoptimizer::kWrongInstanceType);
// Omit check for the last type.
if (last != LAST_TYPE) {
__ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
static_cast<int8_t>(last));
DeoptimizeIf(above, instr, "wrong instance type");
DeoptimizeIf(above, instr, Deoptimizer::kWrongInstanceType);
}
}
} else {
@ -5009,12 +5010,13 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
if (base::bits::IsPowerOfTwo32(mask)) {
DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
__ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask);
DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type");
DeoptimizeIf(tag == 0 ? not_zero : zero, instr,
Deoptimizer::kWrongInstanceType);
} else {
__ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
__ and_(temp, mask);
__ cmp(temp, tag);
DeoptimizeIf(not_equal, instr, "wrong instance type");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongInstanceType);
}
}
}
@ -5030,7 +5032,7 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
Operand operand = ToOperand(instr->value());
__ cmp(operand, object);
}
DeoptimizeIf(not_equal, instr, "value mismatch");
DeoptimizeIf(not_equal, instr, Deoptimizer::kValueMismatch);
}
@ -5045,7 +5047,7 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
__ test(eax, Immediate(kSmiTagMask));
}
DeoptimizeIf(zero, instr, "instance migration failed");
DeoptimizeIf(zero, instr, Deoptimizer::kInstanceMigrationFailed);
}
@ -5099,7 +5101,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
if (instr->hydrogen()->HasMigrationTarget()) {
__ j(not_equal, deferred->entry());
} else {
DeoptimizeIf(not_equal, instr, "wrong map");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap);
}
__ bind(&success);
@ -5138,7 +5140,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
// Check for undefined. Undefined is converted to zero for clamping
// conversions.
__ cmp(input_reg, factory()->undefined_value());
DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumberUndefined);
__ mov(input_reg, 0);
__ jmp(&done, Label::kNear);
@ -5626,17 +5628,17 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
DCHECK(ToRegister(instr->context()).is(esi));
__ cmp(eax, isolate()->factory()->undefined_value());
DeoptimizeIf(equal, instr, "undefined");
DeoptimizeIf(equal, instr, Deoptimizer::kUndefined);
__ cmp(eax, isolate()->factory()->null_value());
DeoptimizeIf(equal, instr, "null");
DeoptimizeIf(equal, instr, Deoptimizer::kNull);
__ test(eax, Immediate(kSmiTagMask));
DeoptimizeIf(zero, instr, "Smi");
DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
__ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx);
DeoptimizeIf(below_equal, instr, "wrong instance type");
DeoptimizeIf(below_equal, instr, Deoptimizer::kWrongInstanceType);
Label use_cache, call_runtime;
__ CheckEnumCache(&call_runtime);
@ -5651,7 +5653,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ cmp(FieldOperand(eax, HeapObject::kMapOffset),
isolate()->factory()->meta_map());
DeoptimizeIf(not_equal, instr, "wrong map");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap);
__ bind(&use_cache);
}
@ -5674,7 +5676,7 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
FieldOperand(result, FixedArray::SizeFor(instr->idx())));
__ bind(&done);
__ test(result, result);
DeoptimizeIf(equal, instr, "no cache");
DeoptimizeIf(equal, instr, Deoptimizer::kNoCache);
}
@ -5682,7 +5684,7 @@ void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
Register object = ToRegister(instr->value());
__ cmp(ToRegister(instr->map()),
FieldOperand(object, HeapObject::kMapOffset));
DeoptimizeIf(not_equal, instr, "wrong map");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap);
}

View File

@ -202,9 +202,11 @@ class LCodeGen: public LCodeGenBase {
void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
Safepoint::DeoptMode mode);
void DeoptimizeIf(Condition cc, LInstruction* instr, const char* detail,
void DeoptimizeIf(Condition cc, LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason,
Deoptimizer::BailoutType bailout_type);
void DeoptimizeIf(Condition cc, LInstruction* instr, const char* detail);
void DeoptimizeIf(Condition cc, LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason);
bool DeoptEveryNTimes() {
return FLAG_deopt_every_n_times != 0 && !info()->IsStub();

View File

@ -153,11 +153,7 @@ void LCodeGenBase::Comment(const char* format, ...) {
void LCodeGenBase::DeoptComment(const Deoptimizer::Reason& reason) {
std::ostringstream os;
os << ";;; deoptimize at " << HSourcePosition(reason.raw_position) << " "
<< reason.mnemonic;
if (reason.detail != NULL) os << ": " << reason.detail;
Comment("%s", os.str().c_str());
masm()->RecordDeoptReason(reason.deopt_reason, reason.raw_position);
}

View File

@ -2347,6 +2347,15 @@ void Assembler::RecordComment(const char* msg) {
}
void Assembler::RecordDeoptReason(const int reason, const int raw_position) {
if (FLAG_trace_deopt) {
EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::POSITION, raw_position);
RecordRelocInfo(RelocInfo::DEOPT_REASON, reason);
}
}
int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) {
Instr instr = instr_at(pc);
DCHECK(IsJ(instr) || IsLui(instr));

View File

@ -1016,6 +1016,11 @@ class Assembler : public AssemblerBase {
// Use --code-comments to enable.
void RecordComment(const char* msg);
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(const int reason, const int raw_position);
static int RelocateInternalReference(byte* pc, intptr_t pc_delta);
// Writes a single byte or word of data in the code stream. Used for

View File

@ -813,9 +813,9 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason,
Deoptimizer::BailoutType bailout_type,
const char* detail, Register src1,
const Operand& src2) {
Register src1, const Operand& src2) {
LEnvironment* environment = instr->environment();
RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
DCHECK(environment->HasBeenRegistered());
@ -857,7 +857,7 @@ void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
}
Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(),
instr->Mnemonic(), detail);
instr->Mnemonic(), deopt_reason);
DCHECK(info()->IsStub() || frame_is_built_);
// Go through jump table if we need to handle condition, build frame, or
// restore caller doubles.
@ -880,12 +880,12 @@ void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
const char* detail, Register src1,
const Operand& src2) {
Deoptimizer::DeoptReason deopt_reason,
Register src1, const Operand& src2) {
Deoptimizer::BailoutType bailout_type = info()->IsStub()
? Deoptimizer::LAZY
: Deoptimizer::EAGER;
DeoptimizeIf(condition, instr, bailout_type, detail, src1, src2);
DeoptimizeIf(condition, instr, deopt_reason, bailout_type, src1, src2);
}
@ -1116,7 +1116,8 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
__ subu(dividend, zero_reg, dividend);
__ And(dividend, dividend, Operand(mask));
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr, "minus zero", dividend, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
Operand(zero_reg));
}
__ Branch(USE_DELAY_SLOT, &done);
__ subu(dividend, zero_reg, dividend);
@ -1148,7 +1149,8 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label remainder_not_zero;
__ Branch(&remainder_not_zero, ne, result, Operand(zero_reg));
DeoptimizeIf(lt, instr, "minus zero", dividend, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, dividend,
Operand(zero_reg));
__ bind(&remainder_not_zero);
}
}
@ -1167,7 +1169,8 @@ void LCodeGen::DoModI(LModI* instr) {
// Check for x % 0, we have to deopt in this case because we can't return a
// NaN.
if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
DeoptimizeIf(eq, instr, "division by zero", right_reg, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, right_reg,
Operand(zero_reg));
}
// Check for kMinInt % -1, div will return kMinInt, which is not what we
@ -1176,7 +1179,7 @@ void LCodeGen::DoModI(LModI* instr) {
Label no_overflow_possible;
__ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt));
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr, "minus zero", right_reg, Operand(-1));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, right_reg, Operand(-1));
} else {
__ Branch(&no_overflow_possible, ne, right_reg, Operand(-1));
__ Branch(USE_DELAY_SLOT, &done);
@ -1188,7 +1191,8 @@ void LCodeGen::DoModI(LModI* instr) {
// If we care about -0, test if the dividend is <0 and the result is 0.
__ Branch(&done, ge, left_reg, Operand(zero_reg));
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr, "minus zero", result_reg, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result_reg,
Operand(zero_reg));
}
__ bind(&done);
}
@ -1204,18 +1208,19 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
DeoptimizeIf(eq, instr, "minus zero", dividend, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
Operand(zero_reg));
}
// Check for (kMinInt / -1).
if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
DeoptimizeIf(eq, instr, "overflow", dividend, Operand(kMinInt));
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow, dividend, Operand(kMinInt));
}
// 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);
__ And(at, dividend, Operand(mask));
DeoptimizeIf(ne, instr, "lost precision", at, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, at, Operand(zero_reg));
}
if (divisor == -1) { // Nice shortcut, not needed for correctness.
@ -1252,7 +1257,8 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
DeoptimizeIf(eq, instr, "minus zero", dividend, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
Operand(zero_reg));
}
__ TruncatingDiv(result, dividend, Abs(divisor));
@ -1261,7 +1267,8 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
__ Mul(scratch0(), result, Operand(divisor));
__ Subu(scratch0(), scratch0(), dividend);
DeoptimizeIf(ne, instr, "lost precision", scratch0(), Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, scratch0(),
Operand(zero_reg));
}
}
@ -1280,14 +1287,16 @@ void LCodeGen::DoDivI(LDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
DeoptimizeIf(eq, instr, "division by zero", divisor, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, divisor,
Operand(zero_reg));
}
// Check for (0 / -x) that will produce negative zero.
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label left_not_zero;
__ Branch(&left_not_zero, ne, dividend, Operand(zero_reg));
DeoptimizeIf(lt, instr, "minus zero", divisor, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, divisor,
Operand(zero_reg));
__ bind(&left_not_zero);
}
@ -1296,12 +1305,13 @@ void LCodeGen::DoDivI(LDivI* instr) {
!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
Label left_not_min_int;
__ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt));
DeoptimizeIf(eq, instr, "overflow", divisor, Operand(-1));
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow, divisor, Operand(-1));
__ bind(&left_not_min_int);
}
if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
DeoptimizeIf(ne, instr, "lost precision", remainder, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, remainder,
Operand(zero_reg));
}
}
@ -1347,14 +1357,15 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
__ Subu(result, zero_reg, dividend);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr, "minus zero", result, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result, Operand(zero_reg));
}
// Dividing by -1 is basically negation, unless we overflow.
__ Xor(scratch, scratch, result);
if (divisor == -1) {
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
DeoptimizeIf(ge, instr, "overflow", scratch, Operand(zero_reg));
DeoptimizeIf(ge, instr, Deoptimizer::kOverflow, scratch,
Operand(zero_reg));
}
return;
}
@ -1389,7 +1400,8 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
// Check for (0 / -x) that will produce negative zero.
HMathFloorOfDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
DeoptimizeIf(eq, instr, "minus zero", dividend, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
Operand(zero_reg));
}
// Easy case: We need no dynamic check for the dividend and the flooring
@ -1433,14 +1445,16 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
DeoptimizeIf(eq, instr, "division by zero", divisor, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, divisor,
Operand(zero_reg));
}
// Check for (0 / -x) that will produce negative zero.
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label left_not_zero;
__ Branch(&left_not_zero, ne, dividend, Operand(zero_reg));
DeoptimizeIf(lt, instr, "minus zero", divisor, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, divisor,
Operand(zero_reg));
__ bind(&left_not_zero);
}
@ -1449,7 +1463,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
Label left_not_min_int;
__ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt));
DeoptimizeIf(eq, instr, "overflow", divisor, Operand(-1));
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow, divisor, Operand(-1));
__ bind(&left_not_min_int);
}
@ -1480,14 +1494,15 @@ void LCodeGen::DoMulI(LMulI* instr) {
if (bailout_on_minus_zero && (constant < 0)) {
// The case of a null constant will be handled separately.
// If constant is negative and left is null, the result should be -0.
DeoptimizeIf(eq, instr, "minus zero", left, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, left, Operand(zero_reg));
}
switch (constant) {
case -1:
if (overflow) {
__ SubuAndCheckForOverflow(result, zero_reg, left, scratch);
DeoptimizeIf(lt, instr, "overflow", scratch, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, scratch,
Operand(zero_reg));
} else {
__ Subu(result, zero_reg, left);
}
@ -1496,7 +1511,8 @@ void LCodeGen::DoMulI(LMulI* instr) {
if (bailout_on_minus_zero) {
// If left is strictly negative and the constant is null, the
// result is -0. Deoptimize if required, otherwise return 0.
DeoptimizeIf(lt, instr, "minus zero", left, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, left,
Operand(zero_reg));
}
__ mov(result, zero_reg);
break;
@ -1548,7 +1564,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ Mul(scratch, result, left, right);
}
__ sra(at, result, 31);
DeoptimizeIf(ne, instr, "overflow", scratch, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, scratch, Operand(at));
} else {
if (instr->hydrogen()->representation().IsSmi()) {
__ SmiUntag(result, left);
@ -1563,7 +1579,8 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ Xor(at, left, right);
__ Branch(&done, ge, at, Operand(zero_reg));
// Bail out if the result is minus zero.
DeoptimizeIf(eq, instr, "minus zero", result, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result,
Operand(zero_reg));
__ bind(&done);
}
}
@ -1627,7 +1644,8 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
case Token::SHR:
__ srlv(result, left, ToRegister(right_op));
if (instr->can_deopt()) {
DeoptimizeIf(lt, instr, "negative value", result, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kNegativeValue, result,
Operand(zero_reg));
}
break;
case Token::SHL:
@ -1662,7 +1680,8 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
} else {
if (instr->can_deopt()) {
__ And(at, left, Operand(0x80000000));
DeoptimizeIf(ne, instr, "negative value", at, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kNegativeValue, at,
Operand(zero_reg));
}
__ Move(result, left);
}
@ -1677,7 +1696,8 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
} else {
__ SmiTagCheckOverflow(result, left, scratch);
}
DeoptimizeIf(lt, instr, "overflow", scratch, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, scratch,
Operand(zero_reg));
} else {
__ sll(result, left, shift_count);
}
@ -1725,7 +1745,8 @@ void LCodeGen::DoSubI(LSubI* instr) {
ToRegister(right),
overflow); // Reg at also used as scratch.
}
DeoptimizeIf(lt, instr, "overflow", overflow, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, overflow,
Operand(zero_reg));
}
}
@ -1793,9 +1814,10 @@ void LCodeGen::DoDateField(LDateField* instr) {
DCHECK(!scratch.is(object));
__ SmiTst(object, at);
DeoptimizeIf(eq, instr, "Smi", at, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
__ GetObjectType(object, scratch, scratch);
DeoptimizeIf(ne, instr, "not a date object", scratch, Operand(JS_DATE_TYPE));
DeoptimizeIf(ne, instr, Deoptimizer::kNotADateObject, scratch,
Operand(JS_DATE_TYPE));
if (index->value() == 0) {
__ lw(result, FieldMemOperand(object, JSDate::kValueOffset));
@ -1930,7 +1952,8 @@ void LCodeGen::DoAddI(LAddI* instr) {
ToRegister(right),
overflow); // Reg at also used as scratch.
}
DeoptimizeIf(lt, instr, "overflow", overflow, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, overflow,
Operand(zero_reg));
}
}
@ -2191,7 +2214,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
} else if (expected.NeedsMap()) {
// If we need a map later and have a Smi -> deopt.
__ SmiTst(reg, at);
DeoptimizeIf(eq, instr, "Smi", at, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
}
const Register map = scratch0();
@ -2247,7 +2270,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, "unexpected object", zero_reg,
DeoptimizeIf(al, instr, Deoptimizer::kUnexpectedObject, zero_reg,
Operand(zero_reg));
}
}
@ -2893,7 +2916,7 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
__ lw(result, FieldMemOperand(at, Cell::kValueOffset));
if (instr->hydrogen()->RequiresHoleCheck()) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr, "hole", result, Operand(at));
DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(at));
}
}
@ -2948,7 +2971,7 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
Register payload = ToRegister(instr->temp());
__ lw(payload, FieldMemOperand(cell, Cell::kValueOffset));
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr, "hole", payload, Operand(at));
DeoptimizeIf(eq, instr, Deoptimizer::kHole, payload, Operand(at));
}
// Store the value.
@ -2967,7 +2990,7 @@ void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(eq, instr, "hole", result, Operand(at));
DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(at));
} else {
Label is_not_hole;
__ Branch(&is_not_hole, ne, result, Operand(at));
@ -2991,7 +3014,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(eq, instr, "hole", scratch, Operand(at));
DeoptimizeIf(eq, instr, Deoptimizer::kHole, scratch, Operand(at));
} else {
__ Branch(&skip_assignment, ne, scratch, Operand(at));
}
@ -3071,7 +3094,7 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
// Check that the function has a prototype or an initial map.
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr, "hole", result, Operand(at));
DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(at));
// If the function does not have an initial map, we're done.
Label done;
@ -3207,8 +3230,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
case UINT32_ELEMENTS:
__ lw(result, mem_operand);
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
DeoptimizeIf(Ugreater_equal, instr, "negative value", result,
Operand(0x80000000));
DeoptimizeIf(Ugreater_equal, instr, Deoptimizer::kNegativeValue,
result, Operand(0x80000000));
}
break;
case FLOAT32_ELEMENTS:
@ -3261,7 +3284,8 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
__ lw(scratch, MemOperand(scratch, kHoleNanUpper32Offset));
DeoptimizeIf(eq, instr, "hole", scratch, Operand(kHoleNanUpper32));
DeoptimizeIf(eq, instr, Deoptimizer::kHole, scratch,
Operand(kHoleNanUpper32));
}
}
@ -3297,10 +3321,11 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
__ SmiTst(result, scratch);
DeoptimizeIf(ne, instr, "not a Smi", scratch, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, scratch,
Operand(zero_reg));
} else {
__ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr, "hole", result, Operand(scratch));
DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(scratch));
}
}
}
@ -3446,10 +3471,10 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
// Deoptimize if the receiver is not a JS object.
__ SmiTst(receiver, scratch);
DeoptimizeIf(eq, instr, "Smi", scratch, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, scratch, Operand(zero_reg));
__ GetObjectType(receiver, scratch, scratch);
DeoptimizeIf(lt, instr, "not a JavaScript object", scratch,
DeoptimizeIf(lt, instr, Deoptimizer::kNotAJavaScriptObject, scratch,
Operand(FIRST_SPEC_OBJECT_TYPE));
__ Branch(&result_in_receiver);
@ -3485,7 +3510,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// Copy the arguments to this function possibly from the
// adaptor frame below it.
const uint32_t kArgumentsLimit = 1 * KB;
DeoptimizeIf(hi, instr, "too many arguments", length,
DeoptimizeIf(hi, instr, Deoptimizer::kTooManyArguments, length,
Operand(kArgumentsLimit));
// Push the receiver and use the register to keep the original
@ -3611,7 +3636,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
// Deoptimize if not a heap number.
__ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
DeoptimizeIf(ne, instr, "not a heap number", scratch, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch, Operand(at));
Label done;
Register exponent = scratch0();
@ -3678,7 +3703,7 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
__ mov(result, input);
__ subu(result, zero_reg, input);
// Overflow if result is still negative, i.e. 0x80000000.
DeoptimizeIf(lt, instr, "overflow", result, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, result, Operand(zero_reg));
__ bind(&done);
}
@ -3733,7 +3758,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
except_flag);
// Deopt if the operation did not succeed.
DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag,
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
Operand(zero_reg));
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -3742,7 +3767,8 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ Branch(&done, ne, result, Operand(zero_reg));
__ Mfhc1(scratch1, input);
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr, "minus zero", scratch1, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
Operand(zero_reg));
__ bind(&done);
}
}
@ -3775,7 +3801,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
// The following conversion will not work with numbers
// outside of ]-2^32, 2^32[.
DeoptimizeIf(ge, instr, "overflow", scratch,
DeoptimizeIf(ge, instr, Deoptimizer::kOverflow, scratch,
Operand(HeapNumber::kExponentBias + 32));
// Save the original sign for later comparison.
@ -3790,7 +3816,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
__ Xor(result, result, Operand(scratch));
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
// ARM uses 'mi' here, which is 'lt'
DeoptimizeIf(lt, instr, "minus zero", result, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, result, Operand(zero_reg));
} else {
Label skip2;
// ARM uses 'mi' here, which is 'lt'
@ -3809,7 +3835,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
double_scratch1,
except_flag);
DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag,
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
Operand(zero_reg));
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -3818,7 +3844,8 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
__ bind(&check_sign_on_zero);
__ Mfhc1(scratch, input);
__ And(scratch, scratch, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr, "minus zero", scratch, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch,
Operand(zero_reg));
}
__ bind(&done);
}
@ -3884,7 +3911,7 @@ void LCodeGen::DoPower(LPower* instr) {
DCHECK(!t3.is(tagged_exponent));
__ lw(t3, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
DeoptimizeIf(ne, instr, "not a heap number", t3, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, t3, Operand(at));
__ bind(&no_deopt);
MathPowStub stub(isolate(), MathPowStub::TAGGED);
__ CallStub(&stub);
@ -4276,7 +4303,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
__ stop("eliminated bounds check failed");
__ bind(&done);
} else {
DeoptimizeIf(cc, instr, "out of bounds", reg, operand);
DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds, reg, operand);
}
}
@ -4870,12 +4897,12 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) {
if (hchange->CheckFlag(HValue::kCanOverflow) &&
hchange->value()->CheckFlag(HValue::kUint32)) {
__ And(at, input, Operand(0xc0000000));
DeoptimizeIf(ne, instr, "overflow", at, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, at, Operand(zero_reg));
}
if (hchange->CheckFlag(HValue::kCanOverflow) &&
!hchange->value()->CheckFlag(HValue::kUint32)) {
__ SmiTagCheckOverflow(output, input, at);
DeoptimizeIf(lt, instr, "overflow", at, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, at, Operand(zero_reg));
} else {
__ SmiTag(output, input);
}
@ -4891,7 +4918,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
// If the input is a HeapObject, value of scratch won't be zero.
__ And(scratch, input, Operand(kHeapObjectTag));
__ SmiUntag(result, input);
DeoptimizeIf(ne, instr, "not a Smi", scratch, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, scratch, Operand(zero_reg));
} else {
__ SmiUntag(result, input);
}
@ -4916,7 +4943,8 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
if (can_convert_undefined_to_nan) {
__ Branch(&convert, ne, scratch, Operand(at));
} else {
DeoptimizeIf(ne, instr, "not a heap number", scratch, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch,
Operand(at));
}
// Load heap number.
__ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
@ -4924,7 +4952,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
__ mfc1(at, result_reg.low());
__ Branch(&done, ne, at, Operand(zero_reg));
__ Mfhc1(scratch, result_reg);
DeoptimizeIf(eq, instr, "minus zero", scratch,
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, scratch,
Operand(HeapNumber::kSignMask));
}
__ Branch(&done);
@ -4932,7 +4960,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
__ bind(&convert);
// Convert undefined (and hole) to NaN.
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
DeoptimizeIf(ne, instr, "not a heap number/undefined", input_reg,
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined, input_reg,
Operand(at));
__ LoadRoot(scratch, Heap::kNanValueRootIndex);
__ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset));
@ -4997,12 +5025,13 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
__ bind(&check_false);
__ LoadRoot(at, Heap::kFalseValueRootIndex);
DeoptimizeIf(ne, instr, "not a heap number/undefined/true/false", scratch2,
Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedBoolean,
scratch2, Operand(at));
__ Branch(USE_DELAY_SLOT, &done);
__ mov(input_reg, zero_reg); // In delay slot.
} else {
DeoptimizeIf(ne, instr, "not a heap number", scratch1, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch1,
Operand(at));
// Load the double value.
__ ldc1(double_scratch,
@ -5017,7 +5046,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
except_flag,
kCheckForInexactConversion);
DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag,
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
Operand(zero_reg));
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -5025,7 +5054,8 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
__ Mfhc1(scratch1, double_scratch);
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr, "minus zero", scratch1, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
Operand(zero_reg));
}
}
__ bind(&done);
@ -5101,7 +5131,7 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
kCheckForInexactConversion);
// Deopt if the operation did not succeed (except_flag != 0).
DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag,
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
Operand(zero_reg));
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -5109,7 +5139,8 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
__ Branch(&done, ne, result_reg, Operand(zero_reg));
__ Mfhc1(scratch1, double_input);
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr, "minus zero", scratch1, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
Operand(zero_reg));
__ bind(&done);
}
}
@ -5135,7 +5166,7 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
kCheckForInexactConversion);
// Deopt if the operation did not succeed (except_flag != 0).
DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag,
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
Operand(zero_reg));
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -5143,19 +5174,20 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
__ Branch(&done, ne, result_reg, Operand(zero_reg));
__ Mfhc1(scratch1, double_input);
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr, "minus zero", scratch1, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
Operand(zero_reg));
__ bind(&done);
}
}
__ SmiTagCheckOverflow(result_reg, result_reg, scratch1);
DeoptimizeIf(lt, instr, "overflow", scratch1, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, scratch1, Operand(zero_reg));
}
void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
LOperand* input = instr->value();
__ SmiTst(ToRegister(input), at);
DeoptimizeIf(ne, instr, "not a Smi", at, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, at, Operand(zero_reg));
}
@ -5163,7 +5195,7 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
if (!instr->hydrogen()->value()->type().IsHeapObject()) {
LOperand* input = instr->value();
__ SmiTst(ToRegister(input), at);
DeoptimizeIf(eq, instr, "Smi", at, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
}
}
@ -5181,12 +5213,15 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
// If there is only one type in the interval check for equality.
if (first == last) {
DeoptimizeIf(ne, instr, "wrong instance type", scratch, Operand(first));
DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType, scratch,
Operand(first));
} else {
DeoptimizeIf(lo, instr, "wrong instance type", scratch, Operand(first));
DeoptimizeIf(lo, instr, Deoptimizer::kWrongInstanceType, scratch,
Operand(first));
// Omit check for the last type.
if (last != LAST_TYPE) {
DeoptimizeIf(hi, instr, "wrong instance type", scratch, Operand(last));
DeoptimizeIf(hi, instr, Deoptimizer::kWrongInstanceType, scratch,
Operand(last));
}
}
} else {
@ -5197,11 +5232,12 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
if (base::bits::IsPowerOfTwo32(mask)) {
DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
__ And(at, scratch, mask);
DeoptimizeIf(tag == 0 ? ne : eq, instr, "wrong instance type", at,
Operand(zero_reg));
DeoptimizeIf(tag == 0 ? ne : eq, instr, Deoptimizer::kWrongInstanceType,
at, Operand(zero_reg));
} else {
__ And(scratch, scratch, Operand(mask));
DeoptimizeIf(ne, instr, "wrong instance type", scratch, Operand(tag));
DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType, scratch,
Operand(tag));
}
}
}
@ -5216,9 +5252,9 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
Handle<Cell> cell = isolate()->factory()->NewCell(object);
__ li(at, Operand(Handle<Object>(cell)));
__ lw(at, FieldMemOperand(at, Cell::kValueOffset));
DeoptimizeIf(ne, instr, "value mismatch", reg, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch, reg, Operand(at));
} else {
DeoptimizeIf(ne, instr, "value mismatch", reg, Operand(object));
DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch, reg, Operand(object));
}
}
@ -5234,7 +5270,8 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
__ StoreToSafepointRegisterSlot(v0, scratch0());
}
__ SmiTst(scratch0(), at);
DeoptimizeIf(eq, instr, "instance migration failed", at, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kInstanceMigrationFailed, at,
Operand(zero_reg));
}
@ -5288,7 +5325,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
if (instr->hydrogen()->HasMigrationTarget()) {
__ Branch(deferred->entry(), ne, map_reg, Operand(map));
} else {
DeoptimizeIf(ne, instr, "wrong map", map_reg, Operand(map));
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, map_reg, Operand(map));
}
__ bind(&success);
@ -5326,7 +5363,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
// Check for undefined. Undefined is converted to zero for clamping
// conversions.
DeoptimizeIf(ne, instr, "not a heap number/undefined", input_reg,
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined, input_reg,
Operand(factory()->undefined_value()));
__ mov(result_reg, zero_reg);
__ jmp(&done);
@ -5749,7 +5786,7 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
type = Deoptimizer::LAZY;
}
DeoptimizeIf(al, instr, type, instr->hydrogen()->reason(), zero_reg,
DeoptimizeIf(al, instr, instr->hydrogen()->reason(), type, zero_reg,
Operand(zero_reg));
}
@ -5840,18 +5877,18 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
Register result = ToRegister(instr->result());
Register object = ToRegister(instr->object());
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
DeoptimizeIf(eq, instr, "undefined", object, Operand(at));
DeoptimizeIf(eq, instr, Deoptimizer::kUndefined, object, Operand(at));
Register null_value = t1;
__ LoadRoot(null_value, Heap::kNullValueRootIndex);
DeoptimizeIf(eq, instr, "null", object, Operand(null_value));
DeoptimizeIf(eq, instr, Deoptimizer::kNull, object, Operand(null_value));
__ And(at, object, kSmiTagMask);
DeoptimizeIf(eq, instr, "Smi", at, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
__ GetObjectType(object, a1, a1);
DeoptimizeIf(le, instr, "not a JavaScript object", a1,
DeoptimizeIf(le, instr, Deoptimizer::kNotAJavaScriptObject, a1,
Operand(LAST_JS_PROXY_TYPE));
Label use_cache, call_runtime;
@ -5869,7 +5906,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
DCHECK(result.is(v0));
__ LoadRoot(at, Heap::kMetaMapRootIndex);
DeoptimizeIf(ne, instr, "wrong map", a1, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, a1, Operand(at));
__ bind(&use_cache);
}
@ -5889,7 +5926,7 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
__ lw(result,
FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
DeoptimizeIf(eq, instr, "no cache", result, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kNoCache, result, Operand(zero_reg));
__ bind(&done);
}
@ -5899,7 +5936,7 @@ void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
Register object = ToRegister(instr->value());
Register map = ToRegister(instr->map());
__ lw(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
DeoptimizeIf(ne, instr, "wrong map", map, Operand(scratch0()));
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, map, Operand(scratch0()));
}

View File

@ -222,12 +222,14 @@ class LCodeGen: public LCodeGenBase {
void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
Safepoint::DeoptMode mode);
void DeoptimizeIf(Condition condition, LInstruction* instr,
Deoptimizer::BailoutType bailout_type, const char* detail,
Deoptimizer::DeoptReason deopt_reason,
Deoptimizer::BailoutType bailout_type,
Register src1 = zero_reg,
const Operand& src2 = Operand(zero_reg));
void DeoptimizeIf(Condition condition, LInstruction* instr,
const char* detail = NULL, Register src1 = zero_reg,
const Operand& src2 = Operand(zero_reg));
void DeoptimizeIf(
Condition condition, LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason = Deoptimizer::kNoReason,
Register src1 = zero_reg, const Operand& src2 = Operand(zero_reg));
void AddToTranslation(LEnvironment* environment,
Translation* translation,

View File

@ -1066,7 +1066,8 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
__ dsubu(dividend, zero_reg, dividend);
__ And(dividend, dividend, Operand(mask));
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr, "minus zero", dividend, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
Operand(zero_reg));
}
__ Branch(USE_DELAY_SLOT, &done);
__ dsubu(dividend, zero_reg, dividend);
@ -1085,7 +1086,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
DCHECK(!dividend.is(result));
if (divisor == 0) {
DeoptimizeIf(al, instr, "division by zero");
DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1098,7 +1099,8 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label remainder_not_zero;
__ Branch(&remainder_not_zero, ne, result, Operand(zero_reg));
DeoptimizeIf(lt, instr, "minus zero", dividend, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, dividend,
Operand(zero_reg));
__ bind(&remainder_not_zero);
}
}
@ -1117,7 +1119,8 @@ void LCodeGen::DoModI(LModI* instr) {
// Check for x % 0, we have to deopt in this case because we can't return a
// NaN.
if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
DeoptimizeIf(eq, instr, "division by zero", right_reg, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, right_reg,
Operand(zero_reg));
}
// Check for kMinInt % -1, div will return kMinInt, which is not what we
@ -1126,7 +1129,7 @@ void LCodeGen::DoModI(LModI* instr) {
Label no_overflow_possible;
__ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt));
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr, "minus zero", right_reg, Operand(-1));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, right_reg, Operand(-1));
} else {
__ Branch(&no_overflow_possible, ne, right_reg, Operand(-1));
__ Branch(USE_DELAY_SLOT, &done);
@ -1139,7 +1142,8 @@ void LCodeGen::DoModI(LModI* instr) {
__ Branch(&done, ge, left_reg, Operand(zero_reg));
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr, "minus zero", result_reg, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result_reg,
Operand(zero_reg));
}
__ bind(&done);
}
@ -1155,18 +1159,19 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
DeoptimizeIf(eq, instr, "minus zero", dividend, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
Operand(zero_reg));
}
// Check for (kMinInt / -1).
if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
DeoptimizeIf(eq, instr, "overflow", dividend, Operand(kMinInt));
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow, dividend, Operand(kMinInt));
}
// 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);
__ And(at, dividend, Operand(mask));
DeoptimizeIf(ne, instr, "lost precision", at, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, at, Operand(zero_reg));
}
if (divisor == -1) { // Nice shortcut, not needed for correctness.
@ -1196,14 +1201,15 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
DCHECK(!dividend.is(result));
if (divisor == 0) {
DeoptimizeIf(al, instr, "division by zero");
DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
return;
}
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
DeoptimizeIf(eq, instr, "minus zero", dividend, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
Operand(zero_reg));
}
__ TruncatingDiv(result, dividend, Abs(divisor));
@ -1212,7 +1218,8 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
__ Dmul(scratch0(), result, Operand(divisor));
__ Dsubu(scratch0(), scratch0(), dividend);
DeoptimizeIf(ne, instr, "lost precision", scratch0(), Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, scratch0(),
Operand(zero_reg));
}
}
@ -1230,14 +1237,16 @@ void LCodeGen::DoDivI(LDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
DeoptimizeIf(eq, instr, "division by zero", divisor, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, divisor,
Operand(zero_reg));
}
// Check for (0 / -x) that will produce negative zero.
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label left_not_zero;
__ Branch(&left_not_zero, ne, dividend, Operand(zero_reg));
DeoptimizeIf(lt, instr, "minus zero", divisor, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, divisor,
Operand(zero_reg));
__ bind(&left_not_zero);
}
@ -1246,7 +1255,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
Label left_not_min_int;
__ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt));
DeoptimizeIf(eq, instr, "overflow", divisor, Operand(-1));
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow, divisor, Operand(-1));
__ bind(&left_not_min_int);
}
@ -1258,7 +1267,8 @@ void LCodeGen::DoDivI(LDivI* instr) {
} else {
__ dmod(remainder, dividend, divisor);
}
DeoptimizeIf(ne, instr, "lost precision", remainder, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, remainder,
Operand(zero_reg));
}
}
@ -1303,14 +1313,14 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
__ Dsubu(result, zero_reg, dividend);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr, "minus zero", result, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result, Operand(zero_reg));
}
__ Xor(scratch, scratch, result);
// Dividing by -1 is basically negation, unless we overflow.
if (divisor == -1) {
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
DeoptimizeIf(gt, instr, "overflow", result, Operand(kMaxInt));
DeoptimizeIf(gt, instr, Deoptimizer::kOverflow, result, Operand(kMaxInt));
}
return;
}
@ -1338,14 +1348,15 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
DCHECK(!dividend.is(result));
if (divisor == 0) {
DeoptimizeIf(al, instr, "division by zero");
DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
return;
}
// Check for (0 / -x) that will produce negative zero.
HMathFloorOfDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
DeoptimizeIf(eq, instr, "minus zero", dividend, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
Operand(zero_reg));
}
// Easy case: We need no dynamic check for the dividend and the flooring
@ -1389,14 +1400,16 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
DeoptimizeIf(eq, instr, "division by zero", divisor, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, divisor,
Operand(zero_reg));
}
// Check for (0 / -x) that will produce negative zero.
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label left_not_zero;
__ Branch(&left_not_zero, ne, dividend, Operand(zero_reg));
DeoptimizeIf(lt, instr, "minus zero", divisor, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, divisor,
Operand(zero_reg));
__ bind(&left_not_zero);
}
@ -1405,7 +1418,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
Label left_not_min_int;
__ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt));
DeoptimizeIf(eq, instr, "overflow", divisor, Operand(-1));
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow, divisor, Operand(-1));
__ bind(&left_not_min_int);
}
@ -1442,14 +1455,15 @@ void LCodeGen::DoMulI(LMulI* instr) {
if (bailout_on_minus_zero && (constant < 0)) {
// The case of a null constant will be handled separately.
// If constant is negative and left is null, the result should be -0.
DeoptimizeIf(eq, instr, "minus zero", left, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, left, Operand(zero_reg));
}
switch (constant) {
case -1:
if (overflow) {
__ SubuAndCheckForOverflow(result, zero_reg, left, scratch);
DeoptimizeIf(gt, instr, "overflow", scratch, Operand(kMaxInt));
DeoptimizeIf(gt, instr, Deoptimizer::kOverflow, scratch,
Operand(kMaxInt));
} else {
__ Dsubu(result, zero_reg, left);
}
@ -1458,7 +1472,8 @@ void LCodeGen::DoMulI(LMulI* instr) {
if (bailout_on_minus_zero) {
// If left is strictly negative and the constant is null, the
// result is -0. Deoptimize if required, otherwise return 0.
DeoptimizeIf(lt, instr, "minus zero", left, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, left,
Operand(zero_reg));
}
__ mov(result, zero_reg);
break;
@ -1513,7 +1528,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
if (instr->hydrogen()->representation().IsSmi()) {
__ SmiTag(result);
}
DeoptimizeIf(ne, instr, "overflow", scratch, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, scratch, Operand(at));
} else {
if (instr->hydrogen()->representation().IsSmi()) {
__ SmiUntag(result, left);
@ -1528,7 +1543,8 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ Xor(at, left, right);
__ Branch(&done, ge, at, Operand(zero_reg));
// Bail out if the result is minus zero.
DeoptimizeIf(eq, instr, "minus zero", result, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result,
Operand(zero_reg));
__ bind(&done);
}
}
@ -1592,8 +1608,10 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
__ srlv(result, left, ToRegister(right_op));
if (instr->can_deopt()) {
// TODO(yy): (-1) >>> 0. anything else?
DeoptimizeIf(lt, instr, "negative value", result, Operand(zero_reg));
DeoptimizeIf(gt, instr, "negative value", result, Operand(kMaxInt));
DeoptimizeIf(lt, instr, Deoptimizer::kNegativeValue, result,
Operand(zero_reg));
DeoptimizeIf(gt, instr, Deoptimizer::kNegativeValue, result,
Operand(kMaxInt));
}
break;
case Token::SHL:
@ -1628,7 +1646,8 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
} else {
if (instr->can_deopt()) {
__ And(at, left, Operand(0x80000000));
DeoptimizeIf(ne, instr, "negative value", at, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kNegativeValue, at,
Operand(zero_reg));
}
__ Move(result, left);
}
@ -1684,10 +1703,13 @@ void LCodeGen::DoSubI(LSubI* instr) {
ToRegister(right),
overflow); // Reg at also used as scratch.
}
DeoptimizeIf(lt, instr, "overflow", overflow, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, overflow,
Operand(zero_reg));
if (!instr->hydrogen()->representation().IsSmi()) {
DeoptimizeIf(gt, instr, "overflow", ToRegister(result), Operand(kMaxInt));
DeoptimizeIf(lt, instr, "overflow", ToRegister(result), Operand(kMinInt));
DeoptimizeIf(gt, instr, Deoptimizer::kOverflow, ToRegister(result),
Operand(kMaxInt));
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, ToRegister(result),
Operand(kMinInt));
}
}
}
@ -1742,9 +1764,10 @@ void LCodeGen::DoDateField(LDateField* instr) {
DCHECK(!scratch.is(object));
__ SmiTst(object, at);
DeoptimizeIf(eq, instr, "Smi", at, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
__ GetObjectType(object, scratch, scratch);
DeoptimizeIf(ne, instr, "not a date object", scratch, Operand(JS_DATE_TYPE));
DeoptimizeIf(ne, instr, Deoptimizer::kNotADateObject, scratch,
Operand(JS_DATE_TYPE));
if (index->value() == 0) {
__ ld(result, FieldMemOperand(object, JSDate::kValueOffset));
@ -1879,11 +1902,14 @@ void LCodeGen::DoAddI(LAddI* instr) {
ToRegister(right),
overflow); // Reg at also used as scratch.
}
DeoptimizeIf(lt, instr, "overflow", overflow, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, overflow,
Operand(zero_reg));
// if not smi, it must int32.
if (!instr->hydrogen()->representation().IsSmi()) {
DeoptimizeIf(gt, instr, "overflow", ToRegister(result), Operand(kMaxInt));
DeoptimizeIf(lt, instr, "overflow", ToRegister(result), Operand(kMinInt));
DeoptimizeIf(gt, instr, Deoptimizer::kOverflow, ToRegister(result),
Operand(kMaxInt));
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, ToRegister(result),
Operand(kMinInt));
}
}
}
@ -2145,7 +2171,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
} else if (expected.NeedsMap()) {
// If we need a map later and have a Smi -> deopt.
__ SmiTst(reg, at);
DeoptimizeIf(eq, instr, "Smi", at, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
}
const Register map = scratch0();
@ -2201,7 +2227,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, "unexpected object", zero_reg,
DeoptimizeIf(al, instr, Deoptimizer::kUnexpectedObject, zero_reg,
Operand(zero_reg));
}
}
@ -2851,7 +2877,7 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
__ ld(result, FieldMemOperand(at, Cell::kValueOffset));
if (instr->hydrogen()->RequiresHoleCheck()) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr, "hole", result, Operand(at));
DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(at));
}
}
@ -2906,7 +2932,7 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
Register payload = ToRegister(instr->temp());
__ ld(payload, FieldMemOperand(cell, Cell::kValueOffset));
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr, "hole", payload, Operand(at));
DeoptimizeIf(eq, instr, Deoptimizer::kHole, payload, Operand(at));
}
// Store the value.
@ -2924,7 +2950,7 @@ void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(eq, instr, "hole", result, Operand(at));
DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(at));
} else {
Label is_not_hole;
__ Branch(&is_not_hole, ne, result, Operand(at));
@ -2948,7 +2974,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(eq, instr, "hole", scratch, Operand(at));
DeoptimizeIf(eq, instr, Deoptimizer::kHole, scratch, Operand(at));
} else {
__ Branch(&skip_assignment, ne, scratch, Operand(at));
}
@ -3043,7 +3069,7 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
// Check that the function has a prototype or an initial map.
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr, "hole", result, Operand(at));
DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(at));
// If the function does not have an initial map, we're done.
Label done;
@ -3189,8 +3215,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
case UINT32_ELEMENTS:
__ lw(result, mem_operand);
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
DeoptimizeIf(Ugreater_equal, instr, "negative value", result,
Operand(0x80000000));
DeoptimizeIf(Ugreater_equal, instr, Deoptimizer::kNegativeValue,
result, Operand(0x80000000));
}
break;
case FLOAT32_ELEMENTS:
@ -3250,7 +3276,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
__ lwu(scratch, MemOperand(scratch, sizeof(kHoleNanLower32)));
DeoptimizeIf(eq, instr, "hole", scratch, Operand(kHoleNanUpper32));
DeoptimizeIf(eq, instr, Deopt::kHole, scratch, Operand(kHoleNanUpper32));
}
}
@ -3304,10 +3330,11 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
if (hinstr->RequiresHoleCheck()) {
if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
__ SmiTst(result, scratch);
DeoptimizeIf(ne, instr, "not a Smi", scratch, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, scratch,
Operand(zero_reg));
} else {
__ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr, "hole", result, Operand(scratch));
DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(scratch));
}
}
}
@ -3463,10 +3490,10 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
// Deoptimize if the receiver is not a JS object.
__ SmiTst(receiver, scratch);
DeoptimizeIf(eq, instr, "Smi", scratch, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, scratch, Operand(zero_reg));
__ GetObjectType(receiver, scratch, scratch);
DeoptimizeIf(lt, instr, "not a JavaScript object", scratch,
DeoptimizeIf(lt, instr, Deoptimizer::kNotAJavaScriptObject, scratch,
Operand(FIRST_SPEC_OBJECT_TYPE));
__ Branch(&result_in_receiver);
@ -3502,7 +3529,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// Copy the arguments to this function possibly from the
// adaptor frame below it.
const uint32_t kArgumentsLimit = 1 * KB;
DeoptimizeIf(hi, instr, "too many arguments", length,
DeoptimizeIf(hi, instr, Deoptimizer::kTooManyArguments, length,
Operand(kArgumentsLimit));
// Push the receiver and use the register to keep the original
@ -3628,7 +3655,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
// Deoptimize if not a heap number.
__ ld(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
DeoptimizeIf(ne, instr, "not a heap number", scratch, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch, Operand(at));
Label done;
Register exponent = scratch0();
@ -3695,7 +3722,7 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
__ mov(result, input);
__ dsubu(result, zero_reg, input);
// Overflow if result is still negative, i.e. 0x80000000.
DeoptimizeIf(lt, instr, "overflow", result, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, result, Operand(zero_reg));
__ bind(&done);
}
@ -3750,7 +3777,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
except_flag);
// Deopt if the operation did not succeed.
DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag,
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
Operand(zero_reg));
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -3759,7 +3786,8 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ Branch(&done, ne, result, Operand(zero_reg));
__ mfhc1(scratch1, input); // Get exponent/sign bits.
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr, "minus zero", scratch1, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
Operand(zero_reg));
__ bind(&done);
}
}
@ -3792,7 +3820,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
// The following conversion will not work with numbers
// outside of ]-2^32, 2^32[.
DeoptimizeIf(ge, instr, "overflow", scratch,
DeoptimizeIf(ge, instr, Deoptimizer::kOverflow, scratch,
Operand(HeapNumber::kExponentBias + 32));
// Save the original sign for later comparison.
@ -3810,7 +3838,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
__ Xor(result, result, Operand(scratch));
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
// ARM uses 'mi' here, which is 'lt'
DeoptimizeIf(lt, instr, "minus zero", result, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, result, Operand(zero_reg));
} else {
Label skip2;
// ARM uses 'mi' here, which is 'lt'
@ -3829,7 +3857,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
double_scratch1,
except_flag);
DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag,
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
Operand(zero_reg));
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -3838,7 +3866,8 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
__ bind(&check_sign_on_zero);
__ mfhc1(scratch, input); // Get exponent/sign bits.
__ And(scratch, scratch, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr, "minus zero", scratch, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch,
Operand(zero_reg));
}
__ bind(&done);
}
@ -3904,7 +3933,7 @@ void LCodeGen::DoPower(LPower* instr) {
DCHECK(!a7.is(tagged_exponent));
__ lw(a7, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
DeoptimizeIf(ne, instr, "not a heap number", a7, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, a7, Operand(at));
__ bind(&no_deopt);
MathPowStub stub(isolate(), MathPowStub::TAGGED);
__ CallStub(&stub);
@ -4305,7 +4334,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
__ stop("eliminated bounds check failed");
__ bind(&done);
} else {
DeoptimizeIf(cc, instr, "out of bounds", reg, operand);
DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds, reg, operand);
}
}
@ -4596,7 +4625,7 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
Label no_memento_found;
__ TestJSArrayForAllocationMemento(object, temp, &no_memento_found,
ne, &no_memento_found);
DeoptimizeIf(al, instr, "memento found");
DeoptimizeIf(al, instr, Deoptimizer::kMementoFound);
__ bind(&no_memento_found);
}
@ -4899,12 +4928,12 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) {
if (hchange->CheckFlag(HValue::kCanOverflow) &&
hchange->value()->CheckFlag(HValue::kUint32)) {
__ And(at, input, Operand(0x80000000));
DeoptimizeIf(ne, instr, "overflow", at, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, at, Operand(zero_reg));
}
if (hchange->CheckFlag(HValue::kCanOverflow) &&
!hchange->value()->CheckFlag(HValue::kUint32)) {
__ SmiTagCheckOverflow(output, input, at);
DeoptimizeIf(lt, instr, "overflow", at, Operand(zero_reg));
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, at, Operand(zero_reg));
} else {
__ SmiTag(output, input);
}
@ -4920,7 +4949,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
// If the input is a HeapObject, value of scratch won't be zero.
__ And(scratch, input, Operand(kHeapObjectTag));
__ SmiUntag(result, input);
DeoptimizeIf(ne, instr, "not a Smi", scratch, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, scratch, Operand(zero_reg));
} else {
__ SmiUntag(result, input);
}
@ -4945,7 +4974,8 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
if (can_convert_undefined_to_nan) {
__ Branch(&convert, ne, scratch, Operand(at));
} else {
DeoptimizeIf(ne, instr, "not a heap number", scratch, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch,
Operand(at));
}
// Load heap number.
__ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
@ -4953,7 +4983,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
__ mfc1(at, result_reg);
__ Branch(&done, ne, at, Operand(zero_reg));
__ mfhc1(scratch, result_reg); // Get exponent/sign bits.
DeoptimizeIf(eq, instr, "minus zero", scratch,
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, scratch,
Operand(HeapNumber::kSignMask));
}
__ Branch(&done);
@ -4961,7 +4991,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
__ bind(&convert);
// Convert undefined (and hole) to NaN.
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
DeoptimizeIf(ne, instr, "not a heap number/undefined", input_reg,
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined, input_reg,
Operand(at));
__ LoadRoot(scratch, Heap::kNanValueRootIndex);
__ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset));
@ -5026,12 +5056,13 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
__ bind(&check_false);
__ LoadRoot(at, Heap::kFalseValueRootIndex);
DeoptimizeIf(ne, instr, "not a heap number/undefined/true/false", scratch2,
Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedTrueFalse,
scratch2, Operand(at));
__ Branch(USE_DELAY_SLOT, &done);
__ mov(input_reg, zero_reg); // In delay slot.
} else {
DeoptimizeIf(ne, instr, "not a heap number", scratch1, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch1,
Operand(at));
// Load the double value.
__ ldc1(double_scratch,
@ -5046,7 +5077,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
except_flag,
kCheckForInexactConversion);
DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag,
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
Operand(zero_reg));
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -5054,7 +5085,8 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
__ mfhc1(scratch1, double_scratch); // Get exponent/sign bits.
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr, "minus zero", scratch1, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
Operand(zero_reg));
}
}
__ bind(&done);
@ -5130,7 +5162,7 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
kCheckForInexactConversion);
// Deopt if the operation did not succeed (except_flag != 0).
DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag,
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
Operand(zero_reg));
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -5138,7 +5170,8 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
__ Branch(&done, ne, result_reg, Operand(zero_reg));
__ mfhc1(scratch1, double_input); // Get exponent/sign bits.
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr, "minus zero", scratch1, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
Operand(zero_reg));
__ bind(&done);
}
}
@ -5164,7 +5197,7 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
kCheckForInexactConversion);
// Deopt if the operation did not succeed (except_flag != 0).
DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag,
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
Operand(zero_reg));
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -5172,7 +5205,8 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
__ Branch(&done, ne, result_reg, Operand(zero_reg));
__ mfhc1(scratch1, double_input); // Get exponent/sign bits.
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr, "minus zero", scratch1, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
Operand(zero_reg));
__ bind(&done);
}
}
@ -5183,7 +5217,7 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
LOperand* input = instr->value();
__ SmiTst(ToRegister(input), at);
DeoptimizeIf(ne, instr, "not a Smi", at, Operand(zero_reg));
DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, at, Operand(zero_reg));
}
@ -5191,7 +5225,7 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
if (!instr->hydrogen()->value()->type().IsHeapObject()) {
LOperand* input = instr->value();
__ SmiTst(ToRegister(input), at);
DeoptimizeIf(eq, instr, "Smi", at, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
}
}
@ -5209,12 +5243,15 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
// If there is only one type in the interval check for equality.
if (first == last) {
DeoptimizeIf(ne, instr, "wrong instance type", scratch, Operand(first));
DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType, scratch,
Operand(first));
} else {
DeoptimizeIf(lo, instr, "wrong instance type", scratch, Operand(first));
DeoptimizeIf(lo, instr, Deoptimizer::kWrongInstanceType, scratch,
Operand(first));
// Omit check for the last type.
if (last != LAST_TYPE) {
DeoptimizeIf(hi, instr, "wrong instance type", scratch, Operand(last));
DeoptimizeIf(hi, instr, Deoptimizer::kWrongInstanceType, scratch,
Operand(last));
}
}
} else {
@ -5225,11 +5262,12 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
if (base::bits::IsPowerOfTwo32(mask)) {
DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
__ And(at, scratch, mask);
DeoptimizeIf(tag == 0 ? ne : eq, instr, "wrong instance type", at,
Operand(zero_reg));
DeoptimizeIf(tag == 0 ? ne : eq, instr, Deoptimizer::kWrongInstanceType,
at, Operand(zero_reg));
} else {
__ And(scratch, scratch, Operand(mask));
DeoptimizeIf(ne, instr, "wrong instance type", scratch, Operand(tag));
DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType, scratch,
Operand(tag));
}
}
}
@ -5244,9 +5282,9 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
Handle<Cell> cell = isolate()->factory()->NewCell(object);
__ li(at, Operand(Handle<Object>(cell)));
__ ld(at, FieldMemOperand(at, Cell::kValueOffset));
DeoptimizeIf(ne, instr, "value mismatch", reg, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch, reg, Operand(at));
} else {
DeoptimizeIf(ne, instr, "value mismatch", reg, Operand(object));
DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch, reg, Operand(object));
}
}
@ -5262,7 +5300,8 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
__ StoreToSafepointRegisterSlot(v0, scratch0());
}
__ SmiTst(scratch0(), at);
DeoptimizeIf(eq, instr, "instance migration failed", at, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kInstanceMigrationFailed, at,
Operand(zero_reg));
}
@ -5316,7 +5355,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
if (instr->hydrogen()->HasMigrationTarget()) {
__ Branch(deferred->entry(), ne, map_reg, Operand(map));
} else {
DeoptimizeIf(ne, instr, "wrong map", map_reg, Operand(map));
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, map_reg, Operand(map));
}
__ bind(&success);
@ -5354,7 +5393,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
// Check for undefined. Undefined is converted to zero for clamping
// conversions.
DeoptimizeIf(ne, instr, "not a heap number/undefined", input_reg,
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined, input_reg,
Operand(factory()->undefined_value()));
__ mov(result_reg, zero_reg);
__ jmp(&done);
@ -5870,18 +5909,18 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
Register result = ToRegister(instr->result());
Register object = ToRegister(instr->object());
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
DeoptimizeIf(eq, instr, "undefined", object, Operand(at));
DeoptimizeIf(eq, instr, Deoptimizer::kUndefined, object, Operand(at));
Register null_value = a5;
__ LoadRoot(null_value, Heap::kNullValueRootIndex);
DeoptimizeIf(eq, instr, "null", object, Operand(null_value));
DeoptimizeIf(eq, instr, Deoptimizer::kNull, object, Operand(null_value));
__ And(at, object, kSmiTagMask);
DeoptimizeIf(eq, instr, "Smi", at, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
__ GetObjectType(object, a1, a1);
DeoptimizeIf(le, instr, "not a JavaScript object", a1,
DeoptimizeIf(le, instr, Deoptimizer::kNotAJavaScriptObject, a1,
Operand(LAST_JS_PROXY_TYPE));
Label use_cache, call_runtime;
@ -5899,7 +5938,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ ld(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
DCHECK(result.is(v0));
__ LoadRoot(at, Heap::kMetaMapRootIndex);
DeoptimizeIf(ne, instr, "wrong map", a1, Operand(at));
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, a1, Operand(at));
__ bind(&use_cache);
}
@ -5919,7 +5958,7 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
__ ld(result,
FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
DeoptimizeIf(eq, instr, "no cache", result, Operand(zero_reg));
DeoptimizeIf(eq, instr, Deoptimizer::kNoCache, result, Operand(zero_reg));
__ bind(&done);
}
@ -5929,7 +5968,7 @@ void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
Register object = ToRegister(instr->value());
Register map = ToRegister(instr->map());
__ ld(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
DeoptimizeIf(ne, instr, "wrong map", map, Operand(scratch0()));
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, map, Operand(scratch0()));
}

View File

@ -11007,14 +11007,18 @@ Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
void Code::PrintDeoptLocation(FILE* out, int bailout_id) {
const char* last_comment = NULL;
int mask = RelocInfo::ModeMask(RelocInfo::COMMENT)
| RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
int last_position = 0;
Deoptimizer::DeoptReason last_reason = Deoptimizer::kNoReason;
int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) |
RelocInfo::ModeMask(RelocInfo::POSITION) |
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
for (RelocIterator it(this, mask); !it.done(); it.next()) {
RelocInfo* info = it.rinfo();
if (info->rmode() == RelocInfo::COMMENT) {
last_comment = reinterpret_cast<const char*>(info->data());
} else if (last_comment != NULL) {
if (info->rmode() == RelocInfo::POSITION) {
last_position = static_cast<int>(info->data());
} else if (info->rmode() == RelocInfo::DEOPT_REASON) {
last_reason = static_cast<Deoptimizer::DeoptReason>(info->data());
} else if (last_reason != Deoptimizer::kNoReason) {
if ((bailout_id == Deoptimizer::GetDeoptimizationId(
GetIsolate(), info->target_address(), Deoptimizer::EAGER)) ||
(bailout_id == Deoptimizer::GetDeoptimizationId(
@ -11022,7 +11026,8 @@ void Code::PrintDeoptLocation(FILE* out, int bailout_id) {
(bailout_id == Deoptimizer::GetDeoptimizationId(
GetIsolate(), info->target_address(), Deoptimizer::LAZY))) {
CHECK(RelocInfo::IsRuntimeEntry(info->rmode()));
PrintF(out, " %s\n", last_comment);
PrintF(out, " ;;; deoptimize at %d: %s\n", last_position,
Deoptimizer::GetDeoptReason(last_reason));
return;
}
}

View File

@ -1065,12 +1065,12 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
__ ExtractBitRange(dividend, dividend, shift - 1, 0);
__ neg(dividend, dividend, LeaveOE, SetRC);
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr, "minus zero", cr0);
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, cr0);
}
} else if (!hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ li(dividend, Operand::Zero());
} else {
DeoptimizeIf(al, instr, "minus zero");
DeoptimizeIf(al, instr, Deoptimizer::kMinusZero);
}
__ b(&done);
}
@ -1092,7 +1092,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
DCHECK(!dividend.is(result));
if (divisor == 0) {
DeoptimizeIf(al, instr, "division by zero");
DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1107,7 +1107,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
Label remainder_not_zero;
__ bne(&remainder_not_zero, cr0);
__ cmpwi(dividend, Operand::Zero());
DeoptimizeIf(lt, instr, "minus zero");
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
__ bind(&remainder_not_zero);
}
}
@ -1131,7 +1131,7 @@ void LCodeGen::DoModI(LModI* instr) {
// Check for x % 0.
if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
__ cmpwi(right_reg, Operand::Zero());
DeoptimizeIf(eq, instr, "division by zero");
DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero);
}
// Check for kMinInt % -1, divw will return undefined, which is not what we
@ -1139,7 +1139,7 @@ void LCodeGen::DoModI(LModI* instr) {
if (hmod->CheckFlag(HValue::kCanOverflow)) {
Label no_overflow_possible;
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(overflow, instr, "minus zero", cr0);
DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero, cr0);
} else {
__ bnooverflow(&no_overflow_possible, cr0);
__ li(result_reg, Operand::Zero());
@ -1155,7 +1155,7 @@ void LCodeGen::DoModI(LModI* instr) {
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ bne(&done, cr0);
__ cmpwi(left_reg, Operand::Zero());
DeoptimizeIf(lt, instr, "minus zero");
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
}
__ bind(&done);
@ -1173,13 +1173,13 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ cmpwi(dividend, Operand::Zero());
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
// Check for (kMinInt / -1).
if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
__ lis(r0, Operand(SIGN_EXT_IMM16(0x8000)));
__ cmpw(dividend, r0);
DeoptimizeIf(eq, instr, "overflow");
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow);
}
int32_t shift = WhichPowerOf2Abs(divisor);
@ -1187,7 +1187,7 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
// Deoptimize if remainder will not be 0.
if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && shift) {
__ TestBitRange(dividend, shift - 1, 0, r0);
DeoptimizeIf(ne, instr, "lost precision", cr0);
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, cr0);
}
if (divisor == -1) { // Nice shortcut, not needed for correctness.
@ -1217,7 +1217,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
DCHECK(!dividend.is(result));
if (divisor == 0) {
DeoptimizeIf(al, instr, "division by zero");
DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1225,7 +1225,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ cmpwi(dividend, Operand::Zero());
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
__ TruncatingDiv(result, dividend, Abs(divisor));
@ -1236,7 +1236,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
__ mov(ip, Operand(divisor));
__ mullw(scratch, result, ip);
__ cmpw(scratch, dividend);
DeoptimizeIf(ne, instr, "lost precision");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision);
}
}
@ -1261,7 +1261,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ cmpwi(divisor, Operand::Zero());
DeoptimizeIf(eq, instr, "division by zero");
DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero);
}
// Check for (0 / -x) that will produce negative zero.
@ -1270,7 +1270,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
__ cmpwi(dividend, Operand::Zero());
__ bne(&dividend_not_zero);
__ cmpwi(divisor, Operand::Zero());
DeoptimizeIf(lt, instr, "minus zero");
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
__ bind(&dividend_not_zero);
}
@ -1278,7 +1278,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
if (hdiv->CheckFlag(HValue::kCanOverflow)) {
Label no_overflow_possible;
if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
DeoptimizeIf(overflow, instr, "overflow", cr0);
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0);
} else {
// When truncating, we want kMinInt / -1 = kMinInt.
__ bnooverflow(&no_overflow_possible, cr0);
@ -1292,7 +1292,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
Register scratch = scratch0();
__ mullw(scratch, divisor, result);
__ cmpw(dividend, scratch);
DeoptimizeIf(ne, instr, "lost precision");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision);
}
}
@ -1319,7 +1319,7 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
if (divisor == -1 && hdiv->CheckFlag(HValue::kLeftCanBeMinInt)) {
__ lis(r0, Operand(SIGN_EXT_IMM16(0x8000)));
__ cmpw(dividend, r0);
DeoptimizeIf(eq, instr, "overflow");
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow);
}
#else
if (hdiv->CheckFlag(HValue::kLeftCanBeMinInt)) {
@ -1331,7 +1331,7 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
__ neg(result, dividend, oe, SetRC);
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr, "minus zero", cr0);
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, cr0);
}
// If the negation could not overflow, simply shifting is OK.
@ -1347,7 +1347,7 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
// Dividing by -1 is basically negation, unless we overflow.
if (divisor == -1) {
DeoptimizeIf(overflow, instr, "overflow", cr0);
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0);
return;
}
@ -1369,7 +1369,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
DCHECK(!dividend.is(result));
if (divisor == 0) {
DeoptimizeIf(al, instr, "division by zero");
DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1377,7 +1377,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
HMathFloorOfDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ cmpwi(dividend, Operand::Zero());
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
// Easy case: We need no dynamic check for the dividend and the flooring
@ -1428,7 +1428,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ cmpwi(divisor, Operand::Zero());
DeoptimizeIf(eq, instr, "division by zero");
DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero);
}
// Check for (0 / -x) that will produce negative zero.
@ -1437,7 +1437,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
__ cmpwi(dividend, Operand::Zero());
__ bne(&dividend_not_zero);
__ cmpwi(divisor, Operand::Zero());
DeoptimizeIf(lt, instr, "minus zero");
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
__ bind(&dividend_not_zero);
}
@ -1445,7 +1445,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
if (hdiv->CheckFlag(HValue::kCanOverflow)) {
Label no_overflow_possible;
if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
DeoptimizeIf(overflow, instr, "overflow", cr0);
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0);
} else {
// When truncating, we want kMinInt / -1 = kMinInt.
__ bnooverflow(&no_overflow_possible, cr0);
@ -1515,7 +1515,7 @@ 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.
__ cmpi(left, Operand::Zero());
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
switch (constant) {
@ -1527,12 +1527,12 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ li(r0, Operand::Zero()); // clear xer
__ mtxer(r0);
__ neg(result, left, SetOE, SetRC);
DeoptimizeIf(overflow, instr, "overflow", cr0);
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0);
#if V8_TARGET_ARCH_PPC64
} else {
__ neg(result, left);
__ TestIfInt32(result, scratch, r0);
DeoptimizeIf(ne, instr, "overflow");
DeoptimizeIf(ne, instr, Deoptimizer::kOverflow);
}
#endif
} else {
@ -1552,7 +1552,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ cmpwi(left, Operand::Zero());
}
#endif
DeoptimizeIf(lt, instr, "minus zero");
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
}
__ li(result, Operand::Zero());
break;
@ -1605,7 +1605,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ Mul(result, left, right);
}
__ TestIfInt32(result, scratch, r0);
DeoptimizeIf(ne, instr, "overflow");
DeoptimizeIf(ne, instr, Deoptimizer::kOverflow);
if (instr->hydrogen()->representation().IsSmi()) {
__ SmiTag(result);
}
@ -1620,7 +1620,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ mullw(result, left, right);
}
__ TestIfInt32(scratch, result, r0);
DeoptimizeIf(ne, instr, "overflow");
DeoptimizeIf(ne, instr, Deoptimizer::kOverflow);
#endif
} else {
if (instr->hydrogen()->representation().IsSmi()) {
@ -1647,7 +1647,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
#endif
// Bail out if the result is minus zero.
__ cmpi(result, Operand::Zero());
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
__ bind(&done);
}
}
@ -1733,7 +1733,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
#if V8_TARGET_ARCH_PPC64
__ extsw(result, result, SetRC);
#endif
DeoptimizeIf(lt, instr, "negative value", cr0);
DeoptimizeIf(lt, instr, Deoptimizer::kNegativeValue, cr0);
} else {
__ srw(result, left, scratch);
}
@ -1773,7 +1773,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
} else {
if (instr->can_deopt()) {
__ cmpwi(left, Operand::Zero());
DeoptimizeIf(lt, instr, "negative value");
DeoptimizeIf(lt, instr, Deoptimizer::kNegativeValue);
}
__ Move(result, left);
}
@ -1792,7 +1792,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
} else {
__ SmiTagCheckOverflow(result, left, scratch);
}
DeoptimizeIf(lt, instr, "overflow", cr0);
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0);
#endif
} else {
__ slwi(result, left, Operand(shift_count));
@ -1837,7 +1837,7 @@ void LCodeGen::DoSubI(LSubI* instr) {
__ extsw(scratch0(), scratch0(), SetRC);
}
#endif
DeoptimizeIf(lt, instr, "overflow", cr0);
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0);
}
#if V8_TARGET_ARCH_PPC64
@ -1917,9 +1917,9 @@ void LCodeGen::DoDateField(LDateField* instr) {
DCHECK(!scratch.is(object));
__ TestIfSmi(object, r0);
DeoptimizeIf(eq, instr, "Smi", cr0);
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
__ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE);
DeoptimizeIf(ne, instr, "not a date object");
DeoptimizeIf(ne, instr, Deoptimizer::kNotADateObject);
if (index->value() == 0) {
__ LoadP(result, FieldMemOperand(object, JSDate::kValueOffset));
@ -2053,7 +2053,7 @@ void LCodeGen::DoAddI(LAddI* instr) {
__ extsw(scratch0(), scratch0(), SetRC);
}
#endif
DeoptimizeIf(lt, instr, "overflow", cr0);
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0);
}
#if V8_TARGET_ARCH_PPC64
@ -2295,7 +2295,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
} else if (expected.NeedsMap()) {
// If we need a map later and have a Smi -> deopt.
__ TestIfSmi(reg, r0);
DeoptimizeIf(eq, instr, "Smi", cr0);
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
}
const Register map = scratch0();
@ -2352,7 +2352,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, "unexpected object");
DeoptimizeIf(al, instr, Deoptimizer::kUnexpectedObject);
}
}
}
@ -3011,7 +3011,7 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(result, ip);
DeoptimizeIf(eq, instr, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
}
}
@ -3061,7 +3061,7 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
Register payload = ToRegister(instr->temp());
__ LoadP(payload, FieldMemOperand(cell, Cell::kValueOffset));
__ CompareRoot(payload, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
}
// Store the value.
@ -3078,7 +3078,7 @@ void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(result, ip);
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(eq, instr, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
} else {
Label skip;
__ bne(&skip);
@ -3102,7 +3102,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(scratch, ip);
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(eq, instr, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
} else {
__ bne(&skip_assignment);
}
@ -3194,7 +3194,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, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
// If the function does not have an initial map, we're done.
Label done;
@ -3354,7 +3354,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
__ lis(r0, Operand(SIGN_EXT_IMM16(0x8000)));
__ cmplw(result, r0);
DeoptimizeIf(ge, instr, "negative value");
DeoptimizeIf(ge, instr, Deoptimizer::kNegativeValue);
}
break;
case FLOAT32_ELEMENTS:
@ -3417,7 +3417,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
__ lwz(scratch, MemOperand(scratch, Register::kExponentOffset));
}
__ Cmpi(scratch, Operand(kHoleNanUpper32), r0);
DeoptimizeIf(eq, instr, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
}
}
@ -3472,11 +3472,11 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
if (requires_hole_check) {
if (IsFastSmiElementsKind(hinstr->elements_kind())) {
__ TestIfSmi(result, r0);
DeoptimizeIf(ne, instr, "not a Smi", cr0);
DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0);
} else {
__ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
__ cmp(result, scratch);
DeoptimizeIf(eq, instr, "hole");
DeoptimizeIf(eq, instr, Deoptimizer::kHole);
}
}
}
@ -3635,9 +3635,9 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
// Deoptimize if the receiver is not a JS object.
__ TestIfSmi(receiver, r0);
DeoptimizeIf(eq, instr, "Smi");
DeoptimizeIf(eq, instr, Deoptimizer::kSmi);
__ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
DeoptimizeIf(lt, instr, "not a JavaScript object");
DeoptimizeIf(lt, instr, Deoptimizer::kNotAJavaScriptObject);
__ b(&result_in_receiver);
__ bind(&global_object);
@ -3670,7 +3670,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// adaptor frame below it.
const uint32_t kArgumentsLimit = 1 * KB;
__ cmpli(length, Operand(kArgumentsLimit));
DeoptimizeIf(gt, instr, "too many arguments");
DeoptimizeIf(gt, instr, Deoptimizer::kTooManyArguments);
// Push the receiver and use the register to keep the original
// number of arguments.
@ -3803,7 +3803,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
__ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
__ cmp(scratch, ip);
DeoptimizeIf(ne, instr, "not a heap number");
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
Label done;
Register exponent = scratch0();
@ -3873,7 +3873,7 @@ void LCodeGen::EmitMathAbs(LMathAbs* instr) {
__ mtxer(r0);
__ neg(result, result, SetOE, SetRC);
// Deoptimize on overflow.
DeoptimizeIf(overflow, instr, "overflow", cr0);
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0);
__ bind(&done);
}
@ -3890,7 +3890,7 @@ void LCodeGen::EmitInteger32MathAbs(LMathAbs* instr) {
// Deoptimize on overflow.
__ lis(r0, Operand(SIGN_EXT_IMM16(0x8000)));
__ cmpw(input, r0);
DeoptimizeIf(eq, instr, "overflow");
DeoptimizeIf(eq, instr, Deoptimizer::kOverflow);
__ neg(result, result);
__ bind(&done);
@ -3949,7 +3949,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ TryInt32Floor(result, input, input_high, scratch, double_scratch0(), &done,
&exact);
DeoptimizeIf(al, instr, "lost precision or NaN");
DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN);
__ bind(&exact);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -3957,7 +3957,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ cmpi(result, Operand::Zero());
__ bne(&done);
__ cmpwi(input_high, Operand::Zero());
DeoptimizeIf(lt, instr, "minus zero");
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
}
__ bind(&done);
}
@ -3976,7 +3976,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
__ LoadDoubleLiteral(dot_five, 0.5, r0);
__ fabs(double_scratch1, input);
__ fcmpu(double_scratch1, dot_five);
DeoptimizeIf(unordered, instr, "lost precision or NaN");
DeoptimizeIf(unordered, instr, Deoptimizer::kLostPrecisionOrNaN);
// If input is in [-0.5, -0], the result is -0.
// If input is in [+0, +0.5[, the result is +0.
// If the input is +0.5, the result is 1.
@ -3989,7 +3989,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
#endif
__ cmpi(scratch1, Operand::Zero());
// [-0.5, -0].
DeoptimizeIf(lt, instr, "minus zero");
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
}
Label return_zero;
__ fcmpu(input, dot_five);
@ -4007,7 +4007,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
// Reuse dot_five (double_scratch0) as we no longer need this value.
__ TryInt32Floor(result, input_plus_dot_five, scratch1, scratch2,
double_scratch0(), &done, &done);
DeoptimizeIf(al, instr, "lost precision or NaN");
DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN);
__ bind(&done);
}
@ -4073,7 +4073,7 @@ void LCodeGen::DoPower(LPower* instr) {
__ LoadP(r10, FieldMemOperand(r5, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
__ cmp(r10, ip);
DeoptimizeIf(ne, instr, "not a heap number");
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
__ bind(&no_deopt);
MathPowStub stub(isolate(), MathPowStub::TAGGED);
__ CallStub(&stub);
@ -4452,7 +4452,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
__ stop("eliminated bounds check failed");
__ bind(&done);
} else {
DeoptimizeIf(cc, instr, "out of bounds");
DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds);
}
}
@ -4725,7 +4725,7 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
Register temp = ToRegister(instr->temp());
Label no_memento_found;
__ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
DeoptimizeIf(eq, instr, "memento found");
DeoptimizeIf(eq, instr, Deoptimizer::kMementoFound);
__ bind(&no_memento_found);
}
@ -5040,13 +5040,13 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) {
if (hchange->CheckFlag(HValue::kCanOverflow) &&
hchange->value()->CheckFlag(HValue::kUint32)) {
__ TestUnsignedSmiCandidate(input, r0);
DeoptimizeIf(ne, instr, "overflow", cr0);
DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, cr0);
}
#if !V8_TARGET_ARCH_PPC64
if (hchange->CheckFlag(HValue::kCanOverflow) &&
!hchange->value()->CheckFlag(HValue::kUint32)) {
__ SmiTagCheckOverflow(output, input, r0);
DeoptimizeIf(lt, instr, "overflow", cr0);
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0);
} else {
#endif
__ SmiTag(output, input);
@ -5065,7 +5065,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
// If the input is a HeapObject, value of scratch won't be zero.
__ andi(scratch, input, Operand(kHeapObjectTag));
__ SmiUntag(result, input);
DeoptimizeIf(ne, instr, "not a Smi", cr0);
DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0);
} else {
__ SmiUntag(result, input);
}
@ -5095,7 +5095,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
if (can_convert_undefined_to_nan) {
__ bne(&convert);
} else {
DeoptimizeIf(ne, instr, "not a heap number");
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
}
// load heap number
__ lfd(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
@ -5111,7 +5111,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
__ bne(&done);
__ Cmpi(scratch, Operand(HeapNumber::kSignMask), r0);
#endif
DeoptimizeIf(eq, instr, "minus zero");
DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero);
}
__ b(&done);
if (can_convert_undefined_to_nan) {
@ -5119,7 +5119,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
// Convert undefined (and hole) to NaN.
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(input_reg, ip);
DeoptimizeIf(ne, instr, "not a heap number/undefined");
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined);
__ LoadRoot(scratch, Heap::kNanValueRootIndex);
__ lfd(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset));
__ b(&done);
@ -5181,10 +5181,11 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
__ bind(&check_false);
__ LoadRoot(ip, Heap::kFalseValueRootIndex);
__ cmp(input_reg, ip);
DeoptimizeIf(ne, instr, "not a heap number/undefined/true/false", cr7);
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedTrueFalse,
cr7);
__ li(input_reg, Operand::Zero());
} else {
DeoptimizeIf(ne, instr, "not a heap number", cr7);
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, cr7);
__ lfd(double_scratch2,
FieldMemOperand(input_reg, HeapNumber::kValueOffset));
@ -5194,7 +5195,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
}
__ TryDoubleToInt32Exact(input_reg, double_scratch2, scratch1,
double_scratch);
DeoptimizeIf(ne, instr, "lost precision or NaN", cr7);
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, cr7);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ cmpi(input_reg, Operand::Zero());
@ -5203,7 +5204,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
FieldMemOperand(scratch2, HeapNumber::kValueOffset +
Register::kExponentOffset));
__ cmpwi(scratch1, Operand::Zero());
DeoptimizeIf(lt, instr, "minus zero", cr7);
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, cr7);
}
}
__ bind(&done);
@ -5272,7 +5273,7 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
__ TryDoubleToInt32Exact(result_reg, double_input, scratch1,
double_scratch);
// Deoptimize if the input wasn't a int32 (inside a double).
DeoptimizeIf(ne, instr, "lost precision or NaN");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label done;
__ cmpi(result_reg, Operand::Zero());
@ -5283,7 +5284,7 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
__ MovDoubleHighToInt(scratch1, double_input);
#endif
__ cmpi(scratch1, Operand::Zero());
DeoptimizeIf(lt, instr, "minus zero");
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
__ bind(&done);
}
}
@ -5302,7 +5303,7 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
__ TryDoubleToInt32Exact(result_reg, double_input, scratch1,
double_scratch);
// Deoptimize if the input wasn't a int32 (inside a double).
DeoptimizeIf(ne, instr, "lost precision or NaN");
DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label done;
__ cmpi(result_reg, Operand::Zero());
@ -5313,7 +5314,7 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
__ MovDoubleHighToInt(scratch1, double_input);
#endif
__ cmpi(scratch1, Operand::Zero());
DeoptimizeIf(lt, instr, "minus zero");
DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero);
__ bind(&done);
}
}
@ -5321,7 +5322,7 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
__ SmiTag(result_reg);
#else
__ SmiTagCheckOverflow(result_reg, r0);
DeoptimizeIf(lt, instr, "overflow", cr0);
DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0);
#endif
}
@ -5329,7 +5330,7 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
LOperand* input = instr->value();
__ TestIfSmi(ToRegister(input), r0);
DeoptimizeIf(ne, instr, "not a Smi", cr0);
DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0);
}
@ -5337,7 +5338,7 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
if (!instr->hydrogen()->value()->type().IsHeapObject()) {
LOperand* input = instr->value();
__ TestIfSmi(ToRegister(input), r0);
DeoptimizeIf(eq, instr, "Smi", cr0);
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
}
}
@ -5358,13 +5359,13 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
// If there is only one type in the interval check for equality.
if (first == last) {
DeoptimizeIf(ne, instr, "wrong instance type");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType);
} else {
DeoptimizeIf(lt, instr, "wrong instance type");
DeoptimizeIf(lt, instr, Deoptimizer::kWrongInstanceType);
// Omit check for the last type.
if (last != LAST_TYPE) {
__ cmpli(scratch, Operand(last));
DeoptimizeIf(gt, instr, "wrong instance type");
DeoptimizeIf(gt, instr, Deoptimizer::kWrongInstanceType);
}
}
} else {
@ -5375,11 +5376,12 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
if (base::bits::IsPowerOfTwo32(mask)) {
DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
__ andi(r0, scratch, Operand(mask));
DeoptimizeIf(tag == 0 ? ne : eq, instr, "wrong instance type", cr0);
DeoptimizeIf(tag == 0 ? ne : eq, instr, Deoptimizer::kWrongInstanceType,
cr0);
} else {
__ andi(scratch, scratch, Operand(mask));
__ cmpi(scratch, Operand(tag));
DeoptimizeIf(ne, instr, "wrong instance type");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType);
}
}
}
@ -5398,7 +5400,7 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
} else {
__ Cmpi(reg, Operand(object), r0);
}
DeoptimizeIf(ne, instr, "value mismatch");
DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch);
}
@ -5413,7 +5415,7 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
__ StoreToSafepointRegisterSlot(r3, scratch0());
}
__ TestIfSmi(scratch0(), r0);
DeoptimizeIf(eq, instr, "instance migration failed", cr0);
DeoptimizeIf(eq, instr, Deoptimizer::kInstanceMigrationFailed, cr0);
}
@ -5471,7 +5473,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
if (instr->hydrogen()->HasMigrationTarget()) {
__ bne(deferred->entry());
} else {
DeoptimizeIf(ne, instr, "wrong map");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
}
__ bind(&success);
@ -5510,7 +5512,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
// Check for undefined. Undefined is converted to zero for clamping
// conversions.
__ Cmpi(input_reg, Operand(factory()->undefined_value()), r0);
DeoptimizeIf(ne, instr, "not a heap number/undefined");
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined);
__ li(result_reg, Operand::Zero());
__ b(&done);
@ -5982,19 +5984,19 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(r3, ip);
DeoptimizeIf(eq, instr, "undefined");
DeoptimizeIf(eq, instr, Deoptimizer::kUndefined);
Register null_value = r8;
__ LoadRoot(null_value, Heap::kNullValueRootIndex);
__ cmp(r3, null_value);
DeoptimizeIf(eq, instr, "null");
DeoptimizeIf(eq, instr, Deoptimizer::kNull);
__ TestIfSmi(r3, r0);
DeoptimizeIf(eq, instr, "Smi", cr0);
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
__ CompareObjectType(r3, r4, r4, LAST_JS_PROXY_TYPE);
DeoptimizeIf(le, instr, "wrong instance type");
DeoptimizeIf(le, instr, Deoptimizer::kWrongInstanceType);
Label use_cache, call_runtime;
__ CheckEnumCache(null_value, &call_runtime);
@ -6010,7 +6012,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ LoadP(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kMetaMapRootIndex);
__ cmp(r4, ip);
DeoptimizeIf(ne, instr, "wrong map");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
__ bind(&use_cache);
}
@ -6030,7 +6032,7 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
__ LoadP(result, FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
__ LoadP(result, FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
__ cmpi(result, Operand::Zero());
DeoptimizeIf(eq, instr, "no cache");
DeoptimizeIf(eq, instr, Deoptimizer::kNoCache);
__ bind(&done);
}
@ -6041,7 +6043,7 @@ void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
Register map = ToRegister(instr->map());
__ LoadP(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
__ cmp(map, scratch0());
DeoptimizeIf(ne, instr, "wrong map");
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
}

View File

@ -3386,6 +3386,15 @@ void Assembler::RecordComment(const char* msg, bool force) {
}
void Assembler::RecordDeoptReason(const int reason, const int raw_position) {
if (FLAG_trace_deopt) {
EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::POSITION, raw_position);
RecordRelocInfo(RelocInfo::DEOPT_REASON, reason);
}
}
Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
// No out-of-line constant pool support.
DCHECK(!FLAG_enable_ool_constant_pool);

View File

@ -1330,6 +1330,10 @@ class Assembler : public AssemblerBase {
// Use --code-comments to enable.
void RecordComment(const char* msg, bool force = false);
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(const int reason, const int raw_position);
// Allocate a constant pool of the correct size for the generated code.
Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);

View File

@ -723,7 +723,7 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
const char* detail,
Deoptimizer::DeoptReason deopt_reason,
Deoptimizer::BailoutType bailout_type) {
LEnvironment* environment = instr->environment();
RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
@ -769,7 +769,7 @@ void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
}
Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(),
instr->Mnemonic(), detail);
instr->Mnemonic(), deopt_reason);
DCHECK(info()->IsStub() || frame_is_built_);
// Go through jump table if we need to handle condition, build frame, or
// restore caller doubles.
@ -796,11 +796,11 @@ void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
const char* detail) {
Deoptimizer::DeoptReason deopt_reason) {
Deoptimizer::BailoutType bailout_type = info()->IsStub()
? Deoptimizer::LAZY
: Deoptimizer::EAGER;
DeoptimizeIf(cc, instr, detail, bailout_type);
DeoptimizeIf(cc, instr, deopt_reason, bailout_type);
}
@ -1032,7 +1032,7 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
__ andl(dividend, Immediate(mask));
__ negl(dividend);
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
__ jmp(&done, Label::kNear);
}
@ -1049,7 +1049,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
DCHECK(ToRegister(instr->result()).is(rax));
if (divisor == 0) {
DeoptimizeIf(no_condition, instr, "division by zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1064,7 +1064,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
Label remainder_not_zero;
__ j(not_zero, &remainder_not_zero, Label::kNear);
__ cmpl(dividend, Immediate(0));
DeoptimizeIf(less, instr, "minus zero");
DeoptimizeIf(less, instr, Deoptimizer::kMinusZero);
__ bind(&remainder_not_zero);
}
}
@ -1086,7 +1086,7 @@ void LCodeGen::DoModI(LModI* instr) {
// deopt in this case because we can't return a NaN.
if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
__ testl(right_reg, right_reg);
DeoptimizeIf(zero, instr, "division by zero");
DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero);
}
// Check for kMinInt % -1, idiv would signal a divide error. We
@ -1097,7 +1097,7 @@ void LCodeGen::DoModI(LModI* instr) {
__ j(not_zero, &no_overflow_possible, Label::kNear);
__ cmpl(right_reg, Immediate(-1));
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(equal, instr, "minus zero");
DeoptimizeIf(equal, instr, Deoptimizer::kMinusZero);
} else {
__ j(not_equal, &no_overflow_possible, Label::kNear);
__ Set(result_reg, 0);
@ -1117,7 +1117,7 @@ void LCodeGen::DoModI(LModI* instr) {
__ j(not_sign, &positive_left, Label::kNear);
__ idivl(right_reg);
__ testl(result_reg, result_reg);
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
__ jmp(&done, Label::kNear);
__ bind(&positive_left);
}
@ -1143,13 +1143,13 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
// If the divisor is negative, we have to negate and handle edge cases.
__ negl(dividend);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
// Dividing by -1 is basically negation, unless we overflow.
if (divisor == -1) {
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
return;
}
@ -1176,7 +1176,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
DCHECK(ToRegister(instr->result()).is(rdx));
if (divisor == 0) {
DeoptimizeIf(no_condition, instr, "division by zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1184,7 +1184,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
HMathFloorOfDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ testl(dividend, dividend);
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
// Easy case: We need no dynamic check for the dividend and the flooring
@ -1231,7 +1231,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ testl(divisor, divisor);
DeoptimizeIf(zero, instr, "division by zero");
DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero);
}
// Check for (0 / -x) that will produce negative zero.
@ -1240,7 +1240,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
__ testl(dividend, dividend);
__ j(not_zero, &dividend_not_zero, Label::kNear);
__ testl(divisor, divisor);
DeoptimizeIf(sign, instr, "minus zero");
DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero);
__ bind(&dividend_not_zero);
}
@ -1250,7 +1250,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
__ cmpl(dividend, Immediate(kMinInt));
__ j(not_zero, &dividend_not_min_int, Label::kNear);
__ cmpl(divisor, Immediate(-1));
DeoptimizeIf(zero, instr, "overflow");
DeoptimizeIf(zero, instr, Deoptimizer::kOverflow);
__ bind(&dividend_not_min_int);
}
@ -1279,19 +1279,19 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ testl(dividend, dividend);
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
// Check for (kMinInt / -1).
if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
__ cmpl(dividend, Immediate(kMinInt));
DeoptimizeIf(zero, instr, "overflow");
DeoptimizeIf(zero, instr, Deoptimizer::kOverflow);
}
// 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);
__ testl(dividend, Immediate(mask));
DeoptimizeIf(not_zero, instr, "lost precision");
DeoptimizeIf(not_zero, instr, Deoptimizer::kLostPrecision);
}
__ Move(result, dividend);
int32_t shift = WhichPowerOf2Abs(divisor);
@ -1312,7 +1312,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
DCHECK(ToRegister(instr->result()).is(rdx));
if (divisor == 0) {
DeoptimizeIf(no_condition, instr, "division by zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1320,7 +1320,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ testl(dividend, dividend);
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
__ TruncatingDiv(dividend, Abs(divisor));
@ -1330,7 +1330,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
__ movl(rax, rdx);
__ imull(rax, rax, Immediate(divisor));
__ subl(rax, dividend);
DeoptimizeIf(not_equal, instr, "lost precision");
DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision);
}
}
@ -1350,7 +1350,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ testl(divisor, divisor);
DeoptimizeIf(zero, instr, "division by zero");
DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero);
}
// Check for (0 / -x) that will produce negative zero.
@ -1359,7 +1359,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
__ testl(dividend, dividend);
__ j(not_zero, &dividend_not_zero, Label::kNear);
__ testl(divisor, divisor);
DeoptimizeIf(sign, instr, "minus zero");
DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero);
__ bind(&dividend_not_zero);
}
@ -1369,7 +1369,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
__ cmpl(dividend, Immediate(kMinInt));
__ j(not_zero, &dividend_not_min_int, Label::kNear);
__ cmpl(divisor, Immediate(-1));
DeoptimizeIf(zero, instr, "overflow");
DeoptimizeIf(zero, instr, Deoptimizer::kOverflow);
__ bind(&dividend_not_min_int);
}
@ -1380,7 +1380,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
// Deoptimize if remainder is not 0.
__ testl(remainder, remainder);
DeoptimizeIf(not_zero, instr, "lost precision");
DeoptimizeIf(not_zero, instr, Deoptimizer::kLostPrecision);
}
}
@ -1457,7 +1457,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
}
if (can_overflow) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -1476,10 +1476,10 @@ void LCodeGen::DoMulI(LMulI* instr) {
? !instr->hydrogen_value()->representation().IsSmi()
: SmiValuesAre31Bits());
if (ToInteger32(LConstantOperand::cast(right)) < 0) {
DeoptimizeIf(no_condition, instr, "minus zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero);
} else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
__ cmpl(kScratchRegister, Immediate(0));
DeoptimizeIf(less, instr, "minus zero");
DeoptimizeIf(less, instr, Deoptimizer::kMinusZero);
}
} else if (right->IsStackSlot()) {
if (instr->hydrogen_value()->representation().IsSmi()) {
@ -1487,7 +1487,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
} else {
__ orl(kScratchRegister, ToOperand(right));
}
DeoptimizeIf(sign, instr, "minus zero");
DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero);
} else {
// Test the non-zero operand for negative sign.
if (instr->hydrogen_value()->representation().IsSmi()) {
@ -1495,7 +1495,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
} else {
__ orl(kScratchRegister, ToRegister(right));
}
DeoptimizeIf(sign, instr, "minus zero");
DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero);
}
__ bind(&done);
}
@ -1608,7 +1608,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
__ shrl_cl(ToRegister(left));
if (instr->can_deopt()) {
__ testl(ToRegister(left), ToRegister(left));
DeoptimizeIf(negative, instr, "negative value");
DeoptimizeIf(negative, instr, Deoptimizer::kNegativeValue);
}
break;
case Token::SHL:
@ -1637,7 +1637,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
__ shrl(ToRegister(left), Immediate(shift_count));
} else if (instr->can_deopt()) {
__ testl(ToRegister(left), ToRegister(left));
DeoptimizeIf(negative, instr, "negative value");
DeoptimizeIf(negative, instr, Deoptimizer::kNegativeValue);
}
break;
case Token::SHL:
@ -1652,7 +1652,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
__ shll(ToRegister(left), Immediate(shift_count - 1));
}
__ Integer32ToSmi(ToRegister(left), ToRegister(left));
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
} else {
__ shll(ToRegister(left), Immediate(shift_count));
}
@ -1695,7 +1695,7 @@ void LCodeGen::DoSubI(LSubI* instr) {
}
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
}
@ -1748,9 +1748,9 @@ void LCodeGen::DoDateField(LDateField* instr) {
DCHECK(object.is(rax));
Condition cc = masm()->CheckSmi(object);
DeoptimizeIf(cc, instr, "Smi");
DeoptimizeIf(cc, instr, Deoptimizer::kSmi);
__ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister);
DeoptimizeIf(not_equal, instr, "not a date object");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotADateObject);
if (index->value() == 0) {
__ movp(result, FieldOperand(object, JSDate::kValueOffset));
@ -1914,7 +1914,7 @@ void LCodeGen::DoAddI(LAddI* instr) {
}
}
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
}
}
@ -2180,7 +2180,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
} else if (expected.NeedsMap()) {
// If we need a map later and have a Smi -> deopt.
__ testb(reg, Immediate(kSmiTagMask));
DeoptimizeIf(zero, instr, "Smi");
DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
}
const Register map = kScratchRegister;
@ -2234,7 +2234,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(no_condition, instr, "unexpected object");
DeoptimizeIf(no_condition, instr, Deoptimizer::kUnexpectedObject);
}
}
}
@ -2851,7 +2851,7 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
__ LoadGlobalCell(result, instr->hydrogen()->cell().handle());
if (instr->hydrogen()->RequiresHoleCheck()) {
__ CompareRoot(result, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
}
}
@ -2904,7 +2904,7 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
DCHECK(!value.is(cell));
__ Move(cell, cell_handle, RelocInfo::CELL);
__ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex);
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
// Store the value.
__ movp(Operand(cell, 0), value);
} else {
@ -2923,7 +2923,7 @@ void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
__ CompareRoot(result, Heap::kTheHoleValueRootIndex);
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
} else {
Label is_not_hole;
__ j(not_equal, &is_not_hole, Label::kNear);
@ -2944,7 +2944,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
__ CompareRoot(target, Heap::kTheHoleValueRootIndex);
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
} else {
__ j(not_equal, &skip_assignment);
}
@ -3044,7 +3044,7 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
// Check that the function has a prototype or an initial map.
__ CompareRoot(result, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
// If the function does not have an initial map, we're done.
Label done;
@ -3156,7 +3156,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
__ movl(result, operand);
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
__ testl(result, result);
DeoptimizeIf(negative, instr, "negative value");
DeoptimizeIf(negative, instr, Deoptimizer::kNegativeValue);
}
break;
case EXTERNAL_FLOAT32_ELEMENTS:
@ -3195,7 +3195,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
FAST_DOUBLE_ELEMENTS,
instr->base_offset() + sizeof(kHoleNanLower32));
__ cmpl(hole_check_operand, Immediate(kHoleNanUpper32));
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
}
Operand double_load_operand = BuildFastArrayOperand(
@ -3252,10 +3252,10 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
if (requires_hole_check) {
if (IsFastSmiElementsKind(hinstr->elements_kind())) {
Condition smi = __ CheckSmi(result);
DeoptimizeIf(NegateCondition(smi), instr, "not a Smi");
DeoptimizeIf(NegateCondition(smi), instr, Deoptimizer::kNotASmi);
} else {
__ CompareRoot(result, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
}
}
}
@ -3402,9 +3402,9 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
// The receiver should be a JS object.
Condition is_smi = __ CheckSmi(receiver);
DeoptimizeIf(is_smi, instr, "Smi");
DeoptimizeIf(is_smi, instr, Deoptimizer::kSmi);
__ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister);
DeoptimizeIf(below, instr, "not a JavaScript object");
DeoptimizeIf(below, instr, Deoptimizer::kNotAJavaScriptObject);
__ jmp(&receiver_ok, Label::kNear);
__ bind(&global_object);
@ -3431,7 +3431,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// adaptor frame below it.
const uint32_t kArgumentsLimit = 1 * KB;
__ cmpp(length, Immediate(kArgumentsLimit));
DeoptimizeIf(above, instr, "too many arguments");
DeoptimizeIf(above, instr, Deoptimizer::kTooManyArguments);
__ Push(receiver);
__ movp(receiver, length);
@ -3645,7 +3645,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
Register input_reg = ToRegister(instr->value());
__ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex);
DeoptimizeIf(not_equal, instr, "not a heap number");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
Label slow, allocated, done;
Register tmp = input_reg.is(rax) ? rcx : rax;
@ -3691,7 +3691,7 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
Label is_positive;
__ j(not_sign, &is_positive, Label::kNear);
__ negl(input_reg); // Sets flags.
DeoptimizeIf(negative, instr, "overflow");
DeoptimizeIf(negative, instr, Deoptimizer::kOverflow);
__ bind(&is_positive);
}
@ -3702,7 +3702,7 @@ void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) {
Label is_positive;
__ j(not_sign, &is_positive, Label::kNear);
__ negp(input_reg); // Sets flags.
DeoptimizeIf(negative, instr, "overflow");
DeoptimizeIf(negative, instr, Deoptimizer::kOverflow);
__ bind(&is_positive);
}
@ -3758,18 +3758,18 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
// Deoptimize if minus zero.
__ movq(output_reg, input_reg);
__ subq(output_reg, Immediate(1));
DeoptimizeIf(overflow, instr, "minus zero");
DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero);
}
__ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
__ cvttsd2si(output_reg, xmm_scratch);
__ cmpl(output_reg, Immediate(0x1));
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
} else {
Label negative_sign, done;
// Deoptimize on unordered.
__ xorps(xmm_scratch, xmm_scratch); // Zero the register.
__ ucomisd(input_reg, xmm_scratch);
DeoptimizeIf(parity_even, instr, "NaN");
DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN);
__ j(below, &negative_sign, Label::kNear);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -3778,7 +3778,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ j(above, &positive_sign, Label::kNear);
__ movmskpd(output_reg, input_reg);
__ testq(output_reg, Immediate(1));
DeoptimizeIf(not_zero, instr, "minus zero");
DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
__ Set(output_reg, 0);
__ jmp(&done);
__ bind(&positive_sign);
@ -3788,7 +3788,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ cvttsd2si(output_reg, input_reg);
// Overflow is signalled with minint.
__ cmpl(output_reg, Immediate(0x1));
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
__ jmp(&done, Label::kNear);
// Non-zero negative reaches here.
@ -3799,7 +3799,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ ucomisd(input_reg, xmm_scratch);
__ j(equal, &done, Label::kNear);
__ subl(output_reg, Immediate(1));
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
__ bind(&done);
}
@ -3826,7 +3826,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
__ cvttsd2si(output_reg, xmm_scratch);
// Overflow is signalled with minint.
__ cmpl(output_reg, Immediate(0x1));
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
__ jmp(&done, dist);
__ bind(&below_one_half);
@ -3842,7 +3842,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
__ cvttsd2si(output_reg, input_temp);
// Catch minint due to overflow, and to prevent overflow when compensating.
__ cmpl(output_reg, Immediate(0x1));
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
__ Cvtlsi2sd(xmm_scratch, output_reg);
__ ucomisd(xmm_scratch, input_temp);
@ -3857,7 +3857,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ movq(output_reg, input_reg);
__ testq(output_reg, output_reg);
DeoptimizeIf(negative, instr, "minus zero");
DeoptimizeIf(negative, instr, Deoptimizer::kMinusZero);
}
__ Set(output_reg, 0);
__ bind(&done);
@ -3936,7 +3936,7 @@ void LCodeGen::DoPower(LPower* instr) {
Label no_deopt;
__ JumpIfSmi(tagged_exponent, &no_deopt, Label::kNear);
__ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, rcx);
DeoptimizeIf(not_equal, instr, "not a heap number");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
__ bind(&no_deopt);
MathPowStub stub(isolate(), MathPowStub::TAGGED);
__ CallStub(&stub);
@ -4330,7 +4330,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
__ int3();
__ bind(&done);
} else {
DeoptimizeIf(cc, instr, "out of bounds");
DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds);
}
}
@ -4571,7 +4571,7 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
Register temp = ToRegister(instr->temp());
Label no_memento_found;
__ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
DeoptimizeIf(equal, instr, "memento found");
DeoptimizeIf(equal, instr, Deoptimizer::kMementoFound);
__ bind(&no_memento_found);
}
@ -4891,12 +4891,12 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) {
if (hchange->CheckFlag(HValue::kCanOverflow) &&
hchange->value()->CheckFlag(HValue::kUint32)) {
Condition is_smi = __ CheckUInteger32ValidSmiValue(input);
DeoptimizeIf(NegateCondition(is_smi), instr, "overflow");
DeoptimizeIf(NegateCondition(is_smi), instr, Deoptimizer::kOverflow);
}
__ Integer32ToSmi(output, input);
if (hchange->CheckFlag(HValue::kCanOverflow) &&
!hchange->value()->CheckFlag(HValue::kUint32)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
}
@ -4906,7 +4906,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
Register input = ToRegister(instr->value());
if (instr->needs_check()) {
Condition is_smi = __ CheckSmi(input);
DeoptimizeIf(NegateCondition(is_smi), instr, "not a Smi");
DeoptimizeIf(NegateCondition(is_smi), instr, Deoptimizer::kNotASmi);
} else {
__ AssertSmi(input);
}
@ -4937,7 +4937,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
if (can_convert_undefined_to_nan) {
__ j(not_equal, &convert, Label::kNear);
} else {
DeoptimizeIf(not_equal, instr, "not a heap number");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
}
if (deoptimize_on_minus_zero) {
@ -4947,7 +4947,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
__ j(not_equal, &done, Label::kNear);
__ movmskpd(kScratchRegister, result_reg);
__ testq(kScratchRegister, Immediate(1));
DeoptimizeIf(not_zero, instr, "minus zero");
DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
}
__ jmp(&done, Label::kNear);
@ -4956,7 +4956,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
// Convert undefined (and hole) to NaN. Compute NaN as 0/0.
__ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumberUndefined);
__ pcmpeqd(result_reg, result_reg);
__ jmp(&done, Label::kNear);
@ -5002,26 +5002,27 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
__ bind(&check_false);
__ CompareRoot(input_reg, Heap::kFalseValueRootIndex);
DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false");
DeoptimizeIf(not_equal, instr,
Deoptimizer::kNotAHeapNumberUndefinedBoolean);
__ Set(input_reg, 0);
} else {
XMMRegister scratch = ToDoubleRegister(instr->temp());
DCHECK(!scratch.is(xmm0));
__ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex);
DeoptimizeIf(not_equal, instr, "not a heap number");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
__ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
__ cvttsd2si(input_reg, xmm0);
__ Cvtlsi2sd(scratch, input_reg);
__ ucomisd(xmm0, scratch);
DeoptimizeIf(not_equal, instr, "lost precision");
DeoptimizeIf(parity_even, instr, "NaN");
DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision);
DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN);
if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
__ testl(input_reg, input_reg);
__ j(not_zero, done);
__ movmskpd(input_reg, xmm0);
__ andl(input_reg, Immediate(1));
DeoptimizeIf(not_zero, instr, "minus zero");
DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
}
}
}
@ -5092,11 +5093,11 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
&is_nan, &minus_zero, dist);
__ jmp(&done, dist);
__ bind(&lost_precision);
DeoptimizeIf(no_condition, instr, "lost precision");
DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision);
__ bind(&is_nan);
DeoptimizeIf(no_condition, instr, "NaN");
DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN);
__ bind(&minus_zero);
DeoptimizeIf(no_condition, instr, "minus zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero);
__ bind(&done);
}
}
@ -5119,21 +5120,21 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
&minus_zero, dist);
__ jmp(&done, dist);
__ bind(&lost_precision);
DeoptimizeIf(no_condition, instr, "lost precision");
DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision);
__ bind(&is_nan);
DeoptimizeIf(no_condition, instr, "NaN");
DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN);
__ bind(&minus_zero);
DeoptimizeIf(no_condition, instr, "minus zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero);
__ bind(&done);
__ Integer32ToSmi(result_reg, result_reg);
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
LOperand* input = instr->value();
Condition cc = masm()->CheckSmi(ToRegister(input));
DeoptimizeIf(NegateCondition(cc), instr, "not a Smi");
DeoptimizeIf(NegateCondition(cc), instr, Deoptimizer::kNotASmi);
}
@ -5141,7 +5142,7 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
if (!instr->hydrogen()->value()->type().IsHeapObject()) {
LOperand* input = instr->value();
Condition cc = masm()->CheckSmi(ToRegister(input));
DeoptimizeIf(cc, instr, "Smi");
DeoptimizeIf(cc, instr, Deoptimizer::kSmi);
}
}
@ -5161,14 +5162,14 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
// If there is only one type in the interval check for equality.
if (first == last) {
DeoptimizeIf(not_equal, instr, "wrong instance type");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongInstanceType);
} else {
DeoptimizeIf(below, instr, "wrong instance type");
DeoptimizeIf(below, instr, Deoptimizer::kWrongInstanceType);
// Omit check for the last type.
if (last != LAST_TYPE) {
__ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
Immediate(static_cast<int8_t>(last)));
DeoptimizeIf(above, instr, "wrong instance type");
DeoptimizeIf(above, instr, Deoptimizer::kWrongInstanceType);
}
}
} else {
@ -5180,13 +5181,14 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
__ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
Immediate(mask));
DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type");
DeoptimizeIf(tag == 0 ? not_zero : zero, instr,
Deoptimizer::kWrongInstanceType);
} else {
__ movzxbl(kScratchRegister,
FieldOperand(kScratchRegister, Map::kInstanceTypeOffset));
__ andb(kScratchRegister, Immediate(mask));
__ cmpb(kScratchRegister, Immediate(tag));
DeoptimizeIf(not_equal, instr, "wrong instance type");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongInstanceType);
}
}
}
@ -5195,7 +5197,7 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
void LCodeGen::DoCheckValue(LCheckValue* instr) {
Register reg = ToRegister(instr->value());
__ Cmp(reg, instr->hydrogen()->object().handle());
DeoptimizeIf(not_equal, instr, "value mismatch");
DeoptimizeIf(not_equal, instr, Deoptimizer::kValueMismatch);
}
@ -5210,7 +5212,7 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
__ testp(rax, Immediate(kSmiTagMask));
}
DeoptimizeIf(zero, instr, "instance migration failed");
DeoptimizeIf(zero, instr, Deoptimizer::kInstanceMigrationFailed);
}
@ -5264,7 +5266,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
if (instr->hydrogen()->HasMigrationTarget()) {
__ j(not_equal, deferred->entry());
} else {
DeoptimizeIf(not_equal, instr, "wrong map");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap);
}
__ bind(&success);
@ -5303,7 +5305,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
// Check for undefined. Undefined is converted to zero for clamping
// conversions.
__ Cmp(input_reg, factory()->undefined_value());
DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumberUndefined);
__ xorl(input_reg, input_reg);
__ jmp(&done, Label::kNear);
@ -5782,19 +5784,19 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
DCHECK(ToRegister(instr->context()).is(rsi));
__ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
DeoptimizeIf(equal, instr, "undefined");
DeoptimizeIf(equal, instr, Deoptimizer::kUndefined);
Register null_value = rdi;
__ LoadRoot(null_value, Heap::kNullValueRootIndex);
__ cmpp(rax, null_value);
DeoptimizeIf(equal, instr, "null");
DeoptimizeIf(equal, instr, Deoptimizer::kNull);
Condition cc = masm()->CheckSmi(rax);
DeoptimizeIf(cc, instr, "Smi");
DeoptimizeIf(cc, instr, Deoptimizer::kSmi);
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
__ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx);
DeoptimizeIf(below_equal, instr, "wrong instance type");
DeoptimizeIf(below_equal, instr, Deoptimizer::kWrongInstanceType);
Label use_cache, call_runtime;
__ CheckEnumCache(null_value, &call_runtime);
@ -5809,7 +5811,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
Heap::kMetaMapRootIndex);
DeoptimizeIf(not_equal, instr, "wrong map");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap);
__ bind(&use_cache);
}
@ -5831,7 +5833,7 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
FieldOperand(result, FixedArray::SizeFor(instr->idx())));
__ bind(&done);
Condition cc = masm()->CheckSmi(result);
DeoptimizeIf(cc, instr, "no cache");
DeoptimizeIf(cc, instr, Deoptimizer::kNoCache);
}
@ -5839,7 +5841,7 @@ void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
Register object = ToRegister(instr->value());
__ cmpp(ToRegister(instr->map()),
FieldOperand(object, HeapObject::kMapOffset));
DeoptimizeIf(not_equal, instr, "wrong map");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap);
}

View File

@ -199,9 +199,11 @@ class LCodeGen: public LCodeGenBase {
int argc);
void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
Safepoint::DeoptMode mode);
void DeoptimizeIf(Condition cc, LInstruction* instr, const char* detail,
void DeoptimizeIf(Condition cc, LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason,
Deoptimizer::BailoutType bailout_type);
void DeoptimizeIf(Condition cc, LInstruction* instr, const char* detail);
void DeoptimizeIf(Condition cc, LInstruction* instr,
Deoptimizer::DeoptReason deopt_reason);
bool DeoptEveryNTimes() {
return FLAG_deopt_every_n_times != 0 && !info()->IsStub();

View File

@ -1413,7 +1413,7 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
__ and_(dividend, mask);
__ neg(dividend);
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
__ jmp(&done, Label::kNear);
}
@ -1430,7 +1430,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
DCHECK(ToRegister(instr->result()).is(eax));
if (divisor == 0) {
DeoptimizeIf(no_condition, instr, "division by zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1445,7 +1445,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
Label remainder_not_zero;
__ j(not_zero, &remainder_not_zero, Label::kNear);
__ cmp(dividend, Immediate(0));
DeoptimizeIf(less, instr, "minus zero");
DeoptimizeIf(less, instr, Deoptimizer::kMinusZero);
__ bind(&remainder_not_zero);
}
}
@ -1467,7 +1467,7 @@ void LCodeGen::DoModI(LModI* instr) {
// deopt in this case because we can't return a NaN.
if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
__ test(right_reg, Operand(right_reg));
DeoptimizeIf(zero, instr, "division by zero");
DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero);
}
// Check for kMinInt % -1, idiv would signal a divide error. We
@ -1478,7 +1478,7 @@ void LCodeGen::DoModI(LModI* instr) {
__ j(not_equal, &no_overflow_possible, Label::kNear);
__ cmp(right_reg, -1);
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(equal, instr, "minus zero");
DeoptimizeIf(equal, instr, Deoptimizer::kMinusZero);
} else {
__ j(not_equal, &no_overflow_possible, Label::kNear);
__ Move(result_reg, Immediate(0));
@ -1497,7 +1497,7 @@ void LCodeGen::DoModI(LModI* instr) {
__ j(not_sign, &positive_left, Label::kNear);
__ idiv(right_reg);
__ test(result_reg, Operand(result_reg));
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
__ jmp(&done, Label::kNear);
__ bind(&positive_left);
}
@ -1517,19 +1517,19 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ test(dividend, dividend);
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
// Check for (kMinInt / -1).
if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
__ cmp(dividend, kMinInt);
DeoptimizeIf(zero, instr, "overflow");
DeoptimizeIf(zero, instr, Deoptimizer::kOverflow);
}
// 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);
__ test(dividend, Immediate(mask));
DeoptimizeIf(not_zero, instr, "lost precision");
DeoptimizeIf(not_zero, instr, Deoptimizer::kLostPrecision);
}
__ Move(result, dividend);
int32_t shift = WhichPowerOf2Abs(divisor);
@ -1550,7 +1550,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
DCHECK(ToRegister(instr->result()).is(edx));
if (divisor == 0) {
DeoptimizeIf(no_condition, instr, "division by zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1558,7 +1558,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ test(dividend, dividend);
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
__ TruncatingDiv(dividend, Abs(divisor));
@ -1568,7 +1568,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
__ mov(eax, edx);
__ imul(eax, eax, divisor);
__ sub(eax, dividend);
DeoptimizeIf(not_equal, instr, "lost precision");
DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision);
}
}
@ -1588,7 +1588,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ test(divisor, divisor);
DeoptimizeIf(zero, instr, "division by zero");
DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero);
}
// Check for (0 / -x) that will produce negative zero.
@ -1597,7 +1597,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
__ test(dividend, dividend);
__ j(not_zero, &dividend_not_zero, Label::kNear);
__ test(divisor, divisor);
DeoptimizeIf(sign, instr, "minus zero");
DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero);
__ bind(&dividend_not_zero);
}
@ -1607,7 +1607,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
__ cmp(dividend, kMinInt);
__ j(not_zero, &dividend_not_min_int, Label::kNear);
__ cmp(divisor, -1);
DeoptimizeIf(zero, instr, "overflow");
DeoptimizeIf(zero, instr, Deoptimizer::kOverflow);
__ bind(&dividend_not_min_int);
}
@ -1618,7 +1618,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
// Deoptimize if remainder is not 0.
__ test(remainder, remainder);
DeoptimizeIf(not_zero, instr, "lost precision");
DeoptimizeIf(not_zero, instr, Deoptimizer::kLostPrecision);
}
}
@ -1640,13 +1640,13 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
// If the divisor is negative, we have to negate and handle edge cases.
__ neg(dividend);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
// Dividing by -1 is basically negation, unless we overflow.
if (divisor == -1) {
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
return;
}
@ -1673,7 +1673,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
DCHECK(ToRegister(instr->result()).is(edx));
if (divisor == 0) {
DeoptimizeIf(no_condition, instr, "division by zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero);
return;
}
@ -1681,7 +1681,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
HMathFloorOfDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ test(dividend, dividend);
DeoptimizeIf(zero, instr, "minus zero");
DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
}
// Easy case: We need no dynamic check for the dividend and the flooring
@ -1728,7 +1728,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ test(divisor, divisor);
DeoptimizeIf(zero, instr, "division by zero");
DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero);
}
// Check for (0 / -x) that will produce negative zero.
@ -1737,7 +1737,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
__ test(dividend, dividend);
__ j(not_zero, &dividend_not_zero, Label::kNear);
__ test(divisor, divisor);
DeoptimizeIf(sign, instr, "minus zero");
DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero);
__ bind(&dividend_not_zero);
}
@ -1747,7 +1747,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
__ cmp(dividend, kMinInt);
__ j(not_zero, &dividend_not_min_int, Label::kNear);
__ cmp(divisor, -1);
DeoptimizeIf(zero, instr, "overflow");
DeoptimizeIf(zero, instr, Deoptimizer::kOverflow);
__ bind(&dividend_not_min_int);
}
@ -1825,7 +1825,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
}
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -1835,15 +1835,15 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ j(not_zero, &done);
if (right->IsConstantOperand()) {
if (ToInteger32(LConstantOperand::cast(right)) < 0) {
DeoptimizeIf(no_condition, instr, "minus zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero);
} else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
__ cmp(ToRegister(instr->temp()), Immediate(0));
DeoptimizeIf(less, instr, "minus zero");
DeoptimizeIf(less, instr, Deoptimizer::kMinusZero);
}
} else {
// Test the non-zero operand for negative sign.
__ or_(ToRegister(instr->temp()), ToOperand(right));
DeoptimizeIf(sign, instr, "minus zero");
DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero);
}
__ bind(&done);
}
@ -1916,7 +1916,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
__ shr_cl(ToRegister(left));
if (instr->can_deopt()) {
__ test(ToRegister(left), ToRegister(left));
DeoptimizeIf(sign, instr, "negative value");
DeoptimizeIf(sign, instr, Deoptimizer::kNegativeValue);
}
break;
case Token::SHL:
@ -1933,7 +1933,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
case Token::ROR:
if (shift_count == 0 && instr->can_deopt()) {
__ test(ToRegister(left), ToRegister(left));
DeoptimizeIf(sign, instr, "negative value");
DeoptimizeIf(sign, instr, Deoptimizer::kNegativeValue);
} else {
__ ror(ToRegister(left), shift_count);
}
@ -1948,7 +1948,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
__ shr(ToRegister(left), shift_count);
} else if (instr->can_deopt()) {
__ test(ToRegister(left), ToRegister(left));
DeoptimizeIf(sign, instr, "negative value");
DeoptimizeIf(sign, instr, Deoptimizer::kNegativeValue);
}
break;
case Token::SHL:
@ -1959,7 +1959,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
__ shl(ToRegister(left), shift_count - 1);
}
__ SmiTag(ToRegister(left));
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
} else {
__ shl(ToRegister(left), shift_count);
}
@ -1985,7 +1985,7 @@ void LCodeGen::DoSubI(LSubI* instr) {
__ sub(ToRegister(left), ToOperand(right));
}
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
}
@ -2044,9 +2044,9 @@ void LCodeGen::DoDateField(LDateField* instr) {
DCHECK(object.is(eax));
__ test(object, Immediate(kSmiTagMask));
DeoptimizeIf(zero, instr, "Smi");
DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
__ CmpObjectType(object, JS_DATE_TYPE, scratch);
DeoptimizeIf(not_equal, instr, "not a date object");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotADateObject);
if (index->value() == 0) {
__ mov(result, FieldOperand(object, JSDate::kValueOffset));
@ -2176,7 +2176,7 @@ void LCodeGen::DoAddI(LAddI* instr) {
__ add(ToRegister(left), ToOperand(right));
}
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
}
}
@ -2419,7 +2419,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
} else if (expected.NeedsMap()) {
// If we need a map later and have a Smi -> deopt.
__ test(reg, Immediate(kSmiTagMask));
DeoptimizeIf(zero, instr, "Smi");
DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
}
Register map = no_reg; // Keep the compiler happy.
@ -2476,7 +2476,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(no_condition, instr, "unexpected object");
DeoptimizeIf(no_condition, instr, Deoptimizer::kUnexpectedObject);
}
}
}
@ -3118,7 +3118,7 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
__ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle()));
if (instr->hydrogen()->RequiresHoleCheck()) {
__ cmp(result, factory()->the_hole_value());
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
}
}
@ -3167,7 +3167,7 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
// it as no longer deleted. We deoptimize in that case.
if (instr->hydrogen()->RequiresHoleCheck()) {
__ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value());
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
}
// Store the value.
@ -3184,7 +3184,7 @@ void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
__ cmp(result, factory()->the_hole_value());
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
} else {
Label is_not_hole;
__ j(not_equal, &is_not_hole, Label::kNear);
@ -3205,7 +3205,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
__ cmp(target, factory()->the_hole_value());
if (instr->hydrogen()->DeoptimizesOnHole()) {
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
} else {
__ j(not_equal, &skip_assignment, Label::kNear);
}
@ -3299,7 +3299,7 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
// Check that the function has a prototype or an initial map.
__ cmp(Operand(result), Immediate(factory()->the_hole_value()));
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
// If the function does not have an initial map, we're done.
Label done;
@ -3390,7 +3390,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
__ mov(result, operand);
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
__ test(result, Operand(result));
DeoptimizeIf(negative, instr, "negative value");
DeoptimizeIf(negative, instr, Deoptimizer::kNegativeValue);
}
break;
case EXTERNAL_FLOAT32_ELEMENTS:
@ -3420,7 +3420,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
FAST_DOUBLE_ELEMENTS,
instr->base_offset() + sizeof(kHoleNanLower32));
__ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
}
Operand double_load_operand = BuildFastArrayOperand(
@ -3446,10 +3446,10 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
__ test(result, Immediate(kSmiTagMask));
DeoptimizeIf(not_equal, instr, "not a Smi");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotASmi);
} else {
__ cmp(result, factory()->the_hole_value());
DeoptimizeIf(equal, instr, "hole");
DeoptimizeIf(equal, instr, Deoptimizer::kHole);
}
}
}
@ -3596,9 +3596,9 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
// The receiver should be a JS object.
__ test(receiver, Immediate(kSmiTagMask));
DeoptimizeIf(equal, instr, "Smi");
DeoptimizeIf(equal, instr, Deoptimizer::kSmi);
__ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
DeoptimizeIf(below, instr, "not a JavaScript object");
DeoptimizeIf(below, instr, Deoptimizer::kNotAJavaScriptObject);
__ jmp(&receiver_ok, Label::kNear);
__ bind(&global_object);
@ -3624,7 +3624,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// adaptor frame below it.
const uint32_t kArgumentsLimit = 1 * KB;
__ cmp(length, kArgumentsLimit);
DeoptimizeIf(above, instr, "too many arguments");
DeoptimizeIf(above, instr, Deoptimizer::kTooManyArguments);
__ push(receiver);
__ mov(receiver, length);
@ -3849,7 +3849,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
Register input_reg = ToRegister(instr->value());
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
factory()->heap_number_map());
DeoptimizeIf(not_equal, instr, "not a heap number");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
Label slow, allocated, done;
Register tmp = input_reg.is(eax) ? ecx : eax;
@ -3896,7 +3896,7 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
Label is_positive;
__ j(not_sign, &is_positive, Label::kNear);
__ neg(input_reg); // Sets flags.
DeoptimizeIf(negative, instr, "overflow");
DeoptimizeIf(negative, instr, Deoptimizer::kOverflow);
__ bind(&is_positive);
}
@ -3949,7 +3949,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ fldz();
__ fld(1);
__ FCmp();
DeoptimizeIf(parity_even, instr, "NaN");
DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN);
__ j(below, &not_minus_zero, Label::kNear);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@ -3958,7 +3958,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
// +- 0.0.
__ fld(0);
__ FXamSign();
DeoptimizeIf(not_zero, instr, "minus zero");
DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
__ Move(output_reg, Immediate(0));
__ jmp(&done, Label::kFar);
}
@ -3972,7 +3972,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
__ fist_s(Operand(esp, 0));
__ pop(output_reg);
__ X87CheckIA();
DeoptimizeIf(equal, instr, "overflow");
DeoptimizeIf(equal, instr, Deoptimizer::kOverflow);
__ fnclex();
__ X87SetRC(0x0000);
__ bind(&done);
@ -4006,7 +4006,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
// Check overflow.
__ X87CheckIA();
__ pop(result);
DeoptimizeIf(equal, instr, "conversion overflow");
DeoptimizeIf(equal, instr, Deoptimizer::kConversionOverflow);
__ fnclex();
// Restore round mode.
__ X87SetRC(0x0000);
@ -4023,7 +4023,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
// If the sign is positive, we return +0.
__ fld(0);
__ FXamSign();
DeoptimizeIf(not_zero, instr, "minus zero");
DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
}
__ Move(result, Immediate(0));
__ jmp(&done);
@ -4040,7 +4040,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
// Check overflow.
__ X87CheckIA();
__ pop(result);
DeoptimizeIf(equal, instr, "conversion overflow");
DeoptimizeIf(equal, instr, Deoptimizer::kConversionOverflow);
__ fnclex();
// Restore round mode.
__ X87SetRC(0x0000);
@ -4172,7 +4172,7 @@ void LCodeGen::DoPower(LPower* instr) {
X87LoadForUsage(base);
__ JumpIfSmi(exponent, &no_deopt);
__ CmpObjectType(exponent, HEAP_NUMBER_TYPE, temp);
DeoptimizeIf(not_equal, instr, "not a heap number");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
// Heap number(double)
__ fld_d(FieldOperand(exponent, HeapNumber::kValueOffset));
__ jmp(&done);
@ -4574,7 +4574,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
__ int3();
__ bind(&done);
} else {
DeoptimizeIf(cc, instr, "out of bounds");
DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds);
}
}
@ -4765,7 +4765,7 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
Register temp = ToRegister(instr->temp());
Label no_memento_found;
__ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
DeoptimizeIf(equal, instr, "memento found");
DeoptimizeIf(equal, instr, Deoptimizer::kMementoFound);
__ bind(&no_memento_found);
}
@ -5137,12 +5137,12 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) {
if (hchange->CheckFlag(HValue::kCanOverflow) &&
hchange->value()->CheckFlag(HValue::kUint32)) {
__ test(input, Immediate(0xc0000000));
DeoptimizeIf(not_zero, instr, "overflow");
DeoptimizeIf(not_zero, instr, Deoptimizer::kOverflow);
}
__ SmiTag(input);
if (hchange->CheckFlag(HValue::kCanOverflow) &&
!hchange->value()->CheckFlag(HValue::kUint32)) {
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
}
@ -5153,7 +5153,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
DCHECK(input->IsRegister() && input->Equals(instr->result()));
if (instr->needs_check()) {
__ test(result, Immediate(kSmiTagMask));
DeoptimizeIf(not_zero, instr, "not a Smi");
DeoptimizeIf(not_zero, instr, Deoptimizer::kNotASmi);
} else {
__ AssertSmi(result);
}
@ -5179,14 +5179,14 @@ void LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg,
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
factory()->heap_number_map());
if (!can_convert_undefined_to_nan) {
DeoptimizeIf(not_equal, instr, "not a heap number");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
} else {
Label heap_number, convert;
__ j(equal, &heap_number);
// Convert undefined (or hole) to NaN.
__ cmp(input_reg, factory()->undefined_value());
DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumberUndefined);
__ bind(&convert);
__ push(Immediate(0xffffffff));
@ -5212,7 +5212,7 @@ void LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg,
// Pop FPU stack before deoptimizing.
__ fstp(0);
DeoptimizeIf(not_zero, instr, "minus zero");
DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
}
__ jmp(&done, Label::kNear);
} else {
@ -5265,14 +5265,15 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
__ bind(&check_false);
__ cmp(input_reg, factory()->false_value());
DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false");
DeoptimizeIf(not_equal, instr,
Deoptimizer::kNotAHeapNumberUndefinedTrueFalse);
__ Move(input_reg, Immediate(0));
} else {
// TODO(olivf) Converting a number on the fpu is actually quite slow. We
// should first try a fast conversion and then bailout to this slow case.
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
isolate()->factory()->heap_number_map());
DeoptimizeIf(not_equal, instr, "not a heap number");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
__ sub(esp, Immediate(kPointerSize));
__ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
@ -5288,12 +5289,12 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
__ j(equal, &no_precision_lost, Label::kNear);
__ fstp(0);
DeoptimizeIf(no_condition, instr, "lost precision");
DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision);
__ bind(&no_precision_lost);
__ j(parity_odd, &not_nan);
__ fstp(0);
DeoptimizeIf(no_condition, instr, "NaN");
DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN);
__ bind(&not_nan);
__ test(input_reg, Operand(input_reg));
@ -5308,14 +5309,14 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
__ fstp_s(Operand(esp, 0));
__ pop(input_reg);
__ test(input_reg, Operand(input_reg));
DeoptimizeIf(not_zero, instr, "minus zero");
DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
} else {
__ fist_s(MemOperand(esp, 0));
__ fild_s(MemOperand(esp, 0));
__ FCmp();
__ pop(input_reg);
DeoptimizeIf(not_equal, instr, "lost precision");
DeoptimizeIf(parity_even, instr, "NaN");
DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision);
DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN);
}
}
}
@ -5396,11 +5397,11 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
&lost_precision, &is_nan, &minus_zero);
__ jmp(&done);
__ bind(&lost_precision);
DeoptimizeIf(no_condition, instr, "lost precision");
DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision);
__ bind(&is_nan);
DeoptimizeIf(no_condition, instr, "NaN");
DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN);
__ bind(&minus_zero);
DeoptimizeIf(no_condition, instr, "minus zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero);
__ bind(&done);
}
}
@ -5420,21 +5421,21 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
&lost_precision, &is_nan, &minus_zero);
__ jmp(&done);
__ bind(&lost_precision);
DeoptimizeIf(no_condition, instr, "lost precision");
DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision);
__ bind(&is_nan);
DeoptimizeIf(no_condition, instr, "NaN");
DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN);
__ bind(&minus_zero);
DeoptimizeIf(no_condition, instr, "minus zero");
DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero);
__ bind(&done);
__ SmiTag(result_reg);
DeoptimizeIf(overflow, instr, "overflow");
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
}
void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
LOperand* input = instr->value();
__ test(ToOperand(input), Immediate(kSmiTagMask));
DeoptimizeIf(not_zero, instr, "not a Smi");
DeoptimizeIf(not_zero, instr, Deoptimizer::kNotASmi);
}
@ -5442,7 +5443,7 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
if (!instr->hydrogen()->value()->type().IsHeapObject()) {
LOperand* input = instr->value();
__ test(ToOperand(input), Immediate(kSmiTagMask));
DeoptimizeIf(zero, instr, "Smi");
DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
}
}
@ -5463,14 +5464,14 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
// If there is only one type in the interval check for equality.
if (first == last) {
DeoptimizeIf(not_equal, instr, "wrong instance type");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongInstanceType);
} else {
DeoptimizeIf(below, instr, "wrong instance type");
DeoptimizeIf(below, instr, Deoptimizer::kWrongInstanceType);
// Omit check for the last type.
if (last != LAST_TYPE) {
__ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
static_cast<int8_t>(last));
DeoptimizeIf(above, instr, "wrong instance type");
DeoptimizeIf(above, instr, Deoptimizer::kWrongInstanceType);
}
}
} else {
@ -5481,12 +5482,13 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
if (base::bits::IsPowerOfTwo32(mask)) {
DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
__ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask);
DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type");
DeoptimizeIf(tag == 0 ? not_zero : zero, instr,
Deoptimizer::kWrongInstanceType);
} else {
__ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
__ and_(temp, mask);
__ cmp(temp, tag);
DeoptimizeIf(not_equal, instr, "wrong instance type");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongInstanceType);
}
}
}
@ -5502,7 +5504,7 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
Operand operand = ToOperand(instr->value());
__ cmp(operand, object);
}
DeoptimizeIf(not_equal, instr, "value mismatch");
DeoptimizeIf(not_equal, instr, Deoptimizer::kValueMismatch);
}
@ -5517,7 +5519,7 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
__ test(eax, Immediate(kSmiTagMask));
}
DeoptimizeIf(zero, instr, "instance migration failed");
DeoptimizeIf(zero, instr, Deoptimizer::kInstanceMigrationFailed);
}
@ -5574,7 +5576,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
if (instr->hydrogen()->HasMigrationTarget()) {
__ j(not_equal, deferred->entry());
} else {
DeoptimizeIf(not_equal, instr, "wrong map");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap);
}
__ bind(&success);
@ -5615,7 +5617,7 @@ void LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) {
// Check for undefined. Undefined is converted to zero for clamping
// conversions.
__ cmp(input_reg, factory()->undefined_value());
DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumberUndefined);
__ jmp(&zero_result, Label::kNear);
// Heap number
@ -6186,17 +6188,17 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
DCHECK(ToRegister(instr->context()).is(esi));
__ cmp(eax, isolate()->factory()->undefined_value());
DeoptimizeIf(equal, instr, "undefined");
DeoptimizeIf(equal, instr, Deoptimizer::kUndefined);
__ cmp(eax, isolate()->factory()->null_value());
DeoptimizeIf(equal, instr, "null");
DeoptimizeIf(equal, instr, Deoptimizer::kNull);
__ test(eax, Immediate(kSmiTagMask));
DeoptimizeIf(zero, instr, "Smi");
DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
__ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx);
DeoptimizeIf(below_equal, instr, "wrong instance type");
DeoptimizeIf(below_equal, instr, Deoptimizer::kWrongInstanceType);
Label use_cache, call_runtime;
__ CheckEnumCache(&call_runtime);
@ -6211,7 +6213,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ cmp(FieldOperand(eax, HeapObject::kMapOffset),
isolate()->factory()->meta_map());
DeoptimizeIf(not_equal, instr, "wrong map");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap);
__ bind(&use_cache);
}
@ -6234,7 +6236,7 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
FieldOperand(result, FixedArray::SizeFor(instr->idx())));
__ bind(&done);
__ test(result, result);
DeoptimizeIf(equal, instr, "no cache");
DeoptimizeIf(equal, instr, Deoptimizer::kNoCache);
}
@ -6242,7 +6244,7 @@ void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
Register object = ToRegister(instr->value());
__ cmp(ToRegister(instr->map()),
FieldOperand(object, HeapObject::kMapOffset));
DeoptimizeIf(not_equal, instr, "wrong map");
DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap);
}