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