diff options
author | Mathieu Chartier <mathieuc@google.com> | 2013-11-13 00:21:46 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-11-13 00:21:47 +0000 |
commit | 0b74e3acc2fd35d95ac55c4ee2ffe5c651229ed8 (patch) | |
tree | 2cba9a33810d360054749a358120b6951a469fb3 /compiler | |
parent | 686d6f3bf7a22bdc5e676a5e735bfaef314f4de8 (diff) | |
parent | 590fee9e8972f872301c2d16a575d579ee564bee (diff) | |
download | art-0b74e3acc2fd35d95ac55c4ee2ffe5c651229ed8.zip art-0b74e3acc2fd35d95ac55c4ee2ffe5c651229ed8.tar.gz art-0b74e3acc2fd35d95ac55c4ee2ffe5c651229ed8.tar.bz2 |
Merge "Compacting collector." into dalvik-dev
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/driver/compiler_driver.cc | 97 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 3 | ||||
-rw-r--r-- | compiler/driver/compiler_driver_test.cc | 9 | ||||
-rw-r--r-- | compiler/image_test.cc | 11 | ||||
-rw-r--r-- | compiler/image_writer.cc | 346 | ||||
-rw-r--r-- | compiler/image_writer.h | 48 | ||||
-rw-r--r-- | compiler/jni/jni_compiler_test.cc | 4 | ||||
-rw-r--r-- | compiler/oat_test.cc | 3 | ||||
-rw-r--r-- | compiler/oat_writer.cc | 37 |
9 files changed, 292 insertions, 266 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 9cc94e8..4af492b 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -513,10 +513,9 @@ void CompilerDriver::CompileAll(jobject class_loader, } } -static DexToDexCompilationLevel GetDexToDexCompilationlevel(mirror::ClassLoader* class_loader, - const DexFile& dex_file, - const DexFile::ClassDef& class_def) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +static DexToDexCompilationLevel GetDexToDexCompilationlevel( + SirtRef<mirror::ClassLoader>& class_loader, const DexFile& dex_file, + const DexFile::ClassDef& class_def) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const char* descriptor = dex_file.GetClassDescriptor(class_def); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); mirror::Class* klass = class_linker->FindClass(descriptor, class_loader); @@ -531,7 +530,7 @@ static DexToDexCompilationLevel GetDexToDexCompilationlevel(mirror::ClassLoader* // function). Since image classes can be verified again while compiling an application, // we must prevent the DEX-to-DEX compiler from introducing them. // TODO: find a way to enable "quick" instructions for image classes and remove this check. - bool compiling_image_classes = (class_loader == NULL); + bool compiling_image_classes = class_loader.get() == nullptr; if (compiling_image_classes) { return kRequired; } else if (klass->IsVerified()) { @@ -579,7 +578,8 @@ void CompilerDriver::CompileOne(const mirror::ArtMethod* method, base::TimingLog { ScopedObjectAccess soa(Thread::Current()); const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_idx); - mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(jclass_loader); + SirtRef<mirror::ClassLoader> class_loader(soa.Self(), + soa.Decode<mirror::ClassLoader*>(jclass_loader)); dex_to_dex_compilation_level = GetDexToDexCompilationlevel(class_loader, *dex_file, class_def); } CompileMethod(code_item, method->GetAccessFlags(), method->GetInvokeType(), @@ -721,8 +721,8 @@ void CompilerDriver::LoadImageClasses(base::TimingLogger& timings) for (const std::pair<uint16_t, const DexFile*>& exception_type : unresolved_exception_types) { uint16_t exception_type_idx = exception_type.first; const DexFile* dex_file = exception_type.second; - mirror::DexCache* dex_cache = class_linker->FindDexCache(*dex_file); - mirror:: ClassLoader* class_loader = NULL; + SirtRef<mirror::DexCache> dex_cache(self, class_linker->FindDexCache(*dex_file)); + SirtRef<mirror::ClassLoader> class_loader(self, nullptr); SirtRef<mirror::Class> klass(self, class_linker->ResolveType(*dex_file, exception_type_idx, dex_cache, class_loader)); if (klass.get() == NULL) { @@ -782,15 +782,14 @@ void CompilerDriver::UpdateImageClasses(base::TimingLogger& timings) { const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter"); gc::Heap* heap = Runtime::Current()->GetHeap(); // TODO: Image spaces only? + ScopedObjectAccess soa(Thread::Current()); WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); - heap->FlushAllocStack(); - heap->GetLiveBitmap()->Walk(FindClinitImageClassesCallback, this); + heap->VisitObjects(FindClinitImageClassesCallback, this); self->EndAssertNoThreadSuspension(old_cause); } } -bool CompilerDriver::CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file, - uint32_t type_idx) { +bool CompilerDriver::CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file, uint32_t type_idx) { if (IsImage() && IsImageClass(dex_file.StringDataByIdx(dex_file.GetTypeId(type_idx).descriptor_idx_))) { if (kIsDebugBuild) { @@ -815,7 +814,7 @@ bool CompilerDriver::CanAssumeStringIsPresentInDexCache(const DexFile& dex_file, if (IsImage()) { // We resolve all const-string strings when building for the image. ScopedObjectAccess soa(Thread::Current()); - mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); + SirtRef<mirror::DexCache> dex_cache(soa.Self(), Runtime::Current()->GetClassLinker()->FindDexCache(dex_file)); Runtime::Current()->GetClassLinker()->ResolveString(dex_file, string_idx, dex_cache); result = true; } @@ -903,26 +902,27 @@ bool CompilerDriver::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_id } static mirror::Class* ComputeCompilingMethodsClass(ScopedObjectAccess& soa, - mirror::DexCache* dex_cache, + SirtRef<mirror::DexCache>& dex_cache, const DexCompilationUnit* mUnit) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // The passed dex_cache is a hint, sanity check before asking the class linker that will take a // lock. if (dex_cache->GetDexFile() != mUnit->GetDexFile()) { - dex_cache = mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile()); + dex_cache.reset(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())); } - mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()); - const DexFile::MethodId& referrer_method_id = mUnit->GetDexFile()->GetMethodId(mUnit->GetDexMethodIndex()); + SirtRef<mirror::ClassLoader> + class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())); + const DexFile::MethodId& referrer_method_id = + mUnit->GetDexFile()->GetMethodId(mUnit->GetDexMethodIndex()); return mUnit->GetClassLinker()->ResolveType(*mUnit->GetDexFile(), referrer_method_id.class_idx_, dex_cache, class_loader); } -static mirror::ArtField* ComputeFieldReferencedFromCompilingMethod(ScopedObjectAccess& soa, - const DexCompilationUnit* mUnit, - uint32_t field_idx) +static mirror::ArtField* ComputeFieldReferencedFromCompilingMethod( + ScopedObjectAccess& soa, const DexCompilationUnit* mUnit, uint32_t field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::DexCache* dex_cache = mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile()); - mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()); + SirtRef<mirror::DexCache> dex_cache(soa.Self(), mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())); + SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())); return mUnit->GetClassLinker()->ResolveField(*mUnit->GetDexFile(), field_idx, dex_cache, class_loader, false); } @@ -932,8 +932,8 @@ static mirror::ArtMethod* ComputeMethodReferencedFromCompilingMethod(ScopedObjec uint32_t method_idx, InvokeType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::DexCache* dex_cache = mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile()); - mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()); + SirtRef<mirror::DexCache> dex_cache(soa.Self(), mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())); + SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())); return mUnit->GetClassLinker()->ResolveMethod(*mUnit->GetDexFile(), method_idx, dex_cache, class_loader, NULL, type); } @@ -947,9 +947,10 @@ bool CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, const DexCompi // Try to resolve field and ignore if an Incompatible Class Change Error (ie is static). mirror::ArtField* resolved_field = ComputeFieldReferencedFromCompilingMethod(soa, mUnit, field_idx); if (resolved_field != NULL && !resolved_field->IsStatic()) { + SirtRef<mirror::DexCache> dex_cache(soa.Self(), + resolved_field->GetDeclaringClass()->GetDexCache()); mirror::Class* referrer_class = - ComputeCompilingMethodsClass(soa, resolved_field->GetDeclaringClass()->GetDexCache(), - mUnit); + ComputeCompilingMethodsClass(soa, dex_cache, mUnit); if (referrer_class != NULL) { mirror::Class* fields_class = resolved_field->GetDeclaringClass(); bool access_ok = referrer_class->CanAccess(fields_class) && @@ -997,9 +998,9 @@ bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompila // Try to resolve field and ignore if an Incompatible Class Change Error (ie isn't static). mirror::ArtField* resolved_field = ComputeFieldReferencedFromCompilingMethod(soa, mUnit, field_idx); if (resolved_field != NULL && resolved_field->IsStatic()) { + SirtRef<mirror::DexCache> dex_cache(soa.Self(), resolved_field->GetDeclaringClass()->GetDexCache()); mirror::Class* referrer_class = - ComputeCompilingMethodsClass(soa, resolved_field->GetDeclaringClass()->GetDexCache(), - mUnit); + ComputeCompilingMethodsClass(soa, dex_cache, mUnit); if (referrer_class != NULL) { mirror::Class* fields_class = resolved_field->GetDeclaringClass(); if (fields_class == referrer_class) { @@ -1085,7 +1086,7 @@ void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType* type, InvokeType *direct_code = 0; *direct_method = 0; bool use_dex_cache = false; - bool compiling_boot = Runtime::Current()->GetHeap()->GetContinuousSpaces().size() == 1; + const bool compiling_boot = Runtime::Current()->GetHeap()->IsCompilingBoot(); if (compiler_backend_ == kPortable) { if (sharp_type != kStatic && sharp_type != kDirect) { return; @@ -1198,9 +1199,9 @@ bool CompilerDriver::ComputeInvokeInfo(const DexCompilationUnit* mUnit, const ui } // Don't try to fast-path if we don't understand the caller's class or this appears to be an // Incompatible Class Change Error. + SirtRef<mirror::DexCache> dex_cache(soa.Self(), resolved_method->GetDeclaringClass()->GetDexCache()); mirror::Class* referrer_class = - ComputeCompilingMethodsClass(soa, resolved_method->GetDeclaringClass()->GetDexCache(), - mUnit); + ComputeCompilingMethodsClass(soa, dex_cache, mUnit); bool icce = resolved_method->CheckIncompatibleClassChange(*invoke_type); if (referrer_class != NULL && !icce) { mirror::Class* methods_class = resolved_method->GetDeclaringClass(); @@ -1254,10 +1255,8 @@ bool CompilerDriver::ComputeInvokeInfo(const DexCompilationUnit* mUnit, const ui const MethodReference* devirt_map_target = verifier::MethodVerifier::GetDevirtMap(caller_method, dex_pc); if (devirt_map_target != NULL) { - mirror::DexCache* target_dex_cache = - mUnit->GetClassLinker()->FindDexCache(*devirt_map_target->dex_file); - mirror::ClassLoader* class_loader = - soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()); + SirtRef<mirror::DexCache> target_dex_cache(soa.Self(), mUnit->GetClassLinker()->FindDexCache(*devirt_map_target->dex_file)); + SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())); mirror::ArtMethod* called_method = mUnit->GetClassLinker()->ResolveMethod(*devirt_map_target->dex_file, devirt_map_target->dex_method_index, @@ -1509,13 +1508,11 @@ static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manag const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); if (!SkipClass(class_linker, jclass_loader, dex_file, class_def)) { ScopedObjectAccess soa(self); - mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(jclass_loader); - mirror::DexCache* dex_cache = class_linker->FindDexCache(dex_file); - + SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(jclass_loader)); + SirtRef<mirror::DexCache> dex_cache(soa.Self(), class_linker->FindDexCache(dex_file)); // Resolve the class. mirror::Class* klass = class_linker->ResolveType(dex_file, class_def.class_idx_, dex_cache, class_loader); - bool resolve_fields_and_methods; if (klass == NULL) { // Class couldn't be resolved, for example, super-class is in a different dex file. Don't @@ -1598,8 +1595,8 @@ static void ResolveType(const ParallelCompilationManager* manager, size_t type_i ScopedObjectAccess soa(Thread::Current()); ClassLinker* class_linker = manager->GetClassLinker(); const DexFile& dex_file = *manager->GetDexFile(); - mirror::DexCache* dex_cache = class_linker->FindDexCache(dex_file); - mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader()); + SirtRef<mirror::DexCache> dex_cache(soa.Self(), class_linker->FindDexCache(dex_file)); + SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader())); mirror::Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader); if (klass == NULL) { @@ -1652,8 +1649,9 @@ static void VerifyClass(const ParallelCompilationManager* manager, size_t class_ const char* descriptor = dex_file.GetClassDescriptor(class_def); ClassLinker* class_linker = manager->GetClassLinker(); jobject jclass_loader = manager->GetClassLoader(); - mirror::Class* klass = class_linker->FindClass(descriptor, - soa.Decode<mirror::ClassLoader*>(jclass_loader)); + SirtRef<mirror::ClassLoader> class_loader( + soa.Self(), soa.Decode<mirror::ClassLoader*>(jclass_loader)); + mirror::Class* klass = class_linker->FindClass(descriptor, class_loader); if (klass == NULL) { CHECK(soa.Self()->IsExceptionPending()); soa.Self()->ClearException(); @@ -1663,11 +1661,10 @@ static void VerifyClass(const ParallelCompilationManager* manager, size_t class_ * This is to ensure the class is structurally sound for compilation. An unsound class * will be rejected by the verifier and later skipped during compilation in the compiler. */ - mirror::DexCache* dex_cache = class_linker->FindDexCache(dex_file); + SirtRef<mirror::DexCache> dex_cache(soa.Self(), class_linker->FindDexCache(dex_file)); std::string error_msg; - if (verifier::MethodVerifier::VerifyClass(&dex_file, dex_cache, - soa.Decode<mirror::ClassLoader*>(jclass_loader), - &class_def, true, &error_msg) == + if (verifier::MethodVerifier::VerifyClass(&dex_file, dex_cache, class_loader, &class_def, true, + &error_msg) == verifier::MethodVerifier::kHardFailure) { LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor) << " because: " << error_msg; @@ -2124,7 +2121,8 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl const char* descriptor = dex_file.StringDataByIdx(class_type_id.descriptor_idx_); ScopedObjectAccess soa(Thread::Current()); - mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(jclass_loader); + SirtRef<mirror::ClassLoader> class_loader(soa.Self(), + soa.Decode<mirror::ClassLoader*>(jclass_loader)); mirror::Class* klass = manager->GetClassLinker()->FindClass(descriptor, class_loader); if (klass != NULL && !SkipClass(jclass_loader, dex_file, klass)) { @@ -2253,7 +2251,8 @@ void CompilerDriver::CompileClass(const ParallelCompilationManager* manager, siz DexToDexCompilationLevel dex_to_dex_compilation_level = kDontDexToDexCompile; { ScopedObjectAccess soa(Thread::Current()); - mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(jclass_loader); + SirtRef<mirror::ClassLoader> class_loader(soa.Self(), + soa.Decode<mirror::ClassLoader*>(jclass_loader)); dex_to_dex_compilation_level = GetDexToDexCompilationlevel(class_loader, dex_file, class_def); } ClassDataItemIterator it(dex_file, class_data); diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 9321f06..9bfea6f 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -368,7 +368,8 @@ class CompilerDriver { ThreadPool& thread_pool, base::TimingLogger& timings) LOCKS_EXCLUDED(Locks::mutator_lock_, compiled_classes_lock_); - void UpdateImageClasses(base::TimingLogger& timings); + void UpdateImageClasses(base::TimingLogger& timings) + LOCKS_EXCLUDED(Locks::mutator_lock_); static void FindClinitImageClassesCallback(mirror::Object* object, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc index c6687bb..bfc93b3 100644 --- a/compiler/driver/compiler_driver_test.cc +++ b/compiler/driver/compiler_driver_test.cc @@ -78,7 +78,9 @@ class CompilerDriverTest : public CommonTest { const DexFile::ClassDef& class_def = dex_file.GetClassDef(i); const char* descriptor = dex_file.GetClassDescriptor(class_def); ScopedObjectAccess soa(Thread::Current()); - mirror::Class* c = class_linker->FindClass(descriptor, soa.Decode<mirror::ClassLoader*>(class_loader)); + Thread* self = Thread::Current(); + SirtRef<mirror::ClassLoader> loader(self, soa.Decode<mirror::ClassLoader*>(class_loader)); + mirror::Class* c = class_linker->FindClass(descriptor, loader); CHECK(c != NULL); for (size_t i = 0; i < c->NumDirectMethods(); i++) { MakeExecutable(c->GetDirectMethod(i)); @@ -142,8 +144,9 @@ TEST_F(CompilerDriverTest, AbstractMethodErrorStub) { jobject class_loader; { ScopedObjectAccess soa(Thread::Current()); - CompileVirtualMethod(NULL, "java.lang.Class", "isFinalizable", "()Z"); - CompileDirectMethod(NULL, "java.lang.Object", "<init>", "()V"); + SirtRef<mirror::ClassLoader> null_loader(soa.Self(), nullptr); + CompileVirtualMethod(null_loader, "java.lang.Class", "isFinalizable", "()Z"); + CompileDirectMethod(null_loader, "java.lang.Object", "<init>", "()V"); class_loader = LoadDex("AbstractMethod"); } ASSERT_TRUE(class_loader != NULL); diff --git a/compiler/image_test.cc b/compiler/image_test.cc index a8b7c88..9d9c064 100644 --- a/compiler/image_test.cc +++ b/compiler/image_test.cc @@ -94,8 +94,8 @@ TEST_F(ImageTest, WriteRead) { ASSERT_NE(0U, image_header.GetImageBitmapSize()); gc::Heap* heap = Runtime::Current()->GetHeap(); - ASSERT_EQ(1U, heap->GetContinuousSpaces().size()); - gc::space::ContinuousSpace* space = heap->GetContinuousSpaces().front(); + ASSERT_TRUE(!heap->GetContinuousSpaces().empty()); + gc::space::ContinuousSpace* space = heap->GetNonMovingSpace(); ASSERT_FALSE(space->IsImageSpace()); ASSERT_TRUE(space != NULL); ASSERT_TRUE(space->IsDlMallocSpace()); @@ -139,11 +139,8 @@ TEST_F(ImageTest, WriteRead) { class_linker_ = runtime_->GetClassLinker(); gc::Heap* heap = Runtime::Current()->GetHeap(); - ASSERT_EQ(2U, heap->GetContinuousSpaces().size()); - ASSERT_TRUE(heap->GetContinuousSpaces()[0]->IsImageSpace()); - ASSERT_FALSE(heap->GetContinuousSpaces()[0]->IsDlMallocSpace()); - ASSERT_FALSE(heap->GetContinuousSpaces()[1]->IsImageSpace()); - ASSERT_TRUE(heap->GetContinuousSpaces()[1]->IsDlMallocSpace()); + ASSERT_TRUE(heap->HasImageSpace()); + ASSERT_TRUE(heap->GetNonMovingSpace()->IsDlMallocSpace()); gc::space::ImageSpace* image_space = heap->GetImageSpace(); image_space->VerifyImageAllocations(); diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 75be2c9..c22f8d6 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -75,8 +75,6 @@ bool ImageWriter::Write(const std::string& image_filename, image_begin_ = reinterpret_cast<byte*>(image_begin); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - const std::vector<DexCache*>& all_dex_caches = class_linker->GetDexCaches(); - dex_caches_.insert(all_dex_caches.begin(), all_dex_caches.end()); UniquePtr<File> oat_file(OS::OpenFileReadWrite(oat_filename.c_str())); if (oat_file.get() == NULL) { @@ -121,22 +119,16 @@ bool ImageWriter::Write(const std::string& image_filename, } gc::Heap* heap = Runtime::Current()->GetHeap(); heap->CollectGarbage(false); // Remove garbage. - // Trim size of alloc spaces. - for (const auto& space : heap->GetContinuousSpaces()) { - if (space->IsDlMallocSpace()) { - space->AsDlMallocSpace()->Trim(); - } - } if (!AllocMemory()) { return false; } -#ifndef NDEBUG - { // NOLINT(whitespace/braces) + + if (kIsDebugBuild) { ScopedObjectAccess soa(Thread::Current()); CheckNonImageClassesRemoved(); } -#endif + Thread::Current()->TransitionFromSuspendedToRunnable(); size_t oat_loaded_size = 0; size_t oat_data_offset = 0; @@ -144,8 +136,6 @@ bool ImageWriter::Write(const std::string& image_filename, CalculateNewObjectOffsets(oat_loaded_size, oat_data_offset); CopyAndFixupObjects(); PatchOatCodeAndMethods(); - // Record allocations into the image bitmap. - RecordImageAllocations(); Thread::Current()->TransitionFromRunnableToSuspended(kNative); UniquePtr<File> image_file(OS::CreateEmptyFile(image_filename.c_str())); @@ -178,39 +168,82 @@ bool ImageWriter::Write(const std::string& image_filename, return true; } -void ImageWriter::RecordImageAllocations() { - uint64_t start_time = NanoTime(); - CHECK(image_bitmap_.get() != nullptr); - for (const auto& it : offsets_) { - mirror::Object* obj = reinterpret_cast<mirror::Object*>(image_->Begin() + it.second); - DCHECK_ALIGNED(obj, kObjectAlignment); - image_bitmap_->Set(obj); +void ImageWriter::SetImageOffset(mirror::Object* object, size_t offset) { + DCHECK(object != nullptr); + DCHECK_NE(offset, 0U); + DCHECK(!IsImageOffsetAssigned(object)); + mirror::Object* obj = reinterpret_cast<mirror::Object*>(image_->Begin() + offset); + DCHECK_ALIGNED(obj, kObjectAlignment); + image_bitmap_->Set(obj); + // Before we stomp over the lock word, save the hash code for later. + Monitor::Deflate(Thread::Current(), object);; + LockWord lw(object->GetLockWord()); + switch (lw.GetState()) { + case LockWord::kFatLocked: { + LOG(FATAL) << "Fat locked object " << obj << " found during object copy"; + break; + } + case LockWord::kThinLocked: { + LOG(FATAL) << "Thin locked object " << obj << " found during object copy"; + break; + } + case LockWord::kUnlocked: + // No hash, don't need to save it. + break; + case LockWord::kHashCode: + saved_hashes_.push_back(std::make_pair(obj, lw.GetHashCode())); + break; + default: + LOG(FATAL) << "Unreachable."; + break; } - LOG(INFO) << "RecordImageAllocations took " << PrettyDuration(NanoTime() - start_time); + object->SetLockWord(LockWord::FromForwardingAddress(offset)); + DCHECK(IsImageOffsetAssigned(object)); } -bool ImageWriter::AllocMemory() { - size_t size = 0; - for (const auto& space : Runtime::Current()->GetHeap()->GetContinuousSpaces()) { - if (space->IsDlMallocSpace()) { - size += space->Size(); - } - } +void ImageWriter::AssignImageOffset(mirror::Object* object) { + DCHECK(object != nullptr); + SetImageOffset(object, image_end_); + image_end_ += RoundUp(object->SizeOf(), 8); // 64-bit alignment + DCHECK_LT(image_end_, image_->Size()); +} - int prot = PROT_READ | PROT_WRITE; - size_t length = RoundUp(size, kPageSize); +bool ImageWriter::IsImageOffsetAssigned(const mirror::Object* object) const { + DCHECK(object != nullptr); + return object->GetLockWord().GetState() == LockWord::kForwardingAddress; +} + +size_t ImageWriter::GetImageOffset(const mirror::Object* object) const { + DCHECK(object != nullptr); + DCHECK(IsImageOffsetAssigned(object)); + LockWord lock_word = object->GetLockWord(); + size_t offset = lock_word.ForwardingAddress(); + DCHECK_LT(offset, image_end_); + return offset; +} + +bool ImageWriter::AllocMemory() { + size_t length = RoundUp(Runtime::Current()->GetHeap()->GetTotalMemory(), kPageSize); std::string error_msg; - image_.reset(MemMap::MapAnonymous("image writer image", NULL, length, prot, &error_msg)); + image_.reset(MemMap::MapAnonymous("image writer image", NULL, length, PROT_READ | PROT_WRITE, + &error_msg)); if (UNLIKELY(image_.get() == nullptr)) { LOG(ERROR) << "Failed to allocate memory for image file generation: " << error_msg; return false; } + + // Create the image bitmap. + image_bitmap_.reset(gc::accounting::SpaceBitmap::Create("image bitmap", image_->Begin(), + length)); + if (image_bitmap_.get() == nullptr) { + LOG(ERROR) << "Failed to allocate memory for image bitmap"; + return false; + } return true; } void ImageWriter::ComputeLazyFieldsForImageClasses() { - Runtime* runtime = Runtime::Current(); - ClassLinker* class_linker = runtime->GetClassLinker(); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); class_linker->VisitClassesWithoutClassesLock(ComputeLazyFieldsForClassesVisitor, NULL); } @@ -223,13 +256,12 @@ void ImageWriter::ComputeEagerResolvedStringsCallback(Object* obj, void* arg) { if (!obj->GetClass()->IsStringClass()) { return; } - String* string = obj->AsString(); + mirror::String* string = obj->AsString(); const uint16_t* utf16_string = string->GetCharArray()->GetData() + string->GetOffset(); - ImageWriter* writer = reinterpret_cast<ImageWriter*>(arg); - for (DexCache* dex_cache : writer->dex_caches_) { + for (DexCache* dex_cache : Runtime::Current()->GetClassLinker()->GetDexCaches()) { const DexFile& dex_file = *dex_cache->GetDexFile(); const DexFile::StringId* string_id = dex_file.FindStringId(utf16_string); - if (string_id != NULL) { + if (string_id != nullptr) { // This string occurs in this dex file, assign the dex cache entry. uint32_t string_idx = dex_file.GetIndexForStringId(*string_id); if (dex_cache->GetResolvedString(string_idx) == NULL) { @@ -239,13 +271,9 @@ void ImageWriter::ComputeEagerResolvedStringsCallback(Object* obj, void* arg) { } } -void ImageWriter::ComputeEagerResolvedStrings() - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // TODO: Check image spaces only? - gc::Heap* heap = Runtime::Current()->GetHeap(); - WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); - heap->FlushAllocStack(); - heap->GetLiveBitmap()->Walk(ComputeEagerResolvedStringsCallback, this); +void ImageWriter::ComputeEagerResolvedStrings() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); + Runtime::Current()->GetHeap()->VisitObjects(ComputeEagerResolvedStringsCallback, this); } bool ImageWriter::IsImageClass(const Class* klass) { @@ -278,7 +306,7 @@ void ImageWriter::PruneNonImageClasses() { // Clear references to removed classes from the DexCaches. ArtMethod* resolution_method = runtime->GetResolutionMethod(); - for (DexCache* dex_cache : dex_caches_) { + for (DexCache* dex_cache : class_linker->GetDexCaches()) { for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) { Class* klass = dex_cache->GetResolvedType(i); if (klass != NULL && !IsImageClass(klass)) { @@ -311,31 +339,22 @@ bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) { void ImageWriter::CheckNonImageClassesRemoved() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (compiler_driver_.GetImageClasses() == NULL) { - return; - } - - gc::Heap* heap = Runtime::Current()->GetHeap(); - Thread* self = Thread::Current(); - { - WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); - heap->FlushAllocStack(); + if (compiler_driver_.GetImageClasses() != nullptr) { + gc::Heap* heap = Runtime::Current()->GetHeap(); + ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); + heap->VisitObjects(CheckNonImageClassesRemovedCallback, this); } - - ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); - heap->GetLiveBitmap()->Walk(CheckNonImageClassesRemovedCallback, this); } void ImageWriter::CheckNonImageClassesRemovedCallback(Object* obj, void* arg) { ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); - if (!obj->IsClass()) { - return; - } - Class* klass = obj->AsClass(); - if (!image_writer->IsImageClass(klass)) { - image_writer->DumpImageClasses(); - CHECK(image_writer->IsImageClass(klass)) << ClassHelper(klass).GetDescriptor() - << " " << PrettyDescriptor(klass); + if (obj->IsClass()) { + Class* klass = obj->AsClass(); + if (!image_writer->IsImageClass(klass)) { + image_writer->DumpImageClasses(); + CHECK(image_writer->IsImageClass(klass)) << ClassHelper(klass).GetDescriptor() + << " " << PrettyDescriptor(klass); + } } } @@ -347,53 +366,50 @@ void ImageWriter::DumpImageClasses() { } } -void ImageWriter::CalculateNewObjectOffsetsCallback(Object* obj, void* arg) { +void ImageWriter::CalculateObjectOffsets(Object* obj) { DCHECK(obj != NULL); - DCHECK(arg != NULL); - ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); - // if it is a string, we want to intern it if its not interned. if (obj->GetClass()->IsStringClass()) { // we must be an interned string that was forward referenced and already assigned - if (image_writer->IsImageOffsetAssigned(obj)) { + if (IsImageOffsetAssigned(obj)) { DCHECK_EQ(obj, obj->AsString()->Intern()); return; } - SirtRef<String> interned(Thread::Current(), obj->AsString()->Intern()); - if (obj != interned.get()) { - if (!image_writer->IsImageOffsetAssigned(interned.get())) { + Thread* self = Thread::Current(); + SirtRef<Object> sirt_obj(self, obj); + mirror::String* interned = obj->AsString()->Intern(); + if (sirt_obj.get() != interned) { + if (!IsImageOffsetAssigned(interned)) { // interned obj is after us, allocate its location early - image_writer->AssignImageOffset(interned.get()); + AssignImageOffset(interned); } // point those looking for this object to the interned version. - image_writer->SetImageOffset(obj, image_writer->GetImageOffset(interned.get())); + SetImageOffset(sirt_obj.get(), GetImageOffset(interned)); return; } // else (obj == interned), nothing to do but fall through to the normal case } - image_writer->AssignImageOffset(obj); + AssignImageOffset(obj); } ObjectArray<Object>* ImageWriter::CreateImageRoots() const { Runtime* runtime = Runtime::Current(); ClassLinker* class_linker = runtime->GetClassLinker(); - Class* object_array_class = class_linker->FindSystemClass("[Ljava/lang/Object;"); Thread* self = Thread::Current(); + SirtRef<Class> object_array_class(self, class_linker->FindSystemClass("[Ljava/lang/Object;")); // build an Object[] of all the DexCaches used in the source_space_ - ObjectArray<Object>* dex_caches = ObjectArray<Object>::Alloc(self, object_array_class, - dex_caches_.size()); + ObjectArray<Object>* dex_caches = ObjectArray<Object>::Alloc(self, object_array_class.get(), + class_linker->GetDexCaches().size()); int i = 0; - for (DexCache* dex_cache : dex_caches_) { + for (DexCache* dex_cache : class_linker->GetDexCaches()) { dex_caches->Set(i++, dex_cache); } // build an Object[] of the roots needed to restore the runtime - SirtRef<ObjectArray<Object> > - image_roots(self, - ObjectArray<Object>::Alloc(self, object_array_class, - ImageHeader::kImageRootsMax)); + SirtRef<ObjectArray<Object> > image_roots( + self, ObjectArray<Object>::Alloc(self, object_array_class.get(), ImageHeader::kImageRootsMax)); image_roots->Set(ImageHeader::kResolutionMethod, runtime->GetResolutionMethod()); image_roots->Set(ImageHeader::kImtConflictMethod, runtime->GetImtConflictMethod()); image_roots->Set(ImageHeader::kDefaultImt, runtime->GetDefaultImt()); @@ -405,24 +421,82 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const { runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)); image_roots->Set(ImageHeader::kOatLocation, String::AllocFromModifiedUtf8(self, oat_file_->GetLocation().c_str())); - image_roots->Set(ImageHeader::kDexCaches, - dex_caches); - image_roots->Set(ImageHeader::kClassRoots, - class_linker->GetClassRoots()); + image_roots->Set(ImageHeader::kDexCaches, dex_caches); + image_roots->Set(ImageHeader::kClassRoots, class_linker->GetClassRoots()); for (int i = 0; i < ImageHeader::kImageRootsMax; i++) { CHECK(image_roots->Get(i) != NULL); } return image_roots.get(); } +// Walk instance fields of the given Class. Separate function to allow recursion on the super +// class. +void ImageWriter::WalkInstanceFields(mirror::Object* obj, mirror::Class* klass) { + // Visit fields of parent classes first. + SirtRef<mirror::Class> sirt_class(Thread::Current(), klass); + mirror::Class* super = sirt_class->GetSuperClass(); + if (super != nullptr) { + WalkInstanceFields(obj, super); + } + // + size_t num_reference_fields = sirt_class->NumReferenceInstanceFields(); + for (size_t i = 0; i < num_reference_fields; ++i) { + mirror::ArtField* field = sirt_class->GetInstanceField(i); + MemberOffset field_offset = field->GetOffset(); + mirror::Object* value = obj->GetFieldObject<mirror::Object*>(field_offset, false); + if (value != nullptr) { + WalkFieldsInOrder(value); + } + } +} + +// For an unvisited object, visit it then all its children found via fields. +void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { + if (!IsImageOffsetAssigned(obj)) { + // Walk instance fields of all objects + Thread* self = Thread::Current(); + SirtRef<mirror::Object> sirt_obj(self, obj); + SirtRef<mirror::Class> klass(self, obj->GetClass()); + // visit the object itself. + CalculateObjectOffsets(sirt_obj.get()); + WalkInstanceFields(sirt_obj.get(), klass.get()); + // Walk static fields of a Class. + if (sirt_obj->IsClass()) { + size_t num_static_fields = klass->NumReferenceStaticFields(); + for (size_t i = 0; i < num_static_fields; ++i) { + mirror::ArtField* field = klass->GetStaticField(i); + MemberOffset field_offset = field->GetOffset(); + mirror::Object* value = sirt_obj->GetFieldObject<mirror::Object*>(field_offset, false); + if (value != nullptr) { + WalkFieldsInOrder(value); + } + } + } else if (sirt_obj->IsObjectArray()) { + // Walk elements of an object array. + int32_t length = sirt_obj->AsObjectArray<mirror::Object>()->GetLength(); + for (int32_t i = 0; i < length; i++) { + mirror::ObjectArray<mirror::Object>* obj_array = sirt_obj->AsObjectArray<mirror::Object>(); + mirror::Object* value = obj_array->Get(i); + if (value != nullptr) { + WalkFieldsInOrder(value); + } + } + } + } +} + +void ImageWriter::WalkFieldsCallback(mirror::Object* obj, void* arg) { + ImageWriter* writer = reinterpret_cast<ImageWriter*>(arg); + DCHECK(writer != nullptr); + writer->WalkFieldsInOrder(obj); +} + void ImageWriter::CalculateNewObjectOffsets(size_t oat_loaded_size, size_t oat_data_offset) { CHECK_NE(0U, oat_loaded_size); Thread* self = Thread::Current(); SirtRef<ObjectArray<Object> > image_roots(self, CreateImageRoots()); gc::Heap* heap = Runtime::Current()->GetHeap(); - const auto& spaces = heap->GetContinuousSpaces(); - DCHECK(!spaces.empty()); DCHECK_EQ(0U, image_end_); // Leave space for the header, but do not write it yet, we need to @@ -431,21 +505,14 @@ void ImageWriter::CalculateNewObjectOffsets(size_t oat_loaded_size, size_t oat_d { WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); - heap->FlushAllocStack(); // TODO: Image spaces only? - // TODO: Add InOrderWalk to heap bitmap. const char* old = self->StartAssertNoThreadSuspension("ImageWriter"); - DCHECK(heap->GetLargeObjectsSpace()->GetLiveObjects()->IsEmpty()); - for (const auto& space : spaces) { - space->GetLiveBitmap()->InOrderWalk(CalculateNewObjectOffsetsCallback, this); - DCHECK_LT(image_end_, image_->Size()); - } + DCHECK_LT(image_end_, image_->Size()); + // Clear any pre-existing monitors which may have been in the monitor words. + heap->VisitObjects(WalkFieldsCallback, this); self->EndAssertNoThreadSuspension(old); } - // Create the image bitmap. - image_bitmap_.reset(gc::accounting::SpaceBitmap::Create("image bitmap", image_->Begin(), - image_end_)); const byte* oat_file_begin = image_begin_ + RoundUp(image_end_, kPageSize); const byte* oat_file_end = oat_file_begin + oat_loaded_size; oat_data_begin_ = oat_file_begin + oat_data_offset; @@ -456,7 +523,8 @@ void ImageWriter::CalculateNewObjectOffsets(size_t oat_loaded_size, size_t oat_d ImageHeader image_header(reinterpret_cast<uint32_t>(image_begin_), static_cast<uint32_t>(image_end_), RoundUp(image_end_, kPageSize), - image_bitmap_->Size(), + RoundUp(image_end_ / gc::accounting::SpaceBitmap::kAlignment, + sizeof(size_t)), reinterpret_cast<uint32_t>(GetImageAddress(image_roots.get())), oat_file_->GetOatHeader().GetChecksum(), reinterpret_cast<uint32_t>(oat_file_begin), @@ -477,17 +545,19 @@ void ImageWriter::CopyAndFixupObjects() heap->DisableObjectValidation(); // TODO: Image spaces only? WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); - heap->FlushAllocStack(); - heap->GetLiveBitmap()->Walk(CopyAndFixupObjectsCallback, this); + heap->VisitObjects(CopyAndFixupObjectsCallback, this); + // Fix up the object previously had hash codes. + for (const std::pair<mirror::Object*, uint32_t>& hash_pair : saved_hashes_) { + hash_pair.first->SetLockWord(LockWord::FromHashCode(hash_pair.second)); + } + saved_hashes_.clear(); self->EndAssertNoThreadSuspension(old_cause); } -void ImageWriter::CopyAndFixupObjectsCallback(Object* object, void* arg) { - DCHECK(object != NULL); +void ImageWriter::CopyAndFixupObjectsCallback(Object* obj, void* arg) { + DCHECK(obj != NULL); DCHECK(arg != NULL); - const Object* obj = object; ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); - // see GetLocalAddress for similar computation size_t offset = image_writer->GetImageOffset(obj); byte* dst = image_writer->image_->Begin() + offset; @@ -498,33 +568,7 @@ void ImageWriter::CopyAndFixupObjectsCallback(Object* object, void* arg) { Object* copy = reinterpret_cast<Object*>(dst); // Write in a hash code of objects which have inflated monitors or a hash code in their monitor // word. - LockWord lw(copy->GetLockWord()); - switch (lw.GetState()) { - case LockWord::kFatLocked: { - Monitor* monitor = lw.FatLockMonitor(); - CHECK(monitor != nullptr); - CHECK(!monitor->IsLocked()); - if (monitor->HasHashCode()) { - copy->SetLockWord(LockWord::FromHashCode(monitor->GetHashCode())); - } else { - copy->SetLockWord(LockWord()); - } - break; - } - case LockWord::kThinLocked: { - LOG(FATAL) << "Thin locked object " << obj << " found during object copy"; - break; - } - case LockWord::kUnlocked: - break; - case LockWord::kHashCode: - // Do nothing since we can just keep the same hash code. - CHECK_NE(lw.GetHashCode(), 0); - break; - default: - LOG(FATAL) << "Unreachable."; - break; - } + copy->SetLockWord(LockWord()); image_writer->FixupObject(obj, copy); } @@ -629,19 +673,13 @@ void ImageWriter::FixupInstanceFields(const Object* orig, Object* copy) { DCHECK(copy != NULL); Class* klass = orig->GetClass(); DCHECK(klass != NULL); - FixupFields(orig, - copy, - klass->GetReferenceInstanceOffsets(), - false); + FixupFields(orig, copy, klass->GetReferenceInstanceOffsets(), false); } void ImageWriter::FixupStaticFields(const Class* orig, Class* copy) { DCHECK(orig != NULL); DCHECK(copy != NULL); - FixupFields(orig, - copy, - orig->GetReferenceStaticOffsets(), - true); + FixupFields(orig, copy, orig->GetReferenceStaticOffsets(), true); } void ImageWriter::FixupFields(const Object* orig, @@ -693,11 +731,13 @@ void ImageWriter::FixupFields(const Object* orig, static ArtMethod* GetTargetMethod(const CompilerDriver::PatchInformation* patch) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - DexCache* dex_cache = class_linker->FindDexCache(patch->GetDexFile()); + Thread* self = Thread::Current(); + SirtRef<mirror::DexCache> dex_cache(self, class_linker->FindDexCache(patch->GetDexFile())); + SirtRef<mirror::ClassLoader> class_loader(self, nullptr); ArtMethod* method = class_linker->ResolveMethod(patch->GetDexFile(), patch->GetTargetMethodIdx(), dex_cache, - NULL, + class_loader, NULL, patch->GetTargetInvokeType()); CHECK(method != NULL) @@ -749,15 +789,15 @@ void ImageWriter::SetPatchLocation(const CompilerDriver::PatchInformation* patch // TODO: make this Thumb2 specific uint8_t* base = reinterpret_cast<uint8_t*>(reinterpret_cast<uint32_t>(oat_code) & ~0x1); uint32_t* patch_location = reinterpret_cast<uint32_t*>(base + patch->GetLiteralOffset()); -#ifndef NDEBUG - const DexFile::MethodId& id = patch->GetDexFile().GetMethodId(patch->GetTargetMethodIdx()); - uint32_t expected = reinterpret_cast<uint32_t>(&id); - uint32_t actual = *patch_location; - CHECK(actual == expected || actual == value) << std::hex - << "actual=" << actual - << "expected=" << expected - << "value=" << value; -#endif + if (kIsDebugBuild) { + const DexFile::MethodId& id = patch->GetDexFile().GetMethodId(patch->GetTargetMethodIdx()); + uint32_t expected = reinterpret_cast<uint32_t>(&id); + uint32_t actual = *patch_location; + CHECK(actual == expected || actual == value) << std::hex + << "actual=" << actual + << "expected=" << expected + << "value=" << value; + } *patch_location = value; oat_header.UpdateChecksum(patch_location, sizeof(value)); } diff --git a/compiler/image_writer.h b/compiler/image_writer.h index 0b408e8..695f59b 100644 --- a/compiler/image_writer.h +++ b/compiler/image_writer.h @@ -63,31 +63,11 @@ class ImageWriter { void RecordImageAllocations() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // We use the lock word to store the offset of the object in the image. - void AssignImageOffset(mirror::Object* object) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(object != NULL); - SetImageOffset(object, image_end_); - image_end_ += RoundUp(object->SizeOf(), 8); // 64-bit alignment - DCHECK_LT(image_end_, image_->Size()); - } - - void SetImageOffset(mirror::Object* object, size_t offset) { - DCHECK(object != NULL); - DCHECK_NE(offset, 0U); - DCHECK(!IsImageOffsetAssigned(object)); - offsets_.Put(object, offset); - } - - size_t IsImageOffsetAssigned(const mirror::Object* object) const { - DCHECK(object != NULL); - return offsets_.find(object) != offsets_.end(); - } - - size_t GetImageOffset(const mirror::Object* object) const { - DCHECK(object != NULL); - DCHECK(IsImageOffsetAssigned(object)); - return offsets_.find(object)->second; - } + void AssignImageOffset(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetImageOffset(mirror::Object* object, size_t offset) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool IsImageOffsetAssigned(const mirror::Object* object) const; + size_t GetImageOffset(const mirror::Object* object) const; mirror::Object* GetImageAddress(const mirror::Object* object) const { if (object == NULL) { @@ -147,7 +127,14 @@ class ImageWriter { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); mirror::ObjectArray<mirror::Object>* CreateImageRoots() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void CalculateNewObjectOffsetsCallback(mirror::Object* obj, void* arg) + void CalculateObjectOffsets(mirror::Object* obj) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void WalkInstanceFields(mirror::Object* obj, mirror::Class* klass) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void WalkFieldsInOrder(mirror::Object* obj) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + static void WalkFieldsCallback(mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Creates the contiguous image in memory and adjusts pointers. @@ -180,9 +167,6 @@ class ImageWriter { const CompilerDriver& compiler_driver_; - // Map of Object to where it will be at runtime. - SafeMap<const mirror::Object*, size_t> offsets_; - // oat file with code for this image OatFile* oat_file_; @@ -195,6 +179,9 @@ class ImageWriter { // Beginning target image address for the output image. byte* image_begin_; + // Saved hashes (objects are inside of the image so that they don't move). + std::vector<std::pair<mirror::Object*, uint32_t> > saved_hashes_; + // Beginning target oat address for the pointers from the output image to its oat file. const byte* oat_data_begin_; @@ -211,9 +198,6 @@ class ImageWriter { uint32_t quick_imt_conflict_trampoline_offset_; uint32_t quick_resolution_trampoline_offset_; uint32_t quick_to_interpreter_bridge_offset_; - - // DexCaches seen while scanning for fixing up CodeAndDirectMethods - std::set<mirror::DexCache*> dex_caches_; }; } // namespace art diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc index 667b913..21dd11e 100644 --- a/compiler/jni/jni_compiler_test.cc +++ b/compiler/jni/jni_compiler_test.cc @@ -48,9 +48,9 @@ class JniCompilerTest : public CommonTest { void CompileForTest(jobject class_loader, bool direct, const char* method_name, const char* method_sig) { ScopedObjectAccess soa(Thread::Current()); + SirtRef<mirror::ClassLoader> loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(class_loader)); // Compile the native method before starting the runtime - mirror::Class* c = class_linker_->FindClass("LMyClassNatives;", - soa.Decode<mirror::ClassLoader*>(class_loader)); + mirror::Class* c = class_linker_->FindClass("LMyClassNatives;", loader); mirror::ArtMethod* method; if (direct) { method = c->FindDirectMethod(method_name, method_sig); diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc index 6213b45..c423f34 100644 --- a/compiler/oat_test.cc +++ b/compiler/oat_test.cc @@ -130,7 +130,8 @@ TEST_F(OatTest, WriteRead) { num_virtual_methods = it.NumVirtualMethods(); } const char* descriptor = dex_file->GetClassDescriptor(class_def); - mirror::Class* klass = class_linker->FindClass(descriptor, NULL); + SirtRef<mirror::ClassLoader> loader(Thread::Current(), nullptr); + mirror::Class* klass = class_linker->FindClass(descriptor, loader); UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(i)); CHECK_EQ(mirror::Class::Status::kStatusNotReady, oat_class->GetStatus()) << descriptor; diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index f3bb112..28fb147 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -405,23 +405,23 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]); gc_map_offset = (gc_map_size == 0) ? 0 : offset; -#if !defined(NDEBUG) - // We expect GC maps except when the class hasn't been verified or the method is native - ClassReference class_ref(&dex_file, class_def_index); - CompiledClass* compiled_class = compiler_driver_->GetCompiledClass(class_ref); - mirror::Class::Status status; - if (compiled_class != NULL) { - status = compiled_class->GetStatus(); - } else if (verifier::MethodVerifier::IsClassRejected(class_ref)) { - status = mirror::Class::kStatusError; - } else { - status = mirror::Class::kStatusNotReady; + if (kIsDebugBuild) { + // We expect GC maps except when the class hasn't been verified or the method is native + ClassReference class_ref(&dex_file, class_def_index); + CompiledClass* compiled_class = compiler_driver_->GetCompiledClass(class_ref); + mirror::Class::Status status; + if (compiled_class != NULL) { + status = compiled_class->GetStatus(); + } else if (verifier::MethodVerifier::IsClassRejected(class_ref)) { + status = mirror::Class::kStatusError; + } else { + status = mirror::Class::kStatusNotReady; + } + CHECK(gc_map_size != 0 || is_native || status < mirror::Class::kStatusVerified) + << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " + << (status < mirror::Class::kStatusVerified) << " " << status << " " + << PrettyMethod(method_idx, dex_file); } - CHECK(gc_map_size != 0 || is_native || status < mirror::Class::kStatusVerified) - << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " - << (status < mirror::Class::kStatusVerified) << " " << status << " " - << PrettyMethod(method_idx, dex_file); -#endif // Deduplicate GC maps SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = @@ -448,11 +448,12 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, if (compiler_driver_->IsImage()) { ClassLinker* linker = Runtime::Current()->GetClassLinker(); - mirror::DexCache* dex_cache = linker->FindDexCache(dex_file); // Unchecked as we hold mutator_lock_ on entry. ScopedObjectAccessUnchecked soa(Thread::Current()); + SirtRef<mirror::DexCache> dex_cache(soa.Self(), linker->FindDexCache(dex_file)); + SirtRef<mirror::ClassLoader> class_loader(soa.Self(), nullptr); mirror::ArtMethod* method = linker->ResolveMethod(dex_file, method_idx, dex_cache, - NULL, NULL, invoke_type); + class_loader, nullptr, invoke_type); CHECK(method != NULL); method->SetFrameSizeInBytes(frame_size_in_bytes); method->SetCoreSpillMask(core_spill_mask); |