diff options
author | Fedor Indutny <fedor.indutny@gmail.com> | 2013-01-01 12:28:07 +0400 |
---|---|---|
committer | Fedor Indutny <fedor.indutny@gmail.com> | 2013-01-01 16:07:02 +0400 |
commit | 7b4d95a976f1b76e6dcefb6ca91dff738c80ab7a (patch) | |
tree | 1eb943733a2e660fc0183778fd441443e06196e2 /deps/v8/src/arm/lithium-codegen-arm.cc | |
parent | 9e32c2ef3ede29ba0ae2086bdf658f6cd44182df (diff) | |
download | node-new-7b4d95a976f1b76e6dcefb6ca91dff738c80ab7a.tar.gz |
deps: update v8 to 3.15.11
Diffstat (limited to 'deps/v8/src/arm/lithium-codegen-arm.cc')
-rw-r--r-- | deps/v8/src/arm/lithium-codegen-arm.cc | 1210 |
1 files changed, 691 insertions, 519 deletions
diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc index e9ba5eec72..06b021669b 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.cc +++ b/deps/v8/src/arm/lithium-codegen-arm.cc @@ -146,8 +146,20 @@ bool LCodeGen::GeneratePrologue() { __ bind(&ok); } - __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); - __ add(fp, sp, Operand(2 * kPointerSize)); // Adjust FP to point to saved FP. + + info()->set_prologue_offset(masm_->pc_offset()); + { + PredictableCodeSizeScope predictible_code_size_scope( + masm_, kNoCodeAgeSequenceLength * Assembler::kInstrSize); + // The following three instructions must remain together and unmodified + // for code aging to work properly. + __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); + // Load undefined value here, so the value is ready for the loop + // below. + __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); + // Adjust FP to point to saved FP. + __ add(fp, sp, Operand(2 * kPointerSize)); + } // Reserve space for the stack slots needed by the code. int slots = GetStackSlotCount(); @@ -222,7 +234,30 @@ bool LCodeGen::GenerateBody() { } if (emit_instructions) { - Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic()); + if (FLAG_code_comments) { + HValue* hydrogen = instr->hydrogen_value(); + if (hydrogen != NULL) { + if (hydrogen->IsChange()) { + HValue* changed_value = HChange::cast(hydrogen)->value(); + int use_id = 0; + const char* use_mnemo = "dead"; + if (hydrogen->UseCount() >= 1) { + HValue* use_value = hydrogen->uses().value(); + use_id = use_value->id(); + use_mnemo = use_value->Mnemonic(); + } + Comment(";;; @%d: %s. <of #%d %s for #%d %s>", + current_instruction_, instr->Mnemonic(), + changed_value->id(), changed_value->Mnemonic(), + use_id, use_mnemo); + } else { + Comment(";;; @%d: %s. <#%d>", current_instruction_, + instr->Mnemonic(), hydrogen->id()); + } + } else { + Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic()); + } + } instr->CompileToNative(this); } } @@ -464,7 +499,9 @@ MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const { void LCodeGen::WriteTranslation(LEnvironment* environment, - Translation* translation) { + Translation* translation, + int* arguments_index, + int* arguments_count) { if (environment == NULL) return; // The translation includes one command per value in the environment. @@ -472,7 +509,17 @@ void LCodeGen::WriteTranslation(LEnvironment* environment, // The output frame height does not include the parameters. int height = translation_size - environment->parameter_count(); - WriteTranslation(environment->outer(), translation); + // Function parameters are arguments to the outermost environment. The + // arguments index points to the first element of a sequence of tagged + // values on the stack that represent the arguments. This needs to be + // kept in sync with the LArgumentsElements implementation. + *arguments_index = -environment->parameter_count(); + *arguments_count = environment->parameter_count(); + + WriteTranslation(environment->outer(), + translation, + arguments_index, + arguments_count); int closure_id = *info()->closure() != *environment->closure() ? DefineDeoptimizationLiteral(environment->closure()) : Translation::kSelfLiteralId; @@ -498,6 +545,17 @@ void LCodeGen::WriteTranslation(LEnvironment* environment, translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); break; } + + // Inlined frames which push their arguments cause the index to be + // bumped and a new stack area to be used for materialization. + if (environment->entry() != NULL && + environment->entry()->arguments_pushed()) { + *arguments_index = *arguments_index < 0 + ? GetStackSlotCount() + : *arguments_index + *arguments_count; + *arguments_count = environment->entry()->arguments_count() + 1; + } + for (int i = 0; i < translation_size; ++i) { LOperand* value = environment->values()->at(i); // spilled_registers_ and spilled_double_registers_ are either @@ -509,7 +567,9 @@ void LCodeGen::WriteTranslation(LEnvironment* environment, AddToTranslation(translation, environment->spilled_registers()[value->index()], environment->HasTaggedValueAt(i), - environment->HasUint32ValueAt(i)); + environment->HasUint32ValueAt(i), + *arguments_index, + *arguments_count); } else if ( value->IsDoubleRegister() && environment->spilled_double_registers()[value->index()] != NULL) { @@ -518,14 +578,18 @@ void LCodeGen::WriteTranslation(LEnvironment* environment, translation, environment->spilled_double_registers()[value->index()], false, - false); + false, + *arguments_index, + *arguments_count); } } AddToTranslation(translation, value, environment->HasTaggedValueAt(i), - environment->HasUint32ValueAt(i)); + environment->HasUint32ValueAt(i), + *arguments_index, + *arguments_count); } } @@ -533,12 +597,14 @@ void LCodeGen::WriteTranslation(LEnvironment* environment, void LCodeGen::AddToTranslation(Translation* translation, LOperand* op, bool is_tagged, - bool is_uint32) { + bool is_uint32, + int arguments_index, + int arguments_count) { if (op == NULL) { // TODO(twuerthinger): Introduce marker operands to indicate that this value // is not present and must be reconstructed from the deoptimizer. Currently // this is only used for the arguments object. - translation->StoreArgumentsObject(); + translation->StoreArgumentsObject(arguments_index, arguments_count); } else if (op->IsStackSlot()) { if (is_tagged) { translation->StoreStackSlot(op->index()); @@ -577,22 +643,24 @@ void LCodeGen::AddToTranslation(Translation* translation, void LCodeGen::CallCode(Handle<Code> code, RelocInfo::Mode mode, - LInstruction* instr) { - CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); + LInstruction* instr, + TargetAddressStorageMode storage_mode) { + CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, storage_mode); } void LCodeGen::CallCodeGeneric(Handle<Code> code, RelocInfo::Mode mode, LInstruction* instr, - SafepointMode safepoint_mode) { + SafepointMode safepoint_mode, + TargetAddressStorageMode storage_mode) { ASSERT(instr != NULL); // Block literal pool emission to ensure nop indicating no inlined smi code // is in the correct position. Assembler::BlockConstPoolScope block_const_pool(masm()); LPointerMap* pointers = instr->pointer_map(); RecordPosition(pointers->position()); - __ Call(code, mode); + __ Call(code, mode, TypeFeedbackId::None(), al, storage_mode); RecordSafepointWithLazyDeopt(instr, safepoint_mode); // Signal that we don't inline smi code before these stubs in the @@ -644,15 +712,16 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, int frame_count = 0; int jsframe_count = 0; + int args_index = 0; + int args_count = 0; for (LEnvironment* e = environment; e != NULL; e = e->outer()) { ++frame_count; if (e->frame_type() == JS_FUNCTION) { ++jsframe_count; } } - Translation translation(&translations_, frame_count, jsframe_count, - zone()); - WriteTranslation(environment, &translation); + Translation translation(&translations_, frame_count, jsframe_count, zone()); + WriteTranslation(environment, &translation, &args_index, &args_count); int deoptimization_index = deoptimizations_.length(); int pc_offset = masm()->pc_offset(); environment->Register(deoptimization_index, @@ -919,7 +988,7 @@ void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { void LCodeGen::DoModI(LModI* instr) { if (instr->hydrogen()->HasPowerOf2Divisor()) { - Register dividend = ToRegister(instr->InputAt(0)); + Register dividend = ToRegister(instr->left()); Register result = ToRegister(instr->result()); int32_t divisor = @@ -944,112 +1013,135 @@ void LCodeGen::DoModI(LModI* instr) { } // These registers hold untagged 32 bit values. - Register left = ToRegister(instr->InputAt(0)); - Register right = ToRegister(instr->InputAt(1)); + Register left = ToRegister(instr->left()); + Register right = ToRegister(instr->right()); Register result = ToRegister(instr->result()); + Label done; - Register scratch = scratch0(); - Register scratch2 = ToRegister(instr->TempAt(0)); - DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1)); - DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2)); - DwVfpRegister quotient = double_scratch0(); - - ASSERT(!dividend.is(divisor)); - ASSERT(!dividend.is(quotient)); - ASSERT(!divisor.is(quotient)); - ASSERT(!scratch.is(left)); - ASSERT(!scratch.is(right)); - ASSERT(!scratch.is(result)); + if (CpuFeatures::IsSupported(SUDIV)) { + CpuFeatures::Scope scope(SUDIV); + // Check for x % 0. + if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { + __ cmp(right, Operand(0)); + DeoptimizeIf(eq, instr->environment()); + } - Label done, vfp_modulo, both_positive, right_negative; + // For r3 = r1 % r2; we can have the following ARM code + // sdiv r3, r1, r2 + // mls r3, r3, r2, r1 - // Check for x % 0. - if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { - __ cmp(right, Operand(0)); - DeoptimizeIf(eq, instr->environment()); - } + __ sdiv(result, left, right); + __ mls(result, result, right, left); + __ cmp(result, Operand(0)); + __ b(ne, &done); - __ Move(result, left); + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { + __ cmp(left, Operand(0)); + DeoptimizeIf(lt, instr->environment()); + } + } else { + Register scratch = scratch0(); + Register scratch2 = ToRegister(instr->temp()); + DwVfpRegister dividend = ToDoubleRegister(instr->temp2()); + DwVfpRegister divisor = ToDoubleRegister(instr->temp3()); + DwVfpRegister quotient = double_scratch0(); + + ASSERT(!dividend.is(divisor)); + ASSERT(!dividend.is(quotient)); + ASSERT(!divisor.is(quotient)); + ASSERT(!scratch.is(left)); + ASSERT(!scratch.is(right)); + ASSERT(!scratch.is(result)); + + Label vfp_modulo, both_positive, right_negative; + + // Check for x % 0. + if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { + __ cmp(right, Operand(0)); + DeoptimizeIf(eq, instr->environment()); + } - // (0 % x) must yield 0 (if x is finite, which is the case here). - __ cmp(left, Operand(0)); - __ b(eq, &done); - // Preload right in a vfp register. - __ vmov(divisor.low(), right); - __ b(lt, &vfp_modulo); + __ Move(result, left); - __ cmp(left, Operand(right)); - __ b(lt, &done); - - // Check for (positive) power of two on the right hand side. - __ JumpIfNotPowerOfTwoOrZeroAndNeg(right, - scratch, - &right_negative, - &both_positive); - // Perform modulo operation (scratch contains right - 1). - __ and_(result, scratch, Operand(left)); - __ b(&done); + // (0 % x) must yield 0 (if x is finite, which is the case here). + __ cmp(left, Operand(0)); + __ b(eq, &done); + // Preload right in a vfp register. + __ vmov(divisor.low(), right); + __ b(lt, &vfp_modulo); - __ bind(&right_negative); - // Negate right. The sign of the divisor does not matter. - __ rsb(right, right, Operand(0)); - - __ bind(&both_positive); - const int kUnfolds = 3; - // If the right hand side is smaller than the (nonnegative) - // left hand side, the left hand side is the result. - // Else try a few subtractions of the left hand side. - __ mov(scratch, left); - for (int i = 0; i < kUnfolds; i++) { - // Check if the left hand side is less or equal than the - // the right hand side. - __ cmp(scratch, Operand(right)); - __ mov(result, scratch, LeaveCC, lt); + __ cmp(left, Operand(right)); __ b(lt, &done); - // If not, reduce the left hand side by the right hand - // side and check again. - if (i < kUnfolds - 1) __ sub(scratch, scratch, right); - } - - __ bind(&vfp_modulo); - // Load the arguments in VFP registers. - // The divisor value is preloaded before. Be careful that 'right' is only live - // on entry. - __ vmov(dividend.low(), left); - // From here on don't use right as it may have been reallocated (for example - // to scratch2). - right = no_reg; - - __ vcvt_f64_s32(dividend, dividend.low()); - __ vcvt_f64_s32(divisor, divisor.low()); - - // We do not care about the sign of the divisor. - __ vabs(divisor, divisor); - // Compute the quotient and round it to a 32bit integer. - __ vdiv(quotient, dividend, divisor); - __ vcvt_s32_f64(quotient.low(), quotient); - __ vcvt_f64_s32(quotient, quotient.low()); - - // Compute the remainder in result. - DwVfpRegister double_scratch = dividend; - __ vmul(double_scratch, divisor, quotient); - __ vcvt_s32_f64(double_scratch.low(), double_scratch); - __ vmov(scratch, double_scratch.low()); - - if (!instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { - __ sub(result, left, scratch); - } else { - Label ok; - // Check for -0. - __ sub(scratch2, left, scratch, SetCC); - __ b(ne, &ok); - __ cmp(left, Operand(0)); - DeoptimizeIf(mi, instr->environment()); - __ bind(&ok); - // Load the result and we are done. - __ mov(result, scratch2); - } + // Check for (positive) power of two on the right hand side. + __ JumpIfNotPowerOfTwoOrZeroAndNeg(right, + scratch, + &right_negative, + &both_positive); + // Perform modulo operation (scratch contains right - 1). + __ and_(result, scratch, Operand(left)); + __ b(&done); + + __ bind(&right_negative); + // Negate right. The sign of the divisor does not matter. + __ rsb(right, right, Operand(0)); + + __ bind(&both_positive); + const int kUnfolds = 3; + // If the right hand side is smaller than the (nonnegative) + // left hand side, the left hand side is the result. + // Else try a few subtractions of the left hand side. + __ mov(scratch, left); + for (int i = 0; i < kUnfolds; i++) { + // Check if the left hand side is less or equal than the + // the right hand side. + __ cmp(scratch, Operand(right)); + __ mov(result, scratch, LeaveCC, lt); + __ b(lt, &done); + // If not, reduce the left hand side by the right hand + // side and check again. + if (i < kUnfolds - 1) __ sub(scratch, scratch, right); + } + + __ bind(&vfp_modulo); + // Load the arguments in VFP registers. + // The divisor value is preloaded before. Be careful that 'right' + // is only live on entry. + __ vmov(dividend.low(), left); + // From here on don't use right as it may have been reallocated + // (for example to scratch2). + right = no_reg; + + __ vcvt_f64_s32(dividend, dividend.low()); + __ vcvt_f64_s32(divisor, divisor.low()); + + // We do not care about the sign of the divisor. + __ vabs(divisor, divisor); + // Compute the quotient and round it to a 32bit integer. + __ vdiv(quotient, dividend, divisor); + __ vcvt_s32_f64(quotient.low(), quotient); + __ vcvt_f64_s32(quotient, quotient.low()); + + // Compute the remainder in result. + DwVfpRegister double_scratch = dividend; + __ vmul(double_scratch, divisor, quotient); + __ vcvt_s32_f64(double_scratch.low(), double_scratch); + __ vmov(scratch, double_scratch.low()); + + if (!instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { + __ sub(result, left, scratch); + } else { + Label ok; + // Check for -0. + __ sub(scratch2, left, scratch, SetCC); + __ b(ne, &ok); + __ cmp(left, Operand(0)); + DeoptimizeIf(mi, instr->environment()); + __ bind(&ok); + // Load the result and we are done. + __ mov(result, scratch2); + } + } __ bind(&done); } @@ -1154,15 +1246,18 @@ void LCodeGen::DoDivI(LDivI* instr) { DeferredDivI(LCodeGen* codegen, LDivI* instr) : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() { - codegen()->DoDeferredBinaryOpStub(instr_, Token::DIV); + codegen()->DoDeferredBinaryOpStub(instr_->pointer_map(), + instr_->left(), + instr_->right(), + Token::DIV); } virtual LInstruction* instr() { return instr_; } private: LDivI* instr_; }; - const Register left = ToRegister(instr->InputAt(0)); - const Register right = ToRegister(instr->InputAt(1)); + const Register left = ToRegister(instr->left()); + const Register right = ToRegister(instr->right()); const Register scratch = scratch0(); const Register result = ToRegister(instr->result()); @@ -1229,17 +1324,29 @@ void LCodeGen::DoDivI(LDivI* instr) { } +void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { + DwVfpRegister addend = ToDoubleRegister(instr->addend()); + DwVfpRegister multiplier = ToDoubleRegister(instr->multiplier()); + DwVfpRegister multiplicand = ToDoubleRegister(instr->multiplicand()); + + // This is computed in-place. + ASSERT(addend.is(ToDoubleRegister(instr->result()))); + + __ vmla(addend, multiplier, multiplicand); +} + + void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { const Register result = ToRegister(instr->result()); - const Register left = ToRegister(instr->InputAt(0)); - const Register remainder = ToRegister(instr->TempAt(0)); + const Register left = ToRegister(instr->left()); + const Register remainder = ToRegister(instr->temp()); const Register scratch = scratch0(); // We only optimize this for division by constants, because the standard // integer division routine is usually slower than transitionning to VFP. // This could be optimized on processors with SDIV available. - ASSERT(instr->InputAt(1)->IsConstantOperand()); - int32_t divisor = ToInteger32(LConstantOperand::cast(instr->InputAt(1))); + ASSERT(instr->right()->IsConstantOperand()); + int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); if (divisor < 0) { __ cmp(left, Operand(0)); DeoptimizeIf(eq, instr->environment()); @@ -1257,11 +1364,12 @@ void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { } -template<int T> -void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr, +void LCodeGen::DoDeferredBinaryOpStub(LPointerMap* pointer_map, + LOperand* left_argument, + LOperand* right_argument, Token::Value op) { - Register left = ToRegister(instr->InputAt(0)); - Register right = ToRegister(instr->InputAt(1)); + Register left = ToRegister(left_argument); + Register right = ToRegister(right_argument); PushSafepointRegistersScope scope(this, Safepoint::kWithRegistersAndDoubles); // Move left to r1 and right to r0 for the stub call. @@ -1280,7 +1388,7 @@ void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr, } BinaryOpStub stub(op, OVERWRITE_LEFT); __ CallStub(&stub); - RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), + RecordSafepointWithRegistersAndDoubles(pointer_map, 0, Safepoint::kNoLazyDeopt); // Overwrite the stored value of r0 with the result of the stub. @@ -1292,8 +1400,8 @@ void LCodeGen::DoMulI(LMulI* instr) { Register scratch = scratch0(); Register result = ToRegister(instr->result()); // Note that result may alias left. - Register left = ToRegister(instr->InputAt(0)); - LOperand* right_op = instr->InputAt(1); + Register left = ToRegister(instr->left()); + LOperand* right_op = instr->right(); bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); bool bailout_on_minus_zero = @@ -1360,7 +1468,7 @@ void LCodeGen::DoMulI(LMulI* instr) { } else { Register right = EmitLoadRegister(right_op, scratch); if (bailout_on_minus_zero) { - __ orr(ToRegister(instr->TempAt(0)), left, right); + __ orr(ToRegister(instr->temp()), left, right); } if (can_overflow) { @@ -1377,7 +1485,7 @@ void LCodeGen::DoMulI(LMulI* instr) { Label done; __ cmp(result, Operand(0)); __ b(ne, &done); - __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); + __ cmp(ToRegister(instr->temp()), Operand(0)); DeoptimizeIf(mi, instr->environment()); __ bind(&done); } @@ -1386,8 +1494,8 @@ void LCodeGen::DoMulI(LMulI* instr) { void LCodeGen::DoBitI(LBitI* instr) { - LOperand* left_op = instr->InputAt(0); - LOperand* right_op = instr->InputAt(1); + LOperand* left_op = instr->left(); + LOperand* right_op = instr->right(); ASSERT(left_op->IsRegister()); Register left = ToRegister(left_op); Register result = ToRegister(instr->result()); @@ -1420,14 +1528,17 @@ void LCodeGen::DoBitI(LBitI* instr) { void LCodeGen::DoShiftI(LShiftI* instr) { // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so // result may alias either of them. - LOperand* right_op = instr->InputAt(1); - Register left = ToRegister(instr->InputAt(0)); + LOperand* right_op = instr->right(); + Register left = ToRegister(instr->left()); Register result = ToRegister(instr->result()); Register scratch = scratch0(); if (right_op->IsRegister()) { // Mask the right_op operand. __ and_(scratch, ToRegister(right_op), Operand(0x1F)); switch (instr->op()) { + case Token::ROR: + __ mov(result, Operand(left, ROR, scratch)); + break; case Token::SAR: __ mov(result, Operand(left, ASR, scratch)); break; @@ -1451,6 +1562,13 @@ void LCodeGen::DoShiftI(LShiftI* instr) { int value = ToInteger32(LConstantOperand::cast(right_op)); uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); switch (instr->op()) { + case Token::ROR: + if (shift_count != 0) { + __ mov(result, Operand(left, ROR, shift_count)); + } else { + __ Move(result, left); + } + break; case Token::SAR: if (shift_count != 0) { __ mov(result, Operand(left, ASR, shift_count)); @@ -1485,8 +1603,8 @@ void LCodeGen::DoShiftI(LShiftI* instr) { void LCodeGen::DoSubI(LSubI* instr) { - LOperand* left = instr->InputAt(0); - LOperand* right = instr->InputAt(1); + LOperand* left = instr->left(); + LOperand* right = instr->right(); LOperand* result = instr->result(); bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); SBit set_cond = can_overflow ? SetCC : LeaveCC; @@ -1505,6 +1623,27 @@ void LCodeGen::DoSubI(LSubI* instr) { } +void LCodeGen::DoRSubI(LRSubI* instr) { + LOperand* left = instr->left(); + LOperand* right = instr->right(); + LOperand* result = instr->result(); + bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); + SBit set_cond = can_overflow ? SetCC : LeaveCC; + + if (right->IsStackSlot() || right->IsArgument()) { + Register right_reg = EmitLoadRegister(right, ip); + __ rsb(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); + } else { + ASSERT(right->IsRegister() || right->IsConstantOperand()); + __ rsb(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); + } + + if (can_overflow) { + DeoptimizeIf(vs, instr->environment()); + } +} + + void LCodeGen::DoConstantI(LConstantI* instr) { ASSERT(instr->result()->IsRegister()); __ mov(ToRegister(instr->result()), Operand(instr->value())); @@ -1515,7 +1654,7 @@ void LCodeGen::DoConstantD(LConstantD* instr) { ASSERT(instr->result()->IsDoubleRegister()); DwVfpRegister result = ToDoubleRegister(instr->result()); double v = instr->value(); - __ Vmov(result, v); + __ Vmov(result, v, scratch0()); } @@ -1532,28 +1671,28 @@ void LCodeGen::DoConstantT(LConstantT* instr) { void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { Register result = ToRegister(instr->result()); - Register array = ToRegister(instr->InputAt(0)); + Register array = ToRegister(instr->value()); __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); } void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { Register result = ToRegister(instr->result()); - Register array = ToRegister(instr->InputAt(0)); + Register array = ToRegister(instr->value()); __ ldr(result, FieldMemOperand(array, FixedArrayBase::kLengthOffset)); } void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { Register result = ToRegister(instr->result()); - Register map = ToRegister(instr->InputAt(0)); + Register map = ToRegister(instr->value()); __ EnumLength(result, map); } void LCodeGen::DoElementsKind(LElementsKind* instr) { Register result = ToRegister(instr->result()); - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); // Load map into |result|. __ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset)); @@ -1566,9 +1705,9 @@ void LCodeGen::DoElementsKind(LElementsKind* instr) { void LCodeGen::DoValueOf(LValueOf* instr) { - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); Register result = ToRegister(instr->result()); - Register map = ToRegister(instr->TempAt(0)); + Register map = ToRegister(instr->temp()); Label done; // If the object is a smi return the object. @@ -1587,9 +1726,9 @@ void LCodeGen::DoValueOf(LValueOf* instr) { void LCodeGen::DoDateField(LDateField* instr) { - Register object = ToRegister(instr->InputAt(0)); + Register object = ToRegister(instr->date()); Register result = ToRegister(instr->result()); - Register scratch = ToRegister(instr->TempAt(0)); + Register scratch = ToRegister(instr->temp()); Smi* index = instr->index(); Label runtime, done; ASSERT(object.is(result)); @@ -1625,15 +1764,24 @@ void LCodeGen::DoDateField(LDateField* instr) { } +void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { + SeqStringSetCharGenerator::Generate(masm(), + instr->encoding(), + ToRegister(instr->string()), + ToRegister(instr->index()), + ToRegister(instr->value())); +} + + void LCodeGen::DoBitNotI(LBitNotI* instr) { - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); Register result = ToRegister(instr->result()); __ mvn(result, Operand(input)); } void LCodeGen::DoThrow(LThrow* instr) { - Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); + Register input_reg = EmitLoadRegister(instr->value(), ip); __ push(input_reg); CallRuntime(Runtime::kThrow, 1, instr); @@ -1644,8 +1792,8 @@ void LCodeGen::DoThrow(LThrow* instr) { void LCodeGen::DoAddI(LAddI* instr) { - LOperand* left = instr->InputAt(0); - LOperand* right = instr->InputAt(1); + LOperand* left = instr->left(); + LOperand* right = instr->right(); LOperand* result = instr->result(); bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); SBit set_cond = can_overflow ? SetCC : LeaveCC; @@ -1665,8 +1813,8 @@ void LCodeGen::DoAddI(LAddI* instr) { void LCodeGen::DoMathMinMax(LMathMinMax* instr) { - LOperand* left = instr->InputAt(0); - LOperand* right = instr->InputAt(1); + LOperand* left = instr->left(); + LOperand* right = instr->right(); HMathMinMax::Operation operation = instr->hydrogen()->operation(); Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; if (instr->hydrogen()->representation().IsInteger32()) { @@ -1727,8 +1875,8 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) { void LCodeGen::DoArithmeticD(LArithmeticD* instr) { - DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); - DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); + DoubleRegister left = ToDoubleRegister(instr->left()); + DoubleRegister right = ToDoubleRegister(instr->right()); DoubleRegister result = ToDoubleRegister(instr->result()); switch (instr->op()) { case Token::ADD: @@ -1767,8 +1915,8 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) { void LCodeGen::DoArithmeticT(LArithmeticT* instr) { - ASSERT(ToRegister(instr->InputAt(0)).is(r1)); - ASSERT(ToRegister(instr->InputAt(1)).is(r0)); + ASSERT(ToRegister(instr->left()).is(r1)); + ASSERT(ToRegister(instr->right()).is(r0)); ASSERT(ToRegister(instr->result()).is(r0)); BinaryOpStub stub(instr->op(), NO_OVERWRITE); @@ -1813,11 +1961,11 @@ void LCodeGen::DoBranch(LBranch* instr) { Representation r = instr->hydrogen()->value()->representation(); if (r.IsInteger32()) { - Register reg = ToRegister(instr->InputAt(0)); + Register reg = ToRegister(instr->value()); __ cmp(reg, Operand(0)); EmitBranch(true_block, false_block, ne); } else if (r.IsDouble()) { - DoubleRegister reg = ToDoubleRegister(instr->InputAt(0)); + DoubleRegister reg = ToDoubleRegister(instr->value()); Register scratch = scratch0(); // Test the double value. Zero and NaN are false. @@ -1826,7 +1974,7 @@ void LCodeGen::DoBranch(LBranch* instr) { EmitBranch(true_block, false_block, eq); } else { ASSERT(r.IsTagged()); - Register reg = ToRegister(instr->InputAt(0)); + Register reg = ToRegister(instr->value()); HType type = instr->hydrogen()->value()->type(); if (type.IsBoolean()) { __ CompareRoot(reg, Heap::kTrueValueRootIndex); @@ -1965,8 +2113,8 @@ Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { - LOperand* left = instr->InputAt(0); - LOperand* right = instr->InputAt(1); + LOperand* left = instr->left(); + LOperand* right = instr->right(); int false_block = chunk_->LookupDestination(instr->false_block_id()); int true_block = chunk_->LookupDestination(instr->true_block_id()); Condition cond = TokenToCondition(instr->op(), false); @@ -2006,8 +2154,8 @@ void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { - Register left = ToRegister(instr->InputAt(0)); - Register right = ToRegister(instr->InputAt(1)); + Register left = ToRegister(instr->left()); + Register right = ToRegister(instr->right()); int false_block = chunk_->LookupDestination(instr->false_block_id()); int true_block = chunk_->LookupDestination(instr->true_block_id()); @@ -2017,7 +2165,7 @@ void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { - Register left = ToRegister(instr->InputAt(0)); + Register left = ToRegister(instr->left()); int true_block = chunk_->LookupDestination(instr->true_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id()); @@ -2028,7 +2176,7 @@ void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { Register scratch = scratch0(); - Register reg = ToRegister(instr->InputAt(0)); + Register reg = ToRegister(instr->value()); int false_block = chunk_->LookupDestination(instr->false_block_id()); // If the expression is known to be untagged or a smi, then it's definitely @@ -2096,8 +2244,8 @@ Condition LCodeGen::EmitIsObject(Register input, void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { - Register reg = ToRegister(instr->InputAt(0)); - Register temp1 = ToRegister(instr->TempAt(0)); + Register reg = ToRegister(instr->value()); + Register temp1 = ToRegister(instr->temp()); int true_block = chunk_->LookupDestination(instr->true_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id()); @@ -2122,8 +2270,8 @@ Condition LCodeGen::EmitIsString(Register input, void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { - Register reg = ToRegister(instr->InputAt(0)); - Register temp1 = ToRegister(instr->TempAt(0)); + Register reg = ToRegister(instr->value()); + Register temp1 = ToRegister(instr->temp()); int true_block = chunk_->LookupDestination(instr->true_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id()); @@ -2140,15 +2288,15 @@ void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { int true_block = chunk_->LookupDestination(instr->true_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id()); - Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); + Register input_reg = EmitLoadRegister(instr->value(), ip); __ tst(input_reg, Operand(kSmiTagMask)); EmitBranch(true_block, false_block, eq); } void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { - Register input = ToRegister(instr->InputAt(0)); - Register temp = ToRegister(instr->TempAt(0)); + Register input = ToRegister(instr->value()); + Register temp = ToRegister(instr->temp()); int true_block = chunk_->LookupDestination(instr->true_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id()); @@ -2218,7 +2366,7 @@ static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { Register scratch = scratch0(); - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); int true_block = chunk_->LookupDestination(instr->true_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id()); @@ -2233,10 +2381,10 @@ void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); Register result = ToRegister(instr->result()); - __ AbortIfNotString(input); + __ AssertString(input); __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset)); __ IndexFromHash(result, result); @@ -2245,7 +2393,7 @@ void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { void LCodeGen::DoHasCachedArrayIndexAndBranch( LHasCachedArrayIndexAndBranch* instr) { - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); Register scratch = scratch0(); int true_block = chunk_->LookupDestination(instr->true_block_id()); @@ -2326,9 +2474,9 @@ void LCodeGen::EmitClassOfTest(Label* is_true, void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); Register temp = scratch0(); - Register temp2 = ToRegister(instr->TempAt(0)); + Register temp2 = ToRegister(instr->temp()); Handle<String> class_name = instr->hydrogen()->class_name(); int true_block = chunk_->LookupDestination(instr->true_block_id()); @@ -2344,8 +2492,8 @@ void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { - Register reg = ToRegister(instr->InputAt(0)); - Register temp = ToRegister(instr->TempAt(0)); + Register reg = ToRegister(instr->value()); + Register temp = ToRegister(instr->temp()); int true_block = instr->true_block_id(); int false_block = instr->false_block_id(); @@ -2356,8 +2504,8 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { void LCodeGen::DoInstanceOf(LInstanceOf* instr) { - ASSERT(ToRegister(instr->InputAt(0)).is(r0)); // Object is in r0. - ASSERT(ToRegister(instr->InputAt(1)).is(r1)); // Function is in r1. + ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. + ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. InstanceofStub stub(InstanceofStub::kArgsInRegisters); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); @@ -2388,8 +2536,8 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); Label done, false_result; - Register object = ToRegister(instr->InputAt(0)); - Register temp = ToRegister(instr->TempAt(0)); + Register object = ToRegister(instr->value()); + Register temp = ToRegister(instr->temp()); Register result = ToRegister(instr->result()); ASSERT(object.is(r0)); @@ -2412,6 +2560,7 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { // We use Factory::the_hole_value() on purpose instead of loading from the // root array to force relocation to be able to later patch with // the cached map. + PredictableCodeSizeScope predictable(masm_, 5 * Assembler::kInstrSize); Handle<JSGlobalPropertyCell> cell = factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); __ mov(ip, Operand(Handle<Object>(cell))); @@ -2469,10 +2618,13 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, // Get the temp register reserved by the instruction. This needs to be r4 as // its slot of the pushing of safepoint registers is used to communicate the // offset to the location of the map check. - Register temp = ToRegister(instr->TempAt(0)); + Register temp = ToRegister(instr->temp()); ASSERT(temp.is(r4)); __ LoadHeapObject(InstanceofStub::right(), instr->function()); static const int kAdditionalDelta = 5; + // Make sure that code size is predicable, since we use specific constants + // offsets in the code to find embedded values.. + PredictableCodeSizeScope predictable(masm_, 6 * Assembler::kInstrSize); int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; Label before_push_delta; __ bind(&before_push_delta); @@ -2566,7 +2718,7 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { // it as no longer deleted. if (instr->hydrogen()->RequiresHoleCheck()) { // We use a temp to check the payload (CompareRoot might clobber ip). - Register payload = ToRegister(instr->TempAt(0)); + Register payload = ToRegister(instr->temp()); __ ldr(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); __ CompareRoot(payload, Heap::kTheHoleValueRootIndex); DeoptimizeIf(eq, instr->environment()); @@ -2645,7 +2797,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { - Register object = ToRegister(instr->InputAt(0)); + Register object = ToRegister(instr->object()); Register result = ToRegister(instr->result()); if (instr->hydrogen()->is_in_object()) { __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); @@ -2736,7 +2888,7 @@ void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { if (need_generic) { __ mov(r2, Operand(name)); Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); - CallCode(ic, RelocInfo::CODE_TARGET, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); } __ bind(&done); } @@ -2749,7 +2901,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { // Name is always in r2. __ mov(r2, Operand(instr->name())); Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); - CallCode(ic, RelocInfo::CODE_TARGET, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); } @@ -2799,7 +2951,7 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { void LCodeGen::DoLoadElements(LLoadElements* instr) { Register result = ToRegister(instr->result()); - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->object()); Register scratch = scratch0(); __ ldr(result, FieldMemOperand(input, JSObject::kElementsOffset)); @@ -2834,7 +2986,7 @@ void LCodeGen::DoLoadElements(LLoadElements* instr) { void LCodeGen::DoLoadExternalArrayPointer( LLoadExternalArrayPointer* instr) { Register to_reg = ToRegister(instr->result()); - Register from_reg = ToRegister(instr->InputAt(0)); + Register from_reg = ToRegister(instr->object()); __ ldr(to_reg, FieldMemOperand(from_reg, ExternalArray::kExternalPointerOffset)); } @@ -2845,63 +2997,95 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { Register length = ToRegister(instr->length()); Register index = ToRegister(instr->index()); Register result = ToRegister(instr->result()); - - // Bailout index is not a valid argument index. Use unsigned check to get - // negative check for free. - __ sub(length, length, index, SetCC); - DeoptimizeIf(ls, instr->environment()); - // There are two words between the frame pointer and the last argument. // Subtracting from length accounts for one of them add one more. + __ sub(length, length, index); __ add(length, length, Operand(1)); __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); } -void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { - Register elements = ToRegister(instr->elements()); - Register result = ToRegister(instr->result()); - Register scratch = scratch0(); - Register store_base = scratch; - int offset = 0; - - if (instr->key()->IsConstantOperand()) { - LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); - offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + - instr->additional_index()); - store_base = elements; - } else { - Register key = EmitLoadRegister(instr->key(), scratch0()); - // Even though the HLoadKeyedFastElement instruction forces the input - // representation for the key to be an integer, the input gets replaced - // during bound check elimination with the index argument to the bounds - // check, which can be tagged, so that case must be handled here, too. - if (instr->hydrogen()->key()->representation().IsTagged()) { - __ add(scratch, elements, - Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); - } else { - __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); +void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { + Register external_pointer = ToRegister(instr->elements()); + Register key = no_reg; + ElementsKind elements_kind = instr->elements_kind(); + bool key_is_constant = instr->key()->IsConstantOperand(); + int constant_key = 0; + if (key_is_constant) { + constant_key = ToInteger32(LConstantOperand::cast(instr->key())); + if (constant_key & 0xF0000000) { + Abort("array index constant value too big."); } - offset = FixedArray::OffsetOfElementAt(instr->additional_index()); + } else { + key = ToRegister(instr->key()); } - __ ldr(result, FieldMemOperand(store_base, offset)); + int element_size_shift = ElementsKindToShiftSize(elements_kind); + int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) + ? (element_size_shift - kSmiTagSize) : element_size_shift; + int additional_offset = instr->additional_index() << element_size_shift; - // Check for the hole value. - if (instr->hydrogen()->RequiresHoleCheck()) { - if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { - __ tst(result, Operand(kSmiTagMask)); - DeoptimizeIf(ne, instr->environment()); - } else { - __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); - __ cmp(result, scratch); - DeoptimizeIf(eq, instr->environment()); + if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || + elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { + CpuFeatures::Scope scope(VFP3); + DwVfpRegister result = ToDoubleRegister(instr->result()); + Operand operand = key_is_constant + ? Operand(constant_key << element_size_shift) + : Operand(key, LSL, shift_size); + __ add(scratch0(), external_pointer, operand); + if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { + __ vldr(result.low(), scratch0(), additional_offset); + __ vcvt_f64_f32(result, result.low()); + } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS + __ vldr(result, scratch0(), additional_offset); + } + } else { + Register result = ToRegister(instr->result()); + MemOperand mem_operand = PrepareKeyedOperand( + key, external_pointer, key_is_constant, constant_key, + element_size_shift, shift_size, + instr->additional_index(), additional_offset); + switch (elements_kind) { + case EXTERNAL_BYTE_ELEMENTS: + __ ldrsb(result, mem_operand); + break; + case EXTERNAL_PIXEL_ELEMENTS: + case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: + __ ldrb(result, mem_operand); + break; + case EXTERNAL_SHORT_ELEMENTS: + __ ldrsh(result, mem_operand); + break; + case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: + __ ldrh(result, mem_operand); + break; + case EXTERNAL_INT_ELEMENTS: + __ ldr(result, mem_operand); + break; + case EXTERNAL_UNSIGNED_INT_ELEMENTS: + __ ldr(result, mem_operand); + if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { + __ cmp(result, Operand(0x80000000)); + DeoptimizeIf(cs, instr->environment()); + } + break; + case EXTERNAL_FLOAT_ELEMENTS: + case EXTERNAL_DOUBLE_ELEMENTS: + case FAST_HOLEY_DOUBLE_ELEMENTS: + case FAST_HOLEY_ELEMENTS: + case FAST_HOLEY_SMI_ELEMENTS: + case FAST_DOUBLE_ELEMENTS: + case FAST_ELEMENTS: + case FAST_SMI_ELEMENTS: + case DICTIONARY_ELEMENTS: + case NON_STRICT_ARGUMENTS_ELEMENTS: + UNREACHABLE(); + break; } } } -void LCodeGen::DoLoadKeyedFastDoubleElement( - LLoadKeyedFastDoubleElement* instr) { +void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { Register elements = ToRegister(instr->elements()); bool key_is_constant = instr->key()->IsConstantOperand(); Register key = no_reg; @@ -2933,13 +3117,65 @@ void LCodeGen::DoLoadKeyedFastDoubleElement( (instr->additional_index() << element_size_shift))); } + __ vldr(result, elements, 0); if (instr->hydrogen()->RequiresHoleCheck()) { __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); __ cmp(scratch, Operand(kHoleNanUpper32)); DeoptimizeIf(eq, instr->environment()); } +} - __ vldr(result, elements, 0); + +void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { + Register elements = ToRegister(instr->elements()); + Register result = ToRegister(instr->result()); + Register scratch = scratch0(); + Register store_base = scratch; + int offset = 0; + + if (instr->key()->IsConstantOperand()) { + LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); + offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + + instr->additional_index()); + store_base = elements; + } else { + Register key = EmitLoadRegister(instr->key(), scratch0()); + // Even though the HLoadKeyed instruction forces the input + // representation for the key to be an integer, the input gets replaced + // during bound check elimination with the index argument to the bounds + // check, which can be tagged, so that case must be handled here, too. + if (instr->hydrogen()->key()->representation().IsTagged()) { + __ add(scratch, elements, + Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); + } else { + __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); + } + offset = FixedArray::OffsetOfElementAt(instr->additional_index()); + } + __ ldr(result, FieldMemOperand(store_base, offset)); + + // Check for the hole value. + if (instr->hydrogen()->RequiresHoleCheck()) { + if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { + __ tst(result, Operand(kSmiTagMask)); + DeoptimizeIf(ne, instr->environment()); + } else { + __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); + __ cmp(result, scratch); + DeoptimizeIf(eq, instr->environment()); + } + } +} + + +void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { + if (instr->is_external()) { + DoLoadKeyedExternalArray(instr); + } else if (instr->hydrogen()->representation().IsDouble()) { + DoLoadKeyedFixedDoubleArray(instr); + } else { + DoLoadKeyedFixedArray(instr); + } } @@ -2979,93 +3215,12 @@ MemOperand LCodeGen::PrepareKeyedOperand(Register key, } -void LCodeGen::DoLoadKeyedSpecializedArrayElement( - LLoadKeyedSpecializedArrayElement* instr) { - Register external_pointer = ToRegister(instr->external_pointer()); - Register key = no_reg; - ElementsKind elements_kind = instr->elements_kind(); - bool key_is_constant = instr->key()->IsConstantOperand(); - int constant_key = 0; - if (key_is_constant) { - constant_key = ToInteger32(LConstantOperand::cast(instr->key())); - if (constant_key & 0xF0000000) { - Abort("array index constant value too big."); - } - } else { - key = ToRegister(instr->key()); - } - int element_size_shift = ElementsKindToShiftSize(elements_kind); - int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) - ? (element_size_shift - kSmiTagSize) : element_size_shift; - int additional_offset = instr->additional_index() << element_size_shift; - - if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || - elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { - CpuFeatures::Scope scope(VFP3); - DwVfpRegister result = ToDoubleRegister(instr->result()); - Operand operand = key_is_constant - ? Operand(constant_key << element_size_shift) - : Operand(key, LSL, shift_size); - __ add(scratch0(), external_pointer, operand); - if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { - __ vldr(result.low(), scratch0(), additional_offset); - __ vcvt_f64_f32(result, result.low()); - } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS - __ vldr(result, scratch0(), additional_offset); - } - } else { - Register result = ToRegister(instr->result()); - MemOperand mem_operand = PrepareKeyedOperand( - key, external_pointer, key_is_constant, constant_key, - element_size_shift, shift_size, - instr->additional_index(), additional_offset); - switch (elements_kind) { - case EXTERNAL_BYTE_ELEMENTS: - __ ldrsb(result, mem_operand); - break; - case EXTERNAL_PIXEL_ELEMENTS: - case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: - __ ldrb(result, mem_operand); - break; - case EXTERNAL_SHORT_ELEMENTS: - __ ldrsh(result, mem_operand); - break; - case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: - __ ldrh(result, mem_operand); - break; - case EXTERNAL_INT_ELEMENTS: - __ ldr(result, mem_operand); - break; - case EXTERNAL_UNSIGNED_INT_ELEMENTS: - __ ldr(result, mem_operand); - if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { - __ cmp(result, Operand(0x80000000)); - DeoptimizeIf(cs, instr->environment()); - } - break; - case EXTERNAL_FLOAT_ELEMENTS: - case EXTERNAL_DOUBLE_ELEMENTS: - case FAST_HOLEY_DOUBLE_ELEMENTS: - case FAST_HOLEY_ELEMENTS: - case FAST_HOLEY_SMI_ELEMENTS: - case FAST_DOUBLE_ELEMENTS: - case FAST_ELEMENTS: - case FAST_SMI_ELEMENTS: - case DICTIONARY_ELEMENTS: - case NON_STRICT_ARGUMENTS_ELEMENTS: - UNREACHABLE(); - break; - } - } -} - - void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { ASSERT(ToRegister(instr->object()).is(r1)); ASSERT(ToRegister(instr->key()).is(r0)); Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); - CallCode(ic, RelocInfo::CODE_TARGET, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); } @@ -3091,7 +3246,7 @@ void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { - Register elem = ToRegister(instr->InputAt(0)); + Register elem = ToRegister(instr->elements()); Register result = ToRegister(instr->result()); Label done; @@ -3210,7 +3365,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { void LCodeGen::DoPushArgument(LPushArgument* instr) { - LOperand* argument = instr->InputAt(0); + LOperand* argument = instr->value(); if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { Abort("DoPushArgument not implemented for double type."); } else { @@ -3262,7 +3417,7 @@ void LCodeGen::DoGlobalObject(LGlobalObject* instr) { void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { - Register global = ToRegister(instr->global()); + Register global = ToRegister(instr->global_object()); Register result = ToRegister(instr->result()); __ ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); } @@ -3322,7 +3477,7 @@ void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); Register result = ToRegister(instr->result()); Register scratch = scratch0(); @@ -3388,7 +3543,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); Register result = ToRegister(instr->result()); __ cmp(input, Operand(0)); __ Move(result, input, pl); @@ -3418,7 +3573,7 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { Representation r = instr->hydrogen()->value()->representation(); if (r.IsDouble()) { - DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); + DwVfpRegister input = ToDoubleRegister(instr->value()); DwVfpRegister result = ToDoubleRegister(instr->result()); __ vabs(result, input); } else if (r.IsInteger32()) { @@ -3427,7 +3582,7 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { // Representation is tagged. DeferredMathAbsTaggedHeapNumber* deferred = new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); // Smi check. __ JumpIfNotSmi(input, deferred->entry()); // If smi, handle it directly. @@ -3438,29 +3593,24 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { - DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); + DoubleRegister input = ToDoubleRegister(instr->value()); Register result = ToRegister(instr->result()); - SwVfpRegister single_scratch = double_scratch0().low(); - Register scratch1 = scratch0(); - Register scratch2 = ToRegister(instr->TempAt(0)); + Register scratch = scratch0(); __ EmitVFPTruncate(kRoundToMinusInf, - single_scratch, + result, input, - scratch1, - scratch2); + scratch, + double_scratch0()); DeoptimizeIf(ne, instr->environment()); - // Move the result back to general purpose register r0. - __ vmov(result, single_scratch); - if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { // Test for -0. Label done; __ cmp(result, Operand(0)); __ b(ne, &done); - __ vmov(scratch1, input.high()); - __ tst(scratch1, Operand(HeapNumber::kSignMask)); + __ vmov(scratch, input.high()); + __ tst(scratch, Operand(HeapNumber::kSignMask)); DeoptimizeIf(ne, instr->environment()); __ bind(&done); } @@ -3468,8 +3618,9 @@ void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { - DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); + DoubleRegister input = ToDoubleRegister(instr->value()); Register result = ToRegister(instr->result()); + DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp()); Register scratch = scratch0(); Label done, check_sign_on_zero; @@ -3494,12 +3645,12 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { __ cmp(scratch, Operand(HeapNumber::kExponentBias + 32)); DeoptimizeIf(ge, instr->environment()); + __ Vmov(double_scratch0(), 0.5, scratch); + __ vadd(double_scratch0(), input, double_scratch0()); + // Save the original sign for later comparison. __ and_(scratch, result, Operand(HeapNumber::kSignMask)); - __ Vmov(double_scratch0(), 0.5); - __ vadd(double_scratch0(), input, double_scratch0()); - // Check sign of the result: if the sign changed, the input // value was in ]0.5, 0[ and the result should be -0. __ vmov(result, double_scratch0().high()); @@ -3512,12 +3663,11 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { } __ EmitVFPTruncate(kRoundToMinusInf, - double_scratch0().low(), - double_scratch0(), result, - scratch); + double_scratch0(), + scratch, + double_scratch1); DeoptimizeIf(ne, instr->environment()); - __ vmov(result, double_scratch0().low()); if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { // Test for -0. @@ -3533,22 +3683,22 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { - DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); + DoubleRegister input = ToDoubleRegister(instr->value()); DoubleRegister result = ToDoubleRegister(instr->result()); __ vsqrt(result, input); } void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { - DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); + DoubleRegister input = ToDoubleRegister(instr->value()); DoubleRegister result = ToDoubleRegister(instr->result()); - DoubleRegister temp = ToDoubleRegister(instr->TempAt(0)); + DoubleRegister temp = ToDoubleRegister(instr->temp()); // Note that according to ECMA-262 15.8.2.13: // Math.pow(-Infinity, 0.5) == Infinity // Math.sqrt(-Infinity) == NaN Label done; - __ vmov(temp, -V8_INFINITY); + __ vmov(temp, -V8_INFINITY, scratch0()); __ VFPCompareAndSetFlags(input, temp); __ vneg(result, temp, eq); __ b(&done, eq); @@ -3564,11 +3714,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. - ASSERT(!instr->InputAt(1)->IsDoubleRegister() || - ToDoubleRegister(instr->InputAt(1)).is(d2)); - ASSERT(!instr->InputAt(1)->IsRegister() || - ToRegister(instr->InputAt(1)).is(r2)); - ASSERT(ToDoubleRegister(instr->InputAt(0)).is(d1)); + ASSERT(!instr->right()->IsDoubleRegister() || + ToDoubleRegister(instr->right()).is(d2)); + ASSERT(!instr->right()->IsRegister() || + ToRegister(instr->right()).is(r2)); + ASSERT(ToDoubleRegister(instr->left()).is(d1)); ASSERT(ToDoubleRegister(instr->result()).is(d3)); if (exponent_type.IsTagged()) { @@ -3608,7 +3758,7 @@ void LCodeGen::DoRandom(LRandom* instr) { // Having marked this instruction as a call we can use any // registers. ASSERT(ToDoubleRegister(instr->result()).is(d7)); - ASSERT(ToRegister(instr->InputAt(0)).is(r0)); + ASSERT(ToRegister(instr->global_object()).is(r0)); static const int kSeedSize = sizeof(uint32_t); STATIC_ASSERT(kPointerSize == kSeedSize); @@ -3670,6 +3820,20 @@ void LCodeGen::DoDeferredRandom(LRandom* instr) { } +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()); + + MathExpGenerator::EmitMathExp( + masm(), input, result, double_scratch1, double_scratch2, + temp1, temp2, scratch0()); +} + + void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { ASSERT(ToDoubleRegister(instr->result()).is(d2)); TranscendentalCacheStub stub(TranscendentalCache::LOG, @@ -3765,7 +3929,7 @@ void LCodeGen::DoCallKeyed(LCallKeyed* instr) { int arity = instr->arity(); Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); - CallCode(ic, RelocInfo::CODE_TARGET, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); } @@ -3778,7 +3942,7 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) { Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arity, mode); __ mov(r2, Operand(instr->name())); - CallCode(ic, mode, instr); + CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); } @@ -3803,7 +3967,7 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) { Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arity, mode); __ mov(r2, Operand(instr->name())); - CallCode(ic, mode, instr); + CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); } @@ -3819,7 +3983,7 @@ void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { void LCodeGen::DoCallNew(LCallNew* instr) { - ASSERT(ToRegister(instr->InputAt(0)).is(r1)); + ASSERT(ToRegister(instr->constructor()).is(r1)); ASSERT(ToRegister(instr->result()).is(r0)); CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); @@ -3845,7 +4009,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { __ mov(scratch, Operand(instr->transition())); __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); if (instr->hydrogen()->NeedsWriteBarrierForMap()) { - Register temp = ToRegister(instr->TempAt(0)); + Register temp = ToRegister(instr->temp()); // Update the write barrier for the map field. __ RecordWriteField(object, HeapObject::kMapOffset, @@ -3903,7 +4067,7 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) ? isolate()->builtins()->StoreIC_Initialize_Strict() : isolate()->builtins()->StoreIC_Initialize(); - CallCode(ic, RelocInfo::CODE_TARGET, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); } @@ -3945,102 +4109,8 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { } -void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { - Register value = ToRegister(instr->value()); - Register elements = ToRegister(instr->object()); - Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; - Register scratch = scratch0(); - Register store_base = scratch; - int offset = 0; - - // Do the store. - if (instr->key()->IsConstantOperand()) { - ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); - LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); - offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + - instr->additional_index()); - store_base = elements; - } else { - // Even though the HLoadKeyedFastElement instruction forces the input - // representation for the key to be an integer, the input gets replaced - // during bound check elimination with the index argument to the bounds - // check, which can be tagged, so that case must be handled here, too. - if (instr->hydrogen()->key()->representation().IsTagged()) { - __ add(scratch, elements, - Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); - } else { - __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); - } - offset = FixedArray::OffsetOfElementAt(instr->additional_index()); - } - __ str(value, FieldMemOperand(store_base, offset)); - - if (instr->hydrogen()->NeedsWriteBarrier()) { - HType type = instr->hydrogen()->value()->type(); - SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; - // Compute address of modified element and store it into key register. - __ add(key, store_base, Operand(offset - kHeapObjectTag)); - __ RecordWrite(elements, - key, - value, - kLRHasBeenSaved, - kSaveFPRegs, - EMIT_REMEMBERED_SET, - check_needed); - } -} - - -void LCodeGen::DoStoreKeyedFastDoubleElement( - LStoreKeyedFastDoubleElement* instr) { - DwVfpRegister value = ToDoubleRegister(instr->value()); - Register elements = ToRegister(instr->elements()); - Register key = no_reg; - Register scratch = scratch0(); - bool key_is_constant = instr->key()->IsConstantOperand(); - int constant_key = 0; - - // Calculate the effective address of the slot in the array to store the - // double value. - if (key_is_constant) { - constant_key = ToInteger32(LConstantOperand::cast(instr->key())); - if (constant_key & 0xF0000000) { - Abort("array index constant value too big."); - } - } else { - key = ToRegister(instr->key()); - } - int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); - int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) - ? (element_size_shift - kSmiTagSize) : element_size_shift; - Operand operand = key_is_constant - ? Operand((constant_key << element_size_shift) + - FixedDoubleArray::kHeaderSize - kHeapObjectTag) - : Operand(key, LSL, shift_size); - __ add(scratch, elements, operand); - if (!key_is_constant) { - __ add(scratch, scratch, - Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); - } - - if (instr->NeedsCanonicalization()) { - // Check for NaN. All NaNs must be canonicalized. - __ VFPCompareAndSetFlags(value, value); - // Only load canonical NaN if the comparison above set the overflow. - __ Vmov(value, - FixedDoubleArray::canonical_not_the_hole_nan_as_double(), - vs); - } - - __ vstr(value, scratch, instr->additional_index() << element_size_shift); -} - - -void LCodeGen::DoStoreKeyedSpecializedArrayElement( - LStoreKeyedSpecializedArrayElement* instr) { - - Register external_pointer = ToRegister(instr->external_pointer()); +void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { + Register external_pointer = ToRegister(instr->elements()); Register key = no_reg; ElementsKind elements_kind = instr->elements_kind(); bool key_is_constant = instr->key()->IsConstantOperand(); @@ -4109,6 +4179,110 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement( } +void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { + DwVfpRegister value = ToDoubleRegister(instr->value()); + Register elements = ToRegister(instr->elements()); + Register key = no_reg; + Register scratch = scratch0(); + bool key_is_constant = instr->key()->IsConstantOperand(); + int constant_key = 0; + + // Calculate the effective address of the slot in the array to store the + // double value. + if (key_is_constant) { + constant_key = ToInteger32(LConstantOperand::cast(instr->key())); + if (constant_key & 0xF0000000) { + Abort("array index constant value too big."); + } + } else { + key = ToRegister(instr->key()); + } + int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); + int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) + ? (element_size_shift - kSmiTagSize) : element_size_shift; + Operand operand = key_is_constant + ? Operand((constant_key << element_size_shift) + + FixedDoubleArray::kHeaderSize - kHeapObjectTag) + : Operand(key, LSL, shift_size); + __ add(scratch, elements, operand); + if (!key_is_constant) { + __ add(scratch, scratch, + Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); + } + + if (instr->NeedsCanonicalization()) { + // Check for NaN. All NaNs must be canonicalized. + __ VFPCompareAndSetFlags(value, value); + // Only load canonical NaN if the comparison above set the overflow. + __ Vmov(value, + FixedDoubleArray::canonical_not_the_hole_nan_as_double(), + no_reg, vs); + } + + __ vstr(value, scratch, instr->additional_index() << element_size_shift); +} + + +void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { + Register value = ToRegister(instr->value()); + Register elements = ToRegister(instr->elements()); + Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) + : no_reg; + Register scratch = scratch0(); + Register store_base = scratch; + int offset = 0; + + // Do the store. + if (instr->key()->IsConstantOperand()) { + ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); + LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); + offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + + instr->additional_index()); + store_base = elements; + } else { + // Even though the HLoadKeyed instruction forces the input + // representation for the key to be an integer, the input gets replaced + // during bound check elimination with the index argument to the bounds + // check, which can be tagged, so that case must be handled here, too. + if (instr->hydrogen()->key()->representation().IsTagged()) { + __ add(scratch, elements, + Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); + } else { + __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); + } + offset = FixedArray::OffsetOfElementAt(instr->additional_index()); + } + __ str(value, FieldMemOperand(store_base, offset)); + + if (instr->hydrogen()->NeedsWriteBarrier()) { + HType type = instr->hydrogen()->value()->type(); + SmiCheck check_needed = + type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + // Compute address of modified element and store it into key register. + __ add(key, store_base, Operand(offset - kHeapObjectTag)); + __ RecordWrite(elements, + key, + value, + kLRHasBeenSaved, + kSaveFPRegs, + EMIT_REMEMBERED_SET, + check_needed); + } +} + + +void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { + // By cases: external, fast double + if (instr->is_external()) { + DoStoreKeyedExternalArray(instr); + } else if (instr->hydrogen()->value()->representation().IsDouble()) { + DoStoreKeyedFixedDoubleArray(instr); + } else { + DoStoreKeyedFixedArray(instr); + } +} + + void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { ASSERT(ToRegister(instr->object()).is(r2)); ASSERT(ToRegister(instr->key()).is(r1)); @@ -4117,13 +4291,13 @@ void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() : isolate()->builtins()->KeyedStoreIC_Initialize(); - CallCode(ic, RelocInfo::CODE_TARGET, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); } void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { Register object_reg = ToRegister(instr->object()); - Register new_map_reg = ToRegister(instr->new_map_reg()); + Register new_map_reg = ToRegister(instr->new_map_temp()); Register scratch = scratch0(); Handle<Map> from_map = instr->original_map(); @@ -4144,7 +4318,7 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { scratch, kLRHasBeenSaved, kDontSaveFPRegs); } else if (IsFastSmiElementsKind(from_kind) && IsFastDoubleElementsKind(to_kind)) { - Register fixed_object_reg = ToRegister(instr->temp_reg()); + Register fixed_object_reg = ToRegister(instr->temp()); ASSERT(fixed_object_reg.is(r2)); ASSERT(new_map_reg.is(r3)); __ mov(fixed_object_reg, object_reg); @@ -4152,7 +4326,7 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { RelocInfo::CODE_TARGET, instr); } else if (IsFastDoubleElementsKind(from_kind) && IsFastObjectElementsKind(to_kind)) { - Register fixed_object_reg = ToRegister(instr->temp_reg()); + Register fixed_object_reg = ToRegister(instr->temp()); ASSERT(fixed_object_reg.is(r2)); ASSERT(new_map_reg.is(r3)); __ mov(fixed_object_reg, object_reg); @@ -4220,9 +4394,7 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { __ push(index); } CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); - if (FLAG_debug_code) { - __ AbortIfNotSmi(r0); - } + __ AssertSmi(r0); __ SmiUntag(r0); __ StoreToSafepointRegisterSlot(r0, result); } @@ -4277,14 +4449,14 @@ void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { void LCodeGen::DoStringLength(LStringLength* instr) { - Register string = ToRegister(instr->InputAt(0)); + Register string = ToRegister(instr->string()); Register result = ToRegister(instr->result()); __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); } void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { - LOperand* input = instr->InputAt(0); + LOperand* input = instr->value(); ASSERT(input->IsRegister() || input->IsStackSlot()); LOperand* output = instr->result(); ASSERT(output->IsDoubleRegister()); @@ -4301,7 +4473,7 @@ void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { - LOperand* input = instr->InputAt(0); + LOperand* input = instr->value(); LOperand* output = instr->result(); SwVfpRegister flt_scratch = double_scratch0().low(); @@ -4317,7 +4489,7 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) { : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_, - instr_->InputAt(0), + instr_->value(), SIGNED_INT32); } virtual LInstruction* instr() { return instr_; } @@ -4325,7 +4497,7 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) { LNumberTagI* instr_; }; - Register src = ToRegister(instr->InputAt(0)); + Register src = ToRegister(instr->value()); Register dst = ToRegister(instr->result()); DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); @@ -4342,7 +4514,7 @@ void LCodeGen::DoNumberTagU(LNumberTagU* instr) { : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_, - instr_->InputAt(0), + instr_->value(), UNSIGNED_INT32); } virtual LInstruction* instr() { return instr_; } @@ -4350,7 +4522,7 @@ void LCodeGen::DoNumberTagU(LNumberTagU* instr) { LNumberTagU* instr_; }; - LOperand* input = instr->InputAt(0); + LOperand* input = instr->value(); ASSERT(input->IsRegister() && input->Equals(instr->result())); Register reg = ToRegister(input); @@ -4392,7 +4564,7 @@ void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, if (FLAG_inline_new) { __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); - __ AllocateHeapNumber(r5, r3, r4, r6, &slow); + __ AllocateHeapNumber(r5, r3, r4, r6, &slow, DONT_TAG_RESULT); __ Move(dst, r5); __ b(&done); } @@ -4407,12 +4579,13 @@ void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, __ StoreToSafepointRegisterSlot(ip, dst); CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); __ Move(dst, r0); + __ sub(dst, dst, Operand(kHeapObjectTag)); // Done. Put the value in dbl_scratch into the value of the allocated heap // number. __ bind(&done); - __ sub(ip, dst, Operand(kHeapObjectTag)); - __ vstr(dbl_scratch, ip, HeapNumber::kValueOffset); + __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); + __ add(dst, dst, Operand(kHeapObjectTag)); __ StoreToSafepointRegisterSlot(dst, dst); } @@ -4428,22 +4601,25 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) { LNumberTagD* instr_; }; - DoubleRegister input_reg = ToDoubleRegister(instr->InputAt(0)); + DoubleRegister input_reg = ToDoubleRegister(instr->value()); Register scratch = scratch0(); Register reg = ToRegister(instr->result()); - Register temp1 = ToRegister(instr->TempAt(0)); - Register temp2 = ToRegister(instr->TempAt(1)); + Register temp1 = ToRegister(instr->temp()); + Register temp2 = ToRegister(instr->temp2()); DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); if (FLAG_inline_new) { __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); - __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); + // We want the untagged address first for performance + __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), + DONT_TAG_RESULT); } else { __ jmp(deferred->entry()); } __ bind(deferred->exit()); - __ sub(ip, reg, Operand(kHeapObjectTag)); - __ vstr(input_reg, ip, HeapNumber::kValueOffset); + __ vstr(input_reg, reg, HeapNumber::kValueOffset); + // Now that we have finished with the object's real address tag it + __ add(reg, reg, Operand(kHeapObjectTag)); } @@ -4456,18 +4632,19 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); + __ sub(r0, r0, Operand(kHeapObjectTag)); __ StoreToSafepointRegisterSlot(r0, reg); } void LCodeGen::DoSmiTag(LSmiTag* instr) { ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); - __ SmiTag(ToRegister(instr->result()), ToRegister(instr->InputAt(0))); + __ SmiTag(ToRegister(instr->result()), ToRegister(instr->value())); } void LCodeGen::DoSmiUntag(LSmiUntag* instr) { - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); Register result = ToRegister(instr->result()); if (instr->needs_check()) { STATIC_ASSERT(kHeapObjectTag == 1); @@ -4539,11 +4716,11 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { - Register input_reg = ToRegister(instr->InputAt(0)); + Register input_reg = ToRegister(instr->value()); Register scratch1 = scratch0(); - Register scratch2 = ToRegister(instr->TempAt(0)); + Register scratch2 = ToRegister(instr->temp()); DwVfpRegister double_scratch = double_scratch0(); - SwVfpRegister single_scratch = double_scratch.low(); + DwVfpRegister double_scratch2 = ToDoubleRegister(instr->temp3()); ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); @@ -4562,8 +4739,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { __ cmp(scratch1, Operand(ip)); if (instr->truncating()) { - Register scratch3 = ToRegister(instr->TempAt(1)); - DwVfpRegister double_scratch2 = ToDoubleRegister(instr->TempAt(2)); + Register scratch3 = ToRegister(instr->temp2()); ASSERT(!scratch3.is(input_reg) && !scratch3.is(scratch1) && !scratch3.is(scratch2)); @@ -4585,7 +4761,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { __ EmitECMATruncate(input_reg, double_scratch2, - single_scratch, + double_scratch, scratch1, scratch2, scratch3); @@ -4598,14 +4774,12 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { __ sub(ip, input_reg, Operand(kHeapObjectTag)); __ vldr(double_scratch, ip, HeapNumber::kValueOffset); __ EmitVFPTruncate(kRoundToZero, - single_scratch, + input_reg, double_scratch, scratch1, - scratch2, + double_scratch2, kCheckForInexactConversion); DeoptimizeIf(ne, instr->environment()); - // Load the result. - __ vmov(input_reg, single_scratch); if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { __ cmp(input_reg, Operand(0)); @@ -4630,7 +4804,7 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) { LTaggedToI* instr_; }; - LOperand* input = instr->InputAt(0); + LOperand* input = instr->value(); ASSERT(input->IsRegister()); ASSERT(input->Equals(instr->result())); @@ -4649,7 +4823,7 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) { void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { - LOperand* input = instr->InputAt(0); + LOperand* input = instr->value(); ASSERT(input->IsRegister()); LOperand* result = instr->result(); ASSERT(result->IsDoubleRegister()); @@ -4667,54 +4841,52 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { void LCodeGen::DoDoubleToI(LDoubleToI* instr) { Register result_reg = ToRegister(instr->result()); Register scratch1 = scratch0(); - Register scratch2 = ToRegister(instr->TempAt(0)); - DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0)); - SwVfpRegister single_scratch = double_scratch0().low(); + Register scratch2 = ToRegister(instr->temp()); + DwVfpRegister double_input = ToDoubleRegister(instr->value()); + DwVfpRegister double_scratch = double_scratch0(); Label done; if (instr->truncating()) { - Register scratch3 = ToRegister(instr->TempAt(1)); + Register scratch3 = ToRegister(instr->temp2()); __ EmitECMATruncate(result_reg, double_input, - single_scratch, + double_scratch, scratch1, scratch2, scratch3); } else { - VFPRoundingMode rounding_mode = kRoundToMinusInf; - __ EmitVFPTruncate(rounding_mode, - single_scratch, + __ EmitVFPTruncate(kRoundToMinusInf, + result_reg, double_input, scratch1, - scratch2, + double_scratch, kCheckForInexactConversion); + // Deoptimize if we had a vfp invalid exception, // including inexact operation. DeoptimizeIf(ne, instr->environment()); - // Retrieve the result. - __ vmov(result_reg, single_scratch); } __ bind(&done); } void LCodeGen::DoCheckSmi(LCheckSmi* instr) { - LOperand* input = instr->InputAt(0); + LOperand* input = instr->value(); __ tst(ToRegister(input), Operand(kSmiTagMask)); DeoptimizeIf(ne, instr->environment()); } void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { - LOperand* input = instr->InputAt(0); + LOperand* input = instr->value(); __ tst(ToRegister(input), Operand(kSmiTagMask)); DeoptimizeIf(eq, instr->environment()); } void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); Register scratch = scratch0(); __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); @@ -4787,7 +4959,7 @@ void LCodeGen::DoCheckMapCommon(Register reg, void LCodeGen::DoCheckMaps(LCheckMaps* instr) { Register scratch = scratch0(); - LOperand* input = instr->InputAt(0); + LOperand* input = instr->value(); ASSERT(input->IsRegister()); Register reg = ToRegister(input); @@ -4807,7 +4979,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) { void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); Register result_reg = ToRegister(instr->result()); - DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0)); + DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); } @@ -4823,7 +4995,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { Register scratch = scratch0(); Register input_reg = ToRegister(instr->unclamped()); Register result_reg = ToRegister(instr->result()); - DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0)); + DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); Label is_smi, done, heap_number; // Both smi and heap number cases are handled. @@ -4857,8 +5029,9 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { - Register temp1 = ToRegister(instr->TempAt(0)); - Register temp2 = ToRegister(instr->TempAt(1)); + ASSERT(instr->temp()->Equals(instr->result())); + Register temp1 = ToRegister(instr->temp()); + Register temp2 = ToRegister(instr->temp2()); Handle<JSObject> holder = instr->holder(); Handle<JSObject> current_prototype = instr->prototype(); @@ -4881,7 +5054,6 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { DoCheckMapCommon(temp1, temp2, Handle<Map>(current_prototype->map()), ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); - DeoptimizeIf(ne, instr->environment()); } @@ -4900,8 +5072,8 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) { new(zone()) DeferredAllocateObject(this, instr); Register result = ToRegister(instr->result()); - Register scratch = ToRegister(instr->TempAt(0)); - Register scratch2 = ToRegister(instr->TempAt(1)); + Register scratch = ToRegister(instr->temp()); + Register scratch2 = ToRegister(instr->temp2()); Handle<JSFunction> constructor = instr->hydrogen()->constructor(); Handle<Map> initial_map(constructor->initial_map()); int instance_size = initial_map->instance_size(); @@ -5193,7 +5365,7 @@ void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { void LCodeGen::DoToFastProperties(LToFastProperties* instr) { - ASSERT(ToRegister(instr->InputAt(0)).is(r0)); + ASSERT(ToRegister(instr->value()).is(r0)); __ push(r0); CallRuntime(Runtime::kToFastProperties, 1, instr); } @@ -5274,14 +5446,14 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { void LCodeGen::DoTypeof(LTypeof* instr) { - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); __ push(input); CallRuntime(Runtime::kTypeof, 1, instr); } void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { - Register input = ToRegister(instr->InputAt(0)); + Register input = ToRegister(instr->value()); int true_block = chunk_->LookupDestination(instr->true_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id()); Label* true_label = chunk_->GetAssemblyLabel(true_block); @@ -5371,7 +5543,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { - Register temp1 = ToRegister(instr->TempAt(0)); + Register temp1 = ToRegister(instr->temp()); int true_block = chunk_->LookupDestination(instr->true_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id()); @@ -5492,6 +5664,7 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) { __ cmp(sp, Operand(ip)); __ b(hs, &done); StackCheckStub stub; + PredictableCodeSizeScope predictable(masm_, 2 * Assembler::kInstrSize); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); EnsureSpaceForLazyDeopt(); __ bind(&done); @@ -5572,7 +5745,6 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { Register map = ToRegister(instr->map()); Register result = ToRegister(instr->result()); - Register scratch = ToRegister(instr->scratch()); Label load_cache, done; __ EnumLength(result, map); __ cmp(result, Operand(Smi::FromInt(0))); @@ -5581,7 +5753,7 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { __ jmp(&done); __ bind(&load_cache); - __ LoadInstanceDescriptors(map, result, scratch); + __ LoadInstanceDescriptors(map, result); __ ldr(result, FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); __ ldr(result, |