Record Class::Status information in oat file
Change-Id: I328de86a89c7d84a211b3aed3d42b8c92c1f3464
diff --git a/src/compiled_class.h b/src/compiled_class.h
new file mode 100644
index 0000000..98f0d9f
--- /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 b09a762..4b5a78b 100644
--- a/src/compiled_method.h
+++ b/src/compiled_method.h
@@ -12,7 +12,7 @@
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 @@
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 e01ab74..88e156d 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -50,6 +50,7 @@
}
Compiler::~Compiler() {
+ STLDeleteValues(&compiled_classes_);
STLDeleteValues(&compiled_methods_);
STLDeleteValues(&compiled_invoke_stubs_);
}
@@ -323,9 +324,20 @@
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 @@
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 @@
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 f05f80b..f59587f 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 @@
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 @@
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 4d6b4a5..646f1c5 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -166,12 +166,12 @@
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 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 5b05ad6..5c011fd 100644
--- a/src/oat_file.h
+++ b/src/oat_file.h
@@ -114,6 +114,8 @@
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 @@
~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 @@
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 fa27737..806ac71 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -96,7 +96,13 @@
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 @@
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 a5de14e..6ae0f4e 100644
--- a/src/oat_writer.h
+++ b/src/oat_writer.h
@@ -109,12 +109,13 @@
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: