diff options
-rw-r--r-- | build/Android.gtest.mk | 2 | ||||
-rw-r--r-- | compiler/common_compiler_test.cc | 3 | ||||
-rw-r--r-- | compiler/dex/quick_compiler_callbacks.h | 5 | ||||
-rw-r--r-- | compiler/driver/compiler_driver_test.cc | 5 | ||||
-rw-r--r-- | compiler/jit/jit_compiler.cc | 3 | ||||
-rw-r--r-- | compiler/oat_test.cc | 3 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 19 | ||||
-rw-r--r-- | oatdump/oatdump.cc | 6 | ||||
-rw-r--r-- | runtime/class_linker.cc | 140 | ||||
-rw-r--r-- | runtime/class_linker.h | 5 | ||||
-rw-r--r-- | runtime/class_linker_test.cc | 17 | ||||
-rw-r--r-- | runtime/common_runtime_test.cc | 82 | ||||
-rw-r--r-- | runtime/common_runtime_test.h | 7 | ||||
-rw-r--r-- | runtime/compiler_callbacks.h | 10 | ||||
-rw-r--r-- | runtime/jni_internal.cc | 6 | ||||
-rw-r--r-- | runtime/mirror/art_field.cc | 2 | ||||
-rw-r--r-- | runtime/mirror/object_test.cc | 3 | ||||
-rw-r--r-- | runtime/noop_compiler_callbacks.h | 2 | ||||
-rw-r--r-- | runtime/runtime.cc | 26 | ||||
-rw-r--r-- | runtime/runtime.h | 16 |
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_; |