summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/Android.gtest.mk2
-rw-r--r--compiler/common_compiler_test.cc3
-rw-r--r--compiler/dex/quick_compiler_callbacks.h5
-rw-r--r--compiler/driver/compiler_driver_test.cc5
-rw-r--r--compiler/jit/jit_compiler.cc3
-rw-r--r--compiler/oat_test.cc3
-rw-r--r--dex2oat/dex2oat.cc19
-rw-r--r--oatdump/oatdump.cc6
-rw-r--r--runtime/class_linker.cc140
-rw-r--r--runtime/class_linker.h5
-rw-r--r--runtime/class_linker_test.cc17
-rw-r--r--runtime/common_runtime_test.cc82
-rw-r--r--runtime/common_runtime_test.h7
-rw-r--r--runtime/compiler_callbacks.h10
-rw-r--r--runtime/jni_internal.cc6
-rw-r--r--runtime/mirror/art_field.cc2
-rw-r--r--runtime/mirror/object_test.cc3
-rw-r--r--runtime/noop_compiler_callbacks.h2
-rw-r--r--runtime/runtime.cc26
-rw-r--r--runtime/runtime.h16
20 files changed, 249 insertions, 113 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 91998fa..c5669c0 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -60,7 +60,7 @@ $(ART_TEST_TARGET_GTEST_MainStripped_DEX): $(ART_TEST_TARGET_GTEST_Main_DEX)
$(call dexpreopt-remove-classes.dex,$@)
# Dex file dependencies for each gtest.
-ART_GTEST_class_linker_test_DEX_DEPS := Interfaces MyClass Nested Statics StaticsFromCode
+ART_GTEST_class_linker_test_DEX_DEPS := Interfaces MultiDex MyClass Nested Statics StaticsFromCode
ART_GTEST_compiler_driver_test_DEX_DEPS := AbstractMethod
ART_GTEST_dex_file_test_DEX_DEPS := GetMethodSignature Main Nested
ART_GTEST_exception_test_DEX_DEPS := ExceptionHandle
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index 09be437..d506cc2 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -178,7 +178,8 @@ void CommonCompilerTest::SetUpRuntimeOptions(RuntimeOptions* options) {
verification_results_.reset(new VerificationResults(compiler_options_.get()));
method_inliner_map_.reset(new DexFileToMethodInlinerMap);
callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
- method_inliner_map_.get()));
+ method_inliner_map_.get(),
+ false));
options->push_back(std::make_pair("compilercallbacks", callbacks_.get()));
}
diff --git a/compiler/dex/quick_compiler_callbacks.h b/compiler/dex/quick_compiler_callbacks.h
index cdf71b6..56706e3 100644
--- a/compiler/dex/quick_compiler_callbacks.h
+++ b/compiler/dex/quick_compiler_callbacks.h
@@ -27,8 +27,9 @@ class DexFileToMethodInlinerMap;
class QuickCompilerCallbacks FINAL : public CompilerCallbacks {
public:
QuickCompilerCallbacks(VerificationResults* verification_results,
- DexFileToMethodInlinerMap* method_inliner_map)
- : verification_results_(verification_results),
+ DexFileToMethodInlinerMap* method_inliner_map,
+ bool boot_image)
+ : CompilerCallbacks(boot_image), verification_results_(verification_results),
method_inliner_map_(method_inliner_map) {
CHECK(verification_results != nullptr);
CHECK(method_inliner_map != nullptr);
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index a02e25e..5ebc029 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -41,7 +41,7 @@ class CompilerDriverTest : public CommonCompilerTest {
TimingLogger timings("CompilerDriverTest::CompileAll", false, false);
TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
compiler_driver_->CompileAll(class_loader,
- Runtime::Current()->GetCompileTimeClassPath(class_loader),
+ GetDexFiles(class_loader),
&timings);
t.NewTiming("MakeAllExecutable");
MakeAllExecutable(class_loader);
@@ -66,8 +66,7 @@ class CompilerDriverTest : public CommonCompilerTest {
}
void MakeAllExecutable(jobject class_loader) {
- const std::vector<const DexFile*>& class_path
- = Runtime::Current()->GetCompileTimeClassPath(class_loader);
+ const std::vector<const DexFile*> class_path = GetDexFiles(class_loader);
for (size_t i = 0; i != class_path.size(); ++i) {
const DexFile* dex_file = class_path[i];
CHECK(dex_file != NULL);
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index 8b31154..d034736 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -89,7 +89,8 @@ JitCompiler::JitCompiler() : total_time_(0) {
verification_results_.reset(new VerificationResults(compiler_options_.get()));
method_inliner_map_.reset(new DexFileToMethodInlinerMap);
callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
- method_inliner_map_.get()));
+ method_inliner_map_.get(),
+ false));
compiler_driver_.reset(new CompilerDriver(
compiler_options_.get(), verification_results_.get(), method_inliner_map_.get(),
Compiler::kQuick, instruction_set, instruction_set_features_.get(), false,
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index c426625..440c1b6 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -86,7 +86,8 @@ TEST_F(OatTest, WriteRead) {
verification_results_.reset(new VerificationResults(compiler_options_.get()));
method_inliner_map_.reset(new DexFileToMethodInlinerMap);
callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
- method_inliner_map_.get()));
+ method_inliner_map_.get(),
+ false));
timer_.reset(new CumulativeLogger("Compilation times"));
compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
verification_results_.get(),
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index dfea783..f1cd30a 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1053,7 +1053,9 @@ class Dex2Oat FINAL {
}
verification_results_.reset(new VerificationResults(compiler_options_.get()));
- callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(), &method_inliner_map_));
+ callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
+ &method_inliner_map_,
+ image_));
runtime_options.push_back(std::make_pair("compilercallbacks", callbacks_.get()));
runtime_options.push_back(
std::make_pair("imageinstructionset", GetInstructionSetString(instruction_set_)));
@@ -1224,19 +1226,16 @@ class Dex2Oat FINAL {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
OpenClassPathFiles(runtime_->GetClassPathString(), dex_files_, &class_path_files_);
ScopedObjectAccess soa(self);
- std::vector<const DexFile*> class_path_files(dex_files_);
+
+ // Classpath: first the class-path given.
+ std::vector<const DexFile*> class_path_files;
for (auto& class_path_file : class_path_files_) {
class_path_files.push_back(class_path_file.get());
}
+ // Then the dex files we'll compile. Thus we'll resolve the class-path first.
+ class_path_files.insert(class_path_files.end(), dex_files_.begin(), dex_files_.end());
- for (size_t i = 0; i < class_path_files.size(); i++) {
- class_linker->RegisterDexFile(*class_path_files[i]);
- }
- soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader);
- ScopedLocalRef<jobject> class_loader_local(soa.Env(),
- soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
- class_loader = soa.Env()->NewGlobalRef(class_loader_local.get());
- Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path_files);
+ class_loader = class_linker->CreatePathClassLoader(self, class_path_files);
}
driver_.reset(new CompilerDriver(compiler_options_.get(),
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index daca971..7bde471 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -2158,16 +2158,12 @@ static int DumpOatWithRuntime(Runtime* runtime, OatFile* oat_file, OatDumperOpti
}
// Need a class loader.
- soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader);
- ScopedLocalRef<jobject> class_loader_local(soa.Env(),
- soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
- jobject class_loader = soa.Env()->NewGlobalRef(class_loader_local.get());
// Fake that we're a compiler.
std::vector<const DexFile*> class_path;
for (auto& dex_file : dex_files) {
class_path.push_back(dex_file.get());
}
- runtime->SetCompileTimeClassPath(class_loader, class_path);
+ jobject class_loader = class_linker->CreatePathClassLoader(self, class_path);
// Use the class loader while dumping.
StackHandleScope<1> scope(self);
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
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 4ebce3e..88a2501 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -454,6 +454,11 @@ class ClassLinker {
bool MayBeCalledWithDirectCodePointer(mirror::ArtMethod* m)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Creates a GlobalRef PathClassLoader that can be used to load classes from the given dex files.
+ // Note: the objects are not completely set up. Do not use this outside of tests and the compiler.
+ jobject CreatePathClassLoader(Thread* self, std::vector<const DexFile*>& dex_files)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
private:
static void InitFromImageInterpretOnlyCallback(mirror::Object* obj, void* arg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 1789ab1..a895a49 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -621,6 +621,20 @@ TEST_F(ClassLinkerTest, FindClassNonexistent) {
AssertNonExistentClass("LNoSuchClass;");
}
+TEST_F(ClassLinkerTest, GetDexFiles) {
+ ScopedObjectAccess soa(Thread::Current());
+
+ jobject jclass_loader = LoadDex("Nested");
+ std::vector<const DexFile*> dex_files(GetDexFiles(jclass_loader));
+ ASSERT_EQ(dex_files.size(), 1U);
+ EXPECT_TRUE(EndsWith(dex_files[0]->GetLocation(), "Nested.jar"));
+
+ jobject jclass_loader2 = LoadDex("MultiDex");
+ std::vector<const DexFile*> dex_files2(GetDexFiles(jclass_loader2));
+ ASSERT_EQ(dex_files2.size(), 2U);
+ EXPECT_TRUE(EndsWith(dex_files2[0]->GetLocation(), "MultiDex.jar"));
+}
+
TEST_F(ClassLinkerTest, FindClassNested) {
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<1> hs(soa.Self());
@@ -985,11 +999,10 @@ TEST_F(ClassLinkerTest, ResolveVerifyAndClinit) {
ScopedObjectAccess soa(Thread::Current());
jobject jclass_loader = LoadDex("StaticsFromCode");
+ const DexFile* dex_file = GetFirstDexFile(jclass_loader);
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
- const DexFile* dex_file = Runtime::Current()->GetCompileTimeClassPath(jclass_loader)[0];
- CHECK(dex_file != nullptr);
mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", class_loader);
mirror::ArtMethod* clinit = klass->FindClassInitializer();
mirror::ArtMethod* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;");
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index e0d62d7..4104509 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -34,6 +34,7 @@
#include "gc_root-inl.h"
#include "gc/heap.h"
#include "gtest/gtest.h"
+#include "handle_scope-inl.h"
#include "interpreter/unstarted_runtime.h"
#include "jni_internal.h"
#include "mirror/class_loader.h"
@@ -386,22 +387,89 @@ std::unique_ptr<const DexFile> CommonRuntimeTest::OpenTestDexFile(const char* na
return std::move(vector[0]);
}
+std::vector<const DexFile*> CommonRuntimeTest::GetDexFiles(jobject jclass_loader) {
+ std::vector<const DexFile*> ret;
+
+ ScopedObjectAccess soa(Thread::Current());
+
+ StackHandleScope<4> hs(Thread::Current());
+ Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
+ soa.Decode<mirror::ClassLoader*>(jclass_loader));
+
+ DCHECK_EQ(class_loader->GetClass(),
+ soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader));
+ DCHECK_EQ(class_loader->GetParent()->GetClass(),
+ soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_BootClassLoader));
+
+ // The class loader is a PathClassLoader which inherits from BaseDexClassLoader.
+ // We need to get the DexPathList and loop through it.
+ Handle<mirror::ArtField> cookie_field =
+ hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie));
+ Handle<mirror::ArtField> dex_file_field =
+ hs.NewHandle(
+ soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile));
+ mirror::Object* dex_path_list =
+ soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)->
+ GetObject(class_loader.Get());
+ if (dex_path_list != nullptr && dex_file_field.Get() != nullptr &&
+ cookie_field.Get() != nullptr) {
+ // DexPathList has an array dexElements of Elements[] which each contain a dex file.
+ mirror::Object* dex_elements_obj =
+ soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)->
+ GetObject(dex_path_list);
+ // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look
+ // at the mCookie which is a DexFile vector.
+ if (dex_elements_obj != nullptr) {
+ Handle<mirror::ObjectArray<mirror::Object>> dex_elements =
+ hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>());
+ for (int32_t i = 0; i < dex_elements->GetLength(); ++i) {
+ mirror::Object* element = dex_elements->GetWithoutChecks(i);
+ if (element == nullptr) {
+ // Should never happen, fall back to java code to throw a NPE.
+ break;
+ }
+ mirror::Object* dex_file = dex_file_field->GetObject(element);
+ if (dex_file != nullptr) {
+ mirror::LongArray* long_array = cookie_field->GetObject(dex_file)->AsLongArray();
+ DCHECK(long_array != nullptr);
+ int32_t long_array_size = long_array->GetLength();
+ for (int32_t j = 0; j < long_array_size; ++j) {
+ const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(
+ long_array->GetWithoutChecks(j)));
+ if (cp_dex_file == nullptr) {
+ LOG(WARNING) << "Null DexFile";
+ continue;
+ }
+ ret.push_back(cp_dex_file);
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+const DexFile* CommonRuntimeTest::GetFirstDexFile(jobject jclass_loader) {
+ std::vector<const DexFile*> tmp(GetDexFiles(jclass_loader));
+ DCHECK(!tmp.empty());
+ const DexFile* ret = tmp[0];
+ DCHECK(ret != nullptr);
+ return ret;
+}
+
jobject CommonRuntimeTest::LoadDex(const char* dex_name) {
std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(dex_name);
std::vector<const DexFile*> class_path;
CHECK_NE(0U, dex_files.size());
for (auto& dex_file : dex_files) {
class_path.push_back(dex_file.get());
- class_linker_->RegisterDexFile(*dex_file);
loaded_dex_files_.push_back(std::move(dex_file));
}
+
Thread* self = Thread::Current();
- JNIEnvExt* env = self->GetJniEnv();
- ScopedLocalRef<jobject> class_loader_local(env,
- env->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
- jobject class_loader = env->NewGlobalRef(class_loader_local.get());
- self->SetClassLoaderOverride(class_loader_local.get());
- Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path);
+ jobject class_loader = Runtime::Current()->GetClassLinker()->CreatePathClassLoader(self, class_path);
+ self->SetClassLoaderOverride(class_loader);
return class_loader;
}
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index cce8485..a29487f 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -133,6 +133,13 @@ class CommonRuntimeTest : public testing::Test {
const DexFile* java_lang_dex_file_;
std::vector<const DexFile*> boot_class_path_;
+ // Get the dex files from a PathClassLoader. This in order of the dex elements and their dex
+ // arrays.
+ std::vector<const DexFile*> GetDexFiles(jobject jclass_loader);
+
+ // Get the first dex file from a PathClassLoader. Will abort if it is null.
+ const DexFile* GetFirstDexFile(jobject jclass_loader);
+
private:
static std::string GetCoreFileLocation(const char* suffix);
diff --git a/runtime/compiler_callbacks.h b/runtime/compiler_callbacks.h
index d1a6861..3fabe3e 100644
--- a/runtime/compiler_callbacks.h
+++ b/runtime/compiler_callbacks.h
@@ -40,8 +40,16 @@ class CompilerCallbacks {
// done so. Return false if relocating in this way would be problematic.
virtual bool IsRelocationPossible() = 0;
+ bool IsBootImage() {
+ return boot_image_;
+ }
+
protected:
- CompilerCallbacks() { }
+ explicit CompilerCallbacks(bool boot_image) : boot_image_(boot_image) { }
+
+ private:
+ // Whether the compiler is creating a boot image.
+ const bool boot_image_;
};
} // namespace art
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 6063e1e..566b097 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -164,8 +164,10 @@ static mirror::ClassLoader* GetClassLoader(const ScopedObjectAccess& soa)
// See if the override ClassLoader is set for gtests.
class_loader = soa.Decode<mirror::ClassLoader*>(soa.Self()->GetClassLoaderOverride());
if (class_loader != nullptr) {
- // If so, CommonCompilerTest should have set UseCompileTimeClassPath.
- CHECK(Runtime::Current()->UseCompileTimeClassPath());
+ // If so, CommonCompilerTest should have marked the runtime as a compiler not compiling an
+ // image.
+ CHECK(Runtime::Current()->IsAotCompiler());
+ CHECK(!Runtime::Current()->GetCompilerCallbacks()->IsBootImage());
return class_loader;
}
// Use the BOOTCLASSPATH.
diff --git a/runtime/mirror/art_field.cc b/runtime/mirror/art_field.cc
index 3cea4a1..5d543a1 100644
--- a/runtime/mirror/art_field.cc
+++ b/runtime/mirror/art_field.cc
@@ -45,7 +45,7 @@ void ArtField::ResetClass() {
void ArtField::SetOffset(MemberOffset num_bytes) {
DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
if (kIsDebugBuild && Runtime::Current()->IsAotCompiler() &&
- !Runtime::Current()->UseCompileTimeClassPath()) {
+ Runtime::Current()->GetCompilerCallbacks()->IsBootImage()) {
Primitive::Type type = GetTypeAsPrimitiveType();
if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) {
DCHECK_ALIGNED(num_bytes.Uint32Value(), 8);
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 21972a1..1ce298d 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -360,8 +360,7 @@ TEST_F(ObjectTest, StaticFieldFromCode) {
// pretend we are trying to access 'Static.s0' from StaticsFromCode.<clinit>
ScopedObjectAccess soa(Thread::Current());
jobject class_loader = LoadDex("StaticsFromCode");
- const DexFile* dex_file = Runtime::Current()->GetCompileTimeClassPath(class_loader)[0];
- CHECK(dex_file != NULL);
+ const DexFile* dex_file = GetFirstDexFile(class_loader);
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<ClassLoader*>(class_loader)));
diff --git a/runtime/noop_compiler_callbacks.h b/runtime/noop_compiler_callbacks.h
index 300abc9..a40659e 100644
--- a/runtime/noop_compiler_callbacks.h
+++ b/runtime/noop_compiler_callbacks.h
@@ -23,7 +23,7 @@ namespace art {
class NoopCompilerCallbacks FINAL : public CompilerCallbacks {
public:
- NoopCompilerCallbacks() {}
+ NoopCompilerCallbacks() : CompilerCallbacks(false) {}
~NoopCompilerCallbacks() {}
bool MethodVerified(verifier::MethodVerifier* verifier ATTRIBUTE_UNUSED) OVERRIDE {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 9ca00b1..ffe3dc6 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -163,7 +163,6 @@ Runtime::Runtime()
method_trace_(false),
method_trace_file_size_(0),
instrumentation_(),
- use_compile_time_class_path_(false),
main_thread_group_(nullptr),
system_thread_group_(nullptr),
system_class_loader_(nullptr),
@@ -405,9 +404,9 @@ bool Runtime::Create(const RuntimeOptions& options, bool ignore_unrecognized) {
return true;
}
-static jobject CreateSystemClassLoader() {
- if (Runtime::Current()->UseCompileTimeClassPath()) {
- return NULL;
+static jobject CreateSystemClassLoader(Runtime* runtime) {
+ if (runtime->IsAotCompiler() && !runtime->GetCompilerCallbacks()->IsBootImage()) {
+ return nullptr;
}
ScopedObjectAccess soa(Thread::Current());
@@ -505,7 +504,7 @@ bool Runtime::Start() {
Thread::FinishStartup();
- system_class_loader_ = CreateSystemClassLoader();
+ system_class_loader_ = CreateSystemClassLoader(this);
if (is_zygote_) {
if (!InitZygote()) {
@@ -1483,23 +1482,6 @@ void Runtime::SetCalleeSaveMethod(mirror::ArtMethod* method, CalleeSaveType type
callee_save_methods_[type] = GcRoot<mirror::ArtMethod>(method);
}
-const std::vector<const DexFile*>& Runtime::GetCompileTimeClassPath(jobject class_loader) {
- if (class_loader == NULL) {
- return GetClassLinker()->GetBootClassPath();
- }
- CHECK(UseCompileTimeClassPath());
- CompileTimeClassPaths::const_iterator it = compile_time_class_paths_.find(class_loader);
- CHECK(it != compile_time_class_paths_.end());
- return it->second;
-}
-
-void Runtime::SetCompileTimeClassPath(jobject class_loader,
- std::vector<const DexFile*>& class_path) {
- CHECK(!IsStarted());
- use_compile_time_class_path_ = true;
- compile_time_class_paths_.Put(class_loader, class_path);
-}
-
void Runtime::StartProfiler(const char* profile_output_filename) {
profile_output_filename_ = profile_output_filename;
profiler_started_ =
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 9a04835..7181097 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -452,16 +452,6 @@ class Runtime {
return &instrumentation_;
}
- bool UseCompileTimeClassPath() const {
- return use_compile_time_class_path_;
- }
-
- const std::vector<const DexFile*>& GetCompileTimeClassPath(jobject class_loader);
-
- // The caller is responsible for ensuring the class_path DexFiles remain
- // valid as long as the Runtime object remains valid.
- void SetCompileTimeClassPath(jobject class_loader, std::vector<const DexFile*>& class_path);
-
void StartProfiler(const char* profile_output_filename);
void UpdateProfilerState(int state);
@@ -685,12 +675,6 @@ class Runtime {
size_t method_trace_file_size_;
instrumentation::Instrumentation instrumentation_;
- typedef AllocationTrackingSafeMap<jobject, std::vector<const DexFile*>,
- kAllocatorTagCompileTimeClassPath, JobjectComparator>
- CompileTimeClassPaths;
- CompileTimeClassPaths compile_time_class_paths_;
- bool use_compile_time_class_path_;
-
jobject main_thread_group_;
jobject system_thread_group_;