lithium-codegen-arm.h revision 1e0659c275bb392c045087af4f6b0d7565cb3d77
1// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_ARM_LITHIUM_CODEGEN_ARM_H_
29#define V8_ARM_LITHIUM_CODEGEN_ARM_H_
30
31#include "arm/lithium-arm.h"
32
33#include "deoptimizer.h"
34#include "safepoint-table.h"
35#include "scopes.h"
36
37namespace v8 {
38namespace internal {
39
40// Forward declarations.
41class LDeferredCode;
42class LGapNode;
43class SafepointGenerator;
44
45class LGapResolver BASE_EMBEDDED {
46 public:
47  LGapResolver();
48  const ZoneList<LMoveOperands>* Resolve(const ZoneList<LMoveOperands>* moves,
49                                         LOperand* marker_operand);
50
51 private:
52  LGapNode* LookupNode(LOperand* operand);
53  bool CanReach(LGapNode* a, LGapNode* b, int visited_id);
54  bool CanReach(LGapNode* a, LGapNode* b);
55  void RegisterMove(LMoveOperands move);
56  void AddResultMove(LOperand* from, LOperand* to);
57  void AddResultMove(LGapNode* from, LGapNode* to);
58  void ResolveCycle(LGapNode* start, LOperand* marker_operand);
59
60  ZoneList<LGapNode*> nodes_;
61  ZoneList<LGapNode*> identified_cycles_;
62  ZoneList<LMoveOperands> result_;
63  int next_visited_id_;
64};
65
66
67class LCodeGen BASE_EMBEDDED {
68 public:
69  LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
70      : chunk_(chunk),
71        masm_(assembler),
72        info_(info),
73        current_block_(-1),
74        current_instruction_(-1),
75        instructions_(chunk->instructions()),
76        deoptimizations_(4),
77        deoptimization_literals_(8),
78        inlined_function_count_(0),
79        scope_(chunk->graph()->info()->scope()),
80        status_(UNUSED),
81        deferred_(8),
82        osr_pc_offset_(-1) {
83    PopulateDeoptimizationLiteralsWithInlinedFunctions();
84  }
85
86  // Try to generate code for the entire chunk, but it may fail if the
87  // chunk contains constructs we cannot handle. Returns true if the
88  // code generation attempt succeeded.
89  bool GenerateCode();
90
91  // Finish the code by setting stack height, safepoint, and bailout
92  // information on it.
93  void FinishCode(Handle<Code> code);
94
95  // Deferred code support.
96  template<int T>
97  void DoDeferredGenericBinaryStub(LTemplateInstruction<1, 2, T>* instr,
98                                   Token::Value op);
99  void DoDeferredNumberTagD(LNumberTagD* instr);
100  void DoDeferredNumberTagI(LNumberTagI* instr);
101  void DoDeferredTaggedToI(LTaggedToI* instr);
102  void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
103  void DoDeferredStackCheck(LGoto* instr);
104  void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
105  void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
106                                        Label* map_check);
107
108  // Parallel move support.
109  void DoParallelMove(LParallelMove* move);
110
111  // Emit frame translation commands for an environment.
112  void WriteTranslation(LEnvironment* environment, Translation* translation);
113
114  // Declare methods that deal with the individual node types.
115#define DECLARE_DO(type) void Do##type(L##type* node);
116  LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
117#undef DECLARE_DO
118
119 private:
120  enum Status {
121    UNUSED,
122    GENERATING,
123    DONE,
124    ABORTED
125  };
126
127  bool is_unused() const { return status_ == UNUSED; }
128  bool is_generating() const { return status_ == GENERATING; }
129  bool is_done() const { return status_ == DONE; }
130  bool is_aborted() const { return status_ == ABORTED; }
131
132  LChunk* chunk() const { return chunk_; }
133  Scope* scope() const { return scope_; }
134  HGraph* graph() const { return chunk_->graph(); }
135  MacroAssembler* masm() const { return masm_; }
136
137  Register scratch0() { return r9; }
138  DwVfpRegister double_scratch0() { return d0; }
139
140  int GetNextEmittedBlock(int block);
141  LInstruction* GetNextInstruction();
142
143  void EmitClassOfTest(Label* if_true,
144                       Label* if_false,
145                       Handle<String> class_name,
146                       Register input,
147                       Register temporary,
148                       Register temporary2);
149
150  int StackSlotCount() const { return chunk()->spill_slot_count(); }
151  int ParameterCount() const { return scope()->num_parameters(); }
152
153  void Abort(const char* format, ...);
154  void Comment(const char* format, ...);
155
156  void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); }
157
158  // Code generation passes.  Returns true if code generation should
159  // continue.
160  bool GeneratePrologue();
161  bool GenerateBody();
162  bool GenerateDeferredCode();
163  bool GenerateSafepointTable();
164
165  void CallCode(Handle<Code> code,
166                RelocInfo::Mode mode,
167                LInstruction* instr);
168  void CallRuntime(Runtime::Function* function,
169                   int num_arguments,
170                   LInstruction* instr);
171  void CallRuntime(Runtime::FunctionId id,
172                   int num_arguments,
173                   LInstruction* instr) {
174    Runtime::Function* function = Runtime::FunctionForId(id);
175    CallRuntime(function, num_arguments, instr);
176  }
177
178  // Generate a direct call to a known function.  Expects the function
179  // to be in edi.
180  void CallKnownFunction(Handle<JSFunction> function,
181                         int arity,
182                         LInstruction* instr);
183
184  void LoadHeapObject(Register result, Handle<HeapObject> object);
185
186  void RegisterLazyDeoptimization(LInstruction* instr);
187  void RegisterEnvironmentForDeoptimization(LEnvironment* environment);
188  void DeoptimizeIf(Condition cc, LEnvironment* environment);
189
190  void AddToTranslation(Translation* translation,
191                        LOperand* op,
192                        bool is_tagged);
193  void PopulateDeoptimizationData(Handle<Code> code);
194  int DefineDeoptimizationLiteral(Handle<Object> literal);
195
196  void PopulateDeoptimizationLiteralsWithInlinedFunctions();
197
198  Register ToRegister(int index) const;
199  DoubleRegister ToDoubleRegister(int index) const;
200
201  // LOperand must be a register.
202  Register ToRegister(LOperand* op) const;
203
204  // LOperand is loaded into scratch, unless already a register.
205  Register EmitLoadRegister(LOperand* op, Register scratch);
206
207  // LOperand must be a double register.
208  DoubleRegister ToDoubleRegister(LOperand* op) const;
209
210  // LOperand is loaded into dbl_scratch, unless already a double register.
211  DoubleRegister EmitLoadDoubleRegister(LOperand* op,
212                                        SwVfpRegister flt_scratch,
213                                        DoubleRegister dbl_scratch);
214
215  int ToInteger32(LConstantOperand* op) const;
216  Operand ToOperand(LOperand* op);
217  MemOperand ToMemOperand(LOperand* op) const;
218
219  // Specific math operations - used from DoUnaryMathOperation.
220  void EmitIntegerMathAbs(LUnaryMathOperation* instr);
221  void DoMathAbs(LUnaryMathOperation* instr);
222  void EmitVFPTruncate(VFPRoundingMode rounding_mode,
223                       SwVfpRegister result,
224                       DwVfpRegister double_input,
225                       Register scratch1,
226                       Register scratch2);
227  void DoMathFloor(LUnaryMathOperation* instr);
228  void DoMathSqrt(LUnaryMathOperation* instr);
229
230  // Support for recording safepoint and position information.
231  void RecordSafepoint(LPointerMap* pointers,
232                       Safepoint::Kind kind,
233                       int arguments,
234                       int deoptimization_index);
235  void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
236  void RecordSafepointWithRegisters(LPointerMap* pointers,
237                                    int arguments,
238                                    int deoptimization_index);
239  void RecordSafepointWithRegistersAndDoubles(LPointerMap* pointers,
240                                              int arguments,
241                                              int deoptimization_index);
242  void RecordPosition(int position);
243
244  static Condition TokenToCondition(Token::Value op, bool is_unsigned);
245  void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL);
246  void EmitBranch(int left_block, int right_block, Condition cc);
247  void EmitCmpI(LOperand* left, LOperand* right);
248  void EmitNumberUntagD(Register input,
249                        DoubleRegister result,
250                        LEnvironment* env);
251
252  // Emits optimized code for typeof x == "y".  Modifies input register.
253  // Returns the condition on which a final split to
254  // true and false label should be made, to optimize fallthrough.
255  Condition EmitTypeofIs(Label* true_label, Label* false_label,
256                         Register input, Handle<String> type_name);
257
258  // Emits optimized code for %_IsObject(x).  Preserves input register.
259  // Returns the condition on which a final split to
260  // true and false label should be made, to optimize fallthrough.
261  Condition EmitIsObject(Register input,
262                         Register temp1,
263                         Register temp2,
264                         Label* is_not_object,
265                         Label* is_object);
266
267  // Emits optimized code for %_IsConstructCall().
268  // Caller should branch on equal condition.
269  void EmitIsConstructCall(Register temp1, Register temp2);
270
271  LChunk* const chunk_;
272  MacroAssembler* const masm_;
273  CompilationInfo* const info_;
274
275  int current_block_;
276  int current_instruction_;
277  const ZoneList<LInstruction*>* instructions_;
278  ZoneList<LEnvironment*> deoptimizations_;
279  ZoneList<Handle<Object> > deoptimization_literals_;
280  int inlined_function_count_;
281  Scope* const scope_;
282  Status status_;
283  TranslationBuffer translations_;
284  ZoneList<LDeferredCode*> deferred_;
285  int osr_pc_offset_;
286
287  // Builder that keeps track of safepoints in the code. The table
288  // itself is emitted at the end of the generated code.
289  SafepointTableBuilder safepoints_;
290
291  // Compiler from a set of parallel moves to a sequential list of moves.
292  LGapResolver resolver_;
293
294  friend class LDeferredCode;
295  friend class LEnvironment;
296  friend class SafepointGenerator;
297  DISALLOW_COPY_AND_ASSIGN(LCodeGen);
298};
299
300
301class LDeferredCode: public ZoneObject {
302 public:
303  explicit LDeferredCode(LCodeGen* codegen)
304      : codegen_(codegen), external_exit_(NULL) {
305    codegen->AddDeferredCode(this);
306  }
307
308  virtual ~LDeferredCode() { }
309  virtual void Generate() = 0;
310
311  void SetExit(Label *exit) { external_exit_ = exit; }
312  Label* entry() { return &entry_; }
313  Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
314
315 protected:
316  LCodeGen* codegen() const { return codegen_; }
317  MacroAssembler* masm() const { return codegen_->masm(); }
318
319 private:
320  LCodeGen* codegen_;
321  Label entry_;
322  Label exit_;
323  Label* external_exit_;
324};
325
326} }  // namespace v8::internal
327
328#endif  // V8_ARM_LITHIUM_CODEGEN_ARM_H_
329