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