blob: 96e0a0f54c21e163d38d77d4d32385917d57f7ff [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"
ager@chromium.org0ee099b2011-01-25 14:06:47 +000037#include "x64/lithium-gap-resolver-x64.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000038
39namespace v8 {
40namespace internal {
41
42// Forward declarations.
43class LDeferredCode;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000044class SafepointGenerator;
45
kasperl@chromium.orga5551262010-12-07 12:49:48 +000046class LCodeGen BASE_EMBEDDED {
47 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000048 LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
49 : chunk_(chunk),
50 masm_(assembler),
51 info_(info),
52 current_block_(-1),
53 current_instruction_(-1),
54 instructions_(chunk->instructions()),
55 deoptimizations_(4),
ager@chromium.org9ee27ae2011-03-02 13:43:26 +000056 jump_table_(4),
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000057 deoptimization_literals_(8),
58 inlined_function_count_(0),
karlklose@chromium.org8f806e82011-03-07 14:06:08 +000059 scope_(info->scope()),
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000060 status_(UNUSED),
61 deferred_(8),
ager@chromium.org0ee099b2011-01-25 14:06:47 +000062 osr_pc_offset_(-1),
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000063 resolver_(this),
64 expected_safepoint_kind_(Safepoint::kSimple) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000065 PopulateDeoptimizationLiteralsWithInlinedFunctions();
66 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +000067
ager@chromium.org0ee099b2011-01-25 14:06:47 +000068 // Simple accessors.
69 MacroAssembler* masm() const { return masm_; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +000070 CompilationInfo* info() const { return info_; }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000071 Isolate* isolate() const { return info_->isolate(); }
72 Factory* factory() const { return isolate()->factory(); }
73 Heap* heap() const { return isolate()->heap(); }
ager@chromium.org0ee099b2011-01-25 14:06:47 +000074
75 // Support for converting LOperands to assembler types.
76 Register ToRegister(LOperand* op) const;
77 XMMRegister ToDoubleRegister(LOperand* op) const;
78 bool IsInteger32Constant(LConstantOperand* op) const;
79 int ToInteger32(LConstantOperand* op) const;
80 bool IsTaggedConstant(LConstantOperand* op) const;
81 Handle<Object> ToHandle(LConstantOperand* op) const;
82 Operand ToOperand(LOperand* op) const;
83
kasperl@chromium.orga5551262010-12-07 12:49:48 +000084 // Try to generate code for the entire chunk, but it may fail if the
85 // chunk contains constructs we cannot handle. Returns true if the
86 // code generation attempt succeeded.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000087 bool GenerateCode();
kasperl@chromium.orga5551262010-12-07 12:49:48 +000088
89 // Finish the code by setting stack height, safepoint, and bailout
90 // information on it.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000091 void FinishCode(Handle<Code> code);
92
93 // Deferred code support.
94 void DoDeferredNumberTagD(LNumberTagD* instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000095 void DoDeferredTaggedToI(LTaggedToI* instr);
96 void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
97 void DoDeferredStackCheck(LGoto* instr);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000098 void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000099 void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000100 void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
101 Label* map_check);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000102
103 // Parallel move support.
104 void DoParallelMove(LParallelMove* move);
105
106 // Emit frame translation commands for an environment.
107 void WriteTranslation(LEnvironment* environment, Translation* translation);
108
109 // Declare methods that deal with the individual node types.
110#define DECLARE_DO(type) void Do##type(L##type* node);
111 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
112#undef DECLARE_DO
113
114 private:
115 enum Status {
116 UNUSED,
117 GENERATING,
118 DONE,
119 ABORTED
120 };
121
122 bool is_unused() const { return status_ == UNUSED; }
123 bool is_generating() const { return status_ == GENERATING; }
124 bool is_done() const { return status_ == DONE; }
125 bool is_aborted() const { return status_ == ABORTED; }
126
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000127 int strict_mode_flag() const {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000128 return info()->is_strict_mode() ? kStrictMode : kNonStrictMode;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000129 }
130
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000131 LChunk* chunk() const { return chunk_; }
132 Scope* scope() const { return scope_; }
133 HGraph* graph() const { return chunk_->graph(); }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000134
135 int GetNextEmittedBlock(int block);
136 LInstruction* GetNextInstruction();
137
138 void EmitClassOfTest(Label* if_true,
139 Label* if_false,
140 Handle<String> class_name,
141 Register input,
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000142 Register temporary);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000143
danno@chromium.org160a7b02011-04-18 15:51:38 +0000144 int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
145 int GetParameterCount() const { return scope()->num_parameters(); }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000146
147 void Abort(const char* format, ...);
148 void Comment(const char* format, ...);
149
150 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); }
151
152 // Code generation passes. Returns true if code generation should
153 // continue.
154 bool GeneratePrologue();
155 bool GenerateBody();
156 bool GenerateDeferredCode();
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000157 bool GenerateJumpTable();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000158 bool GenerateSafepointTable();
159
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000160 enum SafepointMode {
161 RECORD_SIMPLE_SAFEPOINT,
162 RECORD_SAFEPOINT_WITH_REGISTERS
163 };
164
165 void CallCodeGeneric(Handle<Code> code,
166 RelocInfo::Mode mode,
167 LInstruction* instr,
168 SafepointMode safepoint_mode,
169 int argc);
170
171
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000172 void CallCode(Handle<Code> code,
173 RelocInfo::Mode mode,
174 LInstruction* instr);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000175
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000176 void CallRuntime(const Runtime::Function* function,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000177 int num_arguments,
178 LInstruction* instr);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000179
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000180 void CallRuntime(Runtime::FunctionId id,
181 int num_arguments,
182 LInstruction* instr) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000183 const Runtime::Function* function = Runtime::FunctionForId(id);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000184 CallRuntime(function, num_arguments, instr);
185 }
186
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000187 void CallRuntimeFromDeferred(Runtime::FunctionId id,
188 int argc,
189 LInstruction* instr);
190
191
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000192 // Generate a direct call to a known function. Expects the function
193 // to be in edi.
194 void CallKnownFunction(Handle<JSFunction> function,
195 int arity,
196 LInstruction* instr);
197
198 void LoadHeapObject(Register result, Handle<HeapObject> object);
199
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000200 void RegisterLazyDeoptimization(LInstruction* instr,
201 SafepointMode safepoint_mode,
202 int argc);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000203 void RegisterEnvironmentForDeoptimization(LEnvironment* environment);
204 void DeoptimizeIf(Condition cc, LEnvironment* environment);
205
206 void AddToTranslation(Translation* translation,
207 LOperand* op,
208 bool is_tagged);
209 void PopulateDeoptimizationData(Handle<Code> code);
210 int DefineDeoptimizationLiteral(Handle<Object> literal);
211
212 void PopulateDeoptimizationLiteralsWithInlinedFunctions();
213
214 Register ToRegister(int index) const;
215 XMMRegister ToDoubleRegister(int index) const;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000216
217 // Specific math operations - used from DoUnaryMathOperation.
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +0000218 void EmitIntegerMathAbs(LUnaryMathOperation* instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000219 void DoMathAbs(LUnaryMathOperation* instr);
220 void DoMathFloor(LUnaryMathOperation* instr);
221 void DoMathRound(LUnaryMathOperation* instr);
222 void DoMathSqrt(LUnaryMathOperation* instr);
223 void DoMathPowHalf(LUnaryMathOperation* instr);
224 void DoMathLog(LUnaryMathOperation* instr);
225 void DoMathCos(LUnaryMathOperation* instr);
226 void DoMathSin(LUnaryMathOperation* instr);
227
228 // Support for recording safepoint and position information.
ager@chromium.org378b34e2011-01-28 08:04:38 +0000229 void RecordSafepoint(LPointerMap* pointers,
230 Safepoint::Kind kind,
231 int arguments,
232 int deoptimization_index);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000233 void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000234 void RecordSafepoint(int deoptimization_index);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000235 void RecordSafepointWithRegisters(LPointerMap* pointers,
236 int arguments,
237 int deoptimization_index);
238 void RecordPosition(int position);
ricow@chromium.orgeb96f4f2011-03-09 13:41:48 +0000239 int LastSafepointEnd() {
240 return static_cast<int>(safepoints_.GetPcAfterGap());
241 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000242
243 static Condition TokenToCondition(Token::Value op, bool is_unsigned);
244 void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL);
245 void EmitBranch(int left_block, int right_block, Condition cc);
246 void EmitCmpI(LOperand* left, LOperand* right);
247 void EmitNumberUntagD(Register input, XMMRegister result, LEnvironment* env);
248
249 // Emits optimized code for typeof x == "y". Modifies input register.
250 // Returns the condition on which a final split to
251 // true and false label should be made, to optimize fallthrough.
252 Condition EmitTypeofIs(Label* true_label, Label* false_label,
253 Register input, Handle<String> type_name);
254
255 // Emits optimized code for %_IsObject(x). Preserves input register.
256 // Returns the condition on which a final split to
257 // true and false label should be made, to optimize fallthrough.
258 Condition EmitIsObject(Register input,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000259 Label* is_not_object,
260 Label* is_object);
261
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000262 // Emits optimized code for %_IsConstructCall().
263 // Caller should branch on equal condition.
264 void EmitIsConstructCall(Register temp);
265
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000266 void EmitLoadField(Register result,
267 Register object,
268 Handle<Map> type,
269 Handle<String> name);
270
danno@chromium.org160a7b02011-04-18 15:51:38 +0000271 // Emits code for pushing either a tagged constant, a (non-double)
272 // register, or a stack slot operand.
273 void EmitPushTaggedOperand(LOperand* operand);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000274
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000275 struct JumpTableEntry {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000276 explicit inline JumpTableEntry(Address entry)
ricow@chromium.orgeb96f4f2011-03-09 13:41:48 +0000277 : label(),
278 address(entry) { }
279 Label label;
280 Address address;
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000281 };
282
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000283 LChunk* const chunk_;
284 MacroAssembler* const masm_;
285 CompilationInfo* const info_;
286
287 int current_block_;
288 int current_instruction_;
289 const ZoneList<LInstruction*>* instructions_;
290 ZoneList<LEnvironment*> deoptimizations_;
ricow@chromium.orgeb96f4f2011-03-09 13:41:48 +0000291 ZoneList<JumpTableEntry> jump_table_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000292 ZoneList<Handle<Object> > deoptimization_literals_;
293 int inlined_function_count_;
294 Scope* const scope_;
295 Status status_;
296 TranslationBuffer translations_;
297 ZoneList<LDeferredCode*> deferred_;
298 int osr_pc_offset_;
299
300 // Builder that keeps track of safepoints in the code. The table
301 // itself is emitted at the end of the generated code.
302 SafepointTableBuilder safepoints_;
303
304 // Compiler from a set of parallel moves to a sequential list of moves.
305 LGapResolver resolver_;
306
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000307 Safepoint::Kind expected_safepoint_kind_;
308
309 class PushSafepointRegistersScope BASE_EMBEDDED {
310 public:
311 explicit PushSafepointRegistersScope(LCodeGen* codegen)
312 : codegen_(codegen) {
313 ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
314 codegen_->masm_->PushSafepointRegisters();
315 codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters;
316 }
317
318 ~PushSafepointRegistersScope() {
319 ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters);
320 codegen_->masm_->PopSafepointRegisters();
321 codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
322 }
323
324 private:
325 LCodeGen* codegen_;
326 };
327
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000328 friend class LDeferredCode;
329 friend class LEnvironment;
330 friend class SafepointGenerator;
331 DISALLOW_COPY_AND_ASSIGN(LCodeGen);
332};
333
334
335class LDeferredCode: public ZoneObject {
336 public:
337 explicit LDeferredCode(LCodeGen* codegen)
338 : codegen_(codegen), external_exit_(NULL) {
339 codegen->AddDeferredCode(this);
340 }
341
342 virtual ~LDeferredCode() { }
343 virtual void Generate() = 0;
344
345 void SetExit(Label *exit) { external_exit_ = exit; }
346 Label* entry() { return &entry_; }
347 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
348
349 protected:
350 LCodeGen* codegen() const { return codegen_; }
351 MacroAssembler* masm() const { return codegen_->masm(); }
352
353 private:
354 LCodeGen* codegen_;
355 Label entry_;
356 Label exit_;
357 Label* external_exit_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000358};
359
360} } // namespace v8::internal
361
362#endif // V8_X64_LITHIUM_CODEGEN_X64_H_