summaryrefslogtreecommitdiff
path: root/src/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/class_linker.cc')
-rw-r--r--src/class_linker.cc103
1 files changed, 53 insertions, 50 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc
index cfad9d1b7d..0fae4248e9 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -44,7 +44,7 @@
#include "mirror/class.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
-#include "mirror/dex_cache.h"
+#include "mirror/dex_cache-inl.h"
#include "mirror/field-inl.h"
#include "mirror/iftable-inl.h"
#include "mirror/abstract_method.h"
@@ -74,7 +74,9 @@
namespace art {
-void artInterpreterToQuickEntry(Thread* self, ShadowFrame* shadow_frame, JValue* result);
+extern "C" void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh,
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
static void ThrowNoClassDefFoundError(const char* fmt, ...)
__attribute__((__format__(__printf__, 1, 2)))
@@ -195,12 +197,14 @@ ClassLinker* ClassLinker::CreateFromImage(InternTable* intern_table) {
ClassLinker::ClassLinker(InternTable* intern_table)
// dex_lock_ is recursive as it may be used in stack dumping.
- : dex_lock_("ClassLinker dex lock", kDefaultMutexLevel, true),
+ : dex_lock_("ClassLinker dex lock", kDefaultMutexLevel),
class_roots_(NULL),
array_iftable_(NULL),
init_done_(false),
is_dirty_(false),
- intern_table_(intern_table) {
+ intern_table_(intern_table),
+ portable_resolution_trampoline_(NULL),
+ quick_resolution_trampoline_(NULL) {
CHECK_EQ(arraysize(class_roots_descriptors_), size_t(kClassRootsMax));
}
@@ -662,22 +666,22 @@ bool ClassLinker::GenerateOatFile(const std::string& dex_filename,
}
void ClassLinker::RegisterOatFile(const OatFile& oat_file) {
- MutexLock mu(Thread::Current(), dex_lock_);
+ WriterMutexLock mu(Thread::Current(), dex_lock_);
RegisterOatFileLocked(oat_file);
}
void ClassLinker::RegisterOatFileLocked(const OatFile& oat_file) {
- dex_lock_.AssertHeld(Thread::Current());
-#ifndef NDEBUG
- for (size_t i = 0; i < oat_files_.size(); ++i) {
- CHECK_NE(&oat_file, oat_files_[i]) << oat_file.GetLocation();
+ dex_lock_.AssertExclusiveHeld(Thread::Current());
+ if (kIsDebugBuild) {
+ for (size_t i = 0; i < oat_files_.size(); ++i) {
+ CHECK_NE(&oat_file, oat_files_[i]) << oat_file.GetLocation();
+ }
}
-#endif
oat_files_.push_back(&oat_file);
}
OatFile* ClassLinker::OpenOat(const ImageSpace* space) {
- MutexLock mu(Thread::Current(), dex_lock_);
+ WriterMutexLock mu(Thread::Current(), dex_lock_);
const Runtime* runtime = Runtime::Current();
const ImageHeader& image_header = space->GetImageHeader();
// Grab location but don't use Object::AsString as we haven't yet initialized the roots to
@@ -708,7 +712,7 @@ OatFile* ClassLinker::OpenOat(const ImageSpace* space) {
}
const OatFile* ClassLinker::FindOpenedOatFileForDexFile(const DexFile& dex_file) {
- MutexLock mu(Thread::Current(), dex_lock_);
+ ReaderMutexLock mu(Thread::Current(), dex_lock_);
return FindOpenedOatFileFromDexLocation(dex_file.GetLocation());
}
@@ -754,7 +758,7 @@ static const DexFile* FindDexFileInOatLocation(const std::string& dex_location,
const DexFile* ClassLinker::FindOrCreateOatFileForDexLocation(const std::string& dex_location,
const std::string& oat_location) {
- MutexLock mu(Thread::Current(), dex_lock_);
+ WriterMutexLock mu(Thread::Current(), dex_lock_);
return FindOrCreateOatFileForDexLocationLocked(dex_location, oat_location);
}
@@ -856,7 +860,7 @@ const DexFile* ClassLinker::VerifyAndOpenDexFileFromOatFile(const OatFile* oat_f
}
const DexFile* ClassLinker::FindDexFileInOatFileFromDexLocation(const std::string& dex_location) {
- MutexLock mu(Thread::Current(), dex_lock_);
+ WriterMutexLock mu(Thread::Current(), dex_lock_);
const OatFile* open_oat_file = FindOpenedOatFileFromDexLocation(dex_location);
if (open_oat_file != NULL) {
@@ -923,7 +927,7 @@ const OatFile* ClassLinker::FindOpenedOatFileFromOatLocation(const std::string&
}
const OatFile* ClassLinker::FindOatFileFromOatLocation(const std::string& oat_location) {
- MutexLock mu(Thread::Current(), dex_lock_);
+ ReaderMutexLock mu(Thread::Current(), dex_lock_);
return FindOatFileFromOatLocationLocked(oat_location);
}
@@ -951,6 +955,8 @@ void ClassLinker::InitFromImage() {
CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationOatChecksum(), 0U);
CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationOatDataBegin(), 0U);
CHECK(oat_file->GetOatHeader().GetImageFileLocation().empty());
+ portable_resolution_trampoline_ = oat_file->GetOatHeader().GetPortableResolutionTrampoline();
+ quick_resolution_trampoline_ = oat_file->GetOatHeader().GetQuickResolutionTrampoline();
mirror::Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
mirror::ObjectArray<mirror::DexCache>* dex_caches =
dex_caches_object->AsObjectArray<mirror::DexCache>();
@@ -1037,17 +1043,12 @@ void ClassLinker::InitFromImageCallback(mirror::Object* obj, void* arg) {
return;
}
- // Check if object is a method without its code set and point it to the resolution trampoline.
+ // Set entry points to interpreter for methods in interpreter only mode.
if (obj->IsMethod()) {
mirror::AbstractMethod* method = obj->AsMethod();
- // Install entry point from interpreter.
- if (method->GetEntryPointFromCompiledCode() == NULL && !method->IsNative() && !method->IsProxyMethod()) {
- method->SetEntryPointFromInterpreter(interpreter::EnterInterpreterFromInterpreter);
- } else {
- method->SetEntryPointFromInterpreter(artInterpreterToQuickEntry);
- }
- if (method->GetEntryPointFromCompiledCode() == NULL) {
- method->SetEntryPointFromCompiledCode(GetResolutionTrampoline());
+ if (Runtime::Current()->GetInstrumentation()->InterpretOnly() && !method->IsNative()) {
+ method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterEntry);
+ method->SetEntryPointFromCompiledCode(GetInterpreterEntryPoint());
}
}
}
@@ -1059,14 +1060,14 @@ void ClassLinker::VisitRoots(RootVisitor* visitor, void* arg) {
visitor(class_roots_, arg);
Thread* self = Thread::Current();
{
- MutexLock mu(self, dex_lock_);
+ ReaderMutexLock mu(self, dex_lock_);
for (size_t i = 0; i < dex_caches_.size(); i++) {
visitor(dex_caches_[i], arg);
}
}
{
- MutexLock mu(self, *Locks::classlinker_classes_lock_);
+ ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) {
visitor(it->second, arg);
@@ -1081,7 +1082,7 @@ void ClassLinker::VisitRoots(RootVisitor* visitor, void* arg) {
}
void ClassLinker::VisitClasses(ClassVisitor* visitor, void* arg) const {
- MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+ ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) {
if (!visitor(it->second, arg)) {
@@ -1608,14 +1609,16 @@ static void LinkCode(SirtRef<mirror::AbstractMethod>& method, const OatFile::Oat
oat_method.LinkMethod(method.get());
// Install entry point from interpreter.
- if (method->GetEntryPointFromCompiledCode() == NULL && !method->IsNative() &&
- !method->IsProxyMethod()) {
- method->SetEntryPointFromInterpreter(interpreter::EnterInterpreterFromInterpreter);
+ Runtime* runtime = Runtime::Current();
+ bool enter_interpreter = method->GetEntryPointFromCompiledCode() == NULL ||
+ (runtime->GetInstrumentation()->InterpretOnly() &&
+ !method->IsNative() && !method->IsProxyMethod());
+ if (enter_interpreter) {
+ method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterEntry);
} else {
method->SetEntryPointFromInterpreter(artInterpreterToQuickEntry);
}
- Runtime* runtime = Runtime::Current();
if (method->IsAbstract()) {
method->SetEntryPointFromCompiledCode(GetAbstractMethodErrorStub());
return;
@@ -1623,7 +1626,7 @@ static void LinkCode(SirtRef<mirror::AbstractMethod>& method, const OatFile::Oat
if (method->IsStatic() && !method->IsConstructor()) {
// For static methods excluding the class initializer, install the trampoline.
- method->SetEntryPointFromCompiledCode(GetResolutionTrampoline());
+ method->SetEntryPointFromCompiledCode(GetResolutionTrampoline(runtime->GetClassLinker()));
}
if (method->IsNative()) {
@@ -1631,8 +1634,8 @@ static void LinkCode(SirtRef<mirror::AbstractMethod>& method, const OatFile::Oat
method->UnregisterNative(Thread::Current());
}
- if (method->GetEntryPointFromCompiledCode() == NULL) {
- // No code? You must mean to go into the interpreter.
+ if (enter_interpreter) {
+ // Set entry point from compiled code if there's no code or in interpreter only mode.
method->SetEntryPointFromCompiledCode(GetInterpreterEntryPoint());
}
@@ -1807,7 +1810,7 @@ void ClassLinker::AppendToBootClassPath(const DexFile& dex_file, SirtRef<mirror:
}
bool ClassLinker::IsDexFileRegisteredLocked(const DexFile& dex_file) const {
- dex_lock_.AssertHeld(Thread::Current());
+ dex_lock_.AssertSharedHeld(Thread::Current());
for (size_t i = 0; i != dex_caches_.size(); ++i) {
if (dex_caches_[i]->GetDexFile() == &dex_file) {
return true;
@@ -1817,12 +1820,12 @@ bool ClassLinker::IsDexFileRegisteredLocked(const DexFile& dex_file) const {
}
bool ClassLinker::IsDexFileRegistered(const DexFile& dex_file) const {
- MutexLock mu(Thread::Current(), dex_lock_);
+ ReaderMutexLock mu(Thread::Current(), dex_lock_);
return IsDexFileRegisteredLocked(dex_file);
}
void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) {
- dex_lock_.AssertHeld(Thread::Current());
+ dex_lock_.AssertExclusiveHeld(Thread::Current());
CHECK(dex_cache.get() != NULL) << dex_file.GetLocation();
CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation()));
dex_caches_.push_back(dex_cache.get());
@@ -1833,7 +1836,7 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, SirtRef<mirror:
void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
Thread* self = Thread::Current();
{
- MutexLock mu(self, dex_lock_);
+ ReaderMutexLock mu(self, dex_lock_);
if (IsDexFileRegisteredLocked(dex_file)) {
return;
}
@@ -1843,7 +1846,7 @@ void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
// get to a suspend point.
SirtRef<mirror::DexCache> dex_cache(self, AllocDexCache(self, dex_file));
{
- MutexLock mu(self, dex_lock_);
+ WriterMutexLock mu(self, dex_lock_);
if (IsDexFileRegisteredLocked(dex_file)) {
return;
}
@@ -1852,12 +1855,12 @@ void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
}
void ClassLinker::RegisterDexFile(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) {
- MutexLock mu(Thread::Current(), dex_lock_);
+ WriterMutexLock mu(Thread::Current(), dex_lock_);
RegisterDexFileLocked(dex_file, dex_cache);
}
mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const {
- MutexLock mu(Thread::Current(), dex_lock_);
+ ReaderMutexLock mu(Thread::Current(), dex_lock_);
// Search assuming unique-ness of dex file.
for (size_t i = 0; i != dex_caches_.size(); ++i) {
mirror::DexCache* dex_cache = dex_caches_[i];
@@ -1883,7 +1886,7 @@ mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const {
}
void ClassLinker::FixupDexCaches(mirror::AbstractMethod* resolution_method) const {
- MutexLock mu(Thread::Current(), dex_lock_);
+ ReaderMutexLock mu(Thread::Current(), dex_lock_);
for (size_t i = 0; i != dex_caches_.size(); ++i) {
dex_caches_[i]->Fixup(resolution_method);
}
@@ -2079,7 +2082,7 @@ mirror::Class* ClassLinker::InsertClass(const StringPiece& descriptor, mirror::C
LOG(INFO) << "Loaded class " << descriptor << source;
}
size_t hash = StringPieceHash()(descriptor);
- MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+ WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
Table& classes = image_class ? image_classes_ : classes_;
mirror::Class* existing = LookupClassLocked(descriptor.data(), klass->GetClassLoader(), hash, classes);
#ifndef NDEBUG
@@ -2097,7 +2100,7 @@ mirror::Class* ClassLinker::InsertClass(const StringPiece& descriptor, mirror::C
bool ClassLinker::RemoveClass(const char* descriptor, const mirror::ClassLoader* class_loader) {
size_t hash = Hash(descriptor);
- MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+ WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
typedef Table::iterator It; // TODO: C++0x auto
// TODO: determine if its better to search classes_ or image_classes_ first
ClassHelper kh;
@@ -2125,7 +2128,7 @@ bool ClassLinker::RemoveClass(const char* descriptor, const mirror::ClassLoader*
mirror::Class* ClassLinker::LookupClass(const char* descriptor,
const mirror::ClassLoader* class_loader) {
size_t hash = Hash(descriptor);
- MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+ ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
// TODO: determine if its better to search classes_ or image_classes_ first
mirror::Class* klass = NULL;
// Use image class only if the class_loader is null.
@@ -2165,7 +2168,7 @@ mirror::Class* ClassLinker::LookupClassLocked(const char* descriptor,
void ClassLinker::LookupClasses(const char* descriptor, std::vector<mirror::Class*>& classes) {
classes.clear();
size_t hash = Hash(descriptor);
- MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+ ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
// TODO: determine if its better to search classes_ or image_classes_ first
ClassHelper kh(NULL, this);
@@ -2499,7 +2502,7 @@ mirror::AbstractMethod* ClassLinker::FindMethodForProxy(const mirror::Class* pro
mirror::DexCache* dex_cache = NULL;
{
mirror::ObjectArray<mirror::Class>* resolved_types = proxy_method->GetDexCacheResolvedTypes();
- MutexLock mu(Thread::Current(), dex_lock_);
+ ReaderMutexLock mu(Thread::Current(), dex_lock_);
for (size_t i = 0; i != dex_caches_.size(); ++i) {
if (dex_caches_[i]->GetResolvedTypes() == resolved_types) {
dex_cache = dex_caches_[i];
@@ -3880,7 +3883,7 @@ void ClassLinker::DumpAllClasses(int flags) const {
// lock held, because it might need to resolve a field's type, which would try to take the lock.
std::vector<mirror::Class*> all_classes;
{
- MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+ ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) {
all_classes.push_back(it->second);
@@ -3896,13 +3899,13 @@ void ClassLinker::DumpAllClasses(int flags) const {
}
void ClassLinker::DumpForSigQuit(std::ostream& os) const {
- MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+ ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
os << "Loaded classes: " << image_classes_.size() << " image classes; "
<< classes_.size() << " allocated classes\n";
}
size_t ClassLinker::NumLoadedClasses() const {
- MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+ ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
return classes_.size() + image_classes_.size();
}