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