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