d20848918d30aad46f247217479f0e6b9e39544c
[platform/upstream/nodejs.git] / deps / v8 / src / compiler / ia32 / code-generator-ia32.cc
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/compiler/code-generator.h"
6
7 #include "src/compiler/code-generator-impl.h"
8 #include "src/compiler/gap-resolver.h"
9 #include "src/compiler/node-matchers.h"
10 #include "src/ia32/assembler-ia32.h"
11 #include "src/ia32/macro-assembler-ia32.h"
12 #include "src/scopes.h"
13
14 namespace v8 {
15 namespace internal {
16 namespace compiler {
17
18 #define __ masm()->
19
20
21 // Adds IA-32 specific methods for decoding operands.
22 class IA32OperandConverter : public InstructionOperandConverter {
23  public:
24   IA32OperandConverter(CodeGenerator* gen, Instruction* instr)
25       : InstructionOperandConverter(gen, instr) {}
26
27   Operand InputOperand(int index) { return ToOperand(instr_->InputAt(index)); }
28
29   Immediate InputImmediate(int index) {
30     return ToImmediate(instr_->InputAt(index));
31   }
32
33   Operand OutputOperand() { return ToOperand(instr_->Output()); }
34
35   Operand ToOperand(InstructionOperand* op, int extra = 0) {
36     if (op->IsRegister()) {
37       DCHECK(extra == 0);
38       return Operand(ToRegister(op));
39     } else if (op->IsDoubleRegister()) {
40       DCHECK(extra == 0);
41       return Operand(ToDoubleRegister(op));
42     }
43     DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
44     // The linkage computes where all spill slots are located.
45     FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), extra);
46     return Operand(offset.from_stack_pointer() ? esp : ebp, offset.offset());
47   }
48
49   Operand HighOperand(InstructionOperand* op) {
50     DCHECK(op->IsDoubleStackSlot());
51     return ToOperand(op, kPointerSize);
52   }
53
54   Immediate ToImmediate(InstructionOperand* operand) {
55     Constant constant = ToConstant(operand);
56     switch (constant.type()) {
57       case Constant::kInt32:
58         return Immediate(constant.ToInt32());
59       case Constant::kFloat32:
60         return Immediate(
61             isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED));
62       case Constant::kFloat64:
63         return Immediate(
64             isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED));
65       case Constant::kExternalReference:
66         return Immediate(constant.ToExternalReference());
67       case Constant::kHeapObject:
68         return Immediate(constant.ToHeapObject());
69       case Constant::kInt64:
70         break;
71       case Constant::kRpoNumber:
72         return Immediate::CodeRelativeOffset(ToLabel(operand));
73     }
74     UNREACHABLE();
75     return Immediate(-1);
76   }
77
78   static int NextOffset(int* offset) {
79     int i = *offset;
80     (*offset)++;
81     return i;
82   }
83
84   static ScaleFactor ScaleFor(AddressingMode one, AddressingMode mode) {
85     STATIC_ASSERT(0 == static_cast<int>(times_1));
86     STATIC_ASSERT(1 == static_cast<int>(times_2));
87     STATIC_ASSERT(2 == static_cast<int>(times_4));
88     STATIC_ASSERT(3 == static_cast<int>(times_8));
89     int scale = static_cast<int>(mode - one);
90     DCHECK(scale >= 0 && scale < 4);
91     return static_cast<ScaleFactor>(scale);
92   }
93
94   Operand MemoryOperand(int* offset) {
95     AddressingMode mode = AddressingModeField::decode(instr_->opcode());
96     switch (mode) {
97       case kMode_MR: {
98         Register base = InputRegister(NextOffset(offset));
99         int32_t disp = 0;
100         return Operand(base, disp);
101       }
102       case kMode_MRI: {
103         Register base = InputRegister(NextOffset(offset));
104         int32_t disp = InputInt32(NextOffset(offset));
105         return Operand(base, disp);
106       }
107       case kMode_MR1:
108       case kMode_MR2:
109       case kMode_MR4:
110       case kMode_MR8: {
111         Register base = InputRegister(NextOffset(offset));
112         Register index = InputRegister(NextOffset(offset));
113         ScaleFactor scale = ScaleFor(kMode_MR1, mode);
114         int32_t disp = 0;
115         return Operand(base, index, scale, disp);
116       }
117       case kMode_MR1I:
118       case kMode_MR2I:
119       case kMode_MR4I:
120       case kMode_MR8I: {
121         Register base = InputRegister(NextOffset(offset));
122         Register index = InputRegister(NextOffset(offset));
123         ScaleFactor scale = ScaleFor(kMode_MR1I, mode);
124         int32_t disp = InputInt32(NextOffset(offset));
125         return Operand(base, index, scale, disp);
126       }
127       case kMode_M1:
128       case kMode_M2:
129       case kMode_M4:
130       case kMode_M8: {
131         Register index = InputRegister(NextOffset(offset));
132         ScaleFactor scale = ScaleFor(kMode_M1, mode);
133         int32_t disp = 0;
134         return Operand(index, scale, disp);
135       }
136       case kMode_M1I:
137       case kMode_M2I:
138       case kMode_M4I:
139       case kMode_M8I: {
140         Register index = InputRegister(NextOffset(offset));
141         ScaleFactor scale = ScaleFor(kMode_M1I, mode);
142         int32_t disp = InputInt32(NextOffset(offset));
143         return Operand(index, scale, disp);
144       }
145       case kMode_MI: {
146         int32_t disp = InputInt32(NextOffset(offset));
147         return Operand(Immediate(disp));
148       }
149       case kMode_None:
150         UNREACHABLE();
151         return Operand(no_reg, 0);
152     }
153     UNREACHABLE();
154     return Operand(no_reg, 0);
155   }
156
157   Operand MemoryOperand(int first_input = 0) {
158     return MemoryOperand(&first_input);
159   }
160 };
161
162
163 namespace {
164
165 bool HasImmediateInput(Instruction* instr, int index) {
166   return instr->InputAt(index)->IsImmediate();
167 }
168
169
170 class OutOfLineLoadInteger FINAL : public OutOfLineCode {
171  public:
172   OutOfLineLoadInteger(CodeGenerator* gen, Register result)
173       : OutOfLineCode(gen), result_(result) {}
174
175   void Generate() FINAL { __ xor_(result_, result_); }
176
177  private:
178   Register const result_;
179 };
180
181
182 class OutOfLineLoadFloat FINAL : public OutOfLineCode {
183  public:
184   OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result)
185       : OutOfLineCode(gen), result_(result) {}
186
187   void Generate() FINAL { __ pcmpeqd(result_, result_); }
188
189  private:
190   XMMRegister const result_;
191 };
192
193
194 class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode {
195  public:
196   OutOfLineTruncateDoubleToI(CodeGenerator* gen, Register result,
197                              XMMRegister input)
198       : OutOfLineCode(gen), result_(result), input_(input) {}
199
200   void Generate() FINAL {
201     __ sub(esp, Immediate(kDoubleSize));
202     __ movsd(MemOperand(esp, 0), input_);
203     __ SlowTruncateToI(result_, esp, 0);
204     __ add(esp, Immediate(kDoubleSize));
205   }
206
207  private:
208   Register const result_;
209   XMMRegister const input_;
210 };
211
212 }  // namespace
213
214
215 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr)                          \
216   do {                                                                  \
217     auto result = i.OutputDoubleRegister();                             \
218     auto offset = i.InputRegister(0);                                   \
219     if (instr->InputAt(1)->IsRegister()) {                              \
220       __ cmp(offset, i.InputRegister(1));                               \
221     } else {                                                            \
222       __ cmp(offset, i.InputImmediate(1));                              \
223     }                                                                   \
224     OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \
225     __ j(above_equal, ool->entry());                                    \
226     __ asm_instr(result, i.MemoryOperand(2));                           \
227     __ bind(ool->exit());                                               \
228   } while (false)
229
230
231 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr)                          \
232   do {                                                                    \
233     auto result = i.OutputRegister();                                     \
234     auto offset = i.InputRegister(0);                                     \
235     if (instr->InputAt(1)->IsRegister()) {                                \
236       __ cmp(offset, i.InputRegister(1));                                 \
237     } else {                                                              \
238       __ cmp(offset, i.InputImmediate(1));                                \
239     }                                                                     \
240     OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \
241     __ j(above_equal, ool->entry());                                      \
242     __ asm_instr(result, i.MemoryOperand(2));                             \
243     __ bind(ool->exit());                                                 \
244   } while (false)
245
246
247 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr)                 \
248   do {                                                          \
249     auto offset = i.InputRegister(0);                           \
250     if (instr->InputAt(1)->IsRegister()) {                      \
251       __ cmp(offset, i.InputRegister(1));                       \
252     } else {                                                    \
253       __ cmp(offset, i.InputImmediate(1));                      \
254     }                                                           \
255     Label done;                                                 \
256     __ j(above_equal, &done, Label::kNear);                     \
257     __ asm_instr(i.MemoryOperand(3), i.InputDoubleRegister(2)); \
258     __ bind(&done);                                             \
259   } while (false)
260
261
262 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr)            \
263   do {                                                       \
264     auto offset = i.InputRegister(0);                        \
265     if (instr->InputAt(1)->IsRegister()) {                   \
266       __ cmp(offset, i.InputRegister(1));                    \
267     } else {                                                 \
268       __ cmp(offset, i.InputImmediate(1));                   \
269     }                                                        \
270     Label done;                                              \
271     __ j(above_equal, &done, Label::kNear);                  \
272     if (instr->InputAt(2)->IsRegister()) {                   \
273       __ asm_instr(i.MemoryOperand(3), i.InputRegister(2));  \
274     } else {                                                 \
275       __ asm_instr(i.MemoryOperand(3), i.InputImmediate(2)); \
276     }                                                        \
277     __ bind(&done);                                          \
278   } while (false)
279
280
281 // Assembles an instruction after register allocation, producing machine code.
282 void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
283   IA32OperandConverter i(this, instr);
284
285   switch (ArchOpcodeField::decode(instr->opcode())) {
286     case kArchCallCodeObject: {
287       EnsureSpaceForLazyDeopt();
288       if (HasImmediateInput(instr, 0)) {
289         Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
290         __ call(code, RelocInfo::CODE_TARGET);
291       } else {
292         Register reg = i.InputRegister(0);
293         __ call(Operand(reg, Code::kHeaderSize - kHeapObjectTag));
294       }
295       AddSafepointAndDeopt(instr);
296       break;
297     }
298     case kArchCallJSFunction: {
299       EnsureSpaceForLazyDeopt();
300       Register func = i.InputRegister(0);
301       if (FLAG_debug_code) {
302         // Check the function's context matches the context argument.
303         __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
304         __ Assert(equal, kWrongFunctionContext);
305       }
306       __ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
307       AddSafepointAndDeopt(instr);
308       break;
309     }
310     case kArchJmp:
311       AssembleArchJump(i.InputRpo(0));
312       break;
313     case kArchLookupSwitch:
314       AssembleArchLookupSwitch(instr);
315       break;
316     case kArchTableSwitch:
317       AssembleArchTableSwitch(instr);
318       break;
319     case kArchNop:
320       // don't emit code for nops.
321       break;
322     case kArchRet:
323       AssembleReturn();
324       break;
325     case kArchStackPointer:
326       __ mov(i.OutputRegister(), esp);
327       break;
328     case kArchTruncateDoubleToI: {
329       auto result = i.OutputRegister();
330       auto input = i.InputDoubleRegister(0);
331       auto ool = new (zone()) OutOfLineTruncateDoubleToI(this, result, input);
332       __ cvttsd2si(result, Operand(input));
333       __ cmp(result, 1);
334       __ j(overflow, ool->entry());
335       __ bind(ool->exit());
336       break;
337     }
338     case kIA32Add:
339       if (HasImmediateInput(instr, 1)) {
340         __ add(i.InputOperand(0), i.InputImmediate(1));
341       } else {
342         __ add(i.InputRegister(0), i.InputOperand(1));
343       }
344       break;
345     case kIA32And:
346       if (HasImmediateInput(instr, 1)) {
347         __ and_(i.InputOperand(0), i.InputImmediate(1));
348       } else {
349         __ and_(i.InputRegister(0), i.InputOperand(1));
350       }
351       break;
352     case kIA32Cmp:
353       if (HasImmediateInput(instr, 1)) {
354         __ cmp(i.InputOperand(0), i.InputImmediate(1));
355       } else {
356         __ cmp(i.InputRegister(0), i.InputOperand(1));
357       }
358       break;
359     case kIA32Test:
360       if (HasImmediateInput(instr, 1)) {
361         __ test(i.InputOperand(0), i.InputImmediate(1));
362       } else {
363         __ test(i.InputRegister(0), i.InputOperand(1));
364       }
365       break;
366     case kIA32Imul:
367       if (HasImmediateInput(instr, 1)) {
368         __ imul(i.OutputRegister(), i.InputOperand(0), i.InputInt32(1));
369       } else {
370         __ imul(i.OutputRegister(), i.InputOperand(1));
371       }
372       break;
373     case kIA32ImulHigh:
374       __ imul(i.InputRegister(1));
375       break;
376     case kIA32UmulHigh:
377       __ mul(i.InputRegister(1));
378       break;
379     case kIA32Idiv:
380       __ cdq();
381       __ idiv(i.InputOperand(1));
382       break;
383     case kIA32Udiv:
384       __ Move(edx, Immediate(0));
385       __ div(i.InputOperand(1));
386       break;
387     case kIA32Not:
388       __ not_(i.OutputOperand());
389       break;
390     case kIA32Neg:
391       __ neg(i.OutputOperand());
392       break;
393     case kIA32Or:
394       if (HasImmediateInput(instr, 1)) {
395         __ or_(i.InputOperand(0), i.InputImmediate(1));
396       } else {
397         __ or_(i.InputRegister(0), i.InputOperand(1));
398       }
399       break;
400     case kIA32Xor:
401       if (HasImmediateInput(instr, 1)) {
402         __ xor_(i.InputOperand(0), i.InputImmediate(1));
403       } else {
404         __ xor_(i.InputRegister(0), i.InputOperand(1));
405       }
406       break;
407     case kIA32Sub:
408       if (HasImmediateInput(instr, 1)) {
409         __ sub(i.InputOperand(0), i.InputImmediate(1));
410       } else {
411         __ sub(i.InputRegister(0), i.InputOperand(1));
412       }
413       break;
414     case kIA32Shl:
415       if (HasImmediateInput(instr, 1)) {
416         __ shl(i.OutputOperand(), i.InputInt5(1));
417       } else {
418         __ shl_cl(i.OutputOperand());
419       }
420       break;
421     case kIA32Shr:
422       if (HasImmediateInput(instr, 1)) {
423         __ shr(i.OutputOperand(), i.InputInt5(1));
424       } else {
425         __ shr_cl(i.OutputOperand());
426       }
427       break;
428     case kIA32Sar:
429       if (HasImmediateInput(instr, 1)) {
430         __ sar(i.OutputOperand(), i.InputInt5(1));
431       } else {
432         __ sar_cl(i.OutputOperand());
433       }
434       break;
435     case kIA32Ror:
436       if (HasImmediateInput(instr, 1)) {
437         __ ror(i.OutputOperand(), i.InputInt5(1));
438       } else {
439         __ ror_cl(i.OutputOperand());
440       }
441       break;
442     case kSSEFloat64Cmp:
443       __ ucomisd(i.InputDoubleRegister(0), i.InputOperand(1));
444       break;
445     case kSSEFloat64Add:
446       __ addsd(i.InputDoubleRegister(0), i.InputOperand(1));
447       break;
448     case kSSEFloat64Sub:
449       __ subsd(i.InputDoubleRegister(0), i.InputOperand(1));
450       break;
451     case kSSEFloat64Mul:
452       __ mulsd(i.InputDoubleRegister(0), i.InputOperand(1));
453       break;
454     case kSSEFloat64Div:
455       __ divsd(i.InputDoubleRegister(0), i.InputOperand(1));
456       break;
457     case kSSEFloat64Mod: {
458       // TODO(dcarney): alignment is wrong.
459       __ sub(esp, Immediate(kDoubleSize));
460       // Move values to st(0) and st(1).
461       __ movsd(Operand(esp, 0), i.InputDoubleRegister(1));
462       __ fld_d(Operand(esp, 0));
463       __ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
464       __ fld_d(Operand(esp, 0));
465       // Loop while fprem isn't done.
466       Label mod_loop;
467       __ bind(&mod_loop);
468       // This instructions traps on all kinds inputs, but we are assuming the
469       // floating point control word is set to ignore them all.
470       __ fprem();
471       // The following 2 instruction implicitly use eax.
472       __ fnstsw_ax();
473       __ sahf();
474       __ j(parity_even, &mod_loop);
475       // Move output to stack and clean up.
476       __ fstp(1);
477       __ fstp_d(Operand(esp, 0));
478       __ movsd(i.OutputDoubleRegister(), Operand(esp, 0));
479       __ add(esp, Immediate(kDoubleSize));
480       break;
481     }
482     case kSSEFloat64Sqrt:
483       __ sqrtsd(i.OutputDoubleRegister(), i.InputOperand(0));
484       break;
485     case kSSEFloat64Floor: {
486       CpuFeatureScope sse_scope(masm(), SSE4_1);
487       __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
488                  v8::internal::Assembler::kRoundDown);
489       break;
490     }
491     case kSSEFloat64Ceil: {
492       CpuFeatureScope sse_scope(masm(), SSE4_1);
493       __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
494                  v8::internal::Assembler::kRoundUp);
495       break;
496     }
497     case kSSEFloat64RoundTruncate: {
498       CpuFeatureScope sse_scope(masm(), SSE4_1);
499       __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
500                  v8::internal::Assembler::kRoundToZero);
501       break;
502     }
503     case kSSECvtss2sd:
504       __ cvtss2sd(i.OutputDoubleRegister(), i.InputOperand(0));
505       break;
506     case kSSECvtsd2ss:
507       __ cvtsd2ss(i.OutputDoubleRegister(), i.InputOperand(0));
508       break;
509     case kSSEFloat64ToInt32:
510       __ cvttsd2si(i.OutputRegister(), i.InputOperand(0));
511       break;
512     case kSSEFloat64ToUint32: {
513       XMMRegister scratch = xmm0;
514       __ Move(scratch, -2147483648.0);
515       __ addsd(scratch, i.InputOperand(0));
516       __ cvttsd2si(i.OutputRegister(), scratch);
517       __ add(i.OutputRegister(), Immediate(0x80000000));
518       break;
519     }
520     case kSSEInt32ToFloat64:
521       __ cvtsi2sd(i.OutputDoubleRegister(), i.InputOperand(0));
522       break;
523     case kSSEUint32ToFloat64:
524       __ LoadUint32(i.OutputDoubleRegister(), i.InputOperand(0));
525       break;
526     case kAVXFloat64Add: {
527       CpuFeatureScope avx_scope(masm(), AVX);
528       __ vaddsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
529                 i.InputOperand(1));
530       break;
531     }
532     case kAVXFloat64Sub: {
533       CpuFeatureScope avx_scope(masm(), AVX);
534       __ vsubsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
535                 i.InputOperand(1));
536       break;
537     }
538     case kAVXFloat64Mul: {
539       CpuFeatureScope avx_scope(masm(), AVX);
540       __ vmulsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
541                 i.InputOperand(1));
542       break;
543     }
544     case kAVXFloat64Div: {
545       CpuFeatureScope avx_scope(masm(), AVX);
546       __ vdivsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
547                 i.InputOperand(1));
548       break;
549     }
550     case kIA32Movsxbl:
551       __ movsx_b(i.OutputRegister(), i.MemoryOperand());
552       break;
553     case kIA32Movzxbl:
554       __ movzx_b(i.OutputRegister(), i.MemoryOperand());
555       break;
556     case kIA32Movb: {
557       int index = 0;
558       Operand operand = i.MemoryOperand(&index);
559       if (HasImmediateInput(instr, index)) {
560         __ mov_b(operand, i.InputInt8(index));
561       } else {
562         __ mov_b(operand, i.InputRegister(index));
563       }
564       break;
565     }
566     case kIA32Movsxwl:
567       __ movsx_w(i.OutputRegister(), i.MemoryOperand());
568       break;
569     case kIA32Movzxwl:
570       __ movzx_w(i.OutputRegister(), i.MemoryOperand());
571       break;
572     case kIA32Movw: {
573       int index = 0;
574       Operand operand = i.MemoryOperand(&index);
575       if (HasImmediateInput(instr, index)) {
576         __ mov_w(operand, i.InputInt16(index));
577       } else {
578         __ mov_w(operand, i.InputRegister(index));
579       }
580       break;
581     }
582     case kIA32Movl:
583       if (instr->HasOutput()) {
584         __ mov(i.OutputRegister(), i.MemoryOperand());
585       } else {
586         int index = 0;
587         Operand operand = i.MemoryOperand(&index);
588         if (HasImmediateInput(instr, index)) {
589           __ mov(operand, i.InputImmediate(index));
590         } else {
591           __ mov(operand, i.InputRegister(index));
592         }
593       }
594       break;
595     case kIA32Movsd:
596       if (instr->HasOutput()) {
597         __ movsd(i.OutputDoubleRegister(), i.MemoryOperand());
598       } else {
599         int index = 0;
600         Operand operand = i.MemoryOperand(&index);
601         __ movsd(operand, i.InputDoubleRegister(index));
602       }
603       break;
604     case kIA32Movss:
605       if (instr->HasOutput()) {
606         __ movss(i.OutputDoubleRegister(), i.MemoryOperand());
607       } else {
608         int index = 0;
609         Operand operand = i.MemoryOperand(&index);
610         __ movss(operand, i.InputDoubleRegister(index));
611       }
612       break;
613     case kIA32Lea: {
614       AddressingMode mode = AddressingModeField::decode(instr->opcode());
615       // Shorten "leal" to "addl", "subl" or "shll" if the register allocation
616       // and addressing mode just happens to work out. The "addl"/"subl" forms
617       // in these cases are faster based on measurements.
618       if (mode == kMode_MI) {
619         __ Move(i.OutputRegister(), Immediate(i.InputInt32(0)));
620       } else if (i.InputRegister(0).is(i.OutputRegister())) {
621         if (mode == kMode_MRI) {
622           int32_t constant_summand = i.InputInt32(1);
623           if (constant_summand > 0) {
624             __ add(i.OutputRegister(), Immediate(constant_summand));
625           } else if (constant_summand < 0) {
626             __ sub(i.OutputRegister(), Immediate(-constant_summand));
627           }
628         } else if (mode == kMode_MR1) {
629           if (i.InputRegister(1).is(i.OutputRegister())) {
630             __ shl(i.OutputRegister(), 1);
631           } else {
632             __ lea(i.OutputRegister(), i.MemoryOperand());
633           }
634         } else if (mode == kMode_M2) {
635           __ shl(i.OutputRegister(), 1);
636         } else if (mode == kMode_M4) {
637           __ shl(i.OutputRegister(), 2);
638         } else if (mode == kMode_M8) {
639           __ shl(i.OutputRegister(), 3);
640         } else {
641           __ lea(i.OutputRegister(), i.MemoryOperand());
642         }
643       } else {
644         __ lea(i.OutputRegister(), i.MemoryOperand());
645       }
646       break;
647     }
648     case kIA32Push:
649       if (HasImmediateInput(instr, 0)) {
650         __ push(i.InputImmediate(0));
651       } else {
652         __ push(i.InputOperand(0));
653       }
654       break;
655     case kIA32StoreWriteBarrier: {
656       Register object = i.InputRegister(0);
657       Register index = i.InputRegister(1);
658       Register value = i.InputRegister(2);
659       __ mov(Operand(object, index, times_1, 0), value);
660       __ lea(index, Operand(object, index, times_1, 0));
661       SaveFPRegsMode mode =
662           frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
663       __ RecordWrite(object, index, value, mode);
664       break;
665     }
666     case kCheckedLoadInt8:
667       ASSEMBLE_CHECKED_LOAD_INTEGER(movsx_b);
668       break;
669     case kCheckedLoadUint8:
670       ASSEMBLE_CHECKED_LOAD_INTEGER(movzx_b);
671       break;
672     case kCheckedLoadInt16:
673       ASSEMBLE_CHECKED_LOAD_INTEGER(movsx_w);
674       break;
675     case kCheckedLoadUint16:
676       ASSEMBLE_CHECKED_LOAD_INTEGER(movzx_w);
677       break;
678     case kCheckedLoadWord32:
679       ASSEMBLE_CHECKED_LOAD_INTEGER(mov);
680       break;
681     case kCheckedLoadFloat32:
682       ASSEMBLE_CHECKED_LOAD_FLOAT(movss);
683       break;
684     case kCheckedLoadFloat64:
685       ASSEMBLE_CHECKED_LOAD_FLOAT(movsd);
686       break;
687     case kCheckedStoreWord8:
688       ASSEMBLE_CHECKED_STORE_INTEGER(mov_b);
689       break;
690     case kCheckedStoreWord16:
691       ASSEMBLE_CHECKED_STORE_INTEGER(mov_w);
692       break;
693     case kCheckedStoreWord32:
694       ASSEMBLE_CHECKED_STORE_INTEGER(mov);
695       break;
696     case kCheckedStoreFloat32:
697       ASSEMBLE_CHECKED_STORE_FLOAT(movss);
698       break;
699     case kCheckedStoreFloat64:
700       ASSEMBLE_CHECKED_STORE_FLOAT(movsd);
701       break;
702   }
703 }
704
705
706 // Assembles a branch after an instruction.
707 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
708   IA32OperandConverter i(this, instr);
709   Label::Distance flabel_distance =
710       branch->fallthru ? Label::kNear : Label::kFar;
711   Label* tlabel = branch->true_label;
712   Label* flabel = branch->false_label;
713   switch (branch->condition) {
714     case kUnorderedEqual:
715       __ j(parity_even, flabel, flabel_distance);
716     // Fall through.
717     case kEqual:
718       __ j(equal, tlabel);
719       break;
720     case kUnorderedNotEqual:
721       __ j(parity_even, tlabel);
722     // Fall through.
723     case kNotEqual:
724       __ j(not_equal, tlabel);
725       break;
726     case kSignedLessThan:
727       __ j(less, tlabel);
728       break;
729     case kSignedGreaterThanOrEqual:
730       __ j(greater_equal, tlabel);
731       break;
732     case kSignedLessThanOrEqual:
733       __ j(less_equal, tlabel);
734       break;
735     case kSignedGreaterThan:
736       __ j(greater, tlabel);
737       break;
738     case kUnsignedLessThan:
739       __ j(below, tlabel);
740       break;
741     case kUnsignedGreaterThanOrEqual:
742       __ j(above_equal, tlabel);
743       break;
744     case kUnsignedLessThanOrEqual:
745       __ j(below_equal, tlabel);
746       break;
747     case kUnsignedGreaterThan:
748       __ j(above, tlabel);
749       break;
750     case kOverflow:
751       __ j(overflow, tlabel);
752       break;
753     case kNotOverflow:
754       __ j(no_overflow, tlabel);
755       break;
756   }
757   // Add a jump if not falling through to the next block.
758   if (!branch->fallthru) __ jmp(flabel);
759 }
760
761
762 void CodeGenerator::AssembleArchJump(BasicBlock::RpoNumber target) {
763   if (!IsNextInAssemblyOrder(target)) __ jmp(GetLabel(target));
764 }
765
766
767 // Assembles boolean materializations after an instruction.
768 void CodeGenerator::AssembleArchBoolean(Instruction* instr,
769                                         FlagsCondition condition) {
770   IA32OperandConverter i(this, instr);
771   Label done;
772
773   // Materialize a full 32-bit 1 or 0 value. The result register is always the
774   // last output of the instruction.
775   Label check;
776   DCHECK_NE(0u, instr->OutputCount());
777   Register reg = i.OutputRegister(instr->OutputCount() - 1);
778   Condition cc = no_condition;
779   switch (condition) {
780     case kUnorderedEqual:
781       __ j(parity_odd, &check, Label::kNear);
782       __ Move(reg, Immediate(0));
783       __ jmp(&done, Label::kNear);
784     // Fall through.
785     case kEqual:
786       cc = equal;
787       break;
788     case kUnorderedNotEqual:
789       __ j(parity_odd, &check, Label::kNear);
790       __ mov(reg, Immediate(1));
791       __ jmp(&done, Label::kNear);
792     // Fall through.
793     case kNotEqual:
794       cc = not_equal;
795       break;
796     case kSignedLessThan:
797       cc = less;
798       break;
799     case kSignedGreaterThanOrEqual:
800       cc = greater_equal;
801       break;
802     case kSignedLessThanOrEqual:
803       cc = less_equal;
804       break;
805     case kSignedGreaterThan:
806       cc = greater;
807       break;
808     case kUnsignedLessThan:
809       cc = below;
810       break;
811     case kUnsignedGreaterThanOrEqual:
812       cc = above_equal;
813       break;
814     case kUnsignedLessThanOrEqual:
815       cc = below_equal;
816       break;
817     case kUnsignedGreaterThan:
818       cc = above;
819       break;
820     case kOverflow:
821       cc = overflow;
822       break;
823     case kNotOverflow:
824       cc = no_overflow;
825       break;
826   }
827   __ bind(&check);
828   if (reg.is_byte_register()) {
829     // setcc for byte registers (al, bl, cl, dl).
830     __ setcc(cc, reg);
831     __ movzx_b(reg, reg);
832   } else {
833     // Emit a branch to set a register to either 1 or 0.
834     Label set;
835     __ j(cc, &set, Label::kNear);
836     __ Move(reg, Immediate(0));
837     __ jmp(&done, Label::kNear);
838     __ bind(&set);
839     __ mov(reg, Immediate(1));
840   }
841   __ bind(&done);
842 }
843
844
845 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) {
846   IA32OperandConverter i(this, instr);
847   Register input = i.InputRegister(0);
848   for (size_t index = 2; index < instr->InputCount(); index += 2) {
849     __ cmp(input, Immediate(i.InputInt32(index + 0)));
850     __ j(equal, GetLabel(i.InputRpo(index + 1)));
851   }
852   AssembleArchJump(i.InputRpo(1));
853 }
854
855
856 void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
857   IA32OperandConverter i(this, instr);
858   Register input = i.InputRegister(0);
859   size_t const case_count = instr->InputCount() - 2;
860   Label** cases = zone()->NewArray<Label*>(case_count);
861   for (size_t index = 0; index < case_count; ++index) {
862     cases[index] = GetLabel(i.InputRpo(index + 2));
863   }
864   Label* const table = AddJumpTable(cases, case_count);
865   __ cmp(input, Immediate(case_count));
866   __ j(above_equal, GetLabel(i.InputRpo(1)));
867   __ jmp(Operand::JumpTable(input, times_4, table));
868 }
869
870
871 void CodeGenerator::AssembleDeoptimizerCall(int deoptimization_id) {
872   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
873       isolate(), deoptimization_id, Deoptimizer::LAZY);
874   __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
875 }
876
877
878 // The calling convention for JSFunctions on IA32 passes arguments on the
879 // stack and the JSFunction and context in EDI and ESI, respectively, thus
880 // the steps of the call look as follows:
881
882 // --{ before the call instruction }--------------------------------------------
883 //                                                         |  caller frame |
884 //                                                         ^ esp           ^ ebp
885
886 // --{ push arguments and setup ESI, EDI }--------------------------------------
887 //                                       | args + receiver |  caller frame |
888 //                                       ^ esp                             ^ ebp
889 //                 [edi = JSFunction, esi = context]
890
891 // --{ call [edi + kCodeEntryOffset] }------------------------------------------
892 //                                 | RET | args + receiver |  caller frame |
893 //                                 ^ esp                                   ^ ebp
894
895 // =={ prologue of called function }============================================
896 // --{ push ebp }---------------------------------------------------------------
897 //                            | FP | RET | args + receiver |  caller frame |
898 //                            ^ esp                                        ^ ebp
899
900 // --{ mov ebp, esp }-----------------------------------------------------------
901 //                            | FP | RET | args + receiver |  caller frame |
902 //                            ^ ebp,esp
903
904 // --{ push esi }---------------------------------------------------------------
905 //                      | CTX | FP | RET | args + receiver |  caller frame |
906 //                      ^esp  ^ ebp
907
908 // --{ push edi }---------------------------------------------------------------
909 //                | FNC | CTX | FP | RET | args + receiver |  caller frame |
910 //                ^esp        ^ ebp
911
912 // --{ subi esp, #N }-----------------------------------------------------------
913 // | callee frame | FNC | CTX | FP | RET | args + receiver |  caller frame |
914 // ^esp                       ^ ebp
915
916 // =={ body of called function }================================================
917
918 // =={ epilogue of called function }============================================
919 // --{ mov esp, ebp }-----------------------------------------------------------
920 //                            | FP | RET | args + receiver |  caller frame |
921 //                            ^ esp,ebp
922
923 // --{ pop ebp }-----------------------------------------------------------
924 // |                               | RET | args + receiver |  caller frame |
925 //                                 ^ esp                                   ^ ebp
926
927 // --{ ret #A+1 }-----------------------------------------------------------
928 // |                                                       |  caller frame |
929 //                                                         ^ esp           ^ ebp
930
931
932 // Runtime function calls are accomplished by doing a stub call to the
933 // CEntryStub (a real code object). On IA32 passes arguments on the
934 // stack, the number of arguments in EAX, the address of the runtime function
935 // in EBX, and the context in ESI.
936
937 // --{ before the call instruction }--------------------------------------------
938 //                                                         |  caller frame |
939 //                                                         ^ esp           ^ ebp
940
941 // --{ push arguments and setup EAX, EBX, and ESI }-----------------------------
942 //                                       | args + receiver |  caller frame |
943 //                                       ^ esp                             ^ ebp
944 //              [eax = #args, ebx = runtime function, esi = context]
945
946 // --{ call #CEntryStub }-------------------------------------------------------
947 //                                 | RET | args + receiver |  caller frame |
948 //                                 ^ esp                                   ^ ebp
949
950 // =={ body of runtime function }===============================================
951
952 // --{ runtime returns }--------------------------------------------------------
953 //                                                         |  caller frame |
954 //                                                         ^ esp           ^ ebp
955
956 // Other custom linkages (e.g. for calling directly into and out of C++) may
957 // need to save callee-saved registers on the stack, which is done in the
958 // function prologue of generated code.
959
960 // --{ before the call instruction }--------------------------------------------
961 //                                                         |  caller frame |
962 //                                                         ^ esp           ^ ebp
963
964 // --{ set up arguments in registers on stack }---------------------------------
965 //                                                  | args |  caller frame |
966 //                                                  ^ esp                  ^ ebp
967 //                  [r0 = arg0, r1 = arg1, ...]
968
969 // --{ call code }--------------------------------------------------------------
970 //                                            | RET | args |  caller frame |
971 //                                            ^ esp                        ^ ebp
972
973 // =={ prologue of called function }============================================
974 // --{ push ebp }---------------------------------------------------------------
975 //                                       | FP | RET | args |  caller frame |
976 //                                       ^ esp                             ^ ebp
977
978 // --{ mov ebp, esp }-----------------------------------------------------------
979 //                                       | FP | RET | args |  caller frame |
980 //                                       ^ ebp,esp
981
982 // --{ save registers }---------------------------------------------------------
983 //                                | regs | FP | RET | args |  caller frame |
984 //                                ^ esp  ^ ebp
985
986 // --{ subi esp, #N }-----------------------------------------------------------
987 //                 | callee frame | regs | FP | RET | args |  caller frame |
988 //                 ^esp                  ^ ebp
989
990 // =={ body of called function }================================================
991
992 // =={ epilogue of called function }============================================
993 // --{ restore registers }------------------------------------------------------
994 //                                | regs | FP | RET | args |  caller frame |
995 //                                ^ esp  ^ ebp
996
997 // --{ mov esp, ebp }-----------------------------------------------------------
998 //                                       | FP | RET | args |  caller frame |
999 //                                       ^ esp,ebp
1000
1001 // --{ pop ebp }----------------------------------------------------------------
1002 //                                            | RET | args |  caller frame |
1003 //                                            ^ esp                        ^ ebp
1004
1005
1006 void CodeGenerator::AssemblePrologue() {
1007   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
1008   int stack_slots = frame()->GetSpillSlotCount();
1009   if (descriptor->kind() == CallDescriptor::kCallAddress) {
1010     // Assemble a prologue similar the to cdecl calling convention.
1011     __ push(ebp);
1012     __ mov(ebp, esp);
1013     const RegList saves = descriptor->CalleeSavedRegisters();
1014     if (saves != 0) {  // Save callee-saved registers.
1015       int register_save_area_size = 0;
1016       for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
1017         if (!((1 << i) & saves)) continue;
1018         __ push(Register::from_code(i));
1019         register_save_area_size += kPointerSize;
1020       }
1021       frame()->SetRegisterSaveAreaSize(register_save_area_size);
1022     }
1023   } else if (descriptor->IsJSFunctionCall()) {
1024     // TODO(turbofan): this prologue is redundant with OSR, but needed for
1025     // code aging.
1026     CompilationInfo* info = this->info();
1027     __ Prologue(info->IsCodePreAgingActive());
1028     frame()->SetRegisterSaveAreaSize(
1029         StandardFrameConstants::kFixedFrameSizeFromFp);
1030   } else if (stack_slots > 0) {
1031     __ StubPrologue();
1032     frame()->SetRegisterSaveAreaSize(
1033         StandardFrameConstants::kFixedFrameSizeFromFp);
1034   }
1035
1036   if (info()->is_osr()) {
1037     // TurboFan OSR-compiled functions cannot be entered directly.
1038     __ Abort(kShouldNotDirectlyEnterOsrFunction);
1039
1040     // Unoptimized code jumps directly to this entrypoint while the unoptimized
1041     // frame is still on the stack. Optimized code uses OSR values directly from
1042     // the unoptimized frame. Thus, all that needs to be done is to allocate the
1043     // remaining stack slots.
1044     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
1045     osr_pc_offset_ = __ pc_offset();
1046     DCHECK(stack_slots >= frame()->GetOsrStackSlotCount());
1047     stack_slots -= frame()->GetOsrStackSlotCount();
1048   }
1049
1050   if (stack_slots > 0) {
1051     // Allocate the stack slots used by this frame.
1052     __ sub(esp, Immediate(stack_slots * kPointerSize));
1053   }
1054 }
1055
1056
1057 void CodeGenerator::AssembleReturn() {
1058   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
1059   int stack_slots = frame()->GetSpillSlotCount();
1060   if (descriptor->kind() == CallDescriptor::kCallAddress) {
1061     const RegList saves = descriptor->CalleeSavedRegisters();
1062     if (frame()->GetRegisterSaveAreaSize() > 0) {
1063       // Remove this frame's spill slots first.
1064       if (stack_slots > 0) {
1065         __ add(esp, Immediate(stack_slots * kPointerSize));
1066       }
1067       // Restore registers.
1068       if (saves != 0) {
1069         for (int i = 0; i < Register::kNumRegisters; i++) {
1070           if (!((1 << i) & saves)) continue;
1071           __ pop(Register::from_code(i));
1072         }
1073       }
1074       __ pop(ebp);  // Pop caller's frame pointer.
1075       __ ret(0);
1076     } else {
1077       // No saved registers.
1078       __ mov(esp, ebp);  // Move stack pointer back to frame pointer.
1079       __ pop(ebp);       // Pop caller's frame pointer.
1080       __ ret(0);
1081     }
1082   } else if (descriptor->IsJSFunctionCall() || stack_slots > 0) {
1083     __ mov(esp, ebp);  // Move stack pointer back to frame pointer.
1084     __ pop(ebp);       // Pop caller's frame pointer.
1085     int pop_count = descriptor->IsJSFunctionCall()
1086                         ? static_cast<int>(descriptor->JSParameterCount())
1087                         : 0;
1088     __ ret(pop_count * kPointerSize);
1089   } else {
1090     __ ret(0);
1091   }
1092 }
1093
1094
1095 void CodeGenerator::AssembleMove(InstructionOperand* source,
1096                                  InstructionOperand* destination) {
1097   IA32OperandConverter g(this, NULL);
1098   // Dispatch on the source and destination operand kinds.  Not all
1099   // combinations are possible.
1100   if (source->IsRegister()) {
1101     DCHECK(destination->IsRegister() || destination->IsStackSlot());
1102     Register src = g.ToRegister(source);
1103     Operand dst = g.ToOperand(destination);
1104     __ mov(dst, src);
1105   } else if (source->IsStackSlot()) {
1106     DCHECK(destination->IsRegister() || destination->IsStackSlot());
1107     Operand src = g.ToOperand(source);
1108     if (destination->IsRegister()) {
1109       Register dst = g.ToRegister(destination);
1110       __ mov(dst, src);
1111     } else {
1112       Operand dst = g.ToOperand(destination);
1113       __ push(src);
1114       __ pop(dst);
1115     }
1116   } else if (source->IsConstant()) {
1117     Constant src_constant = g.ToConstant(source);
1118     if (src_constant.type() == Constant::kHeapObject) {
1119       Handle<HeapObject> src = src_constant.ToHeapObject();
1120       if (destination->IsRegister()) {
1121         Register dst = g.ToRegister(destination);
1122         __ LoadHeapObject(dst, src);
1123       } else {
1124         DCHECK(destination->IsStackSlot());
1125         Operand dst = g.ToOperand(destination);
1126         AllowDeferredHandleDereference embedding_raw_address;
1127         if (isolate()->heap()->InNewSpace(*src)) {
1128           __ PushHeapObject(src);
1129           __ pop(dst);
1130         } else {
1131           __ mov(dst, src);
1132         }
1133       }
1134     } else if (destination->IsRegister()) {
1135       Register dst = g.ToRegister(destination);
1136       __ Move(dst, g.ToImmediate(source));
1137     } else if (destination->IsStackSlot()) {
1138       Operand dst = g.ToOperand(destination);
1139       __ Move(dst, g.ToImmediate(source));
1140     } else if (src_constant.type() == Constant::kFloat32) {
1141       // TODO(turbofan): Can we do better here?
1142       uint32_t src = bit_cast<uint32_t>(src_constant.ToFloat32());
1143       if (destination->IsDoubleRegister()) {
1144         XMMRegister dst = g.ToDoubleRegister(destination);
1145         __ Move(dst, src);
1146       } else {
1147         DCHECK(destination->IsDoubleStackSlot());
1148         Operand dst = g.ToOperand(destination);
1149         __ Move(dst, Immediate(src));
1150       }
1151     } else {
1152       DCHECK_EQ(Constant::kFloat64, src_constant.type());
1153       uint64_t src = bit_cast<uint64_t>(src_constant.ToFloat64());
1154       uint32_t lower = static_cast<uint32_t>(src);
1155       uint32_t upper = static_cast<uint32_t>(src >> 32);
1156       if (destination->IsDoubleRegister()) {
1157         XMMRegister dst = g.ToDoubleRegister(destination);
1158         __ Move(dst, src);
1159       } else {
1160         DCHECK(destination->IsDoubleStackSlot());
1161         Operand dst0 = g.ToOperand(destination);
1162         Operand dst1 = g.HighOperand(destination);
1163         __ Move(dst0, Immediate(lower));
1164         __ Move(dst1, Immediate(upper));
1165       }
1166     }
1167   } else if (source->IsDoubleRegister()) {
1168     XMMRegister src = g.ToDoubleRegister(source);
1169     if (destination->IsDoubleRegister()) {
1170       XMMRegister dst = g.ToDoubleRegister(destination);
1171       __ movaps(dst, src);
1172     } else {
1173       DCHECK(destination->IsDoubleStackSlot());
1174       Operand dst = g.ToOperand(destination);
1175       __ movsd(dst, src);
1176     }
1177   } else if (source->IsDoubleStackSlot()) {
1178     DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
1179     Operand src = g.ToOperand(source);
1180     if (destination->IsDoubleRegister()) {
1181       XMMRegister dst = g.ToDoubleRegister(destination);
1182       __ movsd(dst, src);
1183     } else {
1184       // We rely on having xmm0 available as a fixed scratch register.
1185       Operand dst = g.ToOperand(destination);
1186       __ movsd(xmm0, src);
1187       __ movsd(dst, xmm0);
1188     }
1189   } else {
1190     UNREACHABLE();
1191   }
1192 }
1193
1194
1195 void CodeGenerator::AssembleSwap(InstructionOperand* source,
1196                                  InstructionOperand* destination) {
1197   IA32OperandConverter g(this, NULL);
1198   // Dispatch on the source and destination operand kinds.  Not all
1199   // combinations are possible.
1200   if (source->IsRegister() && destination->IsRegister()) {
1201     // Register-register.
1202     Register src = g.ToRegister(source);
1203     Register dst = g.ToRegister(destination);
1204     __ xchg(dst, src);
1205   } else if (source->IsRegister() && destination->IsStackSlot()) {
1206     // Register-memory.
1207     __ xchg(g.ToRegister(source), g.ToOperand(destination));
1208   } else if (source->IsStackSlot() && destination->IsStackSlot()) {
1209     // Memory-memory.
1210     Operand src = g.ToOperand(source);
1211     Operand dst = g.ToOperand(destination);
1212     __ push(dst);
1213     __ push(src);
1214     __ pop(dst);
1215     __ pop(src);
1216   } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
1217     // XMM register-register swap. We rely on having xmm0
1218     // available as a fixed scratch register.
1219     XMMRegister src = g.ToDoubleRegister(source);
1220     XMMRegister dst = g.ToDoubleRegister(destination);
1221     __ movaps(xmm0, src);
1222     __ movaps(src, dst);
1223     __ movaps(dst, xmm0);
1224   } else if (source->IsDoubleRegister() && destination->IsDoubleStackSlot()) {
1225     // XMM register-memory swap.  We rely on having xmm0
1226     // available as a fixed scratch register.
1227     XMMRegister reg = g.ToDoubleRegister(source);
1228     Operand other = g.ToOperand(destination);
1229     __ movsd(xmm0, other);
1230     __ movsd(other, reg);
1231     __ movaps(reg, xmm0);
1232   } else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) {
1233     // Double-width memory-to-memory.
1234     Operand src0 = g.ToOperand(source);
1235     Operand src1 = g.HighOperand(source);
1236     Operand dst0 = g.ToOperand(destination);
1237     Operand dst1 = g.HighOperand(destination);
1238     __ movsd(xmm0, dst0);  // Save destination in xmm0.
1239     __ push(src0);         // Then use stack to copy source to destination.
1240     __ pop(dst0);
1241     __ push(src1);
1242     __ pop(dst1);
1243     __ movsd(src0, xmm0);
1244   } else {
1245     // No other combinations are possible.
1246     UNREACHABLE();
1247   }
1248 }
1249
1250
1251 void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) {
1252   for (size_t index = 0; index < target_count; ++index) {
1253     __ dd(targets[index]);
1254   }
1255 }
1256
1257
1258 void CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); }
1259
1260
1261 void CodeGenerator::EnsureSpaceForLazyDeopt() {
1262   int space_needed = Deoptimizer::patch_size();
1263   if (!info()->IsStub()) {
1264     // Ensure that we have enough space after the previous lazy-bailout
1265     // instruction for patching the code here.
1266     int current_pc = masm()->pc_offset();
1267     if (current_pc < last_lazy_deopt_pc_ + space_needed) {
1268       int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
1269       __ Nop(padding_size);
1270     }
1271   }
1272   MarkLazyDeoptSite();
1273 }
1274
1275 #undef __
1276
1277 }  // namespace compiler
1278 }  // namespace internal
1279 }  // namespace v8