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