diff options
Diffstat (limited to 'deps/v8/src/ia32/lithium-codegen-ia32.cc')
-rw-r--r-- | deps/v8/src/ia32/lithium-codegen-ia32.cc | 538 |
1 files changed, 280 insertions, 258 deletions
diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc index 245dcdc482..1d7c8c1b0c 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.cc +++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc @@ -6,20 +6,22 @@ #if V8_TARGET_ARCH_IA32 +#include "src/base/bits.h" +#include "src/code-factory.h" #include "src/code-stubs.h" #include "src/codegen.h" #include "src/deoptimizer.h" #include "src/hydrogen-osr.h" #include "src/ia32/lithium-codegen-ia32.h" -#include "src/ic.h" -#include "src/stub-cache.h" +#include "src/ic/ic.h" +#include "src/ic/stub-cache.h" namespace v8 { namespace internal { // When invoking builtins, we need to record the safepoint in the middle of // the invoke instruction sequence generated by the macro assembler. -class SafepointGenerator V8_FINAL : public CallWrapper { +class SafepointGenerator FINAL : public CallWrapper { public: SafepointGenerator(LCodeGen* codegen, LPointerMap* pointers, @@ -29,9 +31,9 @@ class SafepointGenerator V8_FINAL : public CallWrapper { deopt_mode_(mode) {} virtual ~SafepointGenerator() {} - virtual void BeforeCall(int call_size) const V8_OVERRIDE {} + virtual void BeforeCall(int call_size) const OVERRIDE {} - virtual void AfterCall() const V8_OVERRIDE { + virtual void AfterCall() const OVERRIDE { codegen_->RecordSafepoint(pointers_, deopt_mode_); } @@ -381,16 +383,11 @@ bool LCodeGen::GenerateJumpTable() { Comment(";;; -------------------- Jump table --------------------"); } for (int i = 0; i < jump_table_.length(); i++) { - __ bind(&jump_table_[i].label); - Address entry = jump_table_[i].address; - Deoptimizer::BailoutType type = jump_table_[i].bailout_type; - int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); - if (id == Deoptimizer::kNotDeoptimizationEntry) { - Comment(";;; jump table entry %d.", i); - } else { - Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); - } - if (jump_table_[i].needs_frame) { + Deoptimizer::JumpTableEntry* table_entry = &jump_table_[i]; + __ bind(&table_entry->label); + Address entry = table_entry->address; + DeoptComment(table_entry->reason); + if (table_entry->needs_frame) { DCHECK(!info()->saves_caller_doubles()); __ push(Immediate(ExternalReference::ForDeoptEntry(entry))); if (needs_frame.is_bound()) { @@ -823,9 +820,10 @@ void LCodeGen::RegisterEnvironmentForDeoptimization( } -void LCodeGen::DeoptimizeIf(Condition cc, - LEnvironment* environment, +void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr, + const char* detail, Deoptimizer::BailoutType bailout_type) { + LEnvironment* environment = instr->environment(); RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); DCHECK(environment->HasBeenRegistered()); int id = environment->deoptimization_index(); @@ -865,19 +863,19 @@ void LCodeGen::DeoptimizeIf(Condition cc, __ bind(&done); } + Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(), + instr->Mnemonic(), detail); DCHECK(info()->IsStub() || frame_is_built_); if (cc == no_condition && frame_is_built_) { + DeoptComment(reason); __ call(entry, RelocInfo::RUNTIME_ENTRY); } else { + Deoptimizer::JumpTableEntry table_entry(entry, reason, 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 (jump_table_.is_empty() || - jump_table_.last().address != entry || - jump_table_.last().needs_frame != !frame_is_built_ || - jump_table_.last().bailout_type != bailout_type) { - Deoptimizer::JumpTableEntry table_entry(entry, - bailout_type, - !frame_is_built_); + !table_entry.IsEquivalentTo(jump_table_.last())) { jump_table_.Add(table_entry, zone()); } if (cc == no_condition) { @@ -889,12 +887,12 @@ void LCodeGen::DeoptimizeIf(Condition cc, } -void LCodeGen::DeoptimizeIf(Condition cc, - LEnvironment* environment) { +void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr, + const char* detail) { Deoptimizer::BailoutType bailout_type = info()->IsStub() ? Deoptimizer::LAZY : Deoptimizer::EAGER; - DeoptimizeIf(cc, environment, bailout_type); + DeoptimizeIf(cc, instr, detail, bailout_type); } @@ -902,7 +900,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { int length = deoptimizations_.length(); if (length == 0) return; Handle<DeoptimizationInputData> data = - DeoptimizationInputData::New(isolate(), length, 0, TENURED); + DeoptimizationInputData::New(isolate(), length, TENURED); Handle<ByteArray> translations = translations_.CreateByteArray(isolate()->factory()); @@ -1123,7 +1121,7 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { __ and_(dividend, mask); __ neg(dividend); if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "minus zero"); } __ jmp(&done, Label::kNear); } @@ -1140,7 +1138,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) { DCHECK(ToRegister(instr->result()).is(eax)); if (divisor == 0) { - DeoptimizeIf(no_condition, instr->environment()); + DeoptimizeIf(no_condition, instr, "division by zero"); return; } @@ -1155,7 +1153,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) { Label remainder_not_zero; __ j(not_zero, &remainder_not_zero, Label::kNear); __ cmp(dividend, Immediate(0)); - DeoptimizeIf(less, instr->environment()); + DeoptimizeIf(less, instr, "minus zero"); __ bind(&remainder_not_zero); } } @@ -1177,7 +1175,7 @@ void LCodeGen::DoModI(LModI* instr) { // deopt in this case because we can't return a NaN. if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { __ test(right_reg, Operand(right_reg)); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "division by zero"); } // Check for kMinInt % -1, idiv would signal a divide error. We @@ -1188,7 +1186,7 @@ void LCodeGen::DoModI(LModI* instr) { __ j(not_equal, &no_overflow_possible, Label::kNear); __ cmp(right_reg, -1); if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { - DeoptimizeIf(equal, instr->environment()); + DeoptimizeIf(equal, instr, "minus zero"); } else { __ j(not_equal, &no_overflow_possible, Label::kNear); __ Move(result_reg, Immediate(0)); @@ -1207,7 +1205,7 @@ void LCodeGen::DoModI(LModI* instr) { __ j(not_sign, &positive_left, Label::kNear); __ idiv(right_reg); __ test(result_reg, Operand(result_reg)); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "minus zero"); __ jmp(&done, Label::kNear); __ bind(&positive_left); } @@ -1220,26 +1218,26 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { Register dividend = ToRegister(instr->dividend()); int32_t divisor = instr->divisor(); Register result = ToRegister(instr->result()); - DCHECK(divisor == kMinInt || IsPowerOf2(Abs(divisor))); + DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); DCHECK(!result.is(dividend)); // Check for (0 / -x) that will produce negative zero. HDiv* hdiv = instr->hydrogen(); if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { __ test(dividend, dividend); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "minus zero"); } // Check for (kMinInt / -1). if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { __ cmp(dividend, kMinInt); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "overflow"); } // Deoptimize if remainder will not be 0. if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && divisor != 1 && divisor != -1) { int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); __ test(dividend, Immediate(mask)); - DeoptimizeIf(not_zero, instr->environment()); + DeoptimizeIf(not_zero, instr, "lost precision"); } __ Move(result, dividend); int32_t shift = WhichPowerOf2Abs(divisor); @@ -1260,7 +1258,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) { DCHECK(ToRegister(instr->result()).is(edx)); if (divisor == 0) { - DeoptimizeIf(no_condition, instr->environment()); + DeoptimizeIf(no_condition, instr, "division by zero"); return; } @@ -1268,7 +1266,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) { HDiv* hdiv = instr->hydrogen(); if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { __ test(dividend, dividend); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "minus zero"); } __ TruncatingDiv(dividend, Abs(divisor)); @@ -1278,7 +1276,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) { __ mov(eax, edx); __ imul(eax, eax, divisor); __ sub(eax, dividend); - DeoptimizeIf(not_equal, instr->environment()); + DeoptimizeIf(not_equal, instr, "lost precision"); } } @@ -1298,7 +1296,7 @@ void LCodeGen::DoDivI(LDivI* instr) { // Check for x / 0. if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { __ test(divisor, divisor); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "division by zero"); } // Check for (0 / -x) that will produce negative zero. @@ -1307,7 +1305,7 @@ void LCodeGen::DoDivI(LDivI* instr) { __ test(dividend, dividend); __ j(not_zero, ÷nd_not_zero, Label::kNear); __ test(divisor, divisor); - DeoptimizeIf(sign, instr->environment()); + DeoptimizeIf(sign, instr, "minus zero"); __ bind(÷nd_not_zero); } @@ -1317,7 +1315,7 @@ void LCodeGen::DoDivI(LDivI* instr) { __ cmp(dividend, kMinInt); __ j(not_zero, ÷nd_not_min_int, Label::kNear); __ cmp(divisor, -1); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "overflow"); __ bind(÷nd_not_min_int); } @@ -1328,7 +1326,7 @@ void LCodeGen::DoDivI(LDivI* instr) { if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { // Deoptimize if remainder is not 0. __ test(remainder, remainder); - DeoptimizeIf(not_zero, instr->environment()); + DeoptimizeIf(not_zero, instr, "lost precision"); } } @@ -1350,13 +1348,13 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { // If the divisor is negative, we have to negate and handle edge cases. __ neg(dividend); if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "minus zero"); } // Dividing by -1 is basically negation, unless we overflow. if (divisor == -1) { if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { - DeoptimizeIf(overflow, instr->environment()); + DeoptimizeIf(overflow, instr, "overflow"); } return; } @@ -1383,7 +1381,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { DCHECK(ToRegister(instr->result()).is(edx)); if (divisor == 0) { - DeoptimizeIf(no_condition, instr->environment()); + DeoptimizeIf(no_condition, instr, "division by zero"); return; } @@ -1391,7 +1389,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { HMathFloorOfDiv* hdiv = instr->hydrogen(); if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { __ test(dividend, dividend); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "minus zero"); } // Easy case: We need no dynamic check for the dividend and the flooring @@ -1438,7 +1436,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { // Check for x / 0. if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { __ test(divisor, divisor); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "division by zero"); } // Check for (0 / -x) that will produce negative zero. @@ -1447,7 +1445,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { __ test(dividend, dividend); __ j(not_zero, ÷nd_not_zero, Label::kNear); __ test(divisor, divisor); - DeoptimizeIf(sign, instr->environment()); + DeoptimizeIf(sign, instr, "minus zero"); __ bind(÷nd_not_zero); } @@ -1457,7 +1455,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { __ cmp(dividend, kMinInt); __ j(not_zero, ÷nd_not_min_int, Label::kNear); __ cmp(divisor, -1); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "overflow"); __ bind(÷nd_not_min_int); } @@ -1535,7 +1533,7 @@ void LCodeGen::DoMulI(LMulI* instr) { } if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { - DeoptimizeIf(overflow, instr->environment()); + DeoptimizeIf(overflow, instr, "overflow"); } if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { @@ -1545,15 +1543,15 @@ void LCodeGen::DoMulI(LMulI* instr) { __ j(not_zero, &done, Label::kNear); if (right->IsConstantOperand()) { if (ToInteger32(LConstantOperand::cast(right)) < 0) { - DeoptimizeIf(no_condition, instr->environment()); + DeoptimizeIf(no_condition, instr, "minus zero"); } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { __ cmp(ToRegister(instr->temp()), Immediate(0)); - DeoptimizeIf(less, instr->environment()); + DeoptimizeIf(less, instr, "minus zero"); } } else { // Test the non-zero operand for negative sign. __ or_(ToRegister(instr->temp()), ToOperand(right)); - DeoptimizeIf(sign, instr->environment()); + DeoptimizeIf(sign, instr, "minus zero"); } __ bind(&done); } @@ -1618,10 +1616,6 @@ void LCodeGen::DoShiftI(LShiftI* instr) { switch (instr->op()) { case Token::ROR: __ ror_cl(ToRegister(left)); - if (instr->can_deopt()) { - __ test(ToRegister(left), ToRegister(left)); - DeoptimizeIf(sign, instr->environment()); - } break; case Token::SAR: __ sar_cl(ToRegister(left)); @@ -1630,7 +1624,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) { __ shr_cl(ToRegister(left)); if (instr->can_deopt()) { __ test(ToRegister(left), ToRegister(left)); - DeoptimizeIf(sign, instr->environment()); + DeoptimizeIf(sign, instr, "negative value"); } break; case Token::SHL: @@ -1647,7 +1641,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) { case Token::ROR: if (shift_count == 0 && instr->can_deopt()) { __ test(ToRegister(left), ToRegister(left)); - DeoptimizeIf(sign, instr->environment()); + DeoptimizeIf(sign, instr, "negative value"); } else { __ ror(ToRegister(left), shift_count); } @@ -1662,7 +1656,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) { __ shr(ToRegister(left), shift_count); } else if (instr->can_deopt()) { __ test(ToRegister(left), ToRegister(left)); - DeoptimizeIf(sign, instr->environment()); + DeoptimizeIf(sign, instr, "negative value"); } break; case Token::SHL: @@ -1673,7 +1667,7 @@ void LCodeGen::DoShiftI(LShiftI* instr) { __ shl(ToRegister(left), shift_count - 1); } __ SmiTag(ToRegister(left)); - DeoptimizeIf(overflow, instr->environment()); + DeoptimizeIf(overflow, instr, "overflow"); } else { __ shl(ToRegister(left), shift_count); } @@ -1699,7 +1693,7 @@ void LCodeGen::DoSubI(LSubI* instr) { __ sub(ToRegister(left), ToOperand(right)); } if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { - DeoptimizeIf(overflow, instr->environment()); + DeoptimizeIf(overflow, instr, "overflow"); } } @@ -1716,7 +1710,7 @@ void LCodeGen::DoConstantS(LConstantS* instr) { void LCodeGen::DoConstantD(LConstantD* instr) { double v = instr->value(); - uint64_t int_val = BitCast<uint64_t, double>(v); + uint64_t int_val = bit_cast<uint64_t, double>(v); int32_t lower = static_cast<int32_t>(int_val); int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); DCHECK(instr->result()->IsDoubleRegister()); @@ -1783,9 +1777,9 @@ void LCodeGen::DoDateField(LDateField* instr) { DCHECK(object.is(eax)); __ test(object, Immediate(kSmiTagMask)); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "Smi"); __ CmpObjectType(object, JS_DATE_TYPE, scratch); - DeoptimizeIf(not_equal, instr->environment()); + DeoptimizeIf(not_equal, instr, "not a date object"); if (index->value() == 0) { __ mov(result, FieldOperand(object, JSDate::kValueOffset)); @@ -1915,7 +1909,7 @@ void LCodeGen::DoAddI(LAddI* instr) { __ add(ToRegister(left), ToOperand(right)); } if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { - DeoptimizeIf(overflow, instr->environment()); + DeoptimizeIf(overflow, instr, "overflow"); } } } @@ -2033,8 +2027,9 @@ void LCodeGen::DoArithmeticT(LArithmeticT* instr) { DCHECK(ToRegister(instr->right()).is(eax)); DCHECK(ToRegister(instr->result()).is(eax)); - BinaryOpICStub stub(isolate(), instr->op(), NO_OVERWRITE); - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); + Handle<Code> code = + CodeFactory::BinaryOpIC(isolate(), instr->op(), NO_OVERWRITE).code(); + CallCode(code, RelocInfo::CODE_TARGET, instr); } @@ -2138,7 +2133,7 @@ void LCodeGen::DoBranch(LBranch* instr) { } else if (expected.NeedsMap()) { // If we need a map later and have a Smi -> deopt. __ test(reg, Immediate(kSmiTagMask)); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "Smi"); } Register map = no_reg; // Keep the compiler happy. @@ -2195,7 +2190,7 @@ void LCodeGen::DoBranch(LBranch* instr) { if (!expected.IsGeneric()) { // We've seen something for the first time -> deopt. // This can only happen if we are not generic already. - DeoptimizeIf(no_condition, instr->environment()); + DeoptimizeIf(no_condition, instr, "unexpected object"); } } } @@ -2459,7 +2454,7 @@ static Condition ComputeCompareCondition(Token::Value op) { void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { Token::Value op = instr->op(); - Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); + Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); Condition condition = ComputeCompareCondition(op); @@ -2536,7 +2531,7 @@ void LCodeGen::EmitClassOfTest(Label* is_true, DCHECK(!temp.is(temp2)); __ JumpIfSmi(input, is_false); - if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Function"))) { + if (String::Equals(isolate()->factory()->Function_string(), class_name)) { // Assuming the following assertions, we can use the same compares to test // for both being a function type and being in the object type range. STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); @@ -2566,7 +2561,7 @@ void LCodeGen::EmitClassOfTest(Label* is_true, __ mov(temp, FieldOperand(temp, Map::kConstructorOffset)); // Objects with a non-function constructor have class 'Object'. __ CmpObjectType(temp, JS_FUNCTION_TYPE, temp2); - if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Object"))) { + if (String::Equals(class_name, isolate()->factory()->Object_string())) { __ j(not_equal, is_true); } else { __ j(not_equal, is_false); @@ -2627,15 +2622,15 @@ void LCodeGen::DoInstanceOf(LInstanceOf* instr) { void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { - class DeferredInstanceOfKnownGlobal V8_FINAL : public LDeferredCode { + class DeferredInstanceOfKnownGlobal FINAL : public LDeferredCode { public: DeferredInstanceOfKnownGlobal(LCodeGen* codegen, LInstanceOfKnownGlobal* instr) : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() V8_OVERRIDE { + virtual void Generate() OVERRIDE { codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); } - virtual LInstruction* instr() V8_OVERRIDE { return instr_; } + virtual LInstruction* instr() OVERRIDE { return instr_; } Label* map_check() { return &map_check_; } private: LInstanceOfKnownGlobal* instr_; @@ -2730,7 +2725,7 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, void LCodeGen::DoCmpT(LCmpT* instr) { Token::Value op = instr->op(); - Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); + Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); Condition condition = ComputeCompareCondition(op); @@ -2825,28 +2820,36 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle())); if (instr->hydrogen()->RequiresHoleCheck()) { __ cmp(result, factory()->the_hole_value()); - DeoptimizeIf(equal, instr->environment()); + DeoptimizeIf(equal, instr, "hole"); } } +template <class T> +void LCodeGen::EmitVectorLoadICRegisters(T* instr) { + DCHECK(FLAG_vector_ics); + Register vector = ToRegister(instr->temp_vector()); + DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); + __ mov(vector, instr->hydrogen()->feedback_vector()); + // No need to allocate this register. + DCHECK(VectorLoadICDescriptor::SlotRegister().is(eax)); + __ mov(VectorLoadICDescriptor::SlotRegister(), + Immediate(Smi::FromInt(instr->hydrogen()->slot()))); +} + + void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { DCHECK(ToRegister(instr->context()).is(esi)); - DCHECK(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister())); + DCHECK(ToRegister(instr->global_object()) + .is(LoadDescriptor::ReceiverRegister())); DCHECK(ToRegister(instr->result()).is(eax)); - __ mov(LoadIC::NameRegister(), instr->name()); + __ mov(LoadDescriptor::NameRegister(), instr->name()); if (FLAG_vector_ics) { - Register vector = ToRegister(instr->temp_vector()); - DCHECK(vector.is(LoadIC::VectorRegister())); - __ mov(vector, instr->hydrogen()->feedback_vector()); - // No need to allocate this register. - DCHECK(LoadIC::SlotRegister().is(eax)); - __ mov(LoadIC::SlotRegister(), - Immediate(Smi::FromInt(instr->hydrogen()->slot()))); + EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr); } ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; - Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode); + Handle<Code> ic = CodeFactory::LoadIC(isolate(), mode).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -2861,7 +2864,7 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { // it as no longer deleted. We deoptimize in that case. if (instr->hydrogen()->RequiresHoleCheck()) { __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); - DeoptimizeIf(equal, instr->environment()); + DeoptimizeIf(equal, instr, "hole"); } // Store the value. @@ -2878,7 +2881,7 @@ void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { if (instr->hydrogen()->RequiresHoleCheck()) { __ cmp(result, factory()->the_hole_value()); if (instr->hydrogen()->DeoptimizesOnHole()) { - DeoptimizeIf(equal, instr->environment()); + DeoptimizeIf(equal, instr, "hole"); } else { Label is_not_hole; __ j(not_equal, &is_not_hole, Label::kNear); @@ -2899,7 +2902,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { if (instr->hydrogen()->RequiresHoleCheck()) { __ cmp(target, factory()->the_hole_value()); if (instr->hydrogen()->DeoptimizesOnHole()) { - DeoptimizeIf(equal, instr->environment()); + DeoptimizeIf(equal, instr, "hole"); } else { __ j(not_equal, &skip_assignment, Label::kNear); } @@ -2975,20 +2978,14 @@ void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { DCHECK(ToRegister(instr->context()).is(esi)); - DCHECK(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); + DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister())); DCHECK(ToRegister(instr->result()).is(eax)); - __ mov(LoadIC::NameRegister(), instr->name()); + __ mov(LoadDescriptor::NameRegister(), instr->name()); if (FLAG_vector_ics) { - Register vector = ToRegister(instr->temp_vector()); - DCHECK(vector.is(LoadIC::VectorRegister())); - __ mov(vector, instr->hydrogen()->feedback_vector()); - // No need to allocate this register. - DCHECK(LoadIC::SlotRegister().is(eax)); - __ mov(LoadIC::SlotRegister(), - Immediate(Smi::FromInt(instr->hydrogen()->slot()))); - } - Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); + EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr); + } + Handle<Code> ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3004,7 +3001,7 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { // Check that the function has a prototype or an initial map. __ cmp(Operand(result), Immediate(factory()->the_hole_value())); - DeoptimizeIf(equal, instr->environment()); + DeoptimizeIf(equal, instr, "hole"); // If the function does not have an initial map, we're done. Label done; @@ -3097,7 +3094,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { __ mov(result, operand); if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { __ test(result, Operand(result)); - DeoptimizeIf(negative, instr->environment()); + DeoptimizeIf(negative, instr, "negative value"); } break; case EXTERNAL_FLOAT32_ELEMENTS: @@ -3127,7 +3124,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { FAST_DOUBLE_ELEMENTS, instr->base_offset() + sizeof(kHoleNanLower32)); __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); - DeoptimizeIf(equal, instr->environment()); + DeoptimizeIf(equal, instr, "hole"); } Operand double_load_operand = BuildFastArrayOperand( @@ -3146,20 +3143,18 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { // Load the result. __ mov(result, - BuildFastArrayOperand(instr->elements(), - instr->key(), + BuildFastArrayOperand(instr->elements(), instr->key(), instr->hydrogen()->key()->representation(), - FAST_ELEMENTS, - instr->base_offset())); + FAST_ELEMENTS, instr->base_offset())); // Check for the hole value. if (instr->hydrogen()->RequiresHoleCheck()) { if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { __ test(result, Immediate(kSmiTagMask)); - DeoptimizeIf(not_equal, instr->environment()); + DeoptimizeIf(not_equal, instr, "not a Smi"); } else { __ cmp(result, factory()->the_hole_value()); - DeoptimizeIf(equal, instr->environment()); + DeoptimizeIf(equal, instr, "hole"); } } } @@ -3209,20 +3204,14 @@ Operand LCodeGen::BuildFastArrayOperand( void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { DCHECK(ToRegister(instr->context()).is(esi)); - DCHECK(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); - DCHECK(ToRegister(instr->key()).is(LoadIC::NameRegister())); + DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister())); + DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister())); if (FLAG_vector_ics) { - Register vector = ToRegister(instr->temp_vector()); - DCHECK(vector.is(LoadIC::VectorRegister())); - __ mov(vector, instr->hydrogen()->feedback_vector()); - // No need to allocate this register. - DCHECK(LoadIC::SlotRegister().is(eax)); - __ mov(LoadIC::SlotRegister(), - Immediate(Smi::FromInt(instr->hydrogen()->slot()))); + EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr); } - Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); + Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3312,9 +3301,9 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { // The receiver should be a JS object. __ test(receiver, Immediate(kSmiTagMask)); - DeoptimizeIf(equal, instr->environment()); + DeoptimizeIf(equal, instr, "Smi"); __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); - DeoptimizeIf(below, instr->environment()); + DeoptimizeIf(below, instr, "not a JavaScript object"); __ jmp(&receiver_ok, Label::kNear); __ bind(&global_object); @@ -3340,7 +3329,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { // adaptor frame below it. const uint32_t kArgumentsLimit = 1 * KB; __ cmp(length, kArgumentsLimit); - DeoptimizeIf(above, instr->environment()); + DeoptimizeIf(above, instr, "too many arguments"); __ push(receiver); __ mov(receiver, length); @@ -3452,6 +3441,32 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, } +void LCodeGen::DoTailCallThroughMegamorphicCache( + LTailCallThroughMegamorphicCache* instr) { + Register receiver = ToRegister(instr->receiver()); + Register name = ToRegister(instr->name()); + DCHECK(receiver.is(LoadDescriptor::ReceiverRegister())); + DCHECK(name.is(LoadDescriptor::NameRegister())); + + Register scratch = ebx; + Register extra = eax; + DCHECK(!scratch.is(receiver) && !scratch.is(name)); + DCHECK(!extra.is(receiver) && !extra.is(name)); + + // Important for the tail-call. + bool must_teardown_frame = NeedsEagerFrame(); + + // The probe will tail call to a handler if found. + isolate()->stub_cache()->GenerateProbe(masm(), instr->hydrogen()->flags(), + must_teardown_frame, receiver, name, + scratch, extra); + + // Tail call to miss if we ended up here. + if (must_teardown_frame) __ leave(); + LoadIC::GenerateMiss(masm()); +} + + void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { DCHECK(ToRegister(instr->result()).is(eax)); @@ -3507,7 +3522,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { Register input_reg = ToRegister(instr->value()); __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), factory()->heap_number_map()); - DeoptimizeIf(not_equal, instr->environment()); + DeoptimizeIf(not_equal, instr, "not a heap number"); Label slow, allocated, done; Register tmp = input_reg.is(eax) ? ecx : eax; @@ -3554,22 +3569,22 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { Label is_positive; __ j(not_sign, &is_positive, Label::kNear); __ neg(input_reg); // Sets flags. - DeoptimizeIf(negative, instr->environment()); + DeoptimizeIf(negative, instr, "overflow"); __ bind(&is_positive); } void LCodeGen::DoMathAbs(LMathAbs* instr) { // Class for deferred case. - class DeferredMathAbsTaggedHeapNumber V8_FINAL : public LDeferredCode { + class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { public: DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() V8_OVERRIDE { + virtual void Generate() OVERRIDE { codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); } - virtual LInstruction* instr() V8_OVERRIDE { return instr_; } + virtual LInstruction* instr() OVERRIDE { return instr_; } private: LMathAbs* instr_; }; @@ -3612,20 +3627,20 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) { __ j(not_equal, &non_zero, Label::kNear); __ movmskpd(output_reg, input_reg); __ test(output_reg, Immediate(1)); - DeoptimizeIf(not_zero, instr->environment()); + DeoptimizeIf(not_zero, instr, "minus zero"); __ bind(&non_zero); } __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); __ cvttsd2si(output_reg, Operand(xmm_scratch)); // Overflow is signalled with minint. __ cmp(output_reg, 0x1); - DeoptimizeIf(overflow, instr->environment()); + DeoptimizeIf(overflow, instr, "overflow"); } else { Label negative_sign, done; // Deoptimize on unordered. __ xorps(xmm_scratch, xmm_scratch); // Zero the register. __ ucomisd(input_reg, xmm_scratch); - DeoptimizeIf(parity_even, instr->environment()); + DeoptimizeIf(parity_even, instr, "NaN"); __ j(below, &negative_sign, Label::kNear); if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { @@ -3634,7 +3649,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) { __ j(above, &positive_sign, Label::kNear); __ movmskpd(output_reg, input_reg); __ test(output_reg, Immediate(1)); - DeoptimizeIf(not_zero, instr->environment()); + DeoptimizeIf(not_zero, instr, "minus zero"); __ Move(output_reg, Immediate(0)); __ jmp(&done, Label::kNear); __ bind(&positive_sign); @@ -3644,7 +3659,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) { __ cvttsd2si(output_reg, Operand(input_reg)); // Overflow is signalled with minint. __ cmp(output_reg, 0x1); - DeoptimizeIf(overflow, instr->environment()); + DeoptimizeIf(overflow, instr, "overflow"); __ jmp(&done, Label::kNear); // Non-zero negative reaches here. @@ -3655,7 +3670,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) { __ ucomisd(input_reg, xmm_scratch); __ j(equal, &done, Label::kNear); __ sub(output_reg, Immediate(1)); - DeoptimizeIf(overflow, instr->environment()); + DeoptimizeIf(overflow, instr, "overflow"); __ bind(&done); } @@ -3683,8 +3698,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) { __ cvttsd2si(output_reg, Operand(xmm_scratch)); // Overflow is signalled with minint. __ cmp(output_reg, 0x1); - __ RecordComment("D2I conversion overflow"); - DeoptimizeIf(overflow, instr->environment()); + DeoptimizeIf(overflow, instr, "overflow"); __ jmp(&done, dist); __ bind(&below_one_half); @@ -3699,8 +3713,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) { __ cvttsd2si(output_reg, Operand(input_temp)); // Catch minint due to overflow, and to prevent overflow when compensating. __ cmp(output_reg, 0x1); - __ RecordComment("D2I conversion overflow"); - DeoptimizeIf(overflow, instr->environment()); + DeoptimizeIf(overflow, instr, "overflow"); __ Cvtsi2sd(xmm_scratch, output_reg); __ ucomisd(xmm_scratch, input_temp); @@ -3716,8 +3729,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) { // If the sign is positive, we return +0. __ movmskpd(output_reg, input_reg); __ test(output_reg, Immediate(1)); - __ RecordComment("Minus zero"); - DeoptimizeIf(not_zero, instr->environment()); + DeoptimizeIf(not_zero, instr, "minus zero"); } __ Move(output_reg, Immediate(0)); __ bind(&done); @@ -3777,10 +3789,11 @@ void LCodeGen::DoPower(LPower* instr) { Representation exponent_type = instr->hydrogen()->right()->representation(); // Having marked this as a call, we can use any registers. // Just make sure that the input/output registers are the expected ones. + Register tagged_exponent = MathPowTaggedDescriptor::exponent(); DCHECK(!instr->right()->IsDoubleRegister() || ToDoubleRegister(instr->right()).is(xmm1)); DCHECK(!instr->right()->IsRegister() || - ToRegister(instr->right()).is(eax)); + ToRegister(instr->right()).is(tagged_exponent)); DCHECK(ToDoubleRegister(instr->left()).is(xmm2)); DCHECK(ToDoubleRegister(instr->result()).is(xmm3)); @@ -3789,9 +3802,10 @@ void LCodeGen::DoPower(LPower* instr) { __ CallStub(&stub); } else if (exponent_type.IsTagged()) { Label no_deopt; - __ JumpIfSmi(eax, &no_deopt); - __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx); - DeoptimizeIf(not_equal, instr->environment()); + __ JumpIfSmi(tagged_exponent, &no_deopt); + DCHECK(!ecx.is(tagged_exponent)); + __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, ecx); + DeoptimizeIf(not_equal, instr, "not a heap number"); __ bind(&no_deopt); MathPowStub stub(isolate(), MathPowStub::TAGGED); __ CallStub(&stub); @@ -4074,10 +4088,10 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { DCHECK(ToRegister(instr->context()).is(esi)); - DCHECK(ToRegister(instr->object()).is(StoreIC::ReceiverRegister())); - DCHECK(ToRegister(instr->value()).is(StoreIC::ValueRegister())); + DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister())); + DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister())); - __ mov(StoreIC::NameRegister(), instr->name()); + __ mov(StoreDescriptor::NameRegister(), instr->name()); Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode()); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -4103,7 +4117,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { __ int3(); __ bind(&done); } else { - DeoptimizeIf(cc, instr->environment()); + DeoptimizeIf(cc, instr, "out of bounds"); } } @@ -4256,13 +4270,12 @@ void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { DCHECK(ToRegister(instr->context()).is(esi)); - DCHECK(ToRegister(instr->object()).is(KeyedStoreIC::ReceiverRegister())); - DCHECK(ToRegister(instr->key()).is(KeyedStoreIC::NameRegister())); - DCHECK(ToRegister(instr->value()).is(KeyedStoreIC::ValueRegister())); + DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister())); + DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister())); + DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister())); - Handle<Code> ic = instr->strict_mode() == STRICT - ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() - : isolate()->builtins()->KeyedStoreIC_Initialize(); + Handle<Code> ic = + CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code(); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -4272,7 +4285,7 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { Register temp = ToRegister(instr->temp()); Label no_memento_found; __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); - DeoptimizeIf(equal, instr->environment()); + DeoptimizeIf(equal, instr, "memento found"); __ bind(&no_memento_found); } @@ -4317,15 +4330,15 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { - class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { + class DeferredStringCharCodeAt FINAL : public LDeferredCode { public: DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() V8_OVERRIDE { + virtual void Generate() OVERRIDE { codegen()->DoDeferredStringCharCodeAt(instr_); } - virtual LInstruction* instr() V8_OVERRIDE { return instr_; } + virtual LInstruction* instr() OVERRIDE { return instr_; } private: LStringCharCodeAt* instr_; }; @@ -4375,15 +4388,15 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { - class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { + class DeferredStringCharFromCode FINAL : public LDeferredCode { public: DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() V8_OVERRIDE { + virtual void Generate() OVERRIDE { codegen()->DoDeferredStringCharFromCode(instr_); } - virtual LInstruction* instr() V8_OVERRIDE { return instr_; } + virtual LInstruction* instr() OVERRIDE { return instr_; } private: LStringCharFromCode* instr_; }; @@ -4453,16 +4466,16 @@ void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { void LCodeGen::DoNumberTagI(LNumberTagI* instr) { - class DeferredNumberTagI V8_FINAL : public LDeferredCode { + class DeferredNumberTagI FINAL : public LDeferredCode { public: DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() V8_OVERRIDE { + virtual void Generate() OVERRIDE { codegen()->DoDeferredNumberTagIU( instr_, instr_->value(), instr_->temp(), SIGNED_INT32); } - virtual LInstruction* instr() V8_OVERRIDE { return instr_; } + virtual LInstruction* instr() OVERRIDE { return instr_; } private: LNumberTagI* instr_; }; @@ -4480,15 +4493,15 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) { void LCodeGen::DoNumberTagU(LNumberTagU* instr) { - class DeferredNumberTagU V8_FINAL : public LDeferredCode { + class DeferredNumberTagU FINAL : public LDeferredCode { public: DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() V8_OVERRIDE { + virtual void Generate() OVERRIDE { codegen()->DoDeferredNumberTagIU( instr_, instr_->value(), instr_->temp(), UNSIGNED_INT32); } - virtual LInstruction* instr() V8_OVERRIDE { return instr_; } + virtual LInstruction* instr() OVERRIDE { return instr_; } private: LNumberTagU* instr_; }; @@ -4562,14 +4575,14 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, void LCodeGen::DoNumberTagD(LNumberTagD* instr) { - class DeferredNumberTagD V8_FINAL : public LDeferredCode { + class DeferredNumberTagD FINAL : public LDeferredCode { public: DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() V8_OVERRIDE { + virtual void Generate() OVERRIDE { codegen()->DoDeferredNumberTagD(instr_); } - virtual LInstruction* instr() V8_OVERRIDE { return instr_; } + virtual LInstruction* instr() OVERRIDE { return instr_; } private: LNumberTagD* instr_; }; @@ -4617,12 +4630,12 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) { if (hchange->CheckFlag(HValue::kCanOverflow) && hchange->value()->CheckFlag(HValue::kUint32)) { __ test(input, Immediate(0xc0000000)); - DeoptimizeIf(not_zero, instr->environment()); + DeoptimizeIf(not_zero, instr, "overflow"); } __ SmiTag(input); if (hchange->CheckFlag(HValue::kCanOverflow) && !hchange->value()->CheckFlag(HValue::kUint32)) { - DeoptimizeIf(overflow, instr->environment()); + DeoptimizeIf(overflow, instr, "overflow"); } } @@ -4633,7 +4646,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) { DCHECK(input->IsRegister() && input->Equals(instr->result())); if (instr->needs_check()) { __ test(result, Immediate(kSmiTagMask)); - DeoptimizeIf(not_zero, instr->environment()); + DeoptimizeIf(not_zero, instr, "not a Smi"); } else { __ AssertSmi(result); } @@ -4641,13 +4654,13 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) { } -void LCodeGen::EmitNumberUntagD(Register input_reg, - Register temp_reg, - XMMRegister result_reg, - bool can_convert_undefined_to_nan, - bool deoptimize_on_minus_zero, - LEnvironment* env, +void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, + Register temp_reg, XMMRegister result_reg, NumberUntagDMode mode) { + bool can_convert_undefined_to_nan = + instr->hydrogen()->can_convert_undefined_to_nan(); + bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); + Label convert, load_smi, done; if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { @@ -4660,7 +4673,7 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, if (can_convert_undefined_to_nan) { __ j(not_equal, &convert, Label::kNear); } else { - DeoptimizeIf(not_equal, env); + DeoptimizeIf(not_equal, instr, "not a heap number"); } // Heap number to XMM conversion. @@ -4673,7 +4686,7 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, __ j(not_zero, &done, Label::kNear); __ movmskpd(temp_reg, result_reg); __ test_b(temp_reg, 1); - DeoptimizeIf(not_zero, env); + DeoptimizeIf(not_zero, instr, "minus zero"); } __ jmp(&done, Label::kNear); @@ -4682,7 +4695,7 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, // Convert undefined (and hole) to NaN. __ cmp(input_reg, factory()->undefined_value()); - DeoptimizeIf(not_equal, env); + DeoptimizeIf(not_equal, instr, "not a heap number/undefined"); ExternalReference nan = ExternalReference::address_of_canonical_non_hole_nan(); @@ -4736,32 +4749,40 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { __ bind(&check_false); __ cmp(input_reg, factory()->false_value()); - __ RecordComment("Deferred TaggedToI: cannot truncate"); - DeoptimizeIf(not_equal, instr->environment()); + DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false"); __ Move(input_reg, Immediate(0)); } else { - Label bailout; - XMMRegister scratch = (instr->temp() != NULL) - ? ToDoubleRegister(instr->temp()) - : no_xmm_reg; - __ TaggedToI(input_reg, input_reg, scratch, - instr->hydrogen()->GetMinusZeroMode(), &bailout); - __ jmp(done); - __ bind(&bailout); - DeoptimizeIf(no_condition, instr->environment()); + XMMRegister scratch = ToDoubleRegister(instr->temp()); + DCHECK(!scratch.is(xmm0)); + __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), + isolate()->factory()->heap_number_map()); + DeoptimizeIf(not_equal, instr, "not a heap number"); + __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); + __ cvttsd2si(input_reg, Operand(xmm0)); + __ Cvtsi2sd(scratch, Operand(input_reg)); + __ ucomisd(xmm0, scratch); + DeoptimizeIf(not_equal, instr, "lost precision"); + DeoptimizeIf(parity_even, instr, "NaN"); + if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { + __ test(input_reg, Operand(input_reg)); + __ j(not_zero, done); + __ movmskpd(input_reg, xmm0); + __ and_(input_reg, 1); + DeoptimizeIf(not_zero, instr, "minus zero"); + } } } void LCodeGen::DoTaggedToI(LTaggedToI* instr) { - class DeferredTaggedToI V8_FINAL : public LDeferredCode { + class DeferredTaggedToI FINAL : public LDeferredCode { public: DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() V8_OVERRIDE { + virtual void Generate() OVERRIDE { codegen()->DoDeferredTaggedToI(instr_, done()); } - virtual LInstruction* instr() V8_OVERRIDE { return instr_; } + virtual LInstruction* instr() OVERRIDE { return instr_; } private: LTaggedToI* instr_; }; @@ -4797,8 +4818,6 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { DCHECK(result->IsDoubleRegister()); Register input_reg = ToRegister(input); - bool deoptimize_on_minus_zero = - instr->hydrogen()->deoptimize_on_minus_zero(); Register temp_reg = ToRegister(temp); HValue* value = instr->hydrogen()->value(); @@ -4806,13 +4825,7 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; XMMRegister result_reg = ToDoubleRegister(result); - EmitNumberUntagD(input_reg, - temp_reg, - result_reg, - instr->hydrogen()->can_convert_undefined_to_nan(), - deoptimize_on_minus_zero, - instr->environment(), - mode); + EmitNumberUntagD(instr, input_reg, temp_reg, result_reg, mode); } @@ -4827,14 +4840,20 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { XMMRegister input_reg = ToDoubleRegister(input); __ TruncateDoubleToI(result_reg, input_reg); } else { - Label bailout, done; + Label lost_precision, is_nan, minus_zero, done; XMMRegister input_reg = ToDoubleRegister(input); XMMRegister xmm_scratch = double_scratch0(); - __ DoubleToI(result_reg, input_reg, xmm_scratch, - instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); - __ jmp(&done, Label::kNear); - __ bind(&bailout); - DeoptimizeIf(no_condition, instr->environment()); + Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; + __ DoubleToI(result_reg, input_reg, xmm_scratch, + instr->hydrogen()->GetMinusZeroMode(), &lost_precision, + &is_nan, &minus_zero, dist); + __ jmp(&done, dist); + __ bind(&lost_precision); + DeoptimizeIf(no_condition, instr, "lost precision"); + __ bind(&is_nan); + DeoptimizeIf(no_condition, instr, "NaN"); + __ bind(&minus_zero); + DeoptimizeIf(no_condition, instr, "minus zero"); __ bind(&done); } } @@ -4847,25 +4866,30 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { DCHECK(result->IsRegister()); Register result_reg = ToRegister(result); - Label bailout, done; + Label lost_precision, is_nan, minus_zero, done; XMMRegister input_reg = ToDoubleRegister(input); XMMRegister xmm_scratch = double_scratch0(); + Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; __ DoubleToI(result_reg, input_reg, xmm_scratch, - instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); - __ jmp(&done, Label::kNear); - __ bind(&bailout); - DeoptimizeIf(no_condition, instr->environment()); + instr->hydrogen()->GetMinusZeroMode(), &lost_precision, &is_nan, + &minus_zero, dist); + __ jmp(&done, dist); + __ bind(&lost_precision); + DeoptimizeIf(no_condition, instr, "lost precision"); + __ bind(&is_nan); + DeoptimizeIf(no_condition, instr, "NaN"); + __ bind(&minus_zero); + DeoptimizeIf(no_condition, instr, "minus zero"); __ bind(&done); - __ SmiTag(result_reg); - DeoptimizeIf(overflow, instr->environment()); + DeoptimizeIf(overflow, instr, "overflow"); } void LCodeGen::DoCheckSmi(LCheckSmi* instr) { LOperand* input = instr->value(); __ test(ToOperand(input), Immediate(kSmiTagMask)); - DeoptimizeIf(not_zero, instr->environment()); + DeoptimizeIf(not_zero, instr, "not a Smi"); } @@ -4873,7 +4897,7 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { if (!instr->hydrogen()->value()->type().IsHeapObject()) { LOperand* input = instr->value(); __ test(ToOperand(input), Immediate(kSmiTagMask)); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "Smi"); } } @@ -4894,14 +4918,14 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { // If there is only one type in the interval check for equality. if (first == last) { - DeoptimizeIf(not_equal, instr->environment()); + DeoptimizeIf(not_equal, instr, "wrong instance type"); } else { - DeoptimizeIf(below, instr->environment()); + DeoptimizeIf(below, instr, "wrong instance type"); // Omit check for the last type. if (last != LAST_TYPE) { __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), static_cast<int8_t>(last)); - DeoptimizeIf(above, instr->environment()); + DeoptimizeIf(above, instr, "wrong instance type"); } } } else { @@ -4909,15 +4933,15 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { uint8_t tag; instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); - if (IsPowerOf2(mask)) { - DCHECK(tag == 0 || IsPowerOf2(tag)); + if (base::bits::IsPowerOfTwo32(mask)) { + DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask); - DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment()); + DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type"); } else { __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); __ and_(temp, mask); __ cmp(temp, tag); - DeoptimizeIf(not_equal, instr->environment()); + DeoptimizeIf(not_equal, instr, "wrong instance type"); } } } @@ -4933,7 +4957,7 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) { Operand operand = ToOperand(instr->value()); __ cmp(operand, object); } - DeoptimizeIf(not_equal, instr->environment()); + DeoptimizeIf(not_equal, instr, "value mismatch"); } @@ -4948,22 +4972,22 @@ void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { __ test(eax, Immediate(kSmiTagMask)); } - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "instance migration failed"); } void LCodeGen::DoCheckMaps(LCheckMaps* instr) { - class DeferredCheckMaps V8_FINAL : public LDeferredCode { + class DeferredCheckMaps FINAL : public LDeferredCode { public: DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) : LDeferredCode(codegen), instr_(instr), object_(object) { SetExit(check_maps()); } - virtual void Generate() V8_OVERRIDE { + virtual void Generate() OVERRIDE { codegen()->DoDeferredInstanceMigration(instr_, object_); } Label* check_maps() { return &check_maps_; } - virtual LInstruction* instr() V8_OVERRIDE { return instr_; } + virtual LInstruction* instr() OVERRIDE { return instr_; } private: LCheckMaps* instr_; Label check_maps_; @@ -5001,7 +5025,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) { if (instr->hydrogen()->HasMigrationTarget()) { __ j(not_equal, deferred->entry()); } else { - DeoptimizeIf(not_equal, instr->environment()); + DeoptimizeIf(not_equal, instr, "wrong map"); } __ bind(&success); @@ -5040,7 +5064,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { // Check for undefined. Undefined is converted to zero for clamping // conversions. __ cmp(input_reg, factory()->undefined_value()); - DeoptimizeIf(not_equal, instr->environment()); + DeoptimizeIf(not_equal, instr, "not a heap number/undefined"); __ mov(input_reg, 0); __ jmp(&done, Label::kNear); @@ -5096,14 +5120,14 @@ void LCodeGen::DoConstructDouble(LConstructDouble* instr) { void LCodeGen::DoAllocate(LAllocate* instr) { - class DeferredAllocate V8_FINAL : public LDeferredCode { + class DeferredAllocate FINAL : public LDeferredCode { public: DeferredAllocate(LCodeGen* codegen, LAllocate* instr) : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() V8_OVERRIDE { + virtual void Generate() OVERRIDE { codegen()->DoDeferredAllocate(instr_); } - virtual LInstruction* instr() V8_OVERRIDE { return instr_; } + virtual LInstruction* instr() OVERRIDE { return instr_; } private: LAllocate* instr_; }; @@ -5270,9 +5294,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { // space for nested functions that don't need literals cloning. bool pretenure = instr->hydrogen()->pretenure(); if (!pretenure && instr->hydrogen()->has_no_literals()) { - FastNewClosureStub stub(isolate(), - instr->hydrogen()->strict_mode(), - instr->hydrogen()->is_generator()); + FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(), + instr->hydrogen()->kind()); __ mov(ebx, Immediate(instr->hydrogen()->shared_info())); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); } else { @@ -5436,8 +5459,7 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) { if (info()->IsStub() && type == Deoptimizer::EAGER) { type = Deoptimizer::LAZY; } - Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); - DeoptimizeIf(no_condition, instr->environment(), type); + DeoptimizeIf(no_condition, instr, instr->hydrogen()->reason(), type); } @@ -5464,14 +5486,14 @@ void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { void LCodeGen::DoStackCheck(LStackCheck* instr) { - class DeferredStackCheck V8_FINAL : public LDeferredCode { + class DeferredStackCheck FINAL : public LDeferredCode { public: DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) : LDeferredCode(codegen), instr_(instr) { } - virtual void Generate() V8_OVERRIDE { + virtual void Generate() OVERRIDE { codegen()->DoDeferredStackCheck(instr_); } - virtual LInstruction* instr() V8_OVERRIDE { return instr_; } + virtual LInstruction* instr() OVERRIDE { return instr_; } private: LStackCheck* instr_; }; @@ -5532,17 +5554,17 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) { void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { DCHECK(ToRegister(instr->context()).is(esi)); __ cmp(eax, isolate()->factory()->undefined_value()); - DeoptimizeIf(equal, instr->environment()); + DeoptimizeIf(equal, instr, "undefined"); __ cmp(eax, isolate()->factory()->null_value()); - DeoptimizeIf(equal, instr->environment()); + DeoptimizeIf(equal, instr, "null"); __ test(eax, Immediate(kSmiTagMask)); - DeoptimizeIf(zero, instr->environment()); + DeoptimizeIf(zero, instr, "Smi"); STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx); - DeoptimizeIf(below_equal, instr->environment()); + DeoptimizeIf(below_equal, instr, "wrong instance type"); Label use_cache, call_runtime; __ CheckEnumCache(&call_runtime); @@ -5557,7 +5579,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { __ cmp(FieldOperand(eax, HeapObject::kMapOffset), isolate()->factory()->meta_map()); - DeoptimizeIf(not_equal, instr->environment()); + DeoptimizeIf(not_equal, instr, "wrong map"); __ bind(&use_cache); } @@ -5580,7 +5602,7 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { FieldOperand(result, FixedArray::SizeFor(instr->idx()))); __ bind(&done); __ test(result, result); - DeoptimizeIf(equal, instr->environment()); + DeoptimizeIf(equal, instr, "no cache"); } @@ -5588,7 +5610,7 @@ void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { Register object = ToRegister(instr->value()); __ cmp(ToRegister(instr->map()), FieldOperand(object, HeapObject::kMapOffset)); - DeoptimizeIf(not_equal, instr->environment()); + DeoptimizeIf(not_equal, instr, "wrong map"); } @@ -5607,7 +5629,7 @@ void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { - class DeferredLoadMutableDouble V8_FINAL : public LDeferredCode { + class DeferredLoadMutableDouble FINAL : public LDeferredCode { public: DeferredLoadMutableDouble(LCodeGen* codegen, LLoadFieldByIndex* instr, @@ -5618,10 +5640,10 @@ void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { object_(object), index_(index) { } - virtual void Generate() V8_OVERRIDE { + virtual void Generate() OVERRIDE { codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_); } - virtual LInstruction* instr() V8_OVERRIDE { return instr_; } + virtual LInstruction* instr() OVERRIDE { return instr_; } private: LLoadFieldByIndex* instr_; Register object_; |