blob: e2b572ecb9817cf740ec02f125910482543ef19b [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_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000068
69 // Support for converting LOperands to assembler types.
70 // LOperand must be a register.
71 Register ToRegister(LOperand* op) const;
72
73 // LOperand is loaded into scratch, unless already a register.
74 Register EmitLoadRegister(LOperand* op, Register scratch);
75
76 // LOperand must be a double register.
77 DoubleRegister ToDoubleRegister(LOperand* op) const;
78
79 // LOperand is loaded into dbl_scratch, unless already a double register.
80 DoubleRegister EmitLoadDoubleRegister(LOperand* op,
81 SwVfpRegister flt_scratch,
82 DoubleRegister dbl_scratch);
83 int ToInteger32(LConstantOperand* op) const;
84 Operand ToOperand(LOperand* op);
85 MemOperand ToMemOperand(LOperand* op) const;
86 // Returns a MemOperand pointing to the high word of a DoubleStackSlot.
87 MemOperand ToHighMemOperand(LOperand* op) const;
88
kasperl@chromium.orga5551262010-12-07 12:49:48 +000089 // Try to generate code for the entire chunk, but it may fail if the
90 // chunk contains constructs we cannot handle. Returns true if the
91 // code generation attempt succeeded.
92 bool GenerateCode();
93
94 // Finish the code by setting stack height, safepoint, and bailout
95 // information on it.
96 void FinishCode(Handle<Code> code);
97
98 // Deferred code support.
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000099 template<int T>
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000100 void DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr,
101 Token::Value op);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000102 void DoDeferredNumberTagD(LNumberTagD* instr);
103 void DoDeferredNumberTagI(LNumberTagI* instr);
104 void DoDeferredTaggedToI(LTaggedToI* instr);
105 void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
106 void DoDeferredStackCheck(LGoto* instr);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000107 void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000108 void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000109 void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
110 Label* map_check);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000111
112 // Parallel move support.
113 void DoParallelMove(LParallelMove* move);
114
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000115 // Emit frame translation commands for an environment.
116 void WriteTranslation(LEnvironment* environment, Translation* translation);
117
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000118 // Declare methods that deal with the individual node types.
119#define DECLARE_DO(type) void Do##type(L##type* node);
120 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
121#undef DECLARE_DO
122
123 private:
124 enum Status {
125 UNUSED,
126 GENERATING,
127 DONE,
128 ABORTED
129 };
130
131 bool is_unused() const { return status_ == UNUSED; }
132 bool is_generating() const { return status_ == GENERATING; }
133 bool is_done() const { return status_ == DONE; }
134 bool is_aborted() const { return status_ == ABORTED; }
135
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000136 int strict_mode_flag() const {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000137 return info()->is_strict() ? kStrictMode : kNonStrictMode;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000138 }
139
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000140 LChunk* chunk() const { return chunk_; }
141 Scope* scope() const { return scope_; }
142 HGraph* graph() const { return chunk_->graph(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000143
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000144 Register scratch0() { return r9; }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000145 DwVfpRegister double_scratch0() { return d0; }
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000146
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000147 int GetNextEmittedBlock(int block);
148 LInstruction* GetNextInstruction();
149
150 void EmitClassOfTest(Label* if_true,
151 Label* if_false,
152 Handle<String> class_name,
153 Register input,
154 Register temporary,
155 Register temporary2);
156
157 int StackSlotCount() const { return chunk()->spill_slot_count(); }
158 int ParameterCount() const { return scope()->num_parameters(); }
159
160 void Abort(const char* format, ...);
161 void Comment(const char* format, ...);
162
163 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); }
164
165 // Code generation passes. Returns true if code generation should
166 // continue.
167 bool GeneratePrologue();
168 bool GenerateBody();
169 bool GenerateDeferredCode();
170 bool GenerateSafepointTable();
171
172 void CallCode(Handle<Code> code,
173 RelocInfo::Mode mode,
174 LInstruction* instr);
175 void CallRuntime(Runtime::Function* function,
176 int num_arguments,
177 LInstruction* instr);
178 void CallRuntime(Runtime::FunctionId id,
179 int num_arguments,
180 LInstruction* instr) {
181 Runtime::Function* function = Runtime::FunctionForId(id);
182 CallRuntime(function, num_arguments, instr);
183 }
184
185 // Generate a direct call to a known function. Expects the function
186 // to be in edi.
187 void CallKnownFunction(Handle<JSFunction> function,
188 int arity,
189 LInstruction* instr);
190
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000191 void LoadHeapObject(Register result, Handle<HeapObject> object);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000192
193 void RegisterLazyDeoptimization(LInstruction* instr);
194 void RegisterEnvironmentForDeoptimization(LEnvironment* environment);
195 void DeoptimizeIf(Condition cc, LEnvironment* environment);
196
197 void AddToTranslation(Translation* translation,
198 LOperand* op,
199 bool is_tagged);
200 void PopulateDeoptimizationData(Handle<Code> code);
201 int DefineDeoptimizationLiteral(Handle<Object> literal);
202
203 void PopulateDeoptimizationLiteralsWithInlinedFunctions();
204
205 Register ToRegister(int index) const;
206 DoubleRegister ToDoubleRegister(int index) const;
207
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000208 // Specific math operations - used from DoUnaryMathOperation.
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000209 void EmitIntegerMathAbs(LUnaryMathOperation* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000210 void DoMathAbs(LUnaryMathOperation* instr);
211 void DoMathFloor(LUnaryMathOperation* instr);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000212 void DoMathRound(LUnaryMathOperation* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000213 void DoMathSqrt(LUnaryMathOperation* instr);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000214 void DoMathPowHalf(LUnaryMathOperation* instr);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000215 void DoMathLog(LUnaryMathOperation* instr);
216 void DoMathCos(LUnaryMathOperation* instr);
217 void DoMathSin(LUnaryMathOperation* instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000218
219 // Support for recording safepoint and position information.
ager@chromium.org378b34e2011-01-28 08:04:38 +0000220 void RecordSafepoint(LPointerMap* pointers,
221 Safepoint::Kind kind,
222 int arguments,
223 int deoptimization_index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000224 void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000225 void RecordSafepoint(int deoptimization_index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000226 void RecordSafepointWithRegisters(LPointerMap* pointers,
227 int arguments,
228 int deoptimization_index);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000229 void RecordSafepointWithRegistersAndDoubles(LPointerMap* pointers,
230 int arguments,
231 int deoptimization_index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000232 void RecordPosition(int position);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000233 int LastSafepointEnd() {
234 return static_cast<int>(safepoints_.GetPcAfterGap());
235 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000236
237 static Condition TokenToCondition(Token::Value op, bool is_unsigned);
238 void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL);
239 void EmitBranch(int left_block, int right_block, Condition cc);
240 void EmitCmpI(LOperand* left, LOperand* right);
241 void EmitNumberUntagD(Register input,
242 DoubleRegister result,
243 LEnvironment* env);
244
245 // Emits optimized code for typeof x == "y". Modifies input register.
246 // Returns the condition on which a final split to
247 // true and false label should be made, to optimize fallthrough.
248 Condition EmitTypeofIs(Label* true_label, Label* false_label,
249 Register input, Handle<String> type_name);
250
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000251 // Emits optimized code for %_IsObject(x). Preserves input register.
252 // Returns the condition on which a final split to
253 // true and false label should be made, to optimize fallthrough.
254 Condition EmitIsObject(Register input,
255 Register temp1,
256 Register temp2,
257 Label* is_not_object,
258 Label* is_object);
259
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000260 // Emits optimized code for %_IsConstructCall().
261 // Caller should branch on equal condition.
262 void EmitIsConstructCall(Register temp1, Register temp2);
263
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000264 LChunk* const chunk_;
265 MacroAssembler* const masm_;
266 CompilationInfo* const info_;
267
268 int current_block_;
269 int current_instruction_;
270 const ZoneList<LInstruction*>* instructions_;
271 ZoneList<LEnvironment*> deoptimizations_;
272 ZoneList<Handle<Object> > deoptimization_literals_;
273 int inlined_function_count_;
274 Scope* const scope_;
275 Status status_;
276 TranslationBuffer translations_;
277 ZoneList<LDeferredCode*> deferred_;
278 int osr_pc_offset_;
279
280 // Builder that keeps track of safepoints in the code. The table
281 // itself is emitted at the end of the generated code.
282 SafepointTableBuilder safepoints_;
283
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000284 // Compiler from a set of parallel moves to a sequential list of moves.
285 LGapResolver resolver_;
286
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000287 friend class LDeferredCode;
288 friend class LEnvironment;
289 friend class SafepointGenerator;
290 DISALLOW_COPY_AND_ASSIGN(LCodeGen);
291};
292
293
294class LDeferredCode: public ZoneObject {
295 public:
296 explicit LDeferredCode(LCodeGen* codegen)
297 : codegen_(codegen), external_exit_(NULL) {
298 codegen->AddDeferredCode(this);
299 }
300
301 virtual ~LDeferredCode() { }
302 virtual void Generate() = 0;
303
304 void SetExit(Label *exit) { external_exit_ = exit; }
305 Label* entry() { return &entry_; }
306 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
307
308 protected:
309 LCodeGen* codegen() const { return codegen_; }
310 MacroAssembler* masm() const { return codegen_->masm(); }
311
312 private:
313 LCodeGen* codegen_;
314 Label entry_;
315 Label exit_;
316 Label* external_exit_;
317};
318
319} } // namespace v8::internal
320
321#endif // V8_ARM_LITHIUM_CODEGEN_ARM_H_