• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/ast/scopes.h"
8 #include "src/compiler/code-generator-impl.h"
9 #include "src/compiler/gap-resolver.h"
10 #include "src/compiler/node-matchers.h"
11 #include "src/compiler/osr.h"
12 #include "src/ia32/assembler-ia32.h"
13 #include "src/ia32/frames-ia32.h"
14 #include "src/ia32/macro-assembler-ia32.h"
15 
16 namespace v8 {
17 namespace internal {
18 namespace compiler {
19 
20 #define __ masm()->
21 
22 
23 #define kScratchDoubleReg xmm0
24 
25 
26 // Adds IA-32 specific methods for decoding operands.
27 class IA32OperandConverter : public InstructionOperandConverter {
28  public:
IA32OperandConverter(CodeGenerator * gen,Instruction * instr)29   IA32OperandConverter(CodeGenerator* gen, Instruction* instr)
30       : InstructionOperandConverter(gen, instr) {}
31 
InputOperand(size_t index,int extra=0)32   Operand InputOperand(size_t index, int extra = 0) {
33     return ToOperand(instr_->InputAt(index), extra);
34   }
35 
InputImmediate(size_t index)36   Immediate InputImmediate(size_t index) {
37     return ToImmediate(instr_->InputAt(index));
38   }
39 
OutputOperand()40   Operand OutputOperand() { return ToOperand(instr_->Output()); }
41 
ToOperand(InstructionOperand * op,int extra=0)42   Operand ToOperand(InstructionOperand* op, int extra = 0) {
43     if (op->IsRegister()) {
44       DCHECK(extra == 0);
45       return Operand(ToRegister(op));
46     } else if (op->IsDoubleRegister()) {
47       DCHECK(extra == 0);
48       return Operand(ToDoubleRegister(op));
49     }
50     DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
51     FrameOffset offset = frame_access_state()->GetFrameOffset(
52         AllocatedOperand::cast(op)->index());
53     return Operand(offset.from_stack_pointer() ? esp : ebp,
54                    offset.offset() + extra);
55   }
56 
ToMaterializableOperand(int materializable_offset)57   Operand ToMaterializableOperand(int materializable_offset) {
58     FrameOffset offset = frame_access_state()->GetFrameOffset(
59         Frame::FPOffsetToSlot(materializable_offset));
60     return Operand(offset.from_stack_pointer() ? esp : ebp, offset.offset());
61   }
62 
HighOperand(InstructionOperand * op)63   Operand HighOperand(InstructionOperand* op) {
64     DCHECK(op->IsDoubleStackSlot());
65     return ToOperand(op, kPointerSize);
66   }
67 
ToImmediate(InstructionOperand * operand)68   Immediate ToImmediate(InstructionOperand* operand) {
69     Constant constant = ToConstant(operand);
70     switch (constant.type()) {
71       case Constant::kInt32:
72         return Immediate(constant.ToInt32());
73       case Constant::kFloat32:
74         return Immediate(
75             isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED));
76       case Constant::kFloat64:
77         return Immediate(
78             isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED));
79       case Constant::kExternalReference:
80         return Immediate(constant.ToExternalReference());
81       case Constant::kHeapObject:
82         return Immediate(constant.ToHeapObject());
83       case Constant::kInt64:
84         break;
85       case Constant::kRpoNumber:
86         return Immediate::CodeRelativeOffset(ToLabel(operand));
87     }
88     UNREACHABLE();
89     return Immediate(-1);
90   }
91 
NextOffset(size_t * offset)92   static size_t NextOffset(size_t* offset) {
93     size_t i = *offset;
94     (*offset)++;
95     return i;
96   }
97 
ScaleFor(AddressingMode one,AddressingMode mode)98   static ScaleFactor ScaleFor(AddressingMode one, AddressingMode mode) {
99     STATIC_ASSERT(0 == static_cast<int>(times_1));
100     STATIC_ASSERT(1 == static_cast<int>(times_2));
101     STATIC_ASSERT(2 == static_cast<int>(times_4));
102     STATIC_ASSERT(3 == static_cast<int>(times_8));
103     int scale = static_cast<int>(mode - one);
104     DCHECK(scale >= 0 && scale < 4);
105     return static_cast<ScaleFactor>(scale);
106   }
107 
MemoryOperand(size_t * offset)108   Operand MemoryOperand(size_t* offset) {
109     AddressingMode mode = AddressingModeField::decode(instr_->opcode());
110     switch (mode) {
111       case kMode_MR: {
112         Register base = InputRegister(NextOffset(offset));
113         int32_t disp = 0;
114         return Operand(base, disp);
115       }
116       case kMode_MRI: {
117         Register base = InputRegister(NextOffset(offset));
118         int32_t disp = InputInt32(NextOffset(offset));
119         return Operand(base, disp);
120       }
121       case kMode_MR1:
122       case kMode_MR2:
123       case kMode_MR4:
124       case kMode_MR8: {
125         Register base = InputRegister(NextOffset(offset));
126         Register index = InputRegister(NextOffset(offset));
127         ScaleFactor scale = ScaleFor(kMode_MR1, mode);
128         int32_t disp = 0;
129         return Operand(base, index, scale, disp);
130       }
131       case kMode_MR1I:
132       case kMode_MR2I:
133       case kMode_MR4I:
134       case kMode_MR8I: {
135         Register base = InputRegister(NextOffset(offset));
136         Register index = InputRegister(NextOffset(offset));
137         ScaleFactor scale = ScaleFor(kMode_MR1I, mode);
138         int32_t disp = InputInt32(NextOffset(offset));
139         return Operand(base, index, scale, disp);
140       }
141       case kMode_M1:
142       case kMode_M2:
143       case kMode_M4:
144       case kMode_M8: {
145         Register index = InputRegister(NextOffset(offset));
146         ScaleFactor scale = ScaleFor(kMode_M1, mode);
147         int32_t disp = 0;
148         return Operand(index, scale, disp);
149       }
150       case kMode_M1I:
151       case kMode_M2I:
152       case kMode_M4I:
153       case kMode_M8I: {
154         Register index = InputRegister(NextOffset(offset));
155         ScaleFactor scale = ScaleFor(kMode_M1I, mode);
156         int32_t disp = InputInt32(NextOffset(offset));
157         return Operand(index, scale, disp);
158       }
159       case kMode_MI: {
160         int32_t disp = InputInt32(NextOffset(offset));
161         return Operand(Immediate(disp));
162       }
163       case kMode_None:
164         UNREACHABLE();
165         return Operand(no_reg, 0);
166     }
167     UNREACHABLE();
168     return Operand(no_reg, 0);
169   }
170 
MemoryOperand(size_t first_input=0)171   Operand MemoryOperand(size_t first_input = 0) {
172     return MemoryOperand(&first_input);
173   }
174 };
175 
176 
177 namespace {
178 
HasImmediateInput(Instruction * instr,size_t index)179 bool HasImmediateInput(Instruction* instr, size_t index) {
180   return instr->InputAt(index)->IsImmediate();
181 }
182 
183 
184 class OutOfLineLoadInteger final : public OutOfLineCode {
185  public:
OutOfLineLoadInteger(CodeGenerator * gen,Register result)186   OutOfLineLoadInteger(CodeGenerator* gen, Register result)
187       : OutOfLineCode(gen), result_(result) {}
188 
Generate()189   void Generate() final { __ xor_(result_, result_); }
190 
191  private:
192   Register const result_;
193 };
194 
195 
196 class OutOfLineLoadFloat final : public OutOfLineCode {
197  public:
OutOfLineLoadFloat(CodeGenerator * gen,XMMRegister result)198   OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result)
199       : OutOfLineCode(gen), result_(result) {}
200 
Generate()201   void Generate() final { __ pcmpeqd(result_, result_); }
202 
203  private:
204   XMMRegister const result_;
205 };
206 
207 
208 class OutOfLineTruncateDoubleToI final : public OutOfLineCode {
209  public:
OutOfLineTruncateDoubleToI(CodeGenerator * gen,Register result,XMMRegister input)210   OutOfLineTruncateDoubleToI(CodeGenerator* gen, Register result,
211                              XMMRegister input)
212       : OutOfLineCode(gen), result_(result), input_(input) {}
213 
Generate()214   void Generate() final {
215     __ sub(esp, Immediate(kDoubleSize));
216     __ movsd(MemOperand(esp, 0), input_);
217     __ SlowTruncateToI(result_, esp, 0);
218     __ add(esp, Immediate(kDoubleSize));
219   }
220 
221  private:
222   Register const result_;
223   XMMRegister const input_;
224 };
225 
226 
227 class OutOfLineRecordWrite final : public OutOfLineCode {
228  public:
OutOfLineRecordWrite(CodeGenerator * gen,Register object,Operand operand,Register value,Register scratch0,Register scratch1,RecordWriteMode mode)229   OutOfLineRecordWrite(CodeGenerator* gen, Register object, Operand operand,
230                        Register value, Register scratch0, Register scratch1,
231                        RecordWriteMode mode)
232       : OutOfLineCode(gen),
233         object_(object),
234         operand_(operand),
235         value_(value),
236         scratch0_(scratch0),
237         scratch1_(scratch1),
238         mode_(mode) {}
239 
Generate()240   void Generate() final {
241     if (mode_ > RecordWriteMode::kValueIsPointer) {
242       __ JumpIfSmi(value_, exit());
243     }
244     if (mode_ > RecordWriteMode::kValueIsMap) {
245       __ CheckPageFlag(value_, scratch0_,
246                        MemoryChunk::kPointersToHereAreInterestingMask, zero,
247                        exit());
248     }
249     SaveFPRegsMode const save_fp_mode =
250         frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
251     RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_,
252                          EMIT_REMEMBERED_SET, save_fp_mode);
253     __ lea(scratch1_, operand_);
254     __ CallStub(&stub);
255   }
256 
257  private:
258   Register const object_;
259   Operand const operand_;
260   Register const value_;
261   Register const scratch0_;
262   Register const scratch1_;
263   RecordWriteMode const mode_;
264 };
265 
266 }  // namespace
267 
268 
269 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr)                          \
270   do {                                                                  \
271     auto result = i.OutputDoubleRegister();                             \
272     auto offset = i.InputRegister(0);                                   \
273     if (instr->InputAt(1)->IsRegister()) {                              \
274       __ cmp(offset, i.InputRegister(1));                               \
275     } else {                                                            \
276       __ cmp(offset, i.InputImmediate(1));                              \
277     }                                                                   \
278     OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \
279     __ j(above_equal, ool->entry());                                    \
280     __ asm_instr(result, i.MemoryOperand(2));                           \
281     __ bind(ool->exit());                                               \
282   } while (false)
283 
284 
285 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr)                          \
286   do {                                                                    \
287     auto result = i.OutputRegister();                                     \
288     auto offset = i.InputRegister(0);                                     \
289     if (instr->InputAt(1)->IsRegister()) {                                \
290       __ cmp(offset, i.InputRegister(1));                                 \
291     } else {                                                              \
292       __ cmp(offset, i.InputImmediate(1));                                \
293     }                                                                     \
294     OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \
295     __ j(above_equal, ool->entry());                                      \
296     __ asm_instr(result, i.MemoryOperand(2));                             \
297     __ bind(ool->exit());                                                 \
298   } while (false)
299 
300 
301 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr)                 \
302   do {                                                          \
303     auto offset = i.InputRegister(0);                           \
304     if (instr->InputAt(1)->IsRegister()) {                      \
305       __ cmp(offset, i.InputRegister(1));                       \
306     } else {                                                    \
307       __ cmp(offset, i.InputImmediate(1));                      \
308     }                                                           \
309     Label done;                                                 \
310     __ j(above_equal, &done, Label::kNear);                     \
311     __ asm_instr(i.MemoryOperand(3), i.InputDoubleRegister(2)); \
312     __ bind(&done);                                             \
313   } while (false)
314 
315 
316 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr)            \
317   do {                                                       \
318     auto offset = i.InputRegister(0);                        \
319     if (instr->InputAt(1)->IsRegister()) {                   \
320       __ cmp(offset, i.InputRegister(1));                    \
321     } else {                                                 \
322       __ cmp(offset, i.InputImmediate(1));                   \
323     }                                                        \
324     Label done;                                              \
325     __ j(above_equal, &done, Label::kNear);                  \
326     if (instr->InputAt(2)->IsRegister()) {                   \
327       __ asm_instr(i.MemoryOperand(3), i.InputRegister(2));  \
328     } else {                                                 \
329       __ asm_instr(i.MemoryOperand(3), i.InputImmediate(2)); \
330     }                                                        \
331     __ bind(&done);                                          \
332   } while (false)
333 
334 
AssembleDeconstructActivationRecord(int stack_param_delta)335 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
336   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
337   if (sp_slot_delta > 0) {
338     __ add(esp, Immediate(sp_slot_delta * kPointerSize));
339   }
340   frame_access_state()->SetFrameAccessToDefault();
341 }
342 
343 
AssemblePrepareTailCall(int stack_param_delta)344 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
345   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
346   if (sp_slot_delta < 0) {
347     __ sub(esp, Immediate(-sp_slot_delta * kPointerSize));
348     frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
349   }
350   if (frame()->needs_frame()) {
351     __ mov(ebp, MemOperand(ebp, 0));
352   }
353   frame_access_state()->SetFrameAccessToSP();
354 }
355 
356 
357 // Assembles an instruction after register allocation, producing machine code.
AssembleArchInstruction(Instruction * instr)358 void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
359   IA32OperandConverter i(this, instr);
360 
361   switch (ArchOpcodeField::decode(instr->opcode())) {
362     case kArchCallCodeObject: {
363       EnsureSpaceForLazyDeopt();
364       if (HasImmediateInput(instr, 0)) {
365         Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
366         __ call(code, RelocInfo::CODE_TARGET);
367       } else {
368         Register reg = i.InputRegister(0);
369         __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
370         __ call(reg);
371       }
372       RecordCallPosition(instr);
373       frame_access_state()->ClearSPDelta();
374       break;
375     }
376     case kArchTailCallCodeObject: {
377       int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
378       AssembleDeconstructActivationRecord(stack_param_delta);
379       if (HasImmediateInput(instr, 0)) {
380         Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
381         __ jmp(code, RelocInfo::CODE_TARGET);
382       } else {
383         Register reg = i.InputRegister(0);
384         __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
385         __ jmp(reg);
386       }
387       frame_access_state()->ClearSPDelta();
388       break;
389     }
390     case kArchCallJSFunction: {
391       EnsureSpaceForLazyDeopt();
392       Register func = i.InputRegister(0);
393       if (FLAG_debug_code) {
394         // Check the function's context matches the context argument.
395         __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
396         __ Assert(equal, kWrongFunctionContext);
397       }
398       __ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
399       RecordCallPosition(instr);
400       frame_access_state()->ClearSPDelta();
401       break;
402     }
403     case kArchTailCallJSFunction: {
404       Register func = i.InputRegister(0);
405       if (FLAG_debug_code) {
406         // Check the function's context matches the context argument.
407         __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
408         __ Assert(equal, kWrongFunctionContext);
409       }
410       int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
411       AssembleDeconstructActivationRecord(stack_param_delta);
412       __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset));
413       frame_access_state()->ClearSPDelta();
414       break;
415     }
416     case kArchLazyBailout: {
417       EnsureSpaceForLazyDeopt();
418       RecordCallPosition(instr);
419       break;
420     }
421     case kArchPrepareCallCFunction: {
422       // Frame alignment requires using FP-relative frame addressing.
423       frame_access_state()->SetFrameAccessToFP();
424       int const num_parameters = MiscField::decode(instr->opcode());
425       __ PrepareCallCFunction(num_parameters, i.TempRegister(0));
426       break;
427     }
428     case kArchPrepareTailCall:
429       AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1));
430       break;
431     case kArchCallCFunction: {
432       int const num_parameters = MiscField::decode(instr->opcode());
433       if (HasImmediateInput(instr, 0)) {
434         ExternalReference ref = i.InputExternalReference(0);
435         __ CallCFunction(ref, num_parameters);
436       } else {
437         Register func = i.InputRegister(0);
438         __ CallCFunction(func, num_parameters);
439       }
440       frame_access_state()->SetFrameAccessToDefault();
441       frame_access_state()->ClearSPDelta();
442       break;
443     }
444     case kArchJmp:
445       AssembleArchJump(i.InputRpo(0));
446       break;
447     case kArchLookupSwitch:
448       AssembleArchLookupSwitch(instr);
449       break;
450     case kArchTableSwitch:
451       AssembleArchTableSwitch(instr);
452       break;
453     case kArchNop:
454     case kArchThrowTerminator:
455       // don't emit code for nops.
456       break;
457     case kArchDeoptimize: {
458       int deopt_state_id =
459           BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
460       Deoptimizer::BailoutType bailout_type =
461           Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
462       AssembleDeoptimizerCall(deopt_state_id, bailout_type);
463       break;
464     }
465     case kArchRet:
466       AssembleReturn();
467       break;
468     case kArchStackPointer:
469       __ mov(i.OutputRegister(), esp);
470       break;
471     case kArchFramePointer:
472       __ mov(i.OutputRegister(), ebp);
473       break;
474     case kArchTruncateDoubleToI: {
475       auto result = i.OutputRegister();
476       auto input = i.InputDoubleRegister(0);
477       auto ool = new (zone()) OutOfLineTruncateDoubleToI(this, result, input);
478       __ cvttsd2si(result, Operand(input));
479       __ cmp(result, 1);
480       __ j(overflow, ool->entry());
481       __ bind(ool->exit());
482       break;
483     }
484     case kArchStoreWithWriteBarrier: {
485       RecordWriteMode mode =
486           static_cast<RecordWriteMode>(MiscField::decode(instr->opcode()));
487       Register object = i.InputRegister(0);
488       size_t index = 0;
489       Operand operand = i.MemoryOperand(&index);
490       Register value = i.InputRegister(index);
491       Register scratch0 = i.TempRegister(0);
492       Register scratch1 = i.TempRegister(1);
493       auto ool = new (zone()) OutOfLineRecordWrite(this, object, operand, value,
494                                                    scratch0, scratch1, mode);
495       __ mov(operand, value);
496       __ CheckPageFlag(object, scratch0,
497                        MemoryChunk::kPointersFromHereAreInterestingMask,
498                        not_zero, ool->entry());
499       __ bind(ool->exit());
500       break;
501     }
502     case kIA32Add:
503       if (HasImmediateInput(instr, 1)) {
504         __ add(i.InputOperand(0), i.InputImmediate(1));
505       } else {
506         __ add(i.InputRegister(0), i.InputOperand(1));
507       }
508       break;
509     case kIA32And:
510       if (HasImmediateInput(instr, 1)) {
511         __ and_(i.InputOperand(0), i.InputImmediate(1));
512       } else {
513         __ and_(i.InputRegister(0), i.InputOperand(1));
514       }
515       break;
516     case kIA32Cmp:
517       if (HasImmediateInput(instr, 1)) {
518         __ cmp(i.InputOperand(0), i.InputImmediate(1));
519       } else {
520         __ cmp(i.InputRegister(0), i.InputOperand(1));
521       }
522       break;
523     case kIA32Test:
524       if (HasImmediateInput(instr, 1)) {
525         __ test(i.InputOperand(0), i.InputImmediate(1));
526       } else {
527         __ test(i.InputRegister(0), i.InputOperand(1));
528       }
529       break;
530     case kIA32Imul:
531       if (HasImmediateInput(instr, 1)) {
532         __ imul(i.OutputRegister(), i.InputOperand(0), i.InputInt32(1));
533       } else {
534         __ imul(i.OutputRegister(), i.InputOperand(1));
535       }
536       break;
537     case kIA32ImulHigh:
538       __ imul(i.InputRegister(1));
539       break;
540     case kIA32UmulHigh:
541       __ mul(i.InputRegister(1));
542       break;
543     case kIA32Idiv:
544       __ cdq();
545       __ idiv(i.InputOperand(1));
546       break;
547     case kIA32Udiv:
548       __ Move(edx, Immediate(0));
549       __ div(i.InputOperand(1));
550       break;
551     case kIA32Not:
552       __ not_(i.OutputOperand());
553       break;
554     case kIA32Neg:
555       __ neg(i.OutputOperand());
556       break;
557     case kIA32Or:
558       if (HasImmediateInput(instr, 1)) {
559         __ or_(i.InputOperand(0), i.InputImmediate(1));
560       } else {
561         __ or_(i.InputRegister(0), i.InputOperand(1));
562       }
563       break;
564     case kIA32Xor:
565       if (HasImmediateInput(instr, 1)) {
566         __ xor_(i.InputOperand(0), i.InputImmediate(1));
567       } else {
568         __ xor_(i.InputRegister(0), i.InputOperand(1));
569       }
570       break;
571     case kIA32Sub:
572       if (HasImmediateInput(instr, 1)) {
573         __ sub(i.InputOperand(0), i.InputImmediate(1));
574       } else {
575         __ sub(i.InputRegister(0), i.InputOperand(1));
576       }
577       break;
578     case kIA32Shl:
579       if (HasImmediateInput(instr, 1)) {
580         __ shl(i.OutputOperand(), i.InputInt5(1));
581       } else {
582         __ shl_cl(i.OutputOperand());
583       }
584       break;
585     case kIA32Shr:
586       if (HasImmediateInput(instr, 1)) {
587         __ shr(i.OutputOperand(), i.InputInt5(1));
588       } else {
589         __ shr_cl(i.OutputOperand());
590       }
591       break;
592     case kIA32Sar:
593       if (HasImmediateInput(instr, 1)) {
594         __ sar(i.OutputOperand(), i.InputInt5(1));
595       } else {
596         __ sar_cl(i.OutputOperand());
597       }
598       break;
599     case kIA32Ror:
600       if (HasImmediateInput(instr, 1)) {
601         __ ror(i.OutputOperand(), i.InputInt5(1));
602       } else {
603         __ ror_cl(i.OutputOperand());
604       }
605       break;
606     case kIA32Lzcnt:
607       __ Lzcnt(i.OutputRegister(), i.InputOperand(0));
608       break;
609     case kIA32Tzcnt:
610       __ Tzcnt(i.OutputRegister(), i.InputOperand(0));
611       break;
612     case kIA32Popcnt:
613       __ Popcnt(i.OutputRegister(), i.InputOperand(0));
614       break;
615     case kSSEFloat32Cmp:
616       __ ucomiss(i.InputDoubleRegister(0), i.InputOperand(1));
617       break;
618     case kSSEFloat32Add:
619       __ addss(i.InputDoubleRegister(0), i.InputOperand(1));
620       break;
621     case kSSEFloat32Sub:
622       __ subss(i.InputDoubleRegister(0), i.InputOperand(1));
623       break;
624     case kSSEFloat32Mul:
625       __ mulss(i.InputDoubleRegister(0), i.InputOperand(1));
626       break;
627     case kSSEFloat32Div:
628       __ divss(i.InputDoubleRegister(0), i.InputOperand(1));
629       // Don't delete this mov. It may improve performance on some CPUs,
630       // when there is a (v)mulss depending on the result.
631       __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister());
632       break;
633     case kSSEFloat32Max:
634       __ maxss(i.InputDoubleRegister(0), i.InputOperand(1));
635       break;
636     case kSSEFloat32Min:
637       __ minss(i.InputDoubleRegister(0), i.InputOperand(1));
638       break;
639     case kSSEFloat32Sqrt:
640       __ sqrtss(i.OutputDoubleRegister(), i.InputOperand(0));
641       break;
642     case kSSEFloat32Abs: {
643       // TODO(bmeurer): Use 128-bit constants.
644       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
645       __ psrlq(kScratchDoubleReg, 33);
646       __ andps(i.OutputDoubleRegister(), kScratchDoubleReg);
647       break;
648     }
649     case kSSEFloat32Neg: {
650       // TODO(bmeurer): Use 128-bit constants.
651       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
652       __ psllq(kScratchDoubleReg, 31);
653       __ xorps(i.OutputDoubleRegister(), kScratchDoubleReg);
654       break;
655     }
656     case kSSEFloat32Round: {
657       CpuFeatureScope sse_scope(masm(), SSE4_1);
658       RoundingMode const mode =
659           static_cast<RoundingMode>(MiscField::decode(instr->opcode()));
660       __ roundss(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode);
661       break;
662     }
663     case kSSEFloat64Cmp:
664       __ ucomisd(i.InputDoubleRegister(0), i.InputOperand(1));
665       break;
666     case kSSEFloat64Add:
667       __ addsd(i.InputDoubleRegister(0), i.InputOperand(1));
668       break;
669     case kSSEFloat64Sub:
670       __ subsd(i.InputDoubleRegister(0), i.InputOperand(1));
671       break;
672     case kSSEFloat64Mul:
673       __ mulsd(i.InputDoubleRegister(0), i.InputOperand(1));
674       break;
675     case kSSEFloat64Div:
676       __ divsd(i.InputDoubleRegister(0), i.InputOperand(1));
677       // Don't delete this mov. It may improve performance on some CPUs,
678       // when there is a (v)mulsd depending on the result.
679       __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister());
680       break;
681     case kSSEFloat64Max:
682       __ maxsd(i.InputDoubleRegister(0), i.InputOperand(1));
683       break;
684     case kSSEFloat64Min:
685       __ minsd(i.InputDoubleRegister(0), i.InputOperand(1));
686       break;
687     case kSSEFloat64Mod: {
688       // TODO(dcarney): alignment is wrong.
689       __ sub(esp, Immediate(kDoubleSize));
690       // Move values to st(0) and st(1).
691       __ movsd(Operand(esp, 0), i.InputDoubleRegister(1));
692       __ fld_d(Operand(esp, 0));
693       __ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
694       __ fld_d(Operand(esp, 0));
695       // Loop while fprem isn't done.
696       Label mod_loop;
697       __ bind(&mod_loop);
698       // This instructions traps on all kinds inputs, but we are assuming the
699       // floating point control word is set to ignore them all.
700       __ fprem();
701       // The following 2 instruction implicitly use eax.
702       __ fnstsw_ax();
703       __ sahf();
704       __ j(parity_even, &mod_loop);
705       // Move output to stack and clean up.
706       __ fstp(1);
707       __ fstp_d(Operand(esp, 0));
708       __ movsd(i.OutputDoubleRegister(), Operand(esp, 0));
709       __ add(esp, Immediate(kDoubleSize));
710       break;
711     }
712     case kSSEFloat64Abs: {
713       // TODO(bmeurer): Use 128-bit constants.
714       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
715       __ psrlq(kScratchDoubleReg, 1);
716       __ andpd(i.OutputDoubleRegister(), kScratchDoubleReg);
717       break;
718     }
719     case kSSEFloat64Neg: {
720       // TODO(bmeurer): Use 128-bit constants.
721       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
722       __ psllq(kScratchDoubleReg, 63);
723       __ xorpd(i.OutputDoubleRegister(), kScratchDoubleReg);
724       break;
725     }
726     case kSSEFloat64Sqrt:
727       __ sqrtsd(i.OutputDoubleRegister(), i.InputOperand(0));
728       break;
729     case kSSEFloat64Round: {
730       CpuFeatureScope sse_scope(masm(), SSE4_1);
731       RoundingMode const mode =
732           static_cast<RoundingMode>(MiscField::decode(instr->opcode()));
733       __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode);
734       break;
735     }
736     case kSSEFloat32ToFloat64:
737       __ cvtss2sd(i.OutputDoubleRegister(), i.InputOperand(0));
738       break;
739     case kSSEFloat64ToFloat32:
740       __ cvtsd2ss(i.OutputDoubleRegister(), i.InputOperand(0));
741       break;
742     case kSSEFloat64ToInt32:
743       __ cvttsd2si(i.OutputRegister(), i.InputOperand(0));
744       break;
745     case kSSEFloat64ToUint32: {
746       __ Move(kScratchDoubleReg, -2147483648.0);
747       __ addsd(kScratchDoubleReg, i.InputOperand(0));
748       __ cvttsd2si(i.OutputRegister(), kScratchDoubleReg);
749       __ add(i.OutputRegister(), Immediate(0x80000000));
750       break;
751     }
752     case kSSEInt32ToFloat64:
753       __ cvtsi2sd(i.OutputDoubleRegister(), i.InputOperand(0));
754       break;
755     case kSSEUint32ToFloat64:
756       __ LoadUint32(i.OutputDoubleRegister(), i.InputOperand(0));
757       break;
758     case kSSEFloat64ExtractLowWord32:
759       if (instr->InputAt(0)->IsDoubleStackSlot()) {
760         __ mov(i.OutputRegister(), i.InputOperand(0));
761       } else {
762         __ movd(i.OutputRegister(), i.InputDoubleRegister(0));
763       }
764       break;
765     case kSSEFloat64ExtractHighWord32:
766       if (instr->InputAt(0)->IsDoubleStackSlot()) {
767         __ mov(i.OutputRegister(), i.InputOperand(0, kDoubleSize / 2));
768       } else {
769         __ Pextrd(i.OutputRegister(), i.InputDoubleRegister(0), 1);
770       }
771       break;
772     case kSSEFloat64InsertLowWord32:
773       __ Pinsrd(i.OutputDoubleRegister(), i.InputOperand(1), 0);
774       break;
775     case kSSEFloat64InsertHighWord32:
776       __ Pinsrd(i.OutputDoubleRegister(), i.InputOperand(1), 1);
777       break;
778     case kSSEFloat64LoadLowWord32:
779       __ movd(i.OutputDoubleRegister(), i.InputOperand(0));
780       break;
781     case kAVXFloat32Add: {
782       CpuFeatureScope avx_scope(masm(), AVX);
783       __ vaddss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
784                 i.InputOperand(1));
785       break;
786     }
787     case kAVXFloat32Sub: {
788       CpuFeatureScope avx_scope(masm(), AVX);
789       __ vsubss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
790                 i.InputOperand(1));
791       break;
792     }
793     case kAVXFloat32Mul: {
794       CpuFeatureScope avx_scope(masm(), AVX);
795       __ vmulss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
796                 i.InputOperand(1));
797       break;
798     }
799     case kAVXFloat32Div: {
800       CpuFeatureScope avx_scope(masm(), AVX);
801       __ vdivss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
802                 i.InputOperand(1));
803       // Don't delete this mov. It may improve performance on some CPUs,
804       // when there is a (v)mulss depending on the result.
805       __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister());
806       break;
807     }
808     case kAVXFloat32Max: {
809       CpuFeatureScope avx_scope(masm(), AVX);
810       __ vmaxss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
811                 i.InputOperand(1));
812       break;
813     }
814     case kAVXFloat32Min: {
815       CpuFeatureScope avx_scope(masm(), AVX);
816       __ vminss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
817                 i.InputOperand(1));
818       break;
819     }
820     case kAVXFloat64Add: {
821       CpuFeatureScope avx_scope(masm(), AVX);
822       __ vaddsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
823                 i.InputOperand(1));
824       break;
825     }
826     case kAVXFloat64Sub: {
827       CpuFeatureScope avx_scope(masm(), AVX);
828       __ vsubsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
829                 i.InputOperand(1));
830       break;
831     }
832     case kAVXFloat64Mul: {
833       CpuFeatureScope avx_scope(masm(), AVX);
834       __ vmulsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
835                 i.InputOperand(1));
836       break;
837     }
838     case kAVXFloat64Div: {
839       CpuFeatureScope avx_scope(masm(), AVX);
840       __ vdivsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
841                 i.InputOperand(1));
842       // Don't delete this mov. It may improve performance on some CPUs,
843       // when there is a (v)mulsd depending on the result.
844       __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister());
845       break;
846     }
847     case kAVXFloat64Max: {
848       CpuFeatureScope avx_scope(masm(), AVX);
849       __ vmaxsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
850                 i.InputOperand(1));
851       break;
852     }
853     case kAVXFloat64Min: {
854       CpuFeatureScope avx_scope(masm(), AVX);
855       __ vminsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
856                 i.InputOperand(1));
857       break;
858     }
859     case kAVXFloat32Abs: {
860       // TODO(bmeurer): Use RIP relative 128-bit constants.
861       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
862       __ psrlq(kScratchDoubleReg, 33);
863       CpuFeatureScope avx_scope(masm(), AVX);
864       __ vandps(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0));
865       break;
866     }
867     case kAVXFloat32Neg: {
868       // TODO(bmeurer): Use RIP relative 128-bit constants.
869       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
870       __ psllq(kScratchDoubleReg, 31);
871       CpuFeatureScope avx_scope(masm(), AVX);
872       __ vxorps(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0));
873       break;
874     }
875     case kAVXFloat64Abs: {
876       // TODO(bmeurer): Use RIP relative 128-bit constants.
877       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
878       __ psrlq(kScratchDoubleReg, 1);
879       CpuFeatureScope avx_scope(masm(), AVX);
880       __ vandpd(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0));
881       break;
882     }
883     case kAVXFloat64Neg: {
884       // TODO(bmeurer): Use RIP relative 128-bit constants.
885       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
886       __ psllq(kScratchDoubleReg, 63);
887       CpuFeatureScope avx_scope(masm(), AVX);
888       __ vxorpd(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0));
889       break;
890     }
891     case kIA32Movsxbl:
892       __ movsx_b(i.OutputRegister(), i.MemoryOperand());
893       break;
894     case kIA32Movzxbl:
895       __ movzx_b(i.OutputRegister(), i.MemoryOperand());
896       break;
897     case kIA32Movb: {
898       size_t index = 0;
899       Operand operand = i.MemoryOperand(&index);
900       if (HasImmediateInput(instr, index)) {
901         __ mov_b(operand, i.InputInt8(index));
902       } else {
903         __ mov_b(operand, i.InputRegister(index));
904       }
905       break;
906     }
907     case kIA32Movsxwl:
908       __ movsx_w(i.OutputRegister(), i.MemoryOperand());
909       break;
910     case kIA32Movzxwl:
911       __ movzx_w(i.OutputRegister(), i.MemoryOperand());
912       break;
913     case kIA32Movw: {
914       size_t index = 0;
915       Operand operand = i.MemoryOperand(&index);
916       if (HasImmediateInput(instr, index)) {
917         __ mov_w(operand, i.InputInt16(index));
918       } else {
919         __ mov_w(operand, i.InputRegister(index));
920       }
921       break;
922     }
923     case kIA32Movl:
924       if (instr->HasOutput()) {
925         __ mov(i.OutputRegister(), i.MemoryOperand());
926       } else {
927         size_t index = 0;
928         Operand operand = i.MemoryOperand(&index);
929         if (HasImmediateInput(instr, index)) {
930           __ mov(operand, i.InputImmediate(index));
931         } else {
932           __ mov(operand, i.InputRegister(index));
933         }
934       }
935       break;
936     case kIA32Movsd:
937       if (instr->HasOutput()) {
938         __ movsd(i.OutputDoubleRegister(), i.MemoryOperand());
939       } else {
940         size_t index = 0;
941         Operand operand = i.MemoryOperand(&index);
942         __ movsd(operand, i.InputDoubleRegister(index));
943       }
944       break;
945     case kIA32Movss:
946       if (instr->HasOutput()) {
947         __ movss(i.OutputDoubleRegister(), i.MemoryOperand());
948       } else {
949         size_t index = 0;
950         Operand operand = i.MemoryOperand(&index);
951         __ movss(operand, i.InputDoubleRegister(index));
952       }
953       break;
954     case kIA32BitcastFI:
955       if (instr->InputAt(0)->IsDoubleStackSlot()) {
956         __ mov(i.OutputRegister(), i.InputOperand(0));
957       } else {
958         __ movd(i.OutputRegister(), i.InputDoubleRegister(0));
959       }
960       break;
961     case kIA32BitcastIF:
962       if (instr->InputAt(0)->IsRegister()) {
963         __ movd(i.OutputDoubleRegister(), i.InputRegister(0));
964       } else {
965         __ movss(i.OutputDoubleRegister(), i.InputOperand(0));
966       }
967       break;
968     case kIA32Lea: {
969       AddressingMode mode = AddressingModeField::decode(instr->opcode());
970       // Shorten "leal" to "addl", "subl" or "shll" if the register allocation
971       // and addressing mode just happens to work out. The "addl"/"subl" forms
972       // in these cases are faster based on measurements.
973       if (mode == kMode_MI) {
974         __ Move(i.OutputRegister(), Immediate(i.InputInt32(0)));
975       } else if (i.InputRegister(0).is(i.OutputRegister())) {
976         if (mode == kMode_MRI) {
977           int32_t constant_summand = i.InputInt32(1);
978           if (constant_summand > 0) {
979             __ add(i.OutputRegister(), Immediate(constant_summand));
980           } else if (constant_summand < 0) {
981             __ sub(i.OutputRegister(), Immediate(-constant_summand));
982           }
983         } else if (mode == kMode_MR1) {
984           if (i.InputRegister(1).is(i.OutputRegister())) {
985             __ shl(i.OutputRegister(), 1);
986           } else {
987             __ lea(i.OutputRegister(), i.MemoryOperand());
988           }
989         } else if (mode == kMode_M2) {
990           __ shl(i.OutputRegister(), 1);
991         } else if (mode == kMode_M4) {
992           __ shl(i.OutputRegister(), 2);
993         } else if (mode == kMode_M8) {
994           __ shl(i.OutputRegister(), 3);
995         } else {
996           __ lea(i.OutputRegister(), i.MemoryOperand());
997         }
998       } else {
999         __ lea(i.OutputRegister(), i.MemoryOperand());
1000       }
1001       break;
1002     }
1003     case kIA32PushFloat32:
1004       if (instr->InputAt(0)->IsDoubleRegister()) {
1005         __ sub(esp, Immediate(kDoubleSize));
1006         __ movss(Operand(esp, 0), i.InputDoubleRegister(0));
1007         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
1008       } else if (HasImmediateInput(instr, 0)) {
1009         __ Move(kScratchDoubleReg, i.InputDouble(0));
1010         __ sub(esp, Immediate(kDoubleSize));
1011         __ movss(Operand(esp, 0), kScratchDoubleReg);
1012         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
1013       } else {
1014         __ movsd(kScratchDoubleReg, i.InputOperand(0));
1015         __ sub(esp, Immediate(kDoubleSize));
1016         __ movss(Operand(esp, 0), kScratchDoubleReg);
1017         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
1018       }
1019       break;
1020     case kIA32PushFloat64:
1021       if (instr->InputAt(0)->IsDoubleRegister()) {
1022         __ sub(esp, Immediate(kDoubleSize));
1023         __ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
1024         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
1025       } else if (HasImmediateInput(instr, 0)) {
1026         __ Move(kScratchDoubleReg, i.InputDouble(0));
1027         __ sub(esp, Immediate(kDoubleSize));
1028         __ movsd(Operand(esp, 0), kScratchDoubleReg);
1029         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
1030       } else {
1031         __ movsd(kScratchDoubleReg, i.InputOperand(0));
1032         __ sub(esp, Immediate(kDoubleSize));
1033         __ movsd(Operand(esp, 0), kScratchDoubleReg);
1034         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
1035       }
1036       break;
1037     case kIA32Push:
1038       if (instr->InputAt(0)->IsDoubleRegister()) {
1039         __ sub(esp, Immediate(kDoubleSize));
1040         __ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
1041         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
1042       } else if (HasImmediateInput(instr, 0)) {
1043         __ push(i.InputImmediate(0));
1044         frame_access_state()->IncreaseSPDelta(1);
1045       } else {
1046         __ push(i.InputOperand(0));
1047         frame_access_state()->IncreaseSPDelta(1);
1048       }
1049       break;
1050     case kIA32Poke: {
1051       int const slot = MiscField::decode(instr->opcode());
1052       if (HasImmediateInput(instr, 0)) {
1053         __ mov(Operand(esp, slot * kPointerSize), i.InputImmediate(0));
1054       } else {
1055         __ mov(Operand(esp, slot * kPointerSize), i.InputRegister(0));
1056       }
1057       break;
1058     }
1059     case kCheckedLoadInt8:
1060       ASSEMBLE_CHECKED_LOAD_INTEGER(movsx_b);
1061       break;
1062     case kCheckedLoadUint8:
1063       ASSEMBLE_CHECKED_LOAD_INTEGER(movzx_b);
1064       break;
1065     case kCheckedLoadInt16:
1066       ASSEMBLE_CHECKED_LOAD_INTEGER(movsx_w);
1067       break;
1068     case kCheckedLoadUint16:
1069       ASSEMBLE_CHECKED_LOAD_INTEGER(movzx_w);
1070       break;
1071     case kCheckedLoadWord32:
1072       ASSEMBLE_CHECKED_LOAD_INTEGER(mov);
1073       break;
1074     case kCheckedLoadFloat32:
1075       ASSEMBLE_CHECKED_LOAD_FLOAT(movss);
1076       break;
1077     case kCheckedLoadFloat64:
1078       ASSEMBLE_CHECKED_LOAD_FLOAT(movsd);
1079       break;
1080     case kCheckedStoreWord8:
1081       ASSEMBLE_CHECKED_STORE_INTEGER(mov_b);
1082       break;
1083     case kCheckedStoreWord16:
1084       ASSEMBLE_CHECKED_STORE_INTEGER(mov_w);
1085       break;
1086     case kCheckedStoreWord32:
1087       ASSEMBLE_CHECKED_STORE_INTEGER(mov);
1088       break;
1089     case kCheckedStoreFloat32:
1090       ASSEMBLE_CHECKED_STORE_FLOAT(movss);
1091       break;
1092     case kCheckedStoreFloat64:
1093       ASSEMBLE_CHECKED_STORE_FLOAT(movsd);
1094       break;
1095     case kIA32StackCheck: {
1096       ExternalReference const stack_limit =
1097           ExternalReference::address_of_stack_limit(isolate());
1098       __ cmp(esp, Operand::StaticVariable(stack_limit));
1099       break;
1100     }
1101     case kCheckedLoadWord64:
1102     case kCheckedStoreWord64:
1103       UNREACHABLE();  // currently unsupported checked int64 load/store.
1104       break;
1105   }
1106 }  // NOLINT(readability/fn_size)
1107 
1108 
1109 // Assembles a branch after an instruction.
AssembleArchBranch(Instruction * instr,BranchInfo * branch)1110 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
1111   IA32OperandConverter i(this, instr);
1112   Label::Distance flabel_distance =
1113       branch->fallthru ? Label::kNear : Label::kFar;
1114   Label* tlabel = branch->true_label;
1115   Label* flabel = branch->false_label;
1116   switch (branch->condition) {
1117     case kUnorderedEqual:
1118       __ j(parity_even, flabel, flabel_distance);
1119     // Fall through.
1120     case kEqual:
1121       __ j(equal, tlabel);
1122       break;
1123     case kUnorderedNotEqual:
1124       __ j(parity_even, tlabel);
1125     // Fall through.
1126     case kNotEqual:
1127       __ j(not_equal, tlabel);
1128       break;
1129     case kSignedLessThan:
1130       __ j(less, tlabel);
1131       break;
1132     case kSignedGreaterThanOrEqual:
1133       __ j(greater_equal, tlabel);
1134       break;
1135     case kSignedLessThanOrEqual:
1136       __ j(less_equal, tlabel);
1137       break;
1138     case kSignedGreaterThan:
1139       __ j(greater, tlabel);
1140       break;
1141     case kUnsignedLessThan:
1142       __ j(below, tlabel);
1143       break;
1144     case kUnsignedGreaterThanOrEqual:
1145       __ j(above_equal, tlabel);
1146       break;
1147     case kUnsignedLessThanOrEqual:
1148       __ j(below_equal, tlabel);
1149       break;
1150     case kUnsignedGreaterThan:
1151       __ j(above, tlabel);
1152       break;
1153     case kOverflow:
1154       __ j(overflow, tlabel);
1155       break;
1156     case kNotOverflow:
1157       __ j(no_overflow, tlabel);
1158       break;
1159     default:
1160       UNREACHABLE();
1161       break;
1162   }
1163   // Add a jump if not falling through to the next block.
1164   if (!branch->fallthru) __ jmp(flabel);
1165 }
1166 
1167 
AssembleArchJump(RpoNumber target)1168 void CodeGenerator::AssembleArchJump(RpoNumber target) {
1169   if (!IsNextInAssemblyOrder(target)) __ jmp(GetLabel(target));
1170 }
1171 
1172 
1173 // Assembles boolean materializations after an instruction.
AssembleArchBoolean(Instruction * instr,FlagsCondition condition)1174 void CodeGenerator::AssembleArchBoolean(Instruction* instr,
1175                                         FlagsCondition condition) {
1176   IA32OperandConverter i(this, instr);
1177   Label done;
1178 
1179   // Materialize a full 32-bit 1 or 0 value. The result register is always the
1180   // last output of the instruction.
1181   Label check;
1182   DCHECK_NE(0u, instr->OutputCount());
1183   Register reg = i.OutputRegister(instr->OutputCount() - 1);
1184   Condition cc = no_condition;
1185   switch (condition) {
1186     case kUnorderedEqual:
1187       __ j(parity_odd, &check, Label::kNear);
1188       __ Move(reg, Immediate(0));
1189       __ jmp(&done, Label::kNear);
1190     // Fall through.
1191     case kEqual:
1192       cc = equal;
1193       break;
1194     case kUnorderedNotEqual:
1195       __ j(parity_odd, &check, Label::kNear);
1196       __ mov(reg, Immediate(1));
1197       __ jmp(&done, Label::kNear);
1198     // Fall through.
1199     case kNotEqual:
1200       cc = not_equal;
1201       break;
1202     case kSignedLessThan:
1203       cc = less;
1204       break;
1205     case kSignedGreaterThanOrEqual:
1206       cc = greater_equal;
1207       break;
1208     case kSignedLessThanOrEqual:
1209       cc = less_equal;
1210       break;
1211     case kSignedGreaterThan:
1212       cc = greater;
1213       break;
1214     case kUnsignedLessThan:
1215       cc = below;
1216       break;
1217     case kUnsignedGreaterThanOrEqual:
1218       cc = above_equal;
1219       break;
1220     case kUnsignedLessThanOrEqual:
1221       cc = below_equal;
1222       break;
1223     case kUnsignedGreaterThan:
1224       cc = above;
1225       break;
1226     case kOverflow:
1227       cc = overflow;
1228       break;
1229     case kNotOverflow:
1230       cc = no_overflow;
1231       break;
1232     default:
1233       UNREACHABLE();
1234       break;
1235   }
1236   __ bind(&check);
1237   if (reg.is_byte_register()) {
1238     // setcc for byte registers (al, bl, cl, dl).
1239     __ setcc(cc, reg);
1240     __ movzx_b(reg, reg);
1241   } else {
1242     // Emit a branch to set a register to either 1 or 0.
1243     Label set;
1244     __ j(cc, &set, Label::kNear);
1245     __ Move(reg, Immediate(0));
1246     __ jmp(&done, Label::kNear);
1247     __ bind(&set);
1248     __ mov(reg, Immediate(1));
1249   }
1250   __ bind(&done);
1251 }
1252 
1253 
AssembleArchLookupSwitch(Instruction * instr)1254 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) {
1255   IA32OperandConverter i(this, instr);
1256   Register input = i.InputRegister(0);
1257   for (size_t index = 2; index < instr->InputCount(); index += 2) {
1258     __ cmp(input, Immediate(i.InputInt32(index + 0)));
1259     __ j(equal, GetLabel(i.InputRpo(index + 1)));
1260   }
1261   AssembleArchJump(i.InputRpo(1));
1262 }
1263 
1264 
AssembleArchTableSwitch(Instruction * instr)1265 void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
1266   IA32OperandConverter i(this, instr);
1267   Register input = i.InputRegister(0);
1268   size_t const case_count = instr->InputCount() - 2;
1269   Label** cases = zone()->NewArray<Label*>(case_count);
1270   for (size_t index = 0; index < case_count; ++index) {
1271     cases[index] = GetLabel(i.InputRpo(index + 2));
1272   }
1273   Label* const table = AddJumpTable(cases, case_count);
1274   __ cmp(input, Immediate(case_count));
1275   __ j(above_equal, GetLabel(i.InputRpo(1)));
1276   __ jmp(Operand::JumpTable(input, times_4, table));
1277 }
1278 
1279 
AssembleDeoptimizerCall(int deoptimization_id,Deoptimizer::BailoutType bailout_type)1280 void CodeGenerator::AssembleDeoptimizerCall(
1281     int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
1282   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
1283       isolate(), deoptimization_id, bailout_type);
1284   __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
1285 }
1286 
1287 
1288 // The calling convention for JSFunctions on IA32 passes arguments on the
1289 // stack and the JSFunction and context in EDI and ESI, respectively, thus
1290 // the steps of the call look as follows:
1291 
1292 // --{ before the call instruction }--------------------------------------------
1293 //                                                         |  caller frame |
1294 //                                                         ^ esp           ^ ebp
1295 
1296 // --{ push arguments and setup ESI, EDI }--------------------------------------
1297 //                                       | args + receiver |  caller frame |
1298 //                                       ^ esp                             ^ ebp
1299 //                 [edi = JSFunction, esi = context]
1300 
1301 // --{ call [edi + kCodeEntryOffset] }------------------------------------------
1302 //                                 | RET | args + receiver |  caller frame |
1303 //                                 ^ esp                                   ^ ebp
1304 
1305 // =={ prologue of called function }============================================
1306 // --{ push ebp }---------------------------------------------------------------
1307 //                            | FP | RET | args + receiver |  caller frame |
1308 //                            ^ esp                                        ^ ebp
1309 
1310 // --{ mov ebp, esp }-----------------------------------------------------------
1311 //                            | FP | RET | args + receiver |  caller frame |
1312 //                            ^ ebp,esp
1313 
1314 // --{ push esi }---------------------------------------------------------------
1315 //                      | CTX | FP | RET | args + receiver |  caller frame |
1316 //                      ^esp  ^ ebp
1317 
1318 // --{ push edi }---------------------------------------------------------------
1319 //                | FNC | CTX | FP | RET | args + receiver |  caller frame |
1320 //                ^esp        ^ ebp
1321 
1322 // --{ subi esp, #N }-----------------------------------------------------------
1323 // | callee frame | FNC | CTX | FP | RET | args + receiver |  caller frame |
1324 // ^esp                       ^ ebp
1325 
1326 // =={ body of called function }================================================
1327 
1328 // =={ epilogue of called function }============================================
1329 // --{ mov esp, ebp }-----------------------------------------------------------
1330 //                            | FP | RET | args + receiver |  caller frame |
1331 //                            ^ esp,ebp
1332 
1333 // --{ pop ebp }-----------------------------------------------------------
1334 // |                               | RET | args + receiver |  caller frame |
1335 //                                 ^ esp                                   ^ ebp
1336 
1337 // --{ ret #A+1 }-----------------------------------------------------------
1338 // |                                                       |  caller frame |
1339 //                                                         ^ esp           ^ ebp
1340 
1341 
1342 // Runtime function calls are accomplished by doing a stub call to the
1343 // CEntryStub (a real code object). On IA32 passes arguments on the
1344 // stack, the number of arguments in EAX, the address of the runtime function
1345 // in EBX, and the context in ESI.
1346 
1347 // --{ before the call instruction }--------------------------------------------
1348 //                                                         |  caller frame |
1349 //                                                         ^ esp           ^ ebp
1350 
1351 // --{ push arguments and setup EAX, EBX, and ESI }-----------------------------
1352 //                                       | args + receiver |  caller frame |
1353 //                                       ^ esp                             ^ ebp
1354 //              [eax = #args, ebx = runtime function, esi = context]
1355 
1356 // --{ call #CEntryStub }-------------------------------------------------------
1357 //                                 | RET | args + receiver |  caller frame |
1358 //                                 ^ esp                                   ^ ebp
1359 
1360 // =={ body of runtime function }===============================================
1361 
1362 // --{ runtime returns }--------------------------------------------------------
1363 //                                                         |  caller frame |
1364 //                                                         ^ esp           ^ ebp
1365 
1366 // Other custom linkages (e.g. for calling directly into and out of C++) may
1367 // need to save callee-saved registers on the stack, which is done in the
1368 // function prologue of generated code.
1369 
1370 // --{ before the call instruction }--------------------------------------------
1371 //                                                         |  caller frame |
1372 //                                                         ^ esp           ^ ebp
1373 
1374 // --{ set up arguments in registers on stack }---------------------------------
1375 //                                                  | args |  caller frame |
1376 //                                                  ^ esp                  ^ ebp
1377 //                  [r0 = arg0, r1 = arg1, ...]
1378 
1379 // --{ call code }--------------------------------------------------------------
1380 //                                            | RET | args |  caller frame |
1381 //                                            ^ esp                        ^ ebp
1382 
1383 // =={ prologue of called function }============================================
1384 // --{ push ebp }---------------------------------------------------------------
1385 //                                       | FP | RET | args |  caller frame |
1386 //                                       ^ esp                             ^ ebp
1387 
1388 // --{ mov ebp, esp }-----------------------------------------------------------
1389 //                                       | FP | RET | args |  caller frame |
1390 //                                       ^ ebp,esp
1391 
1392 // --{ save registers }---------------------------------------------------------
1393 //                                | regs | FP | RET | args |  caller frame |
1394 //                                ^ esp  ^ ebp
1395 
1396 // --{ subi esp, #N }-----------------------------------------------------------
1397 //                 | callee frame | regs | FP | RET | args |  caller frame |
1398 //                 ^esp                  ^ ebp
1399 
1400 // =={ body of called function }================================================
1401 
1402 // =={ epilogue of called function }============================================
1403 // --{ restore registers }------------------------------------------------------
1404 //                                | regs | FP | RET | args |  caller frame |
1405 //                                ^ esp  ^ ebp
1406 
1407 // --{ mov esp, ebp }-----------------------------------------------------------
1408 //                                       | FP | RET | args |  caller frame |
1409 //                                       ^ esp,ebp
1410 
1411 // --{ pop ebp }----------------------------------------------------------------
1412 //                                            | RET | args |  caller frame |
1413 //                                            ^ esp                        ^ ebp
1414 
1415 
AssemblePrologue()1416 void CodeGenerator::AssemblePrologue() {
1417   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
1418   if (descriptor->IsCFunctionCall()) {
1419     // Assemble a prologue similar the to cdecl calling convention.
1420     __ push(ebp);
1421     __ mov(ebp, esp);
1422   } else if (descriptor->IsJSFunctionCall()) {
1423     // TODO(turbofan): this prologue is redundant with OSR, but still needed for
1424     // code aging.
1425     __ Prologue(this->info()->GeneratePreagedPrologue());
1426   } else if (frame()->needs_frame()) {
1427     __ StubPrologue();
1428   } else {
1429     frame()->SetElidedFrameSizeInSlots(kPCOnStackSize / kPointerSize);
1430   }
1431   frame_access_state()->SetFrameAccessToDefault();
1432 
1433   int stack_shrink_slots = frame()->GetSpillSlotCount();
1434   if (info()->is_osr()) {
1435     // TurboFan OSR-compiled functions cannot be entered directly.
1436     __ Abort(kShouldNotDirectlyEnterOsrFunction);
1437 
1438     // Unoptimized code jumps directly to this entrypoint while the unoptimized
1439     // frame is still on the stack. Optimized code uses OSR values directly from
1440     // the unoptimized frame. Thus, all that needs to be done is to allocate the
1441     // remaining stack slots.
1442     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
1443     osr_pc_offset_ = __ pc_offset();
1444     // TODO(titzer): cannot address target function == local #-1
1445     __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1446     stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
1447   }
1448 
1449   const RegList saves = descriptor->CalleeSavedRegisters();
1450   if (stack_shrink_slots > 0) {
1451     __ sub(esp, Immediate(stack_shrink_slots * kPointerSize));
1452   }
1453 
1454   if (saves != 0) {  // Save callee-saved registers.
1455     DCHECK(!info()->is_osr());
1456     int pushed = 0;
1457     for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
1458       if (!((1 << i) & saves)) continue;
1459       __ push(Register::from_code(i));
1460       ++pushed;
1461     }
1462     frame()->AllocateSavedCalleeRegisterSlots(pushed);
1463   }
1464 }
1465 
1466 
AssembleReturn()1467 void CodeGenerator::AssembleReturn() {
1468   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
1469 
1470   const RegList saves = descriptor->CalleeSavedRegisters();
1471   // Restore registers.
1472   if (saves != 0) {
1473     for (int i = 0; i < Register::kNumRegisters; i++) {
1474       if (!((1 << i) & saves)) continue;
1475       __ pop(Register::from_code(i));
1476     }
1477   }
1478 
1479   if (descriptor->IsCFunctionCall()) {
1480     __ mov(esp, ebp);  // Move stack pointer back to frame pointer.
1481     __ pop(ebp);       // Pop caller's frame pointer.
1482   } else if (frame()->needs_frame()) {
1483     // Canonicalize JSFunction return sites for now.
1484     if (return_label_.is_bound()) {
1485       __ jmp(&return_label_);
1486       return;
1487     } else {
1488       __ bind(&return_label_);
1489       __ mov(esp, ebp);  // Move stack pointer back to frame pointer.
1490       __ pop(ebp);       // Pop caller's frame pointer.
1491     }
1492   }
1493   size_t pop_size = descriptor->StackParameterCount() * kPointerSize;
1494   // Might need ecx for scratch if pop_size is too big.
1495   DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & ecx.bit());
1496   __ Ret(static_cast<int>(pop_size), ecx);
1497 }
1498 
1499 
AssembleMove(InstructionOperand * source,InstructionOperand * destination)1500 void CodeGenerator::AssembleMove(InstructionOperand* source,
1501                                  InstructionOperand* destination) {
1502   IA32OperandConverter g(this, nullptr);
1503   // Dispatch on the source and destination operand kinds.  Not all
1504   // combinations are possible.
1505   if (source->IsRegister()) {
1506     DCHECK(destination->IsRegister() || destination->IsStackSlot());
1507     Register src = g.ToRegister(source);
1508     Operand dst = g.ToOperand(destination);
1509     __ mov(dst, src);
1510   } else if (source->IsStackSlot()) {
1511     DCHECK(destination->IsRegister() || destination->IsStackSlot());
1512     Operand src = g.ToOperand(source);
1513     if (destination->IsRegister()) {
1514       Register dst = g.ToRegister(destination);
1515       __ mov(dst, src);
1516     } else {
1517       Operand dst = g.ToOperand(destination);
1518       __ push(src);
1519       __ pop(dst);
1520     }
1521   } else if (source->IsConstant()) {
1522     Constant src_constant = g.ToConstant(source);
1523     if (src_constant.type() == Constant::kHeapObject) {
1524       Handle<HeapObject> src = src_constant.ToHeapObject();
1525       int offset;
1526       if (IsMaterializableFromFrame(src, &offset)) {
1527         if (destination->IsRegister()) {
1528           Register dst = g.ToRegister(destination);
1529           __ mov(dst, g.ToMaterializableOperand(offset));
1530         } else {
1531           DCHECK(destination->IsStackSlot());
1532           Operand dst = g.ToOperand(destination);
1533           __ push(g.ToMaterializableOperand(offset));
1534           __ pop(dst);
1535         }
1536       } else if (destination->IsRegister()) {
1537         Register dst = g.ToRegister(destination);
1538         __ LoadHeapObject(dst, src);
1539       } else {
1540         DCHECK(destination->IsStackSlot());
1541         Operand dst = g.ToOperand(destination);
1542         AllowDeferredHandleDereference embedding_raw_address;
1543         if (isolate()->heap()->InNewSpace(*src)) {
1544           __ PushHeapObject(src);
1545           __ pop(dst);
1546         } else {
1547           __ mov(dst, src);
1548         }
1549       }
1550     } else if (destination->IsRegister()) {
1551       Register dst = g.ToRegister(destination);
1552       __ Move(dst, g.ToImmediate(source));
1553     } else if (destination->IsStackSlot()) {
1554       Operand dst = g.ToOperand(destination);
1555       __ Move(dst, g.ToImmediate(source));
1556     } else if (src_constant.type() == Constant::kFloat32) {
1557       // TODO(turbofan): Can we do better here?
1558       uint32_t src = bit_cast<uint32_t>(src_constant.ToFloat32());
1559       if (destination->IsDoubleRegister()) {
1560         XMMRegister dst = g.ToDoubleRegister(destination);
1561         __ Move(dst, src);
1562       } else {
1563         DCHECK(destination->IsDoubleStackSlot());
1564         Operand dst = g.ToOperand(destination);
1565         __ Move(dst, Immediate(src));
1566       }
1567     } else {
1568       DCHECK_EQ(Constant::kFloat64, src_constant.type());
1569       uint64_t src = bit_cast<uint64_t>(src_constant.ToFloat64());
1570       uint32_t lower = static_cast<uint32_t>(src);
1571       uint32_t upper = static_cast<uint32_t>(src >> 32);
1572       if (destination->IsDoubleRegister()) {
1573         XMMRegister dst = g.ToDoubleRegister(destination);
1574         __ Move(dst, src);
1575       } else {
1576         DCHECK(destination->IsDoubleStackSlot());
1577         Operand dst0 = g.ToOperand(destination);
1578         Operand dst1 = g.HighOperand(destination);
1579         __ Move(dst0, Immediate(lower));
1580         __ Move(dst1, Immediate(upper));
1581       }
1582     }
1583   } else if (source->IsDoubleRegister()) {
1584     XMMRegister src = g.ToDoubleRegister(source);
1585     if (destination->IsDoubleRegister()) {
1586       XMMRegister dst = g.ToDoubleRegister(destination);
1587       __ movaps(dst, src);
1588     } else {
1589       DCHECK(destination->IsDoubleStackSlot());
1590       Operand dst = g.ToOperand(destination);
1591       __ movsd(dst, src);
1592     }
1593   } else if (source->IsDoubleStackSlot()) {
1594     DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
1595     Operand src = g.ToOperand(source);
1596     if (destination->IsDoubleRegister()) {
1597       XMMRegister dst = g.ToDoubleRegister(destination);
1598       __ movsd(dst, src);
1599     } else {
1600       Operand dst = g.ToOperand(destination);
1601       __ movsd(kScratchDoubleReg, src);
1602       __ movsd(dst, kScratchDoubleReg);
1603     }
1604   } else {
1605     UNREACHABLE();
1606   }
1607 }
1608 
1609 
AssembleSwap(InstructionOperand * source,InstructionOperand * destination)1610 void CodeGenerator::AssembleSwap(InstructionOperand* source,
1611                                  InstructionOperand* destination) {
1612   IA32OperandConverter g(this, nullptr);
1613   // Dispatch on the source and destination operand kinds.  Not all
1614   // combinations are possible.
1615   if (source->IsRegister() && destination->IsRegister()) {
1616     // Register-register.
1617     Register src = g.ToRegister(source);
1618     Register dst = g.ToRegister(destination);
1619     __ push(src);
1620     __ mov(src, dst);
1621     __ pop(dst);
1622   } else if (source->IsRegister() && destination->IsStackSlot()) {
1623     // Register-memory.
1624     Register src = g.ToRegister(source);
1625     __ push(src);
1626     frame_access_state()->IncreaseSPDelta(1);
1627     Operand dst = g.ToOperand(destination);
1628     __ mov(src, dst);
1629     frame_access_state()->IncreaseSPDelta(-1);
1630     dst = g.ToOperand(destination);
1631     __ pop(dst);
1632   } else if (source->IsStackSlot() && destination->IsStackSlot()) {
1633     // Memory-memory.
1634     Operand dst1 = g.ToOperand(destination);
1635     __ push(dst1);
1636     frame_access_state()->IncreaseSPDelta(1);
1637     Operand src1 = g.ToOperand(source);
1638     __ push(src1);
1639     Operand dst2 = g.ToOperand(destination);
1640     __ pop(dst2);
1641     frame_access_state()->IncreaseSPDelta(-1);
1642     Operand src2 = g.ToOperand(source);
1643     __ pop(src2);
1644   } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
1645     // XMM register-register swap.
1646     XMMRegister src = g.ToDoubleRegister(source);
1647     XMMRegister dst = g.ToDoubleRegister(destination);
1648     __ movaps(kScratchDoubleReg, src);
1649     __ movaps(src, dst);
1650     __ movaps(dst, kScratchDoubleReg);
1651   } else if (source->IsDoubleRegister() && destination->IsDoubleStackSlot()) {
1652     // XMM register-memory swap.
1653     XMMRegister reg = g.ToDoubleRegister(source);
1654     Operand other = g.ToOperand(destination);
1655     __ movsd(kScratchDoubleReg, other);
1656     __ movsd(other, reg);
1657     __ movaps(reg, kScratchDoubleReg);
1658   } else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) {
1659     // Double-width memory-to-memory.
1660     Operand src0 = g.ToOperand(source);
1661     Operand src1 = g.HighOperand(source);
1662     Operand dst0 = g.ToOperand(destination);
1663     Operand dst1 = g.HighOperand(destination);
1664     __ movsd(kScratchDoubleReg, dst0);  // Save destination in scratch register.
1665     __ push(src0);  // Then use stack to copy source to destination.
1666     __ pop(dst0);
1667     __ push(src1);
1668     __ pop(dst1);
1669     __ movsd(src0, kScratchDoubleReg);
1670   } else {
1671     // No other combinations are possible.
1672     UNREACHABLE();
1673   }
1674 }
1675 
1676 
AssembleJumpTable(Label ** targets,size_t target_count)1677 void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) {
1678   for (size_t index = 0; index < target_count; ++index) {
1679     __ dd(targets[index]);
1680   }
1681 }
1682 
1683 
AddNopForSmiCodeInlining()1684 void CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); }
1685 
1686 
EnsureSpaceForLazyDeopt()1687 void CodeGenerator::EnsureSpaceForLazyDeopt() {
1688   if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
1689     return;
1690   }
1691 
1692   int space_needed = Deoptimizer::patch_size();
1693   // Ensure that we have enough space after the previous lazy-bailout
1694   // instruction for patching the code here.
1695   int current_pc = masm()->pc_offset();
1696   if (current_pc < last_lazy_deopt_pc_ + space_needed) {
1697     int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
1698     __ Nop(padding_size);
1699   }
1700 }
1701 
1702 #undef __
1703 
1704 }  // namespace compiler
1705 }  // namespace internal
1706 }  // namespace v8
1707