blob: da341762a569afcbdebe04814bf2442fb07b7702 [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"
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000032#include "arm/lithium-gap-resolver-arm.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000033#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
kasperl@chromium.orga5551262010-12-07 12:49:48 +000044class 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),
karlklose@chromium.org8f806e82011-03-07 14:06:08 +000056 scope_(info->scope()),
kasperl@chromium.orga5551262010-12-07 12:49:48 +000057 status_(UNUSED),
58 deferred_(8),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000059 osr_pc_offset_(-1),
60 resolver_(this) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +000061 PopulateDeoptimizationLiteralsWithInlinedFunctions();
62 }
63
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000064
65 // Simple accessors.
66 MacroAssembler* masm() const { return masm_; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +000067 CompilationInfo* info() const { return info_; }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000068 Isolate* isolate() const { return info_->isolate(); }
69 Factory* factory() const { return isolate()->factory(); }
70 Heap* heap() const { return isolate()->heap(); }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000071
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
kasperl@chromium.orga5551262010-12-07 12:49:48 +000092 // 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.
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000102 template<int T>
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000103 void DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr,
104 Token::Value op);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000105 void DoDeferredNumberTagD(LNumberTagD* instr);
106 void DoDeferredNumberTagI(LNumberTagI* instr);
107 void DoDeferredTaggedToI(LTaggedToI* instr);
108 void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
109 void DoDeferredStackCheck(LGoto* instr);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000110 void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000111 void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000112 void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
113 Label* map_check);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000114
115 // Parallel move support.
116 void DoParallelMove(LParallelMove* move);
117
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000118 // Emit frame translation commands for an environment.
119 void WriteTranslation(LEnvironment* environment, Translation* translation);
120
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000121 // 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
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000139 int strict_mode_flag() const {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000140 return info()->is_strict() ? kStrictMode : kNonStrictMode;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000141 }
142
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000143 LChunk* chunk() const { return chunk_; }
144 Scope* scope() const { return scope_; }
145 HGraph* graph() const { return chunk_->graph(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000146
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000147 Register scratch0() { return r9; }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000148 DwVfpRegister double_scratch0() { return d0; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000149
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000150 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);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000178 void CallRuntime(const Runtime::Function* function,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000179 int num_arguments,
180 LInstruction* instr);
181 void CallRuntime(Runtime::FunctionId id,
182 int num_arguments,
183 LInstruction* instr) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000184 const Runtime::Function* function = Runtime::FunctionForId(id);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000185 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
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000194 void LoadHeapObject(Register result, Handle<HeapObject> object);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000195
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
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000211 // Specific math operations - used from DoUnaryMathOperation.
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000212 void EmitIntegerMathAbs(LUnaryMathOperation* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000213 void DoMathAbs(LUnaryMathOperation* instr);
214 void DoMathFloor(LUnaryMathOperation* instr);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000215 void DoMathRound(LUnaryMathOperation* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000216 void DoMathSqrt(LUnaryMathOperation* instr);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000217 void DoMathPowHalf(LUnaryMathOperation* instr);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000218 void DoMathLog(LUnaryMathOperation* instr);
219 void DoMathCos(LUnaryMathOperation* instr);
220 void DoMathSin(LUnaryMathOperation* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000221
222 // Support for recording safepoint and position information.
ager@chromium.org378b34e2011-01-28 08:04:38 +0000223 void RecordSafepoint(LPointerMap* pointers,
224 Safepoint::Kind kind,
225 int arguments,
226 int deoptimization_index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000227 void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000228 void RecordSafepoint(int deoptimization_index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000229 void RecordSafepointWithRegisters(LPointerMap* pointers,
230 int arguments,
231 int deoptimization_index);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000232 void RecordSafepointWithRegistersAndDoubles(LPointerMap* pointers,
233 int arguments,
234 int deoptimization_index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000235 void RecordPosition(int position);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000236 int LastSafepointEnd() {
237 return static_cast<int>(safepoints_.GetPcAfterGap());
238 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000239
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
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000254 // 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
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000263 // Emits optimized code for %_IsConstructCall().
264 // Caller should branch on equal condition.
265 void EmitIsConstructCall(Register temp1, Register temp2);
266
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000267 LChunk* const chunk_;
268 MacroAssembler* const masm_;
269 CompilationInfo* const info_;
270
271 int current_block_;
272 int current_instruction_;
273 const ZoneList<LInstruction*>* instructions_;
274 ZoneList<LEnvironment*> deoptimizations_;
275 ZoneList<Handle<Object> > deoptimization_literals_;
276 int inlined_function_count_;
277 Scope* const scope_;
278 Status status_;
279 TranslationBuffer translations_;
280 ZoneList<LDeferredCode*> deferred_;
281 int osr_pc_offset_;
282
283 // Builder that keeps track of safepoints in the code. The table
284 // itself is emitted at the end of the generated code.
285 SafepointTableBuilder safepoints_;
286
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000287 // Compiler from a set of parallel moves to a sequential list of moves.
288 LGapResolver resolver_;
289
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000290 friend class LDeferredCode;
291 friend class LEnvironment;
292 friend class SafepointGenerator;
293 DISALLOW_COPY_AND_ASSIGN(LCodeGen);
294};
295
296
297class LDeferredCode: public ZoneObject {
298 public:
299 explicit LDeferredCode(LCodeGen* codegen)
300 : codegen_(codegen), external_exit_(NULL) {
301 codegen->AddDeferredCode(this);
302 }
303
304 virtual ~LDeferredCode() { }
305 virtual void Generate() = 0;
306
307 void SetExit(Label *exit) { external_exit_ = exit; }
308 Label* entry() { return &entry_; }
309 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
310
311 protected:
312 LCodeGen* codegen() const { return codegen_; }
313 MacroAssembler* masm() const { return codegen_->masm(); }
314
315 private:
316 LCodeGen* codegen_;
317 Label entry_;
318 Label exit_;
319 Label* external_exit_;
320};
321
322} } // namespace v8::internal
323
324#endif // V8_ARM_LITHIUM_CODEGEN_ARM_H_