Upstream version 11.39.258.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 = ToRegister(instr->temp_vector());
2984   DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister()));
2985   __ mov(vector, instr->hydrogen()->feedback_vector());
2986   // No need to allocate this register.
2987   DCHECK(VectorLoadICDescriptor::SlotRegister().is(eax));
2988   __ mov(VectorLoadICDescriptor::SlotRegister(),
2989          Immediate(Smi::FromInt(instr->hydrogen()->slot())));
2990 }
2991
2992
2993 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
2994   DCHECK(ToRegister(instr->context()).is(esi));
2995   DCHECK(ToRegister(instr->global_object())
2996              .is(LoadDescriptor::ReceiverRegister()));
2997   DCHECK(ToRegister(instr->result()).is(eax));
2998
2999   __ mov(LoadDescriptor::NameRegister(), instr->name());
3000   if (FLAG_vector_ics) {
3001     EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
3002   }
3003   ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
3004   Handle<Code> ic = CodeFactory::LoadIC(isolate(), mode).code();
3005   CallCode(ic, RelocInfo::CODE_TARGET, instr);
3006 }
3007
3008
3009 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
3010   Register value = ToRegister(instr->value());
3011   Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle();
3012
3013   // If the cell we are storing to contains the hole it could have
3014   // been deleted from the property dictionary. In that case, we need
3015   // to update the property details in the property dictionary to mark
3016   // it as no longer deleted. We deoptimize in that case.
3017   if (instr->hydrogen()->RequiresHoleCheck()) {
3018     __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value());
3019     DeoptimizeIf(equal, instr, "hole");
3020   }
3021
3022   // Store the value.
3023   __ mov(Operand::ForCell(cell_handle), value);
3024   // Cells are always rescanned, so no write barrier here.
3025 }
3026
3027
3028 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
3029   Register context = ToRegister(instr->context());
3030   Register result = ToRegister(instr->result());
3031   __ mov(result, ContextOperand(context, instr->slot_index()));
3032
3033   if (instr->hydrogen()->RequiresHoleCheck()) {
3034     __ cmp(result, factory()->the_hole_value());
3035     if (instr->hydrogen()->DeoptimizesOnHole()) {
3036       DeoptimizeIf(equal, instr, "hole");
3037     } else {
3038       Label is_not_hole;
3039       __ j(not_equal, &is_not_hole, Label::kNear);
3040       __ mov(result, factory()->undefined_value());
3041       __ bind(&is_not_hole);
3042     }
3043   }
3044 }
3045
3046
3047 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
3048   Register context = ToRegister(instr->context());
3049   Register value = ToRegister(instr->value());
3050
3051   Label skip_assignment;
3052
3053   Operand target = ContextOperand(context, instr->slot_index());
3054   if (instr->hydrogen()->RequiresHoleCheck()) {
3055     __ cmp(target, factory()->the_hole_value());
3056     if (instr->hydrogen()->DeoptimizesOnHole()) {
3057       DeoptimizeIf(equal, instr, "hole");
3058     } else {
3059       __ j(not_equal, &skip_assignment, Label::kNear);
3060     }
3061   }
3062
3063   __ mov(target, value);
3064   if (instr->hydrogen()->NeedsWriteBarrier()) {
3065     SmiCheck check_needed =
3066         instr->hydrogen()->value()->type().IsHeapObject()
3067             ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3068     Register temp = ToRegister(instr->temp());
3069     int offset = Context::SlotOffset(instr->slot_index());
3070     __ RecordWriteContextSlot(context,
3071                               offset,
3072                               value,
3073                               temp,
3074                               kSaveFPRegs,
3075                               EMIT_REMEMBERED_SET,
3076                               check_needed);
3077   }
3078
3079   __ bind(&skip_assignment);
3080 }
3081
3082
3083 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
3084   HObjectAccess access = instr->hydrogen()->access();
3085   int offset = access.offset();
3086
3087   if (access.IsExternalMemory()) {
3088     Register result = ToRegister(instr->result());
3089     MemOperand operand = instr->object()->IsConstantOperand()
3090         ? MemOperand::StaticVariable(ToExternalReference(
3091                 LConstantOperand::cast(instr->object())))
3092         : MemOperand(ToRegister(instr->object()), offset);
3093     __ Load(result, operand, access.representation());
3094     return;
3095   }
3096
3097   Register object = ToRegister(instr->object());
3098   if (instr->hydrogen()->representation().IsDouble()) {
3099     XMMRegister result = ToDoubleRegister(instr->result());
3100     __ movsd(result, FieldOperand(object, offset));
3101     return;
3102   }
3103
3104   Register result = ToRegister(instr->result());
3105   if (!access.IsInobject()) {
3106     __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
3107     object = result;
3108   }
3109   __ Load(result, FieldOperand(object, offset), access.representation());
3110 }
3111
3112
3113 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
3114   DCHECK(!operand->IsDoubleRegister());
3115   if (operand->IsConstantOperand()) {
3116     Handle<Object> object = ToHandle(LConstantOperand::cast(operand));
3117     AllowDeferredHandleDereference smi_check;
3118     if (object->IsSmi()) {
3119       __ Push(Handle<Smi>::cast(object));
3120     } else {
3121       __ PushHeapObject(Handle<HeapObject>::cast(object));
3122     }
3123   } else if (operand->IsRegister()) {
3124     __ push(ToRegister(operand));
3125   } else {
3126     __ push(ToOperand(operand));
3127   }
3128 }
3129
3130
3131 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
3132   DCHECK(ToRegister(instr->context()).is(esi));
3133   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
3134   DCHECK(ToRegister(instr->result()).is(eax));
3135
3136   __ mov(LoadDescriptor::NameRegister(), instr->name());
3137   if (FLAG_vector_ics) {
3138     EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
3139   }
3140   Handle<Code> ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code();
3141   CallCode(ic, RelocInfo::CODE_TARGET, instr);
3142 }
3143
3144
3145 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
3146   Register function = ToRegister(instr->function());
3147   Register temp = ToRegister(instr->temp());
3148   Register result = ToRegister(instr->result());
3149
3150   // Get the prototype or initial map from the function.
3151   __ mov(result,
3152          FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3153
3154   // Check that the function has a prototype or an initial map.
3155   __ cmp(Operand(result), Immediate(factory()->the_hole_value()));
3156   DeoptimizeIf(equal, instr, "hole");
3157
3158   // If the function does not have an initial map, we're done.
3159   Label done;
3160   __ CmpObjectType(result, MAP_TYPE, temp);
3161   __ j(not_equal, &done, Label::kNear);
3162
3163   // Get the prototype from the initial map.
3164   __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
3165
3166   // All done.
3167   __ bind(&done);
3168 }
3169
3170
3171 void LCodeGen::DoLoadRoot(LLoadRoot* instr) {
3172   Register result = ToRegister(instr->result());
3173   __ LoadRoot(result, instr->index());
3174 }
3175
3176
3177 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
3178   Register arguments = ToRegister(instr->arguments());
3179   Register result = ToRegister(instr->result());
3180   if (instr->length()->IsConstantOperand() &&
3181       instr->index()->IsConstantOperand()) {
3182     int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
3183     int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
3184     int index = (const_length - const_index) + 1;
3185     __ mov(result, Operand(arguments, index * kPointerSize));
3186   } else {
3187     Register length = ToRegister(instr->length());
3188     Operand index = ToOperand(instr->index());
3189     // There are two words between the frame pointer and the last argument.
3190     // Subtracting from length accounts for one of them add one more.
3191     __ sub(length, index);
3192     __ mov(result, Operand(arguments, length, times_4, kPointerSize));
3193   }
3194 }
3195
3196
3197 void LCodeGen::DoDeferredSIMD128ToTagged(LInstruction* instr,
3198                                          Runtime::FunctionId id) {
3199   // TODO(3095996): Get rid of this. For now, we need to make the
3200   // result register contain a valid pointer because it is already
3201   // contained in the register pointer map.
3202   Register reg = ToRegister(instr->result());
3203   __ Move(reg, Immediate(0));
3204
3205   PushSafepointRegistersScope scope(this);
3206   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3207   __ CallRuntimeSaveDoubles(id);
3208   RecordSafepointWithRegisters(
3209       instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
3210   __ StoreToSafepointRegisterSlot(reg, eax);
3211 }
3212
3213
3214 void LCodeGen::HandleExternalArrayOpRequiresTemp(
3215     LOperand* key,
3216     Representation key_representation,
3217     ElementsKind elements_kind) {
3218   if (ExternalArrayOpRequiresPreScale(key_representation, elements_kind)) {
3219     int pre_shift_size = ElementsKindToShiftSize(elements_kind) -
3220         static_cast<int>(maximal_scale_factor);
3221     if (key_representation.IsSmi()) {
3222       pre_shift_size -= kSmiTagSize;
3223     }
3224     DCHECK(pre_shift_size > 0);
3225     __ shl(ToRegister(key), pre_shift_size);
3226   } else {
3227     __ SmiUntag(ToRegister(key));
3228   }
3229 }
3230
3231
3232 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
3233   ElementsKind elements_kind = instr->elements_kind();
3234   LOperand* key = instr->key();
3235   if (!key->IsConstantOperand() &&
3236       ExternalArrayOpRequiresTemp(
3237           instr->hydrogen()->key()->representation(), elements_kind)) {
3238     HandleExternalArrayOpRequiresTemp(
3239         key, instr->hydrogen()->key()->representation(), elements_kind);
3240   }
3241
3242   Operand operand(BuildFastArrayOperand(
3243       instr->elements(),
3244       key,
3245       instr->hydrogen()->key()->representation(),
3246       elements_kind,
3247       instr->base_offset()));
3248   BuiltinFunctionId op = instr->hydrogen()->op();
3249   if (IsSIMD128LoadStoreOp(op)) {
3250     if (GetSIMD128LoadStoreBytes(op) == 16) {
3251       __ movups(ToSIMD128Register(instr->result()), operand);
3252     } else if (GetSIMD128LoadStoreBytes(op) == 4) {
3253       __ movss(ToSIMD128Register(instr->result()), operand);
3254     } else if (GetSIMD128LoadStoreBytes(op) == 8) {
3255       __ movq(ToSIMD128Register(instr->result()), operand);
3256     } else if (GetSIMD128LoadStoreBytes(op) == 12) {
3257       XMMRegister result(ToSIMD128Register(instr->result()));
3258       XMMRegister xmm_scratch = double_scratch0();
3259       __ movq(result, operand);
3260       Operand operand2(BuildFastArrayOperand(
3261           instr->elements(),
3262           key,
3263           instr->hydrogen()->key()->representation(),
3264           elements_kind,
3265           instr->base_offset() + 8));
3266       __ movss(xmm_scratch, operand2);
3267       __ movlhps(result, xmm_scratch);
3268     }
3269   } else if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
3270       elements_kind == FLOAT32_ELEMENTS) {
3271     XMMRegister result(ToDoubleRegister(instr->result()));
3272     __ movss(result, operand);
3273     __ cvtss2sd(result, result);
3274   } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
3275              elements_kind == FLOAT64_ELEMENTS) {
3276     __ movsd(ToDoubleRegister(instr->result()), operand);
3277   } else if (IsSIMD128ElementsKind(elements_kind)) {
3278     __ movups(ToSIMD128Register(instr->result()), operand);
3279   } else {
3280     Register result(ToRegister(instr->result()));
3281     switch (elements_kind) {
3282       case EXTERNAL_INT8_ELEMENTS:
3283       case INT8_ELEMENTS:
3284         __ movsx_b(result, operand);
3285         break;
3286       case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
3287       case EXTERNAL_UINT8_ELEMENTS:
3288       case UINT8_ELEMENTS:
3289       case UINT8_CLAMPED_ELEMENTS:
3290         __ movzx_b(result, operand);
3291         break;
3292       case EXTERNAL_INT16_ELEMENTS:
3293       case INT16_ELEMENTS:
3294         __ movsx_w(result, operand);
3295         break;
3296       case EXTERNAL_UINT16_ELEMENTS:
3297       case UINT16_ELEMENTS:
3298         __ movzx_w(result, operand);
3299         break;
3300       case EXTERNAL_INT32_ELEMENTS:
3301       case INT32_ELEMENTS:
3302         __ mov(result, operand);
3303         break;
3304       case EXTERNAL_UINT32_ELEMENTS:
3305       case UINT32_ELEMENTS:
3306         __ mov(result, operand);
3307         if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3308           __ test(result, Operand(result));
3309           DeoptimizeIf(negative, instr, "negative value");
3310         }
3311         break;
3312       case EXTERNAL_FLOAT32_ELEMENTS:
3313       case EXTERNAL_FLOAT64_ELEMENTS:
3314       case EXTERNAL_FLOAT32x4_ELEMENTS:
3315       case EXTERNAL_FLOAT64x2_ELEMENTS:
3316       case EXTERNAL_INT32x4_ELEMENTS:
3317       case FLOAT32_ELEMENTS:
3318       case FLOAT64_ELEMENTS:
3319       case FLOAT32x4_ELEMENTS:
3320       case FLOAT64x2_ELEMENTS:
3321       case INT32x4_ELEMENTS:
3322       case FAST_SMI_ELEMENTS:
3323       case FAST_ELEMENTS:
3324       case FAST_DOUBLE_ELEMENTS:
3325       case FAST_HOLEY_SMI_ELEMENTS:
3326       case FAST_HOLEY_ELEMENTS:
3327       case FAST_HOLEY_DOUBLE_ELEMENTS:
3328       case DICTIONARY_ELEMENTS:
3329       case SLOPPY_ARGUMENTS_ELEMENTS:
3330         UNREACHABLE();
3331         break;
3332     }
3333   }
3334 }
3335
3336
3337 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
3338   if (instr->hydrogen()->RequiresHoleCheck()) {
3339     Operand hole_check_operand = BuildFastArrayOperand(
3340         instr->elements(), instr->key(),
3341         instr->hydrogen()->key()->representation(),
3342         FAST_DOUBLE_ELEMENTS,
3343         instr->base_offset() + sizeof(kHoleNanLower32));
3344     __ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
3345     DeoptimizeIf(equal, instr, "hole");
3346   }
3347
3348   Operand double_load_operand = BuildFastArrayOperand(
3349       instr->elements(),
3350       instr->key(),
3351       instr->hydrogen()->key()->representation(),
3352       FAST_DOUBLE_ELEMENTS,
3353       instr->base_offset());
3354   XMMRegister result = ToDoubleRegister(instr->result());
3355   __ movsd(result, double_load_operand);
3356 }
3357
3358
3359 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3360   Register result = ToRegister(instr->result());
3361
3362   // Load the result.
3363   __ mov(result,
3364          BuildFastArrayOperand(instr->elements(), instr->key(),
3365                                instr->hydrogen()->key()->representation(),
3366                                FAST_ELEMENTS, instr->base_offset()));
3367
3368   // Check for the hole value.
3369   if (instr->hydrogen()->RequiresHoleCheck()) {
3370     if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
3371       __ test(result, Immediate(kSmiTagMask));
3372       DeoptimizeIf(not_equal, instr, "not a Smi");
3373     } else {
3374       __ cmp(result, factory()->the_hole_value());
3375       DeoptimizeIf(equal, instr, "hole");
3376     }
3377   }
3378 }
3379
3380
3381 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3382   if (instr->is_typed_elements()) {
3383     DoLoadKeyedExternalArray(instr);
3384   } else if (instr->hydrogen()->representation().IsDouble()) {
3385     DoLoadKeyedFixedDoubleArray(instr);
3386   } else {
3387     DoLoadKeyedFixedArray(instr);
3388   }
3389 }
3390
3391
3392 Operand LCodeGen::BuildFastArrayOperand(
3393     LOperand* elements_pointer,
3394     LOperand* key,
3395     Representation key_representation,
3396     ElementsKind elements_kind,
3397     uint32_t base_offset) {
3398   Register elements_pointer_reg = ToRegister(elements_pointer);
3399   int element_shift_size = ElementsKindToShiftSize(elements_kind);
3400   int shift_size = element_shift_size;
3401   if (key->IsConstantOperand()) {
3402     int constant_value = ToInteger32(LConstantOperand::cast(key));
3403     if (constant_value & 0xF0000000) {
3404       Abort(kArrayIndexConstantValueTooBig);
3405     }
3406     return Operand(elements_pointer_reg,
3407                    ((constant_value) << shift_size)
3408                        + base_offset);
3409   } else {
3410     if (ExternalArrayOpRequiresPreScale(key_representation, elements_kind)) {
3411       // Make sure the key is pre-scaled against maximal_scale_factor.
3412       shift_size = static_cast<int>(maximal_scale_factor);
3413     } else if (key_representation.IsSmi() && (shift_size >= 1)) {
3414       // Take the tag bit into account while computing the shift size.
3415       shift_size -= kSmiTagSize;
3416     }
3417     ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
3418     return Operand(elements_pointer_reg,
3419                    ToRegister(key),
3420                    scale_factor,
3421                    base_offset);
3422   }
3423 }
3424
3425
3426 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
3427   DCHECK(ToRegister(instr->context()).is(esi));
3428   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
3429   DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
3430
3431   if (FLAG_vector_ics) {
3432     EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
3433   }
3434
3435   Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
3436   CallCode(ic, RelocInfo::CODE_TARGET, instr);
3437 }
3438
3439
3440 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
3441   Register result = ToRegister(instr->result());
3442
3443   if (instr->hydrogen()->from_inlined()) {
3444     __ lea(result, Operand(esp, -2 * kPointerSize));
3445   } else {
3446     // Check for arguments adapter frame.
3447     Label done, adapted;
3448     __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3449     __ mov(result, Operand(result, StandardFrameConstants::kContextOffset));
3450     __ cmp(Operand(result),
3451            Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3452     __ j(equal, &adapted, Label::kNear);
3453
3454     // No arguments adaptor frame.
3455     __ mov(result, Operand(ebp));
3456     __ jmp(&done, Label::kNear);
3457
3458     // Arguments adaptor frame present.
3459     __ bind(&adapted);
3460     __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3461
3462     // Result is the frame pointer for the frame if not adapted and for the real
3463     // frame below the adaptor frame if adapted.
3464     __ bind(&done);
3465   }
3466 }
3467
3468
3469 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
3470   Operand elem = ToOperand(instr->elements());
3471   Register result = ToRegister(instr->result());
3472
3473   Label done;
3474
3475   // If no arguments adaptor frame the number of arguments is fixed.
3476   __ cmp(ebp, elem);
3477   __ mov(result, Immediate(scope()->num_parameters()));
3478   __ j(equal, &done, Label::kNear);
3479
3480   // Arguments adaptor frame present. Get argument length from there.
3481   __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3482   __ mov(result, Operand(result,
3483                          ArgumentsAdaptorFrameConstants::kLengthOffset));
3484   __ SmiUntag(result);
3485
3486   // Argument length is in result register.
3487   __ bind(&done);
3488 }
3489
3490
3491 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
3492   Register receiver = ToRegister(instr->receiver());
3493   Register function = ToRegister(instr->function());
3494
3495   // If the receiver is null or undefined, we have to pass the global
3496   // object as a receiver to normal functions. Values have to be
3497   // passed unchanged to builtins and strict-mode functions.
3498   Label receiver_ok, global_object;
3499   Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
3500   Register scratch = ToRegister(instr->temp());
3501
3502   if (!instr->hydrogen()->known_function()) {
3503     // Do not transform the receiver to object for strict mode
3504     // functions.
3505     __ mov(scratch,
3506            FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
3507     __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset),
3508               1 << SharedFunctionInfo::kStrictModeBitWithinByte);
3509     __ j(not_equal, &receiver_ok, dist);
3510
3511     // Do not transform the receiver to object for builtins.
3512     __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
3513               1 << SharedFunctionInfo::kNativeBitWithinByte);
3514     __ j(not_equal, &receiver_ok, dist);
3515   }
3516
3517   // Normal function. Replace undefined or null with global receiver.
3518   __ cmp(receiver, factory()->null_value());
3519   __ j(equal, &global_object, Label::kNear);
3520   __ cmp(receiver, factory()->undefined_value());
3521   __ j(equal, &global_object, Label::kNear);
3522
3523   // The receiver should be a JS object.
3524   __ test(receiver, Immediate(kSmiTagMask));
3525   DeoptimizeIf(equal, instr, "Smi");
3526   __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
3527   DeoptimizeIf(below, instr, "not a JavaScript object");
3528
3529   __ jmp(&receiver_ok, Label::kNear);
3530   __ bind(&global_object);
3531   __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset));
3532   const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
3533   __ mov(receiver, Operand(receiver, global_offset));
3534   const int proxy_offset = GlobalObject::kGlobalProxyOffset;
3535   __ mov(receiver, FieldOperand(receiver, proxy_offset));
3536   __ bind(&receiver_ok);
3537 }
3538
3539
3540 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3541   Register receiver = ToRegister(instr->receiver());
3542   Register function = ToRegister(instr->function());
3543   Register length = ToRegister(instr->length());
3544   Register elements = ToRegister(instr->elements());
3545   DCHECK(receiver.is(eax));  // Used for parameter count.
3546   DCHECK(function.is(edi));  // Required by InvokeFunction.
3547   DCHECK(ToRegister(instr->result()).is(eax));
3548
3549   // Copy the arguments to this function possibly from the
3550   // adaptor frame below it.
3551   const uint32_t kArgumentsLimit = 1 * KB;
3552   __ cmp(length, kArgumentsLimit);
3553   DeoptimizeIf(above, instr, "too many arguments");
3554
3555   __ push(receiver);
3556   __ mov(receiver, length);
3557
3558   // Loop through the arguments pushing them onto the execution
3559   // stack.
3560   Label invoke, loop;
3561   // length is a small non-negative integer, due to the test above.
3562   __ test(length, Operand(length));
3563   __ j(zero, &invoke, Label::kNear);
3564   __ bind(&loop);
3565   __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
3566   __ dec(length);
3567   __ j(not_zero, &loop);
3568
3569   // Invoke the function.
3570   __ bind(&invoke);
3571   DCHECK(instr->HasPointerMap());
3572   LPointerMap* pointers = instr->pointer_map();
3573   SafepointGenerator safepoint_generator(
3574       this, pointers, Safepoint::kLazyDeopt);
3575   ParameterCount actual(eax);
3576   __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator);
3577 }
3578
3579
3580 void LCodeGen::DoDebugBreak(LDebugBreak* instr) {
3581   __ int3();
3582 }
3583
3584
3585 void LCodeGen::DoPushArgument(LPushArgument* instr) {
3586   LOperand* argument = instr->value();
3587   EmitPushTaggedOperand(argument);
3588 }
3589
3590
3591 void LCodeGen::DoDrop(LDrop* instr) {
3592   __ Drop(instr->count());
3593 }
3594
3595
3596 void LCodeGen::DoThisFunction(LThisFunction* instr) {
3597   Register result = ToRegister(instr->result());
3598   __ mov(result, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
3599 }
3600
3601
3602 void LCodeGen::DoContext(LContext* instr) {
3603   Register result = ToRegister(instr->result());
3604   if (info()->IsOptimizing()) {
3605     __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
3606   } else {
3607     // If there is no frame, the context must be in esi.
3608     DCHECK(result.is(esi));
3609   }
3610 }
3611
3612
3613 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
3614   DCHECK(ToRegister(instr->context()).is(esi));
3615   __ push(esi);  // The context is the first argument.
3616   __ push(Immediate(instr->hydrogen()->pairs()));
3617   __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags())));
3618   CallRuntime(Runtime::kDeclareGlobals, 3, instr);
3619 }
3620
3621
3622 void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
3623                                  int formal_parameter_count,
3624                                  int arity,
3625                                  LInstruction* instr,
3626                                  EDIState edi_state) {
3627   bool dont_adapt_arguments =
3628       formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3629   bool can_invoke_directly =
3630       dont_adapt_arguments || formal_parameter_count == arity;
3631
3632   if (can_invoke_directly) {
3633     if (edi_state == EDI_UNINITIALIZED) {
3634       __ LoadHeapObject(edi, function);
3635     }
3636
3637     // Change context.
3638     __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
3639
3640     // Set eax to arguments count if adaption is not needed. Assumes that eax
3641     // is available to write to at this point.
3642     if (dont_adapt_arguments) {
3643       __ mov(eax, arity);
3644     }
3645
3646     // Invoke function directly.
3647     if (function.is_identical_to(info()->closure())) {
3648       __ CallSelf();
3649     } else {
3650       __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
3651     }
3652     RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3653   } else {
3654     // We need to adapt arguments.
3655     LPointerMap* pointers = instr->pointer_map();
3656     SafepointGenerator generator(
3657         this, pointers, Safepoint::kLazyDeopt);
3658     ParameterCount count(arity);
3659     ParameterCount expected(formal_parameter_count);
3660     __ InvokeFunction(function, expected, count, CALL_FUNCTION, generator);
3661   }
3662 }
3663
3664
3665 void LCodeGen::DoTailCallThroughMegamorphicCache(
3666     LTailCallThroughMegamorphicCache* instr) {
3667   Register receiver = ToRegister(instr->receiver());
3668   Register name = ToRegister(instr->name());
3669   DCHECK(receiver.is(LoadDescriptor::ReceiverRegister()));
3670   DCHECK(name.is(LoadDescriptor::NameRegister()));
3671
3672   Register scratch = ebx;
3673   Register extra = eax;
3674   DCHECK(!scratch.is(receiver) && !scratch.is(name));
3675   DCHECK(!extra.is(receiver) && !extra.is(name));
3676
3677   // Important for the tail-call.
3678   bool must_teardown_frame = NeedsEagerFrame();
3679
3680   // The probe will tail call to a handler if found.
3681   isolate()->stub_cache()->GenerateProbe(masm(), instr->hydrogen()->flags(),
3682                                          must_teardown_frame, receiver, name,
3683                                          scratch, extra);
3684
3685   // Tail call to miss if we ended up here.
3686   if (must_teardown_frame) __ leave();
3687   LoadIC::GenerateMiss(masm());
3688 }
3689
3690
3691 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
3692   DCHECK(ToRegister(instr->result()).is(eax));
3693
3694   LPointerMap* pointers = instr->pointer_map();
3695   SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3696
3697   if (instr->target()->IsConstantOperand()) {
3698     LConstantOperand* target = LConstantOperand::cast(instr->target());
3699     Handle<Code> code = Handle<Code>::cast(ToHandle(target));
3700     generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET));
3701     __ call(code, RelocInfo::CODE_TARGET);
3702   } else {
3703     DCHECK(instr->target()->IsRegister());
3704     Register target = ToRegister(instr->target());
3705     generator.BeforeCall(__ CallSize(Operand(target)));
3706     __ add(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
3707     __ call(target);
3708   }
3709   generator.AfterCall();
3710 }
3711
3712
3713 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) {
3714   DCHECK(ToRegister(instr->function()).is(edi));
3715   DCHECK(ToRegister(instr->result()).is(eax));
3716
3717   if (instr->hydrogen()->pass_argument_count()) {
3718     __ mov(eax, instr->arity());
3719   }
3720
3721   // Change context.
3722   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
3723
3724   bool is_self_call = false;
3725   if (instr->hydrogen()->function()->IsConstant()) {
3726     HConstant* fun_const = HConstant::cast(instr->hydrogen()->function());
3727     Handle<JSFunction> jsfun =
3728       Handle<JSFunction>::cast(fun_const->handle(isolate()));
3729     is_self_call = jsfun.is_identical_to(info()->closure());
3730   }
3731
3732   if (is_self_call) {
3733     __ CallSelf();
3734   } else {
3735     __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
3736   }
3737
3738   RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3739 }
3740
3741
3742 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3743   Register input_reg = ToRegister(instr->value());
3744   __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3745          factory()->heap_number_map());
3746   DeoptimizeIf(not_equal, instr, "not a heap number");
3747
3748   Label slow, allocated, done;
3749   Register tmp = input_reg.is(eax) ? ecx : eax;
3750   Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx;
3751
3752   // Preserve the value of all registers.
3753   PushSafepointRegistersScope scope(this);
3754
3755   __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3756   // Check the sign of the argument. If the argument is positive, just
3757   // return it. We do not need to patch the stack since |input| and
3758   // |result| are the same register and |input| will be restored
3759   // unchanged by popping safepoint registers.
3760   __ test(tmp, Immediate(HeapNumber::kSignMask));
3761   __ j(zero, &done, Label::kNear);
3762
3763   __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow);
3764   __ jmp(&allocated, Label::kNear);
3765
3766   // Slow case: Call the runtime system to do the number allocation.
3767   __ bind(&slow);
3768   CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0,
3769                           instr, instr->context());
3770   // Set the pointer to the new heap number in tmp.
3771   if (!tmp.is(eax)) __ mov(tmp, eax);
3772   // Restore input_reg after call to runtime.
3773   __ LoadFromSafepointRegisterSlot(input_reg, input_reg);
3774
3775   __ bind(&allocated);
3776   __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3777   __ and_(tmp2, ~HeapNumber::kSignMask);
3778   __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2);
3779   __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
3780   __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2);
3781   __ StoreToSafepointRegisterSlot(input_reg, tmp);
3782
3783   __ bind(&done);
3784 }
3785
3786
3787 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3788   Register input_reg = ToRegister(instr->value());
3789   __ test(input_reg, Operand(input_reg));
3790   Label is_positive;
3791   __ j(not_sign, &is_positive, Label::kNear);
3792   __ neg(input_reg);  // Sets flags.
3793   DeoptimizeIf(negative, instr, "overflow");
3794   __ bind(&is_positive);
3795 }
3796
3797
3798 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3799   // Class for deferred case.
3800   class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode {
3801    public:
3802     DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
3803                                     LMathAbs* instr)
3804         : LDeferredCode(codegen), instr_(instr) { }
3805     virtual void Generate() OVERRIDE {
3806       codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
3807     }
3808     virtual LInstruction* instr() OVERRIDE { return instr_; }
3809    private:
3810     LMathAbs* instr_;
3811   };
3812
3813   DCHECK(instr->value()->Equals(instr->result()));
3814   Representation r = instr->hydrogen()->value()->representation();
3815
3816   if (r.IsDouble()) {
3817     XMMRegister scratch = double_scratch0();
3818     XMMRegister input_reg = ToDoubleRegister(instr->value());
3819     __ xorps(scratch, scratch);
3820     __ subsd(scratch, input_reg);
3821     __ andps(input_reg, scratch);
3822   } else if (r.IsSmiOrInteger32()) {
3823     EmitIntegerMathAbs(instr);
3824   } else {  // Tagged case.
3825     DeferredMathAbsTaggedHeapNumber* deferred =
3826         new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr);
3827     Register input_reg = ToRegister(instr->value());
3828     // Smi check.
3829     __ JumpIfNotSmi(input_reg, deferred->entry());
3830     EmitIntegerMathAbs(instr);
3831     __ bind(deferred->exit());
3832   }
3833 }
3834
3835
3836 void LCodeGen::DoMathFloor(LMathFloor* instr) {
3837   XMMRegister xmm_scratch = double_scratch0();
3838   Register output_reg = ToRegister(instr->result());
3839   XMMRegister input_reg = ToDoubleRegister(instr->value());
3840
3841   if (CpuFeatures::IsSupported(SSE4_1)) {
3842     CpuFeatureScope scope(masm(), SSE4_1);
3843     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3844       // Deoptimize on negative zero.
3845       Label non_zero;
3846       __ xorps(xmm_scratch, xmm_scratch);  // Zero the register.
3847       __ ucomisd(input_reg, xmm_scratch);
3848       __ j(not_equal, &non_zero, Label::kNear);
3849       __ movmskpd(output_reg, input_reg);
3850       __ test(output_reg, Immediate(1));
3851       DeoptimizeIf(not_zero, instr, "minus zero");
3852       __ bind(&non_zero);
3853     }
3854     __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
3855     __ cvttsd2si(output_reg, Operand(xmm_scratch));
3856     // Overflow is signalled with minint.
3857     __ cmp(output_reg, 0x1);
3858     DeoptimizeIf(overflow, instr, "overflow");
3859   } else {
3860     Label negative_sign, done;
3861     // Deoptimize on unordered.
3862     __ xorps(xmm_scratch, xmm_scratch);  // Zero the register.
3863     __ ucomisd(input_reg, xmm_scratch);
3864     DeoptimizeIf(parity_even, instr, "NaN");
3865     __ j(below, &negative_sign, Label::kNear);
3866
3867     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3868       // Check for negative zero.
3869       Label positive_sign;
3870       __ j(above, &positive_sign, Label::kNear);
3871       __ movmskpd(output_reg, input_reg);
3872       __ test(output_reg, Immediate(1));
3873       DeoptimizeIf(not_zero, instr, "minus zero");
3874       __ Move(output_reg, Immediate(0));
3875       __ jmp(&done, Label::kNear);
3876       __ bind(&positive_sign);
3877     }
3878
3879     // Use truncating instruction (OK because input is positive).
3880     __ cvttsd2si(output_reg, Operand(input_reg));
3881     // Overflow is signalled with minint.
3882     __ cmp(output_reg, 0x1);
3883     DeoptimizeIf(overflow, instr, "overflow");
3884     __ jmp(&done, Label::kNear);
3885
3886     // Non-zero negative reaches here.
3887     __ bind(&negative_sign);
3888     // Truncate, then compare and compensate.
3889     __ cvttsd2si(output_reg, Operand(input_reg));
3890     __ Cvtsi2sd(xmm_scratch, output_reg);
3891     __ ucomisd(input_reg, xmm_scratch);
3892     __ j(equal, &done, Label::kNear);
3893     __ sub(output_reg, Immediate(1));
3894     DeoptimizeIf(overflow, instr, "overflow");
3895
3896     __ bind(&done);
3897   }
3898 }
3899
3900
3901 void LCodeGen::DoMathRound(LMathRound* instr) {
3902   Register output_reg = ToRegister(instr->result());
3903   XMMRegister input_reg = ToDoubleRegister(instr->value());
3904   XMMRegister xmm_scratch = double_scratch0();
3905   XMMRegister input_temp = ToDoubleRegister(instr->temp());
3906   ExternalReference one_half = ExternalReference::address_of_one_half();
3907   ExternalReference minus_one_half =
3908       ExternalReference::address_of_minus_one_half();
3909
3910   Label done, round_to_zero, below_one_half, do_not_compensate;
3911   Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
3912
3913   __ movsd(xmm_scratch, Operand::StaticVariable(one_half));
3914   __ ucomisd(xmm_scratch, input_reg);
3915   __ j(above, &below_one_half, Label::kNear);
3916
3917   // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
3918   __ addsd(xmm_scratch, input_reg);
3919   __ cvttsd2si(output_reg, Operand(xmm_scratch));
3920   // Overflow is signalled with minint.
3921   __ cmp(output_reg, 0x1);
3922   DeoptimizeIf(overflow, instr, "overflow");
3923   __ jmp(&done, dist);
3924
3925   __ bind(&below_one_half);
3926   __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half));
3927   __ ucomisd(xmm_scratch, input_reg);
3928   __ j(below_equal, &round_to_zero, Label::kNear);
3929
3930   // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
3931   // compare and compensate.
3932   __ movaps(input_temp, input_reg);  // Do not alter input_reg.
3933   __ subsd(input_temp, xmm_scratch);
3934   __ cvttsd2si(output_reg, Operand(input_temp));
3935   // Catch minint due to overflow, and to prevent overflow when compensating.
3936   __ cmp(output_reg, 0x1);
3937   DeoptimizeIf(overflow, instr, "overflow");
3938
3939   __ Cvtsi2sd(xmm_scratch, output_reg);
3940   __ ucomisd(xmm_scratch, input_temp);
3941   __ j(equal, &done, dist);
3942   __ sub(output_reg, Immediate(1));
3943   // No overflow because we already ruled out minint.
3944   __ jmp(&done, dist);
3945
3946   __ bind(&round_to_zero);
3947   // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
3948   // we can ignore the difference between a result of -0 and +0.
3949   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3950     // If the sign is positive, we return +0.
3951     __ movmskpd(output_reg, input_reg);
3952     __ test(output_reg, Immediate(1));
3953     DeoptimizeIf(not_zero, instr, "minus zero");
3954   }
3955   __ Move(output_reg, Immediate(0));
3956   __ bind(&done);
3957 }
3958
3959
3960 void LCodeGen::DoMathFround(LMathFround* instr) {
3961   XMMRegister input_reg = ToDoubleRegister(instr->value());
3962   XMMRegister output_reg = ToDoubleRegister(instr->result());
3963   __ cvtsd2ss(output_reg, input_reg);
3964   __ cvtss2sd(output_reg, output_reg);
3965 }
3966
3967
3968 void LCodeGen::DoMathSqrt(LMathSqrt* instr) {
3969   Operand input = ToOperand(instr->value());
3970   XMMRegister output = ToDoubleRegister(instr->result());
3971   __ sqrtsd(output, input);
3972 }
3973
3974
3975 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
3976   XMMRegister xmm_scratch = double_scratch0();
3977   XMMRegister input_reg = ToDoubleRegister(instr->value());
3978   Register scratch = ToRegister(instr->temp());
3979   DCHECK(ToDoubleRegister(instr->result()).is(input_reg));
3980
3981   // Note that according to ECMA-262 15.8.2.13:
3982   // Math.pow(-Infinity, 0.5) == Infinity
3983   // Math.sqrt(-Infinity) == NaN
3984   Label done, sqrt;
3985   // Check base for -Infinity.  According to IEEE-754, single-precision
3986   // -Infinity has the highest 9 bits set and the lowest 23 bits cleared.
3987   __ mov(scratch, 0xFF800000);
3988   __ movd(xmm_scratch, scratch);
3989   __ cvtss2sd(xmm_scratch, xmm_scratch);
3990   __ ucomisd(input_reg, xmm_scratch);
3991   // Comparing -Infinity with NaN results in "unordered", which sets the
3992   // zero flag as if both were equal.  However, it also sets the carry flag.
3993   __ j(not_equal, &sqrt, Label::kNear);
3994   __ j(carry, &sqrt, Label::kNear);
3995   // If input is -Infinity, return Infinity.
3996   __ xorps(input_reg, input_reg);
3997   __ subsd(input_reg, xmm_scratch);
3998   __ jmp(&done, Label::kNear);
3999
4000   // Square root.
4001   __ bind(&sqrt);
4002   __ xorps(xmm_scratch, xmm_scratch);
4003   __ addsd(input_reg, xmm_scratch);  // Convert -0 to +0.
4004   __ sqrtsd(input_reg, input_reg);
4005   __ bind(&done);
4006 }
4007
4008
4009 void LCodeGen::DoPower(LPower* instr) {
4010   Representation exponent_type = instr->hydrogen()->right()->representation();
4011   // Having marked this as a call, we can use any registers.
4012   // Just make sure that the input/output registers are the expected ones.
4013   Register tagged_exponent = MathPowTaggedDescriptor::exponent();
4014   DCHECK(!instr->right()->IsDoubleRegister() ||
4015          ToDoubleRegister(instr->right()).is(xmm1));
4016   DCHECK(!instr->right()->IsRegister() ||
4017          ToRegister(instr->right()).is(tagged_exponent));
4018   DCHECK(ToDoubleRegister(instr->left()).is(xmm2));
4019   DCHECK(ToDoubleRegister(instr->result()).is(xmm3));
4020
4021   if (exponent_type.IsSmi()) {
4022     MathPowStub stub(isolate(), MathPowStub::TAGGED);
4023     __ CallStub(&stub);
4024   } else if (exponent_type.IsTagged()) {
4025     Label no_deopt;
4026     __ JumpIfSmi(tagged_exponent, &no_deopt);
4027     DCHECK(!ecx.is(tagged_exponent));
4028     __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, ecx);
4029     DeoptimizeIf(not_equal, instr, "not a heap number");
4030     __ bind(&no_deopt);
4031     MathPowStub stub(isolate(), MathPowStub::TAGGED);
4032     __ CallStub(&stub);
4033   } else if (exponent_type.IsInteger32()) {
4034     MathPowStub stub(isolate(), MathPowStub::INTEGER);
4035     __ CallStub(&stub);
4036   } else {
4037     DCHECK(exponent_type.IsDouble());
4038     MathPowStub stub(isolate(), MathPowStub::DOUBLE);
4039     __ CallStub(&stub);
4040   }
4041 }
4042
4043
4044 void LCodeGen::DoMathLog(LMathLog* instr) {
4045   DCHECK(instr->value()->Equals(instr->result()));
4046   XMMRegister input_reg = ToDoubleRegister(instr->value());
4047   XMMRegister xmm_scratch = double_scratch0();
4048   Label positive, done, zero;
4049   __ xorps(xmm_scratch, xmm_scratch);
4050   __ ucomisd(input_reg, xmm_scratch);
4051   __ j(above, &positive, Label::kNear);
4052   __ j(not_carry, &zero, Label::kNear);
4053   ExternalReference nan =
4054       ExternalReference::address_of_canonical_non_hole_nan();
4055   __ movsd(input_reg, Operand::StaticVariable(nan));
4056   __ jmp(&done, Label::kNear);
4057   __ bind(&zero);
4058   ExternalReference ninf =
4059       ExternalReference::address_of_negative_infinity();
4060   __ movsd(input_reg, Operand::StaticVariable(ninf));
4061   __ jmp(&done, Label::kNear);
4062   __ bind(&positive);
4063   __ fldln2();
4064   __ sub(Operand(esp), Immediate(kDoubleSize));
4065   __ movsd(Operand(esp, 0), input_reg);
4066   __ fld_d(Operand(esp, 0));
4067   __ fyl2x();
4068   __ fstp_d(Operand(esp, 0));
4069   __ movsd(input_reg, Operand(esp, 0));
4070   __ add(Operand(esp), Immediate(kDoubleSize));
4071   __ bind(&done);
4072 }
4073
4074
4075 void LCodeGen::DoMathClz32(LMathClz32* instr) {
4076   Register input = ToRegister(instr->value());
4077   Register result = ToRegister(instr->result());
4078   Label not_zero_input;
4079   __ bsr(result, input);
4080
4081   __ j(not_zero, &not_zero_input);
4082   __ Move(result, Immediate(63));  // 63^31 == 32
4083
4084   __ bind(&not_zero_input);
4085   __ xor_(result, Immediate(31));  // for x in [0..31], 31^x == 31-x.
4086 }
4087
4088
4089 void LCodeGen::DoMathExp(LMathExp* instr) {
4090   XMMRegister input = ToDoubleRegister(instr->value());
4091   XMMRegister result = ToDoubleRegister(instr->result());
4092   XMMRegister temp0 = double_scratch0();
4093   Register temp1 = ToRegister(instr->temp1());
4094   Register temp2 = ToRegister(instr->temp2());
4095
4096   MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2);
4097 }
4098
4099
4100 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
4101   DCHECK(ToRegister(instr->context()).is(esi));
4102   DCHECK(ToRegister(instr->function()).is(edi));
4103   DCHECK(instr->HasPointerMap());
4104
4105   Handle<JSFunction> known_function = instr->hydrogen()->known_function();
4106   if (known_function.is_null()) {
4107     LPointerMap* pointers = instr->pointer_map();
4108     SafepointGenerator generator(
4109         this, pointers, Safepoint::kLazyDeopt);
4110     ParameterCount count(instr->arity());
4111     __ InvokeFunction(edi, count, CALL_FUNCTION, generator);
4112   } else {
4113     CallKnownFunction(known_function,
4114                       instr->hydrogen()->formal_parameter_count(),
4115                       instr->arity(),
4116                       instr,
4117                       EDI_CONTAINS_TARGET);
4118   }
4119 }
4120
4121
4122 void LCodeGen::DoCallFunction(LCallFunction* instr) {
4123   DCHECK(ToRegister(instr->context()).is(esi));
4124   DCHECK(ToRegister(instr->function()).is(edi));
4125   DCHECK(ToRegister(instr->result()).is(eax));
4126
4127   int arity = instr->arity();
4128   CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags());
4129   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4130 }
4131
4132
4133 void LCodeGen::DoCallNew(LCallNew* instr) {
4134   DCHECK(ToRegister(instr->context()).is(esi));
4135   DCHECK(ToRegister(instr->constructor()).is(edi));
4136   DCHECK(ToRegister(instr->result()).is(eax));
4137
4138   // No cell in ebx for construct type feedback in optimized code
4139   __ mov(ebx, isolate()->factory()->undefined_value());
4140   CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
4141   __ Move(eax, Immediate(instr->arity()));
4142   CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4143 }
4144
4145
4146 void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
4147   DCHECK(ToRegister(instr->context()).is(esi));
4148   DCHECK(ToRegister(instr->constructor()).is(edi));
4149   DCHECK(ToRegister(instr->result()).is(eax));
4150
4151   __ Move(eax, Immediate(instr->arity()));
4152   __ mov(ebx, isolate()->factory()->undefined_value());
4153   ElementsKind kind = instr->hydrogen()->elements_kind();
4154   AllocationSiteOverrideMode override_mode =
4155       (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
4156           ? DISABLE_ALLOCATION_SITES
4157           : DONT_OVERRIDE;
4158
4159   if (instr->arity() == 0) {
4160     ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode);
4161     CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4162   } else if (instr->arity() == 1) {
4163     Label done;
4164     if (IsFastPackedElementsKind(kind)) {
4165       Label packed_case;
4166       // We might need a change here
4167       // look at the first argument
4168       __ mov(ecx, Operand(esp, 0));
4169       __ test(ecx, ecx);
4170       __ j(zero, &packed_case, Label::kNear);
4171
4172       ElementsKind holey_kind = GetHoleyElementsKind(kind);
4173       ArraySingleArgumentConstructorStub stub(isolate(),
4174                                               holey_kind,
4175                                               override_mode);
4176       CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4177       __ jmp(&done, Label::kNear);
4178       __ bind(&packed_case);
4179     }
4180
4181     ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode);
4182     CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4183     __ bind(&done);
4184   } else {
4185     ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
4186     CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4187   }
4188 }
4189
4190
4191 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
4192   DCHECK(ToRegister(instr->context()).is(esi));
4193   CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles());
4194 }
4195
4196
4197 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
4198   Register function = ToRegister(instr->function());
4199   Register code_object = ToRegister(instr->code_object());
4200   __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize));
4201   __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object);
4202 }
4203
4204
4205 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
4206   Register result = ToRegister(instr->result());
4207   Register base = ToRegister(instr->base_object());
4208   if (instr->offset()->IsConstantOperand()) {
4209     LConstantOperand* offset = LConstantOperand::cast(instr->offset());
4210     __ lea(result, Operand(base, ToInteger32(offset)));
4211   } else {
4212     Register offset = ToRegister(instr->offset());
4213     __ lea(result, Operand(base, offset, times_1, 0));
4214   }
4215 }
4216
4217
4218 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
4219   Representation representation = instr->hydrogen()->field_representation();
4220
4221   HObjectAccess access = instr->hydrogen()->access();
4222   int offset = access.offset();
4223
4224   if (access.IsExternalMemory()) {
4225     DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4226     MemOperand operand = instr->object()->IsConstantOperand()
4227         ? MemOperand::StaticVariable(
4228             ToExternalReference(LConstantOperand::cast(instr->object())))
4229         : MemOperand(ToRegister(instr->object()), offset);
4230     if (instr->value()->IsConstantOperand()) {
4231       LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4232       __ mov(operand, Immediate(ToInteger32(operand_value)));
4233     } else {
4234       Register value = ToRegister(instr->value());
4235       __ Store(value, operand, representation);
4236     }
4237     return;
4238   }
4239
4240   Register object = ToRegister(instr->object());
4241   __ AssertNotSmi(object);
4242
4243   DCHECK(!representation.IsSmi() ||
4244          !instr->value()->IsConstantOperand() ||
4245          IsSmi(LConstantOperand::cast(instr->value())));
4246   if (representation.IsDouble()) {
4247     DCHECK(access.IsInobject());
4248     DCHECK(!instr->hydrogen()->has_transition());
4249     DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4250     XMMRegister value = ToDoubleRegister(instr->value());
4251     __ movsd(FieldOperand(object, offset), value);
4252     return;
4253   }
4254
4255   if (instr->hydrogen()->has_transition()) {
4256     Handle<Map> transition = instr->hydrogen()->transition_map();
4257     AddDeprecationDependency(transition);
4258     __ mov(FieldOperand(object, HeapObject::kMapOffset), transition);
4259     if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
4260       Register temp = ToRegister(instr->temp());
4261       Register temp_map = ToRegister(instr->temp_map());
4262       // Update the write barrier for the map field.
4263       __ RecordWriteForMap(object, transition, temp_map, temp, kSaveFPRegs);
4264     }
4265   }
4266
4267   // Do the store.
4268   Register write_register = object;
4269   if (!access.IsInobject()) {
4270     write_register = ToRegister(instr->temp());
4271     __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
4272   }
4273
4274   MemOperand operand = FieldOperand(write_register, offset);
4275   if (instr->value()->IsConstantOperand()) {
4276     LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4277     if (operand_value->IsRegister()) {
4278       Register value = ToRegister(operand_value);
4279       __ Store(value, operand, representation);
4280     } else if (representation.IsInteger32()) {
4281       Immediate immediate = ToImmediate(operand_value, representation);
4282       DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4283       __ mov(operand, immediate);
4284     } else {
4285       Handle<Object> handle_value = ToHandle(operand_value);
4286       DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4287       __ mov(operand, handle_value);
4288     }
4289   } else {
4290     Register value = ToRegister(instr->value());
4291     __ Store(value, operand, representation);
4292   }
4293
4294   if (instr->hydrogen()->NeedsWriteBarrier()) {
4295     Register value = ToRegister(instr->value());
4296     Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object;
4297     // Update the write barrier for the object for in-object properties.
4298     __ RecordWriteField(write_register,
4299                         offset,
4300                         value,
4301                         temp,
4302                         kSaveFPRegs,
4303                         EMIT_REMEMBERED_SET,
4304                         instr->hydrogen()->SmiCheckForWriteBarrier(),
4305                         instr->hydrogen()->PointersToHereCheckForValue());
4306   }
4307 }
4308
4309
4310 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
4311   DCHECK(ToRegister(instr->context()).is(esi));
4312   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
4313   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
4314
4315   __ mov(StoreDescriptor::NameRegister(), instr->name());
4316   Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
4317   CallCode(ic, RelocInfo::CODE_TARGET, instr);
4318 }
4319
4320
4321 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
4322   Condition cc = instr->hydrogen()->allow_equality() ? above : above_equal;
4323   BuiltinFunctionId op = instr->hydrogen()->op();
4324   if (IsSIMD128LoadStoreOp(op)) {
4325     cc = above;
4326     Register index_in_bytes = ToRegister(instr->temp0());
4327     Register length_in_bytes = ToRegister(instr->temp1());
4328     if (instr->index()->IsConstantOperand())
4329       __ mov(index_in_bytes, ToImmediate(LConstantOperand::cast(instr->index()),
4330           instr->hydrogen()->index()->representation()));
4331     else
4332       __ mov(index_in_bytes, ToOperand(instr->index()));
4333     int index_shift_size =
4334         ElementsKindToShiftSize(instr->hydrogen()->element_kind());
4335     DCHECK(index_shift_size >= 0);
4336     if (index_shift_size > 0)
4337       __ shl(index_in_bytes, index_shift_size);
4338     int bytes = GetSIMD128LoadStoreBytes(op);
4339     __ add(index_in_bytes, Immediate(bytes));
4340     if (instr->length()->IsConstantOperand())
4341       __ mov(length_in_bytes,
4342              ToImmediate(LConstantOperand::cast(instr->length()),
4343       instr->hydrogen()->length()->representation()));
4344     else
4345       __ mov(length_in_bytes, ToOperand(instr->length()));
4346     int length_shift_size =
4347       ElementsKindToShiftSize(instr->hydrogen()->element_kind());
4348     DCHECK(length_shift_size >= 0);
4349     if (length_shift_size > 0)
4350       __ shl(length_in_bytes, length_shift_size);
4351     __ cmp(index_in_bytes, length_in_bytes);
4352   } else {
4353     if (instr->index()->IsConstantOperand()) {
4354       __ cmp(ToOperand(instr->length()),
4355         ToImmediate(LConstantOperand::cast(instr->index()),
4356         instr->hydrogen()->length()->representation()));
4357       cc = CommuteCondition(cc);
4358     } else if (instr->length()->IsConstantOperand()) {
4359       __ cmp(ToOperand(instr->index()),
4360         ToImmediate(LConstantOperand::cast(instr->length()),
4361         instr->hydrogen()->index()->representation()));
4362     } else {
4363       __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
4364     }
4365   }
4366   if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4367     Label done;
4368     __ j(NegateCondition(cc), &done, Label::kNear);
4369     __ int3();
4370     __ bind(&done);
4371   } else {
4372     DeoptimizeIf(cc, instr, "out of bounds");
4373   }
4374 }
4375
4376
4377 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4378   ElementsKind elements_kind = instr->elements_kind();
4379   LOperand* key = instr->key();
4380   if (!key->IsConstantOperand() &&
4381       ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
4382                                   elements_kind)) {
4383     HandleExternalArrayOpRequiresTemp(
4384         key, instr->hydrogen()->key()->representation(), elements_kind);
4385   }
4386
4387   Operand operand(BuildFastArrayOperand(
4388       instr->elements(),
4389       key,
4390       instr->hydrogen()->key()->representation(),
4391       elements_kind,
4392       instr->base_offset()));
4393   BuiltinFunctionId op = instr->hydrogen()->op();
4394   if (IsSIMD128LoadStoreOp(op)) {
4395     if (GetSIMD128LoadStoreBytes(op) == 16) {
4396       __ movups(operand, ToSIMD128Register(instr->value()));
4397     } else if (GetSIMD128LoadStoreBytes(op) == 4) {
4398       __ movss(operand, ToSIMD128Register(instr->value()));
4399     } else if (GetSIMD128LoadStoreBytes(op) == 8) {
4400       __ movq(operand, ToSIMD128Register(instr->value()));
4401     } else if (GetSIMD128LoadStoreBytes(op) == 12) {
4402       XMMRegister value(ToSIMD128Register(instr->value()));
4403       XMMRegister xmm_scratch = double_scratch0();
4404       __ movq(operand, value);
4405       Operand operand2(BuildFastArrayOperand(
4406           instr->elements(),
4407           key,
4408           instr->hydrogen()->key()->representation(),
4409           elements_kind,
4410           instr->base_offset() + 8));
4411       __ movhlps(xmm_scratch, value);
4412       __ movss(operand2, xmm_scratch);
4413     }
4414   } else if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
4415       elements_kind == FLOAT32_ELEMENTS) {
4416     XMMRegister xmm_scratch = double_scratch0();
4417     __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value()));
4418     __ movss(operand, xmm_scratch);
4419   } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
4420              elements_kind == FLOAT64_ELEMENTS) {
4421     __ movsd(operand, ToDoubleRegister(instr->value()));
4422   } else if (IsSIMD128ElementsKind(elements_kind)) {
4423     __ movups(operand, ToSIMD128Register(instr->value()));
4424   } else {
4425     Register value = ToRegister(instr->value());
4426     switch (elements_kind) {
4427       case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
4428       case EXTERNAL_UINT8_ELEMENTS:
4429       case EXTERNAL_INT8_ELEMENTS:
4430       case UINT8_ELEMENTS:
4431       case INT8_ELEMENTS:
4432       case UINT8_CLAMPED_ELEMENTS:
4433         __ mov_b(operand, value);
4434         break;
4435       case EXTERNAL_INT16_ELEMENTS:
4436       case EXTERNAL_UINT16_ELEMENTS:
4437       case UINT16_ELEMENTS:
4438       case INT16_ELEMENTS:
4439         __ mov_w(operand, value);
4440         break;
4441       case EXTERNAL_INT32_ELEMENTS:
4442       case EXTERNAL_UINT32_ELEMENTS:
4443       case UINT32_ELEMENTS:
4444       case INT32_ELEMENTS:
4445         __ mov(operand, value);
4446         break;
4447       case EXTERNAL_FLOAT32_ELEMENTS:
4448       case EXTERNAL_FLOAT64_ELEMENTS:
4449       case EXTERNAL_FLOAT32x4_ELEMENTS:
4450       case EXTERNAL_FLOAT64x2_ELEMENTS:
4451       case EXTERNAL_INT32x4_ELEMENTS:
4452       case FLOAT32_ELEMENTS:
4453       case FLOAT64_ELEMENTS:
4454       case FLOAT32x4_ELEMENTS:
4455       case FLOAT64x2_ELEMENTS:
4456       case INT32x4_ELEMENTS:
4457       case FAST_SMI_ELEMENTS:
4458       case FAST_ELEMENTS:
4459       case FAST_DOUBLE_ELEMENTS:
4460       case FAST_HOLEY_SMI_ELEMENTS:
4461       case FAST_HOLEY_ELEMENTS:
4462       case FAST_HOLEY_DOUBLE_ELEMENTS:
4463       case DICTIONARY_ELEMENTS:
4464       case SLOPPY_ARGUMENTS_ELEMENTS:
4465         UNREACHABLE();
4466         break;
4467     }
4468   }
4469 }
4470
4471
4472 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
4473   ExternalReference canonical_nan_reference =
4474       ExternalReference::address_of_canonical_non_hole_nan();
4475   Operand double_store_operand = BuildFastArrayOperand(
4476       instr->elements(),
4477       instr->key(),
4478       instr->hydrogen()->key()->representation(),
4479       FAST_DOUBLE_ELEMENTS,
4480       instr->base_offset());
4481
4482   XMMRegister value = ToDoubleRegister(instr->value());
4483
4484   if (instr->NeedsCanonicalization()) {
4485     Label have_value;
4486
4487     __ ucomisd(value, value);
4488     __ j(parity_odd, &have_value, Label::kNear);  // NaN.
4489
4490     __ movsd(value, Operand::StaticVariable(canonical_nan_reference));
4491     __ bind(&have_value);
4492   }
4493
4494   __ movsd(double_store_operand, value);
4495 }
4496
4497
4498 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
4499   Register elements = ToRegister(instr->elements());
4500   Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
4501
4502   Operand operand = BuildFastArrayOperand(
4503       instr->elements(),
4504       instr->key(),
4505       instr->hydrogen()->key()->representation(),
4506       FAST_ELEMENTS,
4507       instr->base_offset());
4508   if (instr->value()->IsRegister()) {
4509     __ mov(operand, ToRegister(instr->value()));
4510   } else {
4511     LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4512     if (IsSmi(operand_value)) {
4513       Immediate immediate = ToImmediate(operand_value, Representation::Smi());
4514       __ mov(operand, immediate);
4515     } else {
4516       DCHECK(!IsInteger32(operand_value));
4517       Handle<Object> handle_value = ToHandle(operand_value);
4518       __ mov(operand, handle_value);
4519     }
4520   }
4521
4522   if (instr->hydrogen()->NeedsWriteBarrier()) {
4523     DCHECK(instr->value()->IsRegister());
4524     Register value = ToRegister(instr->value());
4525     DCHECK(!instr->key()->IsConstantOperand());
4526     SmiCheck check_needed =
4527         instr->hydrogen()->value()->type().IsHeapObject()
4528           ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4529     // Compute address of modified element and store it into key register.
4530     __ lea(key, operand);
4531     __ RecordWrite(elements,
4532                    key,
4533                    value,
4534                    kSaveFPRegs,
4535                    EMIT_REMEMBERED_SET,
4536                    check_needed,
4537                    instr->hydrogen()->PointersToHereCheckForValue());
4538   }
4539 }
4540
4541
4542 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
4543   // By cases...external, fast-double, fast
4544   if (instr->is_typed_elements()) {
4545     DoStoreKeyedExternalArray(instr);
4546   } else if (instr->hydrogen()->value()->representation().IsDouble()) {
4547     DoStoreKeyedFixedDoubleArray(instr);
4548   } else {
4549     DoStoreKeyedFixedArray(instr);
4550   }
4551 }
4552
4553
4554 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
4555   DCHECK(ToRegister(instr->context()).is(esi));
4556   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
4557   DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
4558   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
4559
4560   Handle<Code> ic =
4561       CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code();
4562   CallCode(ic, RelocInfo::CODE_TARGET, instr);
4563 }
4564
4565
4566 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4567   Register object = ToRegister(instr->object());
4568   Register temp = ToRegister(instr->temp());
4569   Label no_memento_found;
4570   __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4571   DeoptimizeIf(equal, instr, "memento found");
4572   __ bind(&no_memento_found);
4573 }
4574
4575
4576 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4577   Register object_reg = ToRegister(instr->object());
4578
4579   Handle<Map> from_map = instr->original_map();
4580   Handle<Map> to_map = instr->transitioned_map();
4581   ElementsKind from_kind = instr->from_kind();
4582   ElementsKind to_kind = instr->to_kind();
4583
4584   Label not_applicable;
4585   bool is_simple_map_transition =
4586       IsSimpleMapChangeTransition(from_kind, to_kind);
4587   Label::Distance branch_distance =
4588       is_simple_map_transition ? Label::kNear : Label::kFar;
4589   __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
4590   __ j(not_equal, &not_applicable, branch_distance);
4591   if (is_simple_map_transition) {
4592     Register new_map_reg = ToRegister(instr->new_map_temp());
4593     __ mov(FieldOperand(object_reg, HeapObject::kMapOffset),
4594            Immediate(to_map));
4595     // Write barrier.
4596     DCHECK_NE(instr->temp(), NULL);
4597     __ RecordWriteForMap(object_reg, to_map, new_map_reg,
4598                          ToRegister(instr->temp()),
4599                          kDontSaveFPRegs);
4600   } else {
4601     DCHECK(ToRegister(instr->context()).is(esi));
4602     DCHECK(object_reg.is(eax));
4603     PushSafepointRegistersScope scope(this);
4604     __ mov(ebx, to_map);
4605     bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
4606     TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
4607     __ CallStub(&stub);
4608     RecordSafepointWithLazyDeopt(instr,
4609         RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4610   }
4611   __ bind(&not_applicable);
4612 }
4613
4614
4615 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
4616   class DeferredStringCharCodeAt FINAL : public LDeferredCode {
4617    public:
4618     DeferredStringCharCodeAt(LCodeGen* codegen,
4619                              LStringCharCodeAt* instr)
4620         : LDeferredCode(codegen), instr_(instr) { }
4621     virtual void Generate() OVERRIDE {
4622       codegen()->DoDeferredStringCharCodeAt(instr_);
4623     }
4624     virtual LInstruction* instr() OVERRIDE { return instr_; }
4625    private:
4626     LStringCharCodeAt* instr_;
4627   };
4628
4629   DeferredStringCharCodeAt* deferred =
4630       new(zone()) DeferredStringCharCodeAt(this, instr);
4631
4632   StringCharLoadGenerator::Generate(masm(),
4633                                     factory(),
4634                                     ToRegister(instr->string()),
4635                                     ToRegister(instr->index()),
4636                                     ToRegister(instr->result()),
4637                                     deferred->entry());
4638   __ bind(deferred->exit());
4639 }
4640
4641
4642 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
4643   Register string = ToRegister(instr->string());
4644   Register result = ToRegister(instr->result());
4645
4646   // TODO(3095996): Get rid of this. For now, we need to make the
4647   // result register contain a valid pointer because it is already
4648   // contained in the register pointer map.
4649   __ Move(result, Immediate(0));
4650
4651   PushSafepointRegistersScope scope(this);
4652   __ push(string);
4653   // Push the index as a smi. This is safe because of the checks in
4654   // DoStringCharCodeAt above.
4655   STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
4656   if (instr->index()->IsConstantOperand()) {
4657     Immediate immediate = ToImmediate(LConstantOperand::cast(instr->index()),
4658                                       Representation::Smi());
4659     __ push(immediate);
4660   } else {
4661     Register index = ToRegister(instr->index());
4662     __ SmiTag(index);
4663     __ push(index);
4664   }
4665   CallRuntimeFromDeferred(Runtime::kStringCharCodeAtRT, 2,
4666                           instr, instr->context());
4667   __ AssertSmi(eax);
4668   __ SmiUntag(eax);
4669   __ StoreToSafepointRegisterSlot(result, eax);
4670 }
4671
4672
4673 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
4674   class DeferredStringCharFromCode FINAL : public LDeferredCode {
4675    public:
4676     DeferredStringCharFromCode(LCodeGen* codegen,
4677                                LStringCharFromCode* instr)
4678         : LDeferredCode(codegen), instr_(instr) { }
4679     virtual void Generate() OVERRIDE {
4680       codegen()->DoDeferredStringCharFromCode(instr_);
4681     }
4682     virtual LInstruction* instr() OVERRIDE { return instr_; }
4683    private:
4684     LStringCharFromCode* instr_;
4685   };
4686
4687   DeferredStringCharFromCode* deferred =
4688       new(zone()) DeferredStringCharFromCode(this, instr);
4689
4690   DCHECK(instr->hydrogen()->value()->representation().IsInteger32());
4691   Register char_code = ToRegister(instr->char_code());
4692   Register result = ToRegister(instr->result());
4693   DCHECK(!char_code.is(result));
4694
4695   __ cmp(char_code, String::kMaxOneByteCharCode);
4696   __ j(above, deferred->entry());
4697   __ Move(result, Immediate(factory()->single_character_string_cache()));
4698   __ mov(result, FieldOperand(result,
4699                               char_code, times_pointer_size,
4700                               FixedArray::kHeaderSize));
4701   __ cmp(result, factory()->undefined_value());
4702   __ j(equal, deferred->entry());
4703   __ bind(deferred->exit());
4704 }
4705
4706
4707 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
4708   Register char_code = ToRegister(instr->char_code());
4709   Register result = ToRegister(instr->result());
4710
4711   // TODO(3095996): Get rid of this. For now, we need to make the
4712   // result register contain a valid pointer because it is already
4713   // contained in the register pointer map.
4714   __ Move(result, Immediate(0));
4715
4716   PushSafepointRegistersScope scope(this);
4717   __ SmiTag(char_code);
4718   __ push(char_code);
4719   CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context());
4720   __ StoreToSafepointRegisterSlot(result, eax);
4721 }
4722
4723
4724 void LCodeGen::DoStringAdd(LStringAdd* instr) {
4725   DCHECK(ToRegister(instr->context()).is(esi));
4726   DCHECK(ToRegister(instr->left()).is(edx));
4727   DCHECK(ToRegister(instr->right()).is(eax));
4728   StringAddStub stub(isolate(),
4729                      instr->hydrogen()->flags(),
4730                      instr->hydrogen()->pretenure_flag());
4731   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4732 }
4733
4734
4735 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
4736   LOperand* input = instr->value();
4737   LOperand* output = instr->result();
4738   DCHECK(input->IsRegister() || input->IsStackSlot());
4739   DCHECK(output->IsDoubleRegister());
4740   __ Cvtsi2sd(ToDoubleRegister(output), ToOperand(input));
4741 }
4742
4743
4744 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
4745   LOperand* input = instr->value();
4746   LOperand* output = instr->result();
4747   __ LoadUint32(ToDoubleRegister(output), ToRegister(input));
4748 }
4749
4750
4751 void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
4752   class DeferredNumberTagI FINAL : public LDeferredCode {
4753    public:
4754     DeferredNumberTagI(LCodeGen* codegen,
4755                        LNumberTagI* instr)
4756         : LDeferredCode(codegen), instr_(instr) { }
4757     virtual void Generate() OVERRIDE {
4758       codegen()->DoDeferredNumberTagIU(
4759           instr_, instr_->value(), instr_->temp(), SIGNED_INT32);
4760     }
4761     virtual LInstruction* instr() OVERRIDE { return instr_; }
4762    private:
4763     LNumberTagI* instr_;
4764   };
4765
4766   LOperand* input = instr->value();
4767   DCHECK(input->IsRegister() && input->Equals(instr->result()));
4768   Register reg = ToRegister(input);
4769
4770   DeferredNumberTagI* deferred =
4771       new(zone()) DeferredNumberTagI(this, instr);
4772   __ SmiTag(reg);
4773   __ j(overflow, deferred->entry());
4774   __ bind(deferred->exit());
4775 }
4776
4777
4778 void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
4779   class DeferredNumberTagU FINAL : public LDeferredCode {
4780    public:
4781     DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr)
4782         : LDeferredCode(codegen), instr_(instr) { }
4783     virtual void Generate() OVERRIDE {
4784       codegen()->DoDeferredNumberTagIU(
4785           instr_, instr_->value(), instr_->temp(), UNSIGNED_INT32);
4786     }
4787     virtual LInstruction* instr() OVERRIDE { return instr_; }
4788    private:
4789     LNumberTagU* instr_;
4790   };
4791
4792   LOperand* input = instr->value();
4793   DCHECK(input->IsRegister() && input->Equals(instr->result()));
4794   Register reg = ToRegister(input);
4795
4796   DeferredNumberTagU* deferred =
4797       new(zone()) DeferredNumberTagU(this, instr);
4798   __ cmp(reg, Immediate(Smi::kMaxValue));
4799   __ j(above, deferred->entry());
4800   __ SmiTag(reg);
4801   __ bind(deferred->exit());
4802 }
4803
4804
4805 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
4806                                      LOperand* value,
4807                                      LOperand* temp,
4808                                      IntegerSignedness signedness) {
4809   Label done, slow;
4810   Register reg = ToRegister(value);
4811   Register tmp = ToRegister(temp);
4812   XMMRegister xmm_scratch = double_scratch0();
4813
4814   if (signedness == SIGNED_INT32) {
4815     // There was overflow, so bits 30 and 31 of the original integer
4816     // disagree. Try to allocate a heap number in new space and store
4817     // the value in there. If that fails, call the runtime system.
4818     __ SmiUntag(reg);
4819     __ xor_(reg, 0x80000000);
4820     __ Cvtsi2sd(xmm_scratch, Operand(reg));
4821   } else {
4822     __ LoadUint32(xmm_scratch, reg);
4823   }
4824
4825   if (FLAG_inline_new) {
4826     __ AllocateHeapNumber(reg, tmp, no_reg, &slow);
4827     __ jmp(&done, Label::kNear);
4828   }
4829
4830   // Slow case: Call the runtime system to do the number allocation.
4831   __ bind(&slow);
4832   {
4833     // TODO(3095996): Put a valid pointer value in the stack slot where the
4834     // result register is stored, as this register is in the pointer map, but
4835     // contains an integer value.
4836     __ Move(reg, Immediate(0));
4837
4838     // Preserve the value of all registers.
4839     PushSafepointRegistersScope scope(this);
4840
4841     // NumberTagI and NumberTagD use the context from the frame, rather than
4842     // the environment's HContext or HInlinedContext value.
4843     // They only call Runtime::kAllocateHeapNumber.
4844     // The corresponding HChange instructions are added in a phase that does
4845     // not have easy access to the local context.
4846     __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4847     __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4848     RecordSafepointWithRegisters(
4849         instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4850     __ StoreToSafepointRegisterSlot(reg, eax);
4851   }
4852
4853   // Done. Put the value in xmm_scratch into the value of the allocated heap
4854   // number.
4855   __ bind(&done);
4856   __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm_scratch);
4857 }
4858
4859
4860 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
4861   class DeferredNumberTagD FINAL : public LDeferredCode {
4862    public:
4863     DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
4864         : LDeferredCode(codegen), instr_(instr) { }
4865     virtual void Generate() OVERRIDE {
4866       codegen()->DoDeferredNumberTagD(instr_);
4867     }
4868     virtual LInstruction* instr() OVERRIDE { return instr_; }
4869    private:
4870     LNumberTagD* instr_;
4871   };
4872
4873   Register reg = ToRegister(instr->result());
4874
4875   DeferredNumberTagD* deferred =
4876       new(zone()) DeferredNumberTagD(this, instr);
4877   if (FLAG_inline_new) {
4878     Register tmp = ToRegister(instr->temp());
4879     __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry());
4880   } else {
4881     __ jmp(deferred->entry());
4882   }
4883   __ bind(deferred->exit());
4884   XMMRegister input_reg = ToDoubleRegister(instr->value());
4885   __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg);
4886 }
4887
4888
4889 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
4890   // TODO(3095996): Get rid of this. For now, we need to make the
4891   // result register contain a valid pointer because it is already
4892   // contained in the register pointer map.
4893   Register reg = ToRegister(instr->result());
4894   __ Move(reg, Immediate(0));
4895
4896   PushSafepointRegistersScope scope(this);
4897   // NumberTagI and NumberTagD use the context from the frame, rather than
4898   // the environment's HContext or HInlinedContext value.
4899   // They only call Runtime::kAllocateHeapNumber.
4900   // The corresponding HChange instructions are added in a phase that does
4901   // not have easy access to the local context.
4902   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4903   __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4904   RecordSafepointWithRegisters(
4905       instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4906   __ StoreToSafepointRegisterSlot(reg, eax);
4907 }
4908
4909
4910 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4911   HChange* hchange = instr->hydrogen();
4912   Register input = ToRegister(instr->value());
4913   if (hchange->CheckFlag(HValue::kCanOverflow) &&
4914       hchange->value()->CheckFlag(HValue::kUint32)) {
4915     __ test(input, Immediate(0xc0000000));
4916     DeoptimizeIf(not_zero, instr, "overflow");
4917   }
4918   __ SmiTag(input);
4919   if (hchange->CheckFlag(HValue::kCanOverflow) &&
4920       !hchange->value()->CheckFlag(HValue::kUint32)) {
4921     DeoptimizeIf(overflow, instr, "overflow");
4922   }
4923 }
4924
4925
4926 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4927   LOperand* input = instr->value();
4928   Register result = ToRegister(input);
4929   DCHECK(input->IsRegister() && input->Equals(instr->result()));
4930   if (instr->needs_check()) {
4931     __ test(result, Immediate(kSmiTagMask));
4932     DeoptimizeIf(not_zero, instr, "not a Smi");
4933   } else {
4934     __ AssertSmi(result);
4935   }
4936   __ SmiUntag(result);
4937 }
4938
4939
4940 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
4941                                 Register temp_reg, XMMRegister result_reg,
4942                                 NumberUntagDMode mode) {
4943   bool can_convert_undefined_to_nan =
4944       instr->hydrogen()->can_convert_undefined_to_nan();
4945   bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
4946
4947   Label convert, load_smi, done;
4948
4949   if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
4950     // Smi check.
4951     __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
4952
4953     // Heap number map check.
4954     __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
4955            factory()->heap_number_map());
4956     if (can_convert_undefined_to_nan) {
4957       __ j(not_equal, &convert, Label::kNear);
4958     } else {
4959       DeoptimizeIf(not_equal, instr, "not a heap number");
4960     }
4961
4962     // Heap number to XMM conversion.
4963     __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
4964
4965     if (deoptimize_on_minus_zero) {
4966       XMMRegister xmm_scratch = double_scratch0();
4967       __ xorps(xmm_scratch, xmm_scratch);
4968       __ ucomisd(result_reg, xmm_scratch);
4969       __ j(not_zero, &done, Label::kNear);
4970       __ movmskpd(temp_reg, result_reg);
4971       __ test_b(temp_reg, 1);
4972       DeoptimizeIf(not_zero, instr, "minus zero");
4973     }
4974     __ jmp(&done, Label::kNear);
4975
4976     if (can_convert_undefined_to_nan) {
4977       __ bind(&convert);
4978
4979       // Convert undefined (and hole) to NaN.
4980       __ cmp(input_reg, factory()->undefined_value());
4981       DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
4982
4983       ExternalReference nan =
4984           ExternalReference::address_of_canonical_non_hole_nan();
4985       __ movsd(result_reg, Operand::StaticVariable(nan));
4986       __ jmp(&done, Label::kNear);
4987     }
4988   } else {
4989     DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
4990   }
4991
4992   __ bind(&load_smi);
4993   // Smi to XMM conversion. Clobbering a temp is faster than re-tagging the
4994   // input register since we avoid dependencies.
4995   __ mov(temp_reg, input_reg);
4996   __ SmiUntag(temp_reg);  // Untag smi before converting to float.
4997   __ Cvtsi2sd(result_reg, Operand(temp_reg));
4998   __ bind(&done);
4999 }
5000
5001
5002 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
5003   Register input_reg = ToRegister(instr->value());
5004
5005   // The input was optimistically untagged; revert it.
5006   STATIC_ASSERT(kSmiTagSize == 1);
5007   __ lea(input_reg, Operand(input_reg, times_2, kHeapObjectTag));
5008
5009   if (instr->truncating()) {
5010     Label no_heap_number, check_bools, check_false;
5011
5012     // Heap number map check.
5013     __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5014            factory()->heap_number_map());
5015     __ j(not_equal, &no_heap_number, Label::kNear);
5016     __ TruncateHeapNumberToI(input_reg, input_reg);
5017     __ jmp(done);
5018
5019     __ bind(&no_heap_number);
5020     // Check for Oddballs. Undefined/False is converted to zero and True to one
5021     // for truncating conversions.
5022     __ cmp(input_reg, factory()->undefined_value());
5023     __ j(not_equal, &check_bools, Label::kNear);
5024     __ Move(input_reg, Immediate(0));
5025     __ jmp(done);
5026
5027     __ bind(&check_bools);
5028     __ cmp(input_reg, factory()->true_value());
5029     __ j(not_equal, &check_false, Label::kNear);
5030     __ Move(input_reg, Immediate(1));
5031     __ jmp(done);
5032
5033     __ bind(&check_false);
5034     __ cmp(input_reg, factory()->false_value());
5035     DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false");
5036     __ Move(input_reg, Immediate(0));
5037   } else {
5038     XMMRegister scratch = ToDoubleRegister(instr->temp());
5039     DCHECK(!scratch.is(xmm0));
5040     __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5041            isolate()->factory()->heap_number_map());
5042     DeoptimizeIf(not_equal, instr, "not a heap number");
5043     __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
5044     __ cvttsd2si(input_reg, Operand(xmm0));
5045     __ Cvtsi2sd(scratch, Operand(input_reg));
5046     __ ucomisd(xmm0, scratch);
5047     DeoptimizeIf(not_equal, instr, "lost precision");
5048     DeoptimizeIf(parity_even, instr, "NaN");
5049     if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
5050       __ test(input_reg, Operand(input_reg));
5051       __ j(not_zero, done);
5052       __ movmskpd(input_reg, xmm0);
5053       __ and_(input_reg, 1);
5054       DeoptimizeIf(not_zero, instr, "minus zero");
5055     }
5056   }
5057 }
5058
5059
5060 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
5061   class DeferredTaggedToI FINAL : public LDeferredCode {
5062    public:
5063     DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
5064         : LDeferredCode(codegen), instr_(instr) { }
5065     virtual void Generate() OVERRIDE {
5066       codegen()->DoDeferredTaggedToI(instr_, done());
5067     }
5068     virtual LInstruction* instr() OVERRIDE { return instr_; }
5069    private:
5070     LTaggedToI* instr_;
5071   };
5072
5073   LOperand* input = instr->value();
5074   DCHECK(input->IsRegister());
5075   Register input_reg = ToRegister(input);
5076   DCHECK(input_reg.is(ToRegister(instr->result())));
5077
5078   if (instr->hydrogen()->value()->representation().IsSmi()) {
5079     __ SmiUntag(input_reg);
5080   } else {
5081     DeferredTaggedToI* deferred =
5082         new(zone()) DeferredTaggedToI(this, instr);
5083     // Optimistically untag the input.
5084     // If the input is a HeapObject, SmiUntag will set the carry flag.
5085     STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
5086     __ SmiUntag(input_reg);
5087     // Branch to deferred code if the input was tagged.
5088     // The deferred code will take care of restoring the tag.
5089     __ j(carry, deferred->entry());
5090     __ bind(deferred->exit());
5091   }
5092 }
5093
5094
5095 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
5096   LOperand* input = instr->value();
5097   DCHECK(input->IsRegister());
5098   LOperand* temp = instr->temp();
5099   DCHECK(temp->IsRegister());
5100   LOperand* result = instr->result();
5101   DCHECK(result->IsDoubleRegister());
5102
5103   Register input_reg = ToRegister(input);
5104   Register temp_reg = ToRegister(temp);
5105
5106   HValue* value = instr->hydrogen()->value();
5107   NumberUntagDMode mode = value->representation().IsSmi()
5108       ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
5109
5110   XMMRegister result_reg = ToDoubleRegister(result);
5111   EmitNumberUntagD(instr, input_reg, temp_reg, result_reg, mode);
5112 }
5113
5114
5115 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
5116   LOperand* input = instr->value();
5117   DCHECK(input->IsDoubleRegister());
5118   LOperand* result = instr->result();
5119   DCHECK(result->IsRegister());
5120   Register result_reg = ToRegister(result);
5121
5122   if (instr->truncating()) {
5123     XMMRegister input_reg = ToDoubleRegister(input);
5124     __ TruncateDoubleToI(result_reg, input_reg);
5125   } else {
5126     Label lost_precision, is_nan, minus_zero, done;
5127     XMMRegister input_reg = ToDoubleRegister(input);
5128     XMMRegister xmm_scratch = double_scratch0();
5129     Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
5130     __ DoubleToI(result_reg, input_reg, xmm_scratch,
5131                  instr->hydrogen()->GetMinusZeroMode(), &lost_precision,
5132                  &is_nan, &minus_zero, dist);
5133     __ jmp(&done, dist);
5134     __ bind(&lost_precision);
5135     DeoptimizeIf(no_condition, instr, "lost precision");
5136     __ bind(&is_nan);
5137     DeoptimizeIf(no_condition, instr, "NaN");
5138     __ bind(&minus_zero);
5139     DeoptimizeIf(no_condition, instr, "minus zero");
5140     __ bind(&done);
5141   }
5142 }
5143
5144
5145 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5146   LOperand* input = instr->value();
5147   DCHECK(input->IsDoubleRegister());
5148   LOperand* result = instr->result();
5149   DCHECK(result->IsRegister());
5150   Register result_reg = ToRegister(result);
5151
5152   Label lost_precision, is_nan, minus_zero, done;
5153   XMMRegister input_reg = ToDoubleRegister(input);
5154   XMMRegister xmm_scratch = double_scratch0();
5155   Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
5156   __ DoubleToI(result_reg, input_reg, xmm_scratch,
5157                instr->hydrogen()->GetMinusZeroMode(), &lost_precision, &is_nan,
5158                &minus_zero, dist);
5159   __ jmp(&done, dist);
5160   __ bind(&lost_precision);
5161   DeoptimizeIf(no_condition, instr, "lost precision");
5162   __ bind(&is_nan);
5163   DeoptimizeIf(no_condition, instr, "NaN");
5164   __ bind(&minus_zero);
5165   DeoptimizeIf(no_condition, instr, "minus zero");
5166   __ bind(&done);
5167   __ SmiTag(result_reg);
5168   DeoptimizeIf(overflow, instr, "overflow");
5169 }
5170
5171
5172 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5173   LOperand* input = instr->value();
5174   __ test(ToOperand(input), Immediate(kSmiTagMask));
5175   DeoptimizeIf(not_zero, instr, "not a Smi");
5176 }
5177
5178
5179 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5180   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
5181     LOperand* input = instr->value();
5182     __ test(ToOperand(input), Immediate(kSmiTagMask));
5183     DeoptimizeIf(zero, instr, "Smi");
5184   }
5185 }
5186
5187
5188 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5189   Register input = ToRegister(instr->value());
5190   Register temp = ToRegister(instr->temp());
5191
5192   __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
5193
5194   if (instr->hydrogen()->is_interval_check()) {
5195     InstanceType first;
5196     InstanceType last;
5197     instr->hydrogen()->GetCheckInterval(&first, &last);
5198
5199     __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
5200             static_cast<int8_t>(first));
5201
5202     // If there is only one type in the interval check for equality.
5203     if (first == last) {
5204       DeoptimizeIf(not_equal, instr, "wrong instance type");
5205     } else {
5206       DeoptimizeIf(below, instr, "wrong instance type");
5207       // Omit check for the last type.
5208       if (last != LAST_TYPE) {
5209         __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
5210                 static_cast<int8_t>(last));
5211         DeoptimizeIf(above, instr, "wrong instance type");
5212       }
5213     }
5214   } else {
5215     uint8_t mask;
5216     uint8_t tag;
5217     instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
5218
5219     if (base::bits::IsPowerOfTwo32(mask)) {
5220       DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
5221       __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask);
5222       DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type");
5223     } else {
5224       __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
5225       __ and_(temp, mask);
5226       __ cmp(temp, tag);
5227       DeoptimizeIf(not_equal, instr, "wrong instance type");
5228     }
5229   }
5230 }
5231
5232
5233 void LCodeGen::DoCheckValue(LCheckValue* instr) {
5234   Handle<HeapObject> object = instr->hydrogen()->object().handle();
5235   if (instr->hydrogen()->object_in_new_space()) {
5236     Register reg = ToRegister(instr->value());
5237     Handle<Cell> cell = isolate()->factory()->NewCell(object);
5238     __ cmp(reg, Operand::ForCell(cell));
5239   } else {
5240     Operand operand = ToOperand(instr->value());
5241     __ cmp(operand, object);
5242   }
5243   DeoptimizeIf(not_equal, instr, "value mismatch");
5244 }
5245
5246
5247 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
5248   {
5249     PushSafepointRegistersScope scope(this);
5250     __ push(object);
5251     __ xor_(esi, esi);
5252     __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
5253     RecordSafepointWithRegisters(
5254         instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
5255
5256     __ test(eax, Immediate(kSmiTagMask));
5257   }
5258   DeoptimizeIf(zero, instr, "instance migration failed");
5259 }
5260
5261
5262 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5263   class DeferredCheckMaps FINAL : public LDeferredCode {
5264    public:
5265     DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr,  Register object)
5266         : LDeferredCode(codegen), instr_(instr), object_(object) {
5267       SetExit(check_maps());
5268     }
5269     virtual void Generate() OVERRIDE {
5270       codegen()->DoDeferredInstanceMigration(instr_, object_);
5271     }
5272     Label* check_maps() { return &check_maps_; }
5273     virtual LInstruction* instr() OVERRIDE { return instr_; }
5274    private:
5275     LCheckMaps* instr_;
5276     Label check_maps_;
5277     Register object_;
5278   };
5279
5280   if (instr->hydrogen()->IsStabilityCheck()) {
5281     const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5282     for (int i = 0; i < maps->size(); ++i) {
5283       AddStabilityDependency(maps->at(i).handle());
5284     }
5285     return;
5286   }
5287
5288   LOperand* input = instr->value();
5289   DCHECK(input->IsRegister());
5290   Register reg = ToRegister(input);
5291
5292   DeferredCheckMaps* deferred = NULL;
5293   if (instr->hydrogen()->HasMigrationTarget()) {
5294     deferred = new(zone()) DeferredCheckMaps(this, instr, reg);
5295     __ bind(deferred->check_maps());
5296   }
5297
5298   const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5299   Label success;
5300   for (int i = 0; i < maps->size() - 1; i++) {
5301     Handle<Map> map = maps->at(i).handle();
5302     __ CompareMap(reg, map);
5303     __ j(equal, &success, Label::kNear);
5304   }
5305
5306   Handle<Map> map = maps->at(maps->size() - 1).handle();
5307   __ CompareMap(reg, map);
5308   if (instr->hydrogen()->HasMigrationTarget()) {
5309     __ j(not_equal, deferred->entry());
5310   } else {
5311     DeoptimizeIf(not_equal, instr, "wrong map");
5312   }
5313
5314   __ bind(&success);
5315 }
5316
5317
5318 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5319   XMMRegister value_reg = ToDoubleRegister(instr->unclamped());
5320   XMMRegister xmm_scratch = double_scratch0();
5321   Register result_reg = ToRegister(instr->result());
5322   __ ClampDoubleToUint8(value_reg, xmm_scratch, result_reg);
5323 }
5324
5325
5326 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
5327   DCHECK(instr->unclamped()->Equals(instr->result()));
5328   Register value_reg = ToRegister(instr->result());
5329   __ ClampUint8(value_reg);
5330 }
5331
5332
5333 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
5334   DCHECK(instr->unclamped()->Equals(instr->result()));
5335   Register input_reg = ToRegister(instr->unclamped());
5336   XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm());
5337   XMMRegister xmm_scratch = double_scratch0();
5338   Label is_smi, done, heap_number;
5339
5340   __ JumpIfSmi(input_reg, &is_smi);
5341
5342   // Check for heap number
5343   __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5344          factory()->heap_number_map());
5345   __ j(equal, &heap_number, Label::kNear);
5346
5347   // Check for undefined. Undefined is converted to zero for clamping
5348   // conversions.
5349   __ cmp(input_reg, factory()->undefined_value());
5350   DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
5351   __ mov(input_reg, 0);
5352   __ jmp(&done, Label::kNear);
5353
5354   // Heap number
5355   __ bind(&heap_number);
5356   __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset));
5357   __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg);
5358   __ jmp(&done, Label::kNear);
5359
5360   // smi
5361   __ bind(&is_smi);
5362   __ SmiUntag(input_reg);
5363   __ ClampUint8(input_reg);
5364   __ bind(&done);
5365 }
5366
5367
5368 void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
5369   XMMRegister value_reg = ToDoubleRegister(instr->value());
5370   Register result_reg = ToRegister(instr->result());
5371   if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
5372     if (CpuFeatures::IsSupported(SSE4_1)) {
5373       CpuFeatureScope scope2(masm(), SSE4_1);
5374       __ pextrd(result_reg, value_reg, 1);
5375     } else {
5376       XMMRegister xmm_scratch = double_scratch0();
5377       __ pshufd(xmm_scratch, value_reg, 1);
5378       __ movd(result_reg, xmm_scratch);
5379     }
5380   } else {
5381     __ movd(result_reg, value_reg);
5382   }
5383 }
5384
5385
5386 void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
5387   Register hi_reg = ToRegister(instr->hi());
5388   Register lo_reg = ToRegister(instr->lo());
5389   XMMRegister result_reg = ToDoubleRegister(instr->result());
5390
5391   if (CpuFeatures::IsSupported(SSE4_1)) {
5392     CpuFeatureScope scope2(masm(), SSE4_1);
5393     __ movd(result_reg, lo_reg);
5394     __ pinsrd(result_reg, hi_reg, 1);
5395   } else {
5396     XMMRegister xmm_scratch = double_scratch0();
5397     __ movd(result_reg, hi_reg);
5398     __ psllq(result_reg, 32);
5399     __ movd(xmm_scratch, lo_reg);
5400     __ orps(result_reg, xmm_scratch);
5401   }
5402 }
5403
5404
5405 void LCodeGen::DoAllocate(LAllocate* instr) {
5406   class DeferredAllocate FINAL : public LDeferredCode {
5407    public:
5408     DeferredAllocate(LCodeGen* codegen,  LAllocate* instr)
5409         : LDeferredCode(codegen), instr_(instr) { }
5410     virtual void Generate() OVERRIDE {
5411       codegen()->DoDeferredAllocate(instr_);
5412     }
5413     virtual LInstruction* instr() OVERRIDE { return instr_; }
5414    private:
5415     LAllocate* instr_;
5416   };
5417
5418   DeferredAllocate* deferred = new(zone()) DeferredAllocate(this, instr);
5419
5420   Register result = ToRegister(instr->result());
5421   Register temp = ToRegister(instr->temp());
5422
5423   // Allocate memory for the object.
5424   AllocationFlags flags = TAG_OBJECT;
5425   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
5426     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
5427   }
5428   if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
5429     DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation());
5430     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5431     flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
5432   } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
5433     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5434     flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE);
5435   }
5436
5437   if (instr->size()->IsConstantOperand()) {
5438     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5439     if (size <= Page::kMaxRegularHeapObjectSize) {
5440       __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
5441     } else {
5442       __ jmp(deferred->entry());
5443     }
5444   } else {
5445     Register size = ToRegister(instr->size());
5446     __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
5447   }
5448
5449   __ bind(deferred->exit());
5450
5451   if (instr->hydrogen()->MustPrefillWithFiller()) {
5452     if (instr->size()->IsConstantOperand()) {
5453       int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5454       __ mov(temp, (size / kPointerSize) - 1);
5455     } else {
5456       temp = ToRegister(instr->size());
5457       __ shr(temp, kPointerSizeLog2);
5458       __ dec(temp);
5459     }
5460     Label loop;
5461     __ bind(&loop);
5462     __ mov(FieldOperand(result, temp, times_pointer_size, 0),
5463         isolate()->factory()->one_pointer_filler_map());
5464     __ dec(temp);
5465     __ j(not_zero, &loop);
5466   }
5467 }
5468
5469
5470 void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
5471   Register result = ToRegister(instr->result());
5472
5473   // TODO(3095996): Get rid of this. For now, we need to make the
5474   // result register contain a valid pointer because it is already
5475   // contained in the register pointer map.
5476   __ Move(result, Immediate(Smi::FromInt(0)));
5477
5478   PushSafepointRegistersScope scope(this);
5479   if (instr->size()->IsRegister()) {
5480     Register size = ToRegister(instr->size());
5481     DCHECK(!size.is(result));
5482     __ SmiTag(ToRegister(instr->size()));
5483     __ push(size);
5484   } else {
5485     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5486     if (size >= 0 && size <= Smi::kMaxValue) {
5487       __ push(Immediate(Smi::FromInt(size)));
5488     } else {
5489       // We should never get here at runtime => abort
5490       __ int3();
5491       return;
5492     }
5493   }
5494
5495   int flags = AllocateDoubleAlignFlag::encode(
5496       instr->hydrogen()->MustAllocateDoubleAligned());
5497   if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
5498     DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation());
5499     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5500     flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE);
5501   } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
5502     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5503     flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE);
5504   } else {
5505     flags = AllocateTargetSpace::update(flags, NEW_SPACE);
5506   }
5507   __ push(Immediate(Smi::FromInt(flags)));
5508
5509   CallRuntimeFromDeferred(
5510       Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
5511   __ StoreToSafepointRegisterSlot(result, eax);
5512 }
5513
5514
5515 void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
5516   DCHECK(ToRegister(instr->value()).is(eax));
5517   __ push(eax);
5518   CallRuntime(Runtime::kToFastProperties, 1, instr);
5519 }
5520
5521
5522 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
5523   DCHECK(ToRegister(instr->context()).is(esi));
5524   Label materialized;
5525   // Registers will be used as follows:
5526   // ecx = literals array.
5527   // ebx = regexp literal.
5528   // eax = regexp literal clone.
5529   // esi = context.
5530   int literal_offset =
5531       FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
5532   __ LoadHeapObject(ecx, instr->hydrogen()->literals());
5533   __ mov(ebx, FieldOperand(ecx, literal_offset));
5534   __ cmp(ebx, factory()->undefined_value());
5535   __ j(not_equal, &materialized, Label::kNear);
5536
5537   // Create regexp literal using runtime function
5538   // Result will be in eax.
5539   __ push(ecx);
5540   __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
5541   __ push(Immediate(instr->hydrogen()->pattern()));
5542   __ push(Immediate(instr->hydrogen()->flags()));
5543   CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
5544   __ mov(ebx, eax);
5545
5546   __ bind(&materialized);
5547   int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
5548   Label allocated, runtime_allocate;
5549   __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
5550   __ jmp(&allocated, Label::kNear);
5551
5552   __ bind(&runtime_allocate);
5553   __ push(ebx);
5554   __ push(Immediate(Smi::FromInt(size)));
5555   CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
5556   __ pop(ebx);
5557
5558   __ bind(&allocated);
5559   // Copy the content into the newly allocated memory.
5560   // (Unroll copy loop once for better throughput).
5561   for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
5562     __ mov(edx, FieldOperand(ebx, i));
5563     __ mov(ecx, FieldOperand(ebx, i + kPointerSize));
5564     __ mov(FieldOperand(eax, i), edx);
5565     __ mov(FieldOperand(eax, i + kPointerSize), ecx);
5566   }
5567   if ((size % (2 * kPointerSize)) != 0) {
5568     __ mov(edx, FieldOperand(ebx, size - kPointerSize));
5569     __ mov(FieldOperand(eax, size - kPointerSize), edx);
5570   }
5571 }
5572
5573
5574 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
5575   DCHECK(ToRegister(instr->context()).is(esi));
5576   // Use the fast case closure allocation code that allocates in new
5577   // space for nested functions that don't need literals cloning.
5578   bool pretenure = instr->hydrogen()->pretenure();
5579   if (!pretenure && instr->hydrogen()->has_no_literals()) {
5580     FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
5581                             instr->hydrogen()->kind());
5582     __ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
5583     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
5584   } else {
5585     __ push(esi);
5586     __ push(Immediate(instr->hydrogen()->shared_info()));
5587     __ push(Immediate(pretenure ? factory()->true_value()
5588                                 : factory()->false_value()));
5589     CallRuntime(Runtime::kNewClosure, 3, instr);
5590   }
5591 }
5592
5593
5594 void LCodeGen::DoTypeof(LTypeof* instr) {
5595   DCHECK(ToRegister(instr->context()).is(esi));
5596   LOperand* input = instr->value();
5597   EmitPushTaggedOperand(input);
5598   CallRuntime(Runtime::kTypeof, 1, instr);
5599 }
5600
5601
5602 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
5603   Register input = ToRegister(instr->value());
5604   Condition final_branch_condition = EmitTypeofIs(instr, input);
5605   if (final_branch_condition != no_condition) {
5606     EmitBranch(instr, final_branch_condition);
5607   }
5608 }
5609
5610
5611 Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
5612   Label* true_label = instr->TrueLabel(chunk_);
5613   Label* false_label = instr->FalseLabel(chunk_);
5614   Handle<String> type_name = instr->type_literal();
5615   int left_block = instr->TrueDestination(chunk_);
5616   int right_block = instr->FalseDestination(chunk_);
5617   int next_block = GetNextEmittedBlock();
5618
5619   Label::Distance true_distance = left_block == next_block ? Label::kNear
5620                                                            : Label::kFar;
5621   Label::Distance false_distance = right_block == next_block ? Label::kNear
5622                                                              : Label::kFar;
5623   Condition final_branch_condition = no_condition;
5624   if (String::Equals(type_name, factory()->number_string())) {
5625     __ JumpIfSmi(input, true_label, true_distance);
5626     __ cmp(FieldOperand(input, HeapObject::kMapOffset),
5627            factory()->heap_number_map());
5628     final_branch_condition = equal;
5629
5630   } else if (String::Equals(type_name, factory()->string_string())) {
5631     __ JumpIfSmi(input, false_label, false_distance);
5632     __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
5633     __ j(above_equal, false_label, false_distance);
5634     __ test_b(FieldOperand(input, Map::kBitFieldOffset),
5635               1 << Map::kIsUndetectable);
5636     final_branch_condition = zero;
5637
5638   } else if (String::Equals(type_name, factory()->symbol_string())) {
5639     __ JumpIfSmi(input, false_label, false_distance);
5640     __ CmpObjectType(input, SYMBOL_TYPE, input);
5641     final_branch_condition = equal;
5642
5643   } else if (String::Equals(type_name, factory()->boolean_string())) {
5644     __ cmp(input, factory()->true_value());
5645     __ j(equal, true_label, true_distance);
5646     __ cmp(input, factory()->false_value());
5647     final_branch_condition = equal;
5648
5649   } else if (String::Equals(type_name, factory()->undefined_string())) {
5650     __ cmp(input, factory()->undefined_value());
5651     __ j(equal, true_label, true_distance);
5652     __ JumpIfSmi(input, false_label, false_distance);
5653     // Check for undetectable objects => true.
5654     __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
5655     __ test_b(FieldOperand(input, Map::kBitFieldOffset),
5656               1 << Map::kIsUndetectable);
5657     final_branch_condition = not_zero;
5658
5659   } else if (String::Equals(type_name, factory()->function_string())) {
5660     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
5661     __ JumpIfSmi(input, false_label, false_distance);
5662     __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
5663     __ j(equal, true_label, true_distance);
5664     __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
5665     final_branch_condition = equal;
5666
5667   } else if (String::Equals(type_name, factory()->object_string())) {
5668     __ JumpIfSmi(input, false_label, false_distance);
5669     __ cmp(input, factory()->null_value());
5670     __ j(equal, true_label, true_distance);
5671     __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
5672     __ j(below, false_label, false_distance);
5673     __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
5674     __ j(above, false_label, false_distance);
5675     // Check for undetectable objects => false.
5676     __ test_b(FieldOperand(input, Map::kBitFieldOffset),
5677               1 << Map::kIsUndetectable);
5678     final_branch_condition = zero;
5679
5680   } else {
5681     __ jmp(false_label, false_distance);
5682   }
5683   return final_branch_condition;
5684 }
5685
5686
5687 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
5688   Register temp = ToRegister(instr->temp());
5689
5690   EmitIsConstructCall(temp);
5691   EmitBranch(instr, equal);
5692 }
5693
5694
5695 void LCodeGen::EmitIsConstructCall(Register temp) {
5696   // Get the frame pointer for the calling frame.
5697   __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
5698
5699   // Skip the arguments adaptor frame if it exists.
5700   Label check_frame_marker;
5701   __ cmp(Operand(temp, StandardFrameConstants::kContextOffset),
5702          Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
5703   __ j(not_equal, &check_frame_marker, Label::kNear);
5704   __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset));
5705
5706   // Check the marker in the calling frame.
5707   __ bind(&check_frame_marker);
5708   __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset),
5709          Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
5710 }
5711
5712
5713 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
5714   if (!info()->IsStub()) {
5715     // Ensure that we have enough space after the previous lazy-bailout
5716     // instruction for patching the code here.
5717     int current_pc = masm()->pc_offset();
5718     if (current_pc < last_lazy_deopt_pc_ + space_needed) {
5719       int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
5720       __ Nop(padding_size);
5721     }
5722   }
5723   last_lazy_deopt_pc_ = masm()->pc_offset();
5724 }
5725
5726
5727 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
5728   last_lazy_deopt_pc_ = masm()->pc_offset();
5729   DCHECK(instr->HasEnvironment());
5730   LEnvironment* env = instr->environment();
5731   RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
5732   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
5733 }
5734
5735
5736 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
5737   Deoptimizer::BailoutType type = instr->hydrogen()->type();
5738   // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
5739   // needed return address), even though the implementation of LAZY and EAGER is
5740   // now identical. When LAZY is eventually completely folded into EAGER, remove
5741   // the special case below.
5742   if (info()->IsStub() && type == Deoptimizer::EAGER) {
5743     type = Deoptimizer::LAZY;
5744   }
5745   DeoptimizeIf(no_condition, instr, instr->hydrogen()->reason(), type);
5746 }
5747
5748
5749 void LCodeGen::DoDummy(LDummy* instr) {
5750   // Nothing to see here, move on!
5751 }
5752
5753
5754 void LCodeGen::DoDummyUse(LDummyUse* instr) {
5755   // Nothing to see here, move on!
5756 }
5757
5758
5759 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
5760   PushSafepointRegistersScope scope(this);
5761   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
5762   __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
5763   RecordSafepointWithLazyDeopt(
5764       instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
5765   DCHECK(instr->HasEnvironment());
5766   LEnvironment* env = instr->environment();
5767   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
5768 }
5769
5770
5771 void LCodeGen::DoStackCheck(LStackCheck* instr) {
5772   class DeferredStackCheck FINAL : public LDeferredCode {
5773    public:
5774     DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
5775         : LDeferredCode(codegen), instr_(instr) { }
5776     virtual void Generate() OVERRIDE {
5777       codegen()->DoDeferredStackCheck(instr_);
5778     }
5779     virtual LInstruction* instr() OVERRIDE { return instr_; }
5780    private:
5781     LStackCheck* instr_;
5782   };
5783
5784   DCHECK(instr->HasEnvironment());
5785   LEnvironment* env = instr->environment();
5786   // There is no LLazyBailout instruction for stack-checks. We have to
5787   // prepare for lazy deoptimization explicitly here.
5788   if (instr->hydrogen()->is_function_entry()) {
5789     // Perform stack overflow check.
5790     Label done;
5791     ExternalReference stack_limit =
5792         ExternalReference::address_of_stack_limit(isolate());
5793     __ cmp(esp, Operand::StaticVariable(stack_limit));
5794     __ j(above_equal, &done, Label::kNear);
5795
5796     DCHECK(instr->context()->IsRegister());
5797     DCHECK(ToRegister(instr->context()).is(esi));
5798     CallCode(isolate()->builtins()->StackCheck(),
5799              RelocInfo::CODE_TARGET,
5800              instr);
5801     __ bind(&done);
5802   } else {
5803     DCHECK(instr->hydrogen()->is_backwards_branch());
5804     // Perform stack overflow check if this goto needs it before jumping.
5805     DeferredStackCheck* deferred_stack_check =
5806         new(zone()) DeferredStackCheck(this, instr);
5807     ExternalReference stack_limit =
5808         ExternalReference::address_of_stack_limit(isolate());
5809     __ cmp(esp, Operand::StaticVariable(stack_limit));
5810     __ j(below, deferred_stack_check->entry());
5811     EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
5812     __ bind(instr->done_label());
5813     deferred_stack_check->SetExit(instr->done_label());
5814     RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
5815     // Don't record a deoptimization index for the safepoint here.
5816     // This will be done explicitly when emitting call and the safepoint in
5817     // the deferred code.
5818   }
5819 }
5820
5821
5822 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
5823   // This is a pseudo-instruction that ensures that the environment here is
5824   // properly registered for deoptimization and records the assembler's PC
5825   // offset.
5826   LEnvironment* environment = instr->environment();
5827
5828   // If the environment were already registered, we would have no way of
5829   // backpatching it with the spill slot operands.
5830   DCHECK(!environment->HasBeenRegistered());
5831   RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
5832
5833   GenerateOsrPrologue();
5834 }
5835
5836
5837 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
5838   DCHECK(ToRegister(instr->context()).is(esi));
5839   __ cmp(eax, isolate()->factory()->undefined_value());
5840   DeoptimizeIf(equal, instr, "undefined");
5841
5842   __ cmp(eax, isolate()->factory()->null_value());
5843   DeoptimizeIf(equal, instr, "null");
5844
5845   __ test(eax, Immediate(kSmiTagMask));
5846   DeoptimizeIf(zero, instr, "Smi");
5847
5848   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
5849   __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx);
5850   DeoptimizeIf(below_equal, instr, "wrong instance type");
5851
5852   Label use_cache, call_runtime;
5853   __ CheckEnumCache(&call_runtime);
5854
5855   __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
5856   __ jmp(&use_cache, Label::kNear);
5857
5858   // Get the set of properties to enumerate.
5859   __ bind(&call_runtime);
5860   __ push(eax);
5861   CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
5862
5863   __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
5864          isolate()->factory()->meta_map());
5865   DeoptimizeIf(not_equal, instr, "wrong map");
5866   __ bind(&use_cache);
5867 }
5868
5869
5870 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
5871   Register map = ToRegister(instr->map());
5872   Register result = ToRegister(instr->result());
5873   Label load_cache, done;
5874   __ EnumLength(result, map);
5875   __ cmp(result, Immediate(Smi::FromInt(0)));
5876   __ j(not_equal, &load_cache, Label::kNear);
5877   __ mov(result, isolate()->factory()->empty_fixed_array());
5878   __ jmp(&done, Label::kNear);
5879
5880   __ bind(&load_cache);
5881   __ LoadInstanceDescriptors(map, result);
5882   __ mov(result,
5883          FieldOperand(result, DescriptorArray::kEnumCacheOffset));
5884   __ mov(result,
5885          FieldOperand(result, FixedArray::SizeFor(instr->idx())));
5886   __ bind(&done);
5887   __ test(result, result);
5888   DeoptimizeIf(equal, instr, "no cache");
5889 }
5890
5891
5892 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
5893   Register object = ToRegister(instr->value());
5894   __ cmp(ToRegister(instr->map()),
5895          FieldOperand(object, HeapObject::kMapOffset));
5896   DeoptimizeIf(not_equal, instr, "wrong map");
5897 }
5898
5899
5900 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
5901                                            Register object,
5902                                            Register index) {
5903   PushSafepointRegistersScope scope(this);
5904   __ push(object);
5905   __ push(index);
5906   __ xor_(esi, esi);
5907   __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble);
5908   RecordSafepointWithRegisters(
5909       instr->pointer_map(), 2, Safepoint::kNoLazyDeopt);
5910   __ StoreToSafepointRegisterSlot(object, eax);
5911 }
5912
5913
5914 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
5915   class DeferredLoadMutableDouble FINAL : public LDeferredCode {
5916    public:
5917     DeferredLoadMutableDouble(LCodeGen* codegen,
5918                               LLoadFieldByIndex* instr,
5919                               Register object,
5920                               Register index)
5921         : LDeferredCode(codegen),
5922           instr_(instr),
5923           object_(object),
5924           index_(index) {
5925     }
5926     virtual void Generate() OVERRIDE {
5927       codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_);
5928     }
5929     virtual LInstruction* instr() OVERRIDE { return instr_; }
5930    private:
5931     LLoadFieldByIndex* instr_;
5932     Register object_;
5933     Register index_;
5934   };
5935
5936   Register object = ToRegister(instr->object());
5937   Register index = ToRegister(instr->index());
5938
5939   DeferredLoadMutableDouble* deferred;
5940   deferred = new(zone()) DeferredLoadMutableDouble(
5941       this, instr, object, index);
5942
5943   Label out_of_object, done;
5944   __ test(index, Immediate(Smi::FromInt(1)));
5945   __ j(not_zero, deferred->entry());
5946
5947   __ sar(index, 1);
5948
5949   __ cmp(index, Immediate(0));
5950   __ j(less, &out_of_object, Label::kNear);
5951   __ mov(object, FieldOperand(object,
5952                               index,
5953                               times_half_pointer_size,
5954                               JSObject::kHeaderSize));
5955   __ jmp(&done, Label::kNear);
5956
5957   __ bind(&out_of_object);
5958   __ mov(object, FieldOperand(object, JSObject::kPropertiesOffset));
5959   __ neg(index);
5960   // Index is now equal to out of object property index plus 1.
5961   __ mov(object, FieldOperand(object,
5962                               index,
5963                               times_half_pointer_size,
5964                               FixedArray::kHeaderSize - kPointerSize));
5965   __ bind(deferred->exit());
5966   __ bind(&done);
5967 }
5968
5969
5970 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) {
5971   Register context = ToRegister(instr->context());
5972   __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), context);
5973 }
5974
5975
5976 void LCodeGen::DoAllocateBlockContext(LAllocateBlockContext* instr) {
5977   Handle<ScopeInfo> scope_info = instr->scope_info();
5978   __ Push(scope_info);
5979   __ push(ToRegister(instr->function()));
5980   CallRuntime(Runtime::kPushBlockContext, 2, instr);
5981   RecordSafepoint(Safepoint::kNoLazyDeopt);
5982 }
5983
5984
5985 template<class T>
5986 void LCodeGen::HandleSIMD128ToTagged(LSIMD128ToTagged* instr) {
5987   class DeferredSIMD128ToTagged FINAL : public LDeferredCode {
5988    public:
5989     DeferredSIMD128ToTagged(LCodeGen* codegen,
5990         LInstruction* instr,
5991         Runtime::FunctionId id)
5992       : LDeferredCode(codegen), instr_(instr), id_(id) { }
5993     virtual void Generate() OVERRIDE {
5994       codegen()->DoDeferredSIMD128ToTagged(instr_, id_);
5995     }
5996     virtual LInstruction* instr() OVERRIDE { return instr_; }
5997    private:
5998     LInstruction* instr_;
5999     Runtime::FunctionId id_;
6000   };
6001
6002   XMMRegister input_reg = ToSIMD128Register(instr->value());
6003   Register reg = ToRegister(instr->result());
6004   Register tmp = ToRegister(instr->temp());
6005   Register tmp2 = ToRegister(instr->temp2());
6006
6007   DeferredSIMD128ToTagged* deferred = new(zone()) DeferredSIMD128ToTagged(
6008       this, instr, static_cast<Runtime::FunctionId>(T::kRuntimeAllocatorId()));
6009
6010   if (FLAG_inline_new) {
6011     if (T::kInstanceType == FLOAT32x4_TYPE) {
6012       __ AllocateFloat32x4(reg, tmp, tmp2, deferred->entry());
6013     } else if (T::kInstanceType == INT32x4_TYPE) {
6014       __ AllocateInt32x4(reg, tmp, tmp2, deferred->entry());
6015     } else if (T::kInstanceType == FLOAT64x2_TYPE) {
6016       __ AllocateFloat64x2(reg, tmp, tmp2, deferred->entry());
6017     }
6018   } else {
6019     __ jmp(deferred->entry());
6020   }
6021   __ bind(deferred->exit());
6022
6023   // Load the inner FixedTypedArray object.
6024   __ mov(tmp, FieldOperand(reg, T::kValueOffset));
6025
6026   __ movups(FieldOperand(tmp, FixedTypedArrayBase::kDataOffset), input_reg);
6027 }
6028
6029
6030 void LCodeGen::DoSIMD128ToTagged(LSIMD128ToTagged* instr) {
6031   if (instr->value()->IsFloat32x4Register()) {
6032     HandleSIMD128ToTagged<Float32x4>(instr);
6033   } else if (instr->value()->IsFloat64x2Register()) {
6034     HandleSIMD128ToTagged<Float64x2>(instr);
6035   } else {
6036     DCHECK(instr->value()->IsInt32x4Register());
6037     HandleSIMD128ToTagged<Int32x4>(instr);
6038   }
6039 }
6040
6041
6042 template<class T>
6043 void LCodeGen::HandleTaggedToSIMD128(LTaggedToSIMD128* instr) {
6044   LOperand* input = instr->value();
6045   DCHECK(input->IsRegister());
6046   LOperand* result = instr->result();
6047   DCHECK(result->IsSIMD128Register());
6048
6049   Register input_reg = ToRegister(input);
6050   Register temp_reg = ToRegister(instr->temp());
6051   XMMRegister result_reg = ToSIMD128Register(result);
6052
6053   __ test(input_reg, Immediate(kSmiTagMask));
6054   DeoptimizeIf(zero, instr, "value is smi");
6055   __ CmpObjectType(input_reg, T::kInstanceType, temp_reg);
6056   DeoptimizeIf(not_equal, instr, "value is not simd128");
6057
6058   // Load the inner FixedTypedArray object.
6059   __ mov(temp_reg, FieldOperand(input_reg, T::kValueOffset));
6060
6061   __ movups(
6062       result_reg, FieldOperand(temp_reg, FixedTypedArrayBase::kDataOffset));
6063 }
6064
6065
6066 void LCodeGen::DoTaggedToSIMD128(LTaggedToSIMD128* instr) {
6067   if (instr->representation().IsFloat32x4()) {
6068     HandleTaggedToSIMD128<Float32x4>(instr);
6069   } else if (instr->representation().IsFloat64x2()) {
6070     HandleTaggedToSIMD128<Float64x2>(instr);
6071   } else {
6072     DCHECK(instr->representation().IsInt32x4());
6073     HandleTaggedToSIMD128<Int32x4>(instr);
6074   }
6075 }
6076
6077
6078 void LCodeGen::DoNullarySIMDOperation(LNullarySIMDOperation* instr) {
6079   switch (instr->op()) {
6080     case kFloat32x4Zero: {
6081       XMMRegister result_reg = ToFloat32x4Register(instr->result());
6082       __ xorps(result_reg, result_reg);
6083       return;
6084     }
6085     case kFloat64x2Zero: {
6086       XMMRegister result_reg = ToFloat64x2Register(instr->result());
6087       __ xorpd(result_reg, result_reg);
6088       return;
6089     }
6090     case kInt32x4Zero: {
6091       XMMRegister result_reg = ToInt32x4Register(instr->result());
6092       __ xorps(result_reg, result_reg);
6093       return;
6094     }
6095     default:
6096       UNREACHABLE();
6097       return;
6098   }
6099 }
6100
6101
6102 void LCodeGen::DoUnarySIMDOperation(LUnarySIMDOperation* instr) {
6103   uint8_t select = 0;
6104   switch (instr->op()) {
6105     case kFloat32x4Coercion: {
6106       XMMRegister input_reg = ToFloat32x4Register(instr->value());
6107       XMMRegister result_reg = ToFloat32x4Register(instr->result());
6108       if (!result_reg.is(input_reg)) {
6109         __ movaps(result_reg, input_reg);
6110       }
6111       return;
6112     }
6113     case kFloat64x2Coercion: {
6114       XMMRegister input_reg = ToFloat64x2Register(instr->value());
6115       XMMRegister result_reg = ToFloat64x2Register(instr->result());
6116       if (!result_reg.is(input_reg)) {
6117         __ movaps(result_reg, input_reg);
6118       }
6119       return;
6120     }
6121     case kInt32x4Coercion: {
6122       XMMRegister input_reg = ToInt32x4Register(instr->value());
6123       XMMRegister result_reg = ToInt32x4Register(instr->result());
6124       if (!result_reg.is(input_reg)) {
6125         __ movaps(result_reg, input_reg);
6126       }
6127       return;
6128     }
6129     case kSIMD128Change: {
6130       Comment(";;; deoptimize: can not perform representation change"
6131               "for float32x4 or int32x4");
6132       DeoptimizeIf(no_condition, instr, "cannot perform representation change"
6133                    "for float32x4 or int32x4");
6134       return;
6135     }
6136     case kFloat32x4Abs:
6137     case kFloat32x4Neg:
6138     case kFloat32x4Reciprocal:
6139     case kFloat32x4ReciprocalSqrt:
6140     case kFloat32x4Sqrt: {
6141       DCHECK(instr->value()->Equals(instr->result()));
6142       DCHECK(instr->hydrogen()->value()->representation().IsFloat32x4());
6143       XMMRegister input_reg = ToFloat32x4Register(instr->value());
6144       switch (instr->op()) {
6145         case kFloat32x4Abs:
6146           __ absps(input_reg);
6147           break;
6148         case kFloat32x4Neg:
6149           __ negateps(input_reg);
6150           break;
6151         case kFloat32x4Reciprocal:
6152           __ rcpps(input_reg, input_reg);
6153           break;
6154         case kFloat32x4ReciprocalSqrt:
6155           __ rsqrtps(input_reg, input_reg);
6156           break;
6157         case kFloat32x4Sqrt:
6158           __ sqrtps(input_reg, input_reg);
6159           break;
6160         default:
6161           UNREACHABLE();
6162           break;
6163         }
6164       return;
6165     }
6166     case kFloat64x2Abs:
6167     case kFloat64x2Neg:
6168     case kFloat64x2Sqrt: {
6169       DCHECK(instr->value()->Equals(instr->result()));
6170       DCHECK(instr->hydrogen()->value()->representation().IsFloat64x2());
6171       XMMRegister input_reg = ToFloat64x2Register(instr->value());
6172       switch (instr->op()) {
6173         case kFloat64x2Abs:
6174           __ abspd(input_reg);
6175           break;
6176         case kFloat64x2Neg:
6177           __ negatepd(input_reg);
6178           break;
6179         case kFloat64x2Sqrt:
6180           __ sqrtpd(input_reg, input_reg);
6181           break;
6182         default:
6183           UNREACHABLE();
6184           break;
6185         }
6186       return;
6187     }
6188     case kInt32x4Not:
6189     case kInt32x4Neg: {
6190       DCHECK(instr->hydrogen()->value()->representation().IsInt32x4());
6191       XMMRegister input_reg = ToInt32x4Register(instr->value());
6192       switch (instr->op()) {
6193         case kInt32x4Not:
6194           __ notps(input_reg);
6195           break;
6196         case kInt32x4Neg:
6197           __ pnegd(input_reg);
6198           break;
6199         default:
6200           UNREACHABLE();
6201           break;
6202       }
6203       return;
6204     }
6205     case kFloat32x4BitsToInt32x4:
6206     case kFloat32x4ToInt32x4: {
6207       DCHECK(instr->hydrogen()->value()->representation().IsFloat32x4());
6208       XMMRegister input_reg = ToFloat32x4Register(instr->value());
6209       XMMRegister result_reg = ToInt32x4Register(instr->result());
6210       if (instr->op() == kFloat32x4BitsToInt32x4) {
6211         if (!result_reg.is(input_reg)) {
6212           __ movaps(result_reg, input_reg);
6213         }
6214       } else {
6215         DCHECK(instr->op() == kFloat32x4ToInt32x4);
6216         __ cvtps2dq(result_reg, input_reg);
6217       }
6218       return;
6219     }
6220     case kInt32x4BitsToFloat32x4:
6221     case kInt32x4ToFloat32x4: {
6222       DCHECK(instr->hydrogen()->value()->representation().IsInt32x4());
6223       XMMRegister input_reg = ToInt32x4Register(instr->value());
6224       XMMRegister result_reg = ToFloat32x4Register(instr->result());
6225       if (instr->op() == kInt32x4BitsToFloat32x4) {
6226         if (!result_reg.is(input_reg)) {
6227           __ movaps(result_reg, input_reg);
6228         }
6229       } else {
6230         DCHECK(instr->op() == kInt32x4ToFloat32x4);
6231         __ cvtdq2ps(result_reg, input_reg);
6232       }
6233       return;
6234     }
6235     case kFloat32x4Splat: {
6236       DCHECK(instr->hydrogen()->value()->representation().IsDouble());
6237       XMMRegister input_reg = ToDoubleRegister(instr->value());
6238       XMMRegister result_reg = ToFloat32x4Register(instr->result());
6239       XMMRegister xmm_scratch = xmm0;
6240       __ xorps(xmm_scratch, xmm_scratch);
6241       __ cvtsd2ss(xmm_scratch, input_reg);
6242       __ shufps(xmm_scratch, xmm_scratch, 0x0);
6243       __ movaps(result_reg, xmm_scratch);
6244       return;
6245     }
6246     case kInt32x4Splat: {
6247       DCHECK(instr->hydrogen()->value()->representation().IsInteger32());
6248       Register input_reg = ToRegister(instr->value());
6249       XMMRegister result_reg = ToInt32x4Register(instr->result());
6250       __ movd(result_reg, input_reg);
6251       __ shufps(result_reg, result_reg, 0x0);
6252       return;
6253     }
6254     case kInt32x4GetSignMask: {
6255       DCHECK(instr->hydrogen()->value()->representation().IsInt32x4());
6256       XMMRegister input_reg = ToInt32x4Register(instr->value());
6257       Register result = ToRegister(instr->result());
6258       __ movmskps(result, input_reg);
6259       return;
6260     }
6261     case kFloat32x4GetSignMask: {
6262       DCHECK(instr->hydrogen()->value()->representation().IsFloat32x4());
6263       XMMRegister input_reg = ToFloat32x4Register(instr->value());
6264       Register result = ToRegister(instr->result());
6265       __ movmskps(result, input_reg);
6266       return;
6267     }
6268     case kFloat32x4GetW:
6269       select++;
6270     case kFloat32x4GetZ:
6271       select++;
6272     case kFloat32x4GetY:
6273       select++;
6274     case kFloat32x4GetX: {
6275       DCHECK(instr->hydrogen()->value()->representation().IsFloat32x4());
6276       XMMRegister input_reg = ToFloat32x4Register(instr->value());
6277       XMMRegister result = ToDoubleRegister(instr->result());
6278       XMMRegister xmm_scratch = result.is(input_reg) ? xmm0 : result;
6279
6280       if (select == 0x0) {
6281         __ xorps(xmm_scratch, xmm_scratch);
6282         __ cvtss2sd(xmm_scratch, input_reg);
6283         if (!xmm_scratch.is(result)) {
6284           __ movaps(result, xmm_scratch);
6285         }
6286       } else {
6287         __ pshufd(xmm_scratch, input_reg, select);
6288         if (!xmm_scratch.is(result)) {
6289            __ xorps(result, result);
6290         }
6291         __ cvtss2sd(result, xmm_scratch);
6292       }
6293       return;
6294     }
6295     case kFloat64x2GetSignMask: {
6296       DCHECK(instr->hydrogen()->value()->representation().IsFloat64x2());
6297       XMMRegister input_reg = ToFloat64x2Register(instr->value());
6298       Register result = ToRegister(instr->result());
6299       __ movmskpd(result, input_reg);
6300       return;
6301     }
6302     case kFloat64x2GetX: {
6303       DCHECK(instr->hydrogen()->value()->representation().IsFloat64x2());
6304       XMMRegister input_reg = ToFloat64x2Register(instr->value());
6305       XMMRegister result = ToDoubleRegister(instr->result());
6306
6307       if (!input_reg.is(result)) {
6308         __ movaps(result, input_reg);
6309       }
6310       return;
6311     }
6312     case kFloat64x2GetY: {
6313       DCHECK(instr->hydrogen()->value()->representation().IsFloat64x2());
6314       XMMRegister input_reg = ToFloat64x2Register(instr->value());
6315       XMMRegister result = ToDoubleRegister(instr->result());
6316
6317       if (!input_reg.is(result)) {
6318         __ movaps(result, input_reg);
6319       }
6320       __ shufpd(result, input_reg, 0x1);
6321       return;
6322     }
6323     case kInt32x4GetX:
6324     case kInt32x4GetY:
6325     case kInt32x4GetZ:
6326     case kInt32x4GetW:
6327     case kInt32x4GetFlagX:
6328     case kInt32x4GetFlagY:
6329     case kInt32x4GetFlagZ:
6330     case kInt32x4GetFlagW: {
6331       DCHECK(instr->hydrogen()->value()->representation().IsInt32x4());
6332       bool flag = false;
6333       switch (instr->op()) {
6334         case kInt32x4GetFlagX:
6335           flag = true;
6336         case kInt32x4GetX:
6337           break;
6338         case kInt32x4GetFlagY:
6339           flag = true;
6340         case kInt32x4GetY:
6341           select = 0x1;
6342           break;
6343         case kInt32x4GetFlagZ:
6344           flag = true;
6345         case kInt32x4GetZ:
6346           select = 0x2;
6347           break;
6348         case kInt32x4GetFlagW:
6349           flag = true;
6350         case kInt32x4GetW:
6351           select = 0x3;
6352           break;
6353         default:
6354           UNREACHABLE();
6355       }
6356
6357       XMMRegister input_reg = ToInt32x4Register(instr->value());
6358       Register result = ToRegister(instr->result());
6359       if (select == 0x0) {
6360         __ movd(result, input_reg);
6361       } else {
6362         if (CpuFeatures::IsSupported(SSE4_1)) {
6363           CpuFeatureScope scope(masm(), SSE4_1);
6364           __ extractps(result, input_reg, select);
6365         } else {
6366           XMMRegister xmm_scratch = xmm0;
6367           __ pshufd(xmm_scratch, input_reg, select);
6368           __ movd(result, xmm_scratch);
6369         }
6370       }
6371
6372       if (flag) {
6373         Label false_value, done;
6374         __ test(result, result);
6375         __ j(zero, &false_value, Label::kNear);
6376         __ LoadRoot(result, Heap::kTrueValueRootIndex);
6377         __ jmp(&done, Label::kNear);
6378         __ bind(&false_value);
6379         __ LoadRoot(result, Heap::kFalseValueRootIndex);
6380         __ bind(&done);
6381       }
6382       return;
6383     }
6384     default:
6385       UNREACHABLE();
6386       return;
6387   }
6388 }
6389
6390
6391 void LCodeGen::DoBinarySIMDOperation(LBinarySIMDOperation* instr) {
6392   uint8_t imm8 = 0;  // for with operation
6393   switch (instr->op()) {
6394     case kFloat32x4Add:
6395     case kFloat32x4Sub:
6396     case kFloat32x4Mul:
6397     case kFloat32x4Div:
6398     case kFloat32x4Min:
6399     case kFloat32x4Max: {
6400       DCHECK(instr->left()->Equals(instr->result()));
6401       DCHECK(instr->hydrogen()->left()->representation().IsFloat32x4());
6402       DCHECK(instr->hydrogen()->right()->representation().IsFloat32x4());
6403       XMMRegister left_reg = ToFloat32x4Register(instr->left());
6404       XMMRegister right_reg = ToFloat32x4Register(instr->right());
6405       switch (instr->op()) {
6406         case kFloat32x4Add:
6407           __ addps(left_reg, right_reg);
6408           break;
6409         case kFloat32x4Sub:
6410           __ subps(left_reg, right_reg);
6411           break;
6412         case kFloat32x4Mul:
6413           __ mulps(left_reg, right_reg);
6414           break;
6415         case kFloat32x4Div:
6416           __ divps(left_reg, right_reg);
6417           break;
6418         case kFloat32x4Min:
6419           __ minps(left_reg, right_reg);
6420           break;
6421         case kFloat32x4Max:
6422           __ maxps(left_reg, right_reg);
6423           break;
6424         default:
6425           UNREACHABLE();
6426           break;
6427       }
6428       return;
6429     }
6430     case kFloat32x4Scale: {
6431       DCHECK(instr->left()->Equals(instr->result()));
6432       DCHECK(instr->hydrogen()->left()->representation().IsFloat32x4());
6433       DCHECK(instr->hydrogen()->right()->representation().IsDouble());
6434       XMMRegister left_reg = ToFloat32x4Register(instr->left());
6435       XMMRegister right_reg = ToDoubleRegister(instr->right());
6436       XMMRegister scratch_reg = xmm0;
6437       __ xorps(scratch_reg, scratch_reg);
6438       __ cvtsd2ss(scratch_reg, right_reg);
6439       __ shufps(scratch_reg, scratch_reg, 0x0);
6440       __ mulps(left_reg, scratch_reg);
6441       return;
6442     }
6443     case kFloat64x2Add:
6444     case kFloat64x2Sub:
6445     case kFloat64x2Mul:
6446     case kFloat64x2Div:
6447     case kFloat64x2Min:
6448     case kFloat64x2Max: {
6449       DCHECK(instr->left()->Equals(instr->result()));
6450       DCHECK(instr->hydrogen()->left()->representation().IsFloat64x2());
6451       DCHECK(instr->hydrogen()->right()->representation().IsFloat64x2());
6452       XMMRegister left_reg = ToFloat64x2Register(instr->left());
6453       XMMRegister right_reg = ToFloat64x2Register(instr->right());
6454       switch (instr->op()) {
6455         case kFloat64x2Add:
6456           __ addpd(left_reg, right_reg);
6457           break;
6458         case kFloat64x2Sub:
6459           __ subpd(left_reg, right_reg);
6460           break;
6461         case kFloat64x2Mul:
6462           __ mulpd(left_reg, right_reg);
6463           break;
6464         case kFloat64x2Div:
6465           __ divpd(left_reg, right_reg);
6466           break;
6467         case kFloat64x2Min:
6468           __ minpd(left_reg, right_reg);
6469           break;
6470         case kFloat64x2Max:
6471           __ maxpd(left_reg, right_reg);
6472           break;
6473         default:
6474           UNREACHABLE();
6475           break;
6476       }
6477       return;
6478     }
6479     case kFloat64x2Scale: {
6480       DCHECK(instr->left()->Equals(instr->result()));
6481       DCHECK(instr->hydrogen()->left()->representation().IsFloat64x2());
6482       DCHECK(instr->hydrogen()->right()->representation().IsDouble());
6483       XMMRegister left_reg = ToFloat64x2Register(instr->left());
6484       XMMRegister right_reg = ToDoubleRegister(instr->right());
6485       __ shufpd(right_reg, right_reg, 0x0);
6486       __ mulpd(left_reg, right_reg);
6487       return;
6488     }
6489     case kFloat32x4Shuffle: {
6490       DCHECK(instr->left()->Equals(instr->result()));
6491       DCHECK(instr->hydrogen()->left()->representation().IsFloat32x4());
6492       if (instr->hydrogen()->right()->IsConstant() &&
6493           HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) {
6494         int32_t value = ToInteger32(LConstantOperand::cast(instr->right()));
6495         uint8_t select = static_cast<uint8_t>(value & 0xFF);
6496         XMMRegister left_reg = ToFloat32x4Register(instr->left());
6497         __ shufps(left_reg, left_reg, select);
6498         return;
6499       } else {
6500         Comment(";;; deoptimize: non-constant selector for shuffle");
6501         DeoptimizeIf(no_condition, instr, "non-constant selector for shuffle");
6502         return;
6503       }
6504     }
6505     case kInt32x4Shuffle: {
6506       DCHECK(instr->left()->Equals(instr->result()));
6507       DCHECK(instr->hydrogen()->left()->representation().IsInt32x4());
6508       if (instr->hydrogen()->right()->IsConstant() &&
6509           HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) {
6510         int32_t value = ToInteger32(LConstantOperand::cast(instr->right()));
6511         uint8_t select = static_cast<uint8_t>(value & 0xFF);
6512         XMMRegister left_reg = ToInt32x4Register(instr->left());
6513         __ pshufd(left_reg, left_reg, select);
6514         return;
6515       } else {
6516         Comment(";;; deoptimize: non-constant selector for shuffle");
6517         DeoptimizeIf(no_condition, instr, "non-constant selector for shuffle");
6518         return;
6519       }
6520     }
6521     case kInt32x4ShiftLeft:
6522     case kInt32x4ShiftRight:
6523     case kInt32x4ShiftRightArithmetic: {
6524       DCHECK(instr->left()->Equals(instr->result()));
6525       DCHECK(instr->hydrogen()->left()->representation().IsInt32x4());
6526       if (instr->hydrogen()->right()->IsConstant() &&
6527           HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) {
6528         int32_t value = ToInteger32(LConstantOperand::cast(instr->right()));
6529         uint8_t shift = static_cast<uint8_t>(value & 0xFF);
6530         XMMRegister left_reg = ToInt32x4Register(instr->left());
6531         switch (instr->op()) {
6532           case kInt32x4ShiftLeft:
6533             __ pslld(left_reg, shift);
6534             break;
6535           case kInt32x4ShiftRight:
6536             __ psrld(left_reg, shift);
6537             break;
6538           case kInt32x4ShiftRightArithmetic:
6539             __ psrad(left_reg, shift);
6540             break;
6541           default:
6542             UNREACHABLE();
6543         }
6544         return;
6545       } else {
6546         XMMRegister left_reg = ToInt32x4Register(instr->left());
6547         Register shift = ToRegister(instr->right());
6548         XMMRegister xmm_scratch = double_scratch0();
6549         __ movd(xmm_scratch, shift);
6550         switch (instr->op()) {
6551           case kInt32x4ShiftLeft:
6552             __ pslld(left_reg, xmm_scratch);
6553             break;
6554           case kInt32x4ShiftRight:
6555             __ psrld(left_reg, xmm_scratch);
6556             break;
6557           case kInt32x4ShiftRightArithmetic:
6558             __ psrad(left_reg, xmm_scratch);
6559             break;
6560           default:
6561             UNREACHABLE();
6562         }
6563         return;
6564       }
6565     }
6566     case kFloat32x4LessThan:
6567     case kFloat32x4LessThanOrEqual:
6568     case kFloat32x4Equal:
6569     case kFloat32x4NotEqual:
6570     case kFloat32x4GreaterThanOrEqual:
6571     case kFloat32x4GreaterThan: {
6572       DCHECK(instr->hydrogen()->left()->representation().IsFloat32x4());
6573       DCHECK(instr->hydrogen()->right()->representation().IsFloat32x4());
6574       XMMRegister left_reg = ToFloat32x4Register(instr->left());
6575       XMMRegister right_reg = ToFloat32x4Register(instr->right());
6576       XMMRegister result_reg = ToInt32x4Register(instr->result());
6577       switch (instr->op()) {
6578         case kFloat32x4LessThan:
6579           if (result_reg.is(left_reg)) {
6580             __ cmpltps(result_reg, right_reg);
6581           } else if (result_reg.is(right_reg)) {
6582             __ cmpnltps(result_reg, left_reg);
6583           } else {
6584             __ movaps(result_reg, left_reg);
6585             __ cmpltps(result_reg, right_reg);
6586           }
6587           break;
6588         case kFloat32x4LessThanOrEqual:
6589           if (result_reg.is(left_reg)) {
6590             __ cmpleps(result_reg, right_reg);
6591           } else if (result_reg.is(right_reg)) {
6592             __ cmpnleps(result_reg, left_reg);
6593           } else {
6594             __ movaps(result_reg, left_reg);
6595             __ cmpleps(result_reg, right_reg);
6596           }
6597           break;
6598         case kFloat32x4Equal:
6599           if (result_reg.is(left_reg)) {
6600             __ cmpeqps(result_reg, right_reg);
6601           } else if (result_reg.is(right_reg)) {
6602             __ cmpeqps(result_reg, left_reg);
6603           } else {
6604             __ movaps(result_reg, left_reg);
6605             __ cmpeqps(result_reg, right_reg);
6606           }
6607           break;
6608         case kFloat32x4NotEqual:
6609           if (result_reg.is(left_reg)) {
6610             __ cmpneqps(result_reg, right_reg);
6611           } else if (result_reg.is(right_reg)) {
6612             __ cmpneqps(result_reg, left_reg);
6613           } else {
6614             __ movaps(result_reg, left_reg);
6615             __ cmpneqps(result_reg, right_reg);
6616           }
6617           break;
6618         case kFloat32x4GreaterThanOrEqual:
6619           if (result_reg.is(left_reg)) {
6620             __ cmpnltps(result_reg, right_reg);
6621           } else if (result_reg.is(right_reg)) {
6622             __ cmpltps(result_reg, left_reg);
6623           } else {
6624             __ movaps(result_reg, left_reg);
6625             __ cmpnltps(result_reg, right_reg);
6626           }
6627           break;
6628         case kFloat32x4GreaterThan:
6629           if (result_reg.is(left_reg)) {
6630             __ cmpnleps(result_reg, right_reg);
6631           } else if (result_reg.is(right_reg)) {
6632             __ cmpleps(result_reg, left_reg);
6633           } else {
6634             __ movaps(result_reg, left_reg);
6635             __ cmpnleps(result_reg, right_reg);
6636           }
6637           break;
6638         default:
6639           UNREACHABLE();
6640           break;
6641       }
6642       return;
6643     }
6644     case kInt32x4And:
6645     case kInt32x4Or:
6646     case kInt32x4Xor:
6647     case kInt32x4Add:
6648     case kInt32x4Sub:
6649     case kInt32x4Mul:
6650     case kInt32x4GreaterThan:
6651     case kInt32x4Equal:
6652     case kInt32x4LessThan: {
6653       DCHECK(instr->left()->Equals(instr->result()));
6654       DCHECK(instr->hydrogen()->left()->representation().IsInt32x4());
6655       DCHECK(instr->hydrogen()->right()->representation().IsInt32x4());
6656       XMMRegister left_reg = ToInt32x4Register(instr->left());
6657       XMMRegister right_reg = ToInt32x4Register(instr->right());
6658       switch (instr->op()) {
6659         case kInt32x4And:
6660           __ andps(left_reg, right_reg);
6661           break;
6662         case kInt32x4Or:
6663           __ orps(left_reg, right_reg);
6664           break;
6665         case kInt32x4Xor:
6666           __ xorps(left_reg, right_reg);
6667           break;
6668         case kInt32x4Add:
6669           __ paddd(left_reg, right_reg);
6670           break;
6671         case kInt32x4Sub:
6672           __ psubd(left_reg, right_reg);
6673           break;
6674         case kInt32x4Mul:
6675           if (CpuFeatures::IsSupported(SSE4_1)) {
6676             CpuFeatureScope scope(masm(), SSE4_1);
6677             __ pmulld(left_reg, right_reg);
6678           } else {
6679             // The algorithm is from http://stackoverflow.com/questions/10500766/sse-multiplication-of-4-32-bit-integers
6680             XMMRegister xmm_scratch = xmm0;
6681             __ movaps(xmm_scratch, left_reg);
6682             __ pmuludq(left_reg, right_reg);
6683             __ psrldq(xmm_scratch, 4);
6684             __ psrldq(right_reg, 4);
6685             __ pmuludq(xmm_scratch, right_reg);
6686             __ pshufd(left_reg, left_reg, 8);
6687             __ pshufd(xmm_scratch, xmm_scratch, 8);
6688             __ punpackldq(left_reg, xmm_scratch);
6689           }
6690           break;
6691         case kInt32x4GreaterThan:
6692           __ pcmpgtd(left_reg, right_reg);
6693           break;
6694         case kInt32x4Equal:
6695           __ pcmpeqd(left_reg, right_reg);
6696           break;
6697         case kInt32x4LessThan: {
6698           XMMRegister xmm_scratch = xmm0;
6699           __ movaps(xmm_scratch, right_reg);
6700           __ pcmpgtd(xmm_scratch, left_reg);
6701           __ movaps(left_reg, xmm_scratch);
6702           break;
6703         }
6704         default:
6705           UNREACHABLE();
6706           break;
6707       }
6708       return;
6709     }
6710     case kFloat32x4WithW:
6711       imm8++;
6712     case kFloat32x4WithZ:
6713       imm8++;
6714     case kFloat32x4WithY:
6715       imm8++;
6716     case kFloat32x4WithX: {
6717       DCHECK(instr->left()->Equals(instr->result()));
6718       DCHECK(instr->hydrogen()->left()->representation().IsFloat32x4());
6719       DCHECK(instr->hydrogen()->right()->representation().IsDouble());
6720       XMMRegister left_reg = ToFloat32x4Register(instr->left());
6721       XMMRegister right_reg = ToDoubleRegister(instr->right());
6722       XMMRegister xmm_scratch = xmm0;
6723       __ xorps(xmm_scratch, xmm_scratch);
6724       __ cvtsd2ss(xmm_scratch, right_reg);
6725       if (CpuFeatures::IsSupported(SSE4_1)) {
6726         imm8 = imm8 << 4;
6727         CpuFeatureScope scope(masm(), SSE4_1);
6728         __ insertps(left_reg, xmm_scratch, imm8);
6729       } else {
6730         __ sub(esp, Immediate(kFloat32x4Size));
6731         __ movups(Operand(esp, 0), left_reg);
6732         __ movss(Operand(esp, imm8 * kFloatSize), xmm_scratch);
6733         __ movups(left_reg, Operand(esp, 0));
6734         __ add(esp, Immediate(kFloat32x4Size));
6735       }
6736       return;
6737     }
6738     case kFloat64x2WithX: {
6739       DCHECK(instr->left()->Equals(instr->result()));
6740       DCHECK(instr->hydrogen()->left()->representation().IsFloat64x2());
6741       DCHECK(instr->hydrogen()->right()->representation().IsDouble());
6742       XMMRegister left_reg = ToFloat64x2Register(instr->left());
6743       XMMRegister right_reg = ToDoubleRegister(instr->right());
6744       __ sub(esp, Immediate(kFloat64x2Size));
6745       __ movups(Operand(esp, 0), left_reg);
6746       __ movsd(Operand(esp, 0 * kDoubleSize), right_reg);
6747       __ movups(left_reg, Operand(esp, 0));
6748       __ add(esp, Immediate(kFloat64x2Size));
6749       return;
6750     }
6751     case kFloat64x2WithY: {
6752       DCHECK(instr->left()->Equals(instr->result()));
6753       DCHECK(instr->hydrogen()->left()->representation().IsFloat64x2());
6754       DCHECK(instr->hydrogen()->right()->representation().IsDouble());
6755       XMMRegister left_reg = ToFloat64x2Register(instr->left());
6756       XMMRegister right_reg = ToDoubleRegister(instr->right());
6757       __ sub(esp, Immediate(kFloat64x2Size));
6758       __ movups(Operand(esp, 0), left_reg);
6759       __ movsd(Operand(esp, 1 * kDoubleSize), right_reg);
6760       __ movups(left_reg, Operand(esp, 0));
6761       __ add(esp, Immediate(kFloat64x2Size));
6762       return;
6763     }
6764     case kFloat64x2Constructor: {
6765       DCHECK(instr->hydrogen()->left()->representation().IsDouble());
6766       DCHECK(instr->hydrogen()->right()->representation().IsDouble());
6767       XMMRegister left_reg = ToDoubleRegister(instr->left());
6768       XMMRegister right_reg = ToDoubleRegister(instr->right());
6769       XMMRegister result_reg = ToFloat64x2Register(instr->result());
6770       __ sub(esp, Immediate(kFloat64x2Size));
6771       __ movsd(Operand(esp, 0 * kDoubleSize), left_reg);
6772       __ movsd(Operand(esp, 1 * kDoubleSize), right_reg);
6773       __ movups(result_reg, Operand(esp, 0));
6774       __ add(esp, Immediate(kFloat64x2Size));
6775       return;
6776     }
6777     case kInt32x4WithW:
6778       imm8++;
6779     case kInt32x4WithZ:
6780       imm8++;
6781     case kInt32x4WithY:
6782       imm8++;
6783     case kInt32x4WithX: {
6784       DCHECK(instr->left()->Equals(instr->result()));
6785       DCHECK(instr->hydrogen()->left()->representation().IsInt32x4());
6786       DCHECK(instr->hydrogen()->right()->representation().IsInteger32());
6787       XMMRegister left_reg = ToInt32x4Register(instr->left());
6788       Register right_reg = ToRegister(instr->right());
6789       if (CpuFeatures::IsSupported(SSE4_1)) {
6790         CpuFeatureScope scope(masm(), SSE4_1);
6791         __ pinsrd(left_reg, right_reg, imm8);
6792       } else {
6793         __ sub(esp, Immediate(kInt32x4Size));
6794         __ movdqu(Operand(esp, 0), left_reg);
6795         __ mov(Operand(esp, imm8 * kFloatSize), right_reg);
6796         __ movdqu(left_reg, Operand(esp, 0));
6797         __ add(esp, Immediate(kInt32x4Size));
6798       }
6799       return;
6800     }
6801     case kInt32x4WithFlagW:
6802       imm8++;
6803     case kInt32x4WithFlagZ:
6804       imm8++;
6805     case kInt32x4WithFlagY:
6806       imm8++;
6807     case kInt32x4WithFlagX: {
6808       DCHECK(instr->left()->Equals(instr->result()));
6809       DCHECK(instr->hydrogen()->left()->representation().IsInt32x4());
6810       DCHECK(instr->hydrogen()->right()->representation().IsTagged());
6811       HType type = instr->hydrogen()->right()->type();
6812       XMMRegister left_reg = ToInt32x4Register(instr->left());
6813       Register right_reg = ToRegister(instr->right());
6814       Label load_false_value, done;
6815       if (type.IsBoolean()) {
6816         __ sub(esp, Immediate(kInt32x4Size));
6817         __ movups(Operand(esp, 0), left_reg);
6818         __ CompareRoot(right_reg, Heap::kTrueValueRootIndex);
6819         __ j(not_equal, &load_false_value, Label::kNear);
6820      } else {
6821         Comment(";;; deoptimize: other types for int32x4.withFlagX/Y/Z/W.");
6822         DeoptimizeIf(no_condition, instr,
6823                      "other types for int32x4.withFlagX/Y/Z/W");
6824         return;
6825      }
6826       // load true value.
6827       __ mov(Operand(esp, imm8 * kFloatSize), Immediate(0xFFFFFFFF));
6828       __ jmp(&done, Label::kNear);
6829       __ bind(&load_false_value);
6830       __ mov(Operand(esp, imm8 * kFloatSize), Immediate(0x0));
6831       __ bind(&done);
6832       __ movups(left_reg, Operand(esp, 0));
6833       __ add(esp, Immediate(kInt32x4Size));
6834       return;
6835     }
6836     default:
6837       UNREACHABLE();
6838       return;
6839   }
6840 }
6841
6842
6843 void LCodeGen::DoTernarySIMDOperation(LTernarySIMDOperation* instr) {
6844   switch (instr->op()) {
6845     case kFloat32x4Select: {
6846       DCHECK(instr->hydrogen()->first()->representation().IsInt32x4());
6847       DCHECK(instr->hydrogen()->second()->representation().IsFloat32x4());
6848       DCHECK(instr->hydrogen()->third()->representation().IsFloat32x4());
6849
6850       XMMRegister mask_reg = ToInt32x4Register(instr->first());
6851       XMMRegister left_reg = ToFloat32x4Register(instr->second());
6852       XMMRegister right_reg = ToFloat32x4Register(instr->third());
6853       XMMRegister result_reg = ToFloat32x4Register(instr->result());
6854       XMMRegister temp_reg = xmm0;
6855
6856       // Copy mask.
6857       __ movaps(temp_reg, mask_reg);
6858       // Invert it.
6859       __ notps(temp_reg);
6860       // temp_reg = temp_reg & falseValue.
6861       __ andps(temp_reg, right_reg);
6862
6863       if (!result_reg.is(mask_reg)) {
6864         if (result_reg.is(left_reg)) {
6865           // result_reg = result_reg & trueValue.
6866           __ andps(result_reg, mask_reg);
6867           // out = result_reg | temp_reg.
6868           __ orps(result_reg, temp_reg);
6869         } else {
6870           __ movaps(result_reg, mask_reg);
6871           // result_reg = result_reg & trueValue.
6872           __ andps(result_reg, left_reg);
6873           // out = result_reg | temp_reg.
6874           __ orps(result_reg, temp_reg);
6875         }
6876       } else {
6877         // result_reg = result_reg & trueValue.
6878         __ andps(result_reg, left_reg);
6879         // out = result_reg | temp_reg.
6880         __ orps(result_reg, temp_reg);
6881       }
6882       return;
6883     }
6884     case kInt32x4Select: {
6885       DCHECK(instr->hydrogen()->first()->representation().IsInt32x4());
6886       DCHECK(instr->hydrogen()->second()->representation().IsInt32x4());
6887       DCHECK(instr->hydrogen()->third()->representation().IsInt32x4());
6888
6889       XMMRegister mask_reg = ToInt32x4Register(instr->first());
6890       XMMRegister left_reg = ToInt32x4Register(instr->second());
6891       XMMRegister right_reg = ToInt32x4Register(instr->third());
6892       XMMRegister result_reg = ToInt32x4Register(instr->result());
6893       XMMRegister temp_reg = xmm0;
6894
6895       // Copy mask.
6896       __ movaps(temp_reg, mask_reg);
6897       // Invert it.
6898       __ notps(temp_reg);
6899       // temp_reg = temp_reg & falseValue.
6900       __ andps(temp_reg, right_reg);
6901
6902       if (!result_reg.is(mask_reg)) {
6903         if (result_reg.is(left_reg)) {
6904           // result_reg = result_reg & trueValue.
6905           __ andps(result_reg, mask_reg);
6906           // out = result_reg | temp_reg.
6907           __ orps(result_reg, temp_reg);
6908         } else {
6909           __ movaps(result_reg, mask_reg);
6910           // result_reg = result_reg & trueValue.
6911           __ andps(result_reg, left_reg);
6912           // out = result_reg | temp_reg.
6913           __ orps(result_reg, temp_reg);
6914         }
6915       } else {
6916         // result_reg = result_reg & trueValue.
6917         __ andps(result_reg, left_reg);
6918         // out = result_reg | temp_reg.
6919         __ orps(result_reg, temp_reg);
6920       }
6921       return;
6922     }
6923     case kFloat32x4ShuffleMix: {
6924       DCHECK(instr->first()->Equals(instr->result()));
6925       DCHECK(instr->hydrogen()->first()->representation().IsFloat32x4());
6926       DCHECK(instr->hydrogen()->second()->representation().IsFloat32x4());
6927       DCHECK(instr->hydrogen()->third()->representation().IsInteger32());
6928       if (instr->hydrogen()->third()->IsConstant() &&
6929           HConstant::cast(instr->hydrogen()->third())->HasInteger32Value()) {
6930         int32_t value = ToInteger32(LConstantOperand::cast(instr->third()));
6931         uint8_t select = static_cast<uint8_t>(value & 0xFF);
6932         XMMRegister first_reg = ToFloat32x4Register(instr->first());
6933         XMMRegister second_reg = ToFloat32x4Register(instr->second());
6934         __ shufps(first_reg, second_reg, select);
6935         return;
6936       } else {
6937         Comment(";;; deoptimize: non-constant selector for shuffle");
6938         DeoptimizeIf(no_condition, instr, "non-constant selector for shuffle");
6939         return;
6940       }
6941     }
6942     case kFloat32x4Clamp: {
6943       DCHECK(instr->first()->Equals(instr->result()));
6944       DCHECK(instr->hydrogen()->first()->representation().IsFloat32x4());
6945       DCHECK(instr->hydrogen()->second()->representation().IsFloat32x4());
6946       DCHECK(instr->hydrogen()->third()->representation().IsFloat32x4());
6947
6948       XMMRegister value_reg = ToFloat32x4Register(instr->first());
6949       XMMRegister lower_reg = ToFloat32x4Register(instr->second());
6950       XMMRegister upper_reg = ToFloat32x4Register(instr->third());
6951       __ minps(value_reg, upper_reg);
6952       __ maxps(value_reg, lower_reg);
6953       return;
6954     }
6955     case kFloat64x2Clamp: {
6956       DCHECK(instr->first()->Equals(instr->result()));
6957       DCHECK(instr->hydrogen()->first()->representation().IsFloat64x2());
6958       DCHECK(instr->hydrogen()->second()->representation().IsFloat64x2());
6959       DCHECK(instr->hydrogen()->third()->representation().IsFloat64x2());
6960
6961       XMMRegister value_reg = ToFloat64x2Register(instr->first());
6962       XMMRegister lower_reg = ToFloat64x2Register(instr->second());
6963       XMMRegister upper_reg = ToFloat64x2Register(instr->third());
6964       __ minpd(value_reg, upper_reg);
6965       __ maxpd(value_reg, lower_reg);
6966       return;
6967     }
6968     default:
6969       UNREACHABLE();
6970       return;
6971   }
6972 }
6973
6974
6975 void LCodeGen::DoQuarternarySIMDOperation(LQuarternarySIMDOperation* instr) {
6976   switch (instr->op()) {
6977     case kFloat32x4Constructor: {
6978       DCHECK(instr->hydrogen()->x()->representation().IsDouble());
6979       DCHECK(instr->hydrogen()->y()->representation().IsDouble());
6980       DCHECK(instr->hydrogen()->z()->representation().IsDouble());
6981       DCHECK(instr->hydrogen()->w()->representation().IsDouble());
6982       XMMRegister x_reg = ToDoubleRegister(instr->x());
6983       XMMRegister y_reg = ToDoubleRegister(instr->y());
6984       XMMRegister z_reg = ToDoubleRegister(instr->z());
6985       XMMRegister w_reg = ToDoubleRegister(instr->w());
6986       XMMRegister result_reg = ToFloat32x4Register(instr->result());
6987       __ sub(esp, Immediate(kFloat32x4Size));
6988       __ xorps(xmm0, xmm0);
6989       __ cvtsd2ss(xmm0, x_reg);
6990       __ movss(Operand(esp, 0 * kFloatSize), xmm0);
6991       __ xorps(xmm0, xmm0);
6992       __ cvtsd2ss(xmm0, y_reg);
6993       __ movss(Operand(esp, 1 * kFloatSize), xmm0);
6994       __ xorps(xmm0, xmm0);
6995       __ cvtsd2ss(xmm0, z_reg);
6996       __ movss(Operand(esp, 2 * kFloatSize), xmm0);
6997       __ xorps(xmm0, xmm0);
6998       __ cvtsd2ss(xmm0, w_reg);
6999       __ movss(Operand(esp, 3 * kFloatSize), xmm0);
7000       __ movups(result_reg, Operand(esp, 0 * kFloatSize));
7001       __ add(esp, Immediate(kFloat32x4Size));
7002       return;
7003     }
7004     case kInt32x4Constructor: {
7005       DCHECK(instr->hydrogen()->x()->representation().IsInteger32());
7006       DCHECK(instr->hydrogen()->y()->representation().IsInteger32());
7007       DCHECK(instr->hydrogen()->z()->representation().IsInteger32());
7008       DCHECK(instr->hydrogen()->w()->representation().IsInteger32());
7009       Register x_reg = ToRegister(instr->x());
7010       Register y_reg = ToRegister(instr->y());
7011       Register z_reg = ToRegister(instr->z());
7012       Register w_reg = ToRegister(instr->w());
7013       XMMRegister result_reg = ToInt32x4Register(instr->result());
7014       __ sub(esp, Immediate(kInt32x4Size));
7015       __ mov(Operand(esp, 0 * kInt32Size), x_reg);
7016       __ mov(Operand(esp, 1 * kInt32Size), y_reg);
7017       __ mov(Operand(esp, 2 * kInt32Size), z_reg);
7018       __ mov(Operand(esp, 3 * kInt32Size), w_reg);
7019       __ movups(result_reg, Operand(esp, 0 * kInt32Size));
7020       __ add(esp, Immediate(kInt32x4Size));
7021       return;
7022     }
7023     case kInt32x4Bool: {
7024       DCHECK(instr->hydrogen()->x()->representation().IsTagged());
7025       DCHECK(instr->hydrogen()->y()->representation().IsTagged());
7026       DCHECK(instr->hydrogen()->z()->representation().IsTagged());
7027       DCHECK(instr->hydrogen()->w()->representation().IsTagged());
7028       HType x_type = instr->hydrogen()->x()->type();
7029       HType y_type = instr->hydrogen()->y()->type();
7030       HType z_type = instr->hydrogen()->z()->type();
7031       HType w_type = instr->hydrogen()->w()->type();
7032       if (!x_type.IsBoolean() || !y_type.IsBoolean() ||
7033           !z_type.IsBoolean() || !w_type.IsBoolean()) {
7034         Comment(";;; deoptimize: other types for int32x4.bool.");
7035         DeoptimizeIf(no_condition, instr, "other types for int32x4.bool");
7036         return;
7037       }
7038       XMMRegister result_reg = ToInt32x4Register(instr->result());
7039       Register x_reg = ToRegister(instr->x());
7040       Register y_reg = ToRegister(instr->y());
7041       Register z_reg = ToRegister(instr->z());
7042       Register w_reg = ToRegister(instr->w());
7043       Label load_false_x, done_x, load_false_y, done_y,
7044             load_false_z, done_z, load_false_w, done_w;
7045       __ sub(esp, Immediate(kInt32x4Size));
7046
7047       __ CompareRoot(x_reg, Heap::kTrueValueRootIndex);
7048       __ j(not_equal, &load_false_x, Label::kNear);
7049       __ mov(Operand(esp, 0 * kInt32Size), Immediate(-1));
7050       __ jmp(&done_x, Label::kNear);
7051       __ bind(&load_false_x);
7052       __ mov(Operand(esp, 0 * kInt32Size), Immediate(0x0));
7053       __ bind(&done_x);
7054
7055       __ CompareRoot(y_reg, Heap::kTrueValueRootIndex);
7056       __ j(not_equal, &load_false_y, Label::kNear);
7057       __ mov(Operand(esp, 1 * kInt32Size), Immediate(-1));
7058       __ jmp(&done_y, Label::kNear);
7059       __ bind(&load_false_y);
7060       __ mov(Operand(esp, 1 * kInt32Size), Immediate(0x0));
7061       __ bind(&done_y);
7062
7063       __ CompareRoot(z_reg, Heap::kTrueValueRootIndex);
7064       __ j(not_equal, &load_false_z, Label::kNear);
7065       __ mov(Operand(esp, 2 * kInt32Size), Immediate(-1));
7066       __ jmp(&done_z, Label::kNear);
7067       __ bind(&load_false_z);
7068       __ mov(Operand(esp, 2 * kInt32Size), Immediate(0x0));
7069       __ bind(&done_z);
7070
7071       __ CompareRoot(w_reg, Heap::kTrueValueRootIndex);
7072       __ j(not_equal, &load_false_w, Label::kNear);
7073       __ mov(Operand(esp, 3 * kInt32Size), Immediate(-1));
7074       __ jmp(&done_w, Label::kNear);
7075       __ bind(&load_false_w);
7076       __ mov(Operand(esp, 3 * kInt32Size), Immediate(0x0));
7077       __ bind(&done_w);
7078
7079       __ movups(result_reg, Operand(esp, 0));
7080       __ add(esp, Immediate(kInt32x4Size));
7081       return;
7082     }
7083     default:
7084       UNREACHABLE();
7085       return;
7086   }
7087 }
7088
7089
7090 #undef __
7091
7092 } }  // namespace v8::internal
7093
7094 #endif  // V8_TARGET_ARCH_IA32