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