• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 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_X64_LITHIUM_CODEGEN_X64_H_
29 #define V8_X64_LITHIUM_CODEGEN_X64_H_
30 
31 #include "x64/lithium-x64.h"
32 
33 #include "checks.h"
34 #include "deoptimizer.h"
35 #include "safepoint-table.h"
36 #include "scopes.h"
37 #include "x64/lithium-gap-resolver-x64.h"
38 
39 namespace v8 {
40 namespace internal {
41 
42 // Forward declarations.
43 class LDeferredCode;
44 class SafepointGenerator;
45 
46 class LCodeGen BASE_EMBEDDED {
47  public:
LCodeGen(LChunk * chunk,MacroAssembler * assembler,CompilationInfo * info)48   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),
56         jump_table_(4),
57         deoptimization_literals_(8),
58         inlined_function_count_(0),
59         scope_(info->scope()),
60         status_(UNUSED),
61         deferred_(8),
62         osr_pc_offset_(-1),
63         resolver_(this),
64         expected_safepoint_kind_(Safepoint::kSimple) {
65     PopulateDeoptimizationLiteralsWithInlinedFunctions();
66   }
67 
68   // Simple accessors.
masm()69   MacroAssembler* masm() const { return masm_; }
info()70   CompilationInfo* info() const { return info_; }
isolate()71   Isolate* isolate() const { return info_->isolate(); }
factory()72   Factory* factory() const { return isolate()->factory(); }
heap()73   Heap* heap() const { return isolate()->heap(); }
74 
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 
84   // 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.
87   bool GenerateCode();
88 
89   // Finish the code by setting stack height, safepoint, and bailout
90   // information on it.
91   void FinishCode(Handle<Code> code);
92 
93   // Deferred code support.
94   void DoDeferredNumberTagD(LNumberTagD* instr);
95   void DoDeferredTaggedToI(LTaggedToI* instr);
96   void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
97   void DoDeferredStackCheck(LGoto* instr);
98   void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
99   void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
100   void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
101                                         Label* map_check);
102 
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 
is_unused()122   bool is_unused() const { return status_ == UNUSED; }
is_generating()123   bool is_generating() const { return status_ == GENERATING; }
is_done()124   bool is_done() const { return status_ == DONE; }
is_aborted()125   bool is_aborted() const { return status_ == ABORTED; }
126 
strict_mode_flag()127   int strict_mode_flag() const {
128     return info()->is_strict_mode() ? kStrictMode : kNonStrictMode;
129   }
130 
chunk()131   LChunk* chunk() const { return chunk_; }
scope()132   Scope* scope() const { return scope_; }
graph()133   HGraph* graph() const { return chunk_->graph(); }
134 
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,
142                        Register temporary);
143 
StackSlotCount()144   int StackSlotCount() const { return chunk()->spill_slot_count(); }
ParameterCount()145   int ParameterCount() const { return scope()->num_parameters(); }
146 
147   void Abort(const char* format, ...);
148   void Comment(const char* format, ...);
149 
AddDeferredCode(LDeferredCode * code)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();
157   bool GenerateJumpTable();
158   bool GenerateSafepointTable();
159 
160   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 
172   void CallCode(Handle<Code> code,
173                 RelocInfo::Mode mode,
174                 LInstruction* instr);
175 
176   void CallRuntime(const Runtime::Function* function,
177                    int num_arguments,
178                    LInstruction* instr);
179 
CallRuntime(Runtime::FunctionId id,int num_arguments,LInstruction * instr)180   void CallRuntime(Runtime::FunctionId id,
181                    int num_arguments,
182                    LInstruction* instr) {
183     const Runtime::Function* function = Runtime::FunctionForId(id);
184     CallRuntime(function, num_arguments, instr);
185   }
186 
187   void CallRuntimeFromDeferred(Runtime::FunctionId id,
188                                int argc,
189                                LInstruction* instr);
190 
191 
192   // 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 
200   void RegisterLazyDeoptimization(LInstruction* instr,
201                                   SafepointMode safepoint_mode,
202                                   int argc);
203   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;
216 
217   // Specific math operations - used from DoUnaryMathOperation.
218   void EmitIntegerMathAbs(LUnaryMathOperation* instr);
219   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.
229   void RecordSafepoint(LPointerMap* pointers,
230                        Safepoint::Kind kind,
231                        int arguments,
232                        int deoptimization_index);
233   void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
234   void RecordSafepoint(int deoptimization_index);
235   void RecordSafepointWithRegisters(LPointerMap* pointers,
236                                     int arguments,
237                                     int deoptimization_index);
238   void RecordPosition(int position);
LastSafepointEnd()239   int LastSafepointEnd() {
240     return static_cast<int>(safepoints_.GetPcAfterGap());
241   }
242 
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,
248                         XMMRegister result,
249                         bool deoptimize_on_undefined,
250                         LEnvironment* env);
251 
252   // Emits optimized code for typeof x == "y".  Modifies input register.
253   // Returns the condition on which a final split to
254   // true and false label should be made, to optimize fallthrough.
255   Condition EmitTypeofIs(Label* true_label, Label* false_label,
256                          Register input, Handle<String> type_name);
257 
258   // Emits optimized code for %_IsObject(x).  Preserves input register.
259   // Returns the condition on which a final split to
260   // true and false label should be made, to optimize fallthrough.
261   Condition EmitIsObject(Register input,
262                          Label* is_not_object,
263                          Label* is_object);
264 
265   // Emits optimized code for %_IsConstructCall().
266   // Caller should branch on equal condition.
267   void EmitIsConstructCall(Register temp);
268 
269   void EmitLoadField(Register result,
270                      Register object,
271                      Handle<Map> type,
272                      Handle<String> name);
273 
274   // Emits code for pushing a constant operand.
275   void EmitPushConstantOperand(LOperand* operand);
276 
277   struct JumpTableEntry {
JumpTableEntryJumpTableEntry278     explicit inline JumpTableEntry(Address entry)
279         : label(),
280           address(entry) { }
281     Label label;
282     Address address;
283   };
284 
285   LChunk* const chunk_;
286   MacroAssembler* const masm_;
287   CompilationInfo* const info_;
288 
289   int current_block_;
290   int current_instruction_;
291   const ZoneList<LInstruction*>* instructions_;
292   ZoneList<LEnvironment*> deoptimizations_;
293   ZoneList<JumpTableEntry> jump_table_;
294   ZoneList<Handle<Object> > deoptimization_literals_;
295   int inlined_function_count_;
296   Scope* const scope_;
297   Status status_;
298   TranslationBuffer translations_;
299   ZoneList<LDeferredCode*> deferred_;
300   int osr_pc_offset_;
301 
302   // Builder that keeps track of safepoints in the code. The table
303   // itself is emitted at the end of the generated code.
304   SafepointTableBuilder safepoints_;
305 
306   // Compiler from a set of parallel moves to a sequential list of moves.
307   LGapResolver resolver_;
308 
309   Safepoint::Kind expected_safepoint_kind_;
310 
311   class PushSafepointRegistersScope BASE_EMBEDDED {
312    public:
PushSafepointRegistersScope(LCodeGen * codegen)313     explicit PushSafepointRegistersScope(LCodeGen* codegen)
314         : codegen_(codegen) {
315       ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
316       codegen_->masm_->PushSafepointRegisters();
317       codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters;
318     }
319 
~PushSafepointRegistersScope()320     ~PushSafepointRegistersScope() {
321       ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters);
322       codegen_->masm_->PopSafepointRegisters();
323       codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
324     }
325 
326    private:
327     LCodeGen* codegen_;
328   };
329 
330   friend class LDeferredCode;
331   friend class LEnvironment;
332   friend class SafepointGenerator;
333   DISALLOW_COPY_AND_ASSIGN(LCodeGen);
334 };
335 
336 
337 class LDeferredCode: public ZoneObject {
338  public:
LDeferredCode(LCodeGen * codegen)339   explicit LDeferredCode(LCodeGen* codegen)
340       : codegen_(codegen), external_exit_(NULL) {
341     codegen->AddDeferredCode(this);
342   }
343 
~LDeferredCode()344   virtual ~LDeferredCode() { }
345   virtual void Generate() = 0;
346 
SetExit(Label * exit)347   void SetExit(Label *exit) { external_exit_ = exit; }
entry()348   Label* entry() { return &entry_; }
exit()349   Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
350 
351  protected:
codegen()352   LCodeGen* codegen() const { return codegen_; }
masm()353   MacroAssembler* masm() const { return codegen_->masm(); }
354 
355  private:
356   LCodeGen* codegen_;
357   Label entry_;
358   Label exit_;
359   Label* external_exit_;
360 };
361 
362 } }  // namespace v8::internal
363 
364 #endif  // V8_X64_LITHIUM_CODEGEN_X64_H_
365