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