Add GC map to oat file
Change-Id: Ied0462c711a09e2542f231c3b2fa31239958bd28
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 1172186..00b226d 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -5,6 +5,7 @@
#include <iostream>
#include "class_linker.h"
+#include "compiler.h"
#include "dex_cache.h"
#include "dex_file.h"
#include "dex_instruction.h"
@@ -842,7 +843,7 @@
return changed;
}
-void RegisterLine::WriteReferenceBitMap(int8_t* data, size_t max_bytes) {
+void RegisterLine::WriteReferenceBitMap(std::vector<uint8_t>& data, size_t max_bytes) {
for (size_t i = 0; i < num_regs_; i += 8) {
uint8_t val = 0;
for (size_t j = 0; j < 8 && (i + j) < num_regs_; j++) {
@@ -851,10 +852,12 @@
val |= 1 << j;
}
}
- if (val != 0) {
- DCHECK_LT(i / 8, max_bytes);
- data[i / 8] = val;
+ if ((i / 8) >= max_bytes) {
+ DCHECK_EQ(0, val);
+ continue;
}
+ DCHECK_LT(i / 8, max_bytes) << "val=" << static_cast<uint32_t>(val);
+ data.push_back(val);
}
}
@@ -966,12 +969,18 @@
<< verifier.info_messages_.str() << Dumpable<DexVerifier>(verifier);
}
-DexVerifier::DexVerifier(Method* method) : work_insn_idx_(-1), method_(method),
- failure_(VERIFY_ERROR_NONE),
-
- new_instance_count_(0), monitor_enter_count_(0) {
+DexVerifier::DexVerifier(Method* method)
+ : work_insn_idx_(-1),
+ method_(method),
+ failure_(VERIFY_ERROR_NONE),
+ new_instance_count_(0),
+ monitor_enter_count_(0) {
+ CHECK(method != NULL);
+ Runtime* runtime = Runtime::Current();
+ // We should only be running the verifier at compile time
+ CHECK(!runtime->IsStarted());
const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ ClassLinker* class_linker = runtime->GetClassLinker();
dex_file_ = &class_linker->FindDexFile(dex_cache);
code_item_ = dex_file_->GetCodeItem(method->GetCodeItemOffset());
}
@@ -1063,7 +1072,7 @@
insn_flags_[dex_pc].SetInTry();
}
}
- /* Iterate over each of the handlers to verify target addresses. */
+ // Iterate over each of the handlers to verify target addresses.
const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0);
uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
ClassLinker* linker = Runtime::Current()->GetClassLinker();
@@ -1517,13 +1526,14 @@
}
/* Generate a register map and add it to the method. */
- ByteArray* map = GenerateGcMap();
+ const std::vector<uint8_t>* map = GenerateGcMap();
if (map == NULL) {
return false; // Not a real failure, but a failure to encode
}
- method_->SetGcMap(map);
+ Compiler::MethodReference ref(dex_file_, method_->GetDexMethodIndex());
+ verifier::DexVerifier::SetGcMap(ref, *map);
#ifndef NDEBUG
- VerifyGcMap();
+ VerifyGcMap(*map);
#endif
return true;
}
@@ -3712,7 +3722,7 @@
*log2_max_gc_pc = i;
}
-ByteArray* DexVerifier::GenerateGcMap() {
+const std::vector<uint8_t>* DexVerifier::GenerateGcMap() {
size_t num_entries, ref_bitmap_bits, pc_bits;
ComputeGcMapSizes(&num_entries, &ref_bitmap_bits, &pc_bits);
// There's a single byte to encode the size of each bitmap
@@ -3745,39 +3755,35 @@
return NULL;
}
size_t table_size = ((pc_bytes + ref_bitmap_bytes) * num_entries ) + 4;
- ByteArray* table = ByteArray::Alloc(table_size);
+ std::vector<uint8_t>* table = new std::vector<uint8_t>;
if (table == NULL) {
Fail(VERIFY_ERROR_GENERIC) << "Failed to encode GC map (size=" << table_size << ")";
return NULL;
}
// Write table header
- table->Set(0, format);
- table->Set(1, ref_bitmap_bytes);
- table->Set(2, num_entries & 0xFF);
- table->Set(3, (num_entries >> 8) & 0xFF);
+ table->push_back(format);
+ table->push_back(ref_bitmap_bytes);
+ table->push_back(num_entries & 0xFF);
+ table->push_back((num_entries >> 8) & 0xFF);
// Write table data
- size_t offset = 4;
for (size_t i = 0; i < code_item_->insns_size_in_code_units_; i++) {
if (insn_flags_[i].IsGcPoint()) {
- table->Set(offset, i & 0xFF);
- offset++;
+ table->push_back(i & 0xFF);
if (pc_bytes == 2) {
- table->Set(offset, (i >> 8) & 0xFF);
- offset++;
+ table->push_back((i >> 8) & 0xFF);
}
RegisterLine* line = reg_table_.GetLine(i);
- line->WriteReferenceBitMap(table->GetData() + offset, ref_bitmap_bytes);
- offset += ref_bitmap_bytes;
+ line->WriteReferenceBitMap(*table, ref_bitmap_bytes);
}
}
- DCHECK(offset == table_size);
+ DCHECK_EQ(table->size(), table_size);
return table;
}
-void DexVerifier::VerifyGcMap() {
+void DexVerifier::VerifyGcMap(const std::vector<uint8_t>& data) {
// Check that for every GC point there is a map entry, there aren't entries for non-GC points,
// that the table data is well formed and all references are marked (or not) in the bitmap
- PcToReferenceMap map(method_);
+ PcToReferenceMap map(&data[0], data.size());
size_t map_index = 0;
for(size_t i = 0; i < code_item_->insns_size_in_code_units_; i++) {
const uint8_t* reg_bitmap = map.FindBitMap(i, false);
@@ -3834,5 +3840,26 @@
return NULL;
}
+DexVerifier::GcMapTable DexVerifier::gc_maps_;
+
+void DexVerifier::SetGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map) {
+ CHECK(GetGcMap(ref) == NULL);
+ gc_maps_[ref] = &gc_map;
+ CHECK(GetGcMap(ref) != NULL);
+}
+
+const std::vector<uint8_t>* DexVerifier::GetGcMap(Compiler::MethodReference ref) {
+ GcMapTable::const_iterator it = gc_maps_.find(ref);
+ if (it == gc_maps_.end()) {
+ return NULL;
+ }
+ CHECK(it->second != NULL);
+ return it->second;
+}
+
+void DexVerifier::DeleteGcMaps() {
+ STLDeleteValues(&gc_maps_);
+}
+
} // namespace verifier
} // namespace art