Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2011 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_UTILS_JNI_MACRO_ASSEMBLER_H_
     18 #define ART_COMPILER_UTILS_JNI_MACRO_ASSEMBLER_H_
     19 
     20 #include <vector>
     21 
     22 #include "arch/instruction_set.h"
     23 #include "base/arena_allocator.h"
     24 #include "base/arena_object.h"
     25 #include "base/array_ref.h"
     26 #include "base/enums.h"
     27 #include "base/logging.h"
     28 #include "base/macros.h"
     29 #include "managed_register.h"
     30 #include "offsets.h"
     31 
     32 namespace art {
     33 
     34 class ArenaAllocator;
     35 class DebugFrameOpCodeWriterForAssembler;
     36 class InstructionSetFeatures;
     37 class MemoryRegion;
     38 class JNIMacroLabel;
     39 
     40 enum class JNIMacroUnaryCondition {
     41   kZero,
     42   kNotZero
     43 };
     44 
     45 template <PointerSize kPointerSize>
     46 class JNIMacroAssembler : public DeletableArenaObject<kArenaAllocAssembler> {
     47  public:
     48   static std::unique_ptr<JNIMacroAssembler<kPointerSize>> Create(
     49       ArenaAllocator* arena,
     50       InstructionSet instruction_set,
     51       const InstructionSetFeatures* instruction_set_features = nullptr);
     52 
     53   // Finalize the code; emit slow paths, fixup branches, add literal pool, etc.
     54   virtual void FinalizeCode() = 0;
     55 
     56   // Size of generated code
     57   virtual size_t CodeSize() const = 0;
     58 
     59   // Copy instructions out of assembly buffer into the given region of memory
     60   virtual void FinalizeInstructions(const MemoryRegion& region) = 0;
     61 
     62   // Emit code that will create an activation on the stack
     63   virtual void BuildFrame(size_t frame_size,
     64                           ManagedRegister method_reg,
     65                           ArrayRef<const ManagedRegister> callee_save_regs,
     66                           const ManagedRegisterEntrySpills& entry_spills) = 0;
     67 
     68   // Emit code that will remove an activation from the stack
     69   virtual void RemoveFrame(size_t frame_size, ArrayRef<const ManagedRegister> callee_save_regs) = 0;
     70 
     71   virtual void IncreaseFrameSize(size_t adjust) = 0;
     72   virtual void DecreaseFrameSize(size_t adjust) = 0;
     73 
     74   // Store routines
     75   virtual void Store(FrameOffset offs, ManagedRegister src, size_t size) = 0;
     76   virtual void StoreRef(FrameOffset dest, ManagedRegister src) = 0;
     77   virtual void StoreRawPtr(FrameOffset dest, ManagedRegister src) = 0;
     78 
     79   virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) = 0;
     80 
     81   virtual void StoreStackOffsetToThread(ThreadOffset<kPointerSize> thr_offs,
     82                                         FrameOffset fr_offs,
     83                                         ManagedRegister scratch) = 0;
     84 
     85   virtual void StoreStackPointerToThread(ThreadOffset<kPointerSize> thr_offs) = 0;
     86 
     87   virtual void StoreSpanning(FrameOffset dest,
     88                              ManagedRegister src,
     89                              FrameOffset in_off,
     90                              ManagedRegister scratch) = 0;
     91 
     92   // Load routines
     93   virtual void Load(ManagedRegister dest, FrameOffset src, size_t size) = 0;
     94 
     95   virtual void LoadFromThread(ManagedRegister dest,
     96                               ThreadOffset<kPointerSize> src,
     97                               size_t size) = 0;
     98 
     99   virtual void LoadRef(ManagedRegister dest, FrameOffset src) = 0;
    100   // If unpoison_reference is true and kPoisonReference is true, then we negate the read reference.
    101   virtual void LoadRef(ManagedRegister dest,
    102                        ManagedRegister base,
    103                        MemberOffset offs,
    104                        bool unpoison_reference) = 0;
    105 
    106   virtual void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) = 0;
    107 
    108   virtual void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset<kPointerSize> offs) = 0;
    109 
    110   // Copying routines
    111   virtual void Move(ManagedRegister dest, ManagedRegister src, size_t size) = 0;
    112 
    113   virtual void CopyRawPtrFromThread(FrameOffset fr_offs,
    114                                     ThreadOffset<kPointerSize> thr_offs,
    115                                     ManagedRegister scratch) = 0;
    116 
    117   virtual void CopyRawPtrToThread(ThreadOffset<kPointerSize> thr_offs,
    118                                   FrameOffset fr_offs,
    119                                   ManagedRegister scratch) = 0;
    120 
    121   virtual void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) = 0;
    122 
    123   virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) = 0;
    124 
    125   virtual void Copy(FrameOffset dest,
    126                     ManagedRegister src_base,
    127                     Offset src_offset,
    128                     ManagedRegister scratch,
    129                     size_t size) = 0;
    130 
    131   virtual void Copy(ManagedRegister dest_base,
    132                     Offset dest_offset,
    133                     FrameOffset src,
    134                     ManagedRegister scratch,
    135                     size_t size) = 0;
    136 
    137   virtual void Copy(FrameOffset dest,
    138                     FrameOffset src_base,
    139                     Offset src_offset,
    140                     ManagedRegister scratch,
    141                     size_t size) = 0;
    142 
    143   virtual void Copy(ManagedRegister dest,
    144                     Offset dest_offset,
    145                     ManagedRegister src,
    146                     Offset src_offset,
    147                     ManagedRegister scratch,
    148                     size_t size) = 0;
    149 
    150   virtual void Copy(FrameOffset dest,
    151                     Offset dest_offset,
    152                     FrameOffset src,
    153                     Offset src_offset,
    154                     ManagedRegister scratch,
    155                     size_t size) = 0;
    156 
    157   virtual void MemoryBarrier(ManagedRegister scratch) = 0;
    158 
    159   // Sign extension
    160   virtual void SignExtend(ManagedRegister mreg, size_t size) = 0;
    161 
    162   // Zero extension
    163   virtual void ZeroExtend(ManagedRegister mreg, size_t size) = 0;
    164 
    165   // Exploit fast access in managed code to Thread::Current()
    166   virtual void GetCurrentThread(ManagedRegister tr) = 0;
    167   virtual void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) = 0;
    168 
    169   // Set up out_reg to hold a Object** into the handle scope, or to be null if the
    170   // value is null and null_allowed. in_reg holds a possibly stale reference
    171   // that can be used to avoid loading the handle scope entry to see if the value is
    172   // null.
    173   virtual void CreateHandleScopeEntry(ManagedRegister out_reg,
    174                                       FrameOffset handlescope_offset,
    175                                       ManagedRegister in_reg,
    176                                       bool null_allowed) = 0;
    177 
    178   // Set up out_off to hold a Object** into the handle scope, or to be null if the
    179   // value is null and null_allowed.
    180   virtual void CreateHandleScopeEntry(FrameOffset out_off,
    181                                       FrameOffset handlescope_offset,
    182                                       ManagedRegister scratch,
    183                                       bool null_allowed) = 0;
    184 
    185   // src holds a handle scope entry (Object**) load this into dst
    186   virtual void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) = 0;
    187 
    188   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
    189   // know that src may not be null.
    190   virtual void VerifyObject(ManagedRegister src, bool could_be_null) = 0;
    191   virtual void VerifyObject(FrameOffset src, bool could_be_null) = 0;
    192 
    193   // Call to address held at [base+offset]
    194   virtual void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) = 0;
    195   virtual void Call(FrameOffset base, Offset offset, ManagedRegister scratch) = 0;
    196   virtual void CallFromThread(ThreadOffset<kPointerSize> offset, ManagedRegister scratch) = 0;
    197 
    198   // Generate code to check if Thread::Current()->exception_ is non-null
    199   // and branch to a ExceptionSlowPath if it is.
    200   virtual void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) = 0;
    201 
    202   // Create a new label that can be used with Jump/Bind calls.
    203   virtual std::unique_ptr<JNIMacroLabel> CreateLabel() = 0;
    204   // Emit an unconditional jump to the label.
    205   virtual void Jump(JNIMacroLabel* label) = 0;
    206   // Emit a conditional jump to the label by applying a unary condition test to the register.
    207   virtual void Jump(JNIMacroLabel* label, JNIMacroUnaryCondition cond, ManagedRegister test) = 0;
    208   // Code at this offset will serve as the target for the Jump call.
    209   virtual void Bind(JNIMacroLabel* label) = 0;
    210 
    211   virtual ~JNIMacroAssembler() {}
    212 
    213   /**
    214    * @brief Buffer of DWARF's Call Frame Information opcodes.
    215    * @details It is used by debuggers and other tools to unwind the call stack.
    216    */
    217   virtual DebugFrameOpCodeWriterForAssembler& cfi() = 0;
    218 
    219  protected:
    220   explicit JNIMacroAssembler() {}
    221 };
    222 
    223 // A "Label" class used with the JNIMacroAssembler
    224 // allowing one to use branches (jumping from one place to another).
    225 //
    226 // This is just an interface, so every platform must provide
    227 // its own implementation of it.
    228 //
    229 // It is only safe to use a label created
    230 // via JNIMacroAssembler::CreateLabel with that same macro assembler.
    231 class JNIMacroLabel {
    232  public:
    233   virtual ~JNIMacroLabel() = 0;
    234 
    235   const InstructionSet isa_;
    236  protected:
    237   explicit JNIMacroLabel(InstructionSet isa) : isa_(isa) {}
    238 };
    239 
    240 inline JNIMacroLabel::~JNIMacroLabel() {
    241   // Compulsory definition for a pure virtual destructor
    242   // to avoid linking errors.
    243 }
    244 
    245 template <typename T, PointerSize kPointerSize>
    246 class JNIMacroAssemblerFwd : public JNIMacroAssembler<kPointerSize> {
    247  public:
    248   void FinalizeCode() OVERRIDE {
    249     asm_.FinalizeCode();
    250   }
    251 
    252   size_t CodeSize() const OVERRIDE {
    253     return asm_.CodeSize();
    254   }
    255 
    256   void FinalizeInstructions(const MemoryRegion& region) OVERRIDE {
    257     asm_.FinalizeInstructions(region);
    258   }
    259 
    260   DebugFrameOpCodeWriterForAssembler& cfi() OVERRIDE {
    261     return asm_.cfi();
    262   }
    263 
    264  protected:
    265   explicit JNIMacroAssemblerFwd(ArenaAllocator* arena) : asm_(arena) {}
    266 
    267   T asm_;
    268 };
    269 
    270 template <typename Self, typename PlatformLabel, InstructionSet kIsa>
    271 class JNIMacroLabelCommon : public JNIMacroLabel {
    272  public:
    273   static Self* Cast(JNIMacroLabel* label) {
    274     CHECK(label != nullptr);
    275     CHECK_EQ(kIsa, label->isa_);
    276 
    277     return reinterpret_cast<Self*>(label);
    278   }
    279 
    280  protected:
    281   PlatformLabel* AsPlatformLabel() {
    282     return &label_;
    283   }
    284 
    285   JNIMacroLabelCommon() : JNIMacroLabel(kIsa) {
    286   }
    287 
    288   virtual ~JNIMacroLabelCommon() OVERRIDE {}
    289 
    290  private:
    291   PlatformLabel label_;
    292 };
    293 
    294 }  // namespace art
    295 
    296 #endif  // ART_COMPILER_UTILS_JNI_MACRO_ASSEMBLER_H_
    297