| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef ART_DEX2OAT_LINKER_INDEX_BSS_MAPPING_ENCODER_H_ |
| #define ART_DEX2OAT_LINKER_INDEX_BSS_MAPPING_ENCODER_H_ |
| |
| #include <android-base/logging.h> |
| |
| #include "base/bit_utils.h" |
| #include "base/bit_vector-inl.h" |
| #include "oat/index_bss_mapping.h" |
| |
| namespace art { |
| namespace linker { |
| |
| // Helper class for encoding compressed IndexBssMapping. |
| class IndexBssMappingEncoder { |
| public: |
| IndexBssMappingEncoder(size_t number_of_indexes, size_t slot_size) |
| : index_bits_(IndexBssMappingEntry::IndexBits(number_of_indexes)), |
| slot_size_(slot_size) { |
| entry_.index_and_mask = static_cast<uint32_t>(-1); |
| entry_.bss_offset = static_cast<uint32_t>(-1); |
| DCHECK_NE(number_of_indexes, 0u); |
| } |
| |
| // Try to merge the next index -> bss_offset mapping into the current entry. |
| // Return true on success, false on failure. |
| bool TryMerge(uint32_t index, uint32_t bss_offset) { |
| DCHECK_LE(MinimumBitsToStore(index), index_bits_); |
| DCHECK_NE(index, entry_.GetIndex(index_bits_)); |
| if (entry_.bss_offset + slot_size_ != bss_offset) { |
| return false; |
| } |
| uint32_t diff = index - entry_.GetIndex(index_bits_); |
| if (diff > 32u - index_bits_) { |
| return false; |
| } |
| uint32_t mask = entry_.GetMask(index_bits_); |
| if ((mask & ~(static_cast<uint32_t>(-1) << diff)) != 0u) { |
| return false; |
| } |
| // Insert the bit indicating the index we've just overwritten |
| // and shift bits indicating indexes before that. |
| mask = ((mask << index_bits_) >> diff) | (static_cast<uint32_t>(1u) << (32 - diff)); |
| entry_.index_and_mask = mask | index; |
| entry_.bss_offset = bss_offset; |
| return true; |
| } |
| |
| void Reset(uint32_t method_index, uint32_t bss_offset) { |
| DCHECK_LE(MinimumBitsToStore(method_index), index_bits_); |
| entry_.index_and_mask = method_index; // Mask bits set to 0. |
| entry_.bss_offset = bss_offset; |
| } |
| |
| IndexBssMappingEntry GetEntry() { |
| return entry_; |
| } |
| |
| size_t GetIndexBits() const { |
| return index_bits_; |
| } |
| |
| private: |
| const size_t index_bits_; |
| const size_t slot_size_; |
| IndexBssMappingEntry entry_; |
| }; |
| |
| } // namespace linker |
| } // namespace art |
| |
| #endif // ART_DEX2OAT_LINKER_INDEX_BSS_MAPPING_ENCODER_H_ |