summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2013-11-13 00:21:46 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-11-13 00:21:47 +0000
commit0b74e3acc2fd35d95ac55c4ee2ffe5c651229ed8 (patch)
tree2cba9a33810d360054749a358120b6951a469fb3 /compiler
parent686d6f3bf7a22bdc5e676a5e735bfaef314f4de8 (diff)
parent590fee9e8972f872301c2d16a575d579ee564bee (diff)
downloadart-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.cc97
-rw-r--r--compiler/driver/compiler_driver.h3
-rw-r--r--compiler/driver/compiler_driver_test.cc9
-rw-r--r--compiler/image_test.cc11
-rw-r--r--compiler/image_writer.cc346
-rw-r--r--compiler/image_writer.h48
-rw-r--r--compiler/jni/jni_compiler_test.cc4
-rw-r--r--compiler/oat_test.cc3
-rw-r--r--compiler/oat_writer.cc37
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);