1 /* 2 * Copyright (C) 2012 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_RUNTIME_VERIFIER_DEX_GC_MAP_H_ 18 #define ART_RUNTIME_VERIFIER_DEX_GC_MAP_H_ 19 20 #include <stdint.h> 21 22 #include "base/logging.h" 23 #include "base/macros.h" 24 25 namespace art { 26 namespace verifier { 27 28 /* 29 * Format enumeration for RegisterMap data area. 30 */ 31 enum RegisterMapFormat { 32 kRegMapFormatUnknown = 0, 33 kRegMapFormatNone = 1, // Indicates no map data follows. 34 kRegMapFormatCompact8 = 2, // Compact layout, 8-bit addresses. 35 kRegMapFormatCompact16 = 3, // Compact layout, 16-bit addresses. 36 }; 37 38 // Lightweight wrapper for Dex PC to reference bit maps. 39 class DexPcToReferenceMap { 40 public: 41 DexPcToReferenceMap(const uint8_t* data, size_t data_length) : data_(data) { 42 CHECK(data_ != NULL); 43 // Check the size of the table agrees with the number of entries 44 size_t data_size = data_length - 4; 45 DCHECK_EQ(EntryWidth() * NumEntries(), data_size); 46 } 47 48 // The number of entries in the table 49 size_t NumEntries() const { 50 return GetData()[2] | (GetData()[3] << 8); 51 } 52 53 // Get the Dex PC at the given index 54 uint16_t GetDexPc(size_t index) const { 55 size_t entry_offset = index * EntryWidth(); 56 if (DexPcWidth() == 1) { 57 return Table()[entry_offset]; 58 } else { 59 return Table()[entry_offset] | (Table()[entry_offset + 1] << 8); 60 } 61 } 62 63 // Return address of bitmap encoding what are live references 64 const uint8_t* GetBitMap(size_t index) const { 65 size_t entry_offset = index * EntryWidth(); 66 return &Table()[entry_offset + DexPcWidth()]; 67 } 68 69 // Find the bitmap associated with the given dex pc 70 const uint8_t* FindBitMap(uint16_t dex_pc, bool error_if_not_present = true) const; 71 72 // The number of bytes used to encode registers 73 size_t RegWidth() const { 74 return GetData()[1] | ((GetData()[0] & ~kRegMapFormatMask) << kRegMapFormatShift); 75 } 76 77 private: 78 // Table of num_entries * (dex pc, bitmap) 79 const uint8_t* Table() const { 80 return GetData() + 4; 81 } 82 83 // The format of the table of the PCs for the table 84 RegisterMapFormat Format() const { 85 return static_cast<RegisterMapFormat>(GetData()[0] & kRegMapFormatMask); 86 } 87 88 // Number of bytes used to encode a dex pc 89 size_t DexPcWidth() const { 90 RegisterMapFormat format = Format(); 91 switch (format) { 92 case kRegMapFormatCompact8: 93 return 1; 94 case kRegMapFormatCompact16: 95 return 2; 96 default: 97 LOG(FATAL) << "Invalid format " << static_cast<int>(format); 98 return -1; 99 } 100 } 101 102 // The width of an entry in the table 103 size_t EntryWidth() const { 104 return DexPcWidth() + RegWidth(); 105 } 106 107 const uint8_t* GetData() const { 108 return data_; 109 } 110 111 friend class MethodVerifier; 112 113 static const int kRegMapFormatShift = 5; 114 static const uint8_t kRegMapFormatMask = 0x7; 115 116 const uint8_t* const data_; // The header and table data 117 }; 118 119 } // namespace verifier 120 } // namespace art 121 122 #endif // ART_RUNTIME_VERIFIER_DEX_GC_MAP_H_ 123