V8 Project
lithium-codegen-arm.h
Go to the documentation of this file.
1 // Copyright 2012 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_ARM_LITHIUM_CODEGEN_ARM_H_
6 #define V8_ARM_LITHIUM_CODEGEN_ARM_H_
7 
8 #include "src/arm/lithium-arm.h"
9 
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:
27  : LCodeGenBase(chunk, assembler, info),
28  deoptimizations_(4, info->zone()),
29  jump_table_(4, info->zone()),
30  deoptimization_literals_(8, info->zone()),
32  scope_(info->scope()),
33  translations_(info->zone()),
34  deferred_(8, info->zone()),
35  osr_pc_offset_(-1),
37  safepoints_(info->zone()),
38  resolver_(this),
39  expected_safepoint_kind_(Safepoint::kSimple) {
41  }
42 
43 
44  int LookupDestination(int block_id) const {
45  return chunk()->LookupDestination(block_id);
46  }
47 
48  bool IsNextEmittedBlock(int block_id) const {
49  return LookupDestination(block_id) == GetNextEmittedBlock();
50  }
51 
52  bool NeedsEagerFrame() const {
53  return GetStackSlotCount() > 0 ||
54  info()->is_non_deferred_calling() ||
55  !info()->IsStub() ||
56  info()->requires_frame();
57  }
58  bool NeedsDeferredFrame() const {
59  return !NeedsEagerFrame() && info()->is_deferred_calling();
60  }
61 
64  }
65 
66  // Support for converting LOperands to assembler types.
67  // LOperand must be a register.
68  Register ToRegister(LOperand* op) const;
69 
70  // LOperand is loaded into scratch, unless already a register.
72 
73  // LOperand must be a double register.
75 
76  // LOperand is loaded into dbl_scratch, unless already a double register.
78  SwVfpRegister flt_scratch,
79  DwVfpRegister dbl_scratch);
80  int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
81  int32_t ToInteger32(LConstantOperand* op) const;
82  Smi* ToSmi(LConstantOperand* op) const;
83  double ToDouble(LConstantOperand* op) const;
85  MemOperand ToMemOperand(LOperand* op) const;
86  // Returns a MemOperand pointing to the high word of a DoubleStackSlot.
88 
89  bool IsInteger32(LConstantOperand* op) const;
90  bool IsSmi(LConstantOperand* op) const;
91  Handle<Object> ToHandle(LConstantOperand* op) const;
92 
93  // Try to generate code for the entire chunk, but it may fail if the
94  // chunk contains constructs we cannot handle. Returns true if the
95  // code generation attempt succeeded.
96  bool GenerateCode();
97 
98  // Finish the code by setting stack height, safepoint, and bailout
99  // information on it.
100  void FinishCode(Handle<Code> code);
101 
102  // Deferred code support.
103  void DoDeferredNumberTagD(LNumberTagD* instr);
104 
107  LOperand* value,
108  LOperand* temp1,
109  LOperand* temp2,
110  IntegerSignedness signedness);
111 
112  void DoDeferredTaggedToI(LTaggedToI* instr);
113  void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr);
114  void DoDeferredStackCheck(LStackCheck* instr);
115  void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
116  void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
117  void DoDeferredAllocate(LAllocate* instr);
118  void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
119  Label* map_check, Label* bool_load);
120  void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
121  void DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
122  Register result,
123  Register object,
124  Register index);
125 
126  // Parallel move support.
127  void DoParallelMove(LParallelMove* move);
128  void DoGap(LGap* instr);
129 
131  Register base,
132  bool key_is_constant,
133  int constant_key,
134  int element_size,
135  int shift_size,
136  int base_offset);
137 
138  // Emit frame translation commands for an environment.
139  void WriteTranslation(LEnvironment* environment, Translation* translation);
140 
141  // Declare methods that deal with the individual node types.
142 #define DECLARE_DO(type) void Do##type(L##type* node);
144 #undef DECLARE_DO
145 
146  private:
147  StrictMode strict_mode() const { return info()->strict_mode(); }
148 
149  Scope* scope() const { return scope_; }
150 
151  Register scratch0() { return r9; }
153 
155 
156  void EmitClassOfTest(Label* if_true,
157  Label* if_false,
158  Handle<String> class_name,
159  Register input,
160  Register temporary,
161  Register temporary2);
162 
163  int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
164 
165  void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
166 
167  void SaveCallerDoubles();
168  void RestoreCallerDoubles();
169 
170  // Code generation passes. Returns true if code generation should
171  // continue.
173  bool GeneratePrologue();
174  bool GenerateDeferredCode();
175  bool GenerateJumpTable();
176  bool GenerateSafepointTable();
177 
178  // Generates the custom OSR entrypoint and sets the osr_pc_offset.
179  void GenerateOsrPrologue();
180 
184  };
185 
187 
188  void CallCode(
189  Handle<Code> code,
191  LInstruction* instr,
193 
194  void CallCodeGeneric(
195  Handle<Code> code,
197  LInstruction* instr,
198  SafepointMode safepoint_mode,
200 
201  void CallRuntime(const Runtime::Function* function,
202  int num_arguments,
203  LInstruction* instr,
204  SaveFPRegsMode save_doubles = kDontSaveFPRegs);
205 
207  int num_arguments,
208  LInstruction* instr) {
209  const Runtime::Function* function = Runtime::FunctionForId(id);
210  CallRuntime(function, num_arguments, instr);
211  }
212 
213  void LoadContextFromDeferred(LOperand* context);
215  int argc,
216  LInstruction* instr,
217  LOperand* context);
218 
219  enum R1State {
222  };
223 
224  // Generate a direct call to a known function. Expects the function
225  // to be in r1.
227  int formal_parameter_count,
228  int arity,
229  LInstruction* instr,
230  R1State r1_state);
231 
233  SafepointMode safepoint_mode);
234 
236  Safepoint::DeoptMode mode);
237  void DeoptimizeIf(Condition condition, LInstruction* instr,
238  const char* detail, Deoptimizer::BailoutType bailout_type);
239  void DeoptimizeIf(Condition condition, LInstruction* instr,
240  const char* detail);
241 
242  void AddToTranslation(LEnvironment* environment,
243  Translation* translation,
244  LOperand* op,
245  bool is_tagged,
246  bool is_uint32,
247  int* object_index_pointer,
248  int* dematerialized_index_pointer);
251 
253 
254  Register ToRegister(int index) const;
255  DwVfpRegister ToDoubleRegister(int index) const;
256 
258  LOperand* index,
259  String::Encoding encoding);
260 
261  void EmitIntegerMathAbs(LMathAbs* instr);
262 
263  // Support for recording safepoint and position information.
264  void RecordSafepoint(LPointerMap* pointers,
265  Safepoint::Kind kind,
266  int arguments,
267  Safepoint::DeoptMode mode);
268  void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
269  void RecordSafepoint(Safepoint::DeoptMode mode);
270  void RecordSafepointWithRegisters(LPointerMap* pointers,
271  int arguments,
272  Safepoint::DeoptMode mode);
273 
274  void RecordAndWritePosition(int position) OVERRIDE;
275 
276  static Condition TokenToCondition(Token::Value op, bool is_unsigned);
277  void EmitGoto(int block);
278 
279  // EmitBranch expects to be the last instruction of a block.
280  template<class InstrType>
281  void EmitBranch(InstrType instr, Condition condition);
282  template<class InstrType>
283  void EmitFalseBranch(InstrType instr, Condition condition);
284  void EmitNumberUntagD(LNumberUntagD* instr, Register input,
286 
287  // Emits optimized code for typeof x == "y". Modifies input register.
288  // Returns the condition on which a final split to
289  // true and false label should be made, to optimize fallthrough.
290  Condition EmitTypeofIs(Label* true_label,
291  Label* false_label,
292  Register input,
293  Handle<String> type_name);
294 
295  // Emits optimized code for %_IsObject(x). Preserves input register.
296  // Returns the condition on which a final split to
297  // true and false label should be made, to optimize fallthrough.
299  Register temp1,
300  Label* is_not_object,
301  Label* is_object);
302 
303  // Emits optimized code for %_IsString(x). Preserves input register.
304  // Returns the condition on which a final split to
305  // true and false label should be made, to optimize fallthrough.
307  Register temp1,
308  Label* is_not_string,
309  SmiCheck check_needed);
310 
311  // Emits optimized code for %_IsConstructCall().
312  // Caller should branch on equal condition.
313  void EmitIsConstructCall(Register temp1, Register temp2);
314 
315  // Emits optimized code to deep-copy the contents of statically known
316  // object graphs (e.g. object literal boilerplate).
318  Register result,
319  Register source,
320  int* offset,
322 
323  void EnsureSpaceForLazyDeopt(int space_needed) OVERRIDE;
326  void DoLoadKeyedFixedArray(LLoadKeyed* instr);
329  void DoStoreKeyedFixedArray(LStoreKeyed* instr);
330 
331  template <class T>
332  void EmitVectorLoadICRegisters(T* instr);
333 
338  Scope* const scope_;
339  TranslationBuffer translations_;
343 
344  // Builder that keeps track of safepoints in the code. The table
345  // itself is emitted at the end of the generated code.
346  SafepointTableBuilder safepoints_;
347 
348  // Compiler from a set of parallel moves to a sequential list of moves.
350 
351  Safepoint::Kind expected_safepoint_kind_;
352 
353  class PushSafepointRegistersScope FINAL BASE_EMBEDDED {
354  public:
356  : codegen_(codegen) {
357  DCHECK(codegen_->info()->is_calling());
358  DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
359  codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters;
360  codegen_->masm_->PushSafepointRegisters();
361  }
362 
364  DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters);
365  codegen_->masm_->PopSafepointRegisters();
366  codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
367  }
368 
369  private:
371  };
372 
373  friend class LDeferredCode;
374  friend class LEnvironment;
375  friend class SafepointGenerator;
377 };
378 
379 
380 class LDeferredCode : public ZoneObject {
381  public:
383  : codegen_(codegen),
385  instruction_index_(codegen->current_instruction_) {
386  codegen->AddDeferredCode(this);
387  }
388 
389  virtual ~LDeferredCode() {}
390  virtual void Generate() = 0;
391  virtual LInstruction* instr() = 0;
392 
393  void SetExit(Label* exit) { external_exit_ = exit; }
394  Label* entry() { return &entry_; }
395  Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
396  int instruction_index() const { return instruction_index_; }
397 
398  protected:
399  LCodeGen* codegen() const { return codegen_; }
400  MacroAssembler* masm() const { return codegen_->masm(); }
401 
402  private:
404  Label entry_;
405  Label exit_;
408 };
409 
410 } } // namespace v8::internal
411 
412 #endif // V8_ARM_LITHIUM_CODEGEN_ARM_H_
#define kScratchDoubleReg
Source to read snapshot and builtins files from.
Definition: lithium-arm.h:372
bool IsNextEmittedBlock(int block_id) const
void DoStoreKeyedFixedArray(LStoreKeyed *instr)
void AddDeferredCode(LDeferredCode *code)
DwVfpRegister ToDoubleRegister(LOperand *op) const
void RecordSafepointWithRegisters(LPointerMap *pointers, int arguments, Safepoint::DeoptMode mode)
void EmitDeepCopy(Handle< JSObject > object, Register result, Register source, int *offset, AllocationSiteMode mode)
bool IsSmi(LConstantOperand *op) const
LinkRegisterStatus GetLinkRegisterState() const
TranslationBuffer translations_
MemOperand BuildSeqStringOperand(Register string, LOperand *index, String::Encoding encoding)
Condition EmitIsString(Register input, Register temp1, Label *is_not_string, SmiCheck check_needed)
DwVfpRegister EmitLoadDoubleRegister(LOperand *op, SwVfpRegister flt_scratch, DwVfpRegister dbl_scratch)
void DoDeferredStackCheck(LStackCheck *instr)
SafepointTableBuilder safepoints_
LInstruction * GetNextInstruction()
void EmitVectorLoadICRegisters(T *instr)
static Condition TokenToCondition(Token::Value op, bool is_unsigned)
ZoneList< Handle< Object > > deoptimization_literals_
void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal *instr, Label *map_check, Label *bool_load)
MemOperand PrepareKeyedOperand(Register key, Register base, bool key_is_constant, int constant_key, int element_size, int shift_size, int base_offset)
void PopulateDeoptimizationLiteralsWithInlinedFunctions()
void AddToTranslation(LEnvironment *environment, Translation *translation, LOperand *op, bool is_tagged, bool is_uint32, int *object_index_pointer, int *dematerialized_index_pointer)
ZoneList< LEnvironment * > deoptimizations_
DISALLOW_COPY_AND_ASSIGN(LCodeGen)
void EmitIntegerMathAbs(LMathAbs *instr)
int32_t ToRepresentation(LConstantOperand *op, const Representation &r) const
void CallRuntimeFromDeferred(Runtime::FunctionId id, int argc, LInstruction *instr, LOperand *context)
void EmitIsConstructCall(Register temp1, Register temp2)
int32_t ToInteger32(LConstantOperand *op) const
LPlatformChunk * chunk() const
void FinishCode(Handle< Code > code)
int LookupDestination(int block_id) const
Condition EmitTypeofIs(Label *true_label, Label *false_label, Register input, Handle< String > type_name)
void DoDeferredAllocate(LAllocate *instr)
void RecordSafepoint(LPointerMap *pointers, Safepoint::Kind kind, int arguments, Safepoint::DeoptMode mode)
void DoDeferredTaggedToI(LTaggedToI *instr)
LowDwVfpRegister double_scratch0()
void CallCodeGeneric(Handle< Code > code, RelocInfo::Mode mode, LInstruction *instr, SafepointMode safepoint_mode, TargetAddressStorageMode storage_mode=CAN_INLINE_TARGET_ADDRESS)
void DoDeferredStringCharCodeAt(LStringCharCodeAt *instr)
void CallCode(Handle< Code > code, RelocInfo::Mode mode, LInstruction *instr, TargetAddressStorageMode storage_mode=CAN_INLINE_TARGET_ADDRESS)
Safepoint::Kind expected_safepoint_kind_
ZoneList< LDeferredCode * > deferred_
void DoDeferredNumberTagIU(LInstruction *instr, LOperand *value, LOperand *temp1, LOperand *temp2, IntegerSignedness signedness)
Handle< Object > ToHandle(LConstantOperand *op) const
StrictMode strict_mode() const
int CallCodeSize(Handle< Code > code, RelocInfo::Mode mode)
void RegisterEnvironmentForDeoptimization(LEnvironment *environment, Safepoint::DeoptMode mode)
void LoadContextFromDeferred(LOperand *context)
void DoDeferredInstanceMigration(LCheckMaps *instr, Register object)
void DoDeferredLoadMutableDouble(LLoadFieldByIndex *instr, Register result, Register object, Register index)
int DefineDeoptimizationLiteral(Handle< Object > literal)
void DeoptimizeIf(Condition condition, LInstruction *instr, const char *detail, Deoptimizer::BailoutType bailout_type)
void CallKnownFunction(Handle< JSFunction > function, int formal_parameter_count, int arity, LInstruction *instr, R1State r1_state)
void WriteTranslation(LEnvironment *environment, Translation *translation)
void DoDeferredMathAbsTaggedHeapNumber(LMathAbs *instr)
void DoLoadKeyedFixedDoubleArray(LLoadKeyed *instr)
Operand ToOperand(LOperand *op)
Register EmitLoadRegister(LOperand *op, Register scratch)
void EmitClassOfTest(Label *if_true, Label *if_false, Handle< String > class_name, Register input, Register temporary, Register temporary2)
void DoLoadKeyedExternalArray(LLoadKeyed *instr)
double ToDouble(LConstantOperand *op) const
Register ToRegister(LOperand *op) const
void CallRuntime(Runtime::FunctionId id, int num_arguments, LInstruction *instr)
void DoStoreKeyedExternalArray(LStoreKeyed *instr)
void RecordAndWritePosition(int position) OVERRIDE
bool IsInteger32(LConstantOperand *op) const
void PopulateDeoptimizationData(Handle< Code > code)
void DoParallelMove(LParallelMove *move)
Smi * ToSmi(LConstantOperand *op) const
void CallRuntime(const Runtime::Function *function, int num_arguments, LInstruction *instr, SaveFPRegsMode save_doubles=kDontSaveFPRegs)
void DoDeferredStringCharFromCode(LStringCharFromCode *instr)
ZoneList< Deoptimizer::JumpTableEntry > jump_table_
Condition EmitIsObject(Register input, Register temp1, Label *is_not_object, Label *is_object)
void EnsureSpaceForLazyDeopt(int space_needed) OVERRIDE
void EmitNumberUntagD(LNumberUntagD *instr, Register input, DwVfpRegister result, NumberUntagDMode mode)
MemOperand ToMemOperand(LOperand *op) const
void GenerateBodyInstructionPre(LInstruction *instr) OVERRIDE
MemOperand ToHighMemOperand(LOperand *op) const
void RecordSafepointWithLazyDeopt(LInstruction *instr, SafepointMode safepoint_mode)
void EmitFalseBranch(InstrType instr, Condition condition)
void DoLoadKeyedFixedArray(LLoadKeyed *instr)
LCodeGen(LChunk *chunk, MacroAssembler *assembler, CompilationInfo *info)
void EmitBranch(InstrType instr, Condition condition)
void DoDeferredNumberTagD(LNumberTagD *instr)
void DoStoreKeyedFixedDoubleArray(LStoreKeyed *instr)
MacroAssembler * masm() const
virtual void Generate()=0
virtual LInstruction * instr()=0
static const Function * FunctionForId(FunctionId id)
Definition: runtime.cc:9312
#define OVERRIDE
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
Definition: lithium-arm.h:20
#define DECLARE_DO(type)
#define DCHECK(condition)
Definition: logging.h:205
int int32_t
Definition: unicode.cc:24
const Register r9
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
#define T(name, string, precedence)
Definition: token.cc:25