diff options
| author | 2015-12-04 14:01:50 -0800 | |
|---|---|---|
| committer | 2015-12-04 14:01:50 -0800 | |
| commit | c0206e1a89fc996425f2b4b440d98a7425be6e1e (patch) | |
| tree | 17f59747e664c00370710544f18a26f7ebe9c548 /compiler | |
| parent | 4d7bd605663a01daea6a68bfe09dadc575ba95fc (diff) | |
| parent | e8d71c13ad2e9660c9acf51bbe571f1ceaec7120 (diff) | |
Merge "Store class tables in the image" am: a616b4e086
am: e8d71c13ad
* commit 'e8d71c13ad2e9660c9acf51bbe571f1ceaec7120':
Store class tables in the image
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/image_writer.cc | 87 | ||||
| -rw-r--r-- | compiler/image_writer.h | 9 |
2 files changed, 80 insertions, 16 deletions
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 341742e4dc..bf1fcdd5f5 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -540,7 +540,10 @@ ImageWriter::BinSlot ImageWriter::GetImageBinSlot(mirror::Object* object) const } bool ImageWriter::AllocMemory() { - const size_t length = RoundUp(image_objects_offset_begin_ + GetBinSizeSum() + intern_table_bytes_, + const size_t length = RoundUp(image_objects_offset_begin_ + + GetBinSizeSum() + + intern_table_bytes_ + + class_table_bytes_, kPageSize); std::string error_msg; image_.reset(MemMap::MapAnonymous("image writer image", @@ -1030,6 +1033,14 @@ void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { WalkFieldsInOrder(value); } } + } else if (h_obj->IsClassLoader()) { + // Register the class loader if it has a class table. + // The fake boot class loader should not get registered and we should end up with only one + // class loader. + mirror::ClassLoader* class_loader = h_obj->AsClassLoader(); + if (class_loader->GetClassTable() != nullptr) { + class_loaders_.insert(class_loader); + } } } } @@ -1154,10 +1165,26 @@ void ImageWriter::CalculateNewObjectOffsets() { } // Calculate how big the intern table will be after being serialized. - auto* const intern_table = Runtime::Current()->GetInternTable(); + InternTable* const intern_table = runtime->GetInternTable(); CHECK_EQ(intern_table->WeakSize(), 0u) << " should have strong interned all the strings"; intern_table_bytes_ = intern_table->WriteToMemory(nullptr); + // Write out the class table. + ClassLinker* class_linker = runtime->GetClassLinker(); + if (boot_image_space_ == nullptr) { + // Compiling the boot image, add null class loader. + class_loaders_.insert(nullptr); + } + if (!class_loaders_.empty()) { + CHECK_EQ(class_loaders_.size(), 1u) << "Should only have one real class loader in the image"; + ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); + for (mirror::ClassLoader* loader : class_loaders_) { + ClassTable* table = class_linker->ClassTableForClassLoader(loader); + CHECK(table != nullptr); + class_table_bytes_ += table->WriteToMemory(nullptr); + } + } + // Note that image_end_ is left at end of used mirror object section. } @@ -1199,6 +1226,12 @@ void ImageWriter::CreateHeader(size_t oat_loaded_size, size_t oat_data_offset) { auto* interned_strings_section = §ions[ImageHeader::kSectionInternedStrings]; *interned_strings_section = ImageSection(cur_pos, intern_table_bytes_); cur_pos = interned_strings_section->End(); + // Calculate the size of the class table section. + auto* class_table_section = §ions[ImageHeader::kSectionClassTable]; + *class_table_section = ImageSection(cur_pos, class_table_bytes_); + cur_pos = class_table_section->End(); + // Image end goes right before the start of the image bitmap. + const size_t image_end = static_cast<uint32_t>(cur_pos); // Finally bitmap section. const size_t bitmap_bytes = image_bitmap_->Size(); auto* bitmap_section = §ions[ImageHeader::kSectionImageBitmap]; @@ -1212,7 +1245,6 @@ void ImageWriter::CreateHeader(size_t oat_loaded_size, size_t oat_data_offset) { } LOG(INFO) << "Methods: clean=" << clean_methods_ << " dirty=" << dirty_methods_; } - const size_t image_end = static_cast<uint32_t>(interned_strings_section->End()); CHECK_EQ(AlignUp(image_begin_ + image_end, kPageSize), oat_file_begin) << "Oat file should be right after the image."; // Create the header. @@ -1323,23 +1355,48 @@ void ImageWriter::CopyAndFixupNativeData() { } image_header->SetImageMethod(static_cast<ImageHeader::ImageMethod>(i), method); } + FixupRootVisitor root_visitor(this); + // Write the intern table into the image. const ImageSection& intern_table_section = image_header->GetImageSection( ImageHeader::kSectionInternedStrings); - InternTable* const intern_table = Runtime::Current()->GetInternTable(); - uint8_t* const memory_ptr = image_->Begin() + intern_table_section.Offset(); - const size_t intern_table_bytes = intern_table->WriteToMemory(memory_ptr); + Runtime* const runtime = Runtime::Current(); + InternTable* const intern_table = runtime->GetInternTable(); + uint8_t* const intern_table_memory_ptr = image_->Begin() + intern_table_section.Offset(); + const size_t intern_table_bytes = intern_table->WriteToMemory(intern_table_memory_ptr); + CHECK_EQ(intern_table_bytes, intern_table_bytes_); // Fixup the pointers in the newly written intern table to contain image addresses. - InternTable temp_table; + InternTable temp_intern_table; // Note that we require that ReadFromMemory does not make an internal copy of the elements so that // the VisitRoots() will update the memory directly rather than the copies. // This also relies on visit roots not doing any verification which could fail after we update // the roots to be the image addresses. - temp_table.ReadFromMemory(memory_ptr); - CHECK_EQ(temp_table.Size(), intern_table->Size()); - FixupRootVisitor visitor(this); - temp_table.VisitRoots(&visitor, kVisitRootFlagAllRoots); - CHECK_EQ(intern_table_bytes, intern_table_bytes_); + temp_intern_table.ReadFromMemory(intern_table_memory_ptr); + CHECK_EQ(temp_intern_table.Size(), intern_table->Size()); + temp_intern_table.VisitRoots(&root_visitor, kVisitRootFlagAllRoots); + + // Write the class table(s) into the image. + ClassLinker* const class_linker = runtime->GetClassLinker(); + const ImageSection& class_table_section = image_header->GetImageSection( + ImageHeader::kSectionClassTable); + uint8_t* const class_table_memory_ptr = image_->Begin() + class_table_section.Offset(); + ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); + size_t class_table_bytes = 0; + for (mirror::ClassLoader* loader : class_loaders_) { + ClassTable* table = class_linker->ClassTableForClassLoader(loader); + CHECK(table != nullptr); + uint8_t* memory_ptr = class_table_memory_ptr + class_table_bytes; + class_table_bytes += table->WriteToMemory(memory_ptr); + // Fixup the pointers in the newly written class table to contain image addresses. See + // above comment for intern tables. + ClassTable temp_class_table; + temp_class_table.ReadFromMemory(memory_ptr); + // CHECK_EQ(temp_class_table.NumNonZygoteClasses(), table->NumNonZygoteClasses()); + BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(&root_visitor, + RootInfo(kRootUnknown)); + temp_class_table.VisitRoots(buffered_visitor); + } + CHECK_EQ(class_table_bytes, class_table_bytes_); } void ImageWriter::CopyAndFixupObjects() { @@ -1553,8 +1610,7 @@ void ImageWriter::FixupObject(Object* orig, Object* copy) { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); if (klass == class_linker->GetClassRoot(ClassLinker::kJavaLangDexCache)) { FixupDexCache(down_cast<mirror::DexCache*>(orig), down_cast<mirror::DexCache*>(copy)); - } else if (klass->IsSubClass(down_cast<mirror::Class*>( - class_linker->GetClassRoot(ClassLinker::kJavaLangClassLoader)))) { + } else if (klass->IsClassLoaderClass()) { // If src is a ClassLoader, set the class table to null so that it gets recreated by the // ClassLoader. down_cast<mirror::ClassLoader*>(copy)->SetClassTable(nullptr); @@ -1840,7 +1896,8 @@ uint8_t* ImageWriter::GetOatFileBegin() const { bin_slot_sizes_[kBinArtMethodDirty] + bin_slot_sizes_[kBinArtMethodClean] + bin_slot_sizes_[kBinDexCacheArray] + - intern_table_bytes_; + intern_table_bytes_ + + class_table_bytes_; return image_begin_ + RoundUp(image_end_ + native_sections_size, kPageSize); } diff --git a/compiler/image_writer.h b/compiler/image_writer.h index 889cd10dc4..386838fde0 100644 --- a/compiler/image_writer.h +++ b/compiler/image_writer.h @@ -72,7 +72,8 @@ class ImageWriter FINAL { intern_table_bytes_(0u), image_method_array_(ImageHeader::kImageMethodsCount), dirty_methods_(0u), - clean_methods_(0u) { + clean_methods_(0u), + class_table_bytes_(0u) { CHECK_NE(image_begin, 0U); std::fill_n(image_methods_, arraysize(image_methods_), nullptr); std::fill_n(oat_address_offsets_, arraysize(oat_address_offsets_), 0); @@ -453,6 +454,12 @@ class ImageWriter FINAL { // Prune class memoization table to speed up ContainsBootClassLoaderNonImageClass. std::unordered_map<mirror::Class*, bool> prune_class_memo_; + // Class loaders with a class table to write out. Should only be one currently. + std::unordered_set<mirror::ClassLoader*> class_loaders_; + + // Number of image class table bytes. + size_t class_table_bytes_; + friend class ContainsBootClassLoaderNonImageClassVisitor; friend class FixupClassVisitor; friend class FixupRootVisitor; |