diff options
Diffstat (limited to 'src/compiler/codegen/CodegenUtil.cc')
-rw-r--r-- | src/compiler/codegen/CodegenUtil.cc | 118 |
1 files changed, 115 insertions, 3 deletions
diff --git a/src/compiler/codegen/CodegenUtil.cc b/src/compiler/codegen/CodegenUtil.cc index dff30bee5e..ca0a933789 100644 --- a/src/compiler/codegen/CodegenUtil.cc +++ b/src/compiler/codegen/CodegenUtil.cc @@ -14,6 +14,10 @@ * limitations under the License. */ +#include "gc_map.h" +#include "verifier/dex_gc_map.h" +#include "verifier/method_verifier.h" + namespace art { void setMemRefType(LIR* lir, bool isLoad, int memType) @@ -768,6 +772,114 @@ void createMappingTable(CompilationUnit* cUnit) } } +class NativePcToReferenceMapBuilder { + public: + NativePcToReferenceMapBuilder(std::vector<uint8_t>* table, + size_t entries, uint32_t max_native_offset, + size_t references_width) : entries_(entries), + references_width_(references_width), in_use_(entries), + table_(table) { + // Compute width in bytes needed to hold max_native_offset. + native_offset_width_ = 0; + while (max_native_offset != 0) { + native_offset_width_++; + max_native_offset >>= 8; + } + // Resize table and set up header. + table->resize((EntryWidth() * entries) + sizeof(uint32_t)); + CHECK_LT(native_offset_width_, 1U << 8); + (*table)[0] = native_offset_width_; + CHECK_LT(references_width_, 1U << 8); + (*table)[1] = references_width_; + CHECK_LT(entries, 1U << 16); + (*table)[2] = entries & 0xFF; + (*table)[3] = (entries >> 8) & 0xFF; + } + + void AddEntry(uint32_t native_offset, const uint8_t* references) { + size_t table_index = TableIndex(native_offset); + while (in_use_[table_index]) { + table_index = (table_index + 1) % entries_; + } + in_use_[table_index] = true; + SetNativeOffset(table_index, native_offset); + DCHECK_EQ(native_offset, GetNativeOffset(table_index)); + SetReferences(table_index, references); + } + + private: + size_t TableIndex(uint32_t native_offset) { + return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_; + } + + uint32_t GetNativeOffset(size_t table_index) { + uint32_t native_offset = 0; + size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t); + for (size_t i = 0; i < native_offset_width_; i++) { + native_offset |= (*table_)[table_offset + i] << (i * 8); + } + return native_offset; + } + + void SetNativeOffset(size_t table_index, uint32_t native_offset) { + size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t); + for (size_t i = 0; i < native_offset_width_; i++) { + (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF; + } + } + + void SetReferences(size_t table_index, const uint8_t* references) { + size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t); + memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_); + } + + size_t EntryWidth() const { + return native_offset_width_ + references_width_; + } + + // Number of entries in the table. + const size_t entries_; + // Number of bytes used to encode the reference bitmap. + const size_t references_width_; + // Number of bytes used to encode a native offset. + size_t native_offset_width_; + // Entries that are in use. + std::vector<bool> in_use_; + // The table we're building. + std::vector<uint8_t>* const table_; +}; + +static void createNativeGcMap(CompilationUnit* cUnit) { + const std::vector<uint32_t>& mapping_table = cUnit->mappingTable; + uint32_t max_native_offset = 0; + for (size_t i = 0; i < mapping_table.size(); i += 2) { + uint32_t native_offset = mapping_table[i + 0]; + if (native_offset > max_native_offset) { + max_native_offset = native_offset; + } + } + Compiler::MethodReference method_ref(cUnit->dex_file, cUnit->method_idx); + const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref); + verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4); + // Compute native offset to references size. + NativePcToReferenceMapBuilder native_gc_map_builder(&cUnit->nativeGcMap, + mapping_table.size() / 2, max_native_offset, + dex_gc_map.RegWidth()); + + for (size_t i = 0; i < mapping_table.size(); i += 2) { + uint32_t native_offset = mapping_table[i + 0]; + uint32_t dex_pc = mapping_table[i + 1]; + const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false); + if (references != NULL) { + native_gc_map_builder.AddEntry(native_offset, references); + } else { + // TODO: there is a mapping table entry but no reference bitmap. This happens because of + // catch block entries. We should check that the dex_pc corresponds with a catch block + // here. + } + } +} + /* Determine the offset of each literal field */ int assignLiteralOffset(CompilationUnit* cUnit, int offset) { @@ -874,10 +986,10 @@ void oatAssembleLIR(CompilationUnit* cUnit) // Install fill array data installFillArrayData(cUnit); - /* - * Create the mapping table - */ + // Create the mapping table and native offset to reference map. createMappingTable(cUnit); + + createNativeGcMap(cUnit); } /* |