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.
5 #ifndef V8_PPC_LITHIUM_CODEGEN_PPC_H_
6 #define V8_PPC_LITHIUM_CODEGEN_PPC_H_
8 #include "src/ppc/lithium-ppc.h"
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"
20 // Forward declarations.
22 class SafepointGenerator;
24 class LCodeGen : public LCodeGenBase {
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()),
35 frame_is_built_(false),
36 safepoints_(info->zone()),
38 expected_safepoint_kind_(Safepoint::kSimple) {
39 PopulateDeoptimizationLiteralsWithInlinedFunctions();
43 int LookupDestination(int block_id) const {
44 return chunk()->LookupDestination(block_id);
47 bool IsNextEmittedBlock(int block_id) const {
48 return LookupDestination(block_id) == GetNextEmittedBlock();
51 bool NeedsEagerFrame() const {
52 return GetStackSlotCount() > 0 || info()->is_non_deferred_calling() ||
53 !info()->IsStub() || info()->requires_frame();
55 bool NeedsDeferredFrame() const {
56 return !NeedsEagerFrame() && info()->is_deferred_calling();
59 LinkRegisterStatus GetLinkRegisterState() const {
60 return frame_is_built_ ? kLRHasBeenSaved : kLRHasNotBeenSaved;
63 // Support for converting LOperands to assembler types.
64 // LOperand must be a register.
65 Register ToRegister(LOperand* op) const;
67 // LOperand is loaded into scratch, unless already a register.
68 Register EmitLoadRegister(LOperand* op, Register scratch);
70 // LConstantOperand must be an Integer32 or Smi
71 void EmitLoadIntegerConstant(LConstantOperand* const_op, Register dst);
73 // LOperand must be a double register.
74 DoubleRegister ToDoubleRegister(LOperand* op) const;
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;
86 bool IsInteger32(LConstantOperand* op) const;
87 bool IsSmi(LConstantOperand* op) const;
88 Handle<Object> ToHandle(LConstantOperand* op) const;
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.
95 // Finish the code by setting stack height, safepoint, and bailout
97 void FinishCode(Handle<Code> code);
99 // Deferred code support.
100 void DoDeferredNumberTagD(LNumberTagD* instr);
102 enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 };
103 void DoDeferredNumberTagIU(LInstruction* instr, LOperand* value,
104 LOperand* temp1, LOperand* temp2,
105 IntegerSignedness signedness);
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);
118 // Parallel move support.
119 void DoParallelMove(LParallelMove* move);
120 void DoGap(LGap* instr);
122 MemOperand PrepareKeyedOperand(Register key, Register base,
123 bool key_is_constant, bool key_is_tagged,
124 int constant_key, int element_size_shift,
127 // Emit frame translation commands for an environment.
128 void WriteTranslation(LEnvironment* environment, Translation* translation);
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)
136 LanguageMode language_mode() const { return info()->language_mode(); }
138 Scope* scope() const { return scope_; }
140 Register scratch0() { return r11; }
141 DoubleRegister double_scratch0() { return kScratchDoubleReg; }
143 LInstruction* GetNextInstruction();
145 void EmitClassOfTest(Label* if_true, Label* if_false,
146 Handle<String> class_name, Register input,
147 Register temporary, Register temporary2);
149 int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
151 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
153 void SaveCallerDoubles();
154 void RestoreCallerDoubles();
156 // Code generation passes. Returns true if code generation should
158 void GenerateBodyInstructionPre(LInstruction* instr) override;
159 bool GeneratePrologue();
160 bool GenerateDeferredCode();
161 bool GenerateJumpTable();
162 bool GenerateSafepointTable();
164 // Generates the custom OSR entrypoint and sets the osr_pc_offset.
165 void GenerateOsrPrologue();
168 RECORD_SIMPLE_SAFEPOINT,
169 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS
172 void CallCode(Handle<Code> code, RelocInfo::Mode mode, LInstruction* instr);
174 void CallCodeGeneric(Handle<Code> code, RelocInfo::Mode mode,
175 LInstruction* instr, SafepointMode safepoint_mode);
177 void CallRuntime(const Runtime::Function* function, int num_arguments,
179 SaveFPRegsMode save_doubles = kDontSaveFPRegs);
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);
187 void LoadContextFromDeferred(LOperand* context);
188 void CallRuntimeFromDeferred(Runtime::FunctionId id, int argc,
189 LInstruction* instr, LOperand* context);
191 // Generate a direct call to a known function. Expects the function
193 void CallKnownFunction(Handle<JSFunction> function,
194 int formal_parameter_count, int arity,
195 LInstruction* instr);
197 void RecordSafepointWithLazyDeopt(LInstruction* instr,
198 SafepointMode safepoint_mode);
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);
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);
214 void PopulateDeoptimizationLiteralsWithInlinedFunctions();
216 Register ToRegister(int index) const;
217 DoubleRegister ToDoubleRegister(int index) const;
219 MemOperand BuildSeqStringOperand(Register string, LOperand* index,
220 String::Encoding encoding);
222 void EmitMathAbs(LMathAbs* instr);
223 #if V8_TARGET_ARCH_PPC64
224 void EmitInteger32MathAbs(LMathAbs* instr);
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);
235 void RecordAndWritePosition(int position) override;
237 static Condition TokenToCondition(Token::Value op);
238 void EmitGoto(int block);
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,
248 void EmitNumberUntagD(LNumberUntagD* instr, Register input,
249 DoubleRegister result, NumberUntagDMode mode);
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);
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);
263 // Emits optimized code for %_IsConstructCall().
264 // Caller should branch on equal condition.
265 void EmitIsConstructCall(Register temp1, Register temp2);
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);
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);
281 void EmitVectorLoadICRegisters(T* instr);
283 void EmitVectorStoreICRegisters(T* instr);
285 ZoneList<LEnvironment*> deoptimizations_;
286 ZoneList<Deoptimizer::JumpTableEntry> jump_table_;
287 int inlined_function_count_;
289 TranslationBuffer translations_;
290 ZoneList<LDeferredCode*> deferred_;
292 bool frame_is_built_;
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_;
298 // Compiler from a set of parallel moves to a sequential list of moves.
299 LGapResolver resolver_;
301 Safepoint::Kind expected_safepoint_kind_;
303 class PushSafepointRegistersScope final BASE_EMBEDDED {
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);
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;
325 friend class LDeferredCode;
326 friend class LEnvironment;
327 friend class SafepointGenerator;
328 DISALLOW_COPY_AND_ASSIGN(LCodeGen);
332 class LDeferredCode : public ZoneObject {
334 explicit LDeferredCode(LCodeGen* codegen)
336 external_exit_(NULL),
337 instruction_index_(codegen->current_instruction_) {
338 codegen->AddDeferredCode(this);
341 virtual ~LDeferredCode() {}
342 virtual void Generate() = 0;
343 virtual LInstruction* instr() = 0;
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_; }
351 LCodeGen* codegen() const { return codegen_; }
352 MacroAssembler* masm() const { return codegen_->masm(); }
358 Label* external_exit_;
359 int instruction_index_;
362 } // namespace v8::internal
364 #endif // V8_PPC_LITHIUM_CODEGEN_PPC_H_