diff options
Diffstat (limited to 'deps/v8/src/crankshaft/mips/lithium-codegen-mips.cc')
-rw-r--r-- | deps/v8/src/crankshaft/mips/lithium-codegen-mips.cc | 503 |
1 files changed, 241 insertions, 262 deletions
diff --git a/deps/v8/src/crankshaft/mips/lithium-codegen-mips.cc b/deps/v8/src/crankshaft/mips/lithium-codegen-mips.cc index f1717ca474..fa345e5173 100644 --- a/deps/v8/src/crankshaft/mips/lithium-codegen-mips.cc +++ b/deps/v8/src/crankshaft/mips/lithium-codegen-mips.cc @@ -34,8 +34,6 @@ #include "src/crankshaft/mips/lithium-gap-resolver-mips.h" #include "src/ic/ic.h" #include "src/ic/stub-cache.h" -#include "src/profiler/cpu-profiler.h" - namespace v8 { namespace internal { @@ -184,14 +182,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); @@ -200,10 +196,11 @@ void LCodeGen::DoPrologue(LPrologue* instr) { __ mov(cp, v0); __ sw(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; @@ -330,8 +327,6 @@ bool LCodeGen::GenerateJumpTable() { } else { __ Call(&call_deopt_entry); } - info()->LogDeoptCallPosition(masm()->pc_offset(), - table_entry->deopt_info.inlining_id); } if (needs_frame.is_linked()) { @@ -745,9 +740,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(); @@ -789,7 +783,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 @@ -798,13 +792,12 @@ 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(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()); @@ -813,10 +806,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; @@ -877,13 +869,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)"; @@ -955,7 +940,7 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { __ subu(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); @@ -988,7 +973,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); } @@ -1008,7 +993,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)); } @@ -1018,7 +1003,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); @@ -1030,7 +1016,7 @@ 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, Deoptimizer::kMinusZero, result_reg, + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, result_reg, Operand(zero_reg)); } __ bind(&done); @@ -1047,19 +1033,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. @@ -1096,7 +1084,7 @@ 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, Deoptimizer::kMinusZero, dividend, + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, dividend, Operand(zero_reg)); } @@ -1106,7 +1094,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) { if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { __ Mul(scratch0(), result, Operand(divisor)); __ Subu(scratch0(), scratch0(), dividend); - DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, scratch0(), + DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecision, scratch0(), Operand(zero_reg)); } } @@ -1126,7 +1114,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)); } @@ -1134,7 +1122,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); } @@ -1144,12 +1132,12 @@ 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); } if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { - DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, remainder, + DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecision, remainder, Operand(zero_reg)); } } @@ -1196,14 +1184,15 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { __ Subu(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)); } // 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, Deoptimizer::kOverflow, scratch, + DeoptimizeIf(ge, instr, DeoptimizeReason::kOverflow, scratch, Operand(zero_reg)); } return; @@ -1239,7 +1228,7 @@ 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, Deoptimizer::kMinusZero, dividend, + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, dividend, Operand(zero_reg)); } @@ -1284,7 +1273,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)); } @@ -1292,7 +1281,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); } @@ -1302,7 +1291,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); } @@ -1333,7 +1322,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) { @@ -1351,7 +1341,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); @@ -1403,7 +1393,8 @@ void LCodeGen::DoMulI(LMulI* instr) { __ Mul(scratch, result, left, right); } __ sra(at, result, 31); - DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, scratch, Operand(at)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kOverflow, scratch, + Operand(at)); } else { if (instr->hydrogen()->representation().IsSmi()) { __ SmiUntag(result, left); @@ -1418,7 +1409,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); } @@ -1483,7 +1474,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) { case Token::SHR: __ srlv(result, left, ToRegister(right_op)); if (instr->can_deopt()) { - DeoptimizeIf(lt, instr, Deoptimizer::kNegativeValue, result, + DeoptimizeIf(lt, instr, DeoptimizeReason::kNegativeValue, result, Operand(zero_reg)); } break; @@ -1519,7 +1510,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); @@ -1535,7 +1526,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) { } else { __ SmiTagCheckOverflow(result, left, scratch); } - DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, scratch, + DeoptimizeIf(lt, instr, DeoptimizeReason::kOverflow, scratch, Operand(zero_reg)); } else { __ sll(result, left, shift_count); @@ -1728,13 +1719,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); @@ -1749,43 +1740,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); } } @@ -1992,7 +1959,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(); @@ -2056,7 +2023,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)); } } @@ -2409,16 +2376,6 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { } -void LCodeGen::DoInstanceOf(LInstanceOf* instr) { - DCHECK(ToRegister(instr->context()).is(cp)); - 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()); @@ -2445,18 +2402,18 @@ 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)); // Deoptimize for proxies. __ 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)); __ lw(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(USE_DELAY_SLOT, &loop); __ lw(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset)); } @@ -2552,15 +2509,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); } @@ -2574,7 +2528,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)); @@ -2598,7 +2552,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)); } @@ -2659,10 +2613,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); } @@ -2678,7 +2629,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; @@ -2798,7 +2749,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; @@ -2853,7 +2804,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { if (instr->hydrogen()->RequiresHoleCheck()) { __ lw(scratch, MemOperand(scratch, kHoleNanUpper32Offset)); - DeoptimizeIf(eq, instr, Deoptimizer::kHole, scratch, + DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, scratch, Operand(kHoleNanUpper32)); } } @@ -2888,11 +2839,12 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { if (instr->hydrogen()->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); @@ -2905,7 +2857,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { // it needs to bail out. __ LoadRoot(result, Heap::kArrayProtectorRootIndex); __ lw(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); @@ -2967,13 +2919,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); } @@ -3059,10 +3007,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); @@ -3096,7 +3044,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 @@ -3182,6 +3130,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); } @@ -3247,7 +3197,8 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { // Deoptimize if not a heap number. __ lw(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(); @@ -3314,7 +3265,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); } @@ -3369,7 +3321,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)) { @@ -3378,7 +3330,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) { __ Branch(&done, ne, result, Operand(zero_reg)); __ Mfhc1(scratch1, input); __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); - DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1, + DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch1, Operand(zero_reg)); __ bind(&done); } @@ -3412,7 +3364,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. @@ -3427,7 +3379,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' @@ -3446,7 +3399,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)) { @@ -3455,7 +3408,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) { __ bind(&check_sign_on_zero); __ Mfhc1(scratch, input); __ And(scratch, scratch, Operand(HeapNumber::kSignMask)); - DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch, + DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch, Operand(zero_reg)); } __ bind(&done); @@ -3489,10 +3442,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); @@ -3522,7 +3473,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, Deoptimizer::kNotAHeapNumber, t3, Operand(at)); + DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, t3, Operand(at)); __ bind(&no_deopt); MathPowStub stub(isolate(), MathPowStub::TAGGED); __ CallStub(&stub); @@ -3536,26 +3487,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())); } @@ -3578,7 +3535,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()); } @@ -3685,14 +3644,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) @@ -3724,7 +3677,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); } } @@ -3846,14 +3799,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); } @@ -3876,7 +3827,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); } } @@ -4074,13 +4025,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); } @@ -4159,14 +4108,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( @@ -4176,7 +4132,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)); } @@ -4208,8 +4164,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); @@ -4456,7 +4411,7 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, if (FLAG_inline_new) { __ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex); - __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow, DONT_TAG_RESULT); + __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow); __ Branch(&done); } @@ -4470,26 +4425,20 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, // 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. - __ lw(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); - __ Subu(v0, v0, kHeapObjectTag); __ StoreToSafepointRegisterSlot(v0, dst); } - // Done. Put the value in dbl_scratch into the value of the allocated heap // number. __ bind(&done); - __ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset)); - __ Addu(dst, dst, kHeapObjectTag); + __ sdc1(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset)); } @@ -4514,16 +4463,13 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) { DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, 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)); + __ sdc1(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset)); // Now that we have finished with the object's real address tag it - __ Addu(reg, reg, kHeapObjectTag); } @@ -4535,16 +4481,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. - __ lw(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); - __ Subu(v0, v0, kHeapObjectTag); __ StoreToSafepointRegisterSlot(v0, reg); } @@ -4556,12 +4499,12 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) { if (hchange->CheckFlag(HValue::kCanOverflow) && hchange->value()->CheckFlag(HValue::kUint32)) { __ And(at, input, Operand(0xc0000000)); - 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); } @@ -4577,7 +4520,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); } @@ -4602,7 +4546,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. @@ -4611,7 +4555,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, Deoptimizer::kMinusZero, scratch, + DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, scratch, Operand(HeapNumber::kSignMask)); } __ Branch(&done); @@ -4619,8 +4563,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); @@ -4684,12 +4628,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. @@ -4705,7 +4649,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)) { @@ -4713,7 +4657,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { __ Mfhc1(scratch1, double_scratch); __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); - DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1, + DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch1, Operand(zero_reg)); } } @@ -4790,7 +4734,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)) { @@ -4798,7 +4742,7 @@ 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, Deoptimizer::kMinusZero, scratch1, + DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch1, Operand(zero_reg)); __ bind(&done); } @@ -4825,7 +4769,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)) { @@ -4833,20 +4777,21 @@ 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, Deoptimizer::kMinusZero, scratch1, + DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch1, Operand(zero_reg)); __ bind(&done); } } __ SmiTagCheckOverflow(result_reg, result_reg, scratch1); - DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, scratch1, Operand(zero_reg)); + DeoptimizeIf(lt, instr, DeoptimizeReason::kOverflow, scratch1, + Operand(zero_reg)); } 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)); } @@ -4854,7 +4799,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)); } } @@ -4867,7 +4812,8 @@ void LCodeGen::DoCheckArrayBufferNotNeutered( __ lw(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)); } @@ -4884,14 +4830,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)); } } @@ -4903,11 +4849,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)); } } @@ -4923,9 +4869,10 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) { Handle<Cell> cell = isolate()->factory()->NewCell(object); __ li(at, Operand(cell)); __ lw(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)); } } @@ -4941,7 +4888,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)); } @@ -4996,7 +4943,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); @@ -5034,7 +4981,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); @@ -5053,25 +5000,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: @@ -5092,7 +5020,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); } @@ -5100,6 +5028,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); @@ -5168,6 +5102,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(); + __ Subu(v0, v0, Operand(kHeapObjectTag)); + __ li(top_address, Operand(allocation_top)); + __ sw(v0, MemOperand(top_address)); + __ Addu(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); + } } @@ -5180,8 +5157,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); } @@ -5470,7 +5447,8 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); __ lw(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); } @@ -5480,7 +5458,8 @@ void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { Register object = ToRegister(instr->value()); Register map = ToRegister(instr->map()); __ lw(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); - DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, map, Operand(scratch0())); + DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongMap, map, + Operand(scratch0())); } |