Home | History | Annotate | Download | only in arm
      1 /*
      2  * Copyright (C) 2015 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_LINKER_ARM_RELATIVE_PATCHER_ARM_BASE_H_
     18 #define ART_COMPILER_LINKER_ARM_RELATIVE_PATCHER_ARM_BASE_H_
     19 
     20 #include <deque>
     21 #include <vector>
     22 
     23 #include "linker/relative_patcher.h"
     24 #include "method_reference.h"
     25 #include "safe_map.h"
     26 
     27 namespace art {
     28 namespace linker {
     29 
     30 class ArmBaseRelativePatcher : public RelativePatcher {
     31  public:
     32   uint32_t ReserveSpace(uint32_t offset,
     33                         const CompiledMethod* compiled_method,
     34                         MethodReference method_ref) OVERRIDE;
     35   uint32_t ReserveSpaceEnd(uint32_t offset) OVERRIDE;
     36   uint32_t WriteThunks(OutputStream* out, uint32_t offset) OVERRIDE;
     37 
     38  protected:
     39   ArmBaseRelativePatcher(RelativePatcherTargetProvider* provider,
     40                          InstructionSet instruction_set);
     41   ~ArmBaseRelativePatcher();
     42 
     43   enum class ThunkType {
     44     kMethodCall,              // Method call thunk.
     45     kBakerReadBarrier,        // Baker read barrier.
     46   };
     47 
     48   class ThunkKey {
     49    public:
     50     explicit ThunkKey(ThunkType type, uint32_t custom_value1 = 0u, uint32_t custom_value2 = 0u)
     51         : type_(type), custom_value1_(custom_value1), custom_value2_(custom_value2) { }
     52 
     53     ThunkType GetType() const {
     54       return type_;
     55     }
     56 
     57     uint32_t GetCustomValue1() const {
     58       return custom_value1_;
     59     }
     60 
     61     uint32_t GetCustomValue2() const {
     62       return custom_value2_;
     63     }
     64 
     65    private:
     66     ThunkType type_;
     67     uint32_t custom_value1_;
     68     uint32_t custom_value2_;
     69   };
     70 
     71   class ThunkKeyCompare {
     72    public:
     73     bool operator()(const ThunkKey& lhs, const ThunkKey& rhs) const {
     74       if (lhs.GetType() != rhs.GetType()) {
     75         return lhs.GetType() < rhs.GetType();
     76       }
     77       if (lhs.GetCustomValue1() != rhs.GetCustomValue1()) {
     78         return lhs.GetCustomValue1() < rhs.GetCustomValue1();
     79       }
     80       return lhs.GetCustomValue2() < rhs.GetCustomValue2();
     81     }
     82   };
     83 
     84   static ThunkKey GetMethodCallKey();
     85   static ThunkKey GetBakerThunkKey(const LinkerPatch& patch);
     86 
     87   uint32_t ReserveSpaceInternal(uint32_t offset,
     88                                 const CompiledMethod* compiled_method,
     89                                 MethodReference method_ref,
     90                                 uint32_t max_extra_space);
     91   uint32_t GetThunkTargetOffset(const ThunkKey& key, uint32_t patch_offset);
     92 
     93   uint32_t CalculateMethodCallDisplacement(uint32_t patch_offset,
     94                                            uint32_t target_offset);
     95 
     96   virtual std::vector<uint8_t> CompileThunk(const ThunkKey& key) = 0;
     97   virtual uint32_t MaxPositiveDisplacement(const ThunkKey& key) = 0;
     98   virtual uint32_t MaxNegativeDisplacement(const ThunkKey& key) = 0;
     99 
    100  private:
    101   class ThunkData;
    102 
    103   void ProcessPatches(const CompiledMethod* compiled_method, uint32_t code_offset);
    104   void AddUnreservedThunk(ThunkData* data);
    105 
    106   void ResolveMethodCalls(uint32_t quick_code_offset, MethodReference method_ref);
    107 
    108   uint32_t CalculateMaxNextOffset(uint32_t patch_offset, const ThunkKey& key);
    109 
    110   RelativePatcherTargetProvider* const provider_;
    111   const InstructionSet instruction_set_;
    112 
    113   // The data for all thunks.
    114   // SafeMap<> nodes don't move after being inserted, so we can use direct pointers to the data.
    115   using ThunkMap = SafeMap<ThunkKey, ThunkData, ThunkKeyCompare>;
    116   ThunkMap thunks_;
    117 
    118   // ReserveSpace() tracks unprocessed method call patches. These may be resolved later.
    119   class UnprocessedMethodCallPatch {
    120    public:
    121     UnprocessedMethodCallPatch(uint32_t patch_offset, MethodReference target_method)
    122         : patch_offset_(patch_offset), target_method_(target_method) { }
    123 
    124     uint32_t GetPatchOffset() const {
    125       return patch_offset_;
    126     }
    127 
    128     MethodReference GetTargetMethod() const {
    129       return target_method_;
    130     }
    131 
    132    private:
    133     uint32_t patch_offset_;
    134     MethodReference target_method_;
    135   };
    136   std::deque<UnprocessedMethodCallPatch> unprocessed_method_call_patches_;
    137   // Once we have compiled a method call thunk, cache pointer to the data.
    138   ThunkData* method_call_thunk_;
    139 
    140   // Thunks
    141   std::deque<ThunkData*> unreserved_thunks_;
    142 
    143   class PendingThunkComparator;
    144   std::vector<ThunkData*> pending_thunks_;  // Heap with the PendingThunkComparator.
    145 
    146   friend class Arm64RelativePatcherTest;
    147   friend class Thumb2RelativePatcherTest;
    148 
    149   DISALLOW_COPY_AND_ASSIGN(ArmBaseRelativePatcher);
    150 };
    151 
    152 }  // namespace linker
    153 }  // namespace art
    154 
    155 #endif  // ART_COMPILER_LINKER_ARM_RELATIVE_PATCHER_ARM_BASE_H_
    156