diff options
author | 2012-01-11 15:19:46 -0800 | |
---|---|---|
committer | 2012-01-11 17:03:58 -0800 | |
commit | 0755ec5ea1dce0b549fc1adefeb52d89f119ebec (patch) | |
tree | 6565330f01612586ebbfa9b45dda6bd4720c3234 | |
parent | 57e7600af0076bad4d7d3f255e72230d2c3be990 (diff) |
Record Class::Status information in oat file
Change-Id: I328de86a89c7d84a211b3aed3d42b8c92c1f3464
-rw-r--r-- | src/compiled_class.h | 24 | ||||
-rw-r--r-- | src/compiled_method.h | 4 | ||||
-rw-r--r-- | src/compiler.cc | 29 | ||||
-rw-r--r-- | src/compiler.h | 28 | ||||
-rw-r--r-- | src/oat_file.cc | 28 | ||||
-rw-r--r-- | src/oat_file.h | 11 | ||||
-rw-r--r-- | src/oat_writer.cc | 25 | ||||
-rw-r--r-- | src/oat_writer.h | 3 |
8 files changed, 125 insertions, 27 deletions
diff --git a/src/compiled_class.h b/src/compiled_class.h new file mode 100644 index 0000000000..98f0d9fcba --- /dev/null +++ b/src/compiled_class.h @@ -0,0 +1,24 @@ +// Copyright 2011 Google Inc. All Rights Reserved. + +#ifndef ART_SRC_COMPILED_CLASS_H_ +#define ART_SRC_COMPILED_CLASS_H_ + +#include "object.h" + +namespace art { + +class CompiledClass { + public: + CompiledClass(Class::Status status) : status_(status) {}; + ~CompiledClass() {}; + Class::Status GetStatus() const { + return status_; + } + private: + const Class::Status status_; +}; + +} // namespace art + +#endif // ART_SRC_COMPILED_CLASS_H_ + diff --git a/src/compiled_method.h b/src/compiled_method.h index b09a762f11..4b5a78b7d8 100644 --- a/src/compiled_method.h +++ b/src/compiled_method.h @@ -12,7 +12,7 @@ namespace art { class CompiledMethod { public: - // Create an CompiledMethod from the oatCompileMethod + // Create a CompiledMethod from the oatCompileMethod CompiledMethod(InstructionSet instruction_set, std::vector<short>& code, const size_t frame_size_in_bytes, @@ -21,7 +21,7 @@ class CompiledMethod { std::vector<uint32_t>& mapping_table, std::vector<uint16_t>& vmap_table); - // Create an CompiledMethod from the JniCompiler + // Create a CompiledMethod from the JniCompiler CompiledMethod(InstructionSet instruction_set, std::vector<uint8_t>& code, const size_t frame_size_in_bytes, diff --git a/src/compiler.cc b/src/compiler.cc index e01ab749a2..88e156ded5 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -50,6 +50,7 @@ Compiler::Compiler(InstructionSet instruction_set, } Compiler::~Compiler() { + STLDeleteValues(&compiled_classes_); STLDeleteValues(&compiled_methods_); STLDeleteValues(&compiled_invoke_stubs_); } @@ -323,9 +324,20 @@ void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader, c Class* klass = class_linker->FindClass(descriptor, class_loader); if (klass != NULL) { class_linker->EnsureInitialized(klass, false); + // record the final class status if necessary + Class::Status status = klass->GetStatus(); + ClassReference ref(&dex_file, class_def_index); + CompiledClass* compiled_class = GetCompiledClass(ref); + if (compiled_class == NULL) { + compiled_class = new CompiledClass(status); + compiled_classes_[ref] = compiled_class; + } else { + DCHECK_EQ(status, compiled_class->GetStatus()); + } } // clear any class not found or verification exceptions Thread::Current()->ClearException(); + } DexCache* dex_cache = class_linker->FindDexCache(dex_file); @@ -404,13 +416,9 @@ void Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access if (compiled_method != NULL) { MethodReference ref(&dex_file, method_idx); - CHECK(compiled_methods_.find(ref) == compiled_methods_.end()) - << PrettyMethod(method_idx, dex_file); + CHECK(GetCompiledMethod(ref) == NULL) << PrettyMethod(method_idx, dex_file); compiled_methods_[ref] = compiled_method; - DCHECK(compiled_methods_.find(ref) != compiled_methods_.end()) - << PrettyMethod(method_idx, dex_file); - DCHECK(GetCompiledMethod(ref) != NULL) - << PrettyMethod(method_idx, dex_file); + DCHECK(GetCompiledMethod(ref) != NULL) << PrettyMethod(method_idx, dex_file); } const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx)); @@ -455,6 +463,15 @@ void Compiler::InsertInvokeStub(bool is_static, const char* shorty, compiled_invoke_stubs_[key] = compiled_invoke_stub; } +CompiledClass* Compiler::GetCompiledClass(ClassReference ref) const { + ClassTable::const_iterator it = compiled_classes_.find(ref); + if (it == compiled_classes_.end()) { + return NULL; + } + CHECK(it->second != NULL); + return it->second; +} + CompiledMethod* Compiler::GetCompiledMethod(MethodReference ref) const { MethodTable::const_iterator it = compiled_methods_.find(ref); if (it == compiled_methods_.end()) { diff --git a/src/compiler.h b/src/compiler.h index f05f80b9ad..f59587f270 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -3,6 +3,7 @@ #ifndef ART_SRC_COMPILER_H_ #define ART_SRC_COMPILER_H_ +#include "compiled_class.h" #include "compiled_method.h" #include "constants.h" #include "dex_cache.h" @@ -55,10 +56,14 @@ class Compiler { static ByteArray* CreateJniDlysmLookupStub(InstructionSet instruction_set); - // A method is uniquely located by its DexFile and index into the method_id table of that dex file - typedef std::pair<const DexFile*, uint32_t> MethodReference; + // A class is uniquely located by its DexFile and the class_defs_ table index into that DexFile + typedef std::pair<const DexFile*, uint32_t> ClassReference; + CompiledClass* GetCompiledClass(ClassReference ref) const; + // A method is uniquely located by its DexFile and the method_ids_ table index into that DexFile + typedef std::pair<const DexFile*, uint32_t> MethodReference; CompiledMethod* GetCompiledMethod(MethodReference ref) const; + const CompiledInvokeStub* FindInvokeStub(bool is_static, const char* shorty) const; // Callbacks from OAT/ART compiler to see what runtime checks must be generated @@ -122,8 +127,25 @@ class Compiler { InstructionSet instruction_set_; JniCompiler jni_compiler_; + struct ClassReferenceHash { + size_t operator()(const ClassReference& id) const { + size_t dex = reinterpret_cast<size_t>(id.first); + DCHECK_NE(dex, static_cast<size_t>(0)); + dex += 33; // dex is an aligned pointer, get some non-zero low bits + size_t idx = id.second; + if (idx == 0) { // special case of a method index of 0 + return dex * 5381; + } else { + return dex * idx; + } + } + }; + typedef std::tr1::unordered_map<const ClassReference, CompiledClass*, ClassReferenceHash> ClassTable; + // All class references that this compiler has compiled + ClassTable compiled_classes_; + struct MethodReferenceHash { - size_t operator()(const MethodReference id) const { + size_t operator()(const MethodReference& id) const { size_t dex = reinterpret_cast<size_t>(id.first); DCHECK_NE(dex, static_cast<size_t>(0)); dex += 33; // dex is an aligned pointer, get some non-zero low bits diff --git a/src/oat_file.cc b/src/oat_file.cc index 4d6b4a5aed..646f1c5f29 100644 --- a/src/oat_file.cc +++ b/src/oat_file.cc @@ -166,12 +166,12 @@ OatFile::OatDexFile::OatDexFile(const OatFile* oat_file, std::string dex_file_location, uint32_t dex_file_checksum, byte* dex_file_pointer, - const uint32_t* methods_offsets_pointer) + const uint32_t* oat_class_offsets_pointer) : oat_file_(oat_file), dex_file_location_(dex_file_location), dex_file_checksum_(dex_file_checksum), dex_file_pointer_(dex_file_pointer), - methods_offsets_pointer_(methods_offsets_pointer) {} + oat_class_offsets_pointer_(oat_class_offsets_pointer) {} OatFile::OatDexFile::~OatDexFile() {} @@ -181,17 +181,31 @@ const DexFile* OatFile::OatDexFile::OpenDexFile() const { } const OatFile::OatClass* OatFile::OatDexFile::GetOatClass(uint32_t class_def_index) const { - uint32_t methods_offset = methods_offsets_pointer_[class_def_index]; - const byte* methods_pointer = oat_file_->GetBase() + methods_offset; + uint32_t oat_class_offset = oat_class_offsets_pointer_[class_def_index]; + + const byte* oat_class_pointer = oat_file_->GetBase() + oat_class_offset; + CHECK_LT(oat_class_pointer, oat_file_->GetLimit()); + Class::Status status = *reinterpret_cast<const Class::Status*>(oat_class_pointer); + + const byte* methods_pointer = oat_class_pointer + sizeof(status); CHECK_LT(methods_pointer, oat_file_->GetLimit()); - return new OatClass(oat_file_, reinterpret_cast<const OatMethodOffsets*>(methods_pointer)); + + return new OatClass(oat_file_, + status, + reinterpret_cast<const OatMethodOffsets*>(methods_pointer)); } -OatFile::OatClass::OatClass(const OatFile* oat_file, const OatMethodOffsets* methods_pointer) - : oat_file_(oat_file), methods_pointer_(methods_pointer) {} +OatFile::OatClass::OatClass(const OatFile* oat_file, + Class::Status status, + const OatMethodOffsets* methods_pointer) + : oat_file_(oat_file), status_(status), methods_pointer_(methods_pointer) {} OatFile::OatClass::~OatClass() {} +Class::Status OatFile::OatClass::GetStatus() const { + return status_; +} + const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const { const OatMethodOffsets& oat_method_offsets = methods_pointer_[method_index]; return OatMethod( diff --git a/src/oat_file.h b/src/oat_file.h index 5b05ad61c4..5c011fdcd3 100644 --- a/src/oat_file.h +++ b/src/oat_file.h @@ -114,6 +114,8 @@ class OatFile { class OatClass { public: + Class::Status GetStatus() const; + // get the OatMethod entry based on its index into the class // defintion. direct methods come first, followed by virtual // methods. note that runtime created methods such as miranda @@ -122,9 +124,12 @@ class OatFile { ~OatClass(); private: - OatClass(const OatFile* oat_file, const OatMethodOffsets* methods_pointer); + OatClass(const OatFile* oat_file, + Class::Status status, + const OatMethodOffsets* methods_pointer); const OatFile* oat_file_; + const Class::Status status_; const OatMethodOffsets* methods_pointer_; friend class OatDexFile; @@ -149,13 +154,13 @@ class OatFile { std::string dex_file_location, uint32_t dex_file_checksum, byte* dex_file_pointer, - const uint32_t* methods_offsets_pointer); + const uint32_t* oat_class_offsets_pointer); const OatFile* oat_file_; std::string dex_file_location_; uint32_t dex_file_checksum_; const byte* dex_file_pointer_; - const uint32_t* methods_offsets_pointer_; + const uint32_t* oat_class_offsets_pointer_; friend class OatFile; DISALLOW_COPY_AND_ASSIGN(OatDexFile); diff --git a/src/oat_writer.cc b/src/oat_writer.cc index fa27737c98..806ac71e7e 100644 --- a/src/oat_writer.cc +++ b/src/oat_writer.cc @@ -96,7 +96,13 @@ size_t OatWriter::InitOatClasses(size_t offset) { size_t num_virtual_methods = it.NumVirtualMethods(); num_methods = num_direct_methods + num_virtual_methods; } - OatClass* oat_class = new OatClass(num_methods); + + CompiledClass* compiled_class = + compiler_->GetCompiledClass(art::Compiler::MethodReference(dex_file, class_def_index)); + Class::Status status = + (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady; + + OatClass* oat_class = new OatClass(status, num_methods); oat_classes_.push_back(oat_class); offset += oat_class->SizeOf(); } @@ -656,20 +662,29 @@ bool OatWriter::OatDexFile::Write(File* file) const { return true; } -OatWriter::OatClass::OatClass(uint32_t methods_count) { +OatWriter::OatClass::OatClass(Class::Status status, uint32_t methods_count) { + status_ = status; method_offsets_.resize(methods_count); } size_t OatWriter::OatClass::SizeOf() const { - return (sizeof(method_offsets_[0]) * method_offsets_.size()); + return sizeof(status_) + + (sizeof(method_offsets_[0]) * method_offsets_.size()); } void OatWriter::OatClass::UpdateChecksum(OatHeader& oat_header) const { - oat_header.UpdateChecksum(&method_offsets_[0], SizeOf()); + oat_header.UpdateChecksum(&status_, sizeof(status_)); + oat_header.UpdateChecksum(&method_offsets_[0], + sizeof(method_offsets_[0]) * method_offsets_.size()); } bool OatWriter::OatClass::Write(File* file) const { - if (!file->WriteFully(&method_offsets_[0], SizeOf())) { + if (!file->WriteFully(&status_, sizeof(status_))) { + PLOG(ERROR) << "Failed to write class status to " << file->name(); + return false; + } + if (!file->WriteFully(&method_offsets_[0], + sizeof(method_offsets_[0]) * method_offsets_.size())) { PLOG(ERROR) << "Failed to write method offsets to " << file->name(); return false; } diff --git a/src/oat_writer.h b/src/oat_writer.h index a5de14eb85..6ae0f4e4fb 100644 --- a/src/oat_writer.h +++ b/src/oat_writer.h @@ -109,12 +109,13 @@ class OatWriter { class OatClass { public: - explicit OatClass(uint32_t methods_count); + explicit OatClass(Class::Status status, uint32_t methods_count); size_t SizeOf() const; void UpdateChecksum(OatHeader& oat_header) const; bool Write(File* file) const; // data to write + Class::Status status_; std::vector<OatMethodOffsets> method_offsets_; private: |