3e21266d57810727e1ea35385c44ddc7b163db6c
[platform/framework/web/crosswalk.git] / src / v8 / src / x64 / lithium-codegen-x64.h
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_X64_LITHIUM_CODEGEN_X64_H_
6 #define V8_X64_LITHIUM_CODEGEN_X64_H_
7
8 #include "x64/lithium-x64.h"
9
10 #include "checks.h"
11 #include "deoptimizer.h"
12 #include "lithium-codegen.h"
13 #include "safepoint-table.h"
14 #include "scopes.h"
15 #include "utils.h"
16 #include "x64/lithium-gap-resolver-x64.h"
17
18 namespace v8 {
19 namespace internal {
20
21 // Forward declarations.
22 class LDeferredCode;
23 class SafepointGenerator;
24
25 class LCodeGen: public LCodeGenBase {
26  public:
27   LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
28       : LCodeGenBase(chunk, assembler, info),
29         deoptimizations_(4, info->zone()),
30         jump_table_(4, info->zone()),
31         deoptimization_literals_(8, info->zone()),
32         inlined_function_count_(0),
33         scope_(info->scope()),
34         translations_(info->zone()),
35         deferred_(8, info->zone()),
36         osr_pc_offset_(-1),
37         frame_is_built_(false),
38         safepoints_(info->zone()),
39         resolver_(this),
40         expected_safepoint_kind_(Safepoint::kSimple) {
41     PopulateDeoptimizationLiteralsWithInlinedFunctions();
42   }
43
44   int LookupDestination(int block_id) const {
45     return chunk()->LookupDestination(block_id);
46   }
47
48   bool IsNextEmittedBlock(int block_id) const {
49     return LookupDestination(block_id) == GetNextEmittedBlock();
50   }
51
52   bool NeedsEagerFrame() const {
53     return GetStackSlotCount() > 0 ||
54         info()->is_non_deferred_calling() ||
55         !info()->IsStub() ||
56         info()->requires_frame();
57   }
58   bool NeedsDeferredFrame() const {
59     return !NeedsEagerFrame() && info()->is_deferred_calling();
60   }
61
62   // Support for converting LOperands to assembler types.
63   Register ToRegister(LOperand* op) const;
64   XMMRegister ToDoubleRegister(LOperand* op) const;
65   XMMRegister ToFloat32x4Register(LOperand* op) const;
66   XMMRegister ToFloat64x2Register(LOperand* op) const;
67   XMMRegister ToInt32x4Register(LOperand* op) const;
68   XMMRegister ToSIMD128Register(LOperand* op) const;
69   bool IsInteger32Constant(LConstantOperand* op) const;
70   bool IsDehoistedKeyConstant(LConstantOperand* op) const;
71   bool IsSmiConstant(LConstantOperand* op) const;
72   int32_t ToInteger32(LConstantOperand* op) const;
73   Smi* ToSmi(LConstantOperand* op) const;
74   double ToDouble(LConstantOperand* op) const;
75   ExternalReference ToExternalReference(LConstantOperand* op) const;
76   Handle<Object> ToHandle(LConstantOperand* op) const;
77   Operand ToOperand(LOperand* op) const;
78
79   // Try to generate code for the entire chunk, but it may fail if the
80   // chunk contains constructs we cannot handle. Returns true if the
81   // code generation attempt succeeded.
82   bool GenerateCode();
83
84   // Finish the code by setting stack height, safepoint, and bailout
85   // information on it.
86   void FinishCode(Handle<Code> code);
87
88   // Deferred code support.
89   void DoDeferredNumberTagD(LNumberTagD* instr);
90   void DoDeferredNumberTagU(LNumberTagU* instr);
91   void DoDeferredTaggedToI(LTaggedToI* instr, Label* done);
92   void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr);
93   void DoDeferredStackCheck(LStackCheck* instr);
94   void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
95   void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
96   void DoDeferredAllocate(LAllocate* instr);
97   void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
98                                        Label* map_check);
99   void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
100   void DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
101                                    Register object,
102                                    Register index);
103   void DoDeferredSIMD128ToTagged(LSIMD128ToTagged* instr,
104                                  Runtime::FunctionId id);
105
106   template<class T>
107   void HandleTaggedToSIMD128(LTaggedToSIMD128* instr);
108   template<class T>
109   void HandleSIMD128ToTagged(LSIMD128ToTagged* instr);
110
111 // Parallel move support.
112   void DoParallelMove(LParallelMove* move);
113   void DoGap(LGap* instr);
114
115   // Emit frame translation commands for an environment.
116   void WriteTranslation(LEnvironment* environment, Translation* translation);
117
118   // Declare methods that deal with the individual node types.
119 #define DECLARE_DO(type) void Do##type(L##type* node);
120   LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
121 #undef DECLARE_DO
122
123  private:
124   StrictMode strict_mode() const { return info()->strict_mode(); }
125
126   LPlatformChunk* chunk() const { return chunk_; }
127   Scope* scope() const { return scope_; }
128   HGraph* graph() const { return chunk()->graph(); }
129
130   XMMRegister double_scratch0() const { return xmm0; }
131
132   void EmitClassOfTest(Label* if_true,
133                        Label* if_false,
134                        Handle<String> class_name,
135                        Register input,
136                        Register temporary,
137                        Register scratch);
138
139   int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
140
141   void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
142
143
144   void SaveCallerDoubles();
145   void RestoreCallerDoubles();
146
147   // Code generation passes.  Returns true if code generation should
148   // continue.
149   void GenerateBodyInstructionPre(LInstruction* instr) V8_OVERRIDE;
150   void GenerateBodyInstructionPost(LInstruction* instr) V8_OVERRIDE;
151   bool GeneratePrologue();
152   bool GenerateDeferredCode();
153   bool GenerateJumpTable();
154   bool GenerateSafepointTable();
155
156   // Generates the custom OSR entrypoint and sets the osr_pc_offset.
157   void GenerateOsrPrologue();
158
159   enum SafepointMode {
160     RECORD_SIMPLE_SAFEPOINT,
161     RECORD_SAFEPOINT_WITH_REGISTERS
162   };
163
164   void CallCodeGeneric(Handle<Code> code,
165                        RelocInfo::Mode mode,
166                        LInstruction* instr,
167                        SafepointMode safepoint_mode,
168                        int argc);
169
170
171   void CallCode(Handle<Code> code,
172                 RelocInfo::Mode mode,
173                 LInstruction* instr);
174
175   void CallRuntime(const Runtime::Function* function,
176                    int num_arguments,
177                    LInstruction* instr,
178                    SaveFPRegsMode save_doubles = kDontSaveFPRegs);
179
180   void CallRuntime(Runtime::FunctionId id,
181                    int num_arguments,
182                    LInstruction* instr) {
183     const Runtime::Function* function = Runtime::FunctionForId(id);
184     CallRuntime(function, num_arguments, instr);
185   }
186
187   void CallRuntimeFromDeferred(Runtime::FunctionId id,
188                                int argc,
189                                LInstruction* instr,
190                                LOperand* context);
191
192   void LoadContextFromDeferred(LOperand* context);
193
194   enum RDIState {
195     RDI_UNINITIALIZED,
196     RDI_CONTAINS_TARGET
197   };
198
199   // Generate a direct call to a known function.  Expects the function
200   // to be in rdi.
201   void CallKnownFunction(Handle<JSFunction> function,
202                          int formal_parameter_count,
203                          int arity,
204                          LInstruction* instr,
205                          RDIState rdi_state);
206
207   void RecordSafepointWithLazyDeopt(LInstruction* instr,
208                                     SafepointMode safepoint_mode,
209                                     int argc);
210   void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
211                                             Safepoint::DeoptMode mode);
212   void DeoptimizeIf(Condition cc,
213                     LEnvironment* environment,
214                     Deoptimizer::BailoutType bailout_type);
215   void DeoptimizeIf(Condition cc, LEnvironment* environment);
216
217   bool DeoptEveryNTimes() {
218     return FLAG_deopt_every_n_times != 0 && !info()->IsStub();
219   }
220
221   void AddToTranslation(LEnvironment* environment,
222                         Translation* translation,
223                         LOperand* op,
224                         bool is_tagged,
225                         bool is_uint32,
226                         int* object_index_pointer,
227                         int* dematerialized_index_pointer);
228   void PopulateDeoptimizationData(Handle<Code> code);
229   int DefineDeoptimizationLiteral(Handle<Object> literal);
230
231   void PopulateDeoptimizationLiteralsWithInlinedFunctions();
232
233   Register ToRegister(int index) const;
234   XMMRegister ToDoubleRegister(int index) const;
235   XMMRegister ToSIMD128Register(int index) const;
236   Operand BuildFastArrayOperand(
237       LOperand* elements_pointer,
238       LOperand* key,
239       ElementsKind elements_kind,
240       uint32_t offset,
241       uint32_t additional_index = 0);
242
243   Operand BuildSeqStringOperand(Register string,
244                                 LOperand* index,
245                                 String::Encoding encoding);
246
247   void EmitIntegerMathAbs(LMathAbs* instr);
248   void EmitSmiMathAbs(LMathAbs* instr);
249
250   // Support for recording safepoint and position information.
251   void RecordSafepoint(LPointerMap* pointers,
252                        Safepoint::Kind kind,
253                        int arguments,
254                        Safepoint::DeoptMode mode);
255   void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
256   void RecordSafepoint(Safepoint::DeoptMode mode);
257   void RecordSafepointWithRegisters(LPointerMap* pointers,
258                                     int arguments,
259                                     Safepoint::DeoptMode mode);
260   void RecordAndWritePosition(int position) V8_OVERRIDE;
261
262   static Condition TokenToCondition(Token::Value op, bool is_unsigned);
263   void EmitGoto(int block);
264
265   // EmitBranch expects to be the last instruction of a block.
266   template<class InstrType>
267   void EmitBranch(InstrType instr, Condition cc);
268   template<class InstrType>
269   void EmitFalseBranch(InstrType instr, Condition cc);
270   void EmitNumberUntagD(
271       Register input,
272       XMMRegister result,
273       bool allow_undefined_as_nan,
274       bool deoptimize_on_minus_zero,
275       LEnvironment* env,
276       NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED);
277
278   // Emits optimized code for typeof x == "y".  Modifies input register.
279   // Returns the condition on which a final split to
280   // true and false label should be made, to optimize fallthrough.
281   Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input);
282
283   // Emits optimized code for %_IsObject(x).  Preserves input register.
284   // Returns the condition on which a final split to
285   // true and false label should be made, to optimize fallthrough.
286   Condition EmitIsObject(Register input,
287                          Label* is_not_object,
288                          Label* is_object);
289
290   // Emits optimized code for %_IsString(x).  Preserves input register.
291   // Returns the condition on which a final split to
292   // true and false label should be made, to optimize fallthrough.
293   Condition EmitIsString(Register input,
294                          Register temp1,
295                          Label* is_not_string,
296                          SmiCheck check_needed);
297
298   // Emits optimized code for %_IsConstructCall().
299   // Caller should branch on equal condition.
300   void EmitIsConstructCall(Register temp);
301
302   // Emits code for pushing either a tagged constant, a (non-double)
303   // register, or a stack slot operand.
304   void EmitPushTaggedOperand(LOperand* operand);
305
306   // Emits optimized code to deep-copy the contents of statically known
307   // object graphs (e.g. object literal boilerplate).
308   void EmitDeepCopy(Handle<JSObject> object,
309                     Register result,
310                     Register source,
311                     int* offset,
312                     AllocationSiteMode mode);
313
314   void EnsureSpaceForLazyDeopt(int space_needed) V8_OVERRIDE;
315   void DoLoadKeyedExternalArray(LLoadKeyed* instr);
316   void HandleExternalArrayOpRequiresPreScale(LOperand* key,
317                                              ElementsKind elements_kind);
318   void DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr);
319   void DoLoadKeyedFixedArray(LLoadKeyed* instr);
320   void DoStoreKeyedExternalArray(LStoreKeyed* instr);
321   void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
322   void DoStoreKeyedFixedArray(LStoreKeyed* instr);
323 #ifdef _MSC_VER
324   // On windows, you may not access the stack more than one page below
325   // the most recently mapped page. To make the allocated area randomly
326   // accessible, we write an arbitrary value to each page in range
327   // rsp + offset - page_size .. rsp in turn.
328   void MakeSureStackPagesMapped(int offset);
329 #endif
330
331   ZoneList<LEnvironment*> deoptimizations_;
332   ZoneList<Deoptimizer::JumpTableEntry> jump_table_;
333   ZoneList<Handle<Object> > deoptimization_literals_;
334   int inlined_function_count_;
335   Scope* const scope_;
336   TranslationBuffer translations_;
337   ZoneList<LDeferredCode*> deferred_;
338   int osr_pc_offset_;
339   bool frame_is_built_;
340
341   // Builder that keeps track of safepoints in the code. The table
342   // itself is emitted at the end of the generated code.
343   SafepointTableBuilder safepoints_;
344
345   // Compiler from a set of parallel moves to a sequential list of moves.
346   LGapResolver resolver_;
347
348   Safepoint::Kind expected_safepoint_kind_;
349
350   class PushSafepointRegistersScope V8_FINAL BASE_EMBEDDED {
351    public:
352     explicit PushSafepointRegistersScope(LCodeGen* codegen)
353         : codegen_(codegen) {
354       ASSERT(codegen_->info()->is_calling());
355       ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
356       codegen_->masm_->PushSafepointRegisters();
357       codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters;
358     }
359
360     ~PushSafepointRegistersScope() {
361       ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters);
362       codegen_->masm_->PopSafepointRegisters();
363       codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
364     }
365
366    private:
367     LCodeGen* codegen_;
368   };
369
370   friend class LDeferredCode;
371   friend class LEnvironment;
372   friend class SafepointGenerator;
373   DISALLOW_COPY_AND_ASSIGN(LCodeGen);
374 };
375
376
377 class LDeferredCode: public ZoneObject {
378  public:
379   explicit LDeferredCode(LCodeGen* codegen)
380       : codegen_(codegen),
381         external_exit_(NULL),
382         instruction_index_(codegen->current_instruction_) {
383     codegen->AddDeferredCode(this);
384   }
385
386   virtual ~LDeferredCode() {}
387   virtual void Generate() = 0;
388   virtual LInstruction* instr() = 0;
389
390   void SetExit(Label* exit) { external_exit_ = exit; }
391   Label* entry() { return &entry_; }
392   Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
393   Label* done() { return codegen_->NeedsDeferredFrame() ? &done_ : exit(); }
394   int instruction_index() const { return instruction_index_; }
395
396  protected:
397   LCodeGen* codegen() const { return codegen_; }
398   MacroAssembler* masm() const { return codegen_->masm(); }
399
400  private:
401   LCodeGen* codegen_;
402   Label entry_;
403   Label exit_;
404   Label done_;
405   Label* external_exit_;
406   int instruction_index_;
407 };
408
409 } }  // namespace v8::internal
410
411 #endif  // V8_X64_LITHIUM_CODEGEN_X64_H_