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