blob: 9eed64b455b27080116eb362909182359b088bb7 [file] [log] [blame]
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001// Copyright 2011 the V8 project authors. All rights reserved.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002// 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;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000042class LGapNode;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000043class SafepointGenerator;
44
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000045class 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
kasperl@chromium.orga5551262010-12-07 12:49:48 +000066
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.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000096 void DoDeferredGenericBinaryStub(LBinaryOperation* instr, Token::Value op);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000097 void DoDeferredNumberTagD(LNumberTagD* instr);
98 void DoDeferredNumberTagI(LNumberTagI* instr);
99 void DoDeferredTaggedToI(LTaggedToI* instr);
100 void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
101 void DoDeferredStackCheck(LGoto* instr);
102
103 // Parallel move support.
104 void DoParallelMove(LParallelMove* move);
105
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000106 // Emit frame translation commands for an environment.
107 void WriteTranslation(LEnvironment* environment, Translation* translation);
108
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000109 // Declare methods that deal with the individual node types.
110#define DECLARE_DO(type) void Do##type(L##type* node);
111 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
112#undef DECLARE_DO
113
114 private:
115 enum Status {
116 UNUSED,
117 GENERATING,
118 DONE,
119 ABORTED
120 };
121
122 bool is_unused() const { return status_ == UNUSED; }
123 bool is_generating() const { return status_ == GENERATING; }
124 bool is_done() const { return status_ == DONE; }
125 bool is_aborted() const { return status_ == ABORTED; }
126
127 LChunk* chunk() const { return chunk_; }
128 Scope* scope() const { return scope_; }
129 HGraph* graph() const { return chunk_->graph(); }
130 MacroAssembler* masm() const { return masm_; }
131
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000132 Register scratch0() { return r9; }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000133 DwVfpRegister double_scratch0() { return d0; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000134
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000135 int GetNextEmittedBlock(int block);
136 LInstruction* GetNextInstruction();
137
138 void EmitClassOfTest(Label* if_true,
139 Label* if_false,
140 Handle<String> class_name,
141 Register input,
142 Register temporary,
143 Register temporary2);
144
145 int StackSlotCount() const { return chunk()->spill_slot_count(); }
146 int ParameterCount() const { return scope()->num_parameters(); }
147
148 void Abort(const char* format, ...);
149 void Comment(const char* format, ...);
150
151 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); }
152
153 // Code generation passes. Returns true if code generation should
154 // continue.
155 bool GeneratePrologue();
156 bool GenerateBody();
157 bool GenerateDeferredCode();
158 bool GenerateSafepointTable();
159
160 void CallCode(Handle<Code> code,
161 RelocInfo::Mode mode,
162 LInstruction* instr);
163 void CallRuntime(Runtime::Function* function,
164 int num_arguments,
165 LInstruction* instr);
166 void CallRuntime(Runtime::FunctionId id,
167 int num_arguments,
168 LInstruction* instr) {
169 Runtime::Function* function = Runtime::FunctionForId(id);
170 CallRuntime(function, num_arguments, instr);
171 }
172
173 // Generate a direct call to a known function. Expects the function
174 // to be in edi.
175 void CallKnownFunction(Handle<JSFunction> function,
176 int arity,
177 LInstruction* instr);
178
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000179 void LoadHeapObject(Register result, Handle<HeapObject> object);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000180
181 void RegisterLazyDeoptimization(LInstruction* instr);
182 void RegisterEnvironmentForDeoptimization(LEnvironment* environment);
183 void DeoptimizeIf(Condition cc, LEnvironment* environment);
184
185 void AddToTranslation(Translation* translation,
186 LOperand* op,
187 bool is_tagged);
188 void PopulateDeoptimizationData(Handle<Code> code);
189 int DefineDeoptimizationLiteral(Handle<Object> literal);
190
191 void PopulateDeoptimizationLiteralsWithInlinedFunctions();
192
193 Register ToRegister(int index) const;
194 DoubleRegister ToDoubleRegister(int index) const;
195
196 // LOperand must be a register.
197 Register ToRegister(LOperand* op) const;
198
199 // LOperand is loaded into scratch, unless already a register.
200 Register EmitLoadRegister(LOperand* op, Register scratch);
201
202 // LOperand must be a double register.
203 DoubleRegister ToDoubleRegister(LOperand* op) const;
204
205 // LOperand is loaded into dbl_scratch, unless already a double register.
206 DoubleRegister EmitLoadDoubleRegister(LOperand* op,
207 SwVfpRegister flt_scratch,
208 DoubleRegister dbl_scratch);
209
210 int ToInteger32(LConstantOperand* op) const;
211 Operand ToOperand(LOperand* op);
212 MemOperand ToMemOperand(LOperand* op) const;
213
214 // Specific math operations - used from DoUnaryMathOperation.
215 void DoMathAbs(LUnaryMathOperation* instr);
216 void DoMathFloor(LUnaryMathOperation* instr);
217 void DoMathSqrt(LUnaryMathOperation* instr);
218
219 // Support for recording safepoint and position information.
220 void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
221 void RecordSafepointWithRegisters(LPointerMap* pointers,
222 int arguments,
223 int deoptimization_index);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000224 void RecordSafepointWithRegistersAndDoubles(LPointerMap* pointers,
225 int arguments,
226 int deoptimization_index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000227 void RecordPosition(int position);
228
229 static Condition TokenToCondition(Token::Value op, bool is_unsigned);
230 void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL);
231 void EmitBranch(int left_block, int right_block, Condition cc);
232 void EmitCmpI(LOperand* left, LOperand* right);
233 void EmitNumberUntagD(Register input,
234 DoubleRegister result,
235 LEnvironment* env);
236
237 // Emits optimized code for typeof x == "y". Modifies input register.
238 // Returns the condition on which a final split to
239 // true and false label should be made, to optimize fallthrough.
240 Condition EmitTypeofIs(Label* true_label, Label* false_label,
241 Register input, Handle<String> type_name);
242
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000243 // Emits optimized code for %_IsObject(x). Preserves input register.
244 // Returns the condition on which a final split to
245 // true and false label should be made, to optimize fallthrough.
246 Condition EmitIsObject(Register input,
247 Register temp1,
248 Register temp2,
249 Label* is_not_object,
250 Label* is_object);
251
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000252 LChunk* const chunk_;
253 MacroAssembler* const masm_;
254 CompilationInfo* const info_;
255
256 int current_block_;
257 int current_instruction_;
258 const ZoneList<LInstruction*>* instructions_;
259 ZoneList<LEnvironment*> deoptimizations_;
260 ZoneList<Handle<Object> > deoptimization_literals_;
261 int inlined_function_count_;
262 Scope* const scope_;
263 Status status_;
264 TranslationBuffer translations_;
265 ZoneList<LDeferredCode*> deferred_;
266 int osr_pc_offset_;
267
268 // Builder that keeps track of safepoints in the code. The table
269 // itself is emitted at the end of the generated code.
270 SafepointTableBuilder safepoints_;
271
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000272 // Compiler from a set of parallel moves to a sequential list of moves.
273 LGapResolver resolver_;
274
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000275 friend class LDeferredCode;
276 friend class LEnvironment;
277 friend class SafepointGenerator;
278 DISALLOW_COPY_AND_ASSIGN(LCodeGen);
279};
280
281
282class LDeferredCode: public ZoneObject {
283 public:
284 explicit LDeferredCode(LCodeGen* codegen)
285 : codegen_(codegen), external_exit_(NULL) {
286 codegen->AddDeferredCode(this);
287 }
288
289 virtual ~LDeferredCode() { }
290 virtual void Generate() = 0;
291
292 void SetExit(Label *exit) { external_exit_ = exit; }
293 Label* entry() { return &entry_; }
294 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
295
296 protected:
297 LCodeGen* codegen() const { return codegen_; }
298 MacroAssembler* masm() const { return codegen_->masm(); }
299
300 private:
301 LCodeGen* codegen_;
302 Label entry_;
303 Label exit_;
304 Label* external_exit_;
305};
306
307} } // namespace v8::internal
308
309#endif // V8_ARM_LITHIUM_CODEGEN_ARM_H_