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