Merge "Fix test 086-classloader" into dalvik-dev
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/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 3f8d900..08a53bd 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -545,6 +545,7 @@
loadWordDisp(cUnit, rSELF,
OFFSETOF_MEMBER(Thread, pResolveMethodFromCode), rLR);
loadConstant(cUnit, r1, dInsn->vB);
+ loadConstant(cUnit, r2, false);
callRuntimeHelper(cUnit, rLR);
genUnconditionalBranch(cUnit, rollback);
// Resume normal slow path
@@ -729,6 +730,7 @@
loadWordDisp(cUnit, rSELF,
OFFSETOF_MEMBER(Thread, pResolveMethodFromCode), rLR);
loadConstant(cUnit, r1, dInsn->vB);
+ loadConstant(cUnit, r2, true);
callRuntimeHelper(cUnit, rLR);
genUnconditionalBranch(cUnit, rollback);
// Resume normal slow path
@@ -1085,6 +1087,7 @@
loadWordDisp(cUnit, rSELF,
OFFSETOF_MEMBER(Thread, pResolveMethodFromCode), rLR);
loadConstant(cUnit, r1, dInsn->vB);
+ loadConstant(cUnit, r2, true);
callRuntimeHelper(cUnit, rLR);
}
@@ -1157,6 +1160,7 @@
loadWordDisp(cUnit, rSELF,
OFFSETOF_MEMBER(Thread, pResolveMethodFromCode), rLR);
loadConstant(cUnit, r1, dInsn->vB);
+ loadConstant(cUnit, r2, false);
callRuntimeHelper(cUnit, rLR);
}
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:
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 223ea7e..1a6d2e6 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -854,17 +854,22 @@
return InitializeStaticStorageAndVerifyAccess(type_idx, referrer, self);
}
-// TODO: placeholder. Helper function to resolve virtual method
-void ResolveMethodFromCode(Method* method, uint32_t method_idx) {
+// Helper function to resolve virtual method
+extern "C" Method* artResolveMethodFromCode(Method* referrer,
+ uint32_t method_idx,
+ bool is_direct,
+ Thread* self,
+ Method** sp) {
/*
* Slow-path handler on invoke virtual method path in which
- * base method is unresolved at compile-time. Doesn't need to
- * return anything - just either ensure that
- * method->dex_cache_resolved_methods_(method_idx) != NULL or
- * throw and unwind. The caller will restart call sequence
- * from the beginning.
+ * base method is unresolved at compile-time. Caller will
+ * unwind if can't resolve.
*/
- UNIMPLEMENTED(FATAL);
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Method* method = class_linker->ResolveMethod(method_idx, referrer, is_direct);
+ referrer->GetDexCacheResolvedMethods()->Set(method_idx, method);
+ return method;
}
String* ResolveStringFromCode(const Method* referrer, uint32_t string_idx) {
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 2ebfc22..876abd7 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -25,7 +25,6 @@
extern Class* InitializeTypeFromCode(uint32_t type_idx, Method* method);
uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class);
void ObjectInitFromCode(Object* o);
-extern void ResolveMethodFromCode(Method* method, uint32_t method_idx);
extern void LockObjectFromCode(Thread* thread, Object* obj);
uint32_t artTraceMethodUnwindFromCode(Thread* self);
extern int64_t D2L(double d);
@@ -73,6 +72,7 @@
extern "C" void art_trace_entry_from_code(void*);
extern "C" void art_trace_exit_from_code();
extern "C" void* art_resolve_string_from_code(void*, uint32_t);
+ extern "C" void* art_resolve_method_from_code(void* referrer, uint32_t method_idx, bool is_direct);
/* Conversions */
extern "C" float __aeabi_i2f(int op1); // OP_INT_TO_FLOAT
diff --git a/src/runtime_support_arm.S b/src/runtime_support_arm.S
index 38337a3..c73588e 100644
--- a/src/runtime_support_arm.S
+++ b/src/runtime_support_arm.S
@@ -421,6 +421,22 @@
bxeq lr @ return on success
DELIVER_PENDING_EXCEPTION
+ .global art_resolve_method_from_code
+ .extern artResolveMethodFromCode
+ /*
+ * Entry from managed code to resolve a method.
+ */
+art_resolve_method_from_code:
+ SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
+ mov r3, r9 @ pass Thread::Current
+ str sp, [sp, #0] @ pass SP
+ @ artResolveMethodFromCode(Method* referrer, uint32_t method_idx, bool is_direct, Thread*, SP)
+ bl artResolveMethodFromCode
+ RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
+ cmp r0, #0 @ success if result is non-null
+ bxne lr @ return on success
+ DELIVER_PENDING_EXCEPTION
+
.global art_resolve_string_from_code
.extern artResolveStringFromCode
/*
diff --git a/src/thread.cc b/src/thread.cc
index 4adf1e0..b065533 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -127,6 +127,7 @@
pThrowStackOverflowFromCode = art_throw_stack_overflow_from_code;
pThrowVerificationErrorFromCode = art_throw_verification_error_from_code;
pUnlockObjectFromCode = art_unlock_object_from_code;
+ pResolveMethodFromCode = art_resolve_method_from_code;
#endif
pF2l = F2L;
pD2l = D2L;
@@ -137,7 +138,6 @@
pDeliverException = art_deliver_exception_from_code;
pFindNativeMethod = FindNativeMethod;
pInstanceofNonTrivialFromCode = IsAssignableFromCode;
- pResolveMethodFromCode = ResolveMethodFromCode;
pThrowAbstractMethodErrorFromCode = ThrowAbstractMethodErrorFromCode;
pUnresolvedDirectMethodTrampolineFromCode = UnresolvedDirectMethodTrampolineFromCode;
}
diff --git a/src/thread.h b/src/thread.h
index c5fb914..aee784d 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -143,7 +143,7 @@
void* (*pInitializeTypeAndVerifyAccessFromCode)(uint32_t, void*);
void (*pLockObjectFromCode)(void*);
void (*pObjectInit)(void*);
- void (*pResolveMethodFromCode)(Method*, uint32_t);
+ void* (*pResolveMethodFromCode)(void*, uint32_t, bool);
void* (*pResolveStringFromCode)(void*, uint32_t);
int (*pSet32Static)(uint32_t, void*, int32_t);
int (*pSet64Static)(uint32_t, void*, int64_t);