lithium-codegen-arm.h revision 44f0eee88ff00398ff7f715fab053374d808c90d
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#include "arm/lithium-gap-resolver-arm.h"
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 SafepointGenerator;
43
44class LCodeGen BASE_EMBEDDED {
45 public:
46  LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
47      : chunk_(chunk),
48        masm_(assembler),
49        info_(info),
50        current_block_(-1),
51        current_instruction_(-1),
52        instructions_(chunk->instructions()),
53        deoptimizations_(4),
54        deoptimization_literals_(8),
55        inlined_function_count_(0),
56        scope_(info->scope()),
57        status_(UNUSED),
58        deferred_(8),
59        osr_pc_offset_(-1),
60        resolver_(this) {
61    PopulateDeoptimizationLiteralsWithInlinedFunctions();
62  }
63
64
65  // Simple accessors.
66  MacroAssembler* masm() const { return masm_; }
67  CompilationInfo* info() const { return info_; }
68  Isolate* isolate() const { return info_->isolate(); }
69  Factory* factory() const { return isolate()->factory(); }
70  Heap* heap() const { return isolate()->heap(); }
71
72  // Support for converting LOperands to assembler types.
73  // LOperand must be a register.
74  Register ToRegister(LOperand* op) const;
75
76  // LOperand is loaded into scratch, unless already a register.
77  Register EmitLoadRegister(LOperand* op, Register scratch);
78
79  // LOperand must be a double register.
80  DoubleRegister ToDoubleRegister(LOperand* op) const;
81
82  // LOperand is loaded into dbl_scratch, unless already a double register.
83  DoubleRegister EmitLoadDoubleRegister(LOperand* op,
84                                        SwVfpRegister flt_scratch,
85                                        DoubleRegister dbl_scratch);
86  int ToInteger32(LConstantOperand* op) const;
87  Operand ToOperand(LOperand* op);
88  MemOperand ToMemOperand(LOperand* op) const;
89  // Returns a MemOperand pointing to the high word of a DoubleStackSlot.
90  MemOperand ToHighMemOperand(LOperand* op) const;
91
92  // Try to generate code for the entire chunk, but it may fail if the
93  // chunk contains constructs we cannot handle. Returns true if the
94  // code generation attempt succeeded.
95  bool GenerateCode();
96
97  // Finish the code by setting stack height, safepoint, and bailout
98  // information on it.
99  void FinishCode(Handle<Code> code);
100
101  // Deferred code support.
102  template<int T>
103  void DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr,
104                              Token::Value op);
105  void DoDeferredNumberTagD(LNumberTagD* instr);
106  void DoDeferredNumberTagI(LNumberTagI* instr);
107  void DoDeferredTaggedToI(LTaggedToI* instr);
108  void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
109  void DoDeferredStackCheck(LGoto* instr);
110  void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
111  void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
112  void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
113                                        Label* map_check);
114
115  // Parallel move support.
116  void DoParallelMove(LParallelMove* move);
117
118  // Emit frame translation commands for an environment.
119  void WriteTranslation(LEnvironment* environment, Translation* translation);
120
121  // Declare methods that deal with the individual node types.
122#define DECLARE_DO(type) void Do##type(L##type* node);
123  LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
124#undef DECLARE_DO
125
126 private:
127  enum Status {
128    UNUSED,
129    GENERATING,
130    DONE,
131    ABORTED
132  };
133
134  bool is_unused() const { return status_ == UNUSED; }
135  bool is_generating() const { return status_ == GENERATING; }
136  bool is_done() const { return status_ == DONE; }
137  bool is_aborted() const { return status_ == ABORTED; }
138
139  int strict_mode_flag() const {
140    return info()->is_strict() ? kStrictMode : kNonStrictMode;
141  }
142
143  LChunk* chunk() const { return chunk_; }
144  Scope* scope() const { return scope_; }
145  HGraph* graph() const { return chunk_->graph(); }
146
147  Register scratch0() { return r9; }
148  DwVfpRegister double_scratch0() { return d0; }
149
150  int GetNextEmittedBlock(int block);
151  LInstruction* GetNextInstruction();
152
153  void EmitClassOfTest(Label* if_true,
154                       Label* if_false,
155                       Handle<String> class_name,
156                       Register input,
157                       Register temporary,
158                       Register temporary2);
159
160  int StackSlotCount() const { return chunk()->spill_slot_count(); }
161  int ParameterCount() const { return scope()->num_parameters(); }
162
163  void Abort(const char* format, ...);
164  void Comment(const char* format, ...);
165
166  void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); }
167
168  // Code generation passes.  Returns true if code generation should
169  // continue.
170  bool GeneratePrologue();
171  bool GenerateBody();
172  bool GenerateDeferredCode();
173  bool GenerateSafepointTable();
174
175  void CallCode(Handle<Code> code,
176                RelocInfo::Mode mode,
177                LInstruction* instr);
178  void CallRuntime(const Runtime::Function* function,
179                   int num_arguments,
180                   LInstruction* instr);
181  void CallRuntime(Runtime::FunctionId id,
182                   int num_arguments,
183                   LInstruction* instr) {
184    const Runtime::Function* function = Runtime::FunctionForId(id);
185    CallRuntime(function, num_arguments, instr);
186  }
187
188  // Generate a direct call to a known function.  Expects the function
189  // to be in edi.
190  void CallKnownFunction(Handle<JSFunction> function,
191                         int arity,
192                         LInstruction* instr);
193
194  void LoadHeapObject(Register result, Handle<HeapObject> object);
195
196  void RegisterLazyDeoptimization(LInstruction* instr);
197  void RegisterEnvironmentForDeoptimization(LEnvironment* environment);
198  void DeoptimizeIf(Condition cc, LEnvironment* environment);
199
200  void AddToTranslation(Translation* translation,
201                        LOperand* op,
202                        bool is_tagged);
203  void PopulateDeoptimizationData(Handle<Code> code);
204  int DefineDeoptimizationLiteral(Handle<Object> literal);
205
206  void PopulateDeoptimizationLiteralsWithInlinedFunctions();
207
208  Register ToRegister(int index) const;
209  DoubleRegister ToDoubleRegister(int index) const;
210
211  // Specific math operations - used from DoUnaryMathOperation.
212  void EmitIntegerMathAbs(LUnaryMathOperation* instr);
213  void DoMathAbs(LUnaryMathOperation* instr);
214  void DoMathFloor(LUnaryMathOperation* instr);
215  void DoMathRound(LUnaryMathOperation* instr);
216  void DoMathSqrt(LUnaryMathOperation* instr);
217  void DoMathPowHalf(LUnaryMathOperation* instr);
218  void DoMathLog(LUnaryMathOperation* instr);
219  void DoMathCos(LUnaryMathOperation* instr);
220  void DoMathSin(LUnaryMathOperation* instr);
221
222  // Support for recording safepoint and position information.
223  void RecordSafepoint(LPointerMap* pointers,
224                       Safepoint::Kind kind,
225                       int arguments,
226                       int deoptimization_index);
227  void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
228  void RecordSafepoint(int deoptimization_index);
229  void RecordSafepointWithRegisters(LPointerMap* pointers,
230                                    int arguments,
231                                    int deoptimization_index);
232  void RecordSafepointWithRegistersAndDoubles(LPointerMap* pointers,
233                                              int arguments,
234                                              int deoptimization_index);
235  void RecordPosition(int position);
236  int LastSafepointEnd() {
237    return static_cast<int>(safepoints_.GetPcAfterGap());
238  }
239
240  static Condition TokenToCondition(Token::Value op, bool is_unsigned);
241  void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL);
242  void EmitBranch(int left_block, int right_block, Condition cc);
243  void EmitCmpI(LOperand* left, LOperand* right);
244  void EmitNumberUntagD(Register input,
245                        DoubleRegister result,
246                        LEnvironment* env);
247
248  // Emits optimized code for typeof x == "y".  Modifies input register.
249  // Returns the condition on which a final split to
250  // true and false label should be made, to optimize fallthrough.
251  Condition EmitTypeofIs(Label* true_label, Label* false_label,
252                         Register input, Handle<String> type_name);
253
254  // Emits optimized code for %_IsObject(x).  Preserves input register.
255  // Returns the condition on which a final split to
256  // true and false label should be made, to optimize fallthrough.
257  Condition EmitIsObject(Register input,
258                         Register temp1,
259                         Register temp2,
260                         Label* is_not_object,
261                         Label* is_object);
262
263  // Emits optimized code for %_IsConstructCall().
264  // Caller should branch on equal condition.
265  void EmitIsConstructCall(Register temp1, Register temp2);
266
267  void EmitLoadField(Register result,
268                     Register object,
269                     Handle<Map> type,
270                     Handle<String> name);
271
272  LChunk* const chunk_;
273  MacroAssembler* const masm_;
274  CompilationInfo* const info_;
275
276  int current_block_;
277  int current_instruction_;
278  const ZoneList<LInstruction*>* instructions_;
279  ZoneList<LEnvironment*> deoptimizations_;
280  ZoneList<Handle<Object> > deoptimization_literals_;
281  int inlined_function_count_;
282  Scope* const scope_;
283  Status status_;
284  TranslationBuffer translations_;
285  ZoneList<LDeferredCode*> deferred_;
286  int osr_pc_offset_;
287
288  // Builder that keeps track of safepoints in the code. The table
289  // itself is emitted at the end of the generated code.
290  SafepointTableBuilder safepoints_;
291
292  // Compiler from a set of parallel moves to a sequential list of moves.
293  LGapResolver resolver_;
294
295  friend class LDeferredCode;
296  friend class LEnvironment;
297  friend class SafepointGenerator;
298  DISALLOW_COPY_AND_ASSIGN(LCodeGen);
299};
300
301
302class LDeferredCode: public ZoneObject {
303 public:
304  explicit LDeferredCode(LCodeGen* codegen)
305      : codegen_(codegen), external_exit_(NULL) {
306    codegen->AddDeferredCode(this);
307  }
308
309  virtual ~LDeferredCode() { }
310  virtual void Generate() = 0;
311
312  void SetExit(Label *exit) { external_exit_ = exit; }
313  Label* entry() { return &entry_; }
314  Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
315
316 protected:
317  LCodeGen* codegen() const { return codegen_; }
318  MacroAssembler* masm() const { return codegen_->masm(); }
319
320 private:
321  LCodeGen* codegen_;
322  Label entry_;
323  Label exit_;
324  Label* external_exit_;
325};
326
327} }  // namespace v8::internal
328
329#endif  // V8_ARM_LITHIUM_CODEGEN_ARM_H_
330