blob: 608efa9e0dff59864d57bf9b7c211e8e66c7e0ac [file] [log] [blame]
Ben Murdochb0fe1622011-05-05 13:52:32 +01001// Copyright 2010 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 SafepointGenerator;
43
44
45class LCodeGen BASE_EMBEDDED {
46 public:
47 LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
48 : chunk_(chunk),
49 masm_(assembler),
50 info_(info),
51 current_block_(-1),
52 current_instruction_(-1),
53 instructions_(chunk->instructions()),
54 deoptimizations_(4),
55 deoptimization_literals_(8),
56 inlined_function_count_(0),
57 scope_(chunk->graph()->info()->scope()),
58 status_(UNUSED),
59 deferred_(8),
60 osr_pc_offset_(-1) {
61 PopulateDeoptimizationLiteralsWithInlinedFunctions();
62 }
63
64 // Try to generate code for the entire chunk, but it may fail if the
65 // chunk contains constructs we cannot handle. Returns true if the
66 // code generation attempt succeeded.
67 bool GenerateCode();
68
69 // Finish the code by setting stack height, safepoint, and bailout
70 // information on it.
71 void FinishCode(Handle<Code> code);
72
73 // Deferred code support.
74 void DoDeferredNumberTagD(LNumberTagD* instr);
75 void DoDeferredNumberTagI(LNumberTagI* instr);
76 void DoDeferredTaggedToI(LTaggedToI* instr);
77 void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
78 void DoDeferredStackCheck(LGoto* instr);
79
80 // Parallel move support.
81 void DoParallelMove(LParallelMove* move);
82
83 // Declare methods that deal with the individual node types.
84#define DECLARE_DO(type) void Do##type(L##type* node);
85 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
86#undef DECLARE_DO
87
88 private:
89 enum Status {
90 UNUSED,
91 GENERATING,
92 DONE,
93 ABORTED
94 };
95
96 bool is_unused() const { return status_ == UNUSED; }
97 bool is_generating() const { return status_ == GENERATING; }
98 bool is_done() const { return status_ == DONE; }
99 bool is_aborted() const { return status_ == ABORTED; }
100
101 LChunk* chunk() const { return chunk_; }
102 Scope* scope() const { return scope_; }
103 HGraph* graph() const { return chunk_->graph(); }
104 MacroAssembler* masm() const { return masm_; }
105
Steve Block9fac8402011-05-12 15:51:54 +0100106 Register scratch0() { return r9; }
107
Ben Murdochb0fe1622011-05-05 13:52:32 +0100108 int GetNextEmittedBlock(int block);
109 LInstruction* GetNextInstruction();
110
111 void EmitClassOfTest(Label* if_true,
112 Label* if_false,
113 Handle<String> class_name,
114 Register input,
115 Register temporary,
116 Register temporary2);
117
118 int StackSlotCount() const { return chunk()->spill_slot_count(); }
119 int ParameterCount() const { return scope()->num_parameters(); }
120
121 void Abort(const char* format, ...);
122 void Comment(const char* format, ...);
123
124 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); }
125
126 // Code generation passes. Returns true if code generation should
127 // continue.
128 bool GeneratePrologue();
129 bool GenerateBody();
130 bool GenerateDeferredCode();
131 bool GenerateSafepointTable();
132
133 void CallCode(Handle<Code> code,
134 RelocInfo::Mode mode,
135 LInstruction* instr);
136 void CallRuntime(Runtime::Function* function,
137 int num_arguments,
138 LInstruction* instr);
139 void CallRuntime(Runtime::FunctionId id,
140 int num_arguments,
141 LInstruction* instr) {
142 Runtime::Function* function = Runtime::FunctionForId(id);
143 CallRuntime(function, num_arguments, instr);
144 }
145
146 // Generate a direct call to a known function. Expects the function
147 // to be in edi.
148 void CallKnownFunction(Handle<JSFunction> function,
149 int arity,
150 LInstruction* instr);
151
152 void LoadPrototype(Register result, Handle<JSObject> prototype);
153
154 void RegisterLazyDeoptimization(LInstruction* instr);
155 void RegisterEnvironmentForDeoptimization(LEnvironment* environment);
156 void DeoptimizeIf(Condition cc, LEnvironment* environment);
157
158 void AddToTranslation(Translation* translation,
159 LOperand* op,
160 bool is_tagged);
161 void PopulateDeoptimizationData(Handle<Code> code);
162 int DefineDeoptimizationLiteral(Handle<Object> literal);
163
164 void PopulateDeoptimizationLiteralsWithInlinedFunctions();
165
166 Register ToRegister(int index) const;
167 DoubleRegister ToDoubleRegister(int index) const;
168
169 // LOperand must be a register.
170 Register ToRegister(LOperand* op) const;
171
172 // LOperand is loaded into scratch, unless already a register.
173 Register EmitLoadRegister(LOperand* op, Register scratch);
174
175 // LOperand must be a double register.
176 DoubleRegister ToDoubleRegister(LOperand* op) const;
177
178 // LOperand is loaded into dbl_scratch, unless already a double register.
179 DoubleRegister EmitLoadDoubleRegister(LOperand* op,
180 SwVfpRegister flt_scratch,
181 DoubleRegister dbl_scratch);
182
183 int ToInteger32(LConstantOperand* op) const;
184 Operand ToOperand(LOperand* op);
185 MemOperand ToMemOperand(LOperand* op) const;
186
187 // Specific math operations - used from DoUnaryMathOperation.
188 void DoMathAbs(LUnaryMathOperation* instr);
189 void DoMathFloor(LUnaryMathOperation* instr);
190 void DoMathSqrt(LUnaryMathOperation* instr);
191
192 // Support for recording safepoint and position information.
193 void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
194 void RecordSafepointWithRegisters(LPointerMap* pointers,
195 int arguments,
196 int deoptimization_index);
197 void RecordPosition(int position);
198
199 static Condition TokenToCondition(Token::Value op, bool is_unsigned);
200 void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL);
201 void EmitBranch(int left_block, int right_block, Condition cc);
202 void EmitCmpI(LOperand* left, LOperand* right);
203 void EmitNumberUntagD(Register input,
204 DoubleRegister result,
205 LEnvironment* env);
206
207 // Emits optimized code for typeof x == "y". Modifies input register.
208 // Returns the condition on which a final split to
209 // true and false label should be made, to optimize fallthrough.
210 Condition EmitTypeofIs(Label* true_label, Label* false_label,
211 Register input, Handle<String> type_name);
212
213 // Emits optimized code for %_IsObject(x). Preserves input register.
214 // Returns the condition on which a final split to
215 // true and false label should be made, to optimize fallthrough.
216 Condition EmitIsObject(Register input,
217 Register temp1,
218 Register temp2,
219 Label* is_not_object,
220 Label* is_object);
221
222 LChunk* const chunk_;
223 MacroAssembler* const masm_;
224 CompilationInfo* const info_;
225
226 int current_block_;
227 int current_instruction_;
228 const ZoneList<LInstruction*>* instructions_;
229 ZoneList<LEnvironment*> deoptimizations_;
230 ZoneList<Handle<Object> > deoptimization_literals_;
231 int inlined_function_count_;
232 Scope* const scope_;
233 Status status_;
234 TranslationBuffer translations_;
235 ZoneList<LDeferredCode*> deferred_;
236 int osr_pc_offset_;
237
238 // Builder that keeps track of safepoints in the code. The table
239 // itself is emitted at the end of the generated code.
240 SafepointTableBuilder safepoints_;
241
242 friend class LDeferredCode;
243 friend class LEnvironment;
244 friend class SafepointGenerator;
245 DISALLOW_COPY_AND_ASSIGN(LCodeGen);
246};
247
248
249class LDeferredCode: public ZoneObject {
250 public:
251 explicit LDeferredCode(LCodeGen* codegen)
252 : codegen_(codegen), external_exit_(NULL) {
253 codegen->AddDeferredCode(this);
254 }
255
256 virtual ~LDeferredCode() { }
257 virtual void Generate() = 0;
258
259 void SetExit(Label *exit) { external_exit_ = exit; }
260 Label* entry() { return &entry_; }
261 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
262
263 protected:
264 LCodeGen* codegen() const { return codegen_; }
265 MacroAssembler* masm() const { return codegen_->masm(); }
266
267 private:
268 LCodeGen* codegen_;
269 Label entry_;
270 Label exit_;
271 Label* external_exit_;
272};
273
274} } // namespace v8::internal
275
276#endif // V8_ARM_LITHIUM_CODEGEN_ARM_H_