summaryrefslogtreecommitdiffstats
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-03-25 17:19:53 -0700
committerAndreas Gampe <agampe@google.com>2015-03-27 21:43:21 -0700
commit81c6f8db12b203878a7d72444ead2bc7cf5c47ad (patch)
tree11caae30b75b700ac648356fd30759a6154be997 /runtime/class_linker.cc
parentcac51526bbd03947676a8d49700425b19a57e447 (diff)
downloadart-81c6f8db12b203878a7d72444ead2bc7cf5c47ad.zip
art-81c6f8db12b203878a7d72444ead2bc7cf5c47ad.tar.gz
art-81c6f8db12b203878a7d72444ead2bc7cf5c47ad.tar.bz2
ART: PathClassLoader for compiler
Use an actual PathClassLoader when compiling apps, instead of a side structure and cutout. This CL sets up a minimal object 'cluster' that recreates the Java side of a regular ClassLoader such that the Class-Linker will recognize it and use the internal native fast-path. This CL removes the now unnecessary compile-time-classpath and replaces it with a single 'compiling-the-boot-image' flag in the compiler callbacks. Note: This functionality is *only* intended for the compiler, as the objects have not been completely initialized. Bug: 19781184 Change-Id: I7f36af12dd7852d21281110a25c119e8c0669c1d
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc140
1 files changed, 105 insertions, 35 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 67872d7..b81a99a 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1372,38 +1372,6 @@ mirror::Class* ClassLinker::FindClass(Thread* self, const char* descriptor,
self->SetException(pre_allocated);
return nullptr;
}
- } else if (Runtime::Current()->UseCompileTimeClassPath()) {
- // First try with the bootstrap class loader.
- if (class_loader.Get() != nullptr) {
- klass = LookupClass(self, descriptor, hash, nullptr);
- if (klass != nullptr) {
- return EnsureResolved(self, descriptor, klass);
- }
- }
- // If the lookup failed search the boot class path. We don't perform a recursive call to avoid
- // a NoClassDefFoundError being allocated.
- ClassPathEntry pair = FindInClassPath(descriptor, hash, boot_class_path_);
- if (pair.second != nullptr) {
- return DefineClass(self, descriptor, hash, NullHandle<mirror::ClassLoader>(), *pair.first,
- *pair.second);
- }
- // Next try the compile time class path.
- const std::vector<const DexFile*>* class_path;
- {
- ScopedObjectAccessUnchecked soa(self);
- ScopedLocalRef<jobject> jclass_loader(soa.Env(),
- soa.AddLocalReference<jobject>(class_loader.Get()));
- class_path = &Runtime::Current()->GetCompileTimeClassPath(jclass_loader.get());
- }
- pair = FindInClassPath(descriptor, hash, *class_path);
- if (pair.second != nullptr) {
- return DefineClass(self, descriptor, hash, class_loader, *pair.first, *pair.second);
- } else {
- // Use the pre-allocated NCDFE at compile time to avoid wasting time constructing exceptions.
- mirror::Throwable* pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError();
- self->SetException(pre_allocated);
- return nullptr;
- }
} else {
ScopedObjectAccessUnchecked soa(self);
mirror::Class* cp_klass = FindClassInPathClassLoader(soa, self, descriptor, hash,
@@ -1411,6 +1379,14 @@ mirror::Class* ClassLinker::FindClass(Thread* self, const char* descriptor,
if (cp_klass != nullptr) {
return cp_klass;
}
+
+ if (Runtime::Current()->IsAotCompiler()) {
+ // Oops, compile-time, can't run actual class-loader code.
+ mirror::Throwable* pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError();
+ self->SetException(pre_allocated);
+ return nullptr;
+ }
+
ScopedLocalRef<jobject> class_loader_object(soa.Env(),
soa.AddLocalReference<jobject>(class_loader.Get()));
std::string class_name_string(DescriptorToDot(descriptor));
@@ -1767,7 +1743,7 @@ void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) {
return; // No direct methods => no static methods.
}
Runtime* runtime = Runtime::Current();
- if (!runtime->IsStarted() || runtime->UseCompileTimeClassPath()) {
+ if (!runtime->IsStarted()) {
if (runtime->IsAotCompiler() || runtime->GetHeap()->HasImageSpace()) {
return; // OAT file unavailable.
}
@@ -1907,7 +1883,7 @@ void ClassLinker::LoadClass(Thread* self, const DexFile& dex_file,
bool has_oat_class = false;
- if (Runtime::Current()->IsStarted() && !Runtime::Current()->UseCompileTimeClassPath()) {
+ if (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler()) {
OatFile::OatClass oat_class = FindOatClass(dex_file, klass->GetDexClassDefIndex(),
&has_oat_class);
if (has_oat_class) {
@@ -2808,7 +2784,7 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class
// classes.
if (Runtime::Current()->IsAotCompiler()) {
// Are we compiling the bootclasspath?
- if (!Runtime::Current()->UseCompileTimeClassPath()) {
+ if (Runtime::Current()->GetCompilerCallbacks()->IsBootImage()) {
return false;
}
// We are compiling an app (not the image).
@@ -5315,4 +5291,98 @@ bool ClassLinker::MayBeCalledWithDirectCodePointer(mirror::ArtMethod* m) {
}
}
+jobject ClassLinker::CreatePathClassLoader(Thread* self, std::vector<const DexFile*>& dex_files) {
+ // SOAAlreadyRunnable is protected, and we need something to add a global reference.
+ // We could move the jobject to the callers, but all call-sites do this...
+ ScopedObjectAccessUnchecked soa(self);
+
+ // Register the dex files.
+ for (const DexFile* dex_file : dex_files) {
+ RegisterDexFile(*dex_file);
+ }
+
+ // For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex.
+ StackHandleScope<11> hs(self);
+
+ Handle<mirror::ArtField> h_dex_elements_field =
+ hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements));
+
+ mirror::Class* dex_elements_class = h_dex_elements_field->GetType(true);
+ DCHECK(dex_elements_class != nullptr);
+ DCHECK(dex_elements_class->IsArrayClass());
+ Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements =
+ hs.NewHandle(reinterpret_cast<mirror::ObjectArray<mirror::Object>*>(
+ mirror::Array::Alloc<false>(self, dex_elements_class, dex_files.size(),
+ dex_elements_class->GetComponentSizeShift(),
+ Runtime::Current()->GetHeap()->GetCurrentAllocator())));
+ Handle<mirror::Class> h_dex_element_class =
+ hs.NewHandle(dex_elements_class->GetComponentType());
+
+ Handle<mirror::ArtField> h_element_file_field =
+ hs.NewHandle(
+ soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile));
+ DCHECK_EQ(h_dex_element_class.Get(), h_element_file_field->GetDeclaringClass());
+
+ Handle<mirror::ArtField> h_cookie_field =
+ hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie));
+ DCHECK_EQ(h_cookie_field->GetDeclaringClass(), h_element_file_field->GetType(false));
+
+ // Fill the elements array.
+ int32_t index = 0;
+ for (const DexFile* dex_file : dex_files) {
+ StackHandleScope<3> hs2(self);
+
+ Handle<mirror::LongArray> h_long_array = hs2.NewHandle(mirror::LongArray::Alloc(self, 1));
+ DCHECK(h_long_array.Get() != nullptr);
+ h_long_array->Set(0, reinterpret_cast<intptr_t>(dex_file));
+
+ Handle<mirror::Object> h_dex_file = hs2.NewHandle(
+ h_cookie_field->GetDeclaringClass()->AllocObject(self));
+ DCHECK(h_dex_file.Get() != nullptr);
+ h_cookie_field->SetObject<false>(h_dex_file.Get(), h_long_array.Get());
+
+ Handle<mirror::Object> h_element = hs2.NewHandle(h_dex_element_class->AllocObject(self));
+ DCHECK(h_element.Get() != nullptr);
+ h_element_file_field->SetObject<false>(h_element.Get(), h_dex_file.Get());
+
+ h_dex_elements->Set(index, h_element.Get());
+ index++;
+ }
+ DCHECK_EQ(index, h_dex_elements->GetLength());
+
+ // Create DexPathList.
+ Handle<mirror::Object> h_dex_path_list = hs.NewHandle(
+ h_dex_elements_field->GetDeclaringClass()->AllocObject(self));
+ DCHECK(h_dex_path_list.Get() != nullptr);
+ // Set elements.
+ h_dex_elements_field->SetObject<false>(h_dex_path_list.Get(), h_dex_elements.Get());
+
+ // Create PathClassLoader.
+ Handle<mirror::Class> h_path_class_class = hs.NewHandle(
+ soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader));
+ Handle<mirror::Object> h_path_class_loader = hs.NewHandle(
+ h_path_class_class->AllocObject(self));
+ DCHECK(h_path_class_loader.Get() != nullptr);
+ // Set DexPathList.
+ Handle<mirror::ArtField> h_path_list_field = hs.NewHandle(
+ soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList));
+ DCHECK(h_path_list_field.Get() != nullptr);
+ h_path_list_field->SetObject<false>(h_path_class_loader.Get(), h_dex_path_list.Get());
+
+ // Make a pretend boot-classpath.
+ // TODO: Should we scan the image?
+ Handle<mirror::ArtField> h_parent_field = hs.NewHandle(
+ mirror::Class::FindField(self, hs.NewHandle(h_path_class_loader->GetClass()), "parent",
+ "Ljava/lang/ClassLoader;"));
+ DCHECK(h_parent_field.Get() != nullptr);
+ mirror::Object* boot_cl =
+ soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_BootClassLoader)->AllocObject(self);
+ h_parent_field->SetObject<false>(h_path_class_loader.Get(), boot_cl);
+
+ // Make it a global ref and return.
+ ScopedLocalRef<jobject> local_ref(
+ soa.Env(), soa.Env()->AddLocalReference<jobject>(h_path_class_loader.Get()));
+ return soa.Env()->NewGlobalRef(local_ref.get());
+}
+
} // namespace art