117dc574d54d4654ae4433e17622a9dd1b844460
[platform/upstream/v8.git] / src / ppc / lithium-codegen-ppc.h
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_PPC_LITHIUM_CODEGEN_PPC_H_
6 #define V8_PPC_LITHIUM_CODEGEN_PPC_H_
7
8 #include "src/ppc/lithium-ppc.h"
9
10 #include "src/ppc/lithium-gap-resolver-ppc.h"
11 #include "src/deoptimizer.h"
12 #include "src/lithium-codegen.h"
13 #include "src/safepoint-table.h"
14 #include "src/scopes.h"
15 #include "src/utils.h"
16
17 namespace v8 {
18 namespace internal {
19
20 // Forward declarations.
21 class LDeferredCode;
22 class SafepointGenerator;
23
24 class LCodeGen : public LCodeGenBase {
25  public:
26   LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
27       : LCodeGenBase(chunk, assembler, info),
28         deoptimizations_(4, info->zone()),
29         jump_table_(4, info->zone()),
30         inlined_function_count_(0),
31         scope_(info->scope()),
32         translations_(info->zone()),
33         deferred_(8, info->zone()),
34         osr_pc_offset_(-1),
35         frame_is_built_(false),
36         safepoints_(info->zone()),
37         resolver_(this),
38         expected_safepoint_kind_(Safepoint::kSimple) {
39     PopulateDeoptimizationLiteralsWithInlinedFunctions();
40   }
41
42
43   int LookupDestination(int block_id) const {
44     return chunk()->LookupDestination(block_id);
45   }
46
47   bool IsNextEmittedBlock(int block_id) const {
48     return LookupDestination(block_id) == GetNextEmittedBlock();
49   }
50
51   bool NeedsEagerFrame() const {
52     return GetStackSlotCount() > 0 || info()->is_non_deferred_calling() ||
53            !info()->IsStub() || info()->requires_frame();
54   }
55   bool NeedsDeferredFrame() const {
56     return !NeedsEagerFrame() && info()->is_deferred_calling();
57   }
58
59   LinkRegisterStatus GetLinkRegisterState() const {
60     return frame_is_built_ ? kLRHasBeenSaved : kLRHasNotBeenSaved;
61   }
62
63   // Support for converting LOperands to assembler types.
64   // LOperand must be a register.
65   Register ToRegister(LOperand* op) const;
66
67   // LOperand is loaded into scratch, unless already a register.
68   Register EmitLoadRegister(LOperand* op, Register scratch);
69
70   // LConstantOperand must be an Integer32 or Smi
71   void EmitLoadIntegerConstant(LConstantOperand* const_op, Register dst);
72
73   // LOperand must be a double register.
74   DoubleRegister ToDoubleRegister(LOperand* op) const;
75
76   intptr_t ToRepresentation(LConstantOperand* op,
77                             const Representation& r) const;
78   int32_t ToInteger32(LConstantOperand* op) const;
79   Smi* ToSmi(LConstantOperand* op) const;
80   double ToDouble(LConstantOperand* op) const;
81   Operand ToOperand(LOperand* op);
82   MemOperand ToMemOperand(LOperand* op) const;
83   // Returns a MemOperand pointing to the high word of a DoubleStackSlot.
84   MemOperand ToHighMemOperand(LOperand* op) const;
85
86   bool IsInteger32(LConstantOperand* op) const;
87   bool IsSmi(LConstantOperand* op) const;
88   Handle<Object> ToHandle(LConstantOperand* op) const;
89
90   // Try to generate code for the entire chunk, but it may fail if the
91   // chunk contains constructs we cannot handle. Returns true if the
92   // code generation attempt succeeded.
93   bool GenerateCode();
94
95   // Finish the code by setting stack height, safepoint, and bailout
96   // information on it.
97   void FinishCode(Handle<Code> code);
98
99   // Deferred code support.
100   void DoDeferredNumberTagD(LNumberTagD* instr);
101
102   enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 };
103   void DoDeferredNumberTagIU(LInstruction* instr, LOperand* value,
104                              LOperand* temp1, LOperand* temp2,
105                              IntegerSignedness signedness);
106
107   void DoDeferredTaggedToI(LTaggedToI* instr);
108   void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr);
109   void DoDeferredStackCheck(LStackCheck* instr);
110   void DoDeferredMaybeGrowElements(LMaybeGrowElements* instr);
111   void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
112   void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
113   void DoDeferredAllocate(LAllocate* instr);
114   void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
115   void DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, Register result,
116                                    Register object, Register index);
117
118   // Parallel move support.
119   void DoParallelMove(LParallelMove* move);
120   void DoGap(LGap* instr);
121
122   MemOperand PrepareKeyedOperand(Register key, Register base,
123                                  bool key_is_constant, bool key_is_tagged,
124                                  int constant_key, int element_size_shift,
125                                  int base_offset);
126
127   // Emit frame translation commands for an environment.
128   void WriteTranslation(LEnvironment* environment, Translation* translation);
129
130 // Declare methods that deal with the individual node types.
131 #define DECLARE_DO(type) void Do##type(L##type* node);
132   LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
133 #undef DECLARE_DO
134
135  private:
136   LanguageMode language_mode() const { return info()->language_mode(); }
137
138   Scope* scope() const { return scope_; }
139
140   Register scratch0() { return r11; }
141   DoubleRegister double_scratch0() { return kScratchDoubleReg; }
142
143   LInstruction* GetNextInstruction();
144
145   void EmitClassOfTest(Label* if_true, Label* if_false,
146                        Handle<String> class_name, Register input,
147                        Register temporary, Register temporary2);
148
149   int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
150
151   void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
152
153   void SaveCallerDoubles();
154   void RestoreCallerDoubles();
155
156   // Code generation passes.  Returns true if code generation should
157   // continue.
158   void GenerateBodyInstructionPre(LInstruction* instr) override;
159   bool GeneratePrologue();
160   bool GenerateDeferredCode();
161   bool GenerateJumpTable();
162   bool GenerateSafepointTable();
163
164   // Generates the custom OSR entrypoint and sets the osr_pc_offset.
165   void GenerateOsrPrologue();
166
167   enum SafepointMode {
168     RECORD_SIMPLE_SAFEPOINT,
169     RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS
170   };
171
172   void CallCode(Handle<Code> code, RelocInfo::Mode mode, LInstruction* instr);
173
174   void CallCodeGeneric(Handle<Code> code, RelocInfo::Mode mode,
175                        LInstruction* instr, SafepointMode safepoint_mode);
176
177   void CallRuntime(const Runtime::Function* function, int num_arguments,
178                    LInstruction* instr,
179                    SaveFPRegsMode save_doubles = kDontSaveFPRegs);
180
181   void CallRuntime(Runtime::FunctionId id, int num_arguments,
182                    LInstruction* instr) {
183     const Runtime::Function* function = Runtime::FunctionForId(id);
184     CallRuntime(function, num_arguments, instr);
185   }
186
187   void LoadContextFromDeferred(LOperand* context);
188   void CallRuntimeFromDeferred(Runtime::FunctionId id, int argc,
189                                LInstruction* instr, LOperand* context);
190
191   // Generate a direct call to a known function.  Expects the function
192   // to be in r4.
193   void CallKnownFunction(Handle<JSFunction> function,
194                          int formal_parameter_count, int arity,
195                          LInstruction* instr);
196
197   void RecordSafepointWithLazyDeopt(LInstruction* instr,
198                                     SafepointMode safepoint_mode);
199
200   void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
201                                             Safepoint::DeoptMode mode);
202   void DeoptimizeIf(Condition condition, LInstruction* instr,
203                     Deoptimizer::DeoptReason deopt_reason,
204                     Deoptimizer::BailoutType bailout_type, CRegister cr = cr7);
205   void DeoptimizeIf(Condition condition, LInstruction* instr,
206                     Deoptimizer::DeoptReason deopt_reason, CRegister cr = cr7);
207
208   void AddToTranslation(LEnvironment* environment, Translation* translation,
209                         LOperand* op, bool is_tagged, bool is_uint32,
210                         int* object_index_pointer,
211                         int* dematerialized_index_pointer);
212   void PopulateDeoptimizationData(Handle<Code> code);
213
214   void PopulateDeoptimizationLiteralsWithInlinedFunctions();
215
216   Register ToRegister(int index) const;
217   DoubleRegister ToDoubleRegister(int index) const;
218
219   MemOperand BuildSeqStringOperand(Register string, LOperand* index,
220                                    String::Encoding encoding);
221
222   void EmitMathAbs(LMathAbs* instr);
223 #if V8_TARGET_ARCH_PPC64
224   void EmitInteger32MathAbs(LMathAbs* instr);
225 #endif
226
227   // Support for recording safepoint and position information.
228   void RecordSafepoint(LPointerMap* pointers, Safepoint::Kind kind,
229                        int arguments, Safepoint::DeoptMode mode);
230   void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
231   void RecordSafepoint(Safepoint::DeoptMode mode);
232   void RecordSafepointWithRegisters(LPointerMap* pointers, int arguments,
233                                     Safepoint::DeoptMode mode);
234
235   void RecordAndWritePosition(int position) override;
236
237   static Condition TokenToCondition(Token::Value op);
238   void EmitGoto(int block);
239
240   // EmitBranch expects to be the last instruction of a block.
241   template <class InstrType>
242   void EmitBranch(InstrType instr, Condition condition, CRegister cr = cr7);
243   template <class InstrType>
244   void EmitTrueBranch(InstrType instr, Condition condition, CRegister cr = cr7);
245   template <class InstrType>
246   void EmitFalseBranch(InstrType instr, Condition condition,
247                        CRegister cr = cr7);
248   void EmitNumberUntagD(LNumberUntagD* instr, Register input,
249                         DoubleRegister result, NumberUntagDMode mode);
250
251   // Emits optimized code for typeof x == "y".  Modifies input register.
252   // Returns the condition on which a final split to
253   // true and false label should be made, to optimize fallthrough.
254   Condition EmitTypeofIs(Label* true_label, Label* false_label, Register input,
255                          Handle<String> type_name);
256
257   // Emits optimized code for %_IsString(x).  Preserves input register.
258   // Returns the condition on which a final split to
259   // true and false label should be made, to optimize fallthrough.
260   Condition EmitIsString(Register input, Register temp1, Label* is_not_string,
261                          SmiCheck check_needed);
262
263   // Emits optimized code for %_IsConstructCall().
264   // Caller should branch on equal condition.
265   void EmitIsConstructCall(Register temp1, Register temp2);
266
267   // Emits optimized code to deep-copy the contents of statically known
268   // object graphs (e.g. object literal boilerplate).
269   void EmitDeepCopy(Handle<JSObject> object, Register result, Register source,
270                     int* offset, AllocationSiteMode mode);
271
272   void EnsureSpaceForLazyDeopt(int space_needed) override;
273   void DoLoadKeyedExternalArray(LLoadKeyed* instr);
274   void DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr);
275   void DoLoadKeyedFixedArray(LLoadKeyed* instr);
276   void DoStoreKeyedExternalArray(LStoreKeyed* instr);
277   void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
278   void DoStoreKeyedFixedArray(LStoreKeyed* instr);
279
280   template <class T>
281   void EmitVectorLoadICRegisters(T* instr);
282   template <class T>
283   void EmitVectorStoreICRegisters(T* instr);
284
285   ZoneList<LEnvironment*> deoptimizations_;
286   ZoneList<Deoptimizer::JumpTableEntry> jump_table_;
287   int inlined_function_count_;
288   Scope* const scope_;
289   TranslationBuffer translations_;
290   ZoneList<LDeferredCode*> deferred_;
291   int osr_pc_offset_;
292   bool frame_is_built_;
293
294   // Builder that keeps track of safepoints in the code. The table
295   // itself is emitted at the end of the generated code.
296   SafepointTableBuilder safepoints_;
297
298   // Compiler from a set of parallel moves to a sequential list of moves.
299   LGapResolver resolver_;
300
301   Safepoint::Kind expected_safepoint_kind_;
302
303   class PushSafepointRegistersScope final BASE_EMBEDDED {
304    public:
305     explicit PushSafepointRegistersScope(LCodeGen* codegen)
306         : codegen_(codegen) {
307       DCHECK(codegen_->info()->is_calling());
308       DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
309       codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters;
310       StoreRegistersStateStub stub(codegen_->isolate());
311       codegen_->masm_->CallStub(&stub);
312     }
313
314     ~PushSafepointRegistersScope() {
315       DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters);
316       RestoreRegistersStateStub stub(codegen_->isolate());
317       codegen_->masm_->CallStub(&stub);
318       codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
319     }
320
321    private:
322     LCodeGen* codegen_;
323   };
324
325   friend class LDeferredCode;
326   friend class LEnvironment;
327   friend class SafepointGenerator;
328   DISALLOW_COPY_AND_ASSIGN(LCodeGen);
329 };
330
331
332 class LDeferredCode : public ZoneObject {
333  public:
334   explicit LDeferredCode(LCodeGen* codegen)
335       : codegen_(codegen),
336         external_exit_(NULL),
337         instruction_index_(codegen->current_instruction_) {
338     codegen->AddDeferredCode(this);
339   }
340
341   virtual ~LDeferredCode() {}
342   virtual void Generate() = 0;
343   virtual LInstruction* instr() = 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   int instruction_index() const { return instruction_index_; }
349
350  protected:
351   LCodeGen* codegen() const { return codegen_; }
352   MacroAssembler* masm() const { return codegen_->masm(); }
353
354  private:
355   LCodeGen* codegen_;
356   Label entry_;
357   Label exit_;
358   Label* external_exit_;
359   int instruction_index_;
360 };
361 }
362 }  // namespace v8::internal
363
364 #endif  // V8_PPC_LITHIUM_CODEGEN_PPC_H_