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