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