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