diff options
| -rw-r--r-- | src/class_linker.cc | 25 | ||||
| -rw-r--r-- | src/oat_writer.cc | 33 | ||||
| -rw-r--r-- | src/oat_writer.h | 7 |
3 files changed, 51 insertions, 14 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc index 22f8a8a8d1..3154a1bbae 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -1798,6 +1798,29 @@ void ClassLinker::LookupClasses(const char* descriptor, std::vector<Class*>& cla } } +#ifndef NDEBUG +static void CheckMethodsHaveGcMaps(Class* klass) { + if (!Runtime::Current()->IsStarted()) { + return; + } + for (size_t i = 0; i < klass->NumDirectMethods(); i++) { + Method* method = klass->GetDirectMethod(i); + if (!method->IsNative() && !method->IsAbstract()) { + CHECK(method->GetGcMap() != NULL) << PrettyMethod(method); + } + } + for (size_t i = 0; i < klass->NumVirtualMethods(); i++) { + Method* method = klass->GetVirtualMethod(i); + if (!method->IsNative() && !method->IsAbstract()) { + CHECK(method->GetGcMap() != NULL) << PrettyMethod(method); + } + } +} +#else +static void CheckMethodsHaveGcMaps(Class* klass) { +} +#endif + void ClassLinker::VerifyClass(Class* klass) { // TODO: assert that the monitor on the Class is held if (klass->IsVerified()) { @@ -1813,6 +1836,8 @@ void ClassLinker::VerifyClass(Class* klass) { // Make sure all classes referenced by catch blocks are resolved ResolveClassExceptionHandlerTypes(dex_file, klass); klass->SetStatus(Class::kStatusVerified); + // Sanity check that a verified class has GC maps on all methods + CheckMethodsHaveGcMaps(klass); } else { LOG(ERROR) << "Verification failed on class " << PrettyClass(klass); Thread* self = Thread::Current(); diff --git a/src/oat_writer.cc b/src/oat_writer.cc index 9690142ebb..8b19727543 100644 --- a/src/oat_writer.cc +++ b/src/oat_writer.cc @@ -80,12 +80,11 @@ size_t OatWriter::InitDexFiles(size_t offset) { size_t OatWriter::InitOatClasses(size_t offset) { // create the OatClasses // calculate the offsets within OatDexFiles to OatClasses - size_t class_index = 0; for (size_t i = 0; i != dex_files_->size(); ++i) { const DexFile* dex_file = (*dex_files_)[i]; for (size_t class_def_index = 0; class_def_index < dex_file->NumClassDefs(); - class_def_index++, class_index++) { + class_def_index++) { oat_dex_files_[i]->methods_offsets_[class_def_index] = offset; const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); const byte* class_data = dex_file->GetClassData(class_def); @@ -138,14 +137,14 @@ size_t OatWriter::InitOatCodeDexFile(size_t offset, class_def_index < dex_file.NumClassDefs(); class_def_index++, oat_class_index++) { const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); - offset = InitOatCodeClassDef(offset, oat_class_index, dex_file, class_def); + offset = InitOatCodeClassDef(offset, oat_class_index, class_def_index, dex_file, class_def); oat_classes_[oat_class_index]->UpdateChecksum(*oat_header_); } return offset; } size_t OatWriter::InitOatCodeClassDef(size_t offset, - size_t oat_class_index, + size_t oat_class_index, size_t class_def_index, const DexFile& dex_file, const DexFile::ClassDef& class_def) { const byte* class_data = dex_file.GetClassData(class_def); @@ -167,15 +166,17 @@ size_t OatWriter::InitOatCodeClassDef(size_t offset, size_t class_def_method_index = 0; while (it.HasNextDirectMethod()) { bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0; - offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, is_static, true, - it.GetMemberIndex(), &dex_file); + bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0; + offset = InitOatCodeMethod(offset, oat_class_index, class_def_index, class_def_method_index, is_native, + is_static, true, it.GetMemberIndex(), &dex_file); class_def_method_index++; it.Next(); } while (it.HasNextVirtualMethod()) { CHECK_EQ(it.GetMemberAccessFlags() & kAccStatic, 0U); - offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, false, false, - it.GetMemberIndex(), &dex_file); + bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0; + offset = InitOatCodeMethod(offset, oat_class_index, class_def_index, class_def_method_index, is_native, + false, false, it.GetMemberIndex(), &dex_file); class_def_method_index++; it.Next(); } @@ -183,9 +184,9 @@ size_t OatWriter::InitOatCodeClassDef(size_t offset, return offset; } -size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, - size_t class_def_method_index, bool is_static, bool is_direct, - uint32_t method_idx, const DexFile* dex_file) { +size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, size_t class_def_index, + size_t class_def_method_index, bool is_native, bool is_static, + bool is_direct, uint32_t method_idx, const DexFile* dex_file) { // derived from CompiledMethod if available uint32_t code_offset = 0; uint32_t frame_size_in_bytes = kStackAlignment; @@ -264,6 +265,16 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]); gc_map_offset = (gc_map_size == 0) ? 0 : offset; +#ifndef NDEBUG + // We expect GC maps except when the class hasn't been verified or the method is native + CompiledClass* compiled_class = + compiler_->GetCompiledClass(art::Compiler::MethodReference(dex_file, class_def_index)); + Class::Status status = + (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady; + CHECK(gc_map_size != 0 || is_native || status < Class::kStatusVerified) + << PrettyMethod(method_idx, *dex_file); +#endif + // Deduplicate GC maps std::map<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map); if (gc_map_iter != gc_map_offsets_.end()) { diff --git a/src/oat_writer.h b/src/oat_writer.h index d1983a5ce2..a9ea7ef7ce 100644 --- a/src/oat_writer.h +++ b/src/oat_writer.h @@ -68,11 +68,12 @@ class OatWriter { size_t& oat_class_index, const DexFile& dex_file); size_t InitOatCodeClassDef(size_t offset, - size_t oat_class_index, + size_t oat_class_index, size_t class_def_index, const DexFile& dex_file, const DexFile::ClassDef& class_def); - size_t InitOatCodeMethod(size_t offset, size_t oat_class_index, size_t class_def_method_index, - bool is_static, bool is_direct, uint32_t method_idx, const DexFile*); + size_t InitOatCodeMethod(size_t offset, size_t oat_class_index, size_t class_def_index, + size_t class_def_method_index, bool is_native, bool is_static, + bool is_direct, uint32_t method_idx, const DexFile*); bool Write(File* file); bool WriteTables(File* file); |