• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
18 #define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
19 
20 #include "arch/instruction_set.h"
21 #include "arch/instruction_set_features.h"
22 #include "base/arena_containers.h"
23 #include "base/arena_object.h"
24 #include "base/array_ref.h"
25 #include "base/bit_field.h"
26 #include "base/bit_utils.h"
27 #include "base/enums.h"
28 #include "base/globals.h"
29 #include "base/memory_region.h"
30 #include "class_root.h"
31 #include "dex/string_reference.h"
32 #include "dex/type_reference.h"
33 #include "graph_visualizer.h"
34 #include "locations.h"
35 #include "nodes.h"
36 #include "optimizing_compiler_stats.h"
37 #include "read_barrier_option.h"
38 #include "stack.h"
39 #include "utils/assembler.h"
40 #include "utils/label.h"
41 
42 namespace art {
43 
44 // Binary encoding of 2^32 for type double.
45 static int64_t constexpr k2Pow32EncodingForDouble = INT64_C(0x41F0000000000000);
46 // Binary encoding of 2^31 for type double.
47 static int64_t constexpr k2Pow31EncodingForDouble = INT64_C(0x41E0000000000000);
48 
49 // Minimum value for a primitive integer.
50 static int32_t constexpr kPrimIntMin = 0x80000000;
51 // Minimum value for a primitive long.
52 static int64_t constexpr kPrimLongMin = INT64_C(0x8000000000000000);
53 
54 // Maximum value for a primitive integer.
55 static int32_t constexpr kPrimIntMax = 0x7fffffff;
56 // Maximum value for a primitive long.
57 static int64_t constexpr kPrimLongMax = INT64_C(0x7fffffffffffffff);
58 
59 static constexpr ReadBarrierOption kCompilerReadBarrierOption =
60     kEmitCompilerReadBarrier ? kWithReadBarrier : kWithoutReadBarrier;
61 
62 class Assembler;
63 class CodeGenerator;
64 class CompilerOptions;
65 class StackMapStream;
66 class ParallelMoveResolver;
67 
68 namespace linker {
69 class LinkerPatch;
70 }  // namespace linker
71 
72 class CodeAllocator {
73  public:
CodeAllocator()74   CodeAllocator() {}
~CodeAllocator()75   virtual ~CodeAllocator() {}
76 
77   virtual uint8_t* Allocate(size_t size) = 0;
78   virtual ArrayRef<const uint8_t> GetMemory() const = 0;
79 
80  private:
81   DISALLOW_COPY_AND_ASSIGN(CodeAllocator);
82 };
83 
84 class SlowPathCode : public DeletableArenaObject<kArenaAllocSlowPaths> {
85  public:
SlowPathCode(HInstruction * instruction)86   explicit SlowPathCode(HInstruction* instruction) : instruction_(instruction) {
87     for (size_t i = 0; i < kMaximumNumberOfExpectedRegisters; ++i) {
88       saved_core_stack_offsets_[i] = kRegisterNotSaved;
89       saved_fpu_stack_offsets_[i] = kRegisterNotSaved;
90     }
91   }
92 
~SlowPathCode()93   virtual ~SlowPathCode() {}
94 
95   virtual void EmitNativeCode(CodeGenerator* codegen) = 0;
96 
97   // Save live core and floating-point caller-save registers and
98   // update the stack mask in `locations` for registers holding object
99   // references.
100   virtual void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations);
101   // Restore live core and floating-point caller-save registers.
102   virtual void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations);
103 
IsCoreRegisterSaved(int reg)104   bool IsCoreRegisterSaved(int reg) const {
105     return saved_core_stack_offsets_[reg] != kRegisterNotSaved;
106   }
107 
IsFpuRegisterSaved(int reg)108   bool IsFpuRegisterSaved(int reg) const {
109     return saved_fpu_stack_offsets_[reg] != kRegisterNotSaved;
110   }
111 
GetStackOffsetOfCoreRegister(int reg)112   uint32_t GetStackOffsetOfCoreRegister(int reg) const {
113     return saved_core_stack_offsets_[reg];
114   }
115 
GetStackOffsetOfFpuRegister(int reg)116   uint32_t GetStackOffsetOfFpuRegister(int reg) const {
117     return saved_fpu_stack_offsets_[reg];
118   }
119 
IsFatal()120   virtual bool IsFatal() const { return false; }
121 
122   virtual const char* GetDescription() const = 0;
123 
GetEntryLabel()124   Label* GetEntryLabel() { return &entry_label_; }
GetExitLabel()125   Label* GetExitLabel() { return &exit_label_; }
126 
GetInstruction()127   HInstruction* GetInstruction() const {
128     return instruction_;
129   }
130 
GetDexPc()131   uint32_t GetDexPc() const {
132     return instruction_ != nullptr ? instruction_->GetDexPc() : kNoDexPc;
133   }
134 
135  protected:
136   static constexpr size_t kMaximumNumberOfExpectedRegisters = 32;
137   static constexpr uint32_t kRegisterNotSaved = -1;
138   // The instruction where this slow path is happening.
139   HInstruction* instruction_;
140   uint32_t saved_core_stack_offsets_[kMaximumNumberOfExpectedRegisters];
141   uint32_t saved_fpu_stack_offsets_[kMaximumNumberOfExpectedRegisters];
142 
143  private:
144   Label entry_label_;
145   Label exit_label_;
146 
147   DISALLOW_COPY_AND_ASSIGN(SlowPathCode);
148 };
149 
150 class InvokeDexCallingConventionVisitor {
151  public:
152   virtual Location GetNextLocation(DataType::Type type) = 0;
153   virtual Location GetReturnLocation(DataType::Type type) const = 0;
154   virtual Location GetMethodLocation() const = 0;
155 
156  protected:
InvokeDexCallingConventionVisitor()157   InvokeDexCallingConventionVisitor() {}
~InvokeDexCallingConventionVisitor()158   virtual ~InvokeDexCallingConventionVisitor() {}
159 
160   // The current index for core registers.
161   uint32_t gp_index_ = 0u;
162   // The current index for floating-point registers.
163   uint32_t float_index_ = 0u;
164   // The current stack index.
165   uint32_t stack_index_ = 0u;
166 
167  private:
168   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
169 };
170 
171 class FieldAccessCallingConvention {
172  public:
173   virtual Location GetObjectLocation() const = 0;
174   virtual Location GetFieldIndexLocation() const = 0;
175   virtual Location GetReturnLocation(DataType::Type type) const = 0;
176   virtual Location GetSetValueLocation(DataType::Type type, bool is_instance) const = 0;
177   virtual Location GetFpuLocation(DataType::Type type) const = 0;
~FieldAccessCallingConvention()178   virtual ~FieldAccessCallingConvention() {}
179 
180  protected:
FieldAccessCallingConvention()181   FieldAccessCallingConvention() {}
182 
183  private:
184   DISALLOW_COPY_AND_ASSIGN(FieldAccessCallingConvention);
185 };
186 
187 class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> {
188  public:
189   // Compiles the graph to executable instructions.
190   void Compile(CodeAllocator* allocator);
191   static std::unique_ptr<CodeGenerator> Create(HGraph* graph,
192                                                const CompilerOptions& compiler_options,
193                                                OptimizingCompilerStats* stats = nullptr);
194   virtual ~CodeGenerator();
195 
196   // Get the graph. This is the outermost graph, never the graph of a method being inlined.
GetGraph()197   HGraph* GetGraph() const { return graph_; }
198 
199   HBasicBlock* GetNextBlockToEmit() const;
200   HBasicBlock* FirstNonEmptyBlock(HBasicBlock* block) const;
201   bool GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const;
202 
GetStackSlotOfParameter(HParameterValue * parameter)203   size_t GetStackSlotOfParameter(HParameterValue* parameter) const {
204     // Note that this follows the current calling convention.
205     return GetFrameSize()
206         + static_cast<size_t>(InstructionSetPointerSize(GetInstructionSet()))  // Art method
207         + parameter->GetIndex() * kVRegSize;
208   }
209 
210   virtual void Initialize() = 0;
211   virtual void Finalize(CodeAllocator* allocator);
212   virtual void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches);
213   virtual bool NeedsThunkCode(const linker::LinkerPatch& patch) const;
214   virtual void EmitThunkCode(const linker::LinkerPatch& patch,
215                              /*out*/ ArenaVector<uint8_t>* code,
216                              /*out*/ std::string* debug_name);
217   virtual void GenerateFrameEntry() = 0;
218   virtual void GenerateFrameExit() = 0;
219   virtual void Bind(HBasicBlock* block) = 0;
220   virtual void MoveConstant(Location destination, int32_t value) = 0;
221   virtual void MoveLocation(Location dst, Location src, DataType::Type dst_type) = 0;
222   virtual void AddLocationAsTemp(Location location, LocationSummary* locations) = 0;
223 
224   virtual Assembler* GetAssembler() = 0;
225   virtual const Assembler& GetAssembler() const = 0;
226   virtual size_t GetWordSize() const = 0;
227 
228   // Returns whether the target supports predicated SIMD instructions.
SupportsPredicatedSIMD()229   virtual bool SupportsPredicatedSIMD() const { return false; }
230 
231   // Get FP register width in bytes for spilling/restoring in the slow paths.
232   //
233   // Note: In SIMD graphs this should return SIMD register width as all FP and SIMD registers
234   // alias and live SIMD registers are forced to be spilled in full size in the slow paths.
GetSlowPathFPWidth()235   virtual size_t GetSlowPathFPWidth() const {
236     // Default implementation.
237     return GetCalleePreservedFPWidth();
238   }
239 
240   // Get FP register width required to be preserved by the target ABI.
241   virtual size_t GetCalleePreservedFPWidth() const  = 0;
242 
243   // Get the size of the target SIMD register in bytes.
244   virtual size_t GetSIMDRegisterWidth() const = 0;
245   virtual uintptr_t GetAddressOf(HBasicBlock* block) = 0;
246   void InitializeCodeGeneration(size_t number_of_spill_slots,
247                                 size_t maximum_safepoint_spill_size,
248                                 size_t number_of_out_slots,
249                                 const ArenaVector<HBasicBlock*>& block_order);
250   // Backends can override this as necessary. For most, no special alignment is required.
GetPreferredSlotsAlignment()251   virtual uint32_t GetPreferredSlotsAlignment() const { return 1; }
252 
GetFrameSize()253   uint32_t GetFrameSize() const { return frame_size_; }
SetFrameSize(uint32_t size)254   void SetFrameSize(uint32_t size) { frame_size_ = size; }
GetCoreSpillMask()255   uint32_t GetCoreSpillMask() const { return core_spill_mask_; }
GetFpuSpillMask()256   uint32_t GetFpuSpillMask() const { return fpu_spill_mask_; }
257 
GetNumberOfCoreRegisters()258   size_t GetNumberOfCoreRegisters() const { return number_of_core_registers_; }
GetNumberOfFloatingPointRegisters()259   size_t GetNumberOfFloatingPointRegisters() const { return number_of_fpu_registers_; }
260   virtual void SetupBlockedRegisters() const = 0;
261 
ComputeSpillMask()262   virtual void ComputeSpillMask() {
263     core_spill_mask_ = allocated_registers_.GetCoreRegisters() & core_callee_save_mask_;
264     DCHECK_NE(core_spill_mask_, 0u) << "At least the return address register must be saved";
265     fpu_spill_mask_ = allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_;
266   }
267 
ComputeRegisterMask(const int * registers,size_t length)268   static uint32_t ComputeRegisterMask(const int* registers, size_t length) {
269     uint32_t mask = 0;
270     for (size_t i = 0, e = length; i < e; ++i) {
271       mask |= (1 << registers[i]);
272     }
273     return mask;
274   }
275 
276   virtual void DumpCoreRegister(std::ostream& stream, int reg) const = 0;
277   virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const = 0;
278   virtual InstructionSet GetInstructionSet() const = 0;
279 
GetCompilerOptions()280   const CompilerOptions& GetCompilerOptions() const { return compiler_options_; }
281 
282   // Saves the register in the stack. Returns the size taken on stack.
283   virtual size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) = 0;
284   // Restores the register from the stack. Returns the size taken on stack.
285   virtual size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) = 0;
286 
287   virtual size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0;
288   virtual size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0;
289 
290   virtual bool NeedsTwoRegisters(DataType::Type type) const = 0;
291   // Returns whether we should split long moves in parallel moves.
ShouldSplitLongMoves()292   virtual bool ShouldSplitLongMoves() const { return false; }
293 
GetNumberOfCoreCalleeSaveRegisters()294   size_t GetNumberOfCoreCalleeSaveRegisters() const {
295     return POPCOUNT(core_callee_save_mask_);
296   }
297 
GetNumberOfCoreCallerSaveRegisters()298   size_t GetNumberOfCoreCallerSaveRegisters() const {
299     DCHECK_GE(GetNumberOfCoreRegisters(), GetNumberOfCoreCalleeSaveRegisters());
300     return GetNumberOfCoreRegisters() - GetNumberOfCoreCalleeSaveRegisters();
301   }
302 
IsCoreCalleeSaveRegister(int reg)303   bool IsCoreCalleeSaveRegister(int reg) const {
304     return (core_callee_save_mask_ & (1 << reg)) != 0;
305   }
306 
IsFloatingPointCalleeSaveRegister(int reg)307   bool IsFloatingPointCalleeSaveRegister(int reg) const {
308     return (fpu_callee_save_mask_ & (1 << reg)) != 0;
309   }
310 
GetSlowPathSpills(LocationSummary * locations,bool core_registers)311   uint32_t GetSlowPathSpills(LocationSummary* locations, bool core_registers) const {
312     DCHECK(locations->OnlyCallsOnSlowPath() ||
313            (locations->Intrinsified() && locations->CallsOnMainAndSlowPath() &&
314                !locations->HasCustomSlowPathCallingConvention()));
315     uint32_t live_registers = core_registers
316         ? locations->GetLiveRegisters()->GetCoreRegisters()
317         : locations->GetLiveRegisters()->GetFloatingPointRegisters();
318     if (locations->HasCustomSlowPathCallingConvention()) {
319       // Save only the live registers that the custom calling convention wants us to save.
320       uint32_t caller_saves = core_registers
321           ? locations->GetCustomSlowPathCallerSaves().GetCoreRegisters()
322           : locations->GetCustomSlowPathCallerSaves().GetFloatingPointRegisters();
323       return live_registers & caller_saves;
324     } else {
325       // Default ABI, we need to spill non-callee-save live registers.
326       uint32_t callee_saves = core_registers ? core_callee_save_mask_ : fpu_callee_save_mask_;
327       return live_registers & ~callee_saves;
328     }
329   }
330 
GetNumberOfSlowPathSpills(LocationSummary * locations,bool core_registers)331   size_t GetNumberOfSlowPathSpills(LocationSummary* locations, bool core_registers) const {
332     return POPCOUNT(GetSlowPathSpills(locations, core_registers));
333   }
334 
GetStackOffsetOfShouldDeoptimizeFlag()335   size_t GetStackOffsetOfShouldDeoptimizeFlag() const {
336     DCHECK(GetGraph()->HasShouldDeoptimizeFlag());
337     DCHECK_GE(GetFrameSize(), FrameEntrySpillSize() + kShouldDeoptimizeFlagSize);
338     return GetFrameSize() - FrameEntrySpillSize() - kShouldDeoptimizeFlagSize;
339   }
340 
341   // Record native to dex mapping for a suspend point. Required by runtime.
342   void RecordPcInfo(HInstruction* instruction,
343                     uint32_t dex_pc,
344                     uint32_t native_pc,
345                     SlowPathCode* slow_path = nullptr,
346                     bool native_debug_info = false);
347 
348   // Record native to dex mapping for a suspend point.
349   // The native_pc is used from Assembler::CodePosition.
350   //
351   // Note: As Assembler::CodePosition is target dependent, it does not guarantee the exact native_pc
352   // for the instruction. If the exact native_pc is required it must be provided explicitly.
353   void RecordPcInfo(HInstruction* instruction,
354                     uint32_t dex_pc,
355                     SlowPathCode* slow_path = nullptr,
356                     bool native_debug_info = false);
357 
358   // Check whether we have already recorded mapping at this PC.
359   bool HasStackMapAtCurrentPc();
360 
361   // Record extra stack maps if we support native debugging.
362   //
363   // ARM specific behaviour: The recorded native PC might be a branch over pools to instructions
364   // corresponding the dex PC.
365   void MaybeRecordNativeDebugInfo(HInstruction* instruction,
366                                   uint32_t dex_pc,
367                                   SlowPathCode* slow_path = nullptr);
368 
369   bool CanMoveNullCheckToUser(HNullCheck* null_check);
370   virtual void MaybeRecordImplicitNullCheck(HInstruction* instruction);
371   LocationSummary* CreateThrowingSlowPathLocations(
372       HInstruction* instruction, RegisterSet caller_saves = RegisterSet::Empty());
373   void GenerateNullCheck(HNullCheck* null_check);
374   virtual void GenerateImplicitNullCheck(HNullCheck* null_check) = 0;
375   virtual void GenerateExplicitNullCheck(HNullCheck* null_check) = 0;
376 
377   // Records a stack map which the runtime might use to set catch phi values
378   // during exception delivery.
379   // TODO: Replace with a catch-entering instruction that records the environment.
380   void RecordCatchBlockInfo();
381 
382   // Get the ScopedArenaAllocator used for codegen memory allocation.
383   ScopedArenaAllocator* GetScopedAllocator();
384 
385   void AddSlowPath(SlowPathCode* slow_path);
386 
387   ScopedArenaVector<uint8_t> BuildStackMaps(const dex::CodeItem* code_item_for_osr_check);
388   size_t GetNumberOfJitRoots() const;
389 
390   // Fills the `literals` array with literals collected during code generation.
391   // Also emits literal patches.
392   void EmitJitRoots(uint8_t* code,
393                     const uint8_t* roots_data,
394                     /*out*/std::vector<Handle<mirror::Object>>* roots)
395       REQUIRES_SHARED(Locks::mutator_lock_);
396 
IsLeafMethod()397   bool IsLeafMethod() const {
398     return is_leaf_;
399   }
400 
MarkNotLeaf()401   void MarkNotLeaf() {
402     is_leaf_ = false;
403     requires_current_method_ = true;
404   }
405 
NeedsSuspendCheckEntry()406   bool NeedsSuspendCheckEntry() const {
407     return needs_suspend_check_entry_;
408   }
409 
MarkNeedsSuspendCheckEntry()410   void MarkNeedsSuspendCheckEntry() {
411     needs_suspend_check_entry_ = true;
412   }
413 
SetRequiresCurrentMethod()414   void SetRequiresCurrentMethod() {
415     requires_current_method_ = true;
416   }
417 
RequiresCurrentMethod()418   bool RequiresCurrentMethod() const {
419     return requires_current_method_;
420   }
421 
422   // Clears the spill slots taken by loop phis in the `LocationSummary` of the
423   // suspend check. This is called when the code generator generates code
424   // for the suspend check at the back edge (instead of where the suspend check
425   // is, which is the loop entry). At this point, the spill slots for the phis
426   // have not been written to.
427   void ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend_check,
428                                              HParallelMove* spills) const;
429 
GetBlockedCoreRegisters()430   bool* GetBlockedCoreRegisters() const { return blocked_core_registers_; }
GetBlockedFloatingPointRegisters()431   bool* GetBlockedFloatingPointRegisters() const { return blocked_fpu_registers_; }
432 
IsBlockedCoreRegister(size_t i)433   bool IsBlockedCoreRegister(size_t i) { return blocked_core_registers_[i]; }
IsBlockedFloatingPointRegister(size_t i)434   bool IsBlockedFloatingPointRegister(size_t i) { return blocked_fpu_registers_[i]; }
435 
436   // Helper that returns the offset of the array's length field.
437   // Note: Besides the normal arrays, we also use the HArrayLength for
438   // accessing the String's `count` field in String intrinsics.
439   static uint32_t GetArrayLengthOffset(HArrayLength* array_length);
440 
441   // Helper that returns the offset of the array's data.
442   // Note: Besides the normal arrays, we also use the HArrayGet for
443   // accessing the String's `value` field in String intrinsics.
444   static uint32_t GetArrayDataOffset(HArrayGet* array_get);
445 
446   void EmitParallelMoves(Location from1,
447                          Location to1,
448                          DataType::Type type1,
449                          Location from2,
450                          Location to2,
451                          DataType::Type type2);
452 
InstanceOfNeedsReadBarrier(HInstanceOf * instance_of)453   static bool InstanceOfNeedsReadBarrier(HInstanceOf* instance_of) {
454     // Used only for kExactCheck, kAbstractClassCheck, kClassHierarchyCheck and kArrayObjectCheck.
455     DCHECK(instance_of->GetTypeCheckKind() == TypeCheckKind::kExactCheck ||
456            instance_of->GetTypeCheckKind() == TypeCheckKind::kAbstractClassCheck ||
457            instance_of->GetTypeCheckKind() == TypeCheckKind::kClassHierarchyCheck ||
458            instance_of->GetTypeCheckKind() == TypeCheckKind::kArrayObjectCheck)
459         << instance_of->GetTypeCheckKind();
460     // If the target class is in the boot image, it's non-moveable and it doesn't matter
461     // if we compare it with a from-space or to-space reference, the result is the same.
462     // It's OK to traverse a class hierarchy jumping between from-space and to-space.
463     return kEmitCompilerReadBarrier && !instance_of->GetTargetClass()->IsInBootImage();
464   }
465 
ReadBarrierOptionForInstanceOf(HInstanceOf * instance_of)466   static ReadBarrierOption ReadBarrierOptionForInstanceOf(HInstanceOf* instance_of) {
467     return InstanceOfNeedsReadBarrier(instance_of) ? kWithReadBarrier : kWithoutReadBarrier;
468   }
469 
IsTypeCheckSlowPathFatal(HCheckCast * check_cast)470   static bool IsTypeCheckSlowPathFatal(HCheckCast* check_cast) {
471     switch (check_cast->GetTypeCheckKind()) {
472       case TypeCheckKind::kExactCheck:
473       case TypeCheckKind::kAbstractClassCheck:
474       case TypeCheckKind::kClassHierarchyCheck:
475       case TypeCheckKind::kArrayObjectCheck:
476       case TypeCheckKind::kInterfaceCheck: {
477         bool needs_read_barrier =
478             kEmitCompilerReadBarrier && !check_cast->GetTargetClass()->IsInBootImage();
479         // We do not emit read barriers for HCheckCast, so we can get false negatives
480         // and the slow path shall re-check and simply return if the cast is actually OK.
481         return !needs_read_barrier;
482       }
483       case TypeCheckKind::kArrayCheck:
484       case TypeCheckKind::kUnresolvedCheck:
485         return false;
486       case TypeCheckKind::kBitstringCheck:
487         return true;
488     }
489     LOG(FATAL) << "Unreachable";
490     UNREACHABLE();
491   }
492 
GetCheckCastCallKind(HCheckCast * check_cast)493   static LocationSummary::CallKind GetCheckCastCallKind(HCheckCast* check_cast) {
494     return (IsTypeCheckSlowPathFatal(check_cast) && !check_cast->CanThrowIntoCatchBlock())
495         ? LocationSummary::kNoCall  // In fact, call on a fatal (non-returning) slow path.
496         : LocationSummary::kCallOnSlowPath;
497   }
498 
StoreNeedsWriteBarrier(DataType::Type type,HInstruction * value)499   static bool StoreNeedsWriteBarrier(DataType::Type type, HInstruction* value) {
500     // Check that null value is not represented as an integer constant.
501     DCHECK_IMPLIES(type == DataType::Type::kReference, !value->IsIntConstant());
502     return type == DataType::Type::kReference && !value->IsNullConstant();
503   }
504 
505 
506   // Performs checks pertaining to an InvokeRuntime call.
507   void ValidateInvokeRuntime(QuickEntrypointEnum entrypoint,
508                              HInstruction* instruction,
509                              SlowPathCode* slow_path);
510 
511   // Performs checks pertaining to an InvokeRuntimeWithoutRecordingPcInfo call.
512   static void ValidateInvokeRuntimeWithoutRecordingPcInfo(HInstruction* instruction,
513                                                           SlowPathCode* slow_path);
514 
AddAllocatedRegister(Location location)515   void AddAllocatedRegister(Location location) {
516     allocated_registers_.Add(location);
517   }
518 
HasAllocatedRegister(bool is_core,int reg)519   bool HasAllocatedRegister(bool is_core, int reg) const {
520     return is_core
521         ? allocated_registers_.ContainsCoreRegister(reg)
522         : allocated_registers_.ContainsFloatingPointRegister(reg);
523   }
524 
525   void AllocateLocations(HInstruction* instruction);
526 
527   // Tells whether the stack frame of the compiled method is
528   // considered "empty", that is either actually having a size of zero,
529   // or just containing the saved return address register.
HasEmptyFrame()530   bool HasEmptyFrame() const {
531     return GetFrameSize() == (CallPushesPC() ? GetWordSize() : 0);
532   }
533 
GetInt8ValueOf(HConstant * constant)534   static int8_t GetInt8ValueOf(HConstant* constant) {
535     DCHECK(constant->IsIntConstant());
536     return constant->AsIntConstant()->GetValue();
537   }
538 
GetInt16ValueOf(HConstant * constant)539   static int16_t GetInt16ValueOf(HConstant* constant) {
540     DCHECK(constant->IsIntConstant());
541     return constant->AsIntConstant()->GetValue();
542   }
543 
GetInt32ValueOf(HConstant * constant)544   static int32_t GetInt32ValueOf(HConstant* constant) {
545     if (constant->IsIntConstant()) {
546       return constant->AsIntConstant()->GetValue();
547     } else if (constant->IsNullConstant()) {
548       return 0;
549     } else {
550       DCHECK(constant->IsFloatConstant());
551       return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue());
552     }
553   }
554 
GetInt64ValueOf(HConstant * constant)555   static int64_t GetInt64ValueOf(HConstant* constant) {
556     if (constant->IsIntConstant()) {
557       return constant->AsIntConstant()->GetValue();
558     } else if (constant->IsNullConstant()) {
559       return 0;
560     } else if (constant->IsFloatConstant()) {
561       return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue());
562     } else if (constant->IsLongConstant()) {
563       return constant->AsLongConstant()->GetValue();
564     } else {
565       DCHECK(constant->IsDoubleConstant());
566       return bit_cast<int64_t, double>(constant->AsDoubleConstant()->GetValue());
567     }
568   }
569 
GetFirstRegisterSlotInSlowPath()570   size_t GetFirstRegisterSlotInSlowPath() const {
571     return first_register_slot_in_slow_path_;
572   }
573 
FrameEntrySpillSize()574   uint32_t FrameEntrySpillSize() const {
575     return GetFpuSpillSize() + GetCoreSpillSize();
576   }
577 
578   virtual ParallelMoveResolver* GetMoveResolver() = 0;
579 
580   static void CreateCommonInvokeLocationSummary(
581       HInvoke* invoke, InvokeDexCallingConventionVisitor* visitor);
582 
583   template <typename CriticalNativeCallingConventionVisitor,
584             size_t kNativeStackAlignment,
585             size_t GetCriticalNativeDirectCallFrameSize(const char* shorty, uint32_t shorty_len)>
PrepareCriticalNativeCall(HInvokeStaticOrDirect * invoke)586   size_t PrepareCriticalNativeCall(HInvokeStaticOrDirect* invoke) {
587       DCHECK(!invoke->GetLocations()->Intrinsified());
588       CriticalNativeCallingConventionVisitor calling_convention_visitor(
589           /*for_register_allocation=*/ false);
590       HParallelMove parallel_move(GetGraph()->GetAllocator());
591       PrepareCriticalNativeArgumentMoves(invoke, &calling_convention_visitor, &parallel_move);
592       size_t out_frame_size =
593           RoundUp(calling_convention_visitor.GetStackOffset(), kNativeStackAlignment);
594       if (kIsDebugBuild) {
595         uint32_t shorty_len;
596         const char* shorty = GetCriticalNativeShorty(invoke, &shorty_len);
597         DCHECK_EQ(GetCriticalNativeDirectCallFrameSize(shorty, shorty_len), out_frame_size);
598       }
599       if (out_frame_size != 0u) {
600         FinishCriticalNativeFrameSetup(out_frame_size, &parallel_move);
601       }
602       return out_frame_size;
603   }
604 
605   void GenerateInvokeStaticOrDirectRuntimeCall(
606       HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path);
607 
608   void GenerateInvokeUnresolvedRuntimeCall(HInvokeUnresolved* invoke);
609 
610   void GenerateInvokePolymorphicCall(HInvokePolymorphic* invoke, SlowPathCode* slow_path = nullptr);
611 
612   void GenerateInvokeCustomCall(HInvokeCustom* invoke);
613 
614   void CreateStringBuilderAppendLocations(HStringBuilderAppend* instruction, Location out);
615 
616   void CreateUnresolvedFieldLocationSummary(
617       HInstruction* field_access,
618       DataType::Type field_type,
619       const FieldAccessCallingConvention& calling_convention);
620 
621   void GenerateUnresolvedFieldAccess(
622       HInstruction* field_access,
623       DataType::Type field_type,
624       uint32_t field_index,
625       uint32_t dex_pc,
626       const FieldAccessCallingConvention& calling_convention);
627 
628   static void CreateLoadClassRuntimeCallLocationSummary(HLoadClass* cls,
629                                                         Location runtime_type_index_location,
630                                                         Location runtime_return_location);
631   void GenerateLoadClassRuntimeCall(HLoadClass* cls);
632 
633   static void CreateLoadMethodHandleRuntimeCallLocationSummary(HLoadMethodHandle* method_handle,
634                                                              Location runtime_handle_index_location,
635                                                              Location runtime_return_location);
636   void GenerateLoadMethodHandleRuntimeCall(HLoadMethodHandle* method_handle);
637 
638   static void CreateLoadMethodTypeRuntimeCallLocationSummary(HLoadMethodType* method_type,
639                                                              Location runtime_type_index_location,
640                                                              Location runtime_return_location);
641   void GenerateLoadMethodTypeRuntimeCall(HLoadMethodType* method_type);
642 
643   static uint32_t GetBootImageOffset(ObjPtr<mirror::Object> object)
644       REQUIRES_SHARED(Locks::mutator_lock_);
645   static uint32_t GetBootImageOffset(HLoadClass* load_class);
646   static uint32_t GetBootImageOffset(HLoadString* load_string);
647   static uint32_t GetBootImageOffset(HInvoke* invoke);
648   static uint32_t GetBootImageOffset(ClassRoot class_root);
649   static uint32_t GetBootImageOffsetOfIntrinsicDeclaringClass(HInvoke* invoke);
650 
651   static void CreateSystemArrayCopyLocationSummary(HInvoke* invoke);
652 
SetDisassemblyInformation(DisassemblyInformation * info)653   void SetDisassemblyInformation(DisassemblyInformation* info) { disasm_info_ = info; }
GetDisassemblyInformation()654   DisassemblyInformation* GetDisassemblyInformation() const { return disasm_info_; }
655 
656   virtual void InvokeRuntime(QuickEntrypointEnum entrypoint,
657                              HInstruction* instruction,
658                              uint32_t dex_pc,
659                              SlowPathCode* slow_path = nullptr) = 0;
660 
661   // Check if the desired_string_load_kind is supported. If it is, return it,
662   // otherwise return a fall-back kind that should be used instead.
663   virtual HLoadString::LoadKind GetSupportedLoadStringKind(
664       HLoadString::LoadKind desired_string_load_kind) = 0;
665 
666   // Check if the desired_class_load_kind is supported. If it is, return it,
667   // otherwise return a fall-back kind that should be used instead.
668   virtual HLoadClass::LoadKind GetSupportedLoadClassKind(
669       HLoadClass::LoadKind desired_class_load_kind) = 0;
670 
GetLoadStringCallKind(HLoadString * load)671   static LocationSummary::CallKind GetLoadStringCallKind(HLoadString* load) {
672     switch (load->GetLoadKind()) {
673       case HLoadString::LoadKind::kBssEntry:
674         DCHECK(load->NeedsEnvironment());
675         return LocationSummary::kCallOnSlowPath;
676       case HLoadString::LoadKind::kRuntimeCall:
677         DCHECK(load->NeedsEnvironment());
678         return LocationSummary::kCallOnMainOnly;
679       case HLoadString::LoadKind::kJitTableAddress:
680         DCHECK(!load->NeedsEnvironment());
681         return kEmitCompilerReadBarrier
682             ? LocationSummary::kCallOnSlowPath
683             : LocationSummary::kNoCall;
684         break;
685       default:
686         DCHECK(!load->NeedsEnvironment());
687         return LocationSummary::kNoCall;
688     }
689   }
690 
691   // Check if the desired_dispatch_info is supported. If it is, return it,
692   // otherwise return a fall-back info that should be used instead.
693   virtual HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
694       const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
695       ArtMethod* method) = 0;
696 
697   // Generate a call to a static or direct method.
698   virtual void GenerateStaticOrDirectCall(
699       HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) = 0;
700   // Generate a call to a virtual method.
701   virtual void GenerateVirtualCall(
702       HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) = 0;
703 
704   // Copy the result of a call into the given target.
705   virtual void MoveFromReturnRegister(Location trg, DataType::Type type) = 0;
706 
707   virtual void IncreaseFrame(size_t adjustment) = 0;
708   virtual void DecreaseFrame(size_t adjustment) = 0;
709 
710   virtual void GenerateNop() = 0;
711 
712   static QuickEntrypointEnum GetArrayAllocationEntrypoint(HNewArray* new_array);
713   static ScaleFactor ScaleFactorForType(DataType::Type type);
714 
715  protected:
716   // Patch info used for recording locations of required linker patches and their targets,
717   // i.e. target method, string, type or code identified by their dex file and index,
718   // or .data.bimg.rel.ro entries identified by the boot image offset.
719   template <typename LabelType>
720   struct PatchInfo {
PatchInfoPatchInfo721     PatchInfo(const DexFile* dex_file, uint32_t off_or_idx)
722         : target_dex_file(dex_file), offset_or_index(off_or_idx), label() { }
723 
724     // Target dex file or null for .data.bmig.rel.ro patches.
725     const DexFile* target_dex_file;
726     // Either the boot image offset (to write to .data.bmig.rel.ro) or string/type/method index.
727     uint32_t offset_or_index;
728     // Label for the instruction to patch.
729     LabelType label;
730   };
731 
732   CodeGenerator(HGraph* graph,
733                 size_t number_of_core_registers,
734                 size_t number_of_fpu_registers,
735                 size_t number_of_register_pairs,
736                 uint32_t core_callee_save_mask,
737                 uint32_t fpu_callee_save_mask,
738                 const CompilerOptions& compiler_options,
739                 OptimizingCompilerStats* stats);
740 
741   virtual HGraphVisitor* GetLocationBuilder() = 0;
742   virtual HGraphVisitor* GetInstructionVisitor() = 0;
743 
744   // Returns the location of the first spilled entry for floating point registers,
745   // relative to the stack pointer.
GetFpuSpillStart()746   uint32_t GetFpuSpillStart() const {
747     return GetFrameSize() - FrameEntrySpillSize();
748   }
749 
GetFpuSpillSize()750   uint32_t GetFpuSpillSize() const {
751     return POPCOUNT(fpu_spill_mask_) * GetCalleePreservedFPWidth();
752   }
753 
GetCoreSpillSize()754   uint32_t GetCoreSpillSize() const {
755     return POPCOUNT(core_spill_mask_) * GetWordSize();
756   }
757 
HasAllocatedCalleeSaveRegisters()758   virtual bool HasAllocatedCalleeSaveRegisters() const {
759     // We check the core registers against 1 because it always comprises the return PC.
760     return (POPCOUNT(allocated_registers_.GetCoreRegisters() & core_callee_save_mask_) != 1)
761       || (POPCOUNT(allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_) != 0);
762   }
763 
CallPushesPC()764   bool CallPushesPC() const {
765     InstructionSet instruction_set = GetInstructionSet();
766     return instruction_set == InstructionSet::kX86 || instruction_set == InstructionSet::kX86_64;
767   }
768 
769   // Arm64 has its own type for a label, so we need to templatize these methods
770   // to share the logic.
771 
772   template <typename LabelType>
CommonInitializeLabels()773   LabelType* CommonInitializeLabels() {
774     // We use raw array allocations instead of ArenaVector<> because Labels are
775     // non-constructible and non-movable and as such cannot be held in a vector.
776     size_t size = GetGraph()->GetBlocks().size();
777     LabelType* labels =
778         GetGraph()->GetAllocator()->AllocArray<LabelType>(size, kArenaAllocCodeGenerator);
779     for (size_t i = 0; i != size; ++i) {
780       new(labels + i) LabelType();
781     }
782     return labels;
783   }
784 
785   template <typename LabelType>
CommonGetLabelOf(LabelType * raw_pointer_to_labels_array,HBasicBlock * block)786   LabelType* CommonGetLabelOf(LabelType* raw_pointer_to_labels_array, HBasicBlock* block) const {
787     block = FirstNonEmptyBlock(block);
788     return raw_pointer_to_labels_array + block->GetBlockId();
789   }
790 
GetCurrentSlowPath()791   SlowPathCode* GetCurrentSlowPath() {
792     return current_slow_path_;
793   }
794 
795   StackMapStream* GetStackMapStream();
796 
797   void ReserveJitStringRoot(StringReference string_reference, Handle<mirror::String> string);
798   uint64_t GetJitStringRootIndex(StringReference string_reference);
799   void ReserveJitClassRoot(TypeReference type_reference, Handle<mirror::Class> klass);
800   uint64_t GetJitClassRootIndex(TypeReference type_reference);
801 
802   // Emit the patches assocatied with JIT roots. Only applies to JIT compiled code.
803   virtual void EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data);
804 
805   // Frame size required for this method.
806   uint32_t frame_size_;
807   uint32_t core_spill_mask_;
808   uint32_t fpu_spill_mask_;
809   uint32_t first_register_slot_in_slow_path_;
810 
811   // Registers that were allocated during linear scan.
812   RegisterSet allocated_registers_;
813 
814   // Arrays used when doing register allocation to know which
815   // registers we can allocate. `SetupBlockedRegisters` updates the
816   // arrays.
817   bool* const blocked_core_registers_;
818   bool* const blocked_fpu_registers_;
819   size_t number_of_core_registers_;
820   size_t number_of_fpu_registers_;
821   size_t number_of_register_pairs_;
822   const uint32_t core_callee_save_mask_;
823   const uint32_t fpu_callee_save_mask_;
824 
825   // The order to use for code generation.
826   const ArenaVector<HBasicBlock*>* block_order_;
827 
828   DisassemblyInformation* disasm_info_;
829 
830  private:
831   class CodeGenerationData;
832 
833   void InitializeCodeGenerationData();
834   size_t GetStackOffsetOfSavedRegister(size_t index);
835   void GenerateSlowPaths();
836   void BlockIfInRegister(Location location, bool is_out = false) const;
837   void EmitEnvironment(HEnvironment* environment,
838                        SlowPathCode* slow_path,
839                        bool needs_vreg_info = true);
840   void EmitVRegInfo(HEnvironment* environment, SlowPathCode* slow_path);
841 
842   static void PrepareCriticalNativeArgumentMoves(
843       HInvokeStaticOrDirect* invoke,
844       /*inout*/InvokeDexCallingConventionVisitor* visitor,
845       /*out*/HParallelMove* parallel_move);
846 
847   void FinishCriticalNativeFrameSetup(size_t out_frame_size, /*inout*/HParallelMove* parallel_move);
848 
849   static const char* GetCriticalNativeShorty(HInvokeStaticOrDirect* invoke, uint32_t* shorty_len);
850 
851   OptimizingCompilerStats* stats_;
852 
853   HGraph* const graph_;
854   const CompilerOptions& compiler_options_;
855 
856   // The current slow-path that we're generating code for.
857   SlowPathCode* current_slow_path_;
858 
859   // The current block index in `block_order_` of the block
860   // we are generating code for.
861   size_t current_block_index_;
862 
863   // Whether the method is a leaf method.
864   bool is_leaf_;
865 
866   // Whether the method has to emit a SuspendCheck at entry.
867   bool needs_suspend_check_entry_;
868 
869   // Whether an instruction in the graph accesses the current method.
870   // TODO: Rename: this actually indicates that some instruction in the method
871   // needs the environment including a valid stack frame.
872   bool requires_current_method_;
873 
874   // The CodeGenerationData contains a ScopedArenaAllocator intended for reusing the
875   // ArenaStack memory allocated in previous passes instead of adding to the memory
876   // held by the ArenaAllocator. This ScopedArenaAllocator is created in
877   // CodeGenerator::Compile() and remains alive until the CodeGenerator is destroyed.
878   std::unique_ptr<CodeGenerationData> code_generation_data_;
879 
880   friend class OptimizingCFITest;
881   ART_FRIEND_TEST(CodegenTest, ARM64FrameSizeSIMD);
882   ART_FRIEND_TEST(CodegenTest, ARM64FrameSizeNoSIMD);
883 
884   DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
885 };
886 
887 template <typename C, typename F>
888 class CallingConvention {
889  public:
CallingConvention(const C * registers,size_t number_of_registers,const F * fpu_registers,size_t number_of_fpu_registers,PointerSize pointer_size)890   CallingConvention(const C* registers,
891                     size_t number_of_registers,
892                     const F* fpu_registers,
893                     size_t number_of_fpu_registers,
894                     PointerSize pointer_size)
895       : registers_(registers),
896         number_of_registers_(number_of_registers),
897         fpu_registers_(fpu_registers),
898         number_of_fpu_registers_(number_of_fpu_registers),
899         pointer_size_(pointer_size) {}
900 
GetNumberOfRegisters()901   size_t GetNumberOfRegisters() const { return number_of_registers_; }
GetNumberOfFpuRegisters()902   size_t GetNumberOfFpuRegisters() const { return number_of_fpu_registers_; }
903 
GetRegisterAt(size_t index)904   C GetRegisterAt(size_t index) const {
905     DCHECK_LT(index, number_of_registers_);
906     return registers_[index];
907   }
908 
GetFpuRegisterAt(size_t index)909   F GetFpuRegisterAt(size_t index) const {
910     DCHECK_LT(index, number_of_fpu_registers_);
911     return fpu_registers_[index];
912   }
913 
GetStackOffsetOf(size_t index)914   size_t GetStackOffsetOf(size_t index) const {
915     // We still reserve the space for parameters passed by registers.
916     // Add space for the method pointer.
917     return static_cast<size_t>(pointer_size_) + index * kVRegSize;
918   }
919 
920  private:
921   const C* registers_;
922   const size_t number_of_registers_;
923   const F* fpu_registers_;
924   const size_t number_of_fpu_registers_;
925   const PointerSize pointer_size_;
926 
927   DISALLOW_COPY_AND_ASSIGN(CallingConvention);
928 };
929 
930 /**
931  * A templated class SlowPathGenerator with a templated method NewSlowPath()
932  * that can be used by any code generator to share equivalent slow-paths with
933  * the objective of reducing generated code size.
934  *
935  * InstructionType:  instruction that requires SlowPathCodeType
936  * SlowPathCodeType: subclass of SlowPathCode, with constructor SlowPathCodeType(InstructionType *)
937  */
938 template <typename InstructionType>
939 class SlowPathGenerator {
940   static_assert(std::is_base_of<HInstruction, InstructionType>::value,
941                 "InstructionType is not a subclass of art::HInstruction");
942 
943  public:
SlowPathGenerator(HGraph * graph,CodeGenerator * codegen)944   SlowPathGenerator(HGraph* graph, CodeGenerator* codegen)
945       : graph_(graph),
946         codegen_(codegen),
947         slow_path_map_(std::less<uint32_t>(),
948                        graph->GetAllocator()->Adapter(kArenaAllocSlowPaths)) {}
949 
950   // Creates and adds a new slow-path, if needed, or returns existing one otherwise.
951   // Templating the method (rather than the whole class) on the slow-path type enables
952   // keeping this code at a generic, non architecture-specific place.
953   //
954   // NOTE: This approach assumes each InstructionType only generates one SlowPathCodeType.
955   //       To relax this requirement, we would need some RTTI on the stored slow-paths,
956   //       or template the class as a whole on SlowPathType.
957   template <typename SlowPathCodeType>
NewSlowPath(InstructionType * instruction)958   SlowPathCodeType* NewSlowPath(InstructionType* instruction) {
959     static_assert(std::is_base_of<SlowPathCode, SlowPathCodeType>::value,
960                   "SlowPathCodeType is not a subclass of art::SlowPathCode");
961     static_assert(std::is_constructible<SlowPathCodeType, InstructionType*>::value,
962                   "SlowPathCodeType is not constructible from InstructionType*");
963     // Iterate over potential candidates for sharing. Currently, only same-typed
964     // slow-paths with exactly the same dex-pc are viable candidates.
965     // TODO: pass dex-pc/slow-path-type to run-time to allow even more sharing?
966     const uint32_t dex_pc = instruction->GetDexPc();
967     auto iter = slow_path_map_.find(dex_pc);
968     if (iter != slow_path_map_.end()) {
969       const ArenaVector<std::pair<InstructionType*, SlowPathCode*>>& candidates = iter->second;
970       for (const auto& it : candidates) {
971         InstructionType* other_instruction = it.first;
972         SlowPathCodeType* other_slow_path = down_cast<SlowPathCodeType*>(it.second);
973         // Determine if the instructions allow for slow-path sharing.
974         if (HaveSameLiveRegisters(instruction, other_instruction) &&
975             HaveSameStackMap(instruction, other_instruction)) {
976           // Can share: reuse existing one.
977           return other_slow_path;
978         }
979       }
980     } else {
981       // First time this dex-pc is seen.
982       iter = slow_path_map_.Put(dex_pc,
983                                 {{}, {graph_->GetAllocator()->Adapter(kArenaAllocSlowPaths)}});
984     }
985     // Cannot share: create and add new slow-path for this particular dex-pc.
986     SlowPathCodeType* slow_path =
987         new (codegen_->GetScopedAllocator()) SlowPathCodeType(instruction);
988     iter->second.emplace_back(std::make_pair(instruction, slow_path));
989     codegen_->AddSlowPath(slow_path);
990     return slow_path;
991   }
992 
993  private:
994   // Tests if both instructions have same set of live physical registers. This ensures
995   // the slow-path has exactly the same preamble on saving these registers to stack.
HaveSameLiveRegisters(const InstructionType * i1,const InstructionType * i2)996   bool HaveSameLiveRegisters(const InstructionType* i1, const InstructionType* i2) const {
997     const uint32_t core_spill = ~codegen_->GetCoreSpillMask();
998     const uint32_t fpu_spill = ~codegen_->GetFpuSpillMask();
999     RegisterSet* live1 = i1->GetLocations()->GetLiveRegisters();
1000     RegisterSet* live2 = i2->GetLocations()->GetLiveRegisters();
1001     return (((live1->GetCoreRegisters() & core_spill) ==
1002              (live2->GetCoreRegisters() & core_spill)) &&
1003             ((live1->GetFloatingPointRegisters() & fpu_spill) ==
1004              (live2->GetFloatingPointRegisters() & fpu_spill)));
1005   }
1006 
1007   // Tests if both instructions have the same stack map. This ensures the interpreter
1008   // will find exactly the same dex-registers at the same entries.
HaveSameStackMap(const InstructionType * i1,const InstructionType * i2)1009   bool HaveSameStackMap(const InstructionType* i1, const InstructionType* i2) const {
1010     DCHECK(i1->HasEnvironment());
1011     DCHECK(i2->HasEnvironment());
1012     // We conservatively test if the two instructions find exactly the same instructions
1013     // and location in each dex-register. This guarantees they will have the same stack map.
1014     HEnvironment* e1 = i1->GetEnvironment();
1015     HEnvironment* e2 = i2->GetEnvironment();
1016     if (e1->GetParent() != e2->GetParent() || e1->Size() != e2->Size()) {
1017       return false;
1018     }
1019     for (size_t i = 0, sz = e1->Size(); i < sz; ++i) {
1020       if (e1->GetInstructionAt(i) != e2->GetInstructionAt(i) ||
1021           !e1->GetLocationAt(i).Equals(e2->GetLocationAt(i))) {
1022         return false;
1023       }
1024     }
1025     return true;
1026   }
1027 
1028   HGraph* const graph_;
1029   CodeGenerator* const codegen_;
1030 
1031   // Map from dex-pc to vector of already existing instruction/slow-path pairs.
1032   ArenaSafeMap<uint32_t, ArenaVector<std::pair<InstructionType*, SlowPathCode*>>> slow_path_map_;
1033 
1034   DISALLOW_COPY_AND_ASSIGN(SlowPathGenerator);
1035 };
1036 
1037 class InstructionCodeGenerator : public HGraphVisitor {
1038  public:
InstructionCodeGenerator(HGraph * graph,CodeGenerator * codegen)1039   InstructionCodeGenerator(HGraph* graph, CodeGenerator* codegen)
1040       : HGraphVisitor(graph),
1041         deopt_slow_paths_(graph, codegen) {}
1042 
1043  protected:
1044   // Add slow-path generator for each instruction/slow-path combination that desires sharing.
1045   // TODO: under current regime, only deopt sharing make sense; extend later.
1046   SlowPathGenerator<HDeoptimize> deopt_slow_paths_;
1047 };
1048 
1049 }  // namespace art
1050 
1051 #endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
1052