blob: 541a699615633b00e6a58c6c4ffd905b6fefa42d [file] [log] [blame]
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001// 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
106 int GetNextEmittedBlock(int block);
107 LInstruction* GetNextInstruction();
108
109 void EmitClassOfTest(Label* if_true,
110 Label* if_false,
111 Handle<String> class_name,
112 Register input,
113 Register temporary,
114 Register temporary2);
115
116 int StackSlotCount() const { return chunk()->spill_slot_count(); }
117 int ParameterCount() const { return scope()->num_parameters(); }
118
119 void Abort(const char* format, ...);
120 void Comment(const char* format, ...);
121
122 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); }
123
124 // Code generation passes. Returns true if code generation should
125 // continue.
126 bool GeneratePrologue();
127 bool GenerateBody();
128 bool GenerateDeferredCode();
129 bool GenerateSafepointTable();
130
131 void CallCode(Handle<Code> code,
132 RelocInfo::Mode mode,
133 LInstruction* instr);
134 void CallRuntime(Runtime::Function* function,
135 int num_arguments,
136 LInstruction* instr);
137 void CallRuntime(Runtime::FunctionId id,
138 int num_arguments,
139 LInstruction* instr) {
140 Runtime::Function* function = Runtime::FunctionForId(id);
141 CallRuntime(function, num_arguments, instr);
142 }
143
144 // Generate a direct call to a known function. Expects the function
145 // to be in edi.
146 void CallKnownFunction(Handle<JSFunction> function,
147 int arity,
148 LInstruction* instr);
149
150 void LoadPrototype(Register result, Handle<JSObject> prototype);
151
152 void RegisterLazyDeoptimization(LInstruction* instr);
153 void RegisterEnvironmentForDeoptimization(LEnvironment* environment);
154 void DeoptimizeIf(Condition cc, LEnvironment* environment);
155
156 void AddToTranslation(Translation* translation,
157 LOperand* op,
158 bool is_tagged);
159 void PopulateDeoptimizationData(Handle<Code> code);
160 int DefineDeoptimizationLiteral(Handle<Object> literal);
161
162 void PopulateDeoptimizationLiteralsWithInlinedFunctions();
163
164 Register ToRegister(int index) const;
165 DoubleRegister ToDoubleRegister(int index) const;
166
167 // LOperand must be a register.
168 Register ToRegister(LOperand* op) const;
169
170 // LOperand is loaded into scratch, unless already a register.
171 Register EmitLoadRegister(LOperand* op, Register scratch);
172
173 // LOperand must be a double register.
174 DoubleRegister ToDoubleRegister(LOperand* op) const;
175
176 // LOperand is loaded into dbl_scratch, unless already a double register.
177 DoubleRegister EmitLoadDoubleRegister(LOperand* op,
178 SwVfpRegister flt_scratch,
179 DoubleRegister dbl_scratch);
180
181 int ToInteger32(LConstantOperand* op) const;
182 Operand ToOperand(LOperand* op);
183 MemOperand ToMemOperand(LOperand* op) const;
184
185 // Specific math operations - used from DoUnaryMathOperation.
186 void DoMathAbs(LUnaryMathOperation* instr);
187 void DoMathFloor(LUnaryMathOperation* instr);
188 void DoMathSqrt(LUnaryMathOperation* instr);
189
190 // Support for recording safepoint and position information.
191 void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
192 void RecordSafepointWithRegisters(LPointerMap* pointers,
193 int arguments,
194 int deoptimization_index);
195 void RecordPosition(int position);
196
197 static Condition TokenToCondition(Token::Value op, bool is_unsigned);
198 void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL);
199 void EmitBranch(int left_block, int right_block, Condition cc);
200 void EmitCmpI(LOperand* left, LOperand* right);
201 void EmitNumberUntagD(Register input,
202 DoubleRegister result,
203 LEnvironment* env);
204
205 // Emits optimized code for typeof x == "y". Modifies input register.
206 // Returns the condition on which a final split to
207 // true and false label should be made, to optimize fallthrough.
208 Condition EmitTypeofIs(Label* true_label, Label* false_label,
209 Register input, Handle<String> type_name);
210
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000211 // Emits optimized code for %_IsObject(x). Preserves input register.
212 // Returns the condition on which a final split to
213 // true and false label should be made, to optimize fallthrough.
214 Condition EmitIsObject(Register input,
215 Register temp1,
216 Register temp2,
217 Label* is_not_object,
218 Label* is_object);
219
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000220 LChunk* const chunk_;
221 MacroAssembler* const masm_;
222 CompilationInfo* const info_;
223
224 int current_block_;
225 int current_instruction_;
226 const ZoneList<LInstruction*>* instructions_;
227 ZoneList<LEnvironment*> deoptimizations_;
228 ZoneList<Handle<Object> > deoptimization_literals_;
229 int inlined_function_count_;
230 Scope* const scope_;
231 Status status_;
232 TranslationBuffer translations_;
233 ZoneList<LDeferredCode*> deferred_;
234 int osr_pc_offset_;
235
236 // Builder that keeps track of safepoints in the code. The table
237 // itself is emitted at the end of the generated code.
238 SafepointTableBuilder safepoints_;
239
240 friend class LDeferredCode;
241 friend class LEnvironment;
242 friend class SafepointGenerator;
243 DISALLOW_COPY_AND_ASSIGN(LCodeGen);
244};
245
246
247class LDeferredCode: public ZoneObject {
248 public:
249 explicit LDeferredCode(LCodeGen* codegen)
250 : codegen_(codegen), external_exit_(NULL) {
251 codegen->AddDeferredCode(this);
252 }
253
254 virtual ~LDeferredCode() { }
255 virtual void Generate() = 0;
256
257 void SetExit(Label *exit) { external_exit_ = exit; }
258 Label* entry() { return &entry_; }
259 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
260
261 protected:
262 LCodeGen* codegen() const { return codegen_; }
263 MacroAssembler* masm() const { return codegen_->masm(); }
264
265 private:
266 LCodeGen* codegen_;
267 Label entry_;
268 Label exit_;
269 Label* external_exit_;
270};
271
272} } // namespace v8::internal
273
274#endif // V8_ARM_LITHIUM_CODEGEN_ARM_H_