/* * Copyright (C) 2012 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_RUNTIME_VERIFIER_DEX_GC_MAP_H_ #define ART_RUNTIME_VERIFIER_DEX_GC_MAP_H_ #include <stdint.h> #include "base/logging.h" #include "base/macros.h" namespace art { namespace verifier { /* * Format enumeration for RegisterMap data area. */ enum RegisterMapFormat { kRegMapFormatUnknown = 0, kRegMapFormatNone = 1, // Indicates no map data follows. kRegMapFormatCompact8 = 2, // Compact layout, 8-bit addresses. kRegMapFormatCompact16 = 3, // Compact layout, 16-bit addresses. }; // Lightweight wrapper for Dex PC to reference bit maps. class DexPcToReferenceMap { public: DexPcToReferenceMap(const uint8_t* data, size_t data_length) : data_(data) { CHECK(data_ != NULL); // Check the size of the table agrees with the number of entries size_t data_size = data_length - 4; DCHECK_EQ(EntryWidth() * NumEntries(), data_size); } // The number of entries in the table size_t NumEntries() const { return GetData()[2] | (GetData()[3] << 8); } // Get the Dex PC at the given index uint16_t GetDexPc(size_t index) const { size_t entry_offset = index * EntryWidth(); if (DexPcWidth() == 1) { return Table()[entry_offset]; } else { return Table()[entry_offset] | (Table()[entry_offset + 1] << 8); } } // Return address of bitmap encoding what are live references const uint8_t* GetBitMap(size_t index) const { size_t entry_offset = index * EntryWidth(); return &Table()[entry_offset + DexPcWidth()]; } // Find the bitmap associated with the given dex pc const uint8_t* FindBitMap(uint16_t dex_pc, bool error_if_not_present = true) const; // The number of bytes used to encode registers size_t RegWidth() const { return GetData()[1] | ((GetData()[0] & ~kRegMapFormatMask) << kRegMapFormatShift); } private: // Table of num_entries * (dex pc, bitmap) const uint8_t* Table() const { return GetData() + 4; } // The format of the table of the PCs for the table RegisterMapFormat Format() const { return static_cast<RegisterMapFormat>(GetData()[0] & kRegMapFormatMask); } // Number of bytes used to encode a dex pc size_t DexPcWidth() const { RegisterMapFormat format = Format(); switch (format) { case kRegMapFormatCompact8: return 1; case kRegMapFormatCompact16: return 2; default: LOG(FATAL) << "Invalid format " << static_cast<int>(format); return -1; } } // The width of an entry in the table size_t EntryWidth() const { return DexPcWidth() + RegWidth(); } const uint8_t* GetData() const { return data_; } friend class MethodVerifier; static const int kRegMapFormatShift = 5; static const uint8_t kRegMapFormatMask = 0x7; const uint8_t* const data_; // The header and table data }; } // namespace verifier } // namespace art #endif // ART_RUNTIME_VERIFIER_DEX_GC_MAP_H_