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