Upstream version 9.38.207.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) V8_OVERRIDE;
158   void GenerateBodyInstructionPost(LInstruction* instr) V8_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,
221                     LEnvironment* environment,
222                     Deoptimizer::BailoutType bailout_type);
223   void DeoptimizeIf(Condition cc, LEnvironment* environment);
224
225   bool DeoptEveryNTimes() {
226     return FLAG_deopt_every_n_times != 0 && !info()->IsStub();
227   }
228
229   void AddToTranslation(LEnvironment* environment,
230                         Translation* translation,
231                         LOperand* op,
232                         bool is_tagged,
233                         bool is_uint32,
234                         int* object_index_pointer,
235                         int* dematerialized_index_pointer);
236   void PopulateDeoptimizationData(Handle<Code> code);
237   int DefineDeoptimizationLiteral(Handle<Object> literal);
238
239   void PopulateDeoptimizationLiteralsWithInlinedFunctions();
240
241   Register ToRegister(int index) const;
242   XMMRegister ToDoubleRegister(int index) const;
243   XMMRegister ToSIMD128Register(int index) const;
244   Operand BuildFastArrayOperand(
245       LOperand* elements_pointer,
246       LOperand* key,
247       Representation key_representation,
248       ElementsKind elements_kind,
249       uint32_t base_offset);
250
251   Operand BuildSeqStringOperand(Register string,
252                                 LOperand* index,
253                                 String::Encoding encoding);
254
255   void EmitIntegerMathAbs(LMathAbs* instr);
256   void EmitSmiMathAbs(LMathAbs* instr);
257
258   // Support for recording safepoint and position information.
259   void RecordSafepoint(LPointerMap* pointers,
260                        Safepoint::Kind kind,
261                        int arguments,
262                        Safepoint::DeoptMode mode);
263   void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
264   void RecordSafepoint(Safepoint::DeoptMode mode);
265   void RecordSafepointWithRegisters(LPointerMap* pointers,
266                                     int arguments,
267                                     Safepoint::DeoptMode mode);
268   void RecordAndWritePosition(int position) V8_OVERRIDE;
269
270   static Condition TokenToCondition(Token::Value op, bool is_unsigned);
271   void EmitGoto(int block);
272
273   // EmitBranch expects to be the last instruction of a block.
274   template<class InstrType>
275   void EmitBranch(InstrType instr, Condition cc);
276   template<class InstrType>
277   void EmitFalseBranch(InstrType instr, Condition cc);
278   void EmitNumberUntagD(
279       Register input,
280       XMMRegister result,
281       bool allow_undefined_as_nan,
282       bool deoptimize_on_minus_zero,
283       LEnvironment* env,
284       NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED);
285
286   // Emits optimized code for typeof x == "y".  Modifies input register.
287   // Returns the condition on which a final split to
288   // true and false label should be made, to optimize fallthrough.
289   Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input);
290
291   // Emits optimized code for %_IsObject(x).  Preserves input register.
292   // Returns the condition on which a final split to
293   // true and false label should be made, to optimize fallthrough.
294   Condition EmitIsObject(Register input,
295                          Label* is_not_object,
296                          Label* is_object);
297
298   // Emits optimized code for %_IsString(x).  Preserves input register.
299   // Returns the condition on which a final split to
300   // true and false label should be made, to optimize fallthrough.
301   Condition EmitIsString(Register input,
302                          Register temp1,
303                          Label* is_not_string,
304                          SmiCheck check_needed);
305
306   // Emits optimized code for %_IsConstructCall().
307   // Caller should branch on equal condition.
308   void EmitIsConstructCall(Register temp);
309
310   // Emits code for pushing either a tagged constant, a (non-double)
311   // register, or a stack slot operand.
312   void EmitPushTaggedOperand(LOperand* operand);
313
314   // Emits optimized code to deep-copy the contents of statically known
315   // object graphs (e.g. object literal boilerplate).
316   void EmitDeepCopy(Handle<JSObject> object,
317                     Register result,
318                     Register source,
319                     int* offset,
320                     AllocationSiteMode mode);
321
322   void EnsureSpaceForLazyDeopt(int space_needed) V8_OVERRIDE;
323   void DoLoadKeyedExternalArray(LLoadKeyed* instr);
324   bool HandleExternalArrayOpRequiresPreScale(LOperand* key,
325                                              Representation key_representation,
326                                              ElementsKind elements_kind);
327   void DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr);
328   void DoLoadKeyedFixedArray(LLoadKeyed* instr);
329   void DoStoreKeyedExternalArray(LStoreKeyed* instr);
330   void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
331   void DoStoreKeyedFixedArray(LStoreKeyed* instr);
332 #ifdef _MSC_VER
333   // On windows, you may not access the stack more than one page below
334   // the most recently mapped page. To make the allocated area randomly
335   // accessible, we write an arbitrary value to each page in range
336   // rsp + offset - page_size .. rsp in turn.
337   void MakeSureStackPagesMapped(int offset);
338 #endif
339
340   ZoneList<LEnvironment*> deoptimizations_;
341   ZoneList<Deoptimizer::JumpTableEntry> jump_table_;
342   ZoneList<Handle<Object> > deoptimization_literals_;
343   int inlined_function_count_;
344   Scope* const scope_;
345   TranslationBuffer translations_;
346   ZoneList<LDeferredCode*> deferred_;
347   int osr_pc_offset_;
348   bool frame_is_built_;
349
350   // Builder that keeps track of safepoints in the code. The table
351   // itself is emitted at the end of the generated code.
352   SafepointTableBuilder safepoints_;
353
354   // Compiler from a set of parallel moves to a sequential list of moves.
355   LGapResolver resolver_;
356
357   Safepoint::Kind expected_safepoint_kind_;
358
359   class PushSafepointRegistersScope V8_FINAL BASE_EMBEDDED {
360    public:
361     explicit PushSafepointRegistersScope(LCodeGen* codegen)
362         : codegen_(codegen) {
363       DCHECK(codegen_->info()->is_calling());
364       DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
365       codegen_->masm_->PushSafepointRegisters();
366       codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters;
367     }
368
369     ~PushSafepointRegistersScope() {
370       DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters);
371       codegen_->masm_->PopSafepointRegisters();
372       codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
373     }
374
375    private:
376     LCodeGen* codegen_;
377   };
378
379   friend class LDeferredCode;
380   friend class LEnvironment;
381   friend class SafepointGenerator;
382   DISALLOW_COPY_AND_ASSIGN(LCodeGen);
383 };
384
385
386 class LDeferredCode: public ZoneObject {
387  public:
388   explicit LDeferredCode(LCodeGen* codegen)
389       : codegen_(codegen),
390         external_exit_(NULL),
391         instruction_index_(codegen->current_instruction_) {
392     codegen->AddDeferredCode(this);
393   }
394
395   virtual ~LDeferredCode() {}
396   virtual void Generate() = 0;
397   virtual LInstruction* instr() = 0;
398
399   void SetExit(Label* exit) { external_exit_ = exit; }
400   Label* entry() { return &entry_; }
401   Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
402   Label* done() { return codegen_->NeedsDeferredFrame() ? &done_ : exit(); }
403   int instruction_index() const { return instruction_index_; }
404
405  protected:
406   LCodeGen* codegen() const { return codegen_; }
407   MacroAssembler* masm() const { return codegen_->masm(); }
408
409  private:
410   LCodeGen* codegen_;
411   Label entry_;
412   Label exit_;
413   Label done_;
414   Label* external_exit_;
415   int instruction_index_;
416 };
417
418 } }  // namespace v8::internal
419
420 #endif  // V8_X64_LITHIUM_CODEGEN_X64_H_