diff options
Diffstat (limited to 'deps/v8/src/mips/lithium-codegen-mips.cc')
-rw-r--r-- | deps/v8/src/mips/lithium-codegen-mips.cc | 936 |
1 files changed, 477 insertions, 459 deletions
diff --git a/deps/v8/src/mips/lithium-codegen-mips.cc b/deps/v8/src/mips/lithium-codegen-mips.cc index fe3e349c2..8cf77607a 100644 --- a/deps/v8/src/mips/lithium-codegen-mips.cc +++ b/deps/v8/src/mips/lithium-codegen-mips.cc @@ -25,13 +25,13 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "v8.h" +#include "src/v8.h" -#include "mips/lithium-codegen-mips.h" -#include "mips/lithium-gap-resolver-mips.h" -#include "code-stubs.h" -#include "stub-cache.h" -#include "hydrogen-osr.h" +#include "src/code-stubs.h" +#include "src/hydrogen-osr.h" +#include "src/mips/lithium-codegen-mips.h" +#include "src/mips/lithium-gap-resolver-mips.h" +#include "src/stub-cache.h" namespace v8 { namespace internal { @@ -64,7 +64,7 @@ class SafepointGenerator V8_FINAL : public CallWrapper { bool LCodeGen::GenerateCode() { LPhase phase("Z_Code generation", chunk()); - ASSERT(is_unused()); + DCHECK(is_unused()); status_ = GENERATING; // Open a frame scope to indicate that there is a frame on the stack. The @@ -81,7 +81,7 @@ bool LCodeGen::GenerateCode() { void LCodeGen::FinishCode(Handle<Code> code) { - ASSERT(is_done()); + DCHECK(is_done()); code->set_stack_slots(GetStackSlotCount()); code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); @@ -90,8 +90,8 @@ void LCodeGen::FinishCode(Handle<Code> code) { void LCodeGen::SaveCallerDoubles() { - ASSERT(info()->saves_caller_doubles()); - ASSERT(NeedsEagerFrame()); + DCHECK(info()->saves_caller_doubles()); + DCHECK(NeedsEagerFrame()); Comment(";;; Save clobbered callee double registers"); int count = 0; BitVector* doubles = chunk()->allocated_double_registers(); @@ -106,8 +106,8 @@ void LCodeGen::SaveCallerDoubles() { void LCodeGen::RestoreCallerDoubles() { - ASSERT(info()->saves_caller_doubles()); - ASSERT(NeedsEagerFrame()); + DCHECK(info()->saves_caller_doubles()); + DCHECK(NeedsEagerFrame()); Comment(";;; Restore clobbered callee double registers"); BitVector* doubles = chunk()->allocated_double_registers(); BitVector::Iterator save_iterator(doubles); @@ -122,7 +122,7 @@ void LCodeGen::RestoreCallerDoubles() { bool LCodeGen::GeneratePrologue() { - ASSERT(is_generating()); + DCHECK(is_generating()); if (info()->IsOptimizing()) { ProfileEntryHookStub::MaybeCallEntryHook(masm_); @@ -152,7 +152,7 @@ bool LCodeGen::GeneratePrologue() { __ Branch(&ok, ne, a2, Operand(at)); __ lw(a2, GlobalObjectOperand()); - __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset)); + __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset)); __ sw(a2, MemOperand(sp, receiver_offset)); @@ -162,7 +162,11 @@ bool LCodeGen::GeneratePrologue() { info()->set_prologue_offset(masm_->pc_offset()); if (NeedsEagerFrame()) { - __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); + if (info()->IsStub()) { + __ StubPrologue(); + } else { + __ Prologue(info()->IsCodePreAgingActive()); + } frame_is_built_ = true; info_->AddNoFrameRange(0, masm_->pc_offset()); } @@ -194,13 +198,16 @@ bool LCodeGen::GeneratePrologue() { int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; if (heap_slots > 0) { Comment(";;; Allocate local context"); + bool need_write_barrier = true; // Argument to NewContext is the function, which is in a1. if (heap_slots <= FastNewContextStub::kMaximumSlots) { FastNewContextStub stub(isolate(), heap_slots); __ CallStub(&stub); + // Result of FastNewContextStub is always in new space. + need_write_barrier = false; } else { __ push(a1); - __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1); + __ CallRuntime(Runtime::kNewFunctionContext, 1); } RecordSafepoint(Safepoint::kNoLazyDeopt); // Context is returned in both v0. It replaces the context passed to us. @@ -220,8 +227,15 @@ bool LCodeGen::GeneratePrologue() { MemOperand target = ContextOperand(cp, var->index()); __ sw(a0, target); // Update the write barrier. This clobbers a3 and a0. - __ RecordWriteContextSlot( - cp, target.offset(), a0, a3, GetRAState(), kSaveFPRegs); + if (need_write_barrier) { + __ RecordWriteContextSlot( + cp, target.offset(), a0, a3, GetRAState(), kSaveFPRegs); + } else if (FLAG_debug_code) { + Label done; + __ JumpIfInNewSpace(cp, a0, &done); + __ Abort(kExpectedNewSpaceObject); + __ bind(&done); + } } } Comment(";;; End allocate local context"); @@ -247,7 +261,7 @@ void LCodeGen::GenerateOsrPrologue() { // Adjust the frame size, subsuming the unoptimized frame into the // optimized frame. int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); - ASSERT(slots >= 0); + DCHECK(slots >= 0); __ Subu(sp, sp, Operand(slots * kPointerSize)); } @@ -263,7 +277,7 @@ void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { bool LCodeGen::GenerateDeferredCode() { - ASSERT(is_generating()); + DCHECK(is_generating()); if (deferred_.length() > 0) { for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { LDeferredCode* code = deferred_[i]; @@ -281,8 +295,8 @@ bool LCodeGen::GenerateDeferredCode() { __ bind(code->entry()); if (NeedsDeferredFrame()) { Comment(";;; Build frame"); - ASSERT(!frame_is_built_); - ASSERT(info()->IsStub()); + DCHECK(!frame_is_built_); + DCHECK(info()->IsStub()); frame_is_built_ = true; __ MultiPush(cp.bit() | fp.bit() | ra.bit()); __ li(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); @@ -293,7 +307,7 @@ bool LCodeGen::GenerateDeferredCode() { code->Generate(); if (NeedsDeferredFrame()) { Comment(";;; Destroy frame"); - ASSERT(frame_is_built_); + DCHECK(frame_is_built_); __ pop(at); __ MultiPop(cp.bit() | fp.bit() | ra.bit()); frame_is_built_ = false; @@ -310,45 +324,74 @@ bool LCodeGen::GenerateDeferredCode() { bool LCodeGen::GenerateDeoptJumpTable() { if (deopt_jump_table_.length() > 0) { + Label needs_frame, call_deopt_entry; + Comment(";;; -------------------- Jump table --------------------"); - } - Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); - Label table_start; - __ bind(&table_start); - Label needs_frame; - for (int i = 0; i < deopt_jump_table_.length(); i++) { - __ bind(&deopt_jump_table_[i].label); - Address entry = deopt_jump_table_[i].address; - Deoptimizer::BailoutType type = deopt_jump_table_[i].bailout_type; - int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); - if (id == Deoptimizer::kNotDeoptimizationEntry) { - Comment(";;; jump table entry %d.", i); - } else { + Address base = deopt_jump_table_[0].address; + + Register entry_offset = t9; + + int length = deopt_jump_table_.length(); + for (int i = 0; i < length; i++) { + __ bind(&deopt_jump_table_[i].label); + + Deoptimizer::BailoutType type = deopt_jump_table_[i].bailout_type; + DCHECK(type == deopt_jump_table_[0].bailout_type); + Address entry = deopt_jump_table_[i].address; + int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); + DCHECK(id != Deoptimizer::kNotDeoptimizationEntry); Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); - } - __ li(t9, Operand(ExternalReference::ForDeoptEntry(entry))); - if (deopt_jump_table_[i].needs_frame) { - ASSERT(!info()->saves_caller_doubles()); - if (needs_frame.is_bound()) { - __ Branch(&needs_frame); + + // Second-level deopt table entries are contiguous and small, so instead + // of loading the full, absolute address of each one, load an immediate + // offset which will be added to the base address later. + __ li(entry_offset, Operand(entry - base)); + + if (deopt_jump_table_[i].needs_frame) { + DCHECK(!info()->saves_caller_doubles()); + if (needs_frame.is_bound()) { + __ Branch(&needs_frame); + } else { + __ bind(&needs_frame); + Comment(";;; call deopt with frame"); + __ MultiPush(cp.bit() | fp.bit() | ra.bit()); + // This variant of deopt can only be used with stubs. Since we don't + // have a function pointer to install in the stack frame that we're + // building, install a special marker there instead. + DCHECK(info()->IsStub()); + __ li(at, Operand(Smi::FromInt(StackFrame::STUB))); + __ push(at); + __ Addu(fp, sp, + Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); + __ bind(&call_deopt_entry); + // Add the base address to the offset previously loaded in + // entry_offset. + __ Addu(entry_offset, entry_offset, + Operand(ExternalReference::ForDeoptEntry(base))); + __ Call(entry_offset); + } } else { - __ bind(&needs_frame); - __ MultiPush(cp.bit() | fp.bit() | ra.bit()); - // This variant of deopt can only be used with stubs. Since we don't - // have a function pointer to install in the stack frame that we're - // building, install a special marker there instead. - ASSERT(info()->IsStub()); - __ li(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); - __ push(scratch0()); - __ Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); - __ Call(t9); + // The last entry can fall through into `call_deopt_entry`, avoiding a + // branch. + bool need_branch = ((i + 1) != length) || call_deopt_entry.is_bound(); + + if (need_branch) __ Branch(&call_deopt_entry); } - } else { + } + + if (!call_deopt_entry.is_bound()) { + Comment(";;; call deopt"); + __ bind(&call_deopt_entry); + if (info()->saves_caller_doubles()) { - ASSERT(info()->IsStub()); + DCHECK(info()->IsStub()); RestoreCallerDoubles(); } - __ Call(t9); + + // Add the base address to the offset previously loaded in entry_offset. + __ Addu(entry_offset, entry_offset, + Operand(ExternalReference::ForDeoptEntry(base))); + __ Call(entry_offset); } } __ RecordComment("]"); @@ -361,7 +404,7 @@ bool LCodeGen::GenerateDeoptJumpTable() { bool LCodeGen::GenerateSafepointTable() { - ASSERT(is_done()); + DCHECK(is_done()); safepoints_.Emit(masm(), GetStackSlotCount()); return !is_aborted(); } @@ -378,7 +421,7 @@ DoubleRegister LCodeGen::ToDoubleRegister(int index) const { Register LCodeGen::ToRegister(LOperand* op) const { - ASSERT(op->IsRegister()); + DCHECK(op->IsRegister()); return ToRegister(op->index()); } @@ -392,15 +435,15 @@ Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) { Handle<Object> literal = constant->handle(isolate()); Representation r = chunk_->LookupLiteralRepresentation(const_op); if (r.IsInteger32()) { - ASSERT(literal->IsNumber()); + DCHECK(literal->IsNumber()); __ li(scratch, Operand(static_cast<int32_t>(literal->Number()))); } else if (r.IsSmi()) { - ASSERT(constant->HasSmiValue()); + DCHECK(constant->HasSmiValue()); __ li(scratch, Operand(Smi::FromInt(constant->Integer32Value()))); } else if (r.IsDouble()) { Abort(kEmitLoadRegisterUnsupportedDoubleImmediate); } else { - ASSERT(r.IsSmiOrTagged()); + DCHECK(r.IsSmiOrTagged()); __ li(scratch, literal); } return scratch; @@ -414,7 +457,7 @@ Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) { DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const { - ASSERT(op->IsDoubleRegister()); + DCHECK(op->IsDoubleRegister()); return ToDoubleRegister(op->index()); } @@ -430,7 +473,7 @@ DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op, Handle<Object> literal = constant->handle(isolate()); Representation r = chunk_->LookupLiteralRepresentation(const_op); if (r.IsInteger32()) { - ASSERT(literal->IsNumber()); + DCHECK(literal->IsNumber()); __ li(at, Operand(static_cast<int32_t>(literal->Number()))); __ mtc1(at, flt_scratch); __ cvt_d_w(dbl_scratch, flt_scratch); @@ -452,7 +495,7 @@ DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op, Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { HConstant* constant = chunk_->LookupConstant(op); - ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); + DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); return constant->handle(isolate()); } @@ -477,7 +520,7 @@ int32_t LCodeGen::ToRepresentation(LConstantOperand* op, HConstant* constant = chunk_->LookupConstant(op); int32_t value = constant->Integer32Value(); if (r.IsInteger32()) return value; - ASSERT(r.IsSmiOrTagged()); + DCHECK(r.IsSmiOrTagged()); return reinterpret_cast<int32_t>(Smi::FromInt(value)); } @@ -490,7 +533,7 @@ Smi* LCodeGen::ToSmi(LConstantOperand* op) const { double LCodeGen::ToDouble(LConstantOperand* op) const { HConstant* constant = chunk_->LookupConstant(op); - ASSERT(constant->HasDoubleValue()); + DCHECK(constant->HasDoubleValue()); return constant->DoubleValue(); } @@ -501,15 +544,15 @@ Operand LCodeGen::ToOperand(LOperand* op) { HConstant* constant = chunk()->LookupConstant(const_op); Representation r = chunk_->LookupLiteralRepresentation(const_op); if (r.IsSmi()) { - ASSERT(constant->HasSmiValue()); + DCHECK(constant->HasSmiValue()); return Operand(Smi::FromInt(constant->Integer32Value())); } else if (r.IsInteger32()) { - ASSERT(constant->HasInteger32Value()); + DCHECK(constant->HasInteger32Value()); return Operand(constant->Integer32Value()); } else if (r.IsDouble()) { Abort(kToOperandUnsupportedDoubleImmediate); } - ASSERT(r.IsTagged()); + DCHECK(r.IsTagged()); return Operand(constant->handle(isolate())); } else if (op->IsRegister()) { return Operand(ToRegister(op)); @@ -524,15 +567,15 @@ Operand LCodeGen::ToOperand(LOperand* op) { static int ArgumentsOffsetWithoutFrame(int index) { - ASSERT(index < 0); + DCHECK(index < 0); return -(index + 1) * kPointerSize; } MemOperand LCodeGen::ToMemOperand(LOperand* op) const { - ASSERT(!op->IsRegister()); - ASSERT(!op->IsDoubleRegister()); - ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); + DCHECK(!op->IsRegister()); + DCHECK(!op->IsDoubleRegister()); + DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); if (NeedsEagerFrame()) { return MemOperand(fp, StackSlotOffset(op->index())); } else { @@ -544,7 +587,7 @@ MemOperand LCodeGen::ToMemOperand(LOperand* op) const { MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const { - ASSERT(op->IsDoubleStackSlot()); + DCHECK(op->IsDoubleStackSlot()); if (NeedsEagerFrame()) { return MemOperand(fp, StackSlotOffset(op->index()) + kPointerSize); } else { @@ -580,13 +623,13 @@ void LCodeGen::WriteTranslation(LEnvironment* environment, translation->BeginConstructStubFrame(closure_id, translation_size); break; case JS_GETTER: - ASSERT(translation_size == 1); - ASSERT(height == 0); + DCHECK(translation_size == 1); + DCHECK(height == 0); translation->BeginGetterStubFrame(closure_id); break; case JS_SETTER: - ASSERT(translation_size == 2); - ASSERT(height == 0); + DCHECK(translation_size == 2); + DCHECK(height == 0); translation->BeginSetterStubFrame(closure_id); break; case STUB: @@ -691,7 +734,7 @@ void LCodeGen::CallCodeGeneric(Handle<Code> code, RelocInfo::Mode mode, LInstruction* instr, SafepointMode safepoint_mode) { - ASSERT(instr != NULL); + DCHECK(instr != NULL); __ Call(code, mode); RecordSafepointWithLazyDeopt(instr, safepoint_mode); } @@ -701,7 +744,7 @@ void LCodeGen::CallRuntime(const Runtime::Function* function, int num_arguments, LInstruction* instr, SaveFPRegsMode save_doubles) { - ASSERT(instr != NULL); + DCHECK(instr != NULL); __ CallRuntime(function, num_arguments, save_doubles); @@ -778,9 +821,9 @@ void LCodeGen::DeoptimizeIf(Condition condition, Register src1, const Operand& src2) { RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); - ASSERT(environment->HasBeenRegistered()); + DCHECK(environment->HasBeenRegistered()); int id = environment->deoptimization_index(); - ASSERT(info()->IsOptimizing() || info()->IsStub()); + DCHECK(info()->IsOptimizing() || info()->IsStub()); Address entry = Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); if (entry == NULL) { @@ -816,7 +859,7 @@ void LCodeGen::DeoptimizeIf(Condition condition, __ bind(&skip); } - ASSERT(info()->IsStub() || frame_is_built_); + DCHECK(info()->IsStub() || frame_is_built_); // Go through jump table if we need to handle condition, build frame, or // restore caller doubles. if (condition == al && frame_is_built_ && @@ -854,7 +897,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { int length = deoptimizations_.length(); if (length == 0) return; Handle<DeoptimizationInputData> data = - DeoptimizationInputData::New(isolate(), length, TENURED); + DeoptimizationInputData::New(isolate(), length, 0, TENURED); Handle<ByteArray> translations = translations_.CreateByteArray(isolate()->factory()); @@ -905,7 +948,7 @@ int LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) { void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() { - ASSERT(deoptimization_literals_.length() == 0); + DCHECK(deoptimization_literals_.length() == 0); const ZoneList<Handle<JSFunction> >* inlined_closures = chunk()->inlined_closures(); @@ -925,7 +968,7 @@ void LCodeGen::RecordSafepointWithLazyDeopt( if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt); } else { - ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); + DCHECK(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kLazyDeopt); } @@ -937,7 +980,7 @@ void LCodeGen::RecordSafepoint( Safepoint::Kind kind, int arguments, Safepoint::DeoptMode deopt_mode) { - ASSERT(expected_safepoint_kind_ == kind); + DCHECK(expected_safepoint_kind_ == kind); const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands(); Safepoint safepoint = safepoints_.DefineSafepoint(masm(), @@ -973,15 +1016,6 @@ void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, } -void LCodeGen::RecordSafepointWithRegistersAndDoubles( - LPointerMap* pointers, - int arguments, - Safepoint::DeoptMode deopt_mode) { - RecordSafepoint( - pointers, Safepoint::kWithRegistersAndDoubles, arguments, deopt_mode); -} - - void LCodeGen::RecordAndWritePosition(int position) { if (position == RelocInfo::kNoPosition) return; masm()->positions_recorder()->RecordPosition(position); @@ -1035,8 +1069,8 @@ void LCodeGen::DoParameter(LParameter* instr) { void LCodeGen::DoCallStub(LCallStub* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); - ASSERT(ToRegister(instr->result()).is(v0)); + DCHECK(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->result()).is(v0)); switch (instr->hydrogen()->major_key()) { case CodeStub::RegExpExec: { RegExpExecStub stub(isolate()); @@ -1067,7 +1101,7 @@ void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { Register dividend = ToRegister(instr->dividend()); int32_t divisor = instr->divisor(); - ASSERT(dividend.is(ToRegister(instr->result()))); + DCHECK(dividend.is(ToRegister(instr->result()))); // Theoretically, a variation of the branch-free code for integer division by // a power of 2 (calculating the remainder via an additional multiplication @@ -1101,7 +1135,7 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) { Register dividend = ToRegister(instr->dividend()); int32_t divisor = instr->divisor(); Register result = ToRegister(instr->result()); - ASSERT(!dividend.is(result)); + DCHECK(!dividend.is(result)); if (divisor == 0) { DeoptimizeIf(al, instr->environment()); @@ -1168,8 +1202,8 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { Register dividend = ToRegister(instr->dividend()); int32_t divisor = instr->divisor(); Register result = ToRegister(instr->result()); - ASSERT(divisor == kMinInt || IsPowerOf2(Abs(divisor))); - ASSERT(!result.is(dividend)); + DCHECK(divisor == kMinInt || IsPowerOf2(Abs(divisor))); + DCHECK(!result.is(dividend)); // Check for (0 / -x) that will produce negative zero. HDiv* hdiv = instr->hydrogen(); @@ -1212,7 +1246,7 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) { Register dividend = ToRegister(instr->dividend()); int32_t divisor = instr->divisor(); Register result = ToRegister(instr->result()); - ASSERT(!dividend.is(result)); + DCHECK(!dividend.is(result)); if (divisor == 0) { DeoptimizeIf(al, instr->environment()); @@ -1285,7 +1319,7 @@ void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); // This is computed in-place. - ASSERT(addend.is(ToDoubleRegister(instr->result()))); + DCHECK(addend.is(ToDoubleRegister(instr->result()))); __ madd_d(addend, addend, multiplier, multiplicand); } @@ -1295,12 +1329,17 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { Register dividend = ToRegister(instr->dividend()); Register result = ToRegister(instr->result()); int32_t divisor = instr->divisor(); - Register scratch = scratch0(); - ASSERT(!scratch.is(dividend)); + Register scratch = result.is(dividend) ? scratch0() : dividend; + DCHECK(!result.is(dividend) || !scratch.is(dividend)); + + // If the divisor is 1, return the dividend. + if (divisor == 1) { + __ Move(result, dividend); + return; + } // If the divisor is positive, things are easy: There can be no deopts and we // can simply do an arithmetic right shift. - if (divisor == 1) return; uint16_t shift = WhichPowerOf2Abs(divisor); if (divisor > 1) { __ sra(result, dividend, shift); @@ -1308,33 +1347,37 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { } // If the divisor is negative, we have to negate and handle edge cases. - if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { - __ Move(scratch, dividend); - } + + // dividend can be the same register as result so save the value of it + // for checking overflow. + __ Move(scratch, dividend); + __ Subu(result, zero_reg, dividend); if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); } - // If the negation could not overflow, simply shifting is OK. - if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { - __ sra(result, dividend, shift); + // Dividing by -1 is basically negation, unless we overflow. + __ Xor(scratch, scratch, result); + if (divisor == -1) { + if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { + DeoptimizeIf(ge, instr->environment(), scratch, Operand(zero_reg)); + } return; } - // Dividing by -1 is basically negation, unless we overflow. - __ Xor(at, scratch, result); - if (divisor == -1) { - DeoptimizeIf(ge, instr->environment(), at, Operand(zero_reg)); + // If the negation could not overflow, simply shifting is OK. + if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { + __ sra(result, result, shift); return; } Label no_overflow, done; - __ Branch(&no_overflow, lt, at, Operand(zero_reg)); + __ Branch(&no_overflow, lt, scratch, Operand(zero_reg)); __ li(result, Operand(kMinInt / divisor)); __ Branch(&done); __ bind(&no_overflow); - __ sra(result, dividend, shift); + __ sra(result, result, shift); __ bind(&done); } @@ -1343,7 +1386,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { Register dividend = ToRegister(instr->dividend()); int32_t divisor = instr->divisor(); Register result = ToRegister(instr->result()); - ASSERT(!dividend.is(result)); + DCHECK(!dividend.is(result)); if (divisor == 0) { DeoptimizeIf(al, instr->environment()); @@ -1368,7 +1411,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { // In the general case we may need to adjust before and after the truncating // division to get a flooring division. Register temp = ToRegister(instr->temp()); - ASSERT(!temp.is(dividend) && !temp.is(result)); + DCHECK(!temp.is(dividend) && !temp.is(result)); Label needs_adjustment, done; __ Branch(&needs_adjustment, divisor > 0 ? lt : gt, dividend, Operand(zero_reg)); @@ -1503,7 +1546,7 @@ void LCodeGen::DoMulI(LMulI* instr) { } } else { - ASSERT(right_op->IsRegister()); + DCHECK(right_op->IsRegister()); Register right = ToRegister(right_op); if (overflow) { @@ -1547,7 +1590,7 @@ void LCodeGen::DoMulI(LMulI* instr) { void LCodeGen::DoBitI(LBitI* instr) { LOperand* left_op = instr->left(); LOperand* right_op = instr->right(); - ASSERT(left_op->IsRegister()); + DCHECK(left_op->IsRegister()); Register left = ToRegister(left_op); Register result = ToRegister(instr->result()); Operand right(no_reg); @@ -1555,7 +1598,7 @@ void LCodeGen::DoBitI(LBitI* instr) { if (right_op->IsStackSlot()) { right = Operand(EmitLoadRegister(right_op, at)); } else { - ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); + DCHECK(right_op->IsRegister() || right_op->IsConstantOperand()); right = ToOperand(right_op); } @@ -1678,7 +1721,7 @@ void LCodeGen::DoSubI(LSubI* instr) { Register right_reg = EmitLoadRegister(right, at); __ Subu(ToRegister(result), ToRegister(left), Operand(right_reg)); } else { - ASSERT(right->IsRegister() || right->IsConstantOperand()); + DCHECK(right->IsRegister() || right->IsConstantOperand()); __ Subu(ToRegister(result), ToRegister(left), ToOperand(right)); } } else { // can_overflow. @@ -1691,7 +1734,7 @@ void LCodeGen::DoSubI(LSubI* instr) { right_reg, overflow); // Reg at also used as scratch. } else { - ASSERT(right->IsRegister()); + DCHECK(right->IsRegister()); // Due to overflow check macros not supporting constant operands, // handling the IsConstantOperand case was moved to prev if clause. __ SubuAndCheckForOverflow(ToRegister(result), @@ -1715,7 +1758,7 @@ void LCodeGen::DoConstantS(LConstantS* instr) { void LCodeGen::DoConstantD(LConstantD* instr) { - ASSERT(instr->result()->IsDoubleRegister()); + DCHECK(instr->result()->IsDoubleRegister()); DoubleRegister result = ToDoubleRegister(instr->result()); double v = instr->value(); __ Move(result, v); @@ -1730,13 +1773,6 @@ void LCodeGen::DoConstantE(LConstantE* instr) { void LCodeGen::DoConstantT(LConstantT* instr) { Handle<Object> object = instr->value(isolate()); AllowDeferredHandleDereference smi_check; - if (instr->hydrogen()->HasObjectMap()) { - Handle<Map> object_map = instr->hydrogen()->ObjectMap().handle(); - ASSERT(object->IsHeapObject()); - ASSERT(!object_map->is_stable() || - *object_map == Handle<HeapObject>::cast(object)->map()); - USE(object_map); - } __ li(ToRegister(instr->result()), object); } @@ -1754,10 +1790,10 @@ void LCodeGen::DoDateField(LDateField* instr) { Register scratch = ToRegister(instr->temp()); Smi* index = instr->index(); Label runtime, done; - ASSERT(object.is(a0)); - ASSERT(result.is(v0)); - ASSERT(!scratch.is(scratch0())); - ASSERT(!scratch.is(object)); + DCHECK(object.is(a0)); + DCHECK(result.is(v0)); + DCHECK(!scratch.is(scratch0())); + DCHECK(!scratch.is(object)); __ SmiTst(object, at); DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); @@ -1798,8 +1834,8 @@ MemOperand LCodeGen::BuildSeqStringOperand(Register string, return FieldMemOperand(string, SeqString::kHeaderSize + offset); } Register scratch = scratch0(); - ASSERT(!scratch.is(string)); - ASSERT(!scratch.is(ToRegister(index))); + DCHECK(!scratch.is(string)); + DCHECK(!scratch.is(ToRegister(index))); if (encoding == String::ONE_BYTE_ENCODING) { __ Addu(scratch, string, ToRegister(index)); } else { @@ -1875,7 +1911,7 @@ void LCodeGen::DoAddI(LAddI* instr) { Register right_reg = EmitLoadRegister(right, at); __ Addu(ToRegister(result), ToRegister(left), Operand(right_reg)); } else { - ASSERT(right->IsRegister() || right->IsConstantOperand()); + DCHECK(right->IsRegister() || right->IsConstantOperand()); __ Addu(ToRegister(result), ToRegister(left), ToOperand(right)); } } else { // can_overflow. @@ -1889,7 +1925,7 @@ void LCodeGen::DoAddI(LAddI* instr) { right_reg, overflow); // Reg at also used as scratch. } else { - ASSERT(right->IsRegister()); + DCHECK(right->IsRegister()); // Due to overflow check macros not supporting constant operands, // handling the IsConstantOperand case was moved to prev if clause. __ AdduAndCheckForOverflow(ToRegister(result), @@ -1909,22 +1945,21 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) { Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; if (instr->hydrogen()->representation().IsSmiOrInteger32()) { Register left_reg = ToRegister(left); - Operand right_op = (right->IsRegister() || right->IsConstantOperand()) - ? ToOperand(right) - : Operand(EmitLoadRegister(right, at)); + Register right_reg = EmitLoadRegister(right, scratch0()); Register result_reg = ToRegister(instr->result()); Label return_right, done; - if (!result_reg.is(left_reg)) { - __ Branch(&return_right, NegateCondition(condition), left_reg, right_op); - __ mov(result_reg, left_reg); - __ Branch(&done); + Register scratch = scratch1(); + __ Slt(scratch, left_reg, Operand(right_reg)); + if (condition == ge) { + __ Movz(result_reg, left_reg, scratch); + __ Movn(result_reg, right_reg, scratch); + } else { + DCHECK(condition == le); + __ Movn(result_reg, left_reg, scratch); + __ Movz(result_reg, right_reg, scratch); } - __ Branch(&done, condition, left_reg, right_op); - __ bind(&return_right); - __ Addu(result_reg, zero_reg, right_op); - __ bind(&done); } else { - ASSERT(instr->hydrogen()->representation().IsDouble()); + DCHECK(instr->hydrogen()->representation().IsDouble()); FPURegister left_reg = ToDoubleRegister(left); FPURegister right_reg = ToDoubleRegister(right); FPURegister result_reg = ToDoubleRegister(instr->result()); @@ -2006,10 +2041,10 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) { void LCodeGen::DoArithmeticT(LArithmeticT* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); - ASSERT(ToRegister(instr->left()).is(a1)); - ASSERT(ToRegister(instr->right()).is(a0)); - ASSERT(ToRegister(instr->result()).is(v0)); + DCHECK(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->left()).is(a1)); + DCHECK(ToRegister(instr->right()).is(a0)); + DCHECK(ToRegister(instr->result()).is(v0)); BinaryOpICStub stub(isolate(), instr->op(), NO_OVERWRITE); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); @@ -2096,36 +2131,36 @@ void LCodeGen::DoDebugBreak(LDebugBreak* instr) { void LCodeGen::DoBranch(LBranch* instr) { Representation r = instr->hydrogen()->value()->representation(); if (r.IsInteger32() || r.IsSmi()) { - ASSERT(!info()->IsStub()); + DCHECK(!info()->IsStub()); Register reg = ToRegister(instr->value()); EmitBranch(instr, ne, reg, Operand(zero_reg)); } else if (r.IsDouble()) { - ASSERT(!info()->IsStub()); + DCHECK(!info()->IsStub()); DoubleRegister reg = ToDoubleRegister(instr->value()); // Test the double value. Zero and NaN are false. EmitBranchF(instr, nue, reg, kDoubleRegZero); } else { - ASSERT(r.IsTagged()); + DCHECK(r.IsTagged()); Register reg = ToRegister(instr->value()); HType type = instr->hydrogen()->value()->type(); if (type.IsBoolean()) { - ASSERT(!info()->IsStub()); + DCHECK(!info()->IsStub()); __ LoadRoot(at, Heap::kTrueValueRootIndex); EmitBranch(instr, eq, reg, Operand(at)); } else if (type.IsSmi()) { - ASSERT(!info()->IsStub()); + DCHECK(!info()->IsStub()); EmitBranch(instr, ne, reg, Operand(zero_reg)); } else if (type.IsJSArray()) { - ASSERT(!info()->IsStub()); + DCHECK(!info()->IsStub()); EmitBranch(instr, al, zero_reg, Operand(zero_reg)); } else if (type.IsHeapNumber()) { - ASSERT(!info()->IsStub()); + DCHECK(!info()->IsStub()); DoubleRegister dbl_scratch = double_scratch0(); __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); // Test the double value. Zero and NaN are false. EmitBranchF(instr, nue, dbl_scratch, kDoubleRegZero); } else if (type.IsString()) { - ASSERT(!info()->IsStub()); + DCHECK(!info()->IsStub()); __ lw(at, FieldMemOperand(reg, String::kLengthOffset)); EmitBranch(instr, ne, at, Operand(zero_reg)); } else { @@ -2268,7 +2303,10 @@ Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) { LOperand* left = instr->left(); LOperand* right = instr->right(); - Condition cond = TokenToCondition(instr->op(), false); + bool is_unsigned = + instr->hydrogen()->left()->CheckFlag(HInstruction::kUint32) || + instr->hydrogen()->right()->CheckFlag(HInstruction::kUint32); + Condition cond = TokenToCondition(instr->op(), is_unsigned); if (left->IsConstantOperand() && right->IsConstantOperand()) { // We can statically evaluate the comparison. @@ -2312,8 +2350,8 @@ void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) { cmp_left = ToRegister(right); cmp_right = Operand(value); } - // We transposed the operands. Reverse the condition. - cond = ReverseCondition(cond); + // We commuted the operands, so commute the condition. + cond = CommuteCondition(cond); } else { cmp_left = ToRegister(left); cmp_right = Operand(ToRegister(right)); @@ -2352,7 +2390,7 @@ void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { Representation rep = instr->hydrogen()->value()->representation(); - ASSERT(!rep.IsInteger32()); + DCHECK(!rep.IsInteger32()); Register scratch = ToRegister(instr->temp()); if (rep.IsDouble()) { @@ -2434,7 +2472,7 @@ void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { Register temp1 = ToRegister(instr->temp()); SmiCheck check_needed = - instr->hydrogen()->value()->IsHeapObject() + instr->hydrogen()->value()->type().IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; Condition true_cond = EmitIsString(reg, temp1, instr->FalseLabel(chunk_), check_needed); @@ -2455,7 +2493,7 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { Register input = ToRegister(instr->value()); Register temp = ToRegister(instr->temp()); - if (!instr->hydrogen()->value()->IsHeapObject()) { + if (!instr->hydrogen()->value()->type().IsHeapObject()) { __ JumpIfSmi(input, instr->FalseLabel(chunk_)); } __ lw(temp, FieldMemOperand(input, HeapObject::kMapOffset)); @@ -2486,7 +2524,7 @@ static Condition ComputeCompareCondition(Token::Value op) { void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->context()).is(cp)); Token::Value op = instr->op(); Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); @@ -2502,7 +2540,7 @@ static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { InstanceType from = instr->from(); InstanceType to = instr->to(); if (from == FIRST_TYPE) return to; - ASSERT(from == to || to == LAST_TYPE); + DCHECK(from == to || to == LAST_TYPE); return from; } @@ -2522,7 +2560,7 @@ void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { Register scratch = scratch0(); Register input = ToRegister(instr->value()); - if (!instr->hydrogen()->value()->IsHeapObject()) { + if (!instr->hydrogen()->value()->type().IsHeapObject()) { __ JumpIfSmi(input, instr->FalseLabel(chunk_)); } @@ -2565,9 +2603,9 @@ void LCodeGen::EmitClassOfTest(Label* is_true, Register input, Register temp, Register temp2) { - ASSERT(!input.is(temp)); - ASSERT(!input.is(temp2)); - ASSERT(!temp.is(temp2)); + DCHECK(!input.is(temp)); + DCHECK(!input.is(temp2)); + DCHECK(!temp.is(temp2)); __ JumpIfSmi(input, is_false); @@ -2646,12 +2684,12 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { void LCodeGen::DoInstanceOf(LInstanceOf* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->context()).is(cp)); Label true_label, done; - ASSERT(ToRegister(instr->left()).is(a0)); // Object is in a0. - ASSERT(ToRegister(instr->right()).is(a1)); // Function is in a1. + DCHECK(ToRegister(instr->left()).is(a0)); // Object is in a0. + DCHECK(ToRegister(instr->right()).is(a1)); // Function is in a1. Register result = ToRegister(instr->result()); - ASSERT(result.is(v0)); + DCHECK(result.is(v0)); InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); @@ -2690,8 +2728,8 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { Register temp = ToRegister(instr->temp()); Register result = ToRegister(instr->result()); - ASSERT(object.is(a0)); - ASSERT(result.is(v0)); + DCHECK(object.is(a0)); + DCHECK(result.is(v0)); // A Smi is not instance of anything. __ JumpIfSmi(object, &false_result); @@ -2745,7 +2783,7 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, Label* map_check) { Register result = ToRegister(instr->result()); - ASSERT(result.is(v0)); + DCHECK(result.is(v0)); InstanceofStub::Flags flags = InstanceofStub::kNoFlags; flags = static_cast<InstanceofStub::Flags>( @@ -2756,14 +2794,14 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, flags | InstanceofStub::kReturnTrueFalseObject); InstanceofStub stub(isolate(), flags); - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); + PushSafepointRegistersScope scope(this); LoadContextFromDeferred(instr->context()); // Get the temp register reserved by the instruction. This needs to be t0 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->temp()); - ASSERT(temp.is(t0)); + DCHECK(temp.is(t0)); __ li(InstanceofStub::right(), instr->function()); static const int kAdditionalDelta = 7; int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; @@ -2787,7 +2825,7 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, void LCodeGen::DoCmpT(LCmpT* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->context()).is(cp)); Token::Value op = instr->op(); Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); @@ -2802,7 +2840,7 @@ void LCodeGen::DoCmpT(LCmpT* instr) { __ Branch(USE_DELAY_SLOT, &done, condition, v0, Operand(zero_reg)); __ bind(&check); __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); - ASSERT_EQ(1, masm()->InstructionsGeneratedSince(&check)); + DCHECK_EQ(1, masm()->InstructionsGeneratedSince(&check)); __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); __ bind(&done); } @@ -2861,11 +2899,20 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); - ASSERT(ToRegister(instr->global_object()).is(a0)); - ASSERT(ToRegister(instr->result()).is(v0)); - - __ li(a2, Operand(instr->name())); + DCHECK(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister())); + DCHECK(ToRegister(instr->result()).is(v0)); + + __ li(LoadIC::NameRegister(), Operand(instr->name())); + if (FLAG_vector_ics) { + Register vector = ToRegister(instr->temp_vector()); + DCHECK(vector.is(LoadIC::VectorRegister())); + __ li(vector, instr->hydrogen()->feedback_vector()); + // No need to allocate this register. + DCHECK(LoadIC::SlotRegister().is(a0)); + __ li(LoadIC::SlotRegister(), + Operand(Smi::FromInt(instr->hydrogen()->slot()))); + } ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode); CallCode(ic, RelocInfo::CODE_TARGET, instr); @@ -2940,7 +2987,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { __ sw(value, target); if (instr->hydrogen()->NeedsWriteBarrier()) { SmiCheck check_needed = - instr->hydrogen()->value()->IsHeapObject() + instr->hydrogen()->value()->type().IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; __ RecordWriteContextSlot(context, target.offset(), @@ -2985,12 +3032,21 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); - ASSERT(ToRegister(instr->object()).is(a0)); - ASSERT(ToRegister(instr->result()).is(v0)); + DCHECK(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); + DCHECK(ToRegister(instr->result()).is(v0)); // Name is always in a2. - __ li(a2, Operand(instr->name())); + __ li(LoadIC::NameRegister(), Operand(instr->name())); + if (FLAG_vector_ics) { + Register vector = ToRegister(instr->temp_vector()); + DCHECK(vector.is(LoadIC::VectorRegister())); + __ li(vector, instr->hydrogen()->feedback_vector()); + // No need to allocate this register. + DCHECK(LoadIC::SlotRegister().is(a0)); + __ li(LoadIC::SlotRegister(), + Operand(Smi::FromInt(instr->hydrogen()->slot()))); + } Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -3001,17 +3057,6 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { Register function = ToRegister(instr->function()); Register result = ToRegister(instr->result()); - // Check that the function really is a function. Load map into the - // result register. - __ GetObjectType(function, result, scratch); - DeoptimizeIf(ne, instr->environment(), scratch, Operand(JS_FUNCTION_TYPE)); - - // Make sure that the function has an instance prototype. - Label non_instance; - __ lbu(scratch, FieldMemOperand(result, Map::kBitFieldOffset)); - __ And(scratch, scratch, Operand(1 << Map::kHasNonInstancePrototype)); - __ Branch(&non_instance, ne, scratch, Operand(zero_reg)); - // Get the prototype or initial map from the function. __ lw(result, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); @@ -3027,12 +3072,6 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { // Get the prototype from the initial map. __ lw(result, FieldMemOperand(result, Map::kPrototypeOffset)); - __ Branch(&done); - - // Non-instance prototype: Fetch prototype from constructor field - // in initial map. - __ bind(&non_instance); - __ lw(result, FieldMemOperand(result, Map::kConstructorOffset)); // All done. __ bind(&done); @@ -3107,16 +3146,13 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { int element_size_shift = ElementsKindToShiftSize(elements_kind); int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) ? (element_size_shift - kSmiTagSize) : element_size_shift; - int additional_offset = IsFixedTypedArrayElementsKind(elements_kind) - ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag - : 0; + int base_offset = instr->base_offset(); if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || elements_kind == FLOAT32_ELEMENTS || elements_kind == EXTERNAL_FLOAT64_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) { - int base_offset = - (instr->additional_index() << element_size_shift) + additional_offset; + int base_offset = instr->base_offset(); FPURegister result = ToDoubleRegister(instr->result()); if (key_is_constant) { __ Addu(scratch0(), external_pointer, constant_key << element_size_shift); @@ -3128,15 +3164,14 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { elements_kind == FLOAT32_ELEMENTS) { __ lwc1(result, MemOperand(scratch0(), base_offset)); __ cvt_d_s(result, result); - } else { // loading doubles, not floats. + } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS __ ldc1(result, MemOperand(scratch0(), base_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); + element_size_shift, shift_size, base_offset); switch (elements_kind) { case EXTERNAL_INT8_ELEMENTS: case INT8_ELEMENTS: @@ -3196,15 +3231,13 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); - int base_offset = - FixedDoubleArray::kHeaderSize - kHeapObjectTag + - (instr->additional_index() << element_size_shift); + int base_offset = instr->base_offset(); if (key_is_constant) { int constant_key = ToInteger32(LConstantOperand::cast(instr->key())); if (constant_key & 0xF0000000) { Abort(kArrayIndexConstantValueTooBig); } - base_offset += constant_key << element_size_shift; + base_offset += constant_key * kDoubleSize; } __ Addu(scratch, elements, Operand(base_offset)); @@ -3230,12 +3263,11 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { Register result = ToRegister(instr->result()); Register scratch = scratch0(); Register store_base = scratch; - int offset = 0; + int offset = instr->base_offset(); if (instr->key()->IsConstantOperand()) { LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); - offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + - instr->additional_index()); + offset += ToInteger32(const_operand) * kPointerSize; store_base = elements; } else { Register key = ToRegister(instr->key()); @@ -3250,9 +3282,8 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { __ sll(scratch, key, kPointerSizeLog2); __ addu(scratch, elements, scratch); } - offset = FixedArray::OffsetOfElementAt(instr->additional_index()); } - __ lw(result, FieldMemOperand(store_base, offset)); + __ lw(result, MemOperand(store_base, offset)); // Check for the hole value. if (instr->hydrogen()->RequiresHoleCheck()) { @@ -3284,40 +3315,18 @@ MemOperand LCodeGen::PrepareKeyedOperand(Register key, int constant_key, int element_size, int shift_size, - int additional_index, - int additional_offset) { - int base_offset = (additional_index << element_size) + additional_offset; + int base_offset) { if (key_is_constant) { - return MemOperand(base, - base_offset + (constant_key << element_size)); + return MemOperand(base, (constant_key << element_size) + base_offset); } - if (additional_offset != 0) { - if (shift_size >= 0) { - __ sll(scratch0(), key, shift_size); - __ Addu(scratch0(), scratch0(), Operand(base_offset)); - } else { - ASSERT_EQ(-1, shift_size); - // Key can be negative, so using sra here. - __ sra(scratch0(), key, 1); - __ Addu(scratch0(), scratch0(), Operand(base_offset)); - } - __ Addu(scratch0(), base, scratch0()); - return MemOperand(scratch0()); - } - - if (additional_index != 0) { - additional_index *= 1 << (element_size - shift_size); - __ Addu(scratch0(), key, Operand(additional_index)); - } - - if (additional_index == 0) { + if (base_offset == 0) { if (shift_size >= 0) { __ sll(scratch0(), key, shift_size); __ Addu(scratch0(), base, scratch0()); return MemOperand(scratch0()); } else { - ASSERT_EQ(-1, shift_size); + DCHECK_EQ(-1, shift_size); __ srl(scratch0(), key, 1); __ Addu(scratch0(), base, scratch0()); return MemOperand(scratch0()); @@ -3325,22 +3334,32 @@ MemOperand LCodeGen::PrepareKeyedOperand(Register key, } if (shift_size >= 0) { - __ sll(scratch0(), scratch0(), shift_size); + __ sll(scratch0(), key, shift_size); __ Addu(scratch0(), base, scratch0()); - return MemOperand(scratch0()); + return MemOperand(scratch0(), base_offset); } else { - ASSERT_EQ(-1, shift_size); - __ srl(scratch0(), scratch0(), 1); + DCHECK_EQ(-1, shift_size); + __ sra(scratch0(), key, 1); __ Addu(scratch0(), base, scratch0()); - return MemOperand(scratch0()); + return MemOperand(scratch0(), base_offset); } } void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); - ASSERT(ToRegister(instr->object()).is(a1)); - ASSERT(ToRegister(instr->key()).is(a0)); + DCHECK(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); + DCHECK(ToRegister(instr->key()).is(LoadIC::NameRegister())); + + if (FLAG_vector_ics) { + Register vector = ToRegister(instr->temp_vector()); + DCHECK(vector.is(LoadIC::VectorRegister())); + __ li(vector, instr->hydrogen()->feedback_vector()); + // No need to allocate this register. + DCHECK(LoadIC::SlotRegister().is(a0)); + __ li(LoadIC::SlotRegister(), + Operand(Smi::FromInt(instr->hydrogen()->slot()))); + } Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); CallCode(ic, RelocInfo::CODE_TARGET, instr); @@ -3437,7 +3456,7 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { __ lw(result, ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); __ lw(result, - FieldMemOperand(result, GlobalObject::kGlobalReceiverOffset)); + FieldMemOperand(result, GlobalObject::kGlobalProxyOffset)); if (result.is(receiver)) { __ bind(&result_in_receiver); @@ -3457,9 +3476,9 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { Register length = ToRegister(instr->length()); Register elements = ToRegister(instr->elements()); Register scratch = scratch0(); - ASSERT(receiver.is(a0)); // Used for parameter count. - ASSERT(function.is(a1)); // Required by InvokeFunction. - ASSERT(ToRegister(instr->result()).is(v0)); + DCHECK(receiver.is(a0)); // Used for parameter count. + DCHECK(function.is(a1)); // Required by InvokeFunction. + DCHECK(ToRegister(instr->result()).is(v0)); // Copy the arguments to this function possibly from the // adaptor frame below it. @@ -3488,7 +3507,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { __ sll(scratch, length, 2); __ bind(&invoke); - ASSERT(instr->HasPointerMap()); + DCHECK(instr->HasPointerMap()); LPointerMap* pointers = instr->pointer_map(); SafepointGenerator safepoint_generator( this, pointers, Safepoint::kLazyDeopt); @@ -3528,18 +3547,18 @@ void LCodeGen::DoContext(LContext* instr) { __ lw(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); } else { // If there is no frame, the context must be in cp. - ASSERT(result.is(cp)); + DCHECK(result.is(cp)); } } void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->context()).is(cp)); __ li(scratch0(), instr->hydrogen()->pairs()); __ li(scratch1(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); // The context is the first argument. __ Push(cp, scratch0(), scratch1()); - CallRuntime(Runtime::kHiddenDeclareGlobals, 3, instr); + CallRuntime(Runtime::kDeclareGlobals, 3, instr); } @@ -3585,8 +3604,8 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { - ASSERT(instr->context() != NULL); - ASSERT(ToRegister(instr->context()).is(cp)); + DCHECK(instr->context() != NULL); + DCHECK(ToRegister(instr->context()).is(cp)); Register input = ToRegister(instr->value()); Register result = ToRegister(instr->result()); Register scratch = scratch0(); @@ -3609,7 +3628,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { // Input is negative. Reverse its sign. // Preserve the value of all registers. { - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); + PushSafepointRegistersScope scope(this); // Registers were saved at the safepoint, so we can use // many scratch registers. @@ -3628,7 +3647,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { // Slow case: Call the runtime system to do the number allocation. __ bind(&slow); - CallRuntimeFromDeferred(Runtime::kHiddenAllocateHeapNumber, 0, instr, + CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr, instr->context()); // Set the pointer to the new heap number in tmp. if (!tmp1.is(v0)) @@ -3805,6 +3824,14 @@ void LCodeGen::DoMathRound(LMathRound* instr) { } +void LCodeGen::DoMathFround(LMathFround* instr) { + DoubleRegister input = ToDoubleRegister(instr->value()); + DoubleRegister result = ToDoubleRegister(instr->result()); + __ cvt_s_d(result.low(), input); + __ cvt_d_s(result, result.low()); +} + + void LCodeGen::DoMathSqrt(LMathSqrt* instr) { DoubleRegister input = ToDoubleRegister(instr->value()); DoubleRegister result = ToDoubleRegister(instr->result()); @@ -3817,7 +3844,7 @@ void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { DoubleRegister result = ToDoubleRegister(instr->result()); DoubleRegister temp = ToDoubleRegister(instr->temp()); - ASSERT(!input.is(result)); + DCHECK(!input.is(result)); // Note that according to ECMA-262 15.8.2.13: // Math.pow(-Infinity, 0.5) == Infinity @@ -3840,12 +3867,12 @@ 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->right()->IsDoubleRegister() || + DCHECK(!instr->right()->IsDoubleRegister() || ToDoubleRegister(instr->right()).is(f4)); - ASSERT(!instr->right()->IsRegister() || + DCHECK(!instr->right()->IsRegister() || ToRegister(instr->right()).is(a2)); - ASSERT(ToDoubleRegister(instr->left()).is(f2)); - ASSERT(ToDoubleRegister(instr->result()).is(f0)); + DCHECK(ToDoubleRegister(instr->left()).is(f2)); + DCHECK(ToDoubleRegister(instr->result()).is(f0)); if (exponent_type.IsSmi()) { MathPowStub stub(isolate(), MathPowStub::TAGGED); @@ -3863,7 +3890,7 @@ void LCodeGen::DoPower(LPower* instr) { MathPowStub stub(isolate(), MathPowStub::INTEGER); __ CallStub(&stub); } else { - ASSERT(exponent_type.IsDouble()); + DCHECK(exponent_type.IsDouble()); MathPowStub stub(isolate(), MathPowStub::DOUBLE); __ CallStub(&stub); } @@ -3901,9 +3928,9 @@ void LCodeGen::DoMathClz32(LMathClz32* instr) { void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); - ASSERT(ToRegister(instr->function()).is(a1)); - ASSERT(instr->HasPointerMap()); + DCHECK(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->function()).is(a1)); + DCHECK(instr->HasPointerMap()); Handle<JSFunction> known_function = instr->hydrogen()->known_function(); if (known_function.is_null()) { @@ -3922,7 +3949,7 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { - ASSERT(ToRegister(instr->result()).is(v0)); + DCHECK(ToRegister(instr->result()).is(v0)); LPointerMap* pointers = instr->pointer_map(); SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); @@ -3933,7 +3960,7 @@ void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET)); __ Call(code, RelocInfo::CODE_TARGET); } else { - ASSERT(instr->target()->IsRegister()); + DCHECK(instr->target()->IsRegister()); Register target = ToRegister(instr->target()); generator.BeforeCall(__ CallSize(target)); __ Addu(target, target, Operand(Code::kHeaderSize - kHeapObjectTag)); @@ -3944,8 +3971,8 @@ void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { - ASSERT(ToRegister(instr->function()).is(a1)); - ASSERT(ToRegister(instr->result()).is(v0)); + DCHECK(ToRegister(instr->function()).is(a1)); + DCHECK(ToRegister(instr->result()).is(v0)); if (instr->hydrogen()->pass_argument_count()) { __ li(a0, Operand(instr->arity())); @@ -3963,9 +3990,9 @@ void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { void LCodeGen::DoCallFunction(LCallFunction* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); - ASSERT(ToRegister(instr->function()).is(a1)); - ASSERT(ToRegister(instr->result()).is(v0)); + DCHECK(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->function()).is(a1)); + DCHECK(ToRegister(instr->result()).is(v0)); int arity = instr->arity(); CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags()); @@ -3974,9 +4001,9 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) { void LCodeGen::DoCallNew(LCallNew* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); - ASSERT(ToRegister(instr->constructor()).is(a1)); - ASSERT(ToRegister(instr->result()).is(v0)); + DCHECK(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->constructor()).is(a1)); + DCHECK(ToRegister(instr->result()).is(v0)); __ li(a0, Operand(instr->arity())); // No cell in a2 for construct type feedback in optimized code @@ -3987,9 +4014,9 @@ void LCodeGen::DoCallNew(LCallNew* instr) { void LCodeGen::DoCallNewArray(LCallNewArray* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); - ASSERT(ToRegister(instr->constructor()).is(a1)); - ASSERT(ToRegister(instr->result()).is(v0)); + DCHECK(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->constructor()).is(a1)); + DCHECK(ToRegister(instr->result()).is(v0)); __ li(a0, Operand(instr->arity())); __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); @@ -4075,13 +4102,13 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { __ AssertNotSmi(object); - ASSERT(!representation.IsSmi() || + DCHECK(!representation.IsSmi() || !instr->value()->IsConstantOperand() || IsSmi(LConstantOperand::cast(instr->value()))); if (representation.IsDouble()) { - ASSERT(access.IsInobject()); - ASSERT(!instr->hydrogen()->has_transition()); - ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); + DCHECK(access.IsInobject()); + DCHECK(!instr->hydrogen()->has_transition()); + DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); DoubleRegister value = ToDoubleRegister(instr->value()); __ sdc1(value, FieldMemOperand(object, offset)); return; @@ -4095,14 +4122,11 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { if (instr->hydrogen()->NeedsWriteBarrierForMap()) { Register temp = ToRegister(instr->temp()); // Update the write barrier for the map field. - __ RecordWriteField(object, - HeapObject::kMapOffset, - scratch, - temp, - GetRAState(), - kSaveFPRegs, - OMIT_REMEMBERED_SET, - OMIT_SMI_CHECK); + __ RecordWriteForMap(object, + scratch, + temp, + GetRAState(), + kSaveFPRegs); } } @@ -4120,7 +4144,8 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { GetRAState(), kSaveFPRegs, EMIT_REMEMBERED_SET, - instr->hydrogen()->SmiCheckForWriteBarrier()); + instr->hydrogen()->SmiCheckForWriteBarrier(), + instr->hydrogen()->PointersToHereCheckForValue()); } } else { __ lw(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); @@ -4136,19 +4161,19 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { GetRAState(), kSaveFPRegs, EMIT_REMEMBERED_SET, - instr->hydrogen()->SmiCheckForWriteBarrier()); + instr->hydrogen()->SmiCheckForWriteBarrier(), + instr->hydrogen()->PointersToHereCheckForValue()); } } } void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); - ASSERT(ToRegister(instr->object()).is(a1)); - ASSERT(ToRegister(instr->value()).is(a0)); + DCHECK(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->object()).is(StoreIC::ReceiverRegister())); + DCHECK(ToRegister(instr->value()).is(StoreIC::ValueRegister())); - // Name is always in a2. - __ li(a2, Operand(instr->name())); + __ li(StoreIC::NameRegister(), Operand(instr->name())); Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode()); CallCode(ic, RelocInfo::CODE_TARGET, instr); } @@ -4161,7 +4186,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { if (instr->index()->IsConstantOperand()) { operand = ToOperand(instr->index()); reg = ToRegister(instr->length()); - cc = ReverseCondition(cc); + cc = CommuteCondition(cc); } else { reg = ToRegister(instr->index()); operand = ToOperand(instr->length()); @@ -4194,16 +4219,12 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { int element_size_shift = ElementsKindToShiftSize(elements_kind); int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) ? (element_size_shift - kSmiTagSize) : element_size_shift; - int additional_offset = IsFixedTypedArrayElementsKind(elements_kind) - ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag - : 0; + int base_offset = instr->base_offset(); if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || elements_kind == FLOAT32_ELEMENTS || elements_kind == EXTERNAL_FLOAT64_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) { - int base_offset = - (instr->additional_index() << element_size_shift) + additional_offset; Register address = scratch0(); FPURegister value(ToDoubleRegister(instr->value())); if (key_is_constant) { @@ -4230,7 +4251,7 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { MemOperand mem_operand = PrepareKeyedOperand( key, external_pointer, key_is_constant, constant_key, element_size_shift, shift_size, - instr->additional_index(), additional_offset); + base_offset); switch (elements_kind) { case EXTERNAL_UINT8_CLAMPED_ELEMENTS: case EXTERNAL_INT8_ELEMENTS: @@ -4277,6 +4298,7 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { Register scratch = scratch0(); DoubleRegister double_scratch = double_scratch0(); bool key_is_constant = instr->key()->IsConstantOperand(); + int base_offset = instr->base_offset(); Label not_nan, done; // Calculate the effective address of the slot in the array to store the @@ -4288,13 +4310,11 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { Abort(kArrayIndexConstantValueTooBig); } __ Addu(scratch, elements, - Operand((constant_key << element_size_shift) + - FixedDoubleArray::kHeaderSize - kHeapObjectTag)); + Operand((constant_key << element_size_shift) + base_offset)); } else { int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) ? (element_size_shift - kSmiTagSize) : element_size_shift; - __ Addu(scratch, elements, - Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); + __ Addu(scratch, elements, Operand(base_offset)); __ sll(at, ToRegister(instr->key()), shift_size); __ Addu(scratch, scratch, at); } @@ -4309,14 +4329,12 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { __ bind(&is_nan); __ LoadRoot(at, Heap::kNanValueRootIndex); __ ldc1(double_scratch, FieldMemOperand(at, HeapNumber::kValueOffset)); - __ sdc1(double_scratch, MemOperand(scratch, instr->additional_index() << - element_size_shift)); + __ sdc1(double_scratch, MemOperand(scratch, 0)); __ Branch(&done); } __ bind(¬_nan); - __ sdc1(value, MemOperand(scratch, instr->additional_index() << - element_size_shift)); + __ sdc1(value, MemOperand(scratch, 0)); __ bind(&done); } @@ -4328,14 +4346,13 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { : no_reg; Register scratch = scratch0(); Register store_base = scratch; - int offset = 0; + int offset = instr->base_offset(); // Do the store. if (instr->key()->IsConstantOperand()) { - ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); + DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); - offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + - instr->additional_index()); + offset += ToInteger32(const_operand) * kPointerSize; store_base = elements; } else { // Even though the HLoadKeyed instruction forces the input @@ -4349,23 +4366,23 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { __ sll(scratch, key, kPointerSizeLog2); __ addu(scratch, elements, scratch); } - offset = FixedArray::OffsetOfElementAt(instr->additional_index()); } - __ sw(value, FieldMemOperand(store_base, offset)); + __ sw(value, MemOperand(store_base, offset)); if (instr->hydrogen()->NeedsWriteBarrier()) { SmiCheck check_needed = - instr->hydrogen()->value()->IsHeapObject() + instr->hydrogen()->value()->type().IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; // Compute address of modified element and store it into key register. - __ Addu(key, store_base, Operand(offset - kHeapObjectTag)); + __ Addu(key, store_base, Operand(offset)); __ RecordWrite(elements, key, value, GetRAState(), kSaveFPRegs, EMIT_REMEMBERED_SET, - check_needed); + check_needed, + instr->hydrogen()->PointersToHereCheckForValue()); } } @@ -4383,10 +4400,10 @@ void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); - ASSERT(ToRegister(instr->object()).is(a2)); - ASSERT(ToRegister(instr->key()).is(a1)); - ASSERT(ToRegister(instr->value()).is(a0)); + DCHECK(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->object()).is(KeyedStoreIC::ReceiverRegister())); + DCHECK(ToRegister(instr->key()).is(KeyedStoreIC::NameRegister())); + DCHECK(ToRegister(instr->value()).is(KeyedStoreIC::ValueRegister())); Handle<Code> ic = (instr->strict_mode() == STRICT) ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() @@ -4413,18 +4430,20 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { __ li(new_map_reg, Operand(to_map)); __ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); // Write barrier. - __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, - scratch, GetRAState(), kDontSaveFPRegs); + __ RecordWriteForMap(object_reg, + new_map_reg, + scratch, + GetRAState(), + kDontSaveFPRegs); } else { - ASSERT(object_reg.is(a0)); - ASSERT(ToRegister(instr->context()).is(cp)); - PushSafepointRegistersScope scope( - this, Safepoint::kWithRegistersAndDoubles); + DCHECK(object_reg.is(a0)); + DCHECK(ToRegister(instr->context()).is(cp)); + PushSafepointRegistersScope scope(this); __ li(a1, Operand(to_map)); bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE; TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array); __ CallStub(&stub); - RecordSafepointWithRegistersAndDoubles( + RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kLazyDeopt); } __ bind(¬_applicable); @@ -4443,9 +4462,9 @@ void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { void LCodeGen::DoStringAdd(LStringAdd* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); - ASSERT(ToRegister(instr->left()).is(a1)); - ASSERT(ToRegister(instr->right()).is(a0)); + DCHECK(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->left()).is(a1)); + DCHECK(ToRegister(instr->right()).is(a0)); StringAddStub stub(isolate(), instr->hydrogen()->flags(), instr->hydrogen()->pretenure_flag()); @@ -4487,7 +4506,7 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { // contained in the register pointer map. __ mov(result, zero_reg); - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); + PushSafepointRegistersScope scope(this); __ push(string); // Push the index as a smi. This is safe because of the checks in // DoStringCharCodeAt above. @@ -4500,7 +4519,7 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { __ SmiTag(index); __ push(index); } - CallRuntimeFromDeferred(Runtime::kHiddenStringCharCodeAt, 2, instr, + CallRuntimeFromDeferred(Runtime::kStringCharCodeAtRT, 2, instr, instr->context()); __ AssertSmi(v0); __ SmiUntag(v0); @@ -4524,11 +4543,11 @@ void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { DeferredStringCharFromCode* deferred = new(zone()) DeferredStringCharFromCode(this, instr); - ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); + DCHECK(instr->hydrogen()->value()->representation().IsInteger32()); Register char_code = ToRegister(instr->char_code()); Register result = ToRegister(instr->result()); Register scratch = scratch0(); - ASSERT(!char_code.is(result)); + DCHECK(!char_code.is(result)); __ Branch(deferred->entry(), hi, char_code, Operand(String::kMaxOneByteCharCode)); @@ -4551,7 +4570,7 @@ void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { // contained in the register pointer map. __ mov(result, zero_reg); - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); + PushSafepointRegistersScope scope(this); __ SmiTag(char_code); __ push(char_code); CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); @@ -4561,9 +4580,9 @@ void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { LOperand* input = instr->value(); - ASSERT(input->IsRegister() || input->IsStackSlot()); + DCHECK(input->IsRegister() || input->IsStackSlot()); LOperand* output = instr->result(); - ASSERT(output->IsDoubleRegister()); + DCHECK(output->IsDoubleRegister()); FPURegister single_scratch = double_scratch0().low(); if (input->IsStackSlot()) { Register scratch = scratch0(); @@ -4684,15 +4703,15 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, __ mov(dst, zero_reg); // Preserve the value of all registers. - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); + PushSafepointRegistersScope scope(this); // NumberTagI and NumberTagD use the context from the frame, rather than // the environment's HContext or HInlinedContext value. - // They only call Runtime::kHiddenAllocateHeapNumber. + // They only call Runtime::kAllocateHeapNumber. // The corresponding HChange instructions are added in a phase that does // not have easy access to the local context. __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); + __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); __ Subu(v0, v0, kHeapObjectTag); @@ -4750,14 +4769,14 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { Register reg = ToRegister(instr->result()); __ mov(reg, zero_reg); - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); + PushSafepointRegistersScope scope(this); // NumberTagI and NumberTagD use the context from the frame, rather than // the environment's HContext or HInlinedContext value. - // They only call Runtime::kHiddenAllocateHeapNumber. + // They only call Runtime::kAllocateHeapNumber. // The corresponding HChange instructions are added in a phase that does // not have easy access to the local context. __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); + __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); __ Subu(v0, v0, kHeapObjectTag); @@ -4839,7 +4858,7 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, } } else { __ SmiUntag(scratch, input_reg); - ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); + DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); } // Smi to double register conversion __ bind(&load_smi); @@ -4857,8 +4876,8 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { DoubleRegister double_scratch = double_scratch0(); DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp2()); - ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); - ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); + DCHECK(!scratch1.is(input_reg) && !scratch1.is(scratch2)); + DCHECK(!scratch2.is(input_reg) && !scratch2.is(scratch1)); Label done; @@ -4884,7 +4903,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { __ bind(&no_heap_number); __ LoadRoot(at, Heap::kUndefinedValueRootIndex); __ Branch(&check_bools, ne, input_reg, Operand(at)); - ASSERT(ToRegister(instr->result()).is(input_reg)); + DCHECK(ToRegister(instr->result()).is(input_reg)); __ Branch(USE_DELAY_SLOT, &done); __ mov(input_reg, zero_reg); // In delay slot. @@ -4945,8 +4964,8 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) { }; LOperand* input = instr->value(); - ASSERT(input->IsRegister()); - ASSERT(input->Equals(instr->result())); + DCHECK(input->IsRegister()); + DCHECK(input->Equals(instr->result())); Register input_reg = ToRegister(input); @@ -4967,9 +4986,9 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) { void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { LOperand* input = instr->value(); - ASSERT(input->IsRegister()); + DCHECK(input->IsRegister()); LOperand* result = instr->result(); - ASSERT(result->IsDoubleRegister()); + DCHECK(result->IsDoubleRegister()); Register input_reg = ToRegister(input); DoubleRegister result_reg = ToDoubleRegister(result); @@ -5062,7 +5081,7 @@ void LCodeGen::DoCheckSmi(LCheckSmi* instr) { void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { - if (!instr->hydrogen()->value()->IsHeapObject()) { + if (!instr->hydrogen()->value()->type().IsHeapObject()) { LOperand* input = instr->value(); __ SmiTst(ToRegister(input), at); DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); @@ -5097,7 +5116,7 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); if (IsPowerOf2(mask)) { - ASSERT(tag == 0 || IsPowerOf2(tag)); + DCHECK(tag == 0 || IsPowerOf2(tag)); __ And(at, scratch, mask); DeoptimizeIf(tag == 0 ? ne : eq, instr->environment(), at, Operand(zero_reg)); @@ -5129,7 +5148,7 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) { void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { { - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); + PushSafepointRegistersScope scope(this); __ push(object); __ mov(cp, zero_reg); __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); @@ -5170,7 +5189,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) { Register map_reg = scratch0(); LOperand* input = instr->value(); - ASSERT(input->IsRegister()); + DCHECK(input->IsRegister()); Register reg = ToRegister(input); __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); @@ -5293,11 +5312,11 @@ void LCodeGen::DoAllocate(LAllocate* instr) { flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); } if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { - ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); - ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); + DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation()); + DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { - ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); + DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); } if (instr->size()->IsConstantOperand()) { @@ -5309,33 +5328,26 @@ void LCodeGen::DoAllocate(LAllocate* instr) { } } else { Register size = ToRegister(instr->size()); - __ Allocate(size, - result, - scratch, - scratch2, - deferred->entry(), - flags); + __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags); } __ bind(deferred->exit()); if (instr->hydrogen()->MustPrefillWithFiller()) { + STATIC_ASSERT(kHeapObjectTag == 1); if (instr->size()->IsConstantOperand()) { int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); - __ li(scratch, Operand(size)); + __ li(scratch, Operand(size - kHeapObjectTag)); } else { - scratch = ToRegister(instr->size()); + __ Subu(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag)); } - __ Subu(scratch, scratch, Operand(kPointerSize)); - __ Subu(result, result, Operand(kHeapObjectTag)); + __ li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); Label loop; __ bind(&loop); - __ li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); + __ Subu(scratch, scratch, Operand(kPointerSize)); __ Addu(at, result, Operand(scratch)); __ sw(scratch2, MemOperand(at)); - __ Subu(scratch, scratch, Operand(kPointerSize)); __ Branch(&loop, ge, scratch, Operand(zero_reg)); - __ Addu(result, result, Operand(kHeapObjectTag)); } } @@ -5348,10 +5360,10 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) { // contained in the register pointer map. __ mov(result, zero_reg); - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); + PushSafepointRegistersScope scope(this); if (instr->size()->IsRegister()) { Register size = ToRegister(instr->size()); - ASSERT(!size.is(result)); + DCHECK(!size.is(result)); __ SmiTag(size); __ push(size); } else { @@ -5368,11 +5380,11 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) { int flags = AllocateDoubleAlignFlag::encode( instr->hydrogen()->MustAllocateDoubleAligned()); if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { - ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); - ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); + DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation()); + DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { - ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); + DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); } else { flags = AllocateTargetSpace::update(flags, NEW_SPACE); @@ -5380,21 +5392,21 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) { __ Push(Smi::FromInt(flags)); CallRuntimeFromDeferred( - Runtime::kHiddenAllocateInTargetSpace, 2, instr, instr->context()); + Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); __ StoreToSafepointRegisterSlot(v0, result); } void LCodeGen::DoToFastProperties(LToFastProperties* instr) { - ASSERT(ToRegister(instr->value()).is(a0)); - ASSERT(ToRegister(instr->result()).is(v0)); + DCHECK(ToRegister(instr->value()).is(a0)); + DCHECK(ToRegister(instr->result()).is(v0)); __ push(a0); CallRuntime(Runtime::kToFastProperties, 1, instr); } void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->context()).is(cp)); Label materialized; // Registers will be used as follows: // t3 = literals array. @@ -5414,7 +5426,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { __ li(t1, Operand(instr->hydrogen()->pattern())); __ li(t0, Operand(instr->hydrogen()->flags())); __ Push(t3, t2, t1, t0); - CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4, instr); + CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); __ mov(a1, v0); __ bind(&materialized); @@ -5427,7 +5439,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { __ bind(&runtime_allocate); __ li(a0, Operand(Smi::FromInt(size))); __ Push(a1, a0); - CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1, instr); + CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); __ pop(a1); __ bind(&allocated); @@ -5447,7 +5459,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { - ASSERT(ToRegister(instr->context()).is(cp)); + DCHECK(ToRegister(instr->context()).is(cp)); // Use the fast case closure allocation code that allocates in new // space for nested functions that don't need literals cloning. bool pretenure = instr->hydrogen()->pretenure(); @@ -5462,13 +5474,13 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { __ li(a1, Operand(pretenure ? factory()->true_value() : factory()->false_value())); __ Push(cp, a2, a1); - CallRuntime(Runtime::kHiddenNewClosure, 3, instr); + CallRuntime(Runtime::kNewClosure, 3, instr); } } void LCodeGen::DoTypeof(LTypeof* instr) { - ASSERT(ToRegister(instr->result()).is(v0)); + DCHECK(ToRegister(instr->result()).is(v0)); Register input = ToRegister(instr->value()); __ push(input); CallRuntime(Runtime::kTypeof, 1, instr); @@ -5485,11 +5497,11 @@ void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { instr->FalseLabel(chunk_), input, instr->type_literal(), - cmp1, - cmp2); + &cmp1, + &cmp2); - ASSERT(cmp1.is_valid()); - ASSERT(!cmp2.is_reg() || cmp2.rm().is_valid()); + DCHECK(cmp1.is_valid()); + DCHECK(!cmp2.is_reg() || cmp2.rm().is_valid()); if (final_branch_condition != kNoCondition) { EmitBranch(instr, final_branch_condition, cmp1, cmp2); @@ -5501,8 +5513,8 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, Label* false_label, Register input, Handle<String> type_name, - Register& cmp1, - Operand& cmp2) { + Register* cmp1, + Operand* cmp2) { // This function utilizes the delay slot heavily. This is used to load // values that are always usable without depending on the type of the input // register. @@ -5513,8 +5525,8 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, __ JumpIfSmi(input, true_label); __ lw(input, FieldMemOperand(input, HeapObject::kMapOffset)); __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); - cmp1 = input; - cmp2 = Operand(at); + *cmp1 = input; + *cmp2 = Operand(at); final_branch_condition = eq; } else if (String::Equals(type_name, factory->string_string())) { @@ -5526,30 +5538,23 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, // other branch. __ lbu(at, FieldMemOperand(input, Map::kBitFieldOffset)); __ And(at, at, 1 << Map::kIsUndetectable); - cmp1 = at; - cmp2 = Operand(zero_reg); + *cmp1 = at; + *cmp2 = Operand(zero_reg); final_branch_condition = eq; } else if (String::Equals(type_name, factory->symbol_string())) { __ JumpIfSmi(input, false_label); __ GetObjectType(input, input, scratch); - cmp1 = scratch; - cmp2 = Operand(SYMBOL_TYPE); + *cmp1 = scratch; + *cmp2 = Operand(SYMBOL_TYPE); final_branch_condition = eq; } else if (String::Equals(type_name, factory->boolean_string())) { __ LoadRoot(at, Heap::kTrueValueRootIndex); __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input)); __ LoadRoot(at, Heap::kFalseValueRootIndex); - cmp1 = at; - cmp2 = Operand(input); - final_branch_condition = eq; - - } else if (FLAG_harmony_typeof && - String::Equals(type_name, factory->null_string())) { - __ LoadRoot(at, Heap::kNullValueRootIndex); - cmp1 = at; - cmp2 = Operand(input); + *cmp1 = at; + *cmp2 = Operand(input); final_branch_condition = eq; } else if (String::Equals(type_name, factory->undefined_string())) { @@ -5562,8 +5567,8 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, __ lw(input, FieldMemOperand(input, HeapObject::kMapOffset)); __ lbu(at, FieldMemOperand(input, Map::kBitFieldOffset)); __ And(at, at, 1 << Map::kIsUndetectable); - cmp1 = at; - cmp2 = Operand(zero_reg); + *cmp1 = at; + *cmp2 = Operand(zero_reg); final_branch_condition = ne; } else if (String::Equals(type_name, factory->function_string())) { @@ -5571,16 +5576,14 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, __ JumpIfSmi(input, false_label); __ GetObjectType(input, scratch, input); __ Branch(true_label, eq, input, Operand(JS_FUNCTION_TYPE)); - cmp1 = input; - cmp2 = Operand(JS_FUNCTION_PROXY_TYPE); + *cmp1 = input; + *cmp2 = Operand(JS_FUNCTION_PROXY_TYPE); final_branch_condition = eq; } else if (String::Equals(type_name, factory->object_string())) { __ JumpIfSmi(input, false_label); - if (!FLAG_harmony_typeof) { - __ LoadRoot(at, Heap::kNullValueRootIndex); - __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input)); - } + __ LoadRoot(at, Heap::kNullValueRootIndex); + __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input)); Register map = input; __ GetObjectType(input, map, scratch); __ Branch(false_label, @@ -5591,13 +5594,13 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, // Check for undetectable objects => false. __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset)); __ And(at, at, 1 << Map::kIsUndetectable); - cmp1 = at; - cmp2 = Operand(zero_reg); + *cmp1 = at; + *cmp2 = Operand(zero_reg); final_branch_condition = eq; } else { - cmp1 = at; - cmp2 = Operand(zero_reg); // Set to valid regs, to avoid caller assertion. + *cmp1 = at; + *cmp2 = Operand(zero_reg); // Set to valid regs, to avoid caller assertion. __ Branch(false_label); } @@ -5616,7 +5619,7 @@ void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { - ASSERT(!temp1.is(temp2)); + DCHECK(!temp1.is(temp2)); // Get the frame pointer for the calling frame. __ lw(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); @@ -5640,7 +5643,7 @@ void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { int current_pc = masm()->pc_offset(); if (current_pc < last_lazy_deopt_pc_ + space_needed) { int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; - ASSERT_EQ(0, padding_size % Assembler::kInstrSize); + DCHECK_EQ(0, padding_size % Assembler::kInstrSize); while (padding_size > 0) { __ nop(); padding_size -= Assembler::kInstrSize; @@ -5653,7 +5656,7 @@ void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { void LCodeGen::DoLazyBailout(LLazyBailout* instr) { last_lazy_deopt_pc_ = masm()->pc_offset(); - ASSERT(instr->HasEnvironment()); + DCHECK(instr->HasEnvironment()); LEnvironment* env = instr->environment(); RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); @@ -5686,12 +5689,12 @@ void LCodeGen::DoDummyUse(LDummyUse* instr) { void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); + PushSafepointRegistersScope scope(this); LoadContextFromDeferred(instr->context()); - __ CallRuntimeSaveDoubles(Runtime::kHiddenStackGuard); + __ CallRuntimeSaveDoubles(Runtime::kStackGuard); RecordSafepointWithLazyDeopt( instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); - ASSERT(instr->HasEnvironment()); + DCHECK(instr->HasEnvironment()); LEnvironment* env = instr->environment(); safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); } @@ -5710,7 +5713,7 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) { LStackCheck* instr_; }; - ASSERT(instr->HasEnvironment()); + DCHECK(instr->HasEnvironment()); LEnvironment* env = instr->environment(); // There is no LLazyBailout instruction for stack-checks. We have to // prepare for lazy deoptimization explicitly here. @@ -5719,14 +5722,14 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) { Label done; __ LoadRoot(at, Heap::kStackLimitRootIndex); __ Branch(&done, hs, sp, Operand(at)); - ASSERT(instr->context()->IsRegister()); - ASSERT(ToRegister(instr->context()).is(cp)); + DCHECK(instr->context()->IsRegister()); + DCHECK(ToRegister(instr->context()).is(cp)); CallCode(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET, instr); __ bind(&done); } else { - ASSERT(instr->hydrogen()->is_backwards_branch()); + DCHECK(instr->hydrogen()->is_backwards_branch()); // Perform stack overflow check if this goto needs it before jumping. DeferredStackCheck* deferred_stack_check = new(zone()) DeferredStackCheck(this, instr); @@ -5751,7 +5754,7 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) { // If the environment were already registered, we would have no way of // backpatching it with the spill slot operands. - ASSERT(!environment->HasBeenRegistered()); + DCHECK(!environment->HasBeenRegistered()); RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); GenerateOsrPrologue(); @@ -5776,7 +5779,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { DeoptimizeIf(le, instr->environment(), a1, Operand(LAST_JS_PROXY_TYPE)); Label use_cache, call_runtime; - ASSERT(object.is(a0)); + DCHECK(object.is(a0)); __ CheckEnumCache(null_value, &call_runtime); __ lw(result, FieldMemOperand(object, HeapObject::kMapOffset)); @@ -5788,7 +5791,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); - ASSERT(result.is(v0)); + DCHECK(result.is(v0)); __ LoadRoot(at, Heap::kMetaMapRootIndex); DeoptimizeIf(ne, instr->environment(), a1, Operand(at)); __ bind(&use_cache); @@ -5828,7 +5831,7 @@ void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, Register result, Register object, Register index) { - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); + PushSafepointRegistersScope scope(this); __ Push(object, index); __ mov(cp, zero_reg); __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble); @@ -5898,6 +5901,21 @@ void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { } +void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { + Register context = ToRegister(instr->context()); + __ sw(context, MemOperand(fp, StandardFrameConstants::kContextOffset)); +} + + +void LCodeGen::DoAllocateBlockContext(LAllocateBlockContext* instr) { + Handle<ScopeInfo> scope_info = instr->scope_info(); + __ li(at, scope_info); + __ Push(at, ToRegister(instr->function())); + CallRuntime(Runtime::kPushBlockContext, 2, instr); + RecordSafepoint(Safepoint::kNoLazyDeopt); +} + + #undef __ } } // namespace v8::internal |