• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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         last_lazy_deopt_pc_(0),
64         resolver_(this),
65         expected_safepoint_kind_(Safepoint::kSimple) {
66     PopulateDeoptimizationLiteralsWithInlinedFunctions();
67   }
68 
69   // Simple accessors.
masm()70   MacroAssembler* masm() const { return masm_; }
info()71   CompilationInfo* info() const { return info_; }
isolate()72   Isolate* isolate() const { return info_->isolate(); }
factory()73   Factory* factory() const { return isolate()->factory(); }
heap()74   Heap* heap() const { return isolate()->heap(); }
75 
76   // Support for converting LOperands to assembler types.
77   Register ToRegister(LOperand* op) const;
78   XMMRegister ToDoubleRegister(LOperand* op) const;
79   bool IsInteger32Constant(LConstantOperand* op) const;
80   int ToInteger32(LConstantOperand* op) const;
81   double ToDouble(LConstantOperand* op) const;
82   bool IsTaggedConstant(LConstantOperand* op) const;
83   Handle<Object> ToHandle(LConstantOperand* op) const;
84   Operand ToOperand(LOperand* op) const;
85 
86   // Try to generate code for the entire chunk, but it may fail if the
87   // chunk contains constructs we cannot handle. Returns true if the
88   // code generation attempt succeeded.
89   bool GenerateCode();
90 
91   // Finish the code by setting stack height, safepoint, and bailout
92   // information on it.
93   void FinishCode(Handle<Code> code);
94 
95   // Deferred code support.
96   void DoDeferredNumberTagD(LNumberTagD* instr);
97   void DoDeferredTaggedToI(LTaggedToI* instr);
98   void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
99   void DoDeferredStackCheck(LStackCheck* instr);
100   void DoDeferredRandom(LRandom* instr);
101   void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
102   void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
103   void DoDeferredAllocateObject(LAllocateObject* instr);
104   void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
105                                        Label* map_check);
106 
107   void DoCheckMapCommon(Register reg, Handle<Map> map,
108                         CompareMapMode mode, LEnvironment* env);
109 
110 // Parallel move support.
111   void DoParallelMove(LParallelMove* move);
112   void DoGap(LGap* instr);
113 
114   // Emit frame translation commands for an environment.
115   void WriteTranslation(LEnvironment* environment, Translation* translation);
116 
117   // Declare methods that deal with the individual node types.
118 #define DECLARE_DO(type) void Do##type(L##type* node);
119   LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
120 #undef DECLARE_DO
121 
122  private:
123   enum Status {
124     UNUSED,
125     GENERATING,
126     DONE,
127     ABORTED
128   };
129 
is_unused()130   bool is_unused() const { return status_ == UNUSED; }
is_generating()131   bool is_generating() const { return status_ == GENERATING; }
is_done()132   bool is_done() const { return status_ == DONE; }
is_aborted()133   bool is_aborted() const { return status_ == ABORTED; }
134 
strict_mode_flag()135   StrictModeFlag strict_mode_flag() const {
136     return info()->is_classic_mode() ? kNonStrictMode : kStrictMode;
137   }
138 
chunk()139   LChunk* chunk() const { return chunk_; }
scope()140   Scope* scope() const { return scope_; }
graph()141   HGraph* graph() const { return chunk_->graph(); }
142 
143   int GetNextEmittedBlock(int block);
144 
145   void EmitClassOfTest(Label* if_true,
146                        Label* if_false,
147                        Handle<String> class_name,
148                        Register input,
149                        Register temporary,
150                        Register scratch);
151 
GetStackSlotCount()152   int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
GetParameterCount()153   int GetParameterCount() const { return scope()->num_parameters(); }
154 
155   void Abort(const char* format, ...);
156   void Comment(const char* format, ...);
157 
AddDeferredCode(LDeferredCode * code)158   void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); }
159 
160   // Code generation passes.  Returns true if code generation should
161   // continue.
162   bool GeneratePrologue();
163   bool GenerateBody();
164   bool GenerateDeferredCode();
165   bool GenerateJumpTable();
166   bool GenerateSafepointTable();
167 
168   enum SafepointMode {
169     RECORD_SIMPLE_SAFEPOINT,
170     RECORD_SAFEPOINT_WITH_REGISTERS
171   };
172 
173   void CallCodeGeneric(Handle<Code> code,
174                        RelocInfo::Mode mode,
175                        LInstruction* instr,
176                        SafepointMode safepoint_mode,
177                        int argc);
178 
179 
180   void CallCode(Handle<Code> code,
181                 RelocInfo::Mode mode,
182                 LInstruction* instr);
183 
184   void CallRuntime(const Runtime::Function* function,
185                    int num_arguments,
186                    LInstruction* instr);
187 
CallRuntime(Runtime::FunctionId id,int num_arguments,LInstruction * instr)188   void CallRuntime(Runtime::FunctionId id,
189                    int num_arguments,
190                    LInstruction* instr) {
191     const Runtime::Function* function = Runtime::FunctionForId(id);
192     CallRuntime(function, num_arguments, instr);
193   }
194 
195   void CallRuntimeFromDeferred(Runtime::FunctionId id,
196                                int argc,
197                                LInstruction* instr);
198 
199   // Generate a direct call to a known function.  Expects the function
200   // to be in rdi.
201   void CallKnownFunction(Handle<JSFunction> function,
202                          int arity,
203                          LInstruction* instr,
204                          CallKind call_kind);
205 
206 
207   void RecordSafepointWithLazyDeopt(LInstruction* instr,
208                                     SafepointMode safepoint_mode,
209                                     int argc);
210   void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
211                                             Safepoint::DeoptMode mode);
212   void DeoptimizeIf(Condition cc, LEnvironment* environment);
213 
214   void AddToTranslation(Translation* translation,
215                         LOperand* op,
216                         bool is_tagged);
217   void PopulateDeoptimizationData(Handle<Code> code);
218   int DefineDeoptimizationLiteral(Handle<Object> literal);
219 
220   void PopulateDeoptimizationLiteralsWithInlinedFunctions();
221 
222   Register ToRegister(int index) const;
223   XMMRegister ToDoubleRegister(int index) const;
224   Operand BuildFastArrayOperand(
225       LOperand* elements_pointer,
226       LOperand* key,
227       ElementsKind elements_kind,
228       uint32_t offset);
229 
230   // Specific math operations - used from DoUnaryMathOperation.
231   void EmitIntegerMathAbs(LUnaryMathOperation* instr);
232   void DoMathAbs(LUnaryMathOperation* instr);
233   void DoMathFloor(LUnaryMathOperation* instr);
234   void DoMathRound(LUnaryMathOperation* instr);
235   void DoMathSqrt(LUnaryMathOperation* instr);
236   void DoMathPowHalf(LUnaryMathOperation* instr);
237   void DoMathLog(LUnaryMathOperation* instr);
238   void DoMathTan(LUnaryMathOperation* instr);
239   void DoMathCos(LUnaryMathOperation* instr);
240   void DoMathSin(LUnaryMathOperation* instr);
241 
242   // Support for recording safepoint and position information.
243   void RecordSafepoint(LPointerMap* pointers,
244                        Safepoint::Kind kind,
245                        int arguments,
246                        Safepoint::DeoptMode mode);
247   void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
248   void RecordSafepoint(Safepoint::DeoptMode mode);
249   void RecordSafepointWithRegisters(LPointerMap* pointers,
250                                     int arguments,
251                                     Safepoint::DeoptMode mode);
252   void RecordPosition(int position);
253 
254   static Condition TokenToCondition(Token::Value op, bool is_unsigned);
255   void EmitGoto(int block);
256   void EmitBranch(int left_block, int right_block, Condition cc);
257   void EmitNumberUntagD(Register input,
258                         XMMRegister result,
259                         bool deoptimize_on_undefined,
260                         bool deoptimize_on_minus_zero,
261                         LEnvironment* env);
262 
263   // Emits optimized code for typeof x == "y".  Modifies input register.
264   // Returns the condition on which a final split to
265   // true and false label should be made, to optimize fallthrough.
266   Condition EmitTypeofIs(Label* true_label,
267                          Label* false_label,
268                          Register input,
269                          Handle<String> type_name);
270 
271   // Emits optimized code for %_IsObject(x).  Preserves input register.
272   // Returns the condition on which a final split to
273   // true and false label should be made, to optimize fallthrough.
274   Condition EmitIsObject(Register input,
275                          Label* is_not_object,
276                          Label* is_object);
277 
278   // Emits optimized code for %_IsString(x).  Preserves input register.
279   // Returns the condition on which a final split to
280   // true and false label should be made, to optimize fallthrough.
281   Condition EmitIsString(Register input,
282                          Register temp1,
283                          Label* is_not_string);
284 
285   // Emits optimized code for %_IsConstructCall().
286   // Caller should branch on equal condition.
287   void EmitIsConstructCall(Register temp);
288 
289   void EmitLoadFieldOrConstantFunction(Register result,
290                                        Register object,
291                                        Handle<Map> type,
292                                        Handle<String> name);
293 
294   // Emits code for pushing either a tagged constant, a (non-double)
295   // register, or a stack slot operand.
296   void EmitPushTaggedOperand(LOperand* operand);
297 
298   // Emits optimized code to deep-copy the contents of statically known
299   // object graphs (e.g. object literal boilerplate).
300   void EmitDeepCopy(Handle<JSObject> object,
301                     Register result,
302                     Register source,
303                     int* offset);
304 
305   struct JumpTableEntry {
JumpTableEntryJumpTableEntry306     explicit inline JumpTableEntry(Address entry)
307         : label(),
308           address(entry) { }
309     Label label;
310     Address address;
311   };
312 
313   void EnsureSpaceForLazyDeopt(int space_needed);
314 
315   LChunk* const chunk_;
316   MacroAssembler* const masm_;
317   CompilationInfo* const info_;
318 
319   int current_block_;
320   int current_instruction_;
321   const ZoneList<LInstruction*>* instructions_;
322   ZoneList<LEnvironment*> deoptimizations_;
323   ZoneList<JumpTableEntry> jump_table_;
324   ZoneList<Handle<Object> > deoptimization_literals_;
325   int inlined_function_count_;
326   Scope* const scope_;
327   Status status_;
328   TranslationBuffer translations_;
329   ZoneList<LDeferredCode*> deferred_;
330   int osr_pc_offset_;
331   int last_lazy_deopt_pc_;
332 
333   // Builder that keeps track of safepoints in the code. The table
334   // itself is emitted at the end of the generated code.
335   SafepointTableBuilder safepoints_;
336 
337   // Compiler from a set of parallel moves to a sequential list of moves.
338   LGapResolver resolver_;
339 
340   Safepoint::Kind expected_safepoint_kind_;
341 
342   class PushSafepointRegistersScope BASE_EMBEDDED {
343    public:
PushSafepointRegistersScope(LCodeGen * codegen)344     explicit PushSafepointRegistersScope(LCodeGen* codegen)
345         : codegen_(codegen) {
346       ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
347       codegen_->masm_->PushSafepointRegisters();
348       codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters;
349     }
350 
~PushSafepointRegistersScope()351     ~PushSafepointRegistersScope() {
352       ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters);
353       codegen_->masm_->PopSafepointRegisters();
354       codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
355     }
356 
357    private:
358     LCodeGen* codegen_;
359   };
360 
361   friend class LDeferredCode;
362   friend class LEnvironment;
363   friend class SafepointGenerator;
364   DISALLOW_COPY_AND_ASSIGN(LCodeGen);
365 };
366 
367 
368 class LDeferredCode: public ZoneObject {
369  public:
LDeferredCode(LCodeGen * codegen)370   explicit LDeferredCode(LCodeGen* codegen)
371       : codegen_(codegen),
372         external_exit_(NULL),
373         instruction_index_(codegen->current_instruction_) {
374     codegen->AddDeferredCode(this);
375   }
376 
~LDeferredCode()377   virtual ~LDeferredCode() { }
378   virtual void Generate() = 0;
379   virtual LInstruction* instr() = 0;
380 
SetExit(Label * exit)381   void SetExit(Label* exit) { external_exit_ = exit; }
entry()382   Label* entry() { return &entry_; }
exit()383   Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
instruction_index()384   int instruction_index() const { return instruction_index_; }
385 
386  protected:
codegen()387   LCodeGen* codegen() const { return codegen_; }
masm()388   MacroAssembler* masm() const { return codegen_->masm(); }
389 
390  private:
391   LCodeGen* codegen_;
392   Label entry_;
393   Label exit_;
394   Label* external_exit_;
395   int instruction_index_;
396 };
397 
398 } }  // namespace v8::internal
399 
400 #endif  // V8_X64_LITHIUM_CODEGEN_X64_H_
401