• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
type_(type)51         : type_(type), custom_value1_(custom_value1), custom_value2_(custom_value2) { }
52 
GetType()53     ThunkType GetType() const {
54       return type_;
55     }
56 
GetCustomValue1()57     uint32_t GetCustomValue1() const {
58       return custom_value1_;
59     }
60 
GetCustomValue2()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:
operator()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:
UnprocessedMethodCallPatch(uint32_t patch_offset,MethodReference target_method)121     UnprocessedMethodCallPatch(uint32_t patch_offset, MethodReference target_method)
122         : patch_offset_(patch_offset), target_method_(target_method) { }
123 
GetPatchOffset()124     uint32_t GetPatchOffset() const {
125       return patch_offset_;
126     }
127 
GetTargetMethod()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