blob: 4ce70046259ef6d4b9e168041ff9f82870fd56ad [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_X64_LITHIUM_CODEGEN_X64_H_
29#define V8_X64_LITHIUM_CODEGEN_X64_H_
30
31#include "x64/lithium-x64.h"
32
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000033#include "checks.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000034#include "deoptimizer.h"
35#include "safepoint-table.h"
36#include "scopes.h"
37
38namespace v8 {
39namespace internal {
40
41// Forward declarations.
42class LDeferredCode;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000043class LGapNode;
44class SafepointGenerator;
45
46class LGapResolver BASE_EMBEDDED {
47 public:
48 LGapResolver();
49 const ZoneList<LMoveOperands>* Resolve(const ZoneList<LMoveOperands>* moves,
50 LOperand* marker_operand);
51
52 private:
53 LGapNode* LookupNode(LOperand* operand);
54 bool CanReach(LGapNode* a, LGapNode* b, int visited_id);
55 bool CanReach(LGapNode* a, LGapNode* b);
56 void RegisterMove(LMoveOperands move);
57 void AddResultMove(LOperand* from, LOperand* to);
58 void AddResultMove(LGapNode* from, LGapNode* to);
59 void ResolveCycle(LGapNode* start, LOperand* marker_operand);
60
61 ZoneList<LGapNode*> nodes_;
62 ZoneList<LGapNode*> identified_cycles_;
63 ZoneList<LMoveOperands> result_;
64 int next_visited_id_;
65};
66
kasperl@chromium.orga5551262010-12-07 12:49:48 +000067
68class LCodeGen BASE_EMBEDDED {
69 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000070 LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
71 : chunk_(chunk),
72 masm_(assembler),
73 info_(info),
74 current_block_(-1),
75 current_instruction_(-1),
76 instructions_(chunk->instructions()),
77 deoptimizations_(4),
78 deoptimization_literals_(8),
79 inlined_function_count_(0),
80 scope_(chunk->graph()->info()->scope()),
81 status_(UNUSED),
82 deferred_(8),
83 osr_pc_offset_(-1) {
84 PopulateDeoptimizationLiteralsWithInlinedFunctions();
85 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +000086
87 // Try to generate code for the entire chunk, but it may fail if the
88 // chunk contains constructs we cannot handle. Returns true if the
89 // code generation attempt succeeded.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000090 bool GenerateCode();
kasperl@chromium.orga5551262010-12-07 12:49:48 +000091
92 // Finish the code by setting stack height, safepoint, and bailout
93 // information on it.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000094 void FinishCode(Handle<Code> code);
95
96 // Deferred code support.
97 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 void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
103 Label* map_check);
104
105 // Parallel move support.
106 void DoParallelMove(LParallelMove* move);
107
108 // Emit frame translation commands for an environment.
109 void WriteTranslation(LEnvironment* environment, Translation* translation);
110
111 // Declare methods that deal with the individual node types.
112#define DECLARE_DO(type) void Do##type(L##type* node);
113 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
114#undef DECLARE_DO
115
116 private:
117 enum Status {
118 UNUSED,
119 GENERATING,
120 DONE,
121 ABORTED
122 };
123
124 bool is_unused() const { return status_ == UNUSED; }
125 bool is_generating() const { return status_ == GENERATING; }
126 bool is_done() const { return status_ == DONE; }
127 bool is_aborted() const { return status_ == ABORTED; }
128
129 LChunk* chunk() const { return chunk_; }
130 Scope* scope() const { return scope_; }
131 HGraph* graph() const { return chunk_->graph(); }
132 MacroAssembler* masm() const { return masm_; }
133
134 int GetNextEmittedBlock(int block);
135 LInstruction* GetNextInstruction();
136
137 void EmitClassOfTest(Label* if_true,
138 Label* if_false,
139 Handle<String> class_name,
140 Register input,
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000141 Register temporary);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000142
143 int StackSlotCount() const { return chunk()->spill_slot_count(); }
144 int ParameterCount() const { return scope()->num_parameters(); }
145
146 void Abort(const char* format, ...);
147 void Comment(const char* format, ...);
148
149 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); }
150
151 // Code generation passes. Returns true if code generation should
152 // continue.
153 bool GeneratePrologue();
154 bool GenerateBody();
155 bool GenerateDeferredCode();
156 bool GenerateSafepointTable();
157
158 void CallCode(Handle<Code> code,
159 RelocInfo::Mode mode,
160 LInstruction* instr);
161 void CallRuntime(Runtime::Function* function,
162 int num_arguments,
163 LInstruction* instr);
164 void CallRuntime(Runtime::FunctionId id,
165 int num_arguments,
166 LInstruction* instr) {
167 Runtime::Function* function = Runtime::FunctionForId(id);
168 CallRuntime(function, num_arguments, instr);
169 }
170
171 // Generate a direct call to a known function. Expects the function
172 // to be in edi.
173 void CallKnownFunction(Handle<JSFunction> function,
174 int arity,
175 LInstruction* instr);
176
177 void LoadHeapObject(Register result, Handle<HeapObject> object);
178
179 void RegisterLazyDeoptimization(LInstruction* instr);
180 void RegisterEnvironmentForDeoptimization(LEnvironment* environment);
181 void DeoptimizeIf(Condition cc, LEnvironment* environment);
182
183 void AddToTranslation(Translation* translation,
184 LOperand* op,
185 bool is_tagged);
186 void PopulateDeoptimizationData(Handle<Code> code);
187 int DefineDeoptimizationLiteral(Handle<Object> literal);
188
189 void PopulateDeoptimizationLiteralsWithInlinedFunctions();
190
191 Register ToRegister(int index) const;
192 XMMRegister ToDoubleRegister(int index) const;
193 Register ToRegister(LOperand* op) const;
194 XMMRegister ToDoubleRegister(LOperand* op) const;
195 bool IsInteger32Constant(LConstantOperand* op) const;
196 int ToInteger32(LConstantOperand* op) const;
197 bool IsTaggedConstant(LConstantOperand* op) const;
198 Handle<Object> ToHandle(LConstantOperand* op) const;
199 Operand ToOperand(LOperand* op) const;
200
201 // Specific math operations - used from DoUnaryMathOperation.
202 void DoMathAbs(LUnaryMathOperation* instr);
203 void DoMathFloor(LUnaryMathOperation* instr);
204 void DoMathRound(LUnaryMathOperation* instr);
205 void DoMathSqrt(LUnaryMathOperation* instr);
206 void DoMathPowHalf(LUnaryMathOperation* instr);
207 void DoMathLog(LUnaryMathOperation* instr);
208 void DoMathCos(LUnaryMathOperation* instr);
209 void DoMathSin(LUnaryMathOperation* instr);
210
211 // Support for recording safepoint and position information.
212 void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
213 void RecordSafepointWithRegisters(LPointerMap* pointers,
214 int arguments,
215 int deoptimization_index);
216 void RecordPosition(int position);
217
218 static Condition TokenToCondition(Token::Value op, bool is_unsigned);
219 void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL);
220 void EmitBranch(int left_block, int right_block, Condition cc);
221 void EmitCmpI(LOperand* left, LOperand* right);
222 void EmitNumberUntagD(Register input, XMMRegister result, LEnvironment* env);
223
224 // Emits optimized code for typeof x == "y". Modifies input register.
225 // Returns the condition on which a final split to
226 // true and false label should be made, to optimize fallthrough.
227 Condition EmitTypeofIs(Label* true_label, Label* false_label,
228 Register input, Handle<String> type_name);
229
230 // Emits optimized code for %_IsObject(x). Preserves input register.
231 // Returns the condition on which a final split to
232 // true and false label should be made, to optimize fallthrough.
233 Condition EmitIsObject(Register input,
234 Register temp1,
235 Register temp2,
236 Label* is_not_object,
237 Label* is_object);
238
239 LChunk* const chunk_;
240 MacroAssembler* const masm_;
241 CompilationInfo* const info_;
242
243 int current_block_;
244 int current_instruction_;
245 const ZoneList<LInstruction*>* instructions_;
246 ZoneList<LEnvironment*> deoptimizations_;
247 ZoneList<Handle<Object> > deoptimization_literals_;
248 int inlined_function_count_;
249 Scope* const scope_;
250 Status status_;
251 TranslationBuffer translations_;
252 ZoneList<LDeferredCode*> deferred_;
253 int osr_pc_offset_;
254
255 // Builder that keeps track of safepoints in the code. The table
256 // itself is emitted at the end of the generated code.
257 SafepointTableBuilder safepoints_;
258
259 // Compiler from a set of parallel moves to a sequential list of moves.
260 LGapResolver resolver_;
261
262 friend class LDeferredCode;
263 friend class LEnvironment;
264 friend class SafepointGenerator;
265 DISALLOW_COPY_AND_ASSIGN(LCodeGen);
266};
267
268
269class LDeferredCode: public ZoneObject {
270 public:
271 explicit LDeferredCode(LCodeGen* codegen)
272 : codegen_(codegen), external_exit_(NULL) {
273 codegen->AddDeferredCode(this);
274 }
275
276 virtual ~LDeferredCode() { }
277 virtual void Generate() = 0;
278
279 void SetExit(Label *exit) { external_exit_ = exit; }
280 Label* entry() { return &entry_; }
281 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
282
283 protected:
284 LCodeGen* codegen() const { return codegen_; }
285 MacroAssembler* masm() const { return codegen_->masm(); }
286
287 private:
288 LCodeGen* codegen_;
289 Label entry_;
290 Label exit_;
291 Label* external_exit_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000292};
293
294} } // namespace v8::internal
295
296#endif // V8_X64_LITHIUM_CODEGEN_X64_H_