1 /* 2 * Copyright (C) 2017 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_DEX2OAT_LINKER_INDEX_BSS_MAPPING_ENCODER_H_ 18 #define ART_DEX2OAT_LINKER_INDEX_BSS_MAPPING_ENCODER_H_ 19 20 #include <android-base/logging.h> 21 22 #include "base/bit_utils.h" 23 #include "base/bit_vector-inl.h" 24 #include "index_bss_mapping.h" 25 26 namespace art { 27 namespace linker { 28 29 // Helper class for encoding compressed IndexBssMapping. 30 class IndexBssMappingEncoder { 31 public: IndexBssMappingEncoder(size_t number_of_indexes,size_t slot_size)32 IndexBssMappingEncoder(size_t number_of_indexes, size_t slot_size) 33 : index_bits_(IndexBssMappingEntry::IndexBits(number_of_indexes)), 34 slot_size_(slot_size) { 35 entry_.index_and_mask = static_cast<uint32_t>(-1); 36 entry_.bss_offset = static_cast<uint32_t>(-1); 37 DCHECK_NE(number_of_indexes, 0u); 38 } 39 40 // Try to merge the next index -> bss_offset mapping into the current entry. 41 // Return true on success, false on failure. TryMerge(uint32_t index,uint32_t bss_offset)42 bool TryMerge(uint32_t index, uint32_t bss_offset) { 43 DCHECK_LE(MinimumBitsToStore(index), index_bits_); 44 DCHECK_NE(index, entry_.GetIndex(index_bits_)); 45 if (entry_.bss_offset + slot_size_ != bss_offset) { 46 return false; 47 } 48 uint32_t diff = index - entry_.GetIndex(index_bits_); 49 if (diff > 32u - index_bits_) { 50 return false; 51 } 52 uint32_t mask = entry_.GetMask(index_bits_); 53 if ((mask & ~(static_cast<uint32_t>(-1) << diff)) != 0u) { 54 return false; 55 } 56 // Insert the bit indicating the index we've just overwritten 57 // and shift bits indicating indexes before that. 58 mask = ((mask << index_bits_) >> diff) | (static_cast<uint32_t>(1u) << (32 - diff)); 59 entry_.index_and_mask = mask | index; 60 entry_.bss_offset = bss_offset; 61 return true; 62 } 63 Reset(uint32_t method_index,uint32_t bss_offset)64 void Reset(uint32_t method_index, uint32_t bss_offset) { 65 DCHECK_LE(MinimumBitsToStore(method_index), index_bits_); 66 entry_.index_and_mask = method_index; // Mask bits set to 0. 67 entry_.bss_offset = bss_offset; 68 } 69 GetEntry()70 IndexBssMappingEntry GetEntry() { 71 return entry_; 72 } 73 GetIndexBits()74 size_t GetIndexBits() const { 75 return index_bits_; 76 } 77 78 private: 79 const size_t index_bits_; 80 const size_t slot_size_; 81 IndexBssMappingEntry entry_; 82 }; 83 84 } // namespace linker 85 } // namespace art 86 87 #endif // ART_DEX2OAT_LINKER_INDEX_BSS_MAPPING_ENCODER_H_ 88