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