diff options
Diffstat (limited to 'deps/v8/src/crankshaft/mips64/lithium-codegen-mips64.cc')
-rw-r--r-- | deps/v8/src/crankshaft/mips64/lithium-codegen-mips64.cc | 524 |
1 files changed, 254 insertions, 270 deletions
diff --git a/deps/v8/src/crankshaft/mips64/lithium-codegen-mips64.cc b/deps/v8/src/crankshaft/mips64/lithium-codegen-mips64.cc index c7bbe9f07a..65e922848b 100644 --- a/deps/v8/src/crankshaft/mips64/lithium-codegen-mips64.cc +++ b/deps/v8/src/crankshaft/mips64/lithium-codegen-mips64.cc @@ -10,7 +10,6 @@ #include "src/crankshaft/mips64/lithium-gap-resolver-mips64.h" #include "src/ic/ic.h" #include "src/ic/stub-cache.h" -#include "src/profiler/cpu-profiler.h" namespace v8 { namespace internal { @@ -159,14 +158,12 @@ void LCodeGen::DoPrologue(LPrologue* instr) { __ Push(info()->scope()->GetScopeInfo(info()->isolate())); __ CallRuntime(Runtime::kNewScriptContext); deopt_mode = Safepoint::kLazyDeopt; - } else if (slots <= FastNewContextStub::kMaximumSlots) { - FastNewContextStub stub(isolate(), slots); + } else { + FastNewFunctionContextStub stub(isolate()); + __ li(FastNewFunctionContextDescriptor::SlotsRegister(), Operand(slots)); __ CallStub(&stub); - // Result of FastNewContextStub is always in new space. + // Result of FastNewFunctionContextStub is always in new space. need_write_barrier = false; - } else { - __ push(a1); - __ CallRuntime(Runtime::kNewFunctionContext); } RecordSafepoint(deopt_mode); @@ -175,10 +172,11 @@ void LCodeGen::DoPrologue(LPrologue* instr) { __ mov(cp, v0); __ sd(v0, MemOperand(fp, StandardFrameConstants::kContextOffset)); // Copy any necessary parameters into the context. - int num_parameters = scope()->num_parameters(); - int first_parameter = scope()->has_this_declaration() ? -1 : 0; + int num_parameters = info()->scope()->num_parameters(); + int first_parameter = info()->scope()->has_this_declaration() ? -1 : 0; for (int i = first_parameter; i < num_parameters; i++) { - Variable* var = (i == -1) ? scope()->receiver() : scope()->parameter(i); + Variable* var = (i == -1) ? info()->scope()->receiver() + : info()->scope()->parameter(i); if (var->IsContextSlot()) { int parameter_offset = StandardFrameConstants::kCallerSPOffset + (num_parameters - 1 - i) * kPointerSize; @@ -315,8 +313,6 @@ bool LCodeGen::GenerateJumpTable() { __ BranchAndLink(&call_deopt_entry); } } - info()->LogDeoptCallPosition(masm()->pc_offset(), - table_entry->deopt_info.inlining_id); } if (needs_frame.is_linked()) { __ bind(&needs_frame); @@ -732,9 +728,8 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, } } - void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, - Deoptimizer::DeoptReason deopt_reason, + DeoptimizeReason deopt_reason, Deoptimizer::BailoutType bailout_type, Register src1, const Operand& src2) { LEnvironment* environment = instr->environment(); @@ -776,7 +771,7 @@ void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, __ bind(&skip); } - Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason); + Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason, id); DCHECK(info()->IsStub() || frame_is_built_); // Go through jump table if we need to handle condition, build frame, or @@ -785,14 +780,13 @@ void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, !info()->saves_caller_doubles()) { DeoptComment(deopt_info); __ Call(entry, RelocInfo::RUNTIME_ENTRY, condition, src1, src2); - info()->LogDeoptCallPosition(masm()->pc_offset(), deopt_info.inlining_id); } else { Deoptimizer::JumpTableEntry* table_entry = new (zone()) Deoptimizer::JumpTableEntry( entry, deopt_info, bailout_type, !frame_is_built_); // We often have several deopts to the same entry, reuse the last // jump entry if this is the case. - if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling() || + if (FLAG_trace_deopt || isolate()->is_profiling() || jump_table_.is_empty() || !table_entry->IsEquivalentTo(*jump_table_.last())) { jump_table_.Add(table_entry, zone()); @@ -801,10 +795,9 @@ void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, } } - void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, - Deoptimizer::DeoptReason deopt_reason, - Register src1, const Operand& src2) { + DeoptimizeReason deopt_reason, Register src1, + const Operand& src2) { Deoptimizer::BailoutType bailout_type = info()->IsStub() ? Deoptimizer::LAZY : Deoptimizer::EAGER; @@ -865,13 +858,6 @@ void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, } -void LCodeGen::RecordAndWritePosition(int position) { - if (position == RelocInfo::kNoPosition) return; - masm()->positions_recorder()->RecordPosition(position); - masm()->positions_recorder()->WriteRecordedPositions(); -} - - static const char* LabelType(LLabel* label) { if (label->is_loop_header()) return " (loop header)"; if (label->is_osr_entry()) return " (OSR entry)"; @@ -943,7 +929,7 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { __ dsubu(dividend, zero_reg, dividend); __ And(dividend, dividend, Operand(mask)); if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { - DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend, + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, dividend, Operand(zero_reg)); } __ Branch(USE_DELAY_SLOT, &done); @@ -963,7 +949,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) { DCHECK(!dividend.is(result)); if (divisor == 0) { - DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero); + DeoptimizeIf(al, instr, DeoptimizeReason::kDivisionByZero); return; } @@ -976,7 +962,7 @@ 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, Deoptimizer::kMinusZero, dividend, + DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero, dividend, Operand(zero_reg)); __ bind(&remainder_not_zero); } @@ -996,7 +982,7 @@ 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, Deoptimizer::kDivisionByZero, right_reg, + DeoptimizeIf(eq, instr, DeoptimizeReason::kDivisionByZero, right_reg, Operand(zero_reg)); } @@ -1006,7 +992,8 @@ 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, Deoptimizer::kMinusZero, right_reg, Operand(-1)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, right_reg, + Operand(-1)); } else { __ Branch(&no_overflow_possible, ne, right_reg, Operand(-1)); __ Branch(USE_DELAY_SLOT, &done); @@ -1019,7 +1006,7 @@ void LCodeGen::DoModI(LModI* instr) { __ Branch(&done, ge, left_reg, Operand(zero_reg)); if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { - DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result_reg, + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, result_reg, Operand(zero_reg)); } __ bind(&done); @@ -1036,19 +1023,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) { - DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend, + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, dividend, Operand(zero_reg)); } // Check for (kMinInt / -1). if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { - DeoptimizeIf(eq, instr, Deoptimizer::kOverflow, dividend, Operand(kMinInt)); + DeoptimizeIf(eq, instr, DeoptimizeReason::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, Deoptimizer::kLostPrecision, at, Operand(zero_reg)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecision, at, + Operand(zero_reg)); } if (divisor == -1) { // Nice shortcut, not needed for correctness. @@ -1078,14 +1067,14 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) { DCHECK(!dividend.is(result)); if (divisor == 0) { - DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero); + DeoptimizeIf(al, instr, DeoptimizeReason::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, Deoptimizer::kMinusZero, dividend, + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, dividend, Operand(zero_reg)); } @@ -1095,7 +1084,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) { if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { __ Dmul(scratch0(), result, Operand(divisor)); __ Dsubu(scratch0(), scratch0(), dividend); - DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, scratch0(), + DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecision, scratch0(), Operand(zero_reg)); } } @@ -1114,7 +1103,7 @@ void LCodeGen::DoDivI(LDivI* instr) { // Check for x / 0. if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { - DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, divisor, + DeoptimizeIf(eq, instr, DeoptimizeReason::kDivisionByZero, divisor, Operand(zero_reg)); } @@ -1122,7 +1111,7 @@ void LCodeGen::DoDivI(LDivI* instr) { if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { Label left_not_zero; __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); - DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, divisor, + DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero, divisor, Operand(zero_reg)); __ bind(&left_not_zero); } @@ -1132,7 +1121,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, Deoptimizer::kOverflow, divisor, Operand(-1)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kOverflow, divisor, Operand(-1)); __ bind(&left_not_min_int); } @@ -1144,7 +1133,7 @@ void LCodeGen::DoDivI(LDivI* instr) { } else { __ dmod(remainder, dividend, divisor); } - DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, remainder, + DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecision, remainder, Operand(zero_reg)); } } @@ -1170,7 +1159,7 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { DCHECK(!result.is(dividend) || !scratch.is(dividend)); // If the divisor is 1, return the dividend. - if (divisor == 1) { + if (divisor == 0) { __ Move(result, dividend); return; } @@ -1190,14 +1179,16 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { __ Dsubu(result, zero_reg, dividend); if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { - DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result, Operand(zero_reg)); + DeoptimizeIf(eq, instr, DeoptimizeReason::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, Deoptimizer::kOverflow, result, Operand(kMaxInt)); + DeoptimizeIf(gt, instr, DeoptimizeReason::kOverflow, result, + Operand(kMaxInt)); } return; } @@ -1225,14 +1216,14 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { DCHECK(!dividend.is(result)); if (divisor == 0) { - DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero); + DeoptimizeIf(al, instr, DeoptimizeReason::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, Deoptimizer::kMinusZero, dividend, + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, dividend, Operand(zero_reg)); } @@ -1277,7 +1268,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { // Check for x / 0. if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { - DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, divisor, + DeoptimizeIf(eq, instr, DeoptimizeReason::kDivisionByZero, divisor, Operand(zero_reg)); } @@ -1285,7 +1276,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { Label left_not_zero; __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); - DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, divisor, + DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero, divisor, Operand(zero_reg)); __ bind(&left_not_zero); } @@ -1295,7 +1286,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, Deoptimizer::kOverflow, divisor, Operand(-1)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kOverflow, divisor, Operand(-1)); __ bind(&left_not_min_int); } @@ -1332,7 +1323,8 @@ void LCodeGen::DoMulS(LMulS* 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, Deoptimizer::kMinusZero, left, Operand(zero_reg)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, left, + Operand(zero_reg)); } switch (constant) { @@ -1350,7 +1342,7 @@ void LCodeGen::DoMulS(LMulS* 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, Deoptimizer::kMinusZero, left, + DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero, left, Operand(zero_reg)); } __ mov(result, zero_reg); @@ -1398,7 +1390,8 @@ void LCodeGen::DoMulS(LMulS* instr) { __ dsra32(scratch, result, 0); __ sra(at, result, 31); __ SmiTag(result); - DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, scratch, Operand(at)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kOverflow, scratch, + Operand(at)); } else { __ SmiUntag(result, left); __ dmul(result, result, right); @@ -1409,7 +1402,7 @@ void LCodeGen::DoMulS(LMulS* instr) { __ Xor(at, left, right); __ Branch(&done, ge, at, Operand(zero_reg)); // Bail out if the result is minus zero. - DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result, + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, result, Operand(zero_reg)); __ bind(&done); } @@ -1434,7 +1427,8 @@ 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, Deoptimizer::kMinusZero, left, Operand(zero_reg)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, left, + Operand(zero_reg)); } switch (constant) { @@ -1452,7 +1446,7 @@ 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, Deoptimizer::kMinusZero, left, + DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero, left, Operand(zero_reg)); } __ mov(result, zero_reg); @@ -1501,7 +1495,8 @@ void LCodeGen::DoMulI(LMulI* instr) { __ dsra32(scratch, result, 0); __ sra(at, result, 31); - DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, scratch, Operand(at)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kOverflow, scratch, + Operand(at)); } else { __ mul(result, left, right); } @@ -1511,7 +1506,7 @@ 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, Deoptimizer::kMinusZero, result, + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, result, Operand(zero_reg)); __ bind(&done); } @@ -1576,10 +1571,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, Deoptimizer::kNegativeValue, result, - Operand(zero_reg)); - DeoptimizeIf(gt, instr, Deoptimizer::kNegativeValue, result, - Operand(kMaxInt)); + DeoptimizeIf(lt, instr, DeoptimizeReason::kNegativeValue, result, + Operand(zero_reg)); + DeoptimizeIf(gt, instr, DeoptimizeReason::kNegativeValue, result, + Operand(kMaxInt)); } break; case Token::SHL: @@ -1614,7 +1609,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) { } else { if (instr->can_deopt()) { __ And(at, left, Operand(0x80000000)); - DeoptimizeIf(ne, instr, Deoptimizer::kNegativeValue, at, + DeoptimizeIf(ne, instr, DeoptimizeReason::kNegativeValue, at, Operand(zero_reg)); } __ Move(result, left); @@ -1846,13 +1841,13 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) { LOperand* left = instr->left(); LOperand* right = instr->right(); HMathMinMax::Operation operation = instr->hydrogen()->operation(); - Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; + Register scratch = scratch1(); if (instr->hydrogen()->representation().IsSmiOrInteger32()) { + Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; Register left_reg = ToRegister(left); Register right_reg = EmitLoadRegister(right, scratch0()); Register result_reg = ToRegister(instr->result()); Label return_right, done; - Register scratch = scratch1(); __ Slt(scratch, left_reg, Operand(right_reg)); if (condition == ge) { __ Movz(result_reg, left_reg, scratch); @@ -1867,43 +1862,19 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) { FPURegister left_reg = ToDoubleRegister(left); FPURegister right_reg = ToDoubleRegister(right); FPURegister result_reg = ToDoubleRegister(instr->result()); - Label check_nan_left, check_zero, return_left, return_right, done; - __ BranchF(&check_zero, &check_nan_left, eq, left_reg, right_reg); - __ BranchF(&return_left, NULL, condition, left_reg, right_reg); - __ Branch(&return_right); - - __ bind(&check_zero); - // left == right != 0. - __ BranchF(&return_left, NULL, ne, left_reg, kDoubleRegZero); - // At this point, both left and right are either 0 or -0. - if (operation == HMathMinMax::kMathMin) { - // The algorithm is: -((-L) + (-R)), which in case of L and R being - // different registers is most efficiently expressed as -((-L) - R). - __ neg_d(left_reg, left_reg); - if (left_reg.is(right_reg)) { - __ add_d(result_reg, left_reg, right_reg); - } else { - __ sub_d(result_reg, left_reg, right_reg); - } - __ neg_d(result_reg, result_reg); + Label nan, done; + if (operation == HMathMinMax::kMathMax) { + __ MaxNaNCheck_d(result_reg, left_reg, right_reg, &nan); } else { - __ add_d(result_reg, left_reg, right_reg); + DCHECK(operation == HMathMinMax::kMathMin); + __ MinNaNCheck_d(result_reg, left_reg, right_reg, &nan); } __ Branch(&done); - __ bind(&check_nan_left); - // left == NaN. - __ BranchF(NULL, &return_left, eq, left_reg, left_reg); - __ bind(&return_right); - if (!right_reg.is(result_reg)) { - __ mov_d(result_reg, right_reg); - } - __ Branch(&done); + __ bind(&nan); + __ LoadRoot(scratch, Heap::kNanValueRootIndex); + __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset)); - __ bind(&return_left); - if (!left_reg.is(result_reg)) { - __ mov_d(result_reg, left_reg); - } __ bind(&done); } } @@ -2110,7 +2081,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, Deoptimizer::kSmi, at, Operand(zero_reg)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, at, Operand(zero_reg)); } const Register map = scratch0(); @@ -2174,7 +2145,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, Deoptimizer::kUnexpectedObject, zero_reg, + DeoptimizeIf(al, instr, DeoptimizeReason::kUnexpectedObject, zero_reg, Operand(zero_reg)); } } @@ -2529,18 +2500,6 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { } -void LCodeGen::DoInstanceOf(LInstanceOf* instr) { - DCHECK(ToRegister(instr->context()).is(cp)); - Label true_label, done; - DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister())); - DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister())); - DCHECK(ToRegister(instr->result()).is(v0)); - - InstanceOfStub stub(isolate()); - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); -} - - void LCodeGen::DoHasInPrototypeChainAndBranch( LHasInPrototypeChainAndBranch* instr) { Register const object = ToRegister(instr->object()); @@ -2567,17 +2526,17 @@ void LCodeGen::DoHasInPrototypeChainAndBranch( FieldMemOperand(object_map, Map::kBitFieldOffset)); __ And(object_instance_type, object_instance_type, Operand(1 << Map::kIsAccessCheckNeeded)); - DeoptimizeIf(ne, instr, Deoptimizer::kAccessCheck, object_instance_type, + DeoptimizeIf(ne, instr, DeoptimizeReason::kAccessCheck, object_instance_type, Operand(zero_reg)); __ lbu(object_instance_type, FieldMemOperand(object_map, Map::kInstanceTypeOffset)); - DeoptimizeIf(eq, instr, Deoptimizer::kProxy, object_instance_type, + DeoptimizeIf(eq, instr, DeoptimizeReason::kProxy, object_instance_type, Operand(JS_PROXY_TYPE)); __ ld(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset)); - EmitTrueBranch(instr, eq, object_prototype, Operand(prototype)); __ LoadRoot(at, Heap::kNullValueRootIndex); EmitFalseBranch(instr, eq, object_prototype, Operand(at)); + EmitTrueBranch(instr, eq, object_prototype, Operand(prototype)); __ Branch(&loop, USE_DELAY_SLOT); __ ld(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset)); // In delay slot. @@ -2674,15 +2633,12 @@ void LCodeGen::EmitVectorStoreICRegisters(T* instr) { void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { DCHECK(ToRegister(instr->context()).is(cp)); - DCHECK(ToRegister(instr->global_object()) - .is(LoadDescriptor::ReceiverRegister())); DCHECK(ToRegister(instr->result()).is(v0)); - __ li(LoadDescriptor::NameRegister(), Operand(instr->name())); EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr); - Handle<Code> ic = CodeFactory::LoadICInOptimizedCode( - isolate(), instr->typeof_mode(), PREMONOMORPHIC) - .code(); + Handle<Code> ic = + CodeFactory::LoadGlobalICInOptimizedCode(isolate(), instr->typeof_mode()) + .code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -2696,7 +2652,7 @@ void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { __ LoadRoot(at, Heap::kTheHoleValueRootIndex); if (instr->hydrogen()->DeoptimizesOnHole()) { - DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(at)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, result, Operand(at)); } else { Label is_not_hole; __ Branch(&is_not_hole, ne, result, Operand(at)); @@ -2720,7 +2676,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { __ LoadRoot(at, Heap::kTheHoleValueRootIndex); if (instr->hydrogen()->DeoptimizesOnHole()) { - DeoptimizeIf(eq, instr, Deoptimizer::kHole, scratch, Operand(at)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, scratch, Operand(at)); } else { __ Branch(&skip_assignment, ne, scratch, Operand(at)); } @@ -2796,10 +2752,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { // Name is always in a2. __ li(LoadDescriptor::NameRegister(), Operand(instr->name())); EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr); - Handle<Code> ic = CodeFactory::LoadICInOptimizedCode( - isolate(), NOT_INSIDE_TYPEOF, - instr->hydrogen()->initialization_state()) - .code(); + Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate()).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -2815,7 +2768,7 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { // Check that the function has a prototype or an initial map. __ LoadRoot(at, Heap::kTheHoleValueRootIndex); - DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(at)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, result, Operand(at)); // If the function does not have an initial map, we're done. Label done; @@ -2945,7 +2898,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { case UINT32_ELEMENTS: __ lw(result, mem_operand); if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { - DeoptimizeIf(Ugreater_equal, instr, Deoptimizer::kNegativeValue, + DeoptimizeIf(Ugreater_equal, instr, DeoptimizeReason::kNegativeValue, result, Operand(0x80000000)); } break; @@ -3008,7 +2961,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { if (instr->hydrogen()->RequiresHoleCheck()) { __ FmoveHigh(scratch, result); - DeoptimizeIf(eq, instr, Deoptimizer::kHole, scratch, + DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, scratch, Operand(static_cast<int32_t>(kHoleNanUpper32))); } } @@ -3062,11 +3015,12 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { if (hinstr->RequiresHoleCheck()) { if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { __ SmiTst(result, scratch); - DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, scratch, + DeoptimizeIf(ne, instr, DeoptimizeReason::kNotASmi, scratch, Operand(zero_reg)); } else { __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); - DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(scratch)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, result, + Operand(scratch)); } } else if (instr->hydrogen()->hole_mode() == CONVERT_HOLE_TO_UNDEFINED) { DCHECK(instr->hydrogen()->elements_kind() == FAST_HOLEY_ELEMENTS); @@ -3080,7 +3034,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { __ LoadRoot(result, Heap::kArrayProtectorRootIndex); // The comparison only needs LS bits of value, which is a smi. __ ld(result, FieldMemOperand(result, Cell::kValueOffset)); - DeoptimizeIf(ne, instr, Deoptimizer::kHole, result, + DeoptimizeIf(ne, instr, DeoptimizeReason::kHole, result, Operand(Smi::FromInt(Isolate::kArrayProtectorValid))); } __ LoadRoot(result, Heap::kUndefinedValueRootIndex); @@ -3148,13 +3102,9 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister())); DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister())); - if (instr->hydrogen()->HasVectorAndSlot()) { - EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr); - } + EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr); - Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode( - isolate(), instr->hydrogen()->initialization_state()) - .code(); + Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3244,10 +3194,10 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { // Deoptimize if the receiver is not a JS object. __ SmiTst(receiver, scratch); - DeoptimizeIf(eq, instr, Deoptimizer::kSmi, scratch, Operand(zero_reg)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, scratch, Operand(zero_reg)); __ GetObjectType(receiver, scratch, scratch); - DeoptimizeIf(lt, instr, Deoptimizer::kNotAJavaScriptObject, scratch, + DeoptimizeIf(lt, instr, DeoptimizeReason::kNotAJavaScriptObject, scratch, Operand(FIRST_JS_RECEIVER_TYPE)); __ Branch(&result_in_receiver); @@ -3281,7 +3231,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, Deoptimizer::kTooManyArguments, length, + DeoptimizeIf(hi, instr, DeoptimizeReason::kTooManyArguments, length, Operand(kArgumentsLimit)); // Push the receiver and use the register to keep the original @@ -3367,6 +3317,8 @@ void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { __ li(scratch0(), instr->hydrogen()->pairs()); __ li(scratch1(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); __ Push(scratch0(), scratch1()); + __ li(scratch0(), instr->hydrogen()->feedback_vector()); + __ Push(scratch0()); CallRuntime(Runtime::kDeclareGlobals, instr); } @@ -3432,7 +3384,8 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { // Deoptimize if not a heap number. __ ld(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); - DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch, Operand(at)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch, + Operand(at)); Label done; Register exponent = scratch0(); @@ -3499,7 +3452,8 @@ 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, Deoptimizer::kOverflow, result, Operand(zero_reg)); + DeoptimizeIf(lt, instr, DeoptimizeReason::kOverflow, result, + Operand(zero_reg)); __ bind(&done); } @@ -3513,7 +3467,8 @@ void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) { __ mov(result, input); __ dsubu(result, zero_reg, input); // Overflow if result is still negative, i.e. 0x80000000 00000000. - DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, result, Operand(zero_reg)); + DeoptimizeIf(lt, instr, DeoptimizeReason::kOverflow, result, + Operand(zero_reg)); __ bind(&done); } @@ -3570,7 +3525,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) { except_flag); // Deopt if the operation did not succeed. - DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag, + DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecisionOrNaN, except_flag, Operand(zero_reg)); if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { @@ -3579,7 +3534,7 @@ 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, Deoptimizer::kMinusZero, scratch1, + DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch1, Operand(zero_reg)); __ bind(&done); } @@ -3613,7 +3568,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) { // The following conversion will not work with numbers // outside of ]-2^32, 2^32[. - DeoptimizeIf(ge, instr, Deoptimizer::kOverflow, scratch, + DeoptimizeIf(ge, instr, DeoptimizeReason::kOverflow, scratch, Operand(HeapNumber::kExponentBias + 32)); // Save the original sign for later comparison. @@ -3631,7 +3586,8 @@ 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, Deoptimizer::kMinusZero, result, Operand(zero_reg)); + DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero, result, + Operand(zero_reg)); } else { Label skip2; // ARM uses 'mi' here, which is 'lt' @@ -3650,7 +3606,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) { double_scratch1, except_flag); - DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag, + DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecisionOrNaN, except_flag, Operand(zero_reg)); if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { @@ -3659,7 +3615,7 @@ 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, Deoptimizer::kMinusZero, scratch, + DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch, Operand(zero_reg)); } __ bind(&done); @@ -3693,10 +3649,8 @@ void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { // Math.sqrt(-Infinity) == NaN Label done; __ Move(temp, static_cast<double>(-V8_INFINITY)); - __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, temp, input); - // Set up Infinity in the delay slot. - // result is overwritten if the branch is not taken. - __ neg_d(result, temp); + __ Neg_d(result, temp); + __ BranchF(&done, NULL, eq, temp, input); // Add +0 to convert -0 to +0. __ add_d(result, input, kDoubleRegZero); @@ -3726,7 +3680,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, Deoptimizer::kNotAHeapNumber, a7, Operand(at)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, a7, Operand(at)); __ bind(&no_deopt); MathPowStub stub(isolate(), MathPowStub::TAGGED); __ CallStub(&stub); @@ -3740,26 +3694,32 @@ void LCodeGen::DoPower(LPower* instr) { } } +void LCodeGen::DoMathCos(LMathCos* instr) { + __ PrepareCallCFunction(0, 1, scratch0()); + __ MovToFloatParameter(ToDoubleRegister(instr->value())); + __ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 0, 1); + __ MovFromFloatResult(ToDoubleRegister(instr->result())); +} -void LCodeGen::DoMathExp(LMathExp* instr) { - DoubleRegister input = ToDoubleRegister(instr->value()); - DoubleRegister result = ToDoubleRegister(instr->result()); - DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp()); - DoubleRegister double_scratch2 = double_scratch0(); - Register temp1 = ToRegister(instr->temp1()); - Register temp2 = ToRegister(instr->temp2()); +void LCodeGen::DoMathSin(LMathSin* instr) { + __ PrepareCallCFunction(0, 1, scratch0()); + __ MovToFloatParameter(ToDoubleRegister(instr->value())); + __ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 0, 1); + __ MovFromFloatResult(ToDoubleRegister(instr->result())); +} - MathExpGenerator::EmitMathExp( - masm(), input, result, double_scratch1, double_scratch2, - temp1, temp2, scratch0()); +void LCodeGen::DoMathExp(LMathExp* instr) { + __ PrepareCallCFunction(0, 1, scratch0()); + __ MovToFloatParameter(ToDoubleRegister(instr->value())); + __ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 0, 1); + __ MovFromFloatResult(ToDoubleRegister(instr->result())); } void LCodeGen::DoMathLog(LMathLog* instr) { __ PrepareCallCFunction(0, 1, scratch0()); __ MovToFloatParameter(ToDoubleRegister(instr->value())); - __ CallCFunction(ExternalReference::math_log_double_function(isolate()), - 0, 1); + __ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1); __ MovFromFloatResult(ToDoubleRegister(instr->result())); } @@ -3782,7 +3742,9 @@ void LCodeGen::PrepareForTailCall(const ParameterCount& actual, #endif if (FLAG_code_comments) { if (actual.is_reg()) { - Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString()); + Comment(";;; PrepareForTailCall, actual: %s {", + RegisterConfiguration::Crankshaft()->GetGeneralRegisterName( + actual.reg().code())); } else { Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate()); } @@ -3886,14 +3848,8 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) { DCHECK(ToRegister(instr->result()).is(v0)); __ li(a0, Operand(instr->arity())); - if (instr->arity() == 1) { - // We only need the allocation site for the case we have a length argument. - // The case may bail out to the runtime, which will determine the correct - // elements kind with the site. - __ li(a2, instr->hydrogen()->site()); - } else { - __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); - } + __ li(a2, instr->hydrogen()->site()); + ElementsKind kind = instr->hydrogen()->elements_kind(); AllocationSiteOverrideMode override_mode = (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) @@ -3925,7 +3881,7 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) { CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); __ bind(&done); } else { - ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode); + ArrayNArgumentsConstructorStub stub(isolate()); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); } } @@ -4056,14 +4012,12 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister())); DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister())); - if (instr->hydrogen()->HasVectorAndSlot()) { - EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr); - } + EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr); __ li(StoreDescriptor::NameRegister(), Operand(instr->name())); - Handle<Code> ic = CodeFactory::StoreICInOptimizedCode( - isolate(), instr->language_mode(), - instr->hydrogen()->initialization_state()).code(); + Handle<Code> ic = + CodeFactory::StoreICInOptimizedCode(isolate(), instr->language_mode()) + .code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -4086,7 +4040,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { __ stop("eliminated bounds check failed"); __ bind(&done); } else { - DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds, reg, operand); + DeoptimizeIf(cc, instr, DeoptimizeReason::kOutOfBounds, reg, operand); } } @@ -4306,13 +4260,11 @@ void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister())); DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister())); - if (instr->hydrogen()->HasVectorAndSlot()) { - EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr); - } + EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr); Handle<Code> ic = CodeFactory::KeyedStoreICInOptimizedCode( - isolate(), instr->language_mode(), - instr->hydrogen()->initialization_state()).code(); + isolate(), instr->language_mode()) + .code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -4391,14 +4343,21 @@ void LCodeGen::DoDeferredMaybeGrowElements(LMaybeGrowElements* instr) { LOperand* key = instr->key(); if (key->IsConstantOperand()) { - __ li(a3, Operand(ToSmi(LConstantOperand::cast(key)))); + LConstantOperand* constant_key = LConstantOperand::cast(key); + int32_t int_key = ToInteger32(constant_key); + if (Smi::IsValid(int_key)) { + __ li(a3, Operand(Smi::FromInt(int_key))); + } else { + // We should never get here at runtime because there is a smi check on + // the key before this point. + __ stop("expected smi"); + } } else { __ mov(a3, ToRegister(key)); __ SmiTag(a3); } - GrowArrayElementsStub stub(isolate(), instr->hydrogen()->is_js_array(), - instr->hydrogen()->kind()); + GrowArrayElementsStub stub(isolate(), instr->hydrogen()->kind()); __ mov(a0, result); __ CallStub(&stub); RecordSafepointWithLazyDeopt( @@ -4408,7 +4367,7 @@ void LCodeGen::DoDeferredMaybeGrowElements(LMaybeGrowElements* instr) { // Deopt on smi, which means the elements array changed to dictionary mode. __ SmiTst(result, at); - DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, at, Operand(zero_reg)); } @@ -4440,8 +4399,7 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { DCHECK(ToRegister(instr->context()).is(cp)); PushSafepointRegistersScope scope(this); __ li(a1, Operand(to_map)); - bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE; - TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array); + TransitionElementsKindStub stub(isolate(), from_kind, to_kind); __ CallStub(&stub); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kLazyDeopt); @@ -4455,7 +4413,7 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { Register temp = ToRegister(instr->temp()); Label no_memento_found; __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); - DeoptimizeIf(al, instr, Deoptimizer::kMementoFound); + DeoptimizeIf(al, instr, DeoptimizeReason::kMementoFound); __ bind(&no_memento_found); } @@ -4662,7 +4620,7 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, if (FLAG_inline_new) { __ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex); - __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow, TAG_RESULT); + __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow); __ Branch(&done); } @@ -4675,13 +4633,10 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, __ mov(dst, zero_reg); // Preserve the value of all registers. PushSafepointRegistersScope scope(this); - - // NumberTagI and NumberTagD use the context from the frame, rather than - // the environment's HContext or HInlinedContext value. - // They only call Runtime::kAllocateHeapNumber. - // The corresponding HChange instructions are added in a phase that does - // not have easy access to the local context. - __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); + // Reset the context register. + if (!dst.is(cp)) { + __ mov(cp, zero_reg); + } __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); @@ -4717,15 +4672,12 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) { if (FLAG_inline_new) { __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); // We want the untagged address first for performance - __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), - DONT_TAG_RESULT); + __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); } else { __ Branch(deferred->entry()); } __ bind(deferred->exit()); - __ sdc1(input_reg, MemOperand(reg, HeapNumber::kValueOffset)); - // Now that we have finished with the object's real address tag it - __ Daddu(reg, reg, kHeapObjectTag); + __ sdc1(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset)); } @@ -4737,16 +4689,13 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { __ mov(reg, zero_reg); PushSafepointRegistersScope scope(this); - // NumberTagI and NumberTagD use the context from the frame, rather than - // the environment's HContext or HInlinedContext value. - // They only call Runtime::kAllocateHeapNumber. - // The corresponding HChange instructions are added in a phase that does - // not have easy access to the local context. - __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); + // Reset the context register. + if (!reg.is(cp)) { + __ mov(cp, zero_reg); + } __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); - __ Dsubu(v0, v0, kHeapObjectTag); __ StoreToSafepointRegisterSlot(v0, reg); } @@ -4758,12 +4707,12 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) { if (hchange->CheckFlag(HValue::kCanOverflow) && hchange->value()->CheckFlag(HValue::kUint32)) { __ And(at, input, Operand(0x80000000)); - DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, at, Operand(zero_reg)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kOverflow, at, Operand(zero_reg)); } if (hchange->CheckFlag(HValue::kCanOverflow) && !hchange->value()->CheckFlag(HValue::kUint32)) { __ SmiTagCheckOverflow(output, input, at); - DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, at, Operand(zero_reg)); + DeoptimizeIf(lt, instr, DeoptimizeReason::kOverflow, at, Operand(zero_reg)); } else { __ SmiTag(output, input); } @@ -4779,7 +4728,8 @@ 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, Deoptimizer::kNotASmi, scratch, Operand(zero_reg)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kNotASmi, scratch, + Operand(zero_reg)); } else { __ SmiUntag(result, input); } @@ -4804,7 +4754,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, if (can_convert_undefined_to_nan) { __ Branch(&convert, ne, scratch, Operand(at)); } else { - DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch, + DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch, Operand(at)); } // Load heap number. @@ -4813,7 +4763,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, Deoptimizer::kMinusZero, scratch, + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, scratch, Operand(HeapNumber::kSignMask)); } __ Branch(&done); @@ -4821,8 +4771,8 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, __ bind(&convert); // Convert undefined (and hole) to NaN. __ LoadRoot(at, Heap::kUndefinedValueRootIndex); - DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined, input_reg, - Operand(at)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined, + input_reg, Operand(at)); __ LoadRoot(scratch, Heap::kNanValueRootIndex); __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset)); __ Branch(&done); @@ -4886,12 +4836,12 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { __ bind(&check_false); __ LoadRoot(at, Heap::kFalseValueRootIndex); - DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedBoolean, + DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefinedBoolean, scratch2, Operand(at)); __ Branch(USE_DELAY_SLOT, &done); __ mov(input_reg, zero_reg); // In delay slot. } else { - DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch1, + DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch1, Operand(at)); // Load the double value. @@ -4907,7 +4857,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { except_flag, kCheckForInexactConversion); - DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag, + DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecisionOrNaN, except_flag, Operand(zero_reg)); if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { @@ -4915,7 +4865,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { __ mfhc1(scratch1, double_scratch); // Get exponent/sign bits. __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); - DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1, + DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch1, Operand(zero_reg)); } } @@ -4992,7 +4942,7 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { kCheckForInexactConversion); // Deopt if the operation did not succeed (except_flag != 0). - DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag, + DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecisionOrNaN, except_flag, Operand(zero_reg)); if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { @@ -5000,7 +4950,7 @@ 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, Deoptimizer::kMinusZero, scratch1, + DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch1, Operand(zero_reg)); __ bind(&done); } @@ -5027,7 +4977,7 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { kCheckForInexactConversion); // Deopt if the operation did not succeed (except_flag != 0). - DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag, + DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecisionOrNaN, except_flag, Operand(zero_reg)); if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { @@ -5035,7 +4985,7 @@ 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, Deoptimizer::kMinusZero, scratch1, + DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch1, Operand(zero_reg)); __ bind(&done); } @@ -5047,7 +4997,7 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { void LCodeGen::DoCheckSmi(LCheckSmi* instr) { LOperand* input = instr->value(); __ SmiTst(ToRegister(input), at); - DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, at, Operand(zero_reg)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kNotASmi, at, Operand(zero_reg)); } @@ -5055,7 +5005,7 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { if (!instr->hydrogen()->value()->type().IsHeapObject()) { LOperand* input = instr->value(); __ SmiTst(ToRegister(input), at); - DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, at, Operand(zero_reg)); } } @@ -5068,7 +5018,8 @@ void LCodeGen::DoCheckArrayBufferNotNeutered( __ ld(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset)); __ lw(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset)); __ And(at, scratch, 1 << JSArrayBuffer::WasNeutered::kShift); - DeoptimizeIf(ne, instr, Deoptimizer::kOutOfBounds, at, Operand(zero_reg)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kOutOfBounds, at, + Operand(zero_reg)); } @@ -5085,14 +5036,14 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { // If there is only one type in the interval check for equality. if (first == last) { - DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType, scratch, + DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongInstanceType, scratch, Operand(first)); } else { - DeoptimizeIf(lo, instr, Deoptimizer::kWrongInstanceType, scratch, + DeoptimizeIf(lo, instr, DeoptimizeReason::kWrongInstanceType, scratch, Operand(first)); // Omit check for the last type. if (last != LAST_TYPE) { - DeoptimizeIf(hi, instr, Deoptimizer::kWrongInstanceType, scratch, + DeoptimizeIf(hi, instr, DeoptimizeReason::kWrongInstanceType, scratch, Operand(last)); } } @@ -5104,11 +5055,11 @@ 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, Deoptimizer::kWrongInstanceType, - at, Operand(zero_reg)); + DeoptimizeIf(tag == 0 ? ne : eq, instr, + DeoptimizeReason::kWrongInstanceType, at, Operand(zero_reg)); } else { __ And(scratch, scratch, Operand(mask)); - DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType, scratch, + DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongInstanceType, scratch, Operand(tag)); } } @@ -5124,9 +5075,10 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) { Handle<Cell> cell = isolate()->factory()->NewCell(object); __ li(at, Operand(cell)); __ ld(at, FieldMemOperand(at, Cell::kValueOffset)); - DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch, reg, Operand(at)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kValueMismatch, reg, Operand(at)); } else { - DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch, reg, Operand(object)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kValueMismatch, reg, + Operand(object)); } } @@ -5142,7 +5094,7 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { __ StoreToSafepointRegisterSlot(v0, scratch0()); } __ SmiTst(scratch0(), at); - DeoptimizeIf(eq, instr, Deoptimizer::kInstanceMigrationFailed, at, + DeoptimizeIf(eq, instr, DeoptimizeReason::kInstanceMigrationFailed, at, Operand(zero_reg)); } @@ -5197,7 +5149,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) { if (instr->hydrogen()->HasMigrationTarget()) { __ Branch(deferred->entry(), ne, map_reg, Operand(map)); } else { - DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, map_reg, Operand(map)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongMap, map_reg, Operand(map)); } __ bind(&success); @@ -5235,7 +5187,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { // Check for undefined. Undefined is converted to zero for clamping // conversions. - DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined, input_reg, + DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined, input_reg, Operand(factory()->undefined_value())); __ mov(result_reg, zero_reg); __ jmp(&done); @@ -5254,25 +5206,6 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { } -void LCodeGen::DoDoubleBits(LDoubleBits* instr) { - DoubleRegister value_reg = ToDoubleRegister(instr->value()); - Register result_reg = ToRegister(instr->result()); - if (instr->hydrogen()->bits() == HDoubleBits::HIGH) { - __ FmoveHigh(result_reg, value_reg); - } else { - __ FmoveLow(result_reg, value_reg); - } -} - - -void LCodeGen::DoConstructDouble(LConstructDouble* instr) { - Register hi_reg = ToRegister(instr->hi()); - Register lo_reg = ToRegister(instr->lo()); - DoubleRegister result_reg = ToDoubleRegister(instr->result()); - __ Move(result_reg, lo_reg, hi_reg); -} - - void LCodeGen::DoAllocate(LAllocate* instr) { class DeferredAllocate final : public LDeferredCode { public: @@ -5293,7 +5226,7 @@ void LCodeGen::DoAllocate(LAllocate* instr) { Register scratch2 = ToRegister(instr->temp2()); // Allocate memory for the object. - AllocationFlags flags = TAG_OBJECT; + AllocationFlags flags = NO_ALLOCATION_FLAGS; if (instr->hydrogen()->MustAllocateDoubleAligned()) { flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); } @@ -5301,6 +5234,12 @@ void LCodeGen::DoAllocate(LAllocate* instr) { DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); flags = static_cast<AllocationFlags>(flags | PRETENURE); } + + if (instr->hydrogen()->IsAllocationFoldingDominator()) { + flags = static_cast<AllocationFlags>(flags | ALLOCATION_FOLDING_DOMINATOR); + } + DCHECK(!instr->hydrogen()->IsAllocationFolded()); + if (instr->size()->IsConstantOperand()) { int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); CHECK(size <= Page::kMaxRegularHeapObjectSize); @@ -5371,6 +5310,49 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) { CallRuntimeFromDeferred( Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); __ StoreToSafepointRegisterSlot(v0, result); + + if (instr->hydrogen()->IsAllocationFoldingDominator()) { + AllocationFlags allocation_flags = NO_ALLOCATION_FLAGS; + if (instr->hydrogen()->IsOldSpaceAllocation()) { + DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); + allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE); + } + // If the allocation folding dominator allocate triggered a GC, allocation + // happend in the runtime. We have to reset the top pointer to virtually + // undo the allocation. + ExternalReference allocation_top = + AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags); + Register top_address = scratch0(); + __ Dsubu(v0, v0, Operand(kHeapObjectTag)); + __ li(top_address, Operand(allocation_top)); + __ sd(v0, MemOperand(top_address)); + __ Daddu(v0, v0, Operand(kHeapObjectTag)); + } +} + +void LCodeGen::DoFastAllocate(LFastAllocate* instr) { + DCHECK(instr->hydrogen()->IsAllocationFolded()); + DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator()); + Register result = ToRegister(instr->result()); + Register scratch1 = ToRegister(instr->temp1()); + Register scratch2 = ToRegister(instr->temp2()); + + AllocationFlags flags = ALLOCATION_FOLDED; + if (instr->hydrogen()->MustAllocateDoubleAligned()) { + flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); + } + if (instr->hydrogen()->IsOldSpaceAllocation()) { + DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); + flags = static_cast<AllocationFlags>(flags | PRETENURE); + } + if (instr->size()->IsConstantOperand()) { + int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); + CHECK(size <= Page::kMaxRegularHeapObjectSize); + __ FastAllocate(size, result, scratch1, scratch2, flags); + } else { + Register size = ToRegister(instr->size()); + __ FastAllocate(size, result, scratch1, scratch2, flags); + } } @@ -5383,8 +5365,8 @@ void LCodeGen::DoTypeof(LTypeof* instr) { __ li(v0, Operand(isolate()->factory()->number_string())); __ jmp(&end); __ bind(&do_call); - TypeofStub stub(isolate()); - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); + Callable callable = CodeFactory::Typeof(isolate()); + CallCode(callable.code(), RelocInfo::CODE_TARGET, instr); __ bind(&end); } @@ -5674,7 +5656,8 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); __ ld(result, FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); - DeoptimizeIf(eq, instr, Deoptimizer::kNoCache, result, Operand(zero_reg)); + DeoptimizeIf(eq, instr, DeoptimizeReason::kNoCache, result, + Operand(zero_reg)); __ bind(&done); } @@ -5684,7 +5667,8 @@ void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { Register object = ToRegister(instr->value()); Register map = ToRegister(instr->map()); __ ld(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); - DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, map, Operand(scratch0())); + DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongMap, map, + Operand(scratch0())); } |