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