[stubs] Refactor StringCompareStub and use it for HStringCompareAndBranch.
[platform/upstream/v8.git] / src / mips64 / lithium-codegen-mips64.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/code-factory.h"
6 #include "src/code-stubs.h"
7 #include "src/cpu-profiler.h"
8 #include "src/hydrogen-osr.h"
9 #include "src/ic/ic.h"
10 #include "src/ic/stub-cache.h"
11 #include "src/mips64/lithium-codegen-mips64.h"
12 #include "src/mips64/lithium-gap-resolver-mips64.h"
13
14 namespace v8 {
15 namespace internal {
16
17
18 class SafepointGenerator final : public CallWrapper {
19  public:
20   SafepointGenerator(LCodeGen* codegen,
21                      LPointerMap* pointers,
22                      Safepoint::DeoptMode mode)
23       : codegen_(codegen),
24         pointers_(pointers),
25         deopt_mode_(mode) { }
26   virtual ~SafepointGenerator() {}
27
28   void BeforeCall(int call_size) const override {}
29
30   void AfterCall() const override {
31     codegen_->RecordSafepoint(pointers_, deopt_mode_);
32   }
33
34  private:
35   LCodeGen* codegen_;
36   LPointerMap* pointers_;
37   Safepoint::DeoptMode deopt_mode_;
38 };
39
40
41 #define __ masm()->
42
43 bool LCodeGen::GenerateCode() {
44   LPhase phase("Z_Code generation", chunk());
45   DCHECK(is_unused());
46   status_ = GENERATING;
47
48   // Open a frame scope to indicate that there is a frame on the stack.  The
49   // NONE indicates that the scope shouldn't actually generate code to set up
50   // the frame (that is done in GeneratePrologue).
51   FrameScope frame_scope(masm_, StackFrame::NONE);
52
53   return GeneratePrologue() && GenerateBody() && GenerateDeferredCode() &&
54          GenerateJumpTable() && GenerateSafepointTable();
55 }
56
57
58 void LCodeGen::FinishCode(Handle<Code> code) {
59   DCHECK(is_done());
60   code->set_stack_slots(GetStackSlotCount());
61   code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
62   PopulateDeoptimizationData(code);
63 }
64
65
66 void LCodeGen::SaveCallerDoubles() {
67   DCHECK(info()->saves_caller_doubles());
68   DCHECK(NeedsEagerFrame());
69   Comment(";;; Save clobbered callee double registers");
70   int count = 0;
71   BitVector* doubles = chunk()->allocated_double_registers();
72   BitVector::Iterator save_iterator(doubles);
73   while (!save_iterator.Done()) {
74     __ sdc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
75             MemOperand(sp, count * kDoubleSize));
76     save_iterator.Advance();
77     count++;
78   }
79 }
80
81
82 void LCodeGen::RestoreCallerDoubles() {
83   DCHECK(info()->saves_caller_doubles());
84   DCHECK(NeedsEagerFrame());
85   Comment(";;; Restore clobbered callee double registers");
86   BitVector* doubles = chunk()->allocated_double_registers();
87   BitVector::Iterator save_iterator(doubles);
88   int count = 0;
89   while (!save_iterator.Done()) {
90     __ ldc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
91             MemOperand(sp, count * kDoubleSize));
92     save_iterator.Advance();
93     count++;
94   }
95 }
96
97
98 bool LCodeGen::GeneratePrologue() {
99   DCHECK(is_generating());
100
101   if (info()->IsOptimizing()) {
102     ProfileEntryHookStub::MaybeCallEntryHook(masm_);
103
104 #ifdef DEBUG
105     if (strlen(FLAG_stop_at) > 0 &&
106         info_->literal()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
107       __ stop("stop_at");
108     }
109 #endif
110
111     // a1: Callee's JS function.
112     // cp: Callee's context.
113     // fp: Caller's frame pointer.
114     // lr: Caller's pc.
115
116     // Sloppy mode functions and builtins need to replace the receiver with the
117     // global proxy when called as functions (without an explicit receiver
118     // object).
119     if (info()->MustReplaceUndefinedReceiverWithGlobalProxy()) {
120       Label ok;
121       int receiver_offset = info_->scope()->num_parameters() * kPointerSize;
122       __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
123       __ ld(a2, MemOperand(sp, receiver_offset));
124       __ Branch(&ok, ne, a2, Operand(at));
125
126       __ ld(a2, GlobalObjectOperand());
127       __ ld(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset));
128
129       __ sd(a2, MemOperand(sp, receiver_offset));
130
131       __ bind(&ok);
132     }
133   }
134
135   info()->set_prologue_offset(masm_->pc_offset());
136   if (NeedsEagerFrame()) {
137     if (info()->IsStub()) {
138       __ StubPrologue();
139     } else {
140       __ Prologue(info()->IsCodePreAgingActive());
141     }
142     frame_is_built_ = true;
143     info_->AddNoFrameRange(0, masm_->pc_offset());
144   }
145
146   // Reserve space for the stack slots needed by the code.
147   int slots = GetStackSlotCount();
148   if (slots > 0) {
149     if (FLAG_debug_code) {
150       __ Dsubu(sp,  sp, Operand(slots * kPointerSize));
151       __ Push(a0, a1);
152       __ Daddu(a0, sp, Operand(slots *  kPointerSize));
153       __ li(a1, Operand(kSlotsZapValue));
154       Label loop;
155       __ bind(&loop);
156       __ Dsubu(a0, a0, Operand(kPointerSize));
157       __ sd(a1, MemOperand(a0, 2 * kPointerSize));
158       __ Branch(&loop, ne, a0, Operand(sp));
159       __ Pop(a0, a1);
160     } else {
161       __ Dsubu(sp, sp, Operand(slots * kPointerSize));
162     }
163   }
164
165   if (info()->saves_caller_doubles()) {
166     SaveCallerDoubles();
167   }
168   return !is_aborted();
169 }
170
171
172 void LCodeGen::DoPrologue(LPrologue* instr) {
173   Comment(";;; Prologue begin");
174
175   // Possibly allocate a local context.
176   if (info()->scope()->num_heap_slots() > 0) {
177     Comment(";;; Allocate local context");
178     bool need_write_barrier = true;
179     // Argument to NewContext is the function, which is in a1.
180     int slots = info()->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
181     Safepoint::DeoptMode deopt_mode = Safepoint::kNoLazyDeopt;
182     if (info()->scope()->is_script_scope()) {
183       __ push(a1);
184       __ Push(info()->scope()->GetScopeInfo(info()->isolate()));
185       __ CallRuntime(Runtime::kNewScriptContext, 2);
186       deopt_mode = Safepoint::kLazyDeopt;
187     } else if (slots <= FastNewContextStub::kMaximumSlots) {
188       FastNewContextStub stub(isolate(), slots);
189       __ CallStub(&stub);
190       // Result of FastNewContextStub is always in new space.
191       need_write_barrier = false;
192     } else {
193       __ push(a1);
194       __ CallRuntime(Runtime::kNewFunctionContext, 1);
195     }
196     RecordSafepoint(deopt_mode);
197
198     // Context is returned in both v0. It replaces the context passed to us.
199     // It's saved in the stack and kept live in cp.
200     __ mov(cp, v0);
201     __ sd(v0, MemOperand(fp, StandardFrameConstants::kContextOffset));
202     // Copy any necessary parameters into the context.
203     int num_parameters = scope()->num_parameters();
204     int first_parameter = scope()->has_this_declaration() ? -1 : 0;
205     for (int i = first_parameter; i < num_parameters; i++) {
206       Variable* var = (i == -1) ? scope()->receiver() : scope()->parameter(i);
207       if (var->IsContextSlot()) {
208         int parameter_offset = StandardFrameConstants::kCallerSPOffset +
209             (num_parameters - 1 - i) * kPointerSize;
210         // Load parameter from stack.
211         __ ld(a0, MemOperand(fp, parameter_offset));
212         // Store it in the context.
213         MemOperand target = ContextOperand(cp, var->index());
214         __ sd(a0, target);
215         // Update the write barrier. This clobbers a3 and a0.
216         if (need_write_barrier) {
217           __ RecordWriteContextSlot(
218               cp, target.offset(), a0, a3, GetRAState(), kSaveFPRegs);
219         } else if (FLAG_debug_code) {
220           Label done;
221           __ JumpIfInNewSpace(cp, a0, &done);
222           __ Abort(kExpectedNewSpaceObject);
223           __ bind(&done);
224         }
225       }
226     }
227     Comment(";;; End allocate local context");
228   }
229
230   Comment(";;; Prologue end");
231 }
232
233
234 void LCodeGen::GenerateOsrPrologue() {
235   // Generate the OSR entry prologue at the first unknown OSR value, or if there
236   // are none, at the OSR entrypoint instruction.
237   if (osr_pc_offset_ >= 0) return;
238
239   osr_pc_offset_ = masm()->pc_offset();
240
241   // Adjust the frame size, subsuming the unoptimized frame into the
242   // optimized frame.
243   int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots();
244   DCHECK(slots >= 0);
245   __ Dsubu(sp, sp, Operand(slots * kPointerSize));
246 }
247
248
249 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
250   if (instr->IsCall()) {
251     EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
252   }
253   if (!instr->IsLazyBailout() && !instr->IsGap()) {
254     safepoints_.BumpLastLazySafepointIndex();
255   }
256 }
257
258
259 bool LCodeGen::GenerateDeferredCode() {
260   DCHECK(is_generating());
261   if (deferred_.length() > 0) {
262     for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
263       LDeferredCode* code = deferred_[i];
264
265       HValue* value =
266           instructions_->at(code->instruction_index())->hydrogen_value();
267       RecordAndWritePosition(
268           chunk()->graph()->SourcePositionToScriptPosition(value->position()));
269
270       Comment(";;; <@%d,#%d> "
271               "-------------------- Deferred %s --------------------",
272               code->instruction_index(),
273               code->instr()->hydrogen_value()->id(),
274               code->instr()->Mnemonic());
275       __ bind(code->entry());
276       if (NeedsDeferredFrame()) {
277         Comment(";;; Build frame");
278         DCHECK(!frame_is_built_);
279         DCHECK(info()->IsStub());
280         frame_is_built_ = true;
281         __ MultiPush(cp.bit() | fp.bit() | ra.bit());
282         __ li(scratch0(), Operand(Smi::FromInt(StackFrame::STUB)));
283         __ push(scratch0());
284         __ Daddu(fp, sp,
285             Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
286         Comment(";;; Deferred code");
287       }
288       code->Generate();
289       if (NeedsDeferredFrame()) {
290         Comment(";;; Destroy frame");
291         DCHECK(frame_is_built_);
292         __ pop(at);
293         __ MultiPop(cp.bit() | fp.bit() | ra.bit());
294         frame_is_built_ = false;
295       }
296       __ jmp(code->exit());
297     }
298   }
299   // Deferred code is the last part of the instruction sequence. Mark
300   // the generated code as done unless we bailed out.
301   if (!is_aborted()) status_ = DONE;
302   return !is_aborted();
303 }
304
305
306 bool LCodeGen::GenerateJumpTable() {
307   if (jump_table_.length() > 0) {
308     Comment(";;; -------------------- Jump table --------------------");
309     Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
310     Label table_start, call_deopt_entry;
311
312     __ bind(&table_start);
313     Label needs_frame;
314     Address base = jump_table_[0]->address;
315     for (int i = 0; i < jump_table_.length(); i++) {
316       Deoptimizer::JumpTableEntry* table_entry = jump_table_[i];
317       __ bind(&table_entry->label);
318       Address entry = table_entry->address;
319       DeoptComment(table_entry->deopt_info);
320
321       // Second-level deopt table entries are contiguous and small, so instead
322       // of loading the full, absolute address of each one, load the base
323       // address and add an immediate offset.
324       if (is_int16(entry - base)) {
325         if (table_entry->needs_frame) {
326           DCHECK(!info()->saves_caller_doubles());
327           Comment(";;; call deopt with frame");
328           __ MultiPush(cp.bit() | fp.bit() | ra.bit());
329           __ BranchAndLink(&needs_frame, USE_DELAY_SLOT);
330           __ li(t9, Operand(entry - base));
331         } else {
332           __ BranchAndLink(&call_deopt_entry, USE_DELAY_SLOT);
333           __ li(t9, Operand(entry - base));
334         }
335
336       } else {
337         __ li(t9, Operand(entry - base));
338         if (table_entry->needs_frame) {
339           DCHECK(!info()->saves_caller_doubles());
340           Comment(";;; call deopt with frame");
341           __ MultiPush(cp.bit() | fp.bit() | ra.bit());
342           __ BranchAndLink(&needs_frame);
343         } else {
344           __ BranchAndLink(&call_deopt_entry);
345         }
346       }
347       info()->LogDeoptCallPosition(masm()->pc_offset(),
348                                    table_entry->deopt_info.inlining_id);
349     }
350     if (needs_frame.is_linked()) {
351       __ bind(&needs_frame);
352       // This variant of deopt can only be used with stubs. Since we don't
353       // have a function pointer to install in the stack frame that we're
354       // building, install a special marker there instead.
355       DCHECK(info()->IsStub());
356       __ li(at, Operand(Smi::FromInt(StackFrame::STUB)));
357       __ push(at);
358       __ Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
359     }
360
361     Comment(";;; call deopt");
362     __ bind(&call_deopt_entry);
363
364     if (info()->saves_caller_doubles()) {
365       DCHECK(info()->IsStub());
366       RestoreCallerDoubles();
367     }
368
369     __ li(at,
370           Operand(reinterpret_cast<int64_t>(base), RelocInfo::RUNTIME_ENTRY));
371     __ Daddu(t9, t9, Operand(at));
372     __ Jump(t9);
373   }
374   // The deoptimization jump table is the last part of the instruction
375   // sequence. Mark the generated code as done unless we bailed out.
376   if (!is_aborted()) status_ = DONE;
377   return !is_aborted();
378 }
379
380
381 bool LCodeGen::GenerateSafepointTable() {
382   DCHECK(is_done());
383   safepoints_.Emit(masm(), GetStackSlotCount());
384   return !is_aborted();
385 }
386
387
388 Register LCodeGen::ToRegister(int index) const {
389   return Register::FromAllocationIndex(index);
390 }
391
392
393 DoubleRegister LCodeGen::ToDoubleRegister(int index) const {
394   return DoubleRegister::FromAllocationIndex(index);
395 }
396
397
398 Register LCodeGen::ToRegister(LOperand* op) const {
399   DCHECK(op->IsRegister());
400   return ToRegister(op->index());
401 }
402
403
404 Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) {
405   if (op->IsRegister()) {
406     return ToRegister(op->index());
407   } else if (op->IsConstantOperand()) {
408     LConstantOperand* const_op = LConstantOperand::cast(op);
409     HConstant* constant = chunk_->LookupConstant(const_op);
410     Handle<Object> literal = constant->handle(isolate());
411     Representation r = chunk_->LookupLiteralRepresentation(const_op);
412     if (r.IsInteger32()) {
413       AllowDeferredHandleDereference get_number;
414       DCHECK(literal->IsNumber());
415       __ li(scratch, Operand(static_cast<int32_t>(literal->Number())));
416     } else if (r.IsSmi()) {
417       DCHECK(constant->HasSmiValue());
418       __ li(scratch, Operand(Smi::FromInt(constant->Integer32Value())));
419     } else if (r.IsDouble()) {
420       Abort(kEmitLoadRegisterUnsupportedDoubleImmediate);
421     } else {
422       DCHECK(r.IsSmiOrTagged());
423       __ li(scratch, literal);
424     }
425     return scratch;
426   } else if (op->IsStackSlot()) {
427     __ ld(scratch, ToMemOperand(op));
428     return scratch;
429   }
430   UNREACHABLE();
431   return scratch;
432 }
433
434
435 DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
436   DCHECK(op->IsDoubleRegister());
437   return ToDoubleRegister(op->index());
438 }
439
440
441 DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op,
442                                                 FloatRegister flt_scratch,
443                                                 DoubleRegister dbl_scratch) {
444   if (op->IsDoubleRegister()) {
445     return ToDoubleRegister(op->index());
446   } else if (op->IsConstantOperand()) {
447     LConstantOperand* const_op = LConstantOperand::cast(op);
448     HConstant* constant = chunk_->LookupConstant(const_op);
449     Handle<Object> literal = constant->handle(isolate());
450     Representation r = chunk_->LookupLiteralRepresentation(const_op);
451     if (r.IsInteger32()) {
452       DCHECK(literal->IsNumber());
453       __ li(at, Operand(static_cast<int32_t>(literal->Number())));
454       __ mtc1(at, flt_scratch);
455       __ cvt_d_w(dbl_scratch, flt_scratch);
456       return dbl_scratch;
457     } else if (r.IsDouble()) {
458       Abort(kUnsupportedDoubleImmediate);
459     } else if (r.IsTagged()) {
460       Abort(kUnsupportedTaggedImmediate);
461     }
462   } else if (op->IsStackSlot()) {
463     MemOperand mem_op = ToMemOperand(op);
464     __ ldc1(dbl_scratch, mem_op);
465     return dbl_scratch;
466   }
467   UNREACHABLE();
468   return dbl_scratch;
469 }
470
471
472 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
473   HConstant* constant = chunk_->LookupConstant(op);
474   DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
475   return constant->handle(isolate());
476 }
477
478
479 bool LCodeGen::IsInteger32(LConstantOperand* op) const {
480   return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32();
481 }
482
483
484 bool LCodeGen::IsSmi(LConstantOperand* op) const {
485   return chunk_->LookupLiteralRepresentation(op).IsSmi();
486 }
487
488
489 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
490   // return ToRepresentation(op, Representation::Integer32());
491   HConstant* constant = chunk_->LookupConstant(op);
492   return constant->Integer32Value();
493 }
494
495
496 int64_t LCodeGen::ToRepresentation_donotuse(LConstantOperand* op,
497                                             const Representation& r) const {
498   HConstant* constant = chunk_->LookupConstant(op);
499   int32_t value = constant->Integer32Value();
500   if (r.IsInteger32()) return value;
501   DCHECK(r.IsSmiOrTagged());
502   return reinterpret_cast<int64_t>(Smi::FromInt(value));
503 }
504
505
506 Smi* LCodeGen::ToSmi(LConstantOperand* op) const {
507   HConstant* constant = chunk_->LookupConstant(op);
508   return Smi::FromInt(constant->Integer32Value());
509 }
510
511
512 double LCodeGen::ToDouble(LConstantOperand* op) const {
513   HConstant* constant = chunk_->LookupConstant(op);
514   DCHECK(constant->HasDoubleValue());
515   return constant->DoubleValue();
516 }
517
518
519 Operand LCodeGen::ToOperand(LOperand* op) {
520   if (op->IsConstantOperand()) {
521     LConstantOperand* const_op = LConstantOperand::cast(op);
522     HConstant* constant = chunk()->LookupConstant(const_op);
523     Representation r = chunk_->LookupLiteralRepresentation(const_op);
524     if (r.IsSmi()) {
525       DCHECK(constant->HasSmiValue());
526       return Operand(Smi::FromInt(constant->Integer32Value()));
527     } else if (r.IsInteger32()) {
528       DCHECK(constant->HasInteger32Value());
529       return Operand(constant->Integer32Value());
530     } else if (r.IsDouble()) {
531       Abort(kToOperandUnsupportedDoubleImmediate);
532     }
533     DCHECK(r.IsTagged());
534     return Operand(constant->handle(isolate()));
535   } else if (op->IsRegister()) {
536     return Operand(ToRegister(op));
537   } else if (op->IsDoubleRegister()) {
538     Abort(kToOperandIsDoubleRegisterUnimplemented);
539     return Operand((int64_t)0);
540   }
541   // Stack slots not implemented, use ToMemOperand instead.
542   UNREACHABLE();
543   return Operand((int64_t)0);
544 }
545
546
547 static int ArgumentsOffsetWithoutFrame(int index) {
548   DCHECK(index < 0);
549   return -(index + 1) * kPointerSize;
550 }
551
552
553 MemOperand LCodeGen::ToMemOperand(LOperand* op) const {
554   DCHECK(!op->IsRegister());
555   DCHECK(!op->IsDoubleRegister());
556   DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
557   if (NeedsEagerFrame()) {
558     return MemOperand(fp, StackSlotOffset(op->index()));
559   } else {
560     // Retrieve parameter without eager stack-frame relative to the
561     // stack-pointer.
562     return MemOperand(sp, ArgumentsOffsetWithoutFrame(op->index()));
563   }
564 }
565
566
567 MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const {
568   DCHECK(op->IsDoubleStackSlot());
569   if (NeedsEagerFrame()) {
570     // return MemOperand(fp, StackSlotOffset(op->index()) + kPointerSize);
571     return MemOperand(fp, StackSlotOffset(op->index()) + kIntSize);
572   } else {
573     // Retrieve parameter without eager stack-frame relative to the
574     // stack-pointer.
575     // return MemOperand(
576     //    sp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize);
577     return MemOperand(
578         sp, ArgumentsOffsetWithoutFrame(op->index()) + kIntSize);
579   }
580 }
581
582
583 void LCodeGen::WriteTranslation(LEnvironment* environment,
584                                 Translation* translation) {
585   if (environment == NULL) return;
586
587   // The translation includes one command per value in the environment.
588   int translation_size = environment->translation_size();
589
590   WriteTranslation(environment->outer(), translation);
591   WriteTranslationFrame(environment, translation);
592
593   int object_index = 0;
594   int dematerialized_index = 0;
595   for (int i = 0; i < translation_size; ++i) {
596     LOperand* value = environment->values()->at(i);
597     AddToTranslation(
598         environment, translation, value, environment->HasTaggedValueAt(i),
599         environment->HasUint32ValueAt(i), &object_index, &dematerialized_index);
600   }
601 }
602
603
604 void LCodeGen::AddToTranslation(LEnvironment* environment,
605                                 Translation* translation,
606                                 LOperand* op,
607                                 bool is_tagged,
608                                 bool is_uint32,
609                                 int* object_index_pointer,
610                                 int* dematerialized_index_pointer) {
611   if (op == LEnvironment::materialization_marker()) {
612     int object_index = (*object_index_pointer)++;
613     if (environment->ObjectIsDuplicateAt(object_index)) {
614       int dupe_of = environment->ObjectDuplicateOfAt(object_index);
615       translation->DuplicateObject(dupe_of);
616       return;
617     }
618     int object_length = environment->ObjectLengthAt(object_index);
619     if (environment->ObjectIsArgumentsAt(object_index)) {
620       translation->BeginArgumentsObject(object_length);
621     } else {
622       translation->BeginCapturedObject(object_length);
623     }
624     int dematerialized_index = *dematerialized_index_pointer;
625     int env_offset = environment->translation_size() + dematerialized_index;
626     *dematerialized_index_pointer += object_length;
627     for (int i = 0; i < object_length; ++i) {
628       LOperand* value = environment->values()->at(env_offset + i);
629       AddToTranslation(environment,
630                        translation,
631                        value,
632                        environment->HasTaggedValueAt(env_offset + i),
633                        environment->HasUint32ValueAt(env_offset + i),
634                        object_index_pointer,
635                        dematerialized_index_pointer);
636     }
637     return;
638   }
639
640   if (op->IsStackSlot()) {
641     int index = op->index();
642     if (index >= 0) {
643       index += StandardFrameConstants::kFixedFrameSize / kPointerSize;
644     }
645     if (is_tagged) {
646       translation->StoreStackSlot(index);
647     } else if (is_uint32) {
648       translation->StoreUint32StackSlot(index);
649     } else {
650       translation->StoreInt32StackSlot(index);
651     }
652   } else if (op->IsDoubleStackSlot()) {
653     int index = op->index();
654     if (index >= 0) {
655       index += StandardFrameConstants::kFixedFrameSize / kPointerSize;
656     }
657     translation->StoreDoubleStackSlot(index);
658   } else if (op->IsRegister()) {
659     Register reg = ToRegister(op);
660     if (is_tagged) {
661       translation->StoreRegister(reg);
662     } else if (is_uint32) {
663       translation->StoreUint32Register(reg);
664     } else {
665       translation->StoreInt32Register(reg);
666     }
667   } else if (op->IsDoubleRegister()) {
668     DoubleRegister reg = ToDoubleRegister(op);
669     translation->StoreDoubleRegister(reg);
670   } else if (op->IsConstantOperand()) {
671     HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
672     int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
673     translation->StoreLiteral(src_index);
674   } else {
675     UNREACHABLE();
676   }
677 }
678
679
680 void LCodeGen::CallCode(Handle<Code> code,
681                         RelocInfo::Mode mode,
682                         LInstruction* instr) {
683   CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
684 }
685
686
687 void LCodeGen::CallCodeGeneric(Handle<Code> code,
688                                RelocInfo::Mode mode,
689                                LInstruction* instr,
690                                SafepointMode safepoint_mode) {
691   DCHECK(instr != NULL);
692   __ Call(code, mode);
693   RecordSafepointWithLazyDeopt(instr, safepoint_mode);
694 }
695
696
697 void LCodeGen::CallRuntime(const Runtime::Function* function,
698                            int num_arguments,
699                            LInstruction* instr,
700                            SaveFPRegsMode save_doubles) {
701   DCHECK(instr != NULL);
702
703   __ CallRuntime(function, num_arguments, save_doubles);
704
705   RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
706 }
707
708
709 void LCodeGen::LoadContextFromDeferred(LOperand* context) {
710   if (context->IsRegister()) {
711     __ Move(cp, ToRegister(context));
712   } else if (context->IsStackSlot()) {
713     __ ld(cp, ToMemOperand(context));
714   } else if (context->IsConstantOperand()) {
715     HConstant* constant =
716         chunk_->LookupConstant(LConstantOperand::cast(context));
717     __ li(cp, Handle<Object>::cast(constant->handle(isolate())));
718   } else {
719     UNREACHABLE();
720   }
721 }
722
723
724 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
725                                        int argc,
726                                        LInstruction* instr,
727                                        LOperand* context) {
728   LoadContextFromDeferred(context);
729   __ CallRuntimeSaveDoubles(id);
730   RecordSafepointWithRegisters(
731       instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
732 }
733
734
735 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
736                                                     Safepoint::DeoptMode mode) {
737   environment->set_has_been_used();
738   if (!environment->HasBeenRegistered()) {
739     // Physical stack frame layout:
740     // -x ............. -4  0 ..................................... y
741     // [incoming arguments] [spill slots] [pushed outgoing arguments]
742
743     // Layout of the environment:
744     // 0 ..................................................... size-1
745     // [parameters] [locals] [expression stack including arguments]
746
747     // Layout of the translation:
748     // 0 ........................................................ size - 1 + 4
749     // [expression stack including arguments] [locals] [4 words] [parameters]
750     // |>------------  translation_size ------------<|
751
752     int frame_count = 0;
753     int jsframe_count = 0;
754     for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
755       ++frame_count;
756       if (e->frame_type() == JS_FUNCTION) {
757         ++jsframe_count;
758       }
759     }
760     Translation translation(&translations_, frame_count, jsframe_count, zone());
761     WriteTranslation(environment, &translation);
762     int deoptimization_index = deoptimizations_.length();
763     int pc_offset = masm()->pc_offset();
764     environment->Register(deoptimization_index,
765                           translation.index(),
766                           (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
767     deoptimizations_.Add(environment, zone());
768   }
769 }
770
771
772 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
773                             Deoptimizer::DeoptReason deopt_reason,
774                             Deoptimizer::BailoutType bailout_type,
775                             Register src1, const Operand& src2) {
776   LEnvironment* environment = instr->environment();
777   RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
778   DCHECK(environment->HasBeenRegistered());
779   int id = environment->deoptimization_index();
780   Address entry =
781       Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
782   if (entry == NULL) {
783     Abort(kBailoutWasNotPrepared);
784     return;
785   }
786
787   if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) {
788     Register scratch = scratch0();
789     ExternalReference count = ExternalReference::stress_deopt_count(isolate());
790     Label no_deopt;
791     __ Push(a1, scratch);
792     __ li(scratch, Operand(count));
793     __ lw(a1, MemOperand(scratch));
794     __ Subu(a1, a1, Operand(1));
795     __ Branch(&no_deopt, ne, a1, Operand(zero_reg));
796     __ li(a1, Operand(FLAG_deopt_every_n_times));
797     __ sw(a1, MemOperand(scratch));
798     __ Pop(a1, scratch);
799
800     __ Call(entry, RelocInfo::RUNTIME_ENTRY);
801     __ bind(&no_deopt);
802     __ sw(a1, MemOperand(scratch));
803     __ Pop(a1, scratch);
804   }
805
806   if (info()->ShouldTrapOnDeopt()) {
807     Label skip;
808     if (condition != al) {
809       __ Branch(&skip, NegateCondition(condition), src1, src2);
810     }
811     __ stop("trap_on_deopt");
812     __ bind(&skip);
813   }
814
815   Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason);
816
817   DCHECK(info()->IsStub() || frame_is_built_);
818   // Go through jump table if we need to handle condition, build frame, or
819   // restore caller doubles.
820   if (condition == al && frame_is_built_ &&
821       !info()->saves_caller_doubles()) {
822     DeoptComment(deopt_info);
823     __ Call(entry, RelocInfo::RUNTIME_ENTRY, condition, src1, src2);
824     info()->LogDeoptCallPosition(masm()->pc_offset(), deopt_info.inlining_id);
825   } else {
826     Deoptimizer::JumpTableEntry* table_entry =
827         new (zone()) Deoptimizer::JumpTableEntry(
828             entry, deopt_info, bailout_type, !frame_is_built_);
829     // We often have several deopts to the same entry, reuse the last
830     // jump entry if this is the case.
831     if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling() ||
832         jump_table_.is_empty() ||
833         !table_entry->IsEquivalentTo(*jump_table_.last())) {
834       jump_table_.Add(table_entry, zone());
835     }
836     __ Branch(&jump_table_.last()->label, condition, src1, src2);
837   }
838 }
839
840
841 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
842                             Deoptimizer::DeoptReason deopt_reason,
843                             Register src1, const Operand& src2) {
844   Deoptimizer::BailoutType bailout_type = info()->IsStub()
845       ? Deoptimizer::LAZY
846       : Deoptimizer::EAGER;
847   DeoptimizeIf(condition, instr, deopt_reason, bailout_type, src1, src2);
848 }
849
850
851 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
852   int length = deoptimizations_.length();
853   if (length == 0) return;
854   Handle<DeoptimizationInputData> data =
855       DeoptimizationInputData::New(isolate(), length, TENURED);
856
857   Handle<ByteArray> translations =
858       translations_.CreateByteArray(isolate()->factory());
859   data->SetTranslationByteArray(*translations);
860   data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
861   data->SetOptimizationId(Smi::FromInt(info_->optimization_id()));
862   if (info_->IsOptimizing()) {
863     // Reference to shared function info does not change between phases.
864     AllowDeferredHandleDereference allow_handle_dereference;
865     data->SetSharedFunctionInfo(*info_->shared_info());
866   } else {
867     data->SetSharedFunctionInfo(Smi::FromInt(0));
868   }
869   data->SetWeakCellCache(Smi::FromInt(0));
870
871   Handle<FixedArray> literals =
872       factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
873   { AllowDeferredHandleDereference copy_handles;
874     for (int i = 0; i < deoptimization_literals_.length(); i++) {
875       literals->set(i, *deoptimization_literals_[i]);
876     }
877     data->SetLiteralArray(*literals);
878   }
879
880   data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt()));
881   data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
882
883   // Populate the deoptimization entries.
884   for (int i = 0; i < length; i++) {
885     LEnvironment* env = deoptimizations_[i];
886     data->SetAstId(i, env->ast_id());
887     data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
888     data->SetArgumentsStackHeight(i,
889                                   Smi::FromInt(env->arguments_stack_height()));
890     data->SetPc(i, Smi::FromInt(env->pc_offset()));
891   }
892   code->set_deoptimization_data(*data);
893 }
894
895
896 void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() {
897   DCHECK_EQ(0, deoptimization_literals_.length());
898   for (auto function : chunk()->inlined_functions()) {
899     DefineDeoptimizationLiteral(function);
900   }
901   inlined_function_count_ = deoptimization_literals_.length();
902 }
903
904
905 void LCodeGen::RecordSafepointWithLazyDeopt(
906     LInstruction* instr, SafepointMode safepoint_mode) {
907   if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
908     RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
909   } else {
910     DCHECK(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
911     RecordSafepointWithRegisters(
912         instr->pointer_map(), 0, Safepoint::kLazyDeopt);
913   }
914 }
915
916
917 void LCodeGen::RecordSafepoint(
918     LPointerMap* pointers,
919     Safepoint::Kind kind,
920     int arguments,
921     Safepoint::DeoptMode deopt_mode) {
922   DCHECK(expected_safepoint_kind_ == kind);
923
924   const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
925   Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
926       kind, arguments, deopt_mode);
927   for (int i = 0; i < operands->length(); i++) {
928     LOperand* pointer = operands->at(i);
929     if (pointer->IsStackSlot()) {
930       safepoint.DefinePointerSlot(pointer->index(), zone());
931     } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
932       safepoint.DefinePointerRegister(ToRegister(pointer), zone());
933     }
934   }
935 }
936
937
938 void LCodeGen::RecordSafepoint(LPointerMap* pointers,
939                                Safepoint::DeoptMode deopt_mode) {
940   RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode);
941 }
942
943
944 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) {
945   LPointerMap empty_pointers(zone());
946   RecordSafepoint(&empty_pointers, deopt_mode);
947 }
948
949
950 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
951                                             int arguments,
952                                             Safepoint::DeoptMode deopt_mode) {
953   RecordSafepoint(
954       pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
955 }
956
957
958 void LCodeGen::RecordAndWritePosition(int position) {
959   if (position == RelocInfo::kNoPosition) return;
960   masm()->positions_recorder()->RecordPosition(position);
961   masm()->positions_recorder()->WriteRecordedPositions();
962 }
963
964
965 static const char* LabelType(LLabel* label) {
966   if (label->is_loop_header()) return " (loop header)";
967   if (label->is_osr_entry()) return " (OSR entry)";
968   return "";
969 }
970
971
972 void LCodeGen::DoLabel(LLabel* label) {
973   Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------",
974           current_instruction_,
975           label->hydrogen_value()->id(),
976           label->block_id(),
977           LabelType(label));
978   __ bind(label->label());
979   current_block_ = label->block_id();
980   DoGap(label);
981 }
982
983
984 void LCodeGen::DoParallelMove(LParallelMove* move) {
985   resolver_.Resolve(move);
986 }
987
988
989 void LCodeGen::DoGap(LGap* gap) {
990   for (int i = LGap::FIRST_INNER_POSITION;
991        i <= LGap::LAST_INNER_POSITION;
992        i++) {
993     LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
994     LParallelMove* move = gap->GetParallelMove(inner_pos);
995     if (move != NULL) DoParallelMove(move);
996   }
997 }
998
999
1000 void LCodeGen::DoInstructionGap(LInstructionGap* instr) {
1001   DoGap(instr);
1002 }
1003
1004
1005 void LCodeGen::DoParameter(LParameter* instr) {
1006   // Nothing to do.
1007 }
1008
1009
1010 void LCodeGen::DoCallStub(LCallStub* instr) {
1011   DCHECK(ToRegister(instr->context()).is(cp));
1012   DCHECK(ToRegister(instr->result()).is(v0));
1013   switch (instr->hydrogen()->major_key()) {
1014     case CodeStub::RegExpExec: {
1015       RegExpExecStub stub(isolate());
1016       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1017       break;
1018     }
1019     case CodeStub::SubString: {
1020       SubStringStub stub(isolate());
1021       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1022       break;
1023     }
1024     default:
1025       UNREACHABLE();
1026   }
1027 }
1028
1029
1030 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
1031   GenerateOsrPrologue();
1032 }
1033
1034
1035 void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
1036   Register dividend = ToRegister(instr->dividend());
1037   int32_t divisor = instr->divisor();
1038   DCHECK(dividend.is(ToRegister(instr->result())));
1039
1040   // Theoretically, a variation of the branch-free code for integer division by
1041   // a power of 2 (calculating the remainder via an additional multiplication
1042   // (which gets simplified to an 'and') and subtraction) should be faster, and
1043   // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to
1044   // indicate that positive dividends are heavily favored, so the branching
1045   // version performs better.
1046   HMod* hmod = instr->hydrogen();
1047   int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1048   Label dividend_is_not_negative, done;
1049
1050   if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1051     __ Branch(&dividend_is_not_negative, ge, dividend, Operand(zero_reg));
1052     // Note: The code below even works when right contains kMinInt.
1053     __ dsubu(dividend, zero_reg, dividend);
1054     __ And(dividend, dividend, Operand(mask));
1055     if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1056       DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
1057                    Operand(zero_reg));
1058     }
1059     __ Branch(USE_DELAY_SLOT, &done);
1060     __ dsubu(dividend, zero_reg, dividend);
1061   }
1062
1063   __ bind(&dividend_is_not_negative);
1064   __ And(dividend, dividend, Operand(mask));
1065   __ bind(&done);
1066 }
1067
1068
1069 void LCodeGen::DoModByConstI(LModByConstI* instr) {
1070   Register dividend = ToRegister(instr->dividend());
1071   int32_t divisor = instr->divisor();
1072   Register result = ToRegister(instr->result());
1073   DCHECK(!dividend.is(result));
1074
1075   if (divisor == 0) {
1076     DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
1077     return;
1078   }
1079
1080   __ TruncatingDiv(result, dividend, Abs(divisor));
1081   __ Dmul(result, result, Operand(Abs(divisor)));
1082   __ Dsubu(result, dividend, Operand(result));
1083
1084   // Check for negative zero.
1085   HMod* hmod = instr->hydrogen();
1086   if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1087     Label remainder_not_zero;
1088     __ Branch(&remainder_not_zero, ne, result, Operand(zero_reg));
1089     DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, dividend,
1090                  Operand(zero_reg));
1091     __ bind(&remainder_not_zero);
1092   }
1093 }
1094
1095
1096 void LCodeGen::DoModI(LModI* instr) {
1097   HMod* hmod = instr->hydrogen();
1098   const Register left_reg = ToRegister(instr->left());
1099   const Register right_reg = ToRegister(instr->right());
1100   const Register result_reg = ToRegister(instr->result());
1101
1102   // div runs in the background while we check for special cases.
1103   __ Dmod(result_reg, left_reg, right_reg);
1104
1105   Label done;
1106   // Check for x % 0, we have to deopt in this case because we can't return a
1107   // NaN.
1108   if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1109     DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, right_reg,
1110                  Operand(zero_reg));
1111   }
1112
1113   // Check for kMinInt % -1, div will return kMinInt, which is not what we
1114   // want. We have to deopt if we care about -0, because we can't return that.
1115   if (hmod->CheckFlag(HValue::kCanOverflow)) {
1116     Label no_overflow_possible;
1117     __ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt));
1118     if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1119       DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, right_reg, Operand(-1));
1120     } else {
1121       __ Branch(&no_overflow_possible, ne, right_reg, Operand(-1));
1122       __ Branch(USE_DELAY_SLOT, &done);
1123       __ mov(result_reg, zero_reg);
1124     }
1125     __ bind(&no_overflow_possible);
1126   }
1127
1128   // If we care about -0, test if the dividend is <0 and the result is 0.
1129   __ Branch(&done, ge, left_reg, Operand(zero_reg));
1130
1131   if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1132     DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result_reg,
1133                  Operand(zero_reg));
1134   }
1135   __ bind(&done);
1136 }
1137
1138
1139 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1140   Register dividend = ToRegister(instr->dividend());
1141   int32_t divisor = instr->divisor();
1142   Register result = ToRegister(instr->result());
1143   DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1144   DCHECK(!result.is(dividend));
1145
1146   // Check for (0 / -x) that will produce negative zero.
1147   HDiv* hdiv = instr->hydrogen();
1148   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1149     DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
1150                  Operand(zero_reg));
1151   }
1152   // Check for (kMinInt / -1).
1153   if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1154     DeoptimizeIf(eq, instr, Deoptimizer::kOverflow, dividend, Operand(kMinInt));
1155   }
1156   // Deoptimize if remainder will not be 0.
1157   if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1158       divisor != 1 && divisor != -1) {
1159     int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1160     __ And(at, dividend, Operand(mask));
1161     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, at, Operand(zero_reg));
1162   }
1163
1164   if (divisor == -1) {  // Nice shortcut, not needed for correctness.
1165     __ Dsubu(result, zero_reg, dividend);
1166     return;
1167   }
1168   uint16_t shift = WhichPowerOf2Abs(divisor);
1169   if (shift == 0) {
1170     __ Move(result, dividend);
1171   } else if (shift == 1) {
1172     __ dsrl32(result, dividend, 31);
1173     __ Daddu(result, dividend, Operand(result));
1174   } else {
1175     __ dsra32(result, dividend, 31);
1176     __ dsrl32(result, result, 32 - shift);
1177     __ Daddu(result, dividend, Operand(result));
1178   }
1179   if (shift > 0) __ dsra(result, result, shift);
1180   if (divisor < 0) __ Dsubu(result, zero_reg, result);
1181 }
1182
1183
1184 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1185   Register dividend = ToRegister(instr->dividend());
1186   int32_t divisor = instr->divisor();
1187   Register result = ToRegister(instr->result());
1188   DCHECK(!dividend.is(result));
1189
1190   if (divisor == 0) {
1191     DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
1192     return;
1193   }
1194
1195   // Check for (0 / -x) that will produce negative zero.
1196   HDiv* hdiv = instr->hydrogen();
1197   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1198     DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
1199                  Operand(zero_reg));
1200   }
1201
1202   __ TruncatingDiv(result, dividend, Abs(divisor));
1203   if (divisor < 0) __ Subu(result, zero_reg, result);
1204
1205   if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1206     __ Dmul(scratch0(), result, Operand(divisor));
1207     __ Dsubu(scratch0(), scratch0(), dividend);
1208     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, scratch0(),
1209                  Operand(zero_reg));
1210   }
1211 }
1212
1213
1214 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1215 void LCodeGen::DoDivI(LDivI* instr) {
1216   HBinaryOperation* hdiv = instr->hydrogen();
1217   Register dividend = ToRegister(instr->dividend());
1218   Register divisor = ToRegister(instr->divisor());
1219   const Register result = ToRegister(instr->result());
1220
1221   // On MIPS div is asynchronous - it will run in the background while we
1222   // check for special cases.
1223   __ Div(result, dividend, divisor);
1224
1225   // Check for x / 0.
1226   if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1227     DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, divisor,
1228                  Operand(zero_reg));
1229   }
1230
1231   // Check for (0 / -x) that will produce negative zero.
1232   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1233     Label left_not_zero;
1234     __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg));
1235     DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, divisor,
1236                  Operand(zero_reg));
1237     __ bind(&left_not_zero);
1238   }
1239
1240   // Check for (kMinInt / -1).
1241   if (hdiv->CheckFlag(HValue::kCanOverflow) &&
1242       !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1243     Label left_not_min_int;
1244     __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt));
1245     DeoptimizeIf(eq, instr, Deoptimizer::kOverflow, divisor, Operand(-1));
1246     __ bind(&left_not_min_int);
1247   }
1248
1249   if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1250     // Calculate remainder.
1251     Register remainder = ToRegister(instr->temp());
1252     if (kArchVariant != kMips64r6) {
1253       __ mfhi(remainder);
1254     } else {
1255       __ dmod(remainder, dividend, divisor);
1256     }
1257     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, remainder,
1258                  Operand(zero_reg));
1259   }
1260 }
1261
1262
1263 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) {
1264   DoubleRegister addend = ToDoubleRegister(instr->addend());
1265   DoubleRegister multiplier = ToDoubleRegister(instr->multiplier());
1266   DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand());
1267
1268   // This is computed in-place.
1269   DCHECK(addend.is(ToDoubleRegister(instr->result())));
1270
1271   __ Madd_d(addend, addend, multiplier, multiplicand, double_scratch0());
1272 }
1273
1274
1275 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1276   Register dividend = ToRegister(instr->dividend());
1277   Register result = ToRegister(instr->result());
1278   int32_t divisor = instr->divisor();
1279   Register scratch = result.is(dividend) ? scratch0() : dividend;
1280   DCHECK(!result.is(dividend) || !scratch.is(dividend));
1281
1282   // If the divisor is 1, return the dividend.
1283   if (divisor == 1) {
1284     __ Move(result, dividend);
1285     return;
1286   }
1287
1288   // If the divisor is positive, things are easy: There can be no deopts and we
1289   // can simply do an arithmetic right shift.
1290   uint16_t shift = WhichPowerOf2Abs(divisor);
1291   if (divisor > 1) {
1292     __ dsra(result, dividend, shift);
1293     return;
1294   }
1295
1296   // If the divisor is negative, we have to negate and handle edge cases.
1297   // Dividend can be the same register as result so save the value of it
1298   // for checking overflow.
1299   __ Move(scratch, dividend);
1300
1301   __ Dsubu(result, zero_reg, dividend);
1302   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1303     DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result, Operand(zero_reg));
1304   }
1305
1306   __ Xor(scratch, scratch, result);
1307   // Dividing by -1 is basically negation, unless we overflow.
1308   if (divisor == -1) {
1309     if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1310       DeoptimizeIf(gt, instr, Deoptimizer::kOverflow, result, Operand(kMaxInt));
1311     }
1312     return;
1313   }
1314
1315   // If the negation could not overflow, simply shifting is OK.
1316   if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1317     __ dsra(result, result, shift);
1318     return;
1319   }
1320
1321   Label no_overflow, done;
1322   __ Branch(&no_overflow, lt, scratch, Operand(zero_reg));
1323   __ li(result, Operand(kMinInt / divisor), CONSTANT_SIZE);
1324   __ Branch(&done);
1325   __ bind(&no_overflow);
1326   __ dsra(result, result, shift);
1327   __ bind(&done);
1328 }
1329
1330
1331 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1332   Register dividend = ToRegister(instr->dividend());
1333   int32_t divisor = instr->divisor();
1334   Register result = ToRegister(instr->result());
1335   DCHECK(!dividend.is(result));
1336
1337   if (divisor == 0) {
1338     DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero);
1339     return;
1340   }
1341
1342   // Check for (0 / -x) that will produce negative zero.
1343   HMathFloorOfDiv* hdiv = instr->hydrogen();
1344   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1345     DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
1346                  Operand(zero_reg));
1347   }
1348
1349   // Easy case: We need no dynamic check for the dividend and the flooring
1350   // division is the same as the truncating division.
1351   if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1352       (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1353     __ TruncatingDiv(result, dividend, Abs(divisor));
1354     if (divisor < 0) __ Dsubu(result, zero_reg, result);
1355     return;
1356   }
1357
1358   // In the general case we may need to adjust before and after the truncating
1359   // division to get a flooring division.
1360   Register temp = ToRegister(instr->temp());
1361   DCHECK(!temp.is(dividend) && !temp.is(result));
1362   Label needs_adjustment, done;
1363   __ Branch(&needs_adjustment, divisor > 0 ? lt : gt,
1364             dividend, Operand(zero_reg));
1365   __ TruncatingDiv(result, dividend, Abs(divisor));
1366   if (divisor < 0) __ Dsubu(result, zero_reg, result);
1367   __ jmp(&done);
1368   __ bind(&needs_adjustment);
1369   __ Daddu(temp, dividend, Operand(divisor > 0 ? 1 : -1));
1370   __ TruncatingDiv(result, temp, Abs(divisor));
1371   if (divisor < 0) __ Dsubu(result, zero_reg, result);
1372   __ Dsubu(result, result, Operand(1));
1373   __ bind(&done);
1374 }
1375
1376
1377 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI.
1378 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
1379   HBinaryOperation* hdiv = instr->hydrogen();
1380   Register dividend = ToRegister(instr->dividend());
1381   Register divisor = ToRegister(instr->divisor());
1382   const Register result = ToRegister(instr->result());
1383
1384   // On MIPS div is asynchronous - it will run in the background while we
1385   // check for special cases.
1386   __ Ddiv(result, dividend, divisor);
1387
1388   // Check for x / 0.
1389   if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1390     DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, divisor,
1391                  Operand(zero_reg));
1392   }
1393
1394   // Check for (0 / -x) that will produce negative zero.
1395   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1396     Label left_not_zero;
1397     __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg));
1398     DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, divisor,
1399                  Operand(zero_reg));
1400     __ bind(&left_not_zero);
1401   }
1402
1403   // Check for (kMinInt / -1).
1404   if (hdiv->CheckFlag(HValue::kCanOverflow) &&
1405       !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1406     Label left_not_min_int;
1407     __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt));
1408     DeoptimizeIf(eq, instr, Deoptimizer::kOverflow, divisor, Operand(-1));
1409     __ bind(&left_not_min_int);
1410   }
1411
1412   // We performed a truncating division. Correct the result if necessary.
1413   Label done;
1414   Register remainder = scratch0();
1415   if (kArchVariant != kMips64r6) {
1416     __ mfhi(remainder);
1417   } else {
1418     __ dmod(remainder, dividend, divisor);
1419   }
1420   __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT);
1421   __ Xor(remainder, remainder, Operand(divisor));
1422   __ Branch(&done, ge, remainder, Operand(zero_reg));
1423   __ Dsubu(result, result, Operand(1));
1424   __ bind(&done);
1425 }
1426
1427
1428 void LCodeGen::DoMulS(LMulS* instr) {
1429   Register scratch = scratch0();
1430   Register result = ToRegister(instr->result());
1431   // Note that result may alias left.
1432   Register left = ToRegister(instr->left());
1433   LOperand* right_op = instr->right();
1434
1435   bool bailout_on_minus_zero =
1436     instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
1437   bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1438
1439   if (right_op->IsConstantOperand()) {
1440     int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
1441
1442     if (bailout_on_minus_zero && (constant < 0)) {
1443       // The case of a null constant will be handled separately.
1444       // If constant is negative and left is null, the result should be -0.
1445       DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, left, Operand(zero_reg));
1446     }
1447
1448     switch (constant) {
1449       case -1:
1450         if (overflow) {
1451           __ DsubuAndCheckForOverflow(result, zero_reg, left, scratch);
1452           DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, scratch,
1453                        Operand(zero_reg));
1454         } else {
1455           __ Dsubu(result, zero_reg, left);
1456         }
1457         break;
1458       case 0:
1459         if (bailout_on_minus_zero) {
1460           // If left is strictly negative and the constant is null, the
1461           // result is -0. Deoptimize if required, otherwise return 0.
1462           DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, left,
1463                        Operand(zero_reg));
1464         }
1465         __ mov(result, zero_reg);
1466         break;
1467       case 1:
1468         // Nothing to do.
1469         __ Move(result, left);
1470         break;
1471       default:
1472         // Multiplying by powers of two and powers of two plus or minus
1473         // one can be done faster with shifted operands.
1474         // For other constants we emit standard code.
1475         int32_t mask = constant >> 31;
1476         uint32_t constant_abs = (constant + mask) ^ mask;
1477
1478         if (base::bits::IsPowerOfTwo32(constant_abs)) {
1479           int32_t shift = WhichPowerOf2(constant_abs);
1480           __ dsll(result, left, shift);
1481           // Correct the sign of the result if the constant is negative.
1482           if (constant < 0) __ Dsubu(result, zero_reg, result);
1483         } else if (base::bits::IsPowerOfTwo32(constant_abs - 1)) {
1484           int32_t shift = WhichPowerOf2(constant_abs - 1);
1485           __ dsll(scratch, left, shift);
1486           __ Daddu(result, scratch, left);
1487           // Correct the sign of the result if the constant is negative.
1488           if (constant < 0) __ Dsubu(result, zero_reg, result);
1489         } else if (base::bits::IsPowerOfTwo32(constant_abs + 1)) {
1490           int32_t shift = WhichPowerOf2(constant_abs + 1);
1491           __ dsll(scratch, left, shift);
1492           __ Dsubu(result, scratch, left);
1493           // Correct the sign of the result if the constant is negative.
1494           if (constant < 0) __ Dsubu(result, zero_reg, result);
1495         } else {
1496           // Generate standard code.
1497           __ li(at, constant);
1498           __ Dmul(result, left, at);
1499         }
1500     }
1501   } else {
1502     DCHECK(right_op->IsRegister());
1503     Register right = ToRegister(right_op);
1504
1505     if (overflow) {
1506       // hi:lo = left * right.
1507       __ Dmulh(result, left, right);
1508       __ dsra32(scratch, result, 0);
1509       __ sra(at, result, 31);
1510       __ SmiTag(result);
1511       DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, scratch, Operand(at));
1512     } else {
1513       __ SmiUntag(result, left);
1514       __ dmul(result, result, right);
1515     }
1516
1517     if (bailout_on_minus_zero) {
1518       Label done;
1519       __ Xor(at, left, right);
1520       __ Branch(&done, ge, at, Operand(zero_reg));
1521       // Bail out if the result is minus zero.
1522       DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result,
1523                    Operand(zero_reg));
1524       __ bind(&done);
1525     }
1526   }
1527 }
1528
1529
1530 void LCodeGen::DoMulI(LMulI* instr) {
1531   Register scratch = scratch0();
1532   Register result = ToRegister(instr->result());
1533   // Note that result may alias left.
1534   Register left = ToRegister(instr->left());
1535   LOperand* right_op = instr->right();
1536
1537   bool bailout_on_minus_zero =
1538       instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
1539   bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1540
1541   if (right_op->IsConstantOperand()) {
1542     int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
1543
1544     if (bailout_on_minus_zero && (constant < 0)) {
1545       // The case of a null constant will be handled separately.
1546       // If constant is negative and left is null, the result should be -0.
1547       DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, left, Operand(zero_reg));
1548     }
1549
1550     switch (constant) {
1551       case -1:
1552         if (overflow) {
1553           __ SubuAndCheckForOverflow(result, zero_reg, left, scratch);
1554           DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, scratch,
1555                        Operand(zero_reg));
1556         } else {
1557           __ Subu(result, zero_reg, left);
1558         }
1559         break;
1560       case 0:
1561         if (bailout_on_minus_zero) {
1562           // If left is strictly negative and the constant is null, the
1563           // result is -0. Deoptimize if required, otherwise return 0.
1564           DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, left,
1565                        Operand(zero_reg));
1566         }
1567         __ mov(result, zero_reg);
1568         break;
1569       case 1:
1570         // Nothing to do.
1571         __ Move(result, left);
1572         break;
1573       default:
1574         // Multiplying by powers of two and powers of two plus or minus
1575         // one can be done faster with shifted operands.
1576         // For other constants we emit standard code.
1577         int32_t mask = constant >> 31;
1578         uint32_t constant_abs = (constant + mask) ^ mask;
1579
1580         if (base::bits::IsPowerOfTwo32(constant_abs)) {
1581           int32_t shift = WhichPowerOf2(constant_abs);
1582           __ sll(result, left, shift);
1583           // Correct the sign of the result if the constant is negative.
1584           if (constant < 0) __ Subu(result, zero_reg, result);
1585         } else if (base::bits::IsPowerOfTwo32(constant_abs - 1)) {
1586           int32_t shift = WhichPowerOf2(constant_abs - 1);
1587           __ sll(scratch, left, shift);
1588           __ addu(result, scratch, left);
1589           // Correct the sign of the result if the constant is negative.
1590           if (constant < 0) __ Subu(result, zero_reg, result);
1591         } else if (base::bits::IsPowerOfTwo32(constant_abs + 1)) {
1592           int32_t shift = WhichPowerOf2(constant_abs + 1);
1593           __ sll(scratch, left, shift);
1594           __ Subu(result, scratch, left);
1595           // Correct the sign of the result if the constant is negative.
1596           if (constant < 0) __ Subu(result, zero_reg, result);
1597         } else {
1598           // Generate standard code.
1599           __ li(at, constant);
1600           __ Mul(result, left, at);
1601         }
1602     }
1603
1604   } else {
1605     DCHECK(right_op->IsRegister());
1606     Register right = ToRegister(right_op);
1607
1608     if (overflow) {
1609       // hi:lo = left * right.
1610       __ Dmul(result, left, right);
1611       __ dsra32(scratch, result, 0);
1612       __ sra(at, result, 31);
1613
1614       DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, scratch, Operand(at));
1615     } else {
1616       __ mul(result, left, right);
1617     }
1618
1619     if (bailout_on_minus_zero) {
1620       Label done;
1621       __ Xor(at, left, right);
1622       __ Branch(&done, ge, at, Operand(zero_reg));
1623       // Bail out if the result is minus zero.
1624       DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result,
1625                    Operand(zero_reg));
1626       __ bind(&done);
1627     }
1628   }
1629 }
1630
1631
1632 void LCodeGen::DoBitI(LBitI* instr) {
1633   LOperand* left_op = instr->left();
1634   LOperand* right_op = instr->right();
1635   DCHECK(left_op->IsRegister());
1636   Register left = ToRegister(left_op);
1637   Register result = ToRegister(instr->result());
1638   Operand right(no_reg);
1639
1640   if (right_op->IsStackSlot()) {
1641     right = Operand(EmitLoadRegister(right_op, at));
1642   } else {
1643     DCHECK(right_op->IsRegister() || right_op->IsConstantOperand());
1644     right = ToOperand(right_op);
1645   }
1646
1647   switch (instr->op()) {
1648     case Token::BIT_AND:
1649       __ And(result, left, right);
1650       break;
1651     case Token::BIT_OR:
1652       __ Or(result, left, right);
1653       break;
1654     case Token::BIT_XOR:
1655       if (right_op->IsConstantOperand() && right.immediate() == int32_t(~0)) {
1656         __ Nor(result, zero_reg, left);
1657       } else {
1658         __ Xor(result, left, right);
1659       }
1660       break;
1661     default:
1662       UNREACHABLE();
1663       break;
1664   }
1665 }
1666
1667
1668 void LCodeGen::DoShiftI(LShiftI* instr) {
1669   // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so
1670   // result may alias either of them.
1671   LOperand* right_op = instr->right();
1672   Register left = ToRegister(instr->left());
1673   Register result = ToRegister(instr->result());
1674
1675   if (right_op->IsRegister()) {
1676     // No need to mask the right operand on MIPS, it is built into the variable
1677     // shift instructions.
1678     switch (instr->op()) {
1679       case Token::ROR:
1680         __ Ror(result, left, Operand(ToRegister(right_op)));
1681         break;
1682       case Token::SAR:
1683         __ srav(result, left, ToRegister(right_op));
1684         break;
1685       case Token::SHR:
1686         __ srlv(result, left, ToRegister(right_op));
1687         if (instr->can_deopt()) {
1688            // TODO(yy): (-1) >>> 0. anything else?
1689           DeoptimizeIf(lt, instr, Deoptimizer::kNegativeValue, result,
1690                        Operand(zero_reg));
1691           DeoptimizeIf(gt, instr, Deoptimizer::kNegativeValue, result,
1692                        Operand(kMaxInt));
1693         }
1694         break;
1695       case Token::SHL:
1696         __ sllv(result, left, ToRegister(right_op));
1697         break;
1698       default:
1699         UNREACHABLE();
1700         break;
1701     }
1702   } else {
1703     // Mask the right_op operand.
1704     int value = ToInteger32(LConstantOperand::cast(right_op));
1705     uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
1706     switch (instr->op()) {
1707       case Token::ROR:
1708         if (shift_count != 0) {
1709           __ Ror(result, left, Operand(shift_count));
1710         } else {
1711           __ Move(result, left);
1712         }
1713         break;
1714       case Token::SAR:
1715         if (shift_count != 0) {
1716           __ sra(result, left, shift_count);
1717         } else {
1718           __ Move(result, left);
1719         }
1720         break;
1721       case Token::SHR:
1722         if (shift_count != 0) {
1723           __ srl(result, left, shift_count);
1724         } else {
1725           if (instr->can_deopt()) {
1726             __ And(at, left, Operand(0x80000000));
1727             DeoptimizeIf(ne, instr, Deoptimizer::kNegativeValue, at,
1728                          Operand(zero_reg));
1729           }
1730           __ Move(result, left);
1731         }
1732         break;
1733       case Token::SHL:
1734         if (shift_count != 0) {
1735           if (instr->hydrogen_value()->representation().IsSmi()) {
1736             __ dsll(result, left, shift_count);
1737           } else {
1738             __ sll(result, left, shift_count);
1739           }
1740         } else {
1741           __ Move(result, left);
1742         }
1743         break;
1744       default:
1745         UNREACHABLE();
1746         break;
1747     }
1748   }
1749 }
1750
1751
1752 void LCodeGen::DoSubS(LSubS* instr) {
1753   LOperand* left = instr->left();
1754   LOperand* right = instr->right();
1755   LOperand* result = instr->result();
1756   bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1757
1758   if (!can_overflow) {
1759     DCHECK(right->IsRegister() || right->IsConstantOperand());
1760     __ Dsubu(ToRegister(result), ToRegister(left), ToOperand(right));
1761   } else {  // can_overflow.
1762     Register overflow = scratch0();
1763     Register scratch = scratch1();
1764     DCHECK(right->IsRegister() || right->IsConstantOperand());
1765     __ DsubuAndCheckForOverflow(ToRegister(result), ToRegister(left),
1766                                 ToOperand(right), overflow, scratch);
1767     DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, overflow,
1768                  Operand(zero_reg));
1769   }
1770 }
1771
1772
1773 void LCodeGen::DoSubI(LSubI* instr) {
1774   LOperand* left = instr->left();
1775   LOperand* right = instr->right();
1776   LOperand* result = instr->result();
1777   bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1778
1779   if (!can_overflow) {
1780     DCHECK(right->IsRegister() || right->IsConstantOperand());
1781     __ Subu(ToRegister(result), ToRegister(left), ToOperand(right));
1782   } else {  // can_overflow.
1783     Register overflow = scratch0();
1784     Register scratch = scratch1();
1785     DCHECK(right->IsRegister() || right->IsConstantOperand());
1786     __ SubuAndCheckForOverflow(ToRegister(result), ToRegister(left),
1787                                ToOperand(right), overflow, scratch);
1788     DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, overflow,
1789                  Operand(zero_reg));
1790   }
1791 }
1792
1793
1794 void LCodeGen::DoConstantI(LConstantI* instr) {
1795   __ li(ToRegister(instr->result()), Operand(instr->value()));
1796 }
1797
1798
1799 void LCodeGen::DoConstantS(LConstantS* instr) {
1800   __ li(ToRegister(instr->result()), Operand(instr->value()));
1801 }
1802
1803
1804 void LCodeGen::DoConstantD(LConstantD* instr) {
1805   DCHECK(instr->result()->IsDoubleRegister());
1806   DoubleRegister result = ToDoubleRegister(instr->result());
1807   double v = instr->value();
1808   __ Move(result, v);
1809 }
1810
1811
1812 void LCodeGen::DoConstantE(LConstantE* instr) {
1813   __ li(ToRegister(instr->result()), Operand(instr->value()));
1814 }
1815
1816
1817 void LCodeGen::DoConstantT(LConstantT* instr) {
1818   Handle<Object> object = instr->value(isolate());
1819   AllowDeferredHandleDereference smi_check;
1820   __ li(ToRegister(instr->result()), object);
1821 }
1822
1823
1824 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) {
1825   Register result = ToRegister(instr->result());
1826   Register map = ToRegister(instr->value());
1827   __ EnumLength(result, map);
1828 }
1829
1830
1831 void LCodeGen::DoDateField(LDateField* instr) {
1832   Register object = ToRegister(instr->date());
1833   Register result = ToRegister(instr->result());
1834   Register scratch = ToRegister(instr->temp());
1835   Smi* index = instr->index();
1836   DCHECK(object.is(a0));
1837   DCHECK(result.is(v0));
1838   DCHECK(!scratch.is(scratch0()));
1839   DCHECK(!scratch.is(object));
1840
1841   if (index->value() == 0) {
1842     __ ld(result, FieldMemOperand(object, JSDate::kValueOffset));
1843   } else {
1844     Label runtime, done;
1845     if (index->value() < JSDate::kFirstUncachedField) {
1846       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
1847       __ li(scratch, Operand(stamp));
1848       __ ld(scratch, MemOperand(scratch));
1849       __ ld(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset));
1850       __ Branch(&runtime, ne, scratch, Operand(scratch0()));
1851       __ ld(result, FieldMemOperand(object, JSDate::kValueOffset +
1852                                             kPointerSize * index->value()));
1853       __ jmp(&done);
1854     }
1855     __ bind(&runtime);
1856     __ PrepareCallCFunction(2, scratch);
1857     __ li(a1, Operand(index));
1858     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
1859     __ bind(&done);
1860   }
1861 }
1862
1863
1864 MemOperand LCodeGen::BuildSeqStringOperand(Register string,
1865                                            LOperand* index,
1866                                            String::Encoding encoding) {
1867   if (index->IsConstantOperand()) {
1868     int offset = ToInteger32(LConstantOperand::cast(index));
1869     if (encoding == String::TWO_BYTE_ENCODING) {
1870       offset *= kUC16Size;
1871     }
1872     STATIC_ASSERT(kCharSize == 1);
1873     return FieldMemOperand(string, SeqString::kHeaderSize + offset);
1874   }
1875   Register scratch = scratch0();
1876   DCHECK(!scratch.is(string));
1877   DCHECK(!scratch.is(ToRegister(index)));
1878   if (encoding == String::ONE_BYTE_ENCODING) {
1879     __ Daddu(scratch, string, ToRegister(index));
1880   } else {
1881     STATIC_ASSERT(kUC16Size == 2);
1882     __ dsll(scratch, ToRegister(index), 1);
1883     __ Daddu(scratch, string, scratch);
1884   }
1885   return FieldMemOperand(scratch, SeqString::kHeaderSize);
1886 }
1887
1888
1889 void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) {
1890   String::Encoding encoding = instr->hydrogen()->encoding();
1891   Register string = ToRegister(instr->string());
1892   Register result = ToRegister(instr->result());
1893
1894   if (FLAG_debug_code) {
1895     Register scratch = scratch0();
1896     __ ld(scratch, FieldMemOperand(string, HeapObject::kMapOffset));
1897     __ lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
1898
1899     __ And(scratch, scratch,
1900            Operand(kStringRepresentationMask | kStringEncodingMask));
1901     static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
1902     static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
1903     __ Dsubu(at, scratch, Operand(encoding == String::ONE_BYTE_ENCODING
1904                                 ? one_byte_seq_type : two_byte_seq_type));
1905     __ Check(eq, kUnexpectedStringType, at, Operand(zero_reg));
1906   }
1907
1908   MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding);
1909   if (encoding == String::ONE_BYTE_ENCODING) {
1910     __ lbu(result, operand);
1911   } else {
1912     __ lhu(result, operand);
1913   }
1914 }
1915
1916
1917 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
1918   String::Encoding encoding = instr->hydrogen()->encoding();
1919   Register string = ToRegister(instr->string());
1920   Register value = ToRegister(instr->value());
1921
1922   if (FLAG_debug_code) {
1923     Register scratch = scratch0();
1924     Register index = ToRegister(instr->index());
1925     static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
1926     static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
1927     int encoding_mask =
1928         instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
1929         ? one_byte_seq_type : two_byte_seq_type;
1930     __ EmitSeqStringSetCharCheck(string, index, value, scratch, encoding_mask);
1931   }
1932
1933   MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding);
1934   if (encoding == String::ONE_BYTE_ENCODING) {
1935     __ sb(value, operand);
1936   } else {
1937     __ sh(value, operand);
1938   }
1939 }
1940
1941
1942 void LCodeGen::DoAddE(LAddE* instr) {
1943   LOperand* result = instr->result();
1944   LOperand* left = instr->left();
1945   LOperand* right = instr->right();
1946
1947   DCHECK(!instr->hydrogen()->CheckFlag(HValue::kCanOverflow));
1948   DCHECK(right->IsRegister() || right->IsConstantOperand());
1949   __ Daddu(ToRegister(result), ToRegister(left), ToOperand(right));
1950 }
1951
1952
1953 void LCodeGen::DoAddS(LAddS* instr) {
1954   LOperand* left = instr->left();
1955   LOperand* right = instr->right();
1956   LOperand* result = instr->result();
1957   bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1958
1959   if (!can_overflow) {
1960     DCHECK(right->IsRegister() || right->IsConstantOperand());
1961     __ Daddu(ToRegister(result), ToRegister(left), ToOperand(right));
1962   } else {  // can_overflow.
1963     Register overflow = scratch0();
1964     Register scratch = scratch1();
1965     DCHECK(right->IsRegister() || right->IsConstantOperand());
1966     __ DadduAndCheckForOverflow(ToRegister(result), ToRegister(left),
1967                                 ToOperand(right), overflow, scratch);
1968     DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, overflow,
1969                  Operand(zero_reg));
1970   }
1971 }
1972
1973
1974 void LCodeGen::DoAddI(LAddI* instr) {
1975   LOperand* left = instr->left();
1976   LOperand* right = instr->right();
1977   LOperand* result = instr->result();
1978   bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1979
1980   if (!can_overflow) {
1981     DCHECK(right->IsRegister() || right->IsConstantOperand());
1982     __ Addu(ToRegister(result), ToRegister(left), ToOperand(right));
1983   } else {  // can_overflow.
1984     Register overflow = scratch0();
1985     Register scratch = scratch1();
1986     DCHECK(right->IsRegister() || right->IsConstantOperand());
1987     __ AdduAndCheckForOverflow(ToRegister(result), ToRegister(left),
1988                                ToOperand(right), overflow, scratch);
1989     DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, overflow,
1990                  Operand(zero_reg));
1991   }
1992 }
1993
1994
1995 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
1996   LOperand* left = instr->left();
1997   LOperand* right = instr->right();
1998   HMathMinMax::Operation operation = instr->hydrogen()->operation();
1999   Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
2000   if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
2001     Register left_reg = ToRegister(left);
2002     Register right_reg = EmitLoadRegister(right, scratch0());
2003     Register result_reg = ToRegister(instr->result());
2004     Label return_right, done;
2005     Register scratch = scratch1();
2006     __ Slt(scratch, left_reg, Operand(right_reg));
2007     if (condition == ge) {
2008      __  Movz(result_reg, left_reg, scratch);
2009      __  Movn(result_reg, right_reg, scratch);
2010     } else {
2011      DCHECK(condition == le);
2012      __  Movn(result_reg, left_reg, scratch);
2013      __  Movz(result_reg, right_reg, scratch);
2014     }
2015   } else {
2016     DCHECK(instr->hydrogen()->representation().IsDouble());
2017     FPURegister left_reg = ToDoubleRegister(left);
2018     FPURegister right_reg = ToDoubleRegister(right);
2019     FPURegister result_reg = ToDoubleRegister(instr->result());
2020     Label check_nan_left, check_zero, return_left, return_right, done;
2021     __ BranchF(&check_zero, &check_nan_left, eq, left_reg, right_reg);
2022     __ BranchF(&return_left, NULL, condition, left_reg, right_reg);
2023     __ Branch(&return_right);
2024
2025     __ bind(&check_zero);
2026     // left == right != 0.
2027     __ BranchF(&return_left, NULL, ne, left_reg, kDoubleRegZero);
2028     // At this point, both left and right are either 0 or -0.
2029     if (operation == HMathMinMax::kMathMin) {
2030       __ neg_d(left_reg, left_reg);
2031       __ sub_d(result_reg, left_reg, right_reg);
2032       __ neg_d(result_reg, result_reg);
2033     } else {
2034       __ add_d(result_reg, left_reg, right_reg);
2035     }
2036     __ Branch(&done);
2037
2038     __ bind(&check_nan_left);
2039     // left == NaN.
2040     __ BranchF(NULL, &return_left, eq, left_reg, left_reg);
2041     __ bind(&return_right);
2042     if (!right_reg.is(result_reg)) {
2043       __ mov_d(result_reg, right_reg);
2044     }
2045     __ Branch(&done);
2046
2047     __ bind(&return_left);
2048     if (!left_reg.is(result_reg)) {
2049       __ mov_d(result_reg, left_reg);
2050     }
2051     __ bind(&done);
2052   }
2053 }
2054
2055
2056 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
2057   DoubleRegister left = ToDoubleRegister(instr->left());
2058   DoubleRegister right = ToDoubleRegister(instr->right());
2059   DoubleRegister result = ToDoubleRegister(instr->result());
2060   switch (instr->op()) {
2061     case Token::ADD:
2062       __ add_d(result, left, right);
2063       break;
2064     case Token::SUB:
2065       __ sub_d(result, left, right);
2066       break;
2067     case Token::MUL:
2068       __ mul_d(result, left, right);
2069       break;
2070     case Token::DIV:
2071       __ div_d(result, left, right);
2072       break;
2073     case Token::MOD: {
2074       // Save a0-a3 on the stack.
2075       RegList saved_regs = a0.bit() | a1.bit() | a2.bit() | a3.bit();
2076       __ MultiPush(saved_regs);
2077
2078       __ PrepareCallCFunction(0, 2, scratch0());
2079       __ MovToFloatParameters(left, right);
2080       __ CallCFunction(
2081           ExternalReference::mod_two_doubles_operation(isolate()),
2082           0, 2);
2083       // Move the result in the double result register.
2084       __ MovFromFloatResult(result);
2085
2086       // Restore saved register.
2087       __ MultiPop(saved_regs);
2088       break;
2089     }
2090     default:
2091       UNREACHABLE();
2092       break;
2093   }
2094 }
2095
2096
2097 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
2098   DCHECK(ToRegister(instr->context()).is(cp));
2099   DCHECK(ToRegister(instr->left()).is(a1));
2100   DCHECK(ToRegister(instr->right()).is(a0));
2101   DCHECK(ToRegister(instr->result()).is(v0));
2102
2103   Handle<Code> code =
2104       CodeFactory::BinaryOpIC(isolate(), instr->op(), instr->strength()).code();
2105   CallCode(code, RelocInfo::CODE_TARGET, instr);
2106   // Other arch use a nop here, to signal that there is no inlined
2107   // patchable code. Mips does not need the nop, since our marker
2108   // instruction (andi zero_reg) will never be used in normal code.
2109 }
2110
2111
2112 template<class InstrType>
2113 void LCodeGen::EmitBranch(InstrType instr,
2114                           Condition condition,
2115                           Register src1,
2116                           const Operand& src2) {
2117   int left_block = instr->TrueDestination(chunk_);
2118   int right_block = instr->FalseDestination(chunk_);
2119
2120   int next_block = GetNextEmittedBlock();
2121   if (right_block == left_block || condition == al) {
2122     EmitGoto(left_block);
2123   } else if (left_block == next_block) {
2124     __ Branch(chunk_->GetAssemblyLabel(right_block),
2125               NegateCondition(condition), src1, src2);
2126   } else if (right_block == next_block) {
2127     __ Branch(chunk_->GetAssemblyLabel(left_block), condition, src1, src2);
2128   } else {
2129     __ Branch(chunk_->GetAssemblyLabel(left_block), condition, src1, src2);
2130     __ Branch(chunk_->GetAssemblyLabel(right_block));
2131   }
2132 }
2133
2134
2135 template<class InstrType>
2136 void LCodeGen::EmitBranchF(InstrType instr,
2137                            Condition condition,
2138                            FPURegister src1,
2139                            FPURegister src2) {
2140   int right_block = instr->FalseDestination(chunk_);
2141   int left_block = instr->TrueDestination(chunk_);
2142
2143   int next_block = GetNextEmittedBlock();
2144   if (right_block == left_block) {
2145     EmitGoto(left_block);
2146   } else if (left_block == next_block) {
2147     __ BranchF(chunk_->GetAssemblyLabel(right_block), NULL,
2148                NegateFpuCondition(condition), src1, src2);
2149   } else if (right_block == next_block) {
2150     __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL,
2151                condition, src1, src2);
2152   } else {
2153     __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL,
2154                condition, src1, src2);
2155     __ Branch(chunk_->GetAssemblyLabel(right_block));
2156   }
2157 }
2158
2159
2160 template <class InstrType>
2161 void LCodeGen::EmitTrueBranch(InstrType instr, Condition condition,
2162                               Register src1, const Operand& src2) {
2163   int true_block = instr->TrueDestination(chunk_);
2164   __ Branch(chunk_->GetAssemblyLabel(true_block), condition, src1, src2);
2165 }
2166
2167
2168 template <class InstrType>
2169 void LCodeGen::EmitFalseBranch(InstrType instr, Condition condition,
2170                                Register src1, const Operand& src2) {
2171   int false_block = instr->FalseDestination(chunk_);
2172   __ Branch(chunk_->GetAssemblyLabel(false_block), condition, src1, src2);
2173 }
2174
2175
2176 template<class InstrType>
2177 void LCodeGen::EmitFalseBranchF(InstrType instr,
2178                                 Condition condition,
2179                                 FPURegister src1,
2180                                 FPURegister src2) {
2181   int false_block = instr->FalseDestination(chunk_);
2182   __ BranchF(chunk_->GetAssemblyLabel(false_block), NULL,
2183              condition, src1, src2);
2184 }
2185
2186
2187 void LCodeGen::DoDebugBreak(LDebugBreak* instr) {
2188   __ stop("LDebugBreak");
2189 }
2190
2191
2192 void LCodeGen::DoBranch(LBranch* instr) {
2193   Representation r = instr->hydrogen()->value()->representation();
2194   if (r.IsInteger32() || r.IsSmi()) {
2195     DCHECK(!info()->IsStub());
2196     Register reg = ToRegister(instr->value());
2197     EmitBranch(instr, ne, reg, Operand(zero_reg));
2198   } else if (r.IsDouble()) {
2199     DCHECK(!info()->IsStub());
2200     DoubleRegister reg = ToDoubleRegister(instr->value());
2201     // Test the double value. Zero and NaN are false.
2202     EmitBranchF(instr, ogl, reg, kDoubleRegZero);
2203   } else {
2204     DCHECK(r.IsTagged());
2205     Register reg = ToRegister(instr->value());
2206     HType type = instr->hydrogen()->value()->type();
2207     if (type.IsBoolean()) {
2208       DCHECK(!info()->IsStub());
2209       __ LoadRoot(at, Heap::kTrueValueRootIndex);
2210       EmitBranch(instr, eq, reg, Operand(at));
2211     } else if (type.IsSmi()) {
2212       DCHECK(!info()->IsStub());
2213       EmitBranch(instr, ne, reg, Operand(zero_reg));
2214     } else if (type.IsJSArray()) {
2215       DCHECK(!info()->IsStub());
2216       EmitBranch(instr, al, zero_reg, Operand(zero_reg));
2217     } else if (type.IsHeapNumber()) {
2218       DCHECK(!info()->IsStub());
2219       DoubleRegister dbl_scratch = double_scratch0();
2220       __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
2221       // Test the double value. Zero and NaN are false.
2222       EmitBranchF(instr, ogl, dbl_scratch, kDoubleRegZero);
2223     } else if (type.IsString()) {
2224       DCHECK(!info()->IsStub());
2225       __ ld(at, FieldMemOperand(reg, String::kLengthOffset));
2226       EmitBranch(instr, ne, at, Operand(zero_reg));
2227     } else {
2228       ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
2229       // Avoid deopts in the case where we've never executed this path before.
2230       if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
2231
2232       if (expected.Contains(ToBooleanStub::UNDEFINED)) {
2233         // undefined -> false.
2234         __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
2235         __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at));
2236       }
2237       if (expected.Contains(ToBooleanStub::BOOLEAN)) {
2238         // Boolean -> its value.
2239         __ LoadRoot(at, Heap::kTrueValueRootIndex);
2240         __ Branch(instr->TrueLabel(chunk_), eq, reg, Operand(at));
2241         __ LoadRoot(at, Heap::kFalseValueRootIndex);
2242         __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at));
2243       }
2244       if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
2245         // 'null' -> false.
2246         __ LoadRoot(at, Heap::kNullValueRootIndex);
2247         __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at));
2248       }
2249
2250       if (expected.Contains(ToBooleanStub::SMI)) {
2251         // Smis: 0 -> false, all other -> true.
2252         __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(zero_reg));
2253         __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2254       } else if (expected.NeedsMap()) {
2255         // If we need a map later and have a Smi -> deopt.
2256         __ SmiTst(reg, at);
2257         DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
2258       }
2259
2260       const Register map = scratch0();
2261       if (expected.NeedsMap()) {
2262         __ ld(map, FieldMemOperand(reg, HeapObject::kMapOffset));
2263         if (expected.CanBeUndetectable()) {
2264           // Undetectable -> false.
2265           __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset));
2266           __ And(at, at, Operand(1 << Map::kIsUndetectable));
2267           __ Branch(instr->FalseLabel(chunk_), ne, at, Operand(zero_reg));
2268         }
2269       }
2270
2271       if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
2272         // spec object -> true.
2273         __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
2274         __ Branch(instr->TrueLabel(chunk_),
2275                   ge, at, Operand(FIRST_SPEC_OBJECT_TYPE));
2276       }
2277
2278       if (expected.Contains(ToBooleanStub::STRING)) {
2279         // String value -> false iff empty.
2280         Label not_string;
2281         __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
2282         __ Branch(&not_string, ge , at, Operand(FIRST_NONSTRING_TYPE));
2283         __ ld(at, FieldMemOperand(reg, String::kLengthOffset));
2284         __ Branch(instr->TrueLabel(chunk_), ne, at, Operand(zero_reg));
2285         __ Branch(instr->FalseLabel(chunk_));
2286         __ bind(&not_string);
2287       }
2288
2289       if (expected.Contains(ToBooleanStub::SYMBOL)) {
2290         // Symbol value -> true.
2291         const Register scratch = scratch1();
2292         __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
2293         __ Branch(instr->TrueLabel(chunk_), eq, scratch, Operand(SYMBOL_TYPE));
2294       }
2295
2296       if (expected.Contains(ToBooleanStub::SIMD_VALUE)) {
2297         // SIMD value -> true.
2298         const Register scratch = scratch1();
2299         __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
2300         __ Branch(instr->TrueLabel(chunk_), eq, scratch,
2301                   Operand(SIMD128_VALUE_TYPE));
2302       }
2303
2304       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
2305         // heap number -> false iff +0, -0, or NaN.
2306         DoubleRegister dbl_scratch = double_scratch0();
2307         Label not_heap_number;
2308         __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
2309         __ Branch(&not_heap_number, ne, map, Operand(at));
2310         __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
2311         __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2312                    ne, dbl_scratch, kDoubleRegZero);
2313         // Falls through if dbl_scratch == 0.
2314         __ Branch(instr->FalseLabel(chunk_));
2315         __ bind(&not_heap_number);
2316       }
2317
2318       if (!expected.IsGeneric()) {
2319         // We've seen something for the first time -> deopt.
2320         // This can only happen if we are not generic already.
2321         DeoptimizeIf(al, instr, Deoptimizer::kUnexpectedObject, zero_reg,
2322                      Operand(zero_reg));
2323       }
2324     }
2325   }
2326 }
2327
2328
2329 void LCodeGen::EmitGoto(int block) {
2330   if (!IsNextEmittedBlock(block)) {
2331     __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2332   }
2333 }
2334
2335
2336 void LCodeGen::DoGoto(LGoto* instr) {
2337   EmitGoto(instr->block_id());
2338 }
2339
2340
2341 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
2342   Condition cond = kNoCondition;
2343   switch (op) {
2344     case Token::EQ:
2345     case Token::EQ_STRICT:
2346       cond = eq;
2347       break;
2348     case Token::NE:
2349     case Token::NE_STRICT:
2350       cond = ne;
2351       break;
2352     case Token::LT:
2353       cond = is_unsigned ? lo : lt;
2354       break;
2355     case Token::GT:
2356       cond = is_unsigned ? hi : gt;
2357       break;
2358     case Token::LTE:
2359       cond = is_unsigned ? ls : le;
2360       break;
2361     case Token::GTE:
2362       cond = is_unsigned ? hs : ge;
2363       break;
2364     case Token::IN:
2365     case Token::INSTANCEOF:
2366     default:
2367       UNREACHABLE();
2368   }
2369   return cond;
2370 }
2371
2372
2373 void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
2374   LOperand* left = instr->left();
2375   LOperand* right = instr->right();
2376   bool is_unsigned =
2377       instr->hydrogen()->left()->CheckFlag(HInstruction::kUint32) ||
2378       instr->hydrogen()->right()->CheckFlag(HInstruction::kUint32);
2379   Condition cond = TokenToCondition(instr->op(), is_unsigned);
2380
2381   if (left->IsConstantOperand() && right->IsConstantOperand()) {
2382     // We can statically evaluate the comparison.
2383     double left_val = ToDouble(LConstantOperand::cast(left));
2384     double right_val = ToDouble(LConstantOperand::cast(right));
2385     int next_block = EvalComparison(instr->op(), left_val, right_val) ?
2386         instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_);
2387     EmitGoto(next_block);
2388   } else {
2389     if (instr->is_double()) {
2390       // Compare left and right as doubles and load the
2391       // resulting flags into the normal status register.
2392       FPURegister left_reg = ToDoubleRegister(left);
2393       FPURegister right_reg = ToDoubleRegister(right);
2394
2395       // If a NaN is involved, i.e. the result is unordered,
2396       // jump to false block label.
2397       __ BranchF(NULL, instr->FalseLabel(chunk_), eq,
2398                  left_reg, right_reg);
2399
2400       EmitBranchF(instr, cond, left_reg, right_reg);
2401     } else {
2402       Register cmp_left;
2403       Operand cmp_right = Operand((int64_t)0);
2404       if (right->IsConstantOperand()) {
2405         int32_t value = ToInteger32(LConstantOperand::cast(right));
2406         if (instr->hydrogen_value()->representation().IsSmi()) {
2407           cmp_left = ToRegister(left);
2408           cmp_right = Operand(Smi::FromInt(value));
2409         } else {
2410           cmp_left = ToRegister(left);
2411           cmp_right = Operand(value);
2412         }
2413       } else if (left->IsConstantOperand()) {
2414         int32_t value = ToInteger32(LConstantOperand::cast(left));
2415         if (instr->hydrogen_value()->representation().IsSmi()) {
2416           cmp_left = ToRegister(right);
2417           cmp_right = Operand(Smi::FromInt(value));
2418         } else {
2419           cmp_left = ToRegister(right);
2420           cmp_right = Operand(value);
2421         }
2422         // We commuted the operands, so commute the condition.
2423         cond = CommuteCondition(cond);
2424       } else {
2425         cmp_left = ToRegister(left);
2426         cmp_right = Operand(ToRegister(right));
2427       }
2428
2429       EmitBranch(instr, cond, cmp_left, cmp_right);
2430     }
2431   }
2432 }
2433
2434
2435 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
2436   Register left = ToRegister(instr->left());
2437   Register right = ToRegister(instr->right());
2438
2439   EmitBranch(instr, eq, left, Operand(right));
2440 }
2441
2442
2443 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
2444   if (instr->hydrogen()->representation().IsTagged()) {
2445     Register input_reg = ToRegister(instr->object());
2446     __ li(at, Operand(factory()->the_hole_value()));
2447     EmitBranch(instr, eq, input_reg, Operand(at));
2448     return;
2449   }
2450
2451   DoubleRegister input_reg = ToDoubleRegister(instr->object());
2452   EmitFalseBranchF(instr, eq, input_reg, input_reg);
2453
2454   Register scratch = scratch0();
2455   __ FmoveHigh(scratch, input_reg);
2456   EmitBranch(instr, eq, scratch,
2457              Operand(static_cast<int32_t>(kHoleNanUpper32)));
2458 }
2459
2460
2461 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
2462   Representation rep = instr->hydrogen()->value()->representation();
2463   DCHECK(!rep.IsInteger32());
2464   Register scratch = ToRegister(instr->temp());
2465
2466   if (rep.IsDouble()) {
2467     DoubleRegister value = ToDoubleRegister(instr->value());
2468     EmitFalseBranchF(instr, ne, value, kDoubleRegZero);
2469     __ FmoveHigh(scratch, value);
2470     // Only use low 32-bits of value.
2471     __ dsll32(scratch, scratch, 0);
2472     __ dsrl32(scratch, scratch, 0);
2473     __ li(at, 0x80000000);
2474   } else {
2475     Register value = ToRegister(instr->value());
2476     __ CheckMap(value,
2477                 scratch,
2478                 Heap::kHeapNumberMapRootIndex,
2479                 instr->FalseLabel(chunk()),
2480                 DO_SMI_CHECK);
2481     __ lwu(scratch, FieldMemOperand(value, HeapNumber::kExponentOffset));
2482     EmitFalseBranch(instr, ne, scratch, Operand(0x80000000));
2483     __ lwu(scratch, FieldMemOperand(value, HeapNumber::kMantissaOffset));
2484     __ mov(at, zero_reg);
2485   }
2486   EmitBranch(instr, eq, scratch, Operand(at));
2487 }
2488
2489
2490 Condition LCodeGen::EmitIsString(Register input,
2491                                  Register temp1,
2492                                  Label* is_not_string,
2493                                  SmiCheck check_needed = INLINE_SMI_CHECK) {
2494   if (check_needed == INLINE_SMI_CHECK) {
2495     __ JumpIfSmi(input, is_not_string);
2496   }
2497   __ GetObjectType(input, temp1, temp1);
2498
2499   return lt;
2500 }
2501
2502
2503 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
2504   Register reg = ToRegister(instr->value());
2505   Register temp1 = ToRegister(instr->temp());
2506
2507   SmiCheck check_needed =
2508       instr->hydrogen()->value()->type().IsHeapObject()
2509           ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2510   Condition true_cond =
2511       EmitIsString(reg, temp1, instr->FalseLabel(chunk_), check_needed);
2512
2513   EmitBranch(instr, true_cond, temp1,
2514              Operand(FIRST_NONSTRING_TYPE));
2515 }
2516
2517
2518 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
2519   Register input_reg = EmitLoadRegister(instr->value(), at);
2520   __ And(at, input_reg, kSmiTagMask);
2521   EmitBranch(instr, eq, at, Operand(zero_reg));
2522 }
2523
2524
2525 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
2526   Register input = ToRegister(instr->value());
2527   Register temp = ToRegister(instr->temp());
2528
2529   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2530     __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2531   }
2532   __ ld(temp, FieldMemOperand(input, HeapObject::kMapOffset));
2533   __ lbu(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
2534   __ And(at, temp, Operand(1 << Map::kIsUndetectable));
2535   EmitBranch(instr, ne, at, Operand(zero_reg));
2536 }
2537
2538
2539 static Condition ComputeCompareCondition(Token::Value op) {
2540   switch (op) {
2541     case Token::EQ_STRICT:
2542     case Token::EQ:
2543       return eq;
2544     case Token::LT:
2545       return lt;
2546     case Token::GT:
2547       return gt;
2548     case Token::LTE:
2549       return le;
2550     case Token::GTE:
2551       return ge;
2552     default:
2553       UNREACHABLE();
2554       return kNoCondition;
2555   }
2556 }
2557
2558
2559 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
2560   DCHECK(ToRegister(instr->context()).is(cp));
2561   DCHECK(ToRegister(instr->left()).is(a1));
2562   DCHECK(ToRegister(instr->right()).is(a0));
2563
2564   Handle<Code> code = CodeFactory::StringCompare(isolate()).code();
2565   CallCode(code, RelocInfo::CODE_TARGET, instr);
2566
2567   EmitBranch(instr, ComputeCompareCondition(instr->op()), v0,
2568              Operand(zero_reg));
2569 }
2570
2571
2572 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
2573   InstanceType from = instr->from();
2574   InstanceType to = instr->to();
2575   if (from == FIRST_TYPE) return to;
2576   DCHECK(from == to || to == LAST_TYPE);
2577   return from;
2578 }
2579
2580
2581 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
2582   InstanceType from = instr->from();
2583   InstanceType to = instr->to();
2584   if (from == to) return eq;
2585   if (to == LAST_TYPE) return hs;
2586   if (from == FIRST_TYPE) return ls;
2587   UNREACHABLE();
2588   return eq;
2589 }
2590
2591
2592 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
2593   Register scratch = scratch0();
2594   Register input = ToRegister(instr->value());
2595
2596   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2597     __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2598   }
2599
2600   __ GetObjectType(input, scratch, scratch);
2601   EmitBranch(instr,
2602              BranchCondition(instr->hydrogen()),
2603              scratch,
2604              Operand(TestType(instr->hydrogen())));
2605 }
2606
2607
2608 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
2609   Register input = ToRegister(instr->value());
2610   Register result = ToRegister(instr->result());
2611
2612   __ AssertString(input);
2613
2614   __ lwu(result, FieldMemOperand(input, String::kHashFieldOffset));
2615   __ IndexFromHash(result, result);
2616 }
2617
2618
2619 void LCodeGen::DoHasCachedArrayIndexAndBranch(
2620     LHasCachedArrayIndexAndBranch* instr) {
2621   Register input = ToRegister(instr->value());
2622   Register scratch = scratch0();
2623
2624   __ lwu(scratch,
2625          FieldMemOperand(input, String::kHashFieldOffset));
2626   __ And(at, scratch, Operand(String::kContainsCachedArrayIndexMask));
2627   EmitBranch(instr, eq, at, Operand(zero_reg));
2628 }
2629
2630
2631 // Branches to a label or falls through with the answer in flags.  Trashes
2632 // the temp registers, but not the input.
2633 void LCodeGen::EmitClassOfTest(Label* is_true,
2634                                Label* is_false,
2635                                Handle<String>class_name,
2636                                Register input,
2637                                Register temp,
2638                                Register temp2) {
2639   DCHECK(!input.is(temp));
2640   DCHECK(!input.is(temp2));
2641   DCHECK(!temp.is(temp2));
2642
2643   __ JumpIfSmi(input, is_false);
2644
2645   if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
2646     // Assuming the following assertions, we can use the same compares to test
2647     // for both being a function type and being in the object type range.
2648     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
2649     STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2650                   FIRST_SPEC_OBJECT_TYPE + 1);
2651     STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2652                   LAST_SPEC_OBJECT_TYPE - 1);
2653     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
2654
2655     __ GetObjectType(input, temp, temp2);
2656     __ Branch(is_false, lt, temp2, Operand(FIRST_SPEC_OBJECT_TYPE));
2657     __ Branch(is_true, eq, temp2, Operand(FIRST_SPEC_OBJECT_TYPE));
2658     __ Branch(is_true, eq, temp2, Operand(LAST_SPEC_OBJECT_TYPE));
2659   } else {
2660     // Faster code path to avoid two compares: subtract lower bound from the
2661     // actual type and do a signed compare with the width of the type range.
2662     __ GetObjectType(input, temp, temp2);
2663     __ Dsubu(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2664     __ Branch(is_false, gt, temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
2665                                            FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2666   }
2667
2668   // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
2669   // Check if the constructor in the map is a function.
2670   Register instance_type = scratch1();
2671   DCHECK(!instance_type.is(temp));
2672   __ GetMapConstructor(temp, temp, temp2, instance_type);
2673
2674   // Objects with a non-function constructor have class 'Object'.
2675   if (String::Equals(class_name, isolate()->factory()->Object_string())) {
2676     __ Branch(is_true, ne, instance_type, Operand(JS_FUNCTION_TYPE));
2677   } else {
2678     __ Branch(is_false, ne, instance_type, Operand(JS_FUNCTION_TYPE));
2679   }
2680
2681   // temp now contains the constructor function. Grab the
2682   // instance class name from there.
2683   __ ld(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset));
2684   __ ld(temp, FieldMemOperand(temp,
2685                                SharedFunctionInfo::kInstanceClassNameOffset));
2686   // The class name we are testing against is internalized since it's a literal.
2687   // The name in the constructor is internalized because of the way the context
2688   // is booted.  This routine isn't expected to work for random API-created
2689   // classes and it doesn't have to because you can't access it with natives
2690   // syntax.  Since both sides are internalized it is sufficient to use an
2691   // identity comparison.
2692
2693   // End with the address of this class_name instance in temp register.
2694   // On MIPS, the caller must do the comparison with Handle<String>class_name.
2695 }
2696
2697
2698 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
2699   Register input = ToRegister(instr->value());
2700   Register temp = scratch0();
2701   Register temp2 = ToRegister(instr->temp());
2702   Handle<String> class_name = instr->hydrogen()->class_name();
2703
2704   EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2705                   class_name, input, temp, temp2);
2706
2707   EmitBranch(instr, eq, temp, Operand(class_name));
2708 }
2709
2710
2711 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
2712   Register reg = ToRegister(instr->value());
2713   Register temp = ToRegister(instr->temp());
2714
2715   __ ld(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
2716   EmitBranch(instr, eq, temp, Operand(instr->map()));
2717 }
2718
2719
2720 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
2721   DCHECK(ToRegister(instr->context()).is(cp));
2722   Label true_label, done;
2723   DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister()));
2724   DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister()));
2725   DCHECK(ToRegister(instr->result()).is(v0));
2726
2727   InstanceOfStub stub(isolate());
2728   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2729 }
2730
2731
2732 void LCodeGen::DoHasInPrototypeChainAndBranch(
2733     LHasInPrototypeChainAndBranch* instr) {
2734   Register const object = ToRegister(instr->object());
2735   Register const object_map = scratch0();
2736   Register const object_prototype = object_map;
2737   Register const prototype = ToRegister(instr->prototype());
2738
2739   // The {object} must be a spec object.  It's sufficient to know that {object}
2740   // is not a smi, since all other non-spec objects have {null} prototypes and
2741   // will be ruled out below.
2742   if (instr->hydrogen()->ObjectNeedsSmiCheck()) {
2743     __ SmiTst(object, at);
2744     EmitFalseBranch(instr, eq, at, Operand(zero_reg));
2745   }
2746
2747   // Loop through the {object}s prototype chain looking for the {prototype}.
2748   __ ld(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
2749   Label loop;
2750   __ bind(&loop);
2751   __ ld(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset));
2752   EmitTrueBranch(instr, eq, object_prototype, Operand(prototype));
2753   __ LoadRoot(at, Heap::kNullValueRootIndex);
2754   EmitFalseBranch(instr, eq, object_prototype, Operand(at));
2755   __ Branch(&loop, USE_DELAY_SLOT);
2756   __ ld(object_map, FieldMemOperand(object_prototype,
2757                                     HeapObject::kMapOffset));  // In delay slot.
2758 }
2759
2760
2761 void LCodeGen::DoCmpT(LCmpT* instr) {
2762   DCHECK(ToRegister(instr->context()).is(cp));
2763   Token::Value op = instr->op();
2764
2765   Handle<Code> ic =
2766       CodeFactory::CompareIC(isolate(), op, instr->strength()).code();
2767   CallCode(ic, RelocInfo::CODE_TARGET, instr);
2768   // On MIPS there is no need for a "no inlined smi code" marker (nop).
2769
2770   Condition condition = ComputeCompareCondition(op);
2771   // A minor optimization that relies on LoadRoot always emitting one
2772   // instruction.
2773   Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm());
2774   Label done, check;
2775   __ Branch(USE_DELAY_SLOT, &done, condition, v0, Operand(zero_reg));
2776   __ bind(&check);
2777   __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
2778   DCHECK_EQ(1, masm()->InstructionsGeneratedSince(&check));
2779   __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
2780   __ bind(&done);
2781 }
2782
2783
2784 void LCodeGen::DoReturn(LReturn* instr) {
2785   if (FLAG_trace && info()->IsOptimizing()) {
2786     // Push the return value on the stack as the parameter.
2787     // Runtime::TraceExit returns its parameter in v0. We're leaving the code
2788     // managed by the register allocator and tearing down the frame, it's
2789     // safe to write to the context register.
2790     __ push(v0);
2791     __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2792     __ CallRuntime(Runtime::kTraceExit, 1);
2793   }
2794   if (info()->saves_caller_doubles()) {
2795     RestoreCallerDoubles();
2796   }
2797   int no_frame_start = -1;
2798   if (NeedsEagerFrame()) {
2799     __ mov(sp, fp);
2800     no_frame_start = masm_->pc_offset();
2801     __ Pop(ra, fp);
2802   }
2803   if (instr->has_constant_parameter_count()) {
2804     int parameter_count = ToInteger32(instr->constant_parameter_count());
2805     int32_t sp_delta = (parameter_count + 1) * kPointerSize;
2806     if (sp_delta != 0) {
2807       __ Daddu(sp, sp, Operand(sp_delta));
2808     }
2809   } else {
2810     DCHECK(info()->IsStub());  // Functions would need to drop one more value.
2811     Register reg = ToRegister(instr->parameter_count());
2812     // The argument count parameter is a smi
2813     __ SmiUntag(reg);
2814     __ dsll(at, reg, kPointerSizeLog2);
2815     __ Daddu(sp, sp, at);
2816   }
2817
2818   __ Jump(ra);
2819
2820   if (no_frame_start != -1) {
2821     info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
2822   }
2823 }
2824
2825
2826 template <class T>
2827 void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
2828   Register vector_register = ToRegister(instr->temp_vector());
2829   Register slot_register = LoadWithVectorDescriptor::SlotRegister();
2830   DCHECK(vector_register.is(LoadWithVectorDescriptor::VectorRegister()));
2831   DCHECK(slot_register.is(a0));
2832
2833   AllowDeferredHandleDereference vector_structure_check;
2834   Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector();
2835   __ li(vector_register, vector);
2836   // No need to allocate this register.
2837   FeedbackVectorICSlot slot = instr->hydrogen()->slot();
2838   int index = vector->GetIndex(slot);
2839   __ li(slot_register, Operand(Smi::FromInt(index)));
2840 }
2841
2842
2843 template <class T>
2844 void LCodeGen::EmitVectorStoreICRegisters(T* instr) {
2845   Register vector_register = ToRegister(instr->temp_vector());
2846   Register slot_register = ToRegister(instr->temp_slot());
2847
2848   AllowDeferredHandleDereference vector_structure_check;
2849   Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector();
2850   __ li(vector_register, vector);
2851   FeedbackVectorICSlot slot = instr->hydrogen()->slot();
2852   int index = vector->GetIndex(slot);
2853   __ li(slot_register, Operand(Smi::FromInt(index)));
2854 }
2855
2856
2857 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
2858   DCHECK(ToRegister(instr->context()).is(cp));
2859   DCHECK(ToRegister(instr->global_object())
2860             .is(LoadDescriptor::ReceiverRegister()));
2861   DCHECK(ToRegister(instr->result()).is(v0));
2862
2863   __ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
2864   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
2865   Handle<Code> ic =
2866       CodeFactory::LoadICInOptimizedCode(isolate(), instr->typeof_mode(),
2867                                          SLOPPY, PREMONOMORPHIC).code();
2868   CallCode(ic, RelocInfo::CODE_TARGET, instr);
2869 }
2870
2871
2872 void LCodeGen::DoLoadGlobalViaContext(LLoadGlobalViaContext* instr) {
2873   DCHECK(ToRegister(instr->context()).is(cp));
2874   DCHECK(ToRegister(instr->result()).is(v0));
2875
2876   int const slot = instr->slot_index();
2877   int const depth = instr->depth();
2878   if (depth <= LoadGlobalViaContextStub::kMaximumDepth) {
2879     __ li(LoadGlobalViaContextDescriptor::SlotRegister(), Operand(slot));
2880     Handle<Code> stub =
2881         CodeFactory::LoadGlobalViaContext(isolate(), depth).code();
2882     CallCode(stub, RelocInfo::CODE_TARGET, instr);
2883   } else {
2884     __ Push(Smi::FromInt(slot));
2885     __ CallRuntime(Runtime::kLoadGlobalViaContext, 1);
2886   }
2887 }
2888
2889
2890 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2891   Register context = ToRegister(instr->context());
2892   Register result = ToRegister(instr->result());
2893
2894   __ ld(result, ContextOperand(context, instr->slot_index()));
2895   if (instr->hydrogen()->RequiresHoleCheck()) {
2896     __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2897
2898     if (instr->hydrogen()->DeoptimizesOnHole()) {
2899       DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(at));
2900     } else {
2901       Label is_not_hole;
2902       __ Branch(&is_not_hole, ne, result, Operand(at));
2903       __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
2904       __ bind(&is_not_hole);
2905     }
2906   }
2907 }
2908
2909
2910 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2911   Register context = ToRegister(instr->context());
2912   Register value = ToRegister(instr->value());
2913   Register scratch = scratch0();
2914   MemOperand target = ContextOperand(context, instr->slot_index());
2915
2916   Label skip_assignment;
2917
2918   if (instr->hydrogen()->RequiresHoleCheck()) {
2919     __ ld(scratch, target);
2920     __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2921
2922     if (instr->hydrogen()->DeoptimizesOnHole()) {
2923       DeoptimizeIf(eq, instr, Deoptimizer::kHole, scratch, Operand(at));
2924     } else {
2925       __ Branch(&skip_assignment, ne, scratch, Operand(at));
2926     }
2927   }
2928
2929   __ sd(value, target);
2930   if (instr->hydrogen()->NeedsWriteBarrier()) {
2931     SmiCheck check_needed =
2932         instr->hydrogen()->value()->type().IsHeapObject()
2933             ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2934     __ RecordWriteContextSlot(context,
2935                               target.offset(),
2936                               value,
2937                               scratch0(),
2938                               GetRAState(),
2939                               kSaveFPRegs,
2940                               EMIT_REMEMBERED_SET,
2941                               check_needed);
2942   }
2943
2944   __ bind(&skip_assignment);
2945 }
2946
2947
2948 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
2949   HObjectAccess access = instr->hydrogen()->access();
2950   int offset = access.offset();
2951   Register object = ToRegister(instr->object());
2952   if (access.IsExternalMemory()) {
2953     Register result = ToRegister(instr->result());
2954     MemOperand operand = MemOperand(object, offset);
2955     __ Load(result, operand, access.representation());
2956     return;
2957   }
2958
2959   if (instr->hydrogen()->representation().IsDouble()) {
2960     DoubleRegister result = ToDoubleRegister(instr->result());
2961     __ ldc1(result, FieldMemOperand(object, offset));
2962     return;
2963   }
2964
2965   Register result = ToRegister(instr->result());
2966   if (!access.IsInobject()) {
2967     __ ld(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
2968     object = result;
2969   }
2970
2971   Representation representation = access.representation();
2972   if (representation.IsSmi() && SmiValuesAre32Bits() &&
2973       instr->hydrogen()->representation().IsInteger32()) {
2974     if (FLAG_debug_code) {
2975       // Verify this is really an Smi.
2976       Register scratch = scratch0();
2977       __ Load(scratch, FieldMemOperand(object, offset), representation);
2978       __ AssertSmi(scratch);
2979     }
2980
2981     // Read int value directly from upper half of the smi.
2982     STATIC_ASSERT(kSmiTag == 0);
2983     STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32);
2984     offset += kPointerSize / 2;
2985     representation = Representation::Integer32();
2986   }
2987   __ Load(result, FieldMemOperand(object, offset), representation);
2988 }
2989
2990
2991 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
2992   DCHECK(ToRegister(instr->context()).is(cp));
2993   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
2994   DCHECK(ToRegister(instr->result()).is(v0));
2995
2996   // Name is always in a2.
2997   __ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
2998   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
2999   Handle<Code> ic =
3000       CodeFactory::LoadICInOptimizedCode(
3001           isolate(), NOT_INSIDE_TYPEOF, instr->hydrogen()->language_mode(),
3002           instr->hydrogen()->initialization_state()).code();
3003   CallCode(ic, RelocInfo::CODE_TARGET, instr);
3004 }
3005
3006
3007 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
3008   Register scratch = scratch0();
3009   Register function = ToRegister(instr->function());
3010   Register result = ToRegister(instr->result());
3011
3012   // Get the prototype or initial map from the function.
3013   __ ld(result,
3014          FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3015
3016   // Check that the function has a prototype or an initial map.
3017   __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
3018   DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(at));
3019
3020   // If the function does not have an initial map, we're done.
3021   Label done;
3022   __ GetObjectType(result, scratch, scratch);
3023   __ Branch(&done, ne, scratch, Operand(MAP_TYPE));
3024
3025   // Get the prototype from the initial map.
3026   __ ld(result, FieldMemOperand(result, Map::kPrototypeOffset));
3027
3028   // All done.
3029   __ bind(&done);
3030 }
3031
3032
3033 void LCodeGen::DoLoadRoot(LLoadRoot* instr) {
3034   Register result = ToRegister(instr->result());
3035   __ LoadRoot(result, instr->index());
3036 }
3037
3038
3039 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
3040   Register arguments = ToRegister(instr->arguments());
3041   Register result = ToRegister(instr->result());
3042   // There are two words between the frame pointer and the last argument.
3043   // Subtracting from length accounts for one of them add one more.
3044   if (instr->length()->IsConstantOperand()) {
3045     int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
3046     if (instr->index()->IsConstantOperand()) {
3047       int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
3048       int index = (const_length - const_index) + 1;
3049       __ ld(result, MemOperand(arguments, index * kPointerSize));
3050     } else {
3051       Register index = ToRegister(instr->index());
3052       __ li(at, Operand(const_length + 1));
3053       __ Dsubu(result, at, index);
3054       __ dsll(at, result, kPointerSizeLog2);
3055       __ Daddu(at, arguments, at);
3056       __ ld(result, MemOperand(at));
3057     }
3058   } else if (instr->index()->IsConstantOperand()) {
3059     Register length = ToRegister(instr->length());
3060     int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
3061     int loc = const_index - 1;
3062     if (loc != 0) {
3063       __ Dsubu(result, length, Operand(loc));
3064       __ dsll(at, result, kPointerSizeLog2);
3065       __ Daddu(at, arguments, at);
3066       __ ld(result, MemOperand(at));
3067     } else {
3068       __ dsll(at, length, kPointerSizeLog2);
3069       __ Daddu(at, arguments, at);
3070       __ ld(result, MemOperand(at));
3071     }
3072   } else {
3073     Register length = ToRegister(instr->length());
3074     Register index = ToRegister(instr->index());
3075     __ Dsubu(result, length, index);
3076     __ Daddu(result, result, 1);
3077     __ dsll(at, result, kPointerSizeLog2);
3078     __ Daddu(at, arguments, at);
3079     __ ld(result, MemOperand(at));
3080   }
3081 }
3082
3083
3084 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
3085   Register external_pointer = ToRegister(instr->elements());
3086   Register key = no_reg;
3087   ElementsKind elements_kind = instr->elements_kind();
3088   bool key_is_constant = instr->key()->IsConstantOperand();
3089   int constant_key = 0;
3090   if (key_is_constant) {
3091     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
3092     if (constant_key & 0xF0000000) {
3093       Abort(kArrayIndexConstantValueTooBig);
3094     }
3095   } else {
3096     key = ToRegister(instr->key());
3097   }
3098   int element_size_shift = ElementsKindToShiftSize(elements_kind);
3099   int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
3100       ? (element_size_shift - (kSmiTagSize + kSmiShiftSize))
3101       : element_size_shift;
3102   int base_offset = instr->base_offset();
3103
3104   if (elements_kind == FLOAT32_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) {
3105     FPURegister result = ToDoubleRegister(instr->result());
3106     if (key_is_constant) {
3107       __ Daddu(scratch0(), external_pointer,
3108           constant_key << element_size_shift);
3109     } else {
3110       if (shift_size < 0) {
3111          if (shift_size == -32) {
3112            __ dsra32(scratch0(), key, 0);
3113          } else {
3114            __ dsra(scratch0(), key, -shift_size);
3115          }
3116       } else {
3117         __ dsll(scratch0(), key, shift_size);
3118       }
3119       __ Daddu(scratch0(), scratch0(), external_pointer);
3120     }
3121     if (elements_kind == FLOAT32_ELEMENTS) {
3122       __ lwc1(result, MemOperand(scratch0(), base_offset));
3123       __ cvt_d_s(result, result);
3124     } else  {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
3125       __ ldc1(result, MemOperand(scratch0(), base_offset));
3126     }
3127   } else {
3128     Register result = ToRegister(instr->result());
3129     MemOperand mem_operand = PrepareKeyedOperand(
3130         key, external_pointer, key_is_constant, constant_key,
3131         element_size_shift, shift_size, base_offset);
3132     switch (elements_kind) {
3133       case INT8_ELEMENTS:
3134         __ lb(result, mem_operand);
3135         break;
3136       case UINT8_ELEMENTS:
3137       case UINT8_CLAMPED_ELEMENTS:
3138         __ lbu(result, mem_operand);
3139         break;
3140       case INT16_ELEMENTS:
3141         __ lh(result, mem_operand);
3142         break;
3143       case UINT16_ELEMENTS:
3144         __ lhu(result, mem_operand);
3145         break;
3146       case INT32_ELEMENTS:
3147         __ lw(result, mem_operand);
3148         break;
3149       case UINT32_ELEMENTS:
3150         __ lw(result, mem_operand);
3151         if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3152           DeoptimizeIf(Ugreater_equal, instr, Deoptimizer::kNegativeValue,
3153                        result, Operand(0x80000000));
3154         }
3155         break;
3156       case FLOAT32_ELEMENTS:
3157       case FLOAT64_ELEMENTS:
3158       case FAST_DOUBLE_ELEMENTS:
3159       case FAST_ELEMENTS:
3160       case FAST_SMI_ELEMENTS:
3161       case FAST_HOLEY_DOUBLE_ELEMENTS:
3162       case FAST_HOLEY_ELEMENTS:
3163       case FAST_HOLEY_SMI_ELEMENTS:
3164       case DICTIONARY_ELEMENTS:
3165       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
3166       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
3167         UNREACHABLE();
3168         break;
3169     }
3170   }
3171 }
3172
3173
3174 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
3175   Register elements = ToRegister(instr->elements());
3176   bool key_is_constant = instr->key()->IsConstantOperand();
3177   Register key = no_reg;
3178   DoubleRegister result = ToDoubleRegister(instr->result());
3179   Register scratch = scratch0();
3180
3181   int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
3182
3183   int base_offset = instr->base_offset();
3184   if (key_is_constant) {
3185     int constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
3186     if (constant_key & 0xF0000000) {
3187       Abort(kArrayIndexConstantValueTooBig);
3188     }
3189     base_offset += constant_key * kDoubleSize;
3190   }
3191   __ Daddu(scratch, elements, Operand(base_offset));
3192
3193   if (!key_is_constant) {
3194     key = ToRegister(instr->key());
3195     int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
3196         ? (element_size_shift - (kSmiTagSize + kSmiShiftSize))
3197         : element_size_shift;
3198     if (shift_size > 0) {
3199       __ dsll(at, key, shift_size);
3200     } else if (shift_size == -32) {
3201       __ dsra32(at, key, 0);
3202     } else {
3203       __ dsra(at, key, -shift_size);
3204     }
3205     __ Daddu(scratch, scratch, at);
3206   }
3207
3208   __ ldc1(result, MemOperand(scratch));
3209
3210   if (instr->hydrogen()->RequiresHoleCheck()) {
3211     __ FmoveHigh(scratch, result);
3212     DeoptimizeIf(eq, instr, Deoptimizer::kHole, scratch,
3213                  Operand(static_cast<int32_t>(kHoleNanUpper32)));
3214   }
3215 }
3216
3217
3218 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3219   HLoadKeyed* hinstr = instr->hydrogen();
3220   Register elements = ToRegister(instr->elements());
3221   Register result = ToRegister(instr->result());
3222   Register scratch = scratch0();
3223   Register store_base = scratch;
3224   int offset = instr->base_offset();
3225
3226   if (instr->key()->IsConstantOperand()) {
3227     LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
3228     offset += ToInteger32(const_operand) * kPointerSize;
3229     store_base = elements;
3230   } else {
3231     Register key = ToRegister(instr->key());
3232     // Even though the HLoadKeyed instruction forces the input
3233     // representation for the key to be an integer, the input gets replaced
3234     // during bound check elimination with the index argument to the bounds
3235     // check, which can be tagged, so that case must be handled here, too.
3236     if (instr->hydrogen()->key()->representation().IsSmi()) {
3237     __ SmiScale(scratch, key, kPointerSizeLog2);
3238     __ daddu(scratch, elements, scratch);
3239     } else {
3240       __ dsll(scratch, key, kPointerSizeLog2);
3241       __ daddu(scratch, elements, scratch);
3242     }
3243   }
3244
3245   Representation representation = hinstr->representation();
3246   if (representation.IsInteger32() && SmiValuesAre32Bits() &&
3247       hinstr->elements_kind() == FAST_SMI_ELEMENTS) {
3248     DCHECK(!hinstr->RequiresHoleCheck());
3249     if (FLAG_debug_code) {
3250       Register temp = scratch1();
3251       __ Load(temp, MemOperand(store_base, offset), Representation::Smi());
3252       __ AssertSmi(temp);
3253     }
3254
3255     // Read int value directly from upper half of the smi.
3256     STATIC_ASSERT(kSmiTag == 0);
3257     STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32);
3258     offset += kPointerSize / 2;
3259   }
3260
3261   __ Load(result, MemOperand(store_base, offset), representation);
3262
3263   // Check for the hole value.
3264   if (hinstr->RequiresHoleCheck()) {
3265     if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
3266       __ SmiTst(result, scratch);
3267       DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, scratch,
3268                    Operand(zero_reg));
3269     } else {
3270       __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
3271       DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(scratch));
3272     }
3273   } else if (instr->hydrogen()->hole_mode() == CONVERT_HOLE_TO_UNDEFINED) {
3274     DCHECK(instr->hydrogen()->elements_kind() == FAST_HOLEY_ELEMENTS);
3275     Label done;
3276     __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
3277     __ Branch(&done, ne, result, Operand(scratch));
3278     if (info()->IsStub()) {
3279       // A stub can safely convert the hole to undefined only if the array
3280       // protector cell contains (Smi) Isolate::kArrayProtectorValid. Otherwise
3281       // it needs to bail out.
3282       __ LoadRoot(result, Heap::kArrayProtectorRootIndex);
3283       // The comparison only needs LS bits of value, which is a smi.
3284       __ ld(result, FieldMemOperand(result, Cell::kValueOffset));
3285       DeoptimizeIf(ne, instr, Deoptimizer::kHole, result,
3286                    Operand(Smi::FromInt(Isolate::kArrayProtectorValid)));
3287     }
3288     __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
3289     __ bind(&done);
3290   }
3291 }
3292
3293
3294 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3295   if (instr->is_fixed_typed_array()) {
3296     DoLoadKeyedExternalArray(instr);
3297   } else if (instr->hydrogen()->representation().IsDouble()) {
3298     DoLoadKeyedFixedDoubleArray(instr);
3299   } else {
3300     DoLoadKeyedFixedArray(instr);
3301   }
3302 }
3303
3304
3305 MemOperand LCodeGen::PrepareKeyedOperand(Register key,
3306                                          Register base,
3307                                          bool key_is_constant,
3308                                          int constant_key,
3309                                          int element_size,
3310                                          int shift_size,
3311                                          int base_offset) {
3312   if (key_is_constant) {
3313     return MemOperand(base, (constant_key << element_size) + base_offset);
3314   }
3315
3316   if (base_offset == 0) {
3317     if (shift_size >= 0) {
3318       __ dsll(scratch0(), key, shift_size);
3319       __ Daddu(scratch0(), base, scratch0());
3320       return MemOperand(scratch0());
3321     } else {
3322       if (shift_size == -32) {
3323         __ dsra32(scratch0(), key, 0);
3324       } else {
3325         __ dsra(scratch0(), key, -shift_size);
3326       }
3327       __ Daddu(scratch0(), base, scratch0());
3328       return MemOperand(scratch0());
3329     }
3330   }
3331
3332   if (shift_size >= 0) {
3333     __ dsll(scratch0(), key, shift_size);
3334     __ Daddu(scratch0(), base, scratch0());
3335     return MemOperand(scratch0(), base_offset);
3336   } else {
3337     if (shift_size == -32) {
3338        __ dsra32(scratch0(), key, 0);
3339     } else {
3340       __ dsra(scratch0(), key, -shift_size);
3341     }
3342     __ Daddu(scratch0(), base, scratch0());
3343     return MemOperand(scratch0(), base_offset);
3344   }
3345 }
3346
3347
3348 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
3349   DCHECK(ToRegister(instr->context()).is(cp));
3350   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
3351   DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
3352
3353   if (instr->hydrogen()->HasVectorAndSlot()) {
3354     EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
3355   }
3356
3357   Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
3358                         isolate(), instr->hydrogen()->language_mode(),
3359                         instr->hydrogen()->initialization_state()).code();
3360   CallCode(ic, RelocInfo::CODE_TARGET, instr);
3361 }
3362
3363
3364 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
3365   Register scratch = scratch0();
3366   Register temp = scratch1();
3367   Register result = ToRegister(instr->result());
3368
3369   if (instr->hydrogen()->from_inlined()) {
3370     __ Dsubu(result, sp, 2 * kPointerSize);
3371   } else {
3372     // Check if the calling frame is an arguments adaptor frame.
3373     Label done, adapted;
3374     __ ld(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3375     __ ld(result, MemOperand(scratch, StandardFrameConstants::kContextOffset));
3376     __ Xor(temp, result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3377
3378     // Result is the frame pointer for the frame if not adapted and for the real
3379     // frame below the adaptor frame if adapted.
3380     __ Movn(result, fp, temp);  // Move only if temp is not equal to zero (ne).
3381     __ Movz(result, scratch, temp);  // Move only if temp is equal to zero (eq).
3382   }
3383 }
3384
3385
3386 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
3387   Register elem = ToRegister(instr->elements());
3388   Register result = ToRegister(instr->result());
3389
3390   Label done;
3391
3392   // If no arguments adaptor frame the number of arguments is fixed.
3393   __ Daddu(result, zero_reg, Operand(scope()->num_parameters()));
3394   __ Branch(&done, eq, fp, Operand(elem));
3395
3396   // Arguments adaptor frame present. Get argument length from there.
3397   __ ld(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3398   __ ld(result,
3399         MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset));
3400   __ SmiUntag(result);
3401
3402   // Argument length is in result register.
3403   __ bind(&done);
3404 }
3405
3406
3407 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
3408   Register receiver = ToRegister(instr->receiver());
3409   Register function = ToRegister(instr->function());
3410   Register result = ToRegister(instr->result());
3411   Register scratch = scratch0();
3412
3413   // If the receiver is null or undefined, we have to pass the global
3414   // object as a receiver to normal functions. Values have to be
3415   // passed unchanged to builtins and strict-mode functions.
3416   Label global_object, result_in_receiver;
3417
3418   if (!instr->hydrogen()->known_function()) {
3419     // Do not transform the receiver to object for strict mode functions.
3420     __ ld(scratch,
3421            FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
3422
3423     // Do not transform the receiver to object for builtins.
3424     int32_t strict_mode_function_mask =
3425         1 <<  SharedFunctionInfo::kStrictModeBitWithinByte;
3426     int32_t native_mask = 1 << SharedFunctionInfo::kNativeBitWithinByte;
3427
3428     __ lbu(at,
3429            FieldMemOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset));
3430     __ And(at, at, Operand(strict_mode_function_mask));
3431     __ Branch(&result_in_receiver, ne, at, Operand(zero_reg));
3432     __ lbu(at,
3433            FieldMemOperand(scratch, SharedFunctionInfo::kNativeByteOffset));
3434     __ And(at, at, Operand(native_mask));
3435     __ Branch(&result_in_receiver, ne, at, Operand(zero_reg));
3436   }
3437
3438   // Normal function. Replace undefined or null with global receiver.
3439   __ LoadRoot(scratch, Heap::kNullValueRootIndex);
3440   __ Branch(&global_object, eq, receiver, Operand(scratch));
3441   __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
3442   __ Branch(&global_object, eq, receiver, Operand(scratch));
3443
3444   // Deoptimize if the receiver is not a JS object.
3445   __ SmiTst(receiver, scratch);
3446   DeoptimizeIf(eq, instr, Deoptimizer::kSmi, scratch, Operand(zero_reg));
3447
3448   __ GetObjectType(receiver, scratch, scratch);
3449   DeoptimizeIf(lt, instr, Deoptimizer::kNotAJavaScriptObject, scratch,
3450                Operand(FIRST_SPEC_OBJECT_TYPE));
3451   __ Branch(&result_in_receiver);
3452
3453   __ bind(&global_object);
3454   __ ld(result, FieldMemOperand(function, JSFunction::kContextOffset));
3455   __ ld(result,
3456         ContextOperand(result, Context::GLOBAL_OBJECT_INDEX));
3457   __ ld(result,
3458         FieldMemOperand(result, GlobalObject::kGlobalProxyOffset));
3459
3460   if (result.is(receiver)) {
3461     __ bind(&result_in_receiver);
3462   } else {
3463     Label result_ok;
3464     __ Branch(&result_ok);
3465     __ bind(&result_in_receiver);
3466     __ mov(result, receiver);
3467     __ bind(&result_ok);
3468   }
3469 }
3470
3471
3472 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3473   Register receiver = ToRegister(instr->receiver());
3474   Register function = ToRegister(instr->function());
3475   Register length = ToRegister(instr->length());
3476   Register elements = ToRegister(instr->elements());
3477   Register scratch = scratch0();
3478   DCHECK(receiver.is(a0));  // Used for parameter count.
3479   DCHECK(function.is(a1));  // Required by InvokeFunction.
3480   DCHECK(ToRegister(instr->result()).is(v0));
3481
3482   // Copy the arguments to this function possibly from the
3483   // adaptor frame below it.
3484   const uint32_t kArgumentsLimit = 1 * KB;
3485   DeoptimizeIf(hi, instr, Deoptimizer::kTooManyArguments, length,
3486                Operand(kArgumentsLimit));
3487
3488   // Push the receiver and use the register to keep the original
3489   // number of arguments.
3490   __ push(receiver);
3491   __ Move(receiver, length);
3492   // The arguments are at a one pointer size offset from elements.
3493   __ Daddu(elements, elements, Operand(1 * kPointerSize));
3494
3495   // Loop through the arguments pushing them onto the execution
3496   // stack.
3497   Label invoke, loop;
3498   // length is a small non-negative integer, due to the test above.
3499   __ Branch(USE_DELAY_SLOT, &invoke, eq, length, Operand(zero_reg));
3500   __ dsll(scratch, length, kPointerSizeLog2);
3501   __ bind(&loop);
3502   __ Daddu(scratch, elements, scratch);
3503   __ ld(scratch, MemOperand(scratch));
3504   __ push(scratch);
3505   __ Dsubu(length, length, Operand(1));
3506   __ Branch(USE_DELAY_SLOT, &loop, ne, length, Operand(zero_reg));
3507   __ dsll(scratch, length, kPointerSizeLog2);
3508
3509   __ bind(&invoke);
3510   DCHECK(instr->HasPointerMap());
3511   LPointerMap* pointers = instr->pointer_map();
3512   SafepointGenerator safepoint_generator(
3513       this, pointers, Safepoint::kLazyDeopt);
3514   // The number of arguments is stored in receiver which is a0, as expected
3515   // by InvokeFunction.
3516   ParameterCount actual(receiver);
3517   __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator);
3518 }
3519
3520
3521 void LCodeGen::DoPushArgument(LPushArgument* instr) {
3522   LOperand* argument = instr->value();
3523   if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
3524     Abort(kDoPushArgumentNotImplementedForDoubleType);
3525   } else {
3526     Register argument_reg = EmitLoadRegister(argument, at);
3527     __ push(argument_reg);
3528   }
3529 }
3530
3531
3532 void LCodeGen::DoDrop(LDrop* instr) {
3533   __ Drop(instr->count());
3534 }
3535
3536
3537 void LCodeGen::DoThisFunction(LThisFunction* instr) {
3538   Register result = ToRegister(instr->result());
3539   __ ld(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
3540 }
3541
3542
3543 void LCodeGen::DoContext(LContext* instr) {
3544   // If there is a non-return use, the context must be moved to a register.
3545   Register result = ToRegister(instr->result());
3546   if (info()->IsOptimizing()) {
3547     __ ld(result, MemOperand(fp, StandardFrameConstants::kContextOffset));
3548   } else {
3549     // If there is no frame, the context must be in cp.
3550     DCHECK(result.is(cp));
3551   }
3552 }
3553
3554
3555 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
3556   DCHECK(ToRegister(instr->context()).is(cp));
3557   __ li(scratch0(), instr->hydrogen()->pairs());
3558   __ li(scratch1(), Operand(Smi::FromInt(instr->hydrogen()->flags())));
3559   __ Push(scratch0(), scratch1());
3560   CallRuntime(Runtime::kDeclareGlobals, 2, instr);
3561 }
3562
3563
3564 void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
3565                                  int formal_parameter_count, int arity,
3566                                  LInstruction* instr) {
3567   bool dont_adapt_arguments =
3568       formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3569   bool can_invoke_directly =
3570       dont_adapt_arguments || formal_parameter_count == arity;
3571
3572   Register function_reg = a1;
3573   LPointerMap* pointers = instr->pointer_map();
3574
3575   if (can_invoke_directly) {
3576     // Change context.
3577     __ ld(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset));
3578
3579     // Always initialize a0 to the number of actual arguments.
3580     __ li(a0, Operand(arity));
3581
3582     // Invoke function.
3583     __ ld(at, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset));
3584     __ Call(at);
3585
3586     // Set up deoptimization.
3587     RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3588   } else {
3589     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3590     ParameterCount count(arity);
3591     ParameterCount expected(formal_parameter_count);
3592     __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator);
3593   }
3594 }
3595
3596
3597 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3598   DCHECK(instr->context() != NULL);
3599   DCHECK(ToRegister(instr->context()).is(cp));
3600   Register input = ToRegister(instr->value());
3601   Register result = ToRegister(instr->result());
3602   Register scratch = scratch0();
3603
3604   // Deoptimize if not a heap number.
3605   __ ld(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
3606   __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
3607   DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch, Operand(at));
3608
3609   Label done;
3610   Register exponent = scratch0();
3611   scratch = no_reg;
3612   __ lwu(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
3613   // Check the sign of the argument. If the argument is positive, just
3614   // return it.
3615   __ Move(result, input);
3616   __ And(at, exponent, Operand(HeapNumber::kSignMask));
3617   __ Branch(&done, eq, at, Operand(zero_reg));
3618
3619   // Input is negative. Reverse its sign.
3620   // Preserve the value of all registers.
3621   {
3622     PushSafepointRegistersScope scope(this);
3623
3624     // Registers were saved at the safepoint, so we can use
3625     // many scratch registers.
3626     Register tmp1 = input.is(a1) ? a0 : a1;
3627     Register tmp2 = input.is(a2) ? a0 : a2;
3628     Register tmp3 = input.is(a3) ? a0 : a3;
3629     Register tmp4 = input.is(a4) ? a0 : a4;
3630
3631     // exponent: floating point exponent value.
3632
3633     Label allocated, slow;
3634     __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex);
3635     __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow);
3636     __ Branch(&allocated);
3637
3638     // Slow case: Call the runtime system to do the number allocation.
3639     __ bind(&slow);
3640
3641     CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr,
3642                             instr->context());
3643     // Set the pointer to the new heap number in tmp.
3644     if (!tmp1.is(v0))
3645       __ mov(tmp1, v0);
3646     // Restore input_reg after call to runtime.
3647     __ LoadFromSafepointRegisterSlot(input, input);
3648     __ lwu(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
3649
3650     __ bind(&allocated);
3651     // exponent: floating point exponent value.
3652     // tmp1: allocated heap number.
3653     __ And(exponent, exponent, Operand(~HeapNumber::kSignMask));
3654     __ sw(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
3655     __ lwu(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
3656     __ sw(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
3657
3658     __ StoreToSafepointRegisterSlot(tmp1, result);
3659   }
3660
3661   __ bind(&done);
3662 }
3663
3664
3665 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3666   Register input = ToRegister(instr->value());
3667   Register result = ToRegister(instr->result());
3668   Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
3669   Label done;
3670   __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg));
3671   __ mov(result, input);
3672   __ subu(result, zero_reg, input);
3673   // Overflow if result is still negative, i.e. 0x80000000.
3674   DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, result, Operand(zero_reg));
3675   __ bind(&done);
3676 }
3677
3678
3679 void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) {
3680   Register input = ToRegister(instr->value());
3681   Register result = ToRegister(instr->result());
3682   Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
3683   Label done;
3684   __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg));
3685   __ mov(result, input);
3686   __ dsubu(result, zero_reg, input);
3687   // Overflow if result is still negative, i.e. 0x80000000 00000000.
3688   DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, result, Operand(zero_reg));
3689   __ bind(&done);
3690 }
3691
3692
3693 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3694   // Class for deferred case.
3695   class DeferredMathAbsTaggedHeapNumber final : public LDeferredCode {
3696    public:
3697     DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr)
3698         : LDeferredCode(codegen), instr_(instr) { }
3699     void Generate() override {
3700       codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
3701     }
3702     LInstruction* instr() override { return instr_; }
3703
3704    private:
3705     LMathAbs* instr_;
3706   };
3707
3708   Representation r = instr->hydrogen()->value()->representation();
3709   if (r.IsDouble()) {
3710     FPURegister input = ToDoubleRegister(instr->value());
3711     FPURegister result = ToDoubleRegister(instr->result());
3712     __ abs_d(result, input);
3713   } else if (r.IsInteger32()) {
3714     EmitIntegerMathAbs(instr);
3715   } else if (r.IsSmi()) {
3716     EmitSmiMathAbs(instr);
3717   } else {
3718     // Representation is tagged.
3719     DeferredMathAbsTaggedHeapNumber* deferred =
3720         new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr);
3721     Register input = ToRegister(instr->value());
3722     // Smi check.
3723     __ JumpIfNotSmi(input, deferred->entry());
3724     // If smi, handle it directly.
3725     EmitSmiMathAbs(instr);
3726     __ bind(deferred->exit());
3727   }
3728 }
3729
3730
3731 void LCodeGen::DoMathFloor(LMathFloor* instr) {
3732   DoubleRegister input = ToDoubleRegister(instr->value());
3733   Register result = ToRegister(instr->result());
3734   Register scratch1 = scratch0();
3735   Register except_flag = ToRegister(instr->temp());
3736
3737   __ EmitFPUTruncate(kRoundToMinusInf,
3738                      result,
3739                      input,
3740                      scratch1,
3741                      double_scratch0(),
3742                      except_flag);
3743
3744   // Deopt if the operation did not succeed.
3745   DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
3746                Operand(zero_reg));
3747
3748   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3749     // Test for -0.
3750     Label done;
3751     __ Branch(&done, ne, result, Operand(zero_reg));
3752     __ mfhc1(scratch1, input);  // Get exponent/sign bits.
3753     __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
3754     DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
3755                  Operand(zero_reg));
3756     __ bind(&done);
3757   }
3758 }
3759
3760
3761 void LCodeGen::DoMathRound(LMathRound* instr) {
3762   DoubleRegister input = ToDoubleRegister(instr->value());
3763   Register result = ToRegister(instr->result());
3764   DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp());
3765   Register scratch = scratch0();
3766   Label done, check_sign_on_zero;
3767
3768   // Extract exponent bits.
3769   __ mfhc1(result, input);
3770   __ Ext(scratch,
3771          result,
3772          HeapNumber::kExponentShift,
3773          HeapNumber::kExponentBits);
3774
3775   // If the number is in ]-0.5, +0.5[, the result is +/- 0.
3776   Label skip1;
3777   __ Branch(&skip1, gt, scratch, Operand(HeapNumber::kExponentBias - 2));
3778   __ mov(result, zero_reg);
3779   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3780     __ Branch(&check_sign_on_zero);
3781   } else {
3782     __ Branch(&done);
3783   }
3784   __ bind(&skip1);
3785
3786   // The following conversion will not work with numbers
3787   // outside of ]-2^32, 2^32[.
3788   DeoptimizeIf(ge, instr, Deoptimizer::kOverflow, scratch,
3789                Operand(HeapNumber::kExponentBias + 32));
3790
3791   // Save the original sign for later comparison.
3792   __ And(scratch, result, Operand(HeapNumber::kSignMask));
3793
3794   __ Move(double_scratch0(), 0.5);
3795   __ add_d(double_scratch0(), input, double_scratch0());
3796
3797   // Check sign of the result: if the sign changed, the input
3798   // value was in ]0.5, 0[ and the result should be -0.
3799   __ mfhc1(result, double_scratch0());
3800   // mfhc1 sign-extends, clear the upper bits.
3801   __ dsll32(result, result, 0);
3802   __ dsrl32(result, result, 0);
3803   __ Xor(result, result, Operand(scratch));
3804   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3805     // ARM uses 'mi' here, which is 'lt'
3806     DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, result, Operand(zero_reg));
3807   } else {
3808     Label skip2;
3809     // ARM uses 'mi' here, which is 'lt'
3810     // Negating it results in 'ge'
3811     __ Branch(&skip2, ge, result, Operand(zero_reg));
3812     __ mov(result, zero_reg);
3813     __ Branch(&done);
3814     __ bind(&skip2);
3815   }
3816
3817   Register except_flag = scratch;
3818   __ EmitFPUTruncate(kRoundToMinusInf,
3819                      result,
3820                      double_scratch0(),
3821                      at,
3822                      double_scratch1,
3823                      except_flag);
3824
3825   DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
3826                Operand(zero_reg));
3827
3828   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3829     // Test for -0.
3830     __ Branch(&done, ne, result, Operand(zero_reg));
3831     __ bind(&check_sign_on_zero);
3832     __ mfhc1(scratch, input);  // Get exponent/sign bits.
3833     __ And(scratch, scratch, Operand(HeapNumber::kSignMask));
3834     DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch,
3835                  Operand(zero_reg));
3836   }
3837   __ bind(&done);
3838 }
3839
3840
3841 void LCodeGen::DoMathFround(LMathFround* instr) {
3842   DoubleRegister input = ToDoubleRegister(instr->value());
3843   DoubleRegister result = ToDoubleRegister(instr->result());
3844   __ cvt_s_d(result, input);
3845   __ cvt_d_s(result, result);
3846 }
3847
3848
3849 void LCodeGen::DoMathSqrt(LMathSqrt* instr) {
3850   DoubleRegister input = ToDoubleRegister(instr->value());
3851   DoubleRegister result = ToDoubleRegister(instr->result());
3852   __ sqrt_d(result, input);
3853 }
3854
3855
3856 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
3857   DoubleRegister input = ToDoubleRegister(instr->value());
3858   DoubleRegister result = ToDoubleRegister(instr->result());
3859   DoubleRegister temp = ToDoubleRegister(instr->temp());
3860
3861   DCHECK(!input.is(result));
3862
3863   // Note that according to ECMA-262 15.8.2.13:
3864   // Math.pow(-Infinity, 0.5) == Infinity
3865   // Math.sqrt(-Infinity) == NaN
3866   Label done;
3867   __ Move(temp, static_cast<double>(-V8_INFINITY));
3868   __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, temp, input);
3869   // Set up Infinity in the delay slot.
3870   // result is overwritten if the branch is not taken.
3871   __ neg_d(result, temp);
3872
3873   // Add +0 to convert -0 to +0.
3874   __ add_d(result, input, kDoubleRegZero);
3875   __ sqrt_d(result, result);
3876   __ bind(&done);
3877 }
3878
3879
3880 void LCodeGen::DoPower(LPower* instr) {
3881   Representation exponent_type = instr->hydrogen()->right()->representation();
3882   // Having marked this as a call, we can use any registers.
3883   // Just make sure that the input/output registers are the expected ones.
3884   Register tagged_exponent = MathPowTaggedDescriptor::exponent();
3885   DCHECK(!instr->right()->IsDoubleRegister() ||
3886          ToDoubleRegister(instr->right()).is(f4));
3887   DCHECK(!instr->right()->IsRegister() ||
3888          ToRegister(instr->right()).is(tagged_exponent));
3889   DCHECK(ToDoubleRegister(instr->left()).is(f2));
3890   DCHECK(ToDoubleRegister(instr->result()).is(f0));
3891
3892   if (exponent_type.IsSmi()) {
3893     MathPowStub stub(isolate(), MathPowStub::TAGGED);
3894     __ CallStub(&stub);
3895   } else if (exponent_type.IsTagged()) {
3896     Label no_deopt;
3897     __ JumpIfSmi(tagged_exponent, &no_deopt);
3898     DCHECK(!a7.is(tagged_exponent));
3899     __ lw(a7, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset));
3900     __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
3901     DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, a7, Operand(at));
3902     __ bind(&no_deopt);
3903     MathPowStub stub(isolate(), MathPowStub::TAGGED);
3904     __ CallStub(&stub);
3905   } else if (exponent_type.IsInteger32()) {
3906     MathPowStub stub(isolate(), MathPowStub::INTEGER);
3907     __ CallStub(&stub);
3908   } else {
3909     DCHECK(exponent_type.IsDouble());
3910     MathPowStub stub(isolate(), MathPowStub::DOUBLE);
3911     __ CallStub(&stub);
3912   }
3913 }
3914
3915
3916 void LCodeGen::DoMathExp(LMathExp* instr) {
3917   DoubleRegister input = ToDoubleRegister(instr->value());
3918   DoubleRegister result = ToDoubleRegister(instr->result());
3919   DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
3920   DoubleRegister double_scratch2 = double_scratch0();
3921   Register temp1 = ToRegister(instr->temp1());
3922   Register temp2 = ToRegister(instr->temp2());
3923
3924   MathExpGenerator::EmitMathExp(
3925       masm(), input, result, double_scratch1, double_scratch2,
3926       temp1, temp2, scratch0());
3927 }
3928
3929
3930 void LCodeGen::DoMathLog(LMathLog* instr) {
3931   __ PrepareCallCFunction(0, 1, scratch0());
3932   __ MovToFloatParameter(ToDoubleRegister(instr->value()));
3933   __ CallCFunction(ExternalReference::math_log_double_function(isolate()),
3934                    0, 1);
3935   __ MovFromFloatResult(ToDoubleRegister(instr->result()));
3936 }
3937
3938
3939 void LCodeGen::DoMathClz32(LMathClz32* instr) {
3940   Register input = ToRegister(instr->value());
3941   Register result = ToRegister(instr->result());
3942   __ Clz(result, input);
3943 }
3944
3945
3946 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
3947   DCHECK(ToRegister(instr->context()).is(cp));
3948   DCHECK(ToRegister(instr->function()).is(a1));
3949   DCHECK(instr->HasPointerMap());
3950
3951   Handle<JSFunction> known_function = instr->hydrogen()->known_function();
3952   if (known_function.is_null()) {
3953     LPointerMap* pointers = instr->pointer_map();
3954     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3955     ParameterCount count(instr->arity());
3956     __ InvokeFunction(a1, count, CALL_FUNCTION, generator);
3957   } else {
3958     CallKnownFunction(known_function,
3959                       instr->hydrogen()->formal_parameter_count(),
3960                       instr->arity(), instr);
3961   }
3962 }
3963
3964
3965 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
3966   DCHECK(ToRegister(instr->result()).is(v0));
3967
3968   if (instr->hydrogen()->IsTailCall()) {
3969     if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL);
3970
3971     if (instr->target()->IsConstantOperand()) {
3972       LConstantOperand* target = LConstantOperand::cast(instr->target());
3973       Handle<Code> code = Handle<Code>::cast(ToHandle(target));
3974       __ Jump(code, RelocInfo::CODE_TARGET);
3975     } else {
3976       DCHECK(instr->target()->IsRegister());
3977       Register target = ToRegister(instr->target());
3978       __ Daddu(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
3979       __ Jump(target);
3980     }
3981   } else {
3982     LPointerMap* pointers = instr->pointer_map();
3983     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3984
3985     if (instr->target()->IsConstantOperand()) {
3986       LConstantOperand* target = LConstantOperand::cast(instr->target());
3987       Handle<Code> code = Handle<Code>::cast(ToHandle(target));
3988       generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET));
3989       __ Call(code, RelocInfo::CODE_TARGET);
3990     } else {
3991       DCHECK(instr->target()->IsRegister());
3992       Register target = ToRegister(instr->target());
3993       generator.BeforeCall(__ CallSize(target));
3994       __ Daddu(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
3995       __ Call(target);
3996     }
3997     generator.AfterCall();
3998   }
3999 }
4000
4001
4002 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) {
4003   DCHECK(ToRegister(instr->function()).is(a1));
4004   DCHECK(ToRegister(instr->result()).is(v0));
4005
4006   __ li(a0, Operand(instr->arity()));
4007
4008   // Change context.
4009   __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
4010
4011   // Load the code entry address
4012   __ ld(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
4013   __ Call(at);
4014
4015   RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
4016 }
4017
4018
4019 void LCodeGen::DoCallFunction(LCallFunction* instr) {
4020   DCHECK(ToRegister(instr->context()).is(cp));
4021   DCHECK(ToRegister(instr->function()).is(a1));
4022   DCHECK(ToRegister(instr->result()).is(v0));
4023
4024   int arity = instr->arity();
4025   CallFunctionFlags flags = instr->hydrogen()->function_flags();
4026   if (instr->hydrogen()->HasVectorAndSlot()) {
4027     Register slot_register = ToRegister(instr->temp_slot());
4028     Register vector_register = ToRegister(instr->temp_vector());
4029     DCHECK(slot_register.is(a3));
4030     DCHECK(vector_register.is(a2));
4031
4032     AllowDeferredHandleDereference vector_structure_check;
4033     Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector();
4034     int index = vector->GetIndex(instr->hydrogen()->slot());
4035
4036     __ li(vector_register, vector);
4037     __ li(slot_register, Operand(Smi::FromInt(index)));
4038
4039     CallICState::CallType call_type =
4040         (flags & CALL_AS_METHOD) ? CallICState::METHOD : CallICState::FUNCTION;
4041
4042     Handle<Code> ic =
4043         CodeFactory::CallICInOptimizedCode(isolate(), arity, call_type).code();
4044     CallCode(ic, RelocInfo::CODE_TARGET, instr);
4045   } else {
4046     CallFunctionStub stub(isolate(), arity, flags);
4047     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4048   }
4049 }
4050
4051
4052 void LCodeGen::DoCallNew(LCallNew* instr) {
4053   DCHECK(ToRegister(instr->context()).is(cp));
4054   DCHECK(ToRegister(instr->constructor()).is(a1));
4055   DCHECK(ToRegister(instr->result()).is(v0));
4056
4057   __ li(a0, Operand(instr->arity()));
4058   // No cell in a2 for construct type feedback in optimized code
4059   __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
4060   CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
4061   CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4062 }
4063
4064
4065 void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
4066   DCHECK(ToRegister(instr->context()).is(cp));
4067   DCHECK(ToRegister(instr->constructor()).is(a1));
4068   DCHECK(ToRegister(instr->result()).is(v0));
4069
4070   __ li(a0, Operand(instr->arity()));
4071   if (instr->arity() == 1) {
4072     // We only need the allocation site for the case we have a length argument.
4073     // The case may bail out to the runtime, which will determine the correct
4074     // elements kind with the site.
4075     __ li(a2, instr->hydrogen()->site());
4076   } else {
4077     __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
4078   }
4079   ElementsKind kind = instr->hydrogen()->elements_kind();
4080   AllocationSiteOverrideMode override_mode =
4081       (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
4082           ? DISABLE_ALLOCATION_SITES
4083           : DONT_OVERRIDE;
4084
4085   if (instr->arity() == 0) {
4086     ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode);
4087     CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4088   } else if (instr->arity() == 1) {
4089     Label done;
4090     if (IsFastPackedElementsKind(kind)) {
4091       Label packed_case;
4092       // We might need a change here,
4093       // look at the first argument.
4094       __ ld(a5, MemOperand(sp, 0));
4095       __ Branch(&packed_case, eq, a5, Operand(zero_reg));
4096
4097       ElementsKind holey_kind = GetHoleyElementsKind(kind);
4098       ArraySingleArgumentConstructorStub stub(isolate(),
4099                                               holey_kind,
4100                                               override_mode);
4101       CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4102       __ jmp(&done);
4103       __ bind(&packed_case);
4104     }
4105
4106     ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode);
4107     CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4108     __ bind(&done);
4109   } else {
4110     ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
4111     CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4112   }
4113 }
4114
4115
4116 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
4117   CallRuntime(instr->function(), instr->arity(), instr);
4118 }
4119
4120
4121 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
4122   Register function = ToRegister(instr->function());
4123   Register code_object = ToRegister(instr->code_object());
4124   __ Daddu(code_object, code_object,
4125           Operand(Code::kHeaderSize - kHeapObjectTag));
4126   __ sd(code_object,
4127         FieldMemOperand(function, JSFunction::kCodeEntryOffset));
4128 }
4129
4130
4131 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
4132   Register result = ToRegister(instr->result());
4133   Register base = ToRegister(instr->base_object());
4134   if (instr->offset()->IsConstantOperand()) {
4135     LConstantOperand* offset = LConstantOperand::cast(instr->offset());
4136     __ Daddu(result, base, Operand(ToInteger32(offset)));
4137   } else {
4138     Register offset = ToRegister(instr->offset());
4139     __ Daddu(result, base, offset);
4140   }
4141 }
4142
4143
4144 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
4145   Representation representation = instr->representation();
4146
4147   Register object = ToRegister(instr->object());
4148   Register scratch2 = scratch1();
4149   Register scratch1 = scratch0();
4150
4151   HObjectAccess access = instr->hydrogen()->access();
4152   int offset = access.offset();
4153   if (access.IsExternalMemory()) {
4154     Register value = ToRegister(instr->value());
4155     MemOperand operand = MemOperand(object, offset);
4156     __ Store(value, operand, representation);
4157     return;
4158   }
4159
4160   __ AssertNotSmi(object);
4161
4162   DCHECK(!representation.IsSmi() ||
4163          !instr->value()->IsConstantOperand() ||
4164          IsSmi(LConstantOperand::cast(instr->value())));
4165   if (!FLAG_unbox_double_fields && representation.IsDouble()) {
4166     DCHECK(access.IsInobject());
4167     DCHECK(!instr->hydrogen()->has_transition());
4168     DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4169     DoubleRegister value = ToDoubleRegister(instr->value());
4170     __ sdc1(value, FieldMemOperand(object, offset));
4171     return;
4172   }
4173
4174   if (instr->hydrogen()->has_transition()) {
4175     Handle<Map> transition = instr->hydrogen()->transition_map();
4176     AddDeprecationDependency(transition);
4177     __ li(scratch1, Operand(transition));
4178     __ sd(scratch1, FieldMemOperand(object, HeapObject::kMapOffset));
4179     if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
4180       Register temp = ToRegister(instr->temp());
4181       // Update the write barrier for the map field.
4182       __ RecordWriteForMap(object,
4183                            scratch1,
4184                            temp,
4185                            GetRAState(),
4186                            kSaveFPRegs);
4187     }
4188   }
4189
4190   // Do the store.
4191   Register destination = object;
4192   if (!access.IsInobject()) {
4193        destination = scratch1;
4194     __ ld(destination, FieldMemOperand(object, JSObject::kPropertiesOffset));
4195   }
4196
4197   if (representation.IsSmi() && SmiValuesAre32Bits() &&
4198       instr->hydrogen()->value()->representation().IsInteger32()) {
4199     DCHECK(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY);
4200     if (FLAG_debug_code) {
4201       __ Load(scratch2, FieldMemOperand(destination, offset), representation);
4202       __ AssertSmi(scratch2);
4203     }
4204     // Store int value directly to upper half of the smi.
4205     offset += kPointerSize / 2;
4206     representation = Representation::Integer32();
4207   }
4208   MemOperand operand = FieldMemOperand(destination, offset);
4209
4210   if (FLAG_unbox_double_fields && representation.IsDouble()) {
4211     DCHECK(access.IsInobject());
4212     DoubleRegister value = ToDoubleRegister(instr->value());
4213     __ sdc1(value, operand);
4214   } else {
4215     DCHECK(instr->value()->IsRegister());
4216     Register value = ToRegister(instr->value());
4217     __ Store(value, operand, representation);
4218   }
4219
4220   if (instr->hydrogen()->NeedsWriteBarrier()) {
4221     // Update the write barrier for the object for in-object properties.
4222     Register value = ToRegister(instr->value());
4223     __ RecordWriteField(destination,
4224                         offset,
4225                         value,
4226                         scratch2,
4227                         GetRAState(),
4228                         kSaveFPRegs,
4229                         EMIT_REMEMBERED_SET,
4230                         instr->hydrogen()->SmiCheckForWriteBarrier(),
4231                         instr->hydrogen()->PointersToHereCheckForValue());
4232   }
4233 }
4234
4235
4236 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
4237   DCHECK(ToRegister(instr->context()).is(cp));
4238   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
4239   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
4240
4241   if (instr->hydrogen()->HasVectorAndSlot()) {
4242     EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
4243   }
4244
4245   __ li(StoreDescriptor::NameRegister(), Operand(instr->name()));
4246   Handle<Code> ic = CodeFactory::StoreICInOptimizedCode(
4247                         isolate(), instr->language_mode(),
4248                         instr->hydrogen()->initialization_state()).code();
4249   CallCode(ic, RelocInfo::CODE_TARGET, instr);
4250 }
4251
4252
4253 void LCodeGen::DoStoreGlobalViaContext(LStoreGlobalViaContext* instr) {
4254   DCHECK(ToRegister(instr->context()).is(cp));
4255   DCHECK(ToRegister(instr->value())
4256              .is(StoreGlobalViaContextDescriptor::ValueRegister()));
4257
4258   int const slot = instr->slot_index();
4259   int const depth = instr->depth();
4260   if (depth <= StoreGlobalViaContextStub::kMaximumDepth) {
4261     __ li(StoreGlobalViaContextDescriptor::SlotRegister(), Operand(slot));
4262     Handle<Code> stub = CodeFactory::StoreGlobalViaContext(
4263                             isolate(), depth, instr->language_mode())
4264                             .code();
4265     CallCode(stub, RelocInfo::CODE_TARGET, instr);
4266   } else {
4267     __ Push(Smi::FromInt(slot));
4268     __ Push(StoreGlobalViaContextDescriptor::ValueRegister());
4269     __ CallRuntime(is_strict(language_mode())
4270                        ? Runtime::kStoreGlobalViaContext_Strict
4271                        : Runtime::kStoreGlobalViaContext_Sloppy,
4272                    2);
4273   }
4274 }
4275
4276
4277 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
4278   Condition cc = instr->hydrogen()->allow_equality() ? hi : hs;
4279   Operand operand((int64_t)0);
4280   Register reg;
4281   if (instr->index()->IsConstantOperand()) {
4282     operand = ToOperand(instr->index());
4283     reg = ToRegister(instr->length());
4284     cc = CommuteCondition(cc);
4285   } else {
4286     reg = ToRegister(instr->index());
4287     operand = ToOperand(instr->length());
4288   }
4289   if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4290     Label done;
4291     __ Branch(&done, NegateCondition(cc), reg, operand);
4292     __ stop("eliminated bounds check failed");
4293     __ bind(&done);
4294   } else {
4295     DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds, reg, operand);
4296   }
4297 }
4298
4299
4300 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4301   Register external_pointer = ToRegister(instr->elements());
4302   Register key = no_reg;
4303   ElementsKind elements_kind = instr->elements_kind();
4304   bool key_is_constant = instr->key()->IsConstantOperand();
4305   int constant_key = 0;
4306   if (key_is_constant) {
4307     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
4308     if (constant_key & 0xF0000000) {
4309       Abort(kArrayIndexConstantValueTooBig);
4310     }
4311   } else {
4312     key = ToRegister(instr->key());
4313   }
4314   int element_size_shift = ElementsKindToShiftSize(elements_kind);
4315   int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
4316       ? (element_size_shift - (kSmiTagSize + kSmiShiftSize))
4317       : element_size_shift;
4318   int base_offset = instr->base_offset();
4319
4320   if (elements_kind == FLOAT32_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) {
4321     Register address = scratch0();
4322     FPURegister value(ToDoubleRegister(instr->value()));
4323     if (key_is_constant) {
4324       if (constant_key != 0) {
4325         __ Daddu(address, external_pointer,
4326                 Operand(constant_key << element_size_shift));
4327       } else {
4328         address = external_pointer;
4329       }
4330     } else {
4331       if (shift_size < 0) {
4332         if (shift_size == -32) {
4333           __ dsra32(address, key, 0);
4334         } else {
4335           __ dsra(address, key, -shift_size);
4336         }
4337       } else {
4338         __ dsll(address, key, shift_size);
4339       }
4340       __ Daddu(address, external_pointer, address);
4341     }
4342
4343     if (elements_kind == FLOAT32_ELEMENTS) {
4344       __ cvt_s_d(double_scratch0(), value);
4345       __ swc1(double_scratch0(), MemOperand(address, base_offset));
4346     } else {  // Storing doubles, not floats.
4347       __ sdc1(value, MemOperand(address, base_offset));
4348     }
4349   } else {
4350     Register value(ToRegister(instr->value()));
4351     MemOperand mem_operand = PrepareKeyedOperand(
4352         key, external_pointer, key_is_constant, constant_key,
4353         element_size_shift, shift_size,
4354         base_offset);
4355     switch (elements_kind) {
4356       case UINT8_ELEMENTS:
4357       case UINT8_CLAMPED_ELEMENTS:
4358       case INT8_ELEMENTS:
4359         __ sb(value, mem_operand);
4360         break;
4361       case INT16_ELEMENTS:
4362       case UINT16_ELEMENTS:
4363         __ sh(value, mem_operand);
4364         break;
4365       case INT32_ELEMENTS:
4366       case UINT32_ELEMENTS:
4367         __ sw(value, mem_operand);
4368         break;
4369       case FLOAT32_ELEMENTS:
4370       case FLOAT64_ELEMENTS:
4371       case FAST_DOUBLE_ELEMENTS:
4372       case FAST_ELEMENTS:
4373       case FAST_SMI_ELEMENTS:
4374       case FAST_HOLEY_DOUBLE_ELEMENTS:
4375       case FAST_HOLEY_ELEMENTS:
4376       case FAST_HOLEY_SMI_ELEMENTS:
4377       case DICTIONARY_ELEMENTS:
4378       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
4379       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
4380         UNREACHABLE();
4381         break;
4382     }
4383   }
4384 }
4385
4386
4387 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
4388   DoubleRegister value = ToDoubleRegister(instr->value());
4389   Register elements = ToRegister(instr->elements());
4390   Register scratch = scratch0();
4391   DoubleRegister double_scratch = double_scratch0();
4392   bool key_is_constant = instr->key()->IsConstantOperand();
4393   int base_offset = instr->base_offset();
4394   Label not_nan, done;
4395
4396   // Calculate the effective address of the slot in the array to store the
4397   // double value.
4398   int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
4399   if (key_is_constant) {
4400     int constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
4401     if (constant_key & 0xF0000000) {
4402       Abort(kArrayIndexConstantValueTooBig);
4403     }
4404     __ Daddu(scratch, elements,
4405              Operand((constant_key << element_size_shift) + base_offset));
4406   } else {
4407     int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
4408         ? (element_size_shift - (kSmiTagSize + kSmiShiftSize))
4409         : element_size_shift;
4410     __ Daddu(scratch, elements, Operand(base_offset));
4411     DCHECK((shift_size == 3) || (shift_size == -29));
4412     if (shift_size == 3) {
4413       __ dsll(at, ToRegister(instr->key()), 3);
4414     } else if (shift_size == -29) {
4415       __ dsra(at, ToRegister(instr->key()), 29);
4416     }
4417     __ Daddu(scratch, scratch, at);
4418   }
4419
4420   if (instr->NeedsCanonicalization()) {
4421     __ FPUCanonicalizeNaN(double_scratch, value);
4422     __ sdc1(double_scratch, MemOperand(scratch, 0));
4423   } else {
4424     __ sdc1(value, MemOperand(scratch, 0));
4425   }
4426 }
4427
4428
4429 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
4430   Register value = ToRegister(instr->value());
4431   Register elements = ToRegister(instr->elements());
4432   Register key = instr->key()->IsRegister() ? ToRegister(instr->key())
4433       : no_reg;
4434   Register scratch = scratch0();
4435   Register store_base = scratch;
4436   int offset = instr->base_offset();
4437
4438   // Do the store.
4439   if (instr->key()->IsConstantOperand()) {
4440     DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4441     LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
4442     offset += ToInteger32(const_operand) * kPointerSize;
4443     store_base = elements;
4444   } else {
4445     // Even though the HLoadKeyed instruction forces the input
4446     // representation for the key to be an integer, the input gets replaced
4447     // during bound check elimination with the index argument to the bounds
4448     // check, which can be tagged, so that case must be handled here, too.
4449     if (instr->hydrogen()->key()->representation().IsSmi()) {
4450       __ SmiScale(scratch, key, kPointerSizeLog2);
4451       __ daddu(store_base, elements, scratch);
4452     } else {
4453       __ dsll(scratch, key, kPointerSizeLog2);
4454       __ daddu(store_base, elements, scratch);
4455     }
4456   }
4457
4458   Representation representation = instr->hydrogen()->value()->representation();
4459   if (representation.IsInteger32() && SmiValuesAre32Bits()) {
4460     DCHECK(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY);
4461     DCHECK(instr->hydrogen()->elements_kind() == FAST_SMI_ELEMENTS);
4462     if (FLAG_debug_code) {
4463       Register temp = scratch1();
4464       __ Load(temp, MemOperand(store_base, offset), Representation::Smi());
4465       __ AssertSmi(temp);
4466     }
4467
4468     // Store int value directly to upper half of the smi.
4469     STATIC_ASSERT(kSmiTag == 0);
4470     STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32);
4471     offset += kPointerSize / 2;
4472     representation = Representation::Integer32();
4473   }
4474
4475   __ Store(value, MemOperand(store_base, offset), representation);
4476
4477   if (instr->hydrogen()->NeedsWriteBarrier()) {
4478     SmiCheck check_needed =
4479         instr->hydrogen()->value()->type().IsHeapObject()
4480             ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4481     // Compute address of modified element and store it into key register.
4482     __ Daddu(key, store_base, Operand(offset));
4483     __ RecordWrite(elements,
4484                    key,
4485                    value,
4486                    GetRAState(),
4487                    kSaveFPRegs,
4488                    EMIT_REMEMBERED_SET,
4489                    check_needed,
4490                    instr->hydrogen()->PointersToHereCheckForValue());
4491   }
4492 }
4493
4494
4495 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
4496   // By cases: external, fast double
4497   if (instr->is_fixed_typed_array()) {
4498     DoStoreKeyedExternalArray(instr);
4499   } else if (instr->hydrogen()->value()->representation().IsDouble()) {
4500     DoStoreKeyedFixedDoubleArray(instr);
4501   } else {
4502     DoStoreKeyedFixedArray(instr);
4503   }
4504 }
4505
4506
4507 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
4508   DCHECK(ToRegister(instr->context()).is(cp));
4509   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
4510   DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
4511   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
4512
4513   if (instr->hydrogen()->HasVectorAndSlot()) {
4514     EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
4515   }
4516
4517   Handle<Code> ic = CodeFactory::KeyedStoreICInOptimizedCode(
4518                         isolate(), instr->language_mode(),
4519                         instr->hydrogen()->initialization_state()).code();
4520   CallCode(ic, RelocInfo::CODE_TARGET, instr);
4521 }
4522
4523
4524 void LCodeGen::DoMaybeGrowElements(LMaybeGrowElements* instr) {
4525   class DeferredMaybeGrowElements final : public LDeferredCode {
4526    public:
4527     DeferredMaybeGrowElements(LCodeGen* codegen, LMaybeGrowElements* instr)
4528         : LDeferredCode(codegen), instr_(instr) {}
4529     void Generate() override { codegen()->DoDeferredMaybeGrowElements(instr_); }
4530     LInstruction* instr() override { return instr_; }
4531
4532    private:
4533     LMaybeGrowElements* instr_;
4534   };
4535
4536   Register result = v0;
4537   DeferredMaybeGrowElements* deferred =
4538       new (zone()) DeferredMaybeGrowElements(this, instr);
4539   LOperand* key = instr->key();
4540   LOperand* current_capacity = instr->current_capacity();
4541
4542   DCHECK(instr->hydrogen()->key()->representation().IsInteger32());
4543   DCHECK(instr->hydrogen()->current_capacity()->representation().IsInteger32());
4544   DCHECK(key->IsConstantOperand() || key->IsRegister());
4545   DCHECK(current_capacity->IsConstantOperand() ||
4546          current_capacity->IsRegister());
4547
4548   if (key->IsConstantOperand() && current_capacity->IsConstantOperand()) {
4549     int32_t constant_key = ToInteger32(LConstantOperand::cast(key));
4550     int32_t constant_capacity =
4551         ToInteger32(LConstantOperand::cast(current_capacity));
4552     if (constant_key >= constant_capacity) {
4553       // Deferred case.
4554       __ jmp(deferred->entry());
4555     }
4556   } else if (key->IsConstantOperand()) {
4557     int32_t constant_key = ToInteger32(LConstantOperand::cast(key));
4558     __ Branch(deferred->entry(), le, ToRegister(current_capacity),
4559               Operand(constant_key));
4560   } else if (current_capacity->IsConstantOperand()) {
4561     int32_t constant_capacity =
4562         ToInteger32(LConstantOperand::cast(current_capacity));
4563     __ Branch(deferred->entry(), ge, ToRegister(key),
4564               Operand(constant_capacity));
4565   } else {
4566     __ Branch(deferred->entry(), ge, ToRegister(key),
4567               Operand(ToRegister(current_capacity)));
4568   }
4569
4570   if (instr->elements()->IsRegister()) {
4571     __ mov(result, ToRegister(instr->elements()));
4572   } else {
4573     __ ld(result, ToMemOperand(instr->elements()));
4574   }
4575
4576   __ bind(deferred->exit());
4577 }
4578
4579
4580 void LCodeGen::DoDeferredMaybeGrowElements(LMaybeGrowElements* instr) {
4581   // TODO(3095996): Get rid of this. For now, we need to make the
4582   // result register contain a valid pointer because it is already
4583   // contained in the register pointer map.
4584   Register result = v0;
4585   __ mov(result, zero_reg);
4586
4587   // We have to call a stub.
4588   {
4589     PushSafepointRegistersScope scope(this);
4590     if (instr->object()->IsRegister()) {
4591       __ mov(result, ToRegister(instr->object()));
4592     } else {
4593       __ ld(result, ToMemOperand(instr->object()));
4594     }
4595
4596     LOperand* key = instr->key();
4597     if (key->IsConstantOperand()) {
4598       __ li(a3, Operand(ToSmi(LConstantOperand::cast(key))));
4599     } else {
4600       __ mov(a3, ToRegister(key));
4601       __ SmiTag(a3);
4602     }
4603
4604     GrowArrayElementsStub stub(isolate(), instr->hydrogen()->is_js_array(),
4605                                instr->hydrogen()->kind());
4606     __ mov(a0, result);
4607     __ CallStub(&stub);
4608     RecordSafepointWithLazyDeopt(
4609         instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4610     __ StoreToSafepointRegisterSlot(result, result);
4611   }
4612
4613   // Deopt on smi, which means the elements array changed to dictionary mode.
4614   __ SmiTst(result, at);
4615   DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
4616 }
4617
4618
4619 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4620   Register object_reg = ToRegister(instr->object());
4621   Register scratch = scratch0();
4622
4623   Handle<Map> from_map = instr->original_map();
4624   Handle<Map> to_map = instr->transitioned_map();
4625   ElementsKind from_kind = instr->from_kind();
4626   ElementsKind to_kind = instr->to_kind();
4627
4628   Label not_applicable;
4629   __ ld(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset));
4630   __ Branch(&not_applicable, ne, scratch, Operand(from_map));
4631
4632   if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
4633     Register new_map_reg = ToRegister(instr->new_map_temp());
4634     __ li(new_map_reg, Operand(to_map));
4635     __ sd(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset));
4636     // Write barrier.
4637     __ RecordWriteForMap(object_reg,
4638                          new_map_reg,
4639                          scratch,
4640                          GetRAState(),
4641                          kDontSaveFPRegs);
4642   } else {
4643     DCHECK(object_reg.is(a0));
4644     DCHECK(ToRegister(instr->context()).is(cp));
4645     PushSafepointRegistersScope scope(this);
4646     __ li(a1, Operand(to_map));
4647     bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
4648     TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
4649     __ CallStub(&stub);
4650     RecordSafepointWithRegisters(
4651         instr->pointer_map(), 0, Safepoint::kLazyDeopt);
4652   }
4653   __ bind(&not_applicable);
4654 }
4655
4656
4657 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4658   Register object = ToRegister(instr->object());
4659   Register temp = ToRegister(instr->temp());
4660   Label no_memento_found;
4661   __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found,
4662                                      ne, &no_memento_found);
4663   DeoptimizeIf(al, instr, Deoptimizer::kMementoFound);
4664   __ bind(&no_memento_found);
4665 }
4666
4667
4668 void LCodeGen::DoStringAdd(LStringAdd* instr) {
4669   DCHECK(ToRegister(instr->context()).is(cp));
4670   DCHECK(ToRegister(instr->left()).is(a1));
4671   DCHECK(ToRegister(instr->right()).is(a0));
4672   StringAddStub stub(isolate(),
4673                      instr->hydrogen()->flags(),
4674                      instr->hydrogen()->pretenure_flag());
4675   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4676 }
4677
4678
4679 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
4680   class DeferredStringCharCodeAt final : public LDeferredCode {
4681    public:
4682     DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
4683         : LDeferredCode(codegen), instr_(instr) { }
4684     void Generate() override { codegen()->DoDeferredStringCharCodeAt(instr_); }
4685     LInstruction* instr() override { return instr_; }
4686
4687    private:
4688     LStringCharCodeAt* instr_;
4689   };
4690
4691   DeferredStringCharCodeAt* deferred =
4692       new(zone()) DeferredStringCharCodeAt(this, instr);
4693   StringCharLoadGenerator::Generate(masm(),
4694                                     ToRegister(instr->string()),
4695                                     ToRegister(instr->index()),
4696                                     ToRegister(instr->result()),
4697                                     deferred->entry());
4698   __ bind(deferred->exit());
4699 }
4700
4701
4702 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
4703   Register string = ToRegister(instr->string());
4704   Register result = ToRegister(instr->result());
4705   Register scratch = scratch0();
4706
4707   // TODO(3095996): Get rid of this. For now, we need to make the
4708   // result register contain a valid pointer because it is already
4709   // contained in the register pointer map.
4710   __ mov(result, zero_reg);
4711
4712   PushSafepointRegistersScope scope(this);
4713   __ push(string);
4714   // Push the index as a smi. This is safe because of the checks in
4715   // DoStringCharCodeAt above.
4716   if (instr->index()->IsConstantOperand()) {
4717     int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
4718     __ Daddu(scratch, zero_reg, Operand(Smi::FromInt(const_index)));
4719     __ push(scratch);
4720   } else {
4721     Register index = ToRegister(instr->index());
4722     __ SmiTag(index);
4723     __ push(index);
4724   }
4725   CallRuntimeFromDeferred(Runtime::kStringCharCodeAtRT, 2, instr,
4726                           instr->context());
4727   __ AssertSmi(v0);
4728   __ SmiUntag(v0);
4729   __ StoreToSafepointRegisterSlot(v0, result);
4730 }
4731
4732
4733 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
4734   class DeferredStringCharFromCode final : public LDeferredCode {
4735    public:
4736     DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
4737         : LDeferredCode(codegen), instr_(instr) { }
4738     void Generate() override {
4739       codegen()->DoDeferredStringCharFromCode(instr_);
4740     }
4741     LInstruction* instr() override { return instr_; }
4742
4743    private:
4744     LStringCharFromCode* instr_;
4745   };
4746
4747   DeferredStringCharFromCode* deferred =
4748       new(zone()) DeferredStringCharFromCode(this, instr);
4749
4750   DCHECK(instr->hydrogen()->value()->representation().IsInteger32());
4751   Register char_code = ToRegister(instr->char_code());
4752   Register result = ToRegister(instr->result());
4753   Register scratch = scratch0();
4754   DCHECK(!char_code.is(result));
4755
4756   __ Branch(deferred->entry(), hi,
4757             char_code, Operand(String::kMaxOneByteCharCode));
4758   __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
4759   __ dsll(scratch, char_code, kPointerSizeLog2);
4760   __ Daddu(result, result, scratch);
4761   __ ld(result, FieldMemOperand(result, FixedArray::kHeaderSize));
4762   __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
4763   __ Branch(deferred->entry(), eq, result, Operand(scratch));
4764   __ bind(deferred->exit());
4765 }
4766
4767
4768 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
4769   Register char_code = ToRegister(instr->char_code());
4770   Register result = ToRegister(instr->result());
4771
4772   // TODO(3095996): Get rid of this. For now, we need to make the
4773   // result register contain a valid pointer because it is already
4774   // contained in the register pointer map.
4775   __ mov(result, zero_reg);
4776
4777   PushSafepointRegistersScope scope(this);
4778   __ SmiTag(char_code);
4779   __ push(char_code);
4780   CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context());
4781   __ StoreToSafepointRegisterSlot(v0, result);
4782 }
4783
4784
4785 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
4786   LOperand* input = instr->value();
4787   DCHECK(input->IsRegister() || input->IsStackSlot());
4788   LOperand* output = instr->result();
4789   DCHECK(output->IsDoubleRegister());
4790   FPURegister single_scratch = double_scratch0().low();
4791   if (input->IsStackSlot()) {
4792     Register scratch = scratch0();
4793     __ ld(scratch, ToMemOperand(input));
4794     __ mtc1(scratch, single_scratch);
4795   } else {
4796     __ mtc1(ToRegister(input), single_scratch);
4797   }
4798   __ cvt_d_w(ToDoubleRegister(output), single_scratch);
4799 }
4800
4801
4802 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
4803   LOperand* input = instr->value();
4804   LOperand* output = instr->result();
4805
4806   FPURegister dbl_scratch = double_scratch0();
4807   __ mtc1(ToRegister(input), dbl_scratch);
4808   __ Cvt_d_uw(ToDoubleRegister(output), dbl_scratch, f22);  // TODO(plind): f22?
4809 }
4810
4811
4812 void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
4813   class DeferredNumberTagU final : public LDeferredCode {
4814    public:
4815     DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr)
4816         : LDeferredCode(codegen), instr_(instr) { }
4817     void Generate() override {
4818       codegen()->DoDeferredNumberTagIU(instr_,
4819                                        instr_->value(),
4820                                        instr_->temp1(),
4821                                        instr_->temp2(),
4822                                        UNSIGNED_INT32);
4823     }
4824     LInstruction* instr() override { return instr_; }
4825
4826    private:
4827     LNumberTagU* instr_;
4828   };
4829
4830   Register input = ToRegister(instr->value());
4831   Register result = ToRegister(instr->result());
4832
4833   DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr);
4834   __ Branch(deferred->entry(), hi, input, Operand(Smi::kMaxValue));
4835   __ SmiTag(result, input);
4836   __ bind(deferred->exit());
4837 }
4838
4839
4840 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
4841                                      LOperand* value,
4842                                      LOperand* temp1,
4843                                      LOperand* temp2,
4844                                      IntegerSignedness signedness) {
4845   Label done, slow;
4846   Register src = ToRegister(value);
4847   Register dst = ToRegister(instr->result());
4848   Register tmp1 = scratch0();
4849   Register tmp2 = ToRegister(temp1);
4850   Register tmp3 = ToRegister(temp2);
4851   DoubleRegister dbl_scratch = double_scratch0();
4852
4853   if (signedness == SIGNED_INT32) {
4854     // There was overflow, so bits 30 and 31 of the original integer
4855     // disagree. Try to allocate a heap number in new space and store
4856     // the value in there. If that fails, call the runtime system.
4857     if (dst.is(src)) {
4858       __ SmiUntag(src, dst);
4859       __ Xor(src, src, Operand(0x80000000));
4860     }
4861     __ mtc1(src, dbl_scratch);
4862     __ cvt_d_w(dbl_scratch, dbl_scratch);
4863   } else {
4864     __ mtc1(src, dbl_scratch);
4865     __ Cvt_d_uw(dbl_scratch, dbl_scratch, f22);
4866   }
4867
4868   if (FLAG_inline_new) {
4869     __ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex);
4870     __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow, TAG_RESULT);
4871     __ Branch(&done);
4872   }
4873
4874   // Slow case: Call the runtime system to do the number allocation.
4875   __ bind(&slow);
4876   {
4877     // TODO(3095996): Put a valid pointer value in the stack slot where the
4878     // result register is stored, as this register is in the pointer map, but
4879     // contains an integer value.
4880     __ mov(dst, zero_reg);
4881     // Preserve the value of all registers.
4882     PushSafepointRegistersScope scope(this);
4883
4884     // NumberTagI and NumberTagD use the context from the frame, rather than
4885     // the environment's HContext or HInlinedContext value.
4886     // They only call Runtime::kAllocateHeapNumber.
4887     // The corresponding HChange instructions are added in a phase that does
4888     // not have easy access to the local context.
4889     __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
4890     __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4891     RecordSafepointWithRegisters(
4892         instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4893     __ StoreToSafepointRegisterSlot(v0, dst);
4894   }
4895
4896   // Done. Put the value in dbl_scratch into the value of the allocated heap
4897   // number.
4898   __ bind(&done);
4899   __ sdc1(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset));
4900 }
4901
4902
4903 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
4904   class DeferredNumberTagD final : public LDeferredCode {
4905    public:
4906     DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
4907         : LDeferredCode(codegen), instr_(instr) { }
4908     void Generate() override { codegen()->DoDeferredNumberTagD(instr_); }
4909     LInstruction* instr() override { return instr_; }
4910
4911    private:
4912     LNumberTagD* instr_;
4913   };
4914
4915   DoubleRegister input_reg = ToDoubleRegister(instr->value());
4916   Register scratch = scratch0();
4917   Register reg = ToRegister(instr->result());
4918   Register temp1 = ToRegister(instr->temp());
4919   Register temp2 = ToRegister(instr->temp2());
4920
4921   DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
4922   if (FLAG_inline_new) {
4923     __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
4924     // We want the untagged address first for performance
4925     __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(),
4926                           DONT_TAG_RESULT);
4927   } else {
4928     __ Branch(deferred->entry());
4929   }
4930   __ bind(deferred->exit());
4931   __ sdc1(input_reg, MemOperand(reg, HeapNumber::kValueOffset));
4932   // Now that we have finished with the object's real address tag it
4933   __ Daddu(reg, reg, kHeapObjectTag);
4934 }
4935
4936
4937 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
4938   // TODO(3095996): Get rid of this. For now, we need to make the
4939   // result register contain a valid pointer because it is already
4940   // contained in the register pointer map.
4941   Register reg = ToRegister(instr->result());
4942   __ mov(reg, zero_reg);
4943
4944   PushSafepointRegistersScope scope(this);
4945   // NumberTagI and NumberTagD use the context from the frame, rather than
4946   // the environment's HContext or HInlinedContext value.
4947   // They only call Runtime::kAllocateHeapNumber.
4948   // The corresponding HChange instructions are added in a phase that does
4949   // not have easy access to the local context.
4950   __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
4951   __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4952   RecordSafepointWithRegisters(
4953       instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4954   __ Dsubu(v0, v0, kHeapObjectTag);
4955   __ StoreToSafepointRegisterSlot(v0, reg);
4956 }
4957
4958
4959 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4960   HChange* hchange = instr->hydrogen();
4961   Register input = ToRegister(instr->value());
4962   Register output = ToRegister(instr->result());
4963   if (hchange->CheckFlag(HValue::kCanOverflow) &&
4964       hchange->value()->CheckFlag(HValue::kUint32)) {
4965     __ And(at, input, Operand(0x80000000));
4966     DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, at, Operand(zero_reg));
4967   }
4968   if (hchange->CheckFlag(HValue::kCanOverflow) &&
4969       !hchange->value()->CheckFlag(HValue::kUint32)) {
4970     __ SmiTagCheckOverflow(output, input, at);
4971     DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, at, Operand(zero_reg));
4972   } else {
4973     __ SmiTag(output, input);
4974   }
4975 }
4976
4977
4978 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4979   Register scratch = scratch0();
4980   Register input = ToRegister(instr->value());
4981   Register result = ToRegister(instr->result());
4982   if (instr->needs_check()) {
4983     STATIC_ASSERT(kHeapObjectTag == 1);
4984     // If the input is a HeapObject, value of scratch won't be zero.
4985     __ And(scratch, input, Operand(kHeapObjectTag));
4986     __ SmiUntag(result, input);
4987     DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, scratch, Operand(zero_reg));
4988   } else {
4989     __ SmiUntag(result, input);
4990   }
4991 }
4992
4993
4994 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
4995                                 DoubleRegister result_reg,
4996                                 NumberUntagDMode mode) {
4997   bool can_convert_undefined_to_nan =
4998       instr->hydrogen()->can_convert_undefined_to_nan();
4999   bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
5000
5001   Register scratch = scratch0();
5002   Label convert, load_smi, done;
5003   if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
5004     // Smi check.
5005     __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
5006     // Heap number map check.
5007     __ ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
5008     __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
5009     if (can_convert_undefined_to_nan) {
5010       __ Branch(&convert, ne, scratch, Operand(at));
5011     } else {
5012       DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch,
5013                    Operand(at));
5014     }
5015     // Load heap number.
5016     __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
5017     if (deoptimize_on_minus_zero) {
5018       __ mfc1(at, result_reg);
5019       __ Branch(&done, ne, at, Operand(zero_reg));
5020       __ mfhc1(scratch, result_reg);  // Get exponent/sign bits.
5021       DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, scratch,
5022                    Operand(HeapNumber::kSignMask));
5023     }
5024     __ Branch(&done);
5025     if (can_convert_undefined_to_nan) {
5026       __ bind(&convert);
5027       // Convert undefined (and hole) to NaN.
5028       __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
5029       DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined, input_reg,
5030                    Operand(at));
5031       __ LoadRoot(scratch, Heap::kNanValueRootIndex);
5032       __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset));
5033       __ Branch(&done);
5034     }
5035   } else {
5036     __ SmiUntag(scratch, input_reg);
5037     DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
5038   }
5039   // Smi to double register conversion
5040   __ bind(&load_smi);
5041   // scratch: untagged value of input_reg
5042   __ mtc1(scratch, result_reg);
5043   __ cvt_d_w(result_reg, result_reg);
5044   __ bind(&done);
5045 }
5046
5047
5048 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
5049   Register input_reg = ToRegister(instr->value());
5050   Register scratch1 = scratch0();
5051   Register scratch2 = ToRegister(instr->temp());
5052   DoubleRegister double_scratch = double_scratch0();
5053   DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp2());
5054
5055   DCHECK(!scratch1.is(input_reg) && !scratch1.is(scratch2));
5056   DCHECK(!scratch2.is(input_reg) && !scratch2.is(scratch1));
5057
5058   Label done;
5059
5060   // The input is a tagged HeapObject.
5061   // Heap number map check.
5062   __ ld(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
5063   __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
5064   // This 'at' value and scratch1 map value are used for tests in both clauses
5065   // of the if.
5066
5067   if (instr->truncating()) {
5068     // Performs a truncating conversion of a floating point number as used by
5069     // the JS bitwise operations.
5070     Label no_heap_number, check_bools, check_false;
5071     // Check HeapNumber map.
5072     __ Branch(USE_DELAY_SLOT, &no_heap_number, ne, scratch1, Operand(at));
5073     __ mov(scratch2, input_reg);  // In delay slot.
5074     __ TruncateHeapNumberToI(input_reg, scratch2);
5075     __ Branch(&done);
5076
5077     // Check for Oddballs. Undefined/False is converted to zero and True to one
5078     // for truncating conversions.
5079     __ bind(&no_heap_number);
5080     __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
5081     __ Branch(&check_bools, ne, input_reg, Operand(at));
5082     DCHECK(ToRegister(instr->result()).is(input_reg));
5083     __ Branch(USE_DELAY_SLOT, &done);
5084     __ mov(input_reg, zero_reg);  // In delay slot.
5085
5086     __ bind(&check_bools);
5087     __ LoadRoot(at, Heap::kTrueValueRootIndex);
5088     __ Branch(&check_false, ne, scratch2, Operand(at));
5089     __ Branch(USE_DELAY_SLOT, &done);
5090     __ li(input_reg, Operand(1));  // In delay slot.
5091
5092     __ bind(&check_false);
5093     __ LoadRoot(at, Heap::kFalseValueRootIndex);
5094     DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedBoolean,
5095                  scratch2, Operand(at));
5096     __ Branch(USE_DELAY_SLOT, &done);
5097     __ mov(input_reg, zero_reg);  // In delay slot.
5098   } else {
5099     DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch1,
5100                  Operand(at));
5101
5102     // Load the double value.
5103     __ ldc1(double_scratch,
5104             FieldMemOperand(input_reg, HeapNumber::kValueOffset));
5105
5106     Register except_flag = scratch2;
5107     __ EmitFPUTruncate(kRoundToZero,
5108                        input_reg,
5109                        double_scratch,
5110                        scratch1,
5111                        double_scratch2,
5112                        except_flag,
5113                        kCheckForInexactConversion);
5114
5115     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
5116                  Operand(zero_reg));
5117
5118     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5119       __ Branch(&done, ne, input_reg, Operand(zero_reg));
5120
5121       __ mfhc1(scratch1, double_scratch);  // Get exponent/sign bits.
5122       __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
5123       DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
5124                    Operand(zero_reg));
5125     }
5126   }
5127   __ bind(&done);
5128 }
5129
5130
5131 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
5132   class DeferredTaggedToI final : public LDeferredCode {
5133    public:
5134     DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
5135         : LDeferredCode(codegen), instr_(instr) { }
5136     void Generate() override { codegen()->DoDeferredTaggedToI(instr_); }
5137     LInstruction* instr() override { return instr_; }
5138
5139    private:
5140     LTaggedToI* instr_;
5141   };
5142
5143   LOperand* input = instr->value();
5144   DCHECK(input->IsRegister());
5145   DCHECK(input->Equals(instr->result()));
5146
5147   Register input_reg = ToRegister(input);
5148
5149   if (instr->hydrogen()->value()->representation().IsSmi()) {
5150     __ SmiUntag(input_reg);
5151   } else {
5152     DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr);
5153
5154     // Let the deferred code handle the HeapObject case.
5155     __ JumpIfNotSmi(input_reg, deferred->entry());
5156
5157     // Smi to int32 conversion.
5158     __ SmiUntag(input_reg);
5159     __ bind(deferred->exit());
5160   }
5161 }
5162
5163
5164 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
5165   LOperand* input = instr->value();
5166   DCHECK(input->IsRegister());
5167   LOperand* result = instr->result();
5168   DCHECK(result->IsDoubleRegister());
5169
5170   Register input_reg = ToRegister(input);
5171   DoubleRegister result_reg = ToDoubleRegister(result);
5172
5173   HValue* value = instr->hydrogen()->value();
5174   NumberUntagDMode mode = value->representation().IsSmi()
5175       ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
5176
5177   EmitNumberUntagD(instr, input_reg, result_reg, mode);
5178 }
5179
5180
5181 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
5182   Register result_reg = ToRegister(instr->result());
5183   Register scratch1 = scratch0();
5184   DoubleRegister double_input = ToDoubleRegister(instr->value());
5185
5186   if (instr->truncating()) {
5187     __ TruncateDoubleToI(result_reg, double_input);
5188   } else {
5189     Register except_flag = LCodeGen::scratch1();
5190
5191     __ EmitFPUTruncate(kRoundToMinusInf,
5192                        result_reg,
5193                        double_input,
5194                        scratch1,
5195                        double_scratch0(),
5196                        except_flag,
5197                        kCheckForInexactConversion);
5198
5199     // Deopt if the operation did not succeed (except_flag != 0).
5200     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
5201                  Operand(zero_reg));
5202
5203     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5204       Label done;
5205       __ Branch(&done, ne, result_reg, Operand(zero_reg));
5206       __ mfhc1(scratch1, double_input);  // Get exponent/sign bits.
5207       __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
5208       DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
5209                    Operand(zero_reg));
5210       __ bind(&done);
5211     }
5212   }
5213 }
5214
5215
5216 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5217   Register result_reg = ToRegister(instr->result());
5218   Register scratch1 = LCodeGen::scratch0();
5219   DoubleRegister double_input = ToDoubleRegister(instr->value());
5220
5221   if (instr->truncating()) {
5222     __ TruncateDoubleToI(result_reg, double_input);
5223   } else {
5224     Register except_flag = LCodeGen::scratch1();
5225
5226     __ EmitFPUTruncate(kRoundToMinusInf,
5227                        result_reg,
5228                        double_input,
5229                        scratch1,
5230                        double_scratch0(),
5231                        except_flag,
5232                        kCheckForInexactConversion);
5233
5234     // Deopt if the operation did not succeed (except_flag != 0).
5235     DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
5236                  Operand(zero_reg));
5237
5238     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5239       Label done;
5240       __ Branch(&done, ne, result_reg, Operand(zero_reg));
5241       __ mfhc1(scratch1, double_input);  // Get exponent/sign bits.
5242       __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
5243       DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
5244                    Operand(zero_reg));
5245       __ bind(&done);
5246     }
5247   }
5248   __ SmiTag(result_reg, result_reg);
5249 }
5250
5251
5252 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5253   LOperand* input = instr->value();
5254   __ SmiTst(ToRegister(input), at);
5255   DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, at, Operand(zero_reg));
5256 }
5257
5258
5259 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5260   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
5261     LOperand* input = instr->value();
5262     __ SmiTst(ToRegister(input), at);
5263     DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
5264   }
5265 }
5266
5267
5268 void LCodeGen::DoCheckArrayBufferNotNeutered(
5269     LCheckArrayBufferNotNeutered* instr) {
5270   Register view = ToRegister(instr->view());
5271   Register scratch = scratch0();
5272
5273   __ ld(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset));
5274   __ lw(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset));
5275   __ And(at, scratch, 1 << JSArrayBuffer::WasNeutered::kShift);
5276   DeoptimizeIf(ne, instr, Deoptimizer::kOutOfBounds, at, Operand(zero_reg));
5277 }
5278
5279
5280 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5281   Register input = ToRegister(instr->value());
5282   Register scratch = scratch0();
5283
5284   __ GetObjectType(input, scratch, scratch);
5285
5286   if (instr->hydrogen()->is_interval_check()) {
5287     InstanceType first;
5288     InstanceType last;
5289     instr->hydrogen()->GetCheckInterval(&first, &last);
5290
5291     // If there is only one type in the interval check for equality.
5292     if (first == last) {
5293       DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType, scratch,
5294                    Operand(first));
5295     } else {
5296       DeoptimizeIf(lo, instr, Deoptimizer::kWrongInstanceType, scratch,
5297                    Operand(first));
5298       // Omit check for the last type.
5299       if (last != LAST_TYPE) {
5300         DeoptimizeIf(hi, instr, Deoptimizer::kWrongInstanceType, scratch,
5301                      Operand(last));
5302       }
5303     }
5304   } else {
5305     uint8_t mask;
5306     uint8_t tag;
5307     instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
5308
5309     if (base::bits::IsPowerOfTwo32(mask)) {
5310       DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
5311       __ And(at, scratch, mask);
5312       DeoptimizeIf(tag == 0 ? ne : eq, instr, Deoptimizer::kWrongInstanceType,
5313                    at, Operand(zero_reg));
5314     } else {
5315       __ And(scratch, scratch, Operand(mask));
5316       DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType, scratch,
5317                    Operand(tag));
5318     }
5319   }
5320 }
5321
5322
5323 void LCodeGen::DoCheckValue(LCheckValue* instr) {
5324   Register reg = ToRegister(instr->value());
5325   Handle<HeapObject> object = instr->hydrogen()->object().handle();
5326   AllowDeferredHandleDereference smi_check;
5327   if (isolate()->heap()->InNewSpace(*object)) {
5328     Register reg = ToRegister(instr->value());
5329     Handle<Cell> cell = isolate()->factory()->NewCell(object);
5330     __ li(at, Operand(cell));
5331     __ ld(at, FieldMemOperand(at, Cell::kValueOffset));
5332     DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch, reg, Operand(at));
5333   } else {
5334     DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch, reg, Operand(object));
5335   }
5336 }
5337
5338
5339 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
5340   {
5341     PushSafepointRegistersScope scope(this);
5342     __ push(object);
5343     __ mov(cp, zero_reg);
5344     __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
5345     RecordSafepointWithRegisters(
5346         instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
5347     __ StoreToSafepointRegisterSlot(v0, scratch0());
5348   }
5349   __ SmiTst(scratch0(), at);
5350   DeoptimizeIf(eq, instr, Deoptimizer::kInstanceMigrationFailed, at,
5351                Operand(zero_reg));
5352 }
5353
5354
5355 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5356   class DeferredCheckMaps final : public LDeferredCode {
5357    public:
5358     DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
5359         : LDeferredCode(codegen), instr_(instr), object_(object) {
5360       SetExit(check_maps());
5361     }
5362     void Generate() override {
5363       codegen()->DoDeferredInstanceMigration(instr_, object_);
5364     }
5365     Label* check_maps() { return &check_maps_; }
5366     LInstruction* instr() override { return instr_; }
5367
5368    private:
5369     LCheckMaps* instr_;
5370     Label check_maps_;
5371     Register object_;
5372   };
5373
5374   if (instr->hydrogen()->IsStabilityCheck()) {
5375     const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5376     for (int i = 0; i < maps->size(); ++i) {
5377       AddStabilityDependency(maps->at(i).handle());
5378     }
5379     return;
5380   }
5381
5382   Register map_reg = scratch0();
5383   LOperand* input = instr->value();
5384   DCHECK(input->IsRegister());
5385   Register reg = ToRegister(input);
5386   __ ld(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
5387
5388   DeferredCheckMaps* deferred = NULL;
5389   if (instr->hydrogen()->HasMigrationTarget()) {
5390     deferred = new(zone()) DeferredCheckMaps(this, instr, reg);
5391     __ bind(deferred->check_maps());
5392   }
5393
5394   const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5395   Label success;
5396   for (int i = 0; i < maps->size() - 1; i++) {
5397     Handle<Map> map = maps->at(i).handle();
5398     __ CompareMapAndBranch(map_reg, map, &success, eq, &success);
5399   }
5400   Handle<Map> map = maps->at(maps->size() - 1).handle();
5401   // Do the CompareMap() directly within the Branch() and DeoptimizeIf().
5402   if (instr->hydrogen()->HasMigrationTarget()) {
5403     __ Branch(deferred->entry(), ne, map_reg, Operand(map));
5404   } else {
5405     DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, map_reg, Operand(map));
5406   }
5407
5408   __ bind(&success);
5409 }
5410
5411
5412 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5413   DoubleRegister value_reg = ToDoubleRegister(instr->unclamped());
5414   Register result_reg = ToRegister(instr->result());
5415   DoubleRegister temp_reg = ToDoubleRegister(instr->temp());
5416   __ ClampDoubleToUint8(result_reg, value_reg, temp_reg);
5417 }
5418
5419
5420 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
5421   Register unclamped_reg = ToRegister(instr->unclamped());
5422   Register result_reg = ToRegister(instr->result());
5423   __ ClampUint8(result_reg, unclamped_reg);
5424 }
5425
5426
5427 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
5428   Register scratch = scratch0();
5429   Register input_reg = ToRegister(instr->unclamped());
5430   Register result_reg = ToRegister(instr->result());
5431   DoubleRegister temp_reg = ToDoubleRegister(instr->temp());
5432   Label is_smi, done, heap_number;
5433
5434   // Both smi and heap number cases are handled.
5435   __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi);
5436
5437   // Check for heap number
5438   __ ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
5439   __ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map()));
5440
5441   // Check for undefined. Undefined is converted to zero for clamping
5442   // conversions.
5443   DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined, input_reg,
5444                Operand(factory()->undefined_value()));
5445   __ mov(result_reg, zero_reg);
5446   __ jmp(&done);
5447
5448   // Heap number
5449   __ bind(&heap_number);
5450   __ ldc1(double_scratch0(), FieldMemOperand(input_reg,
5451                                              HeapNumber::kValueOffset));
5452   __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg);
5453   __ jmp(&done);
5454
5455   __ bind(&is_smi);
5456   __ ClampUint8(result_reg, scratch);
5457
5458   __ bind(&done);
5459 }
5460
5461
5462 void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
5463   DoubleRegister value_reg = ToDoubleRegister(instr->value());
5464   Register result_reg = ToRegister(instr->result());
5465   if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
5466     __ FmoveHigh(result_reg, value_reg);
5467   } else {
5468     __ FmoveLow(result_reg, value_reg);
5469   }
5470 }
5471
5472
5473 void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
5474   Register hi_reg = ToRegister(instr->hi());
5475   Register lo_reg = ToRegister(instr->lo());
5476   DoubleRegister result_reg = ToDoubleRegister(instr->result());
5477   __ Move(result_reg, lo_reg, hi_reg);
5478 }
5479
5480
5481 void LCodeGen::DoAllocate(LAllocate* instr) {
5482   class DeferredAllocate final : public LDeferredCode {
5483    public:
5484     DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
5485         : LDeferredCode(codegen), instr_(instr) { }
5486     void Generate() override { codegen()->DoDeferredAllocate(instr_); }
5487     LInstruction* instr() override { return instr_; }
5488
5489    private:
5490     LAllocate* instr_;
5491   };
5492
5493   DeferredAllocate* deferred =
5494       new(zone()) DeferredAllocate(this, instr);
5495
5496   Register result = ToRegister(instr->result());
5497   Register scratch = ToRegister(instr->temp1());
5498   Register scratch2 = ToRegister(instr->temp2());
5499
5500   // Allocate memory for the object.
5501   AllocationFlags flags = TAG_OBJECT;
5502   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
5503     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
5504   }
5505   if (instr->hydrogen()->IsOldSpaceAllocation()) {
5506     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5507     flags = static_cast<AllocationFlags>(flags | PRETENURE);
5508   }
5509   if (instr->size()->IsConstantOperand()) {
5510     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5511     if (size <= Page::kMaxRegularHeapObjectSize) {
5512       __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
5513     } else {
5514       __ jmp(deferred->entry());
5515     }
5516   } else {
5517     Register size = ToRegister(instr->size());
5518     __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
5519   }
5520
5521   __ bind(deferred->exit());
5522
5523   if (instr->hydrogen()->MustPrefillWithFiller()) {
5524     STATIC_ASSERT(kHeapObjectTag == 1);
5525     if (instr->size()->IsConstantOperand()) {
5526       int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5527       __ li(scratch, Operand(size - kHeapObjectTag));
5528     } else {
5529       __ Dsubu(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag));
5530     }
5531     __ li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
5532     Label loop;
5533     __ bind(&loop);
5534     __ Dsubu(scratch, scratch, Operand(kPointerSize));
5535     __ Daddu(at, result, Operand(scratch));
5536     __ sd(scratch2, MemOperand(at));
5537     __ Branch(&loop, ge, scratch, Operand(zero_reg));
5538   }
5539 }
5540
5541
5542 void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
5543   Register result = ToRegister(instr->result());
5544
5545   // TODO(3095996): Get rid of this. For now, we need to make the
5546   // result register contain a valid pointer because it is already
5547   // contained in the register pointer map.
5548   __ mov(result, zero_reg);
5549
5550   PushSafepointRegistersScope scope(this);
5551   if (instr->size()->IsRegister()) {
5552     Register size = ToRegister(instr->size());
5553     DCHECK(!size.is(result));
5554     __ SmiTag(size);
5555     __ push(size);
5556   } else {
5557     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5558     if (size >= 0 && size <= Smi::kMaxValue) {
5559       __ li(v0, Operand(Smi::FromInt(size)));
5560       __ Push(v0);
5561     } else {
5562       // We should never get here at runtime => abort
5563       __ stop("invalid allocation size");
5564       return;
5565     }
5566   }
5567
5568   int flags = AllocateDoubleAlignFlag::encode(
5569       instr->hydrogen()->MustAllocateDoubleAligned());
5570   if (instr->hydrogen()->IsOldSpaceAllocation()) {
5571     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5572     flags = AllocateTargetSpace::update(flags, OLD_SPACE);
5573   } else {
5574     flags = AllocateTargetSpace::update(flags, NEW_SPACE);
5575   }
5576   __ li(v0, Operand(Smi::FromInt(flags)));
5577   __ Push(v0);
5578
5579   CallRuntimeFromDeferred(
5580       Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
5581   __ StoreToSafepointRegisterSlot(v0, result);
5582 }
5583
5584
5585 void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
5586   DCHECK(ToRegister(instr->value()).is(a0));
5587   DCHECK(ToRegister(instr->result()).is(v0));
5588   __ push(a0);
5589   CallRuntime(Runtime::kToFastProperties, 1, instr);
5590 }
5591
5592
5593 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
5594   DCHECK(ToRegister(instr->context()).is(cp));
5595   Label materialized;
5596   // Registers will be used as follows:
5597   // a7 = literals array.
5598   // a1 = regexp literal.
5599   // a0 = regexp literal clone.
5600   // a2 and a4-a6 are used as temporaries.
5601   int literal_offset =
5602       FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
5603   __ li(a7, instr->hydrogen()->literals());
5604   __ ld(a1, FieldMemOperand(a7, literal_offset));
5605   __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
5606   __ Branch(&materialized, ne, a1, Operand(at));
5607
5608   // Create regexp literal using runtime function
5609   // Result will be in v0.
5610   __ li(a6, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
5611   __ li(a5, Operand(instr->hydrogen()->pattern()));
5612   __ li(a4, Operand(instr->hydrogen()->flags()));
5613   __ Push(a7, a6, a5, a4);
5614   CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
5615   __ mov(a1, v0);
5616
5617   __ bind(&materialized);
5618   int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
5619   Label allocated, runtime_allocate;
5620
5621   __ Allocate(size, v0, a2, a3, &runtime_allocate, TAG_OBJECT);
5622   __ jmp(&allocated);
5623
5624   __ bind(&runtime_allocate);
5625   __ li(a0, Operand(Smi::FromInt(size)));
5626   __ Push(a1, a0);
5627   CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
5628   __ pop(a1);
5629
5630   __ bind(&allocated);
5631   // Copy the content into the newly allocated memory.
5632   // (Unroll copy loop once for better throughput).
5633   for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
5634     __ ld(a3, FieldMemOperand(a1, i));
5635     __ ld(a2, FieldMemOperand(a1, i + kPointerSize));
5636     __ sd(a3, FieldMemOperand(v0, i));
5637     __ sd(a2, FieldMemOperand(v0, i + kPointerSize));
5638   }
5639   if ((size % (2 * kPointerSize)) != 0) {
5640     __ ld(a3, FieldMemOperand(a1, size - kPointerSize));
5641     __ sd(a3, FieldMemOperand(v0, size - kPointerSize));
5642   }
5643 }
5644
5645
5646 void LCodeGen::DoTypeof(LTypeof* instr) {
5647   DCHECK(ToRegister(instr->value()).is(a3));
5648   DCHECK(ToRegister(instr->result()).is(v0));
5649   Label end, do_call;
5650   Register value_register = ToRegister(instr->value());
5651   __ JumpIfNotSmi(value_register, &do_call);
5652   __ li(v0, Operand(isolate()->factory()->number_string()));
5653   __ jmp(&end);
5654   __ bind(&do_call);
5655   TypeofStub stub(isolate());
5656   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
5657   __ bind(&end);
5658 }
5659
5660
5661 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
5662   Register input = ToRegister(instr->value());
5663
5664   Register cmp1 = no_reg;
5665   Operand cmp2 = Operand(no_reg);
5666
5667   Condition final_branch_condition = EmitTypeofIs(instr->TrueLabel(chunk_),
5668                                                   instr->FalseLabel(chunk_),
5669                                                   input,
5670                                                   instr->type_literal(),
5671                                                   &cmp1,
5672                                                   &cmp2);
5673
5674   DCHECK(cmp1.is_valid());
5675   DCHECK(!cmp2.is_reg() || cmp2.rm().is_valid());
5676
5677   if (final_branch_condition != kNoCondition) {
5678     EmitBranch(instr, final_branch_condition, cmp1, cmp2);
5679   }
5680 }
5681
5682
5683 Condition LCodeGen::EmitTypeofIs(Label* true_label,
5684                                  Label* false_label,
5685                                  Register input,
5686                                  Handle<String> type_name,
5687                                  Register* cmp1,
5688                                  Operand* cmp2) {
5689   // This function utilizes the delay slot heavily. This is used to load
5690   // values that are always usable without depending on the type of the input
5691   // register.
5692   Condition final_branch_condition = kNoCondition;
5693   Register scratch = scratch0();
5694   Factory* factory = isolate()->factory();
5695   if (String::Equals(type_name, factory->number_string())) {
5696     __ JumpIfSmi(input, true_label);
5697     __ ld(input, FieldMemOperand(input, HeapObject::kMapOffset));
5698     __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
5699     *cmp1 = input;
5700     *cmp2 = Operand(at);
5701     final_branch_condition = eq;
5702
5703   } else if (String::Equals(type_name, factory->string_string())) {
5704     __ JumpIfSmi(input, false_label);
5705     __ GetObjectType(input, input, scratch);
5706     *cmp1 = scratch;
5707     *cmp2 = Operand(FIRST_NONSTRING_TYPE);
5708     final_branch_condition = lt;
5709
5710   } else if (String::Equals(type_name, factory->symbol_string())) {
5711     __ JumpIfSmi(input, false_label);
5712     __ GetObjectType(input, input, scratch);
5713     *cmp1 = scratch;
5714     *cmp2 = Operand(SYMBOL_TYPE);
5715     final_branch_condition = eq;
5716
5717   } else if (String::Equals(type_name, factory->boolean_string())) {
5718     __ LoadRoot(at, Heap::kTrueValueRootIndex);
5719     __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
5720     __ LoadRoot(at, Heap::kFalseValueRootIndex);
5721     *cmp1 = at;
5722     *cmp2 = Operand(input);
5723     final_branch_condition = eq;
5724
5725   } else if (String::Equals(type_name, factory->undefined_string())) {
5726     __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
5727     __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
5728     // The first instruction of JumpIfSmi is an And - it is safe in the delay
5729     // slot.
5730     __ JumpIfSmi(input, false_label);
5731     // Check for undetectable objects => true.
5732     __ ld(input, FieldMemOperand(input, HeapObject::kMapOffset));
5733     __ lbu(at, FieldMemOperand(input, Map::kBitFieldOffset));
5734     __ And(at, at, 1 << Map::kIsUndetectable);
5735     *cmp1 = at;
5736     *cmp2 = Operand(zero_reg);
5737     final_branch_condition = ne;
5738
5739   } else if (String::Equals(type_name, factory->function_string())) {
5740     __ JumpIfSmi(input, false_label);
5741     __ ld(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
5742     __ lbu(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
5743     __ And(scratch, scratch,
5744            Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
5745     *cmp1 = scratch;
5746     *cmp2 = Operand(1 << Map::kIsCallable);
5747     final_branch_condition = eq;
5748
5749   } else if (String::Equals(type_name, factory->object_string())) {
5750     __ JumpIfSmi(input, false_label);
5751     __ LoadRoot(at, Heap::kNullValueRootIndex);
5752     __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
5753     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
5754     __ GetObjectType(input, scratch, scratch1());
5755     __ Branch(false_label, lt, scratch1(), Operand(FIRST_SPEC_OBJECT_TYPE));
5756     // Check for callable or undetectable objects => false.
5757     __ lbu(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
5758     __ And(at, scratch,
5759            Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
5760     *cmp1 = at;
5761     *cmp2 = Operand(zero_reg);
5762     final_branch_condition = eq;
5763
5764 // clang-format off
5765 #define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type)        \
5766   } else if (String::Equals(type_name, factory->type##_string())) {  \
5767     __ JumpIfSmi(input, false_label);                                \
5768     __ ld(input, FieldMemOperand(input, HeapObject::kMapOffset));    \
5769     __ LoadRoot(at, Heap::k##Type##MapRootIndex);                    \
5770     *cmp1 = input;                                                   \
5771     *cmp2 = Operand(at);                                             \
5772     final_branch_condition = eq;
5773   SIMD128_TYPES(SIMD128_TYPE)
5774 #undef SIMD128_TYPE
5775     // clang-format on
5776
5777
5778   } else {
5779     *cmp1 = at;
5780     *cmp2 = Operand(zero_reg);  // Set to valid regs, to avoid caller assertion.
5781     __ Branch(false_label);
5782   }
5783
5784   return final_branch_condition;
5785 }
5786
5787
5788 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
5789   Register temp1 = ToRegister(instr->temp());
5790
5791   EmitIsConstructCall(temp1, scratch0());
5792
5793   EmitBranch(instr, eq, temp1,
5794              Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
5795 }
5796
5797
5798 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) {
5799   DCHECK(!temp1.is(temp2));
5800   // Get the frame pointer for the calling frame.
5801   __ ld(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
5802
5803   // Skip the arguments adaptor frame if it exists.
5804   Label check_frame_marker;
5805   __ ld(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset));
5806   __ Branch(&check_frame_marker, ne, temp2,
5807             Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
5808   __ ld(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset));
5809
5810   // Check the marker in the calling frame.
5811   __ bind(&check_frame_marker);
5812   __ ld(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset));
5813 }
5814
5815
5816 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
5817   if (info()->ShouldEnsureSpaceForLazyDeopt()) {
5818     // Ensure that we have enough space after the previous lazy-bailout
5819     // instruction for patching the code here.
5820     int current_pc = masm()->pc_offset();
5821     if (current_pc < last_lazy_deopt_pc_ + space_needed) {
5822       int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
5823       DCHECK_EQ(0, padding_size % Assembler::kInstrSize);
5824       while (padding_size > 0) {
5825         __ nop();
5826         padding_size -= Assembler::kInstrSize;
5827       }
5828     }
5829   }
5830   last_lazy_deopt_pc_ = masm()->pc_offset();
5831 }
5832
5833
5834 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
5835   last_lazy_deopt_pc_ = masm()->pc_offset();
5836   DCHECK(instr->HasEnvironment());
5837   LEnvironment* env = instr->environment();
5838   RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
5839   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
5840 }
5841
5842
5843 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
5844   Deoptimizer::BailoutType type = instr->hydrogen()->type();
5845   // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
5846   // needed return address), even though the implementation of LAZY and EAGER is
5847   // now identical. When LAZY is eventually completely folded into EAGER, remove
5848   // the special case below.
5849   if (info()->IsStub() && type == Deoptimizer::EAGER) {
5850     type = Deoptimizer::LAZY;
5851   }
5852
5853   DeoptimizeIf(al, instr, instr->hydrogen()->reason(), type, zero_reg,
5854                Operand(zero_reg));
5855 }
5856
5857
5858 void LCodeGen::DoDummy(LDummy* instr) {
5859   // Nothing to see here, move on!
5860 }
5861
5862
5863 void LCodeGen::DoDummyUse(LDummyUse* instr) {
5864   // Nothing to see here, move on!
5865 }
5866
5867
5868 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
5869   PushSafepointRegistersScope scope(this);
5870   LoadContextFromDeferred(instr->context());
5871   __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
5872   RecordSafepointWithLazyDeopt(
5873       instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
5874   DCHECK(instr->HasEnvironment());
5875   LEnvironment* env = instr->environment();
5876   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
5877 }
5878
5879
5880 void LCodeGen::DoStackCheck(LStackCheck* instr) {
5881   class DeferredStackCheck final : public LDeferredCode {
5882    public:
5883     DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
5884         : LDeferredCode(codegen), instr_(instr) { }
5885     void Generate() override { codegen()->DoDeferredStackCheck(instr_); }
5886     LInstruction* instr() override { return instr_; }
5887
5888    private:
5889     LStackCheck* instr_;
5890   };
5891
5892   DCHECK(instr->HasEnvironment());
5893   LEnvironment* env = instr->environment();
5894   // There is no LLazyBailout instruction for stack-checks. We have to
5895   // prepare for lazy deoptimization explicitly here.
5896   if (instr->hydrogen()->is_function_entry()) {
5897     // Perform stack overflow check.
5898     Label done;
5899     __ LoadRoot(at, Heap::kStackLimitRootIndex);
5900     __ Branch(&done, hs, sp, Operand(at));
5901     DCHECK(instr->context()->IsRegister());
5902     DCHECK(ToRegister(instr->context()).is(cp));
5903     CallCode(isolate()->builtins()->StackCheck(),
5904              RelocInfo::CODE_TARGET,
5905              instr);
5906     __ bind(&done);
5907   } else {
5908     DCHECK(instr->hydrogen()->is_backwards_branch());
5909     // Perform stack overflow check if this goto needs it before jumping.
5910     DeferredStackCheck* deferred_stack_check =
5911         new(zone()) DeferredStackCheck(this, instr);
5912     __ LoadRoot(at, Heap::kStackLimitRootIndex);
5913     __ Branch(deferred_stack_check->entry(), lo, sp, Operand(at));
5914     EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
5915     __ bind(instr->done_label());
5916     deferred_stack_check->SetExit(instr->done_label());
5917     RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
5918     // Don't record a deoptimization index for the safepoint here.
5919     // This will be done explicitly when emitting call and the safepoint in
5920     // the deferred code.
5921   }
5922 }
5923
5924
5925 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
5926   // This is a pseudo-instruction that ensures that the environment here is
5927   // properly registered for deoptimization and records the assembler's PC
5928   // offset.
5929   LEnvironment* environment = instr->environment();
5930
5931   // If the environment were already registered, we would have no way of
5932   // backpatching it with the spill slot operands.
5933   DCHECK(!environment->HasBeenRegistered());
5934   RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
5935
5936   GenerateOsrPrologue();
5937 }
5938
5939
5940 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
5941   Register result = ToRegister(instr->result());
5942   Register object = ToRegister(instr->object());
5943
5944   __ And(at, object, kSmiTagMask);
5945   DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
5946
5947   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
5948   __ GetObjectType(object, a1, a1);
5949   DeoptimizeIf(le, instr, Deoptimizer::kNotAJavaScriptObject, a1,
5950                Operand(LAST_JS_PROXY_TYPE));
5951
5952   Label use_cache, call_runtime;
5953   DCHECK(object.is(a0));
5954   Register null_value = a5;
5955   __ LoadRoot(null_value, Heap::kNullValueRootIndex);
5956   __ CheckEnumCache(null_value, &call_runtime);
5957
5958   __ ld(result, FieldMemOperand(object, HeapObject::kMapOffset));
5959   __ Branch(&use_cache);
5960
5961   // Get the set of properties to enumerate.
5962   __ bind(&call_runtime);
5963   __ push(object);
5964   CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
5965
5966   __ ld(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
5967   DCHECK(result.is(v0));
5968   __ LoadRoot(at, Heap::kMetaMapRootIndex);
5969   DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, a1, Operand(at));
5970   __ bind(&use_cache);
5971 }
5972
5973
5974 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
5975   Register map = ToRegister(instr->map());
5976   Register result = ToRegister(instr->result());
5977   Label load_cache, done;
5978   __ EnumLength(result, map);
5979   __ Branch(&load_cache, ne, result, Operand(Smi::FromInt(0)));
5980   __ li(result, Operand(isolate()->factory()->empty_fixed_array()));
5981   __ jmp(&done);
5982
5983   __ bind(&load_cache);
5984   __ LoadInstanceDescriptors(map, result);
5985   __ ld(result,
5986         FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
5987   __ ld(result,
5988         FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
5989   DeoptimizeIf(eq, instr, Deoptimizer::kNoCache, result, Operand(zero_reg));
5990
5991   __ bind(&done);
5992 }
5993
5994
5995 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
5996   Register object = ToRegister(instr->value());
5997   Register map = ToRegister(instr->map());
5998   __ ld(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
5999   DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, map, Operand(scratch0()));
6000 }
6001
6002
6003 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
6004                                            Register result,
6005                                            Register object,
6006                                            Register index) {
6007   PushSafepointRegistersScope scope(this);
6008   __ Push(object, index);
6009   __ mov(cp, zero_reg);
6010   __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble);
6011   RecordSafepointWithRegisters(
6012      instr->pointer_map(), 2, Safepoint::kNoLazyDeopt);
6013   __ StoreToSafepointRegisterSlot(v0, result);
6014 }
6015
6016
6017 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
6018   class DeferredLoadMutableDouble final : public LDeferredCode {
6019    public:
6020     DeferredLoadMutableDouble(LCodeGen* codegen,
6021                               LLoadFieldByIndex* instr,
6022                               Register result,
6023                               Register object,
6024                               Register index)
6025         : LDeferredCode(codegen),
6026           instr_(instr),
6027           result_(result),
6028           object_(object),
6029           index_(index) {
6030     }
6031     void Generate() override {
6032       codegen()->DoDeferredLoadMutableDouble(instr_, result_, object_, index_);
6033     }
6034     LInstruction* instr() override { return instr_; }
6035
6036    private:
6037     LLoadFieldByIndex* instr_;
6038     Register result_;
6039     Register object_;
6040     Register index_;
6041   };
6042
6043   Register object = ToRegister(instr->object());
6044   Register index = ToRegister(instr->index());
6045   Register result = ToRegister(instr->result());
6046   Register scratch = scratch0();
6047
6048   DeferredLoadMutableDouble* deferred;
6049   deferred = new(zone()) DeferredLoadMutableDouble(
6050       this, instr, result, object, index);
6051
6052   Label out_of_object, done;
6053
6054   __ And(scratch, index, Operand(Smi::FromInt(1)));
6055   __ Branch(deferred->entry(), ne, scratch, Operand(zero_reg));
6056   __ dsra(index, index, 1);
6057
6058   __ Branch(USE_DELAY_SLOT, &out_of_object, lt, index, Operand(zero_reg));
6059   __ SmiScale(scratch, index, kPointerSizeLog2);  // In delay slot.
6060   __ Daddu(scratch, object, scratch);
6061   __ ld(result, FieldMemOperand(scratch, JSObject::kHeaderSize));
6062
6063   __ Branch(&done);
6064
6065   __ bind(&out_of_object);
6066   __ ld(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
6067   // Index is equal to negated out of object property index plus 1.
6068   __ Dsubu(scratch, result, scratch);
6069   __ ld(result, FieldMemOperand(scratch,
6070                                 FixedArray::kHeaderSize - kPointerSize));
6071   __ bind(deferred->exit());
6072   __ bind(&done);
6073 }
6074
6075
6076 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) {
6077   Register context = ToRegister(instr->context());
6078   __ sd(context, MemOperand(fp, StandardFrameConstants::kContextOffset));
6079 }
6080
6081
6082 void LCodeGen::DoAllocateBlockContext(LAllocateBlockContext* instr) {
6083   Handle<ScopeInfo> scope_info = instr->scope_info();
6084   __ li(at, scope_info);
6085   __ Push(at, ToRegister(instr->function()));
6086   CallRuntime(Runtime::kPushBlockContext, 2, instr);
6087   RecordSafepoint(Safepoint::kNoLazyDeopt);
6088 }
6089
6090
6091 #undef __
6092
6093 }  // namespace internal
6094 }  // namespace v8