TEST_F(ImageTest, TestImageLayout) {
std::vector<size_t> image_sizes;
std::vector<size_t> image_sizes_extra; // Compile multi-image with ImageLayoutA being the last image.
{
CompilationHelper helper;
Compile(ImageHeader::kStorageModeUncompressed, /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
helper, "ImageLayoutA",
{"LMyClass;"});
image_sizes = helper.GetImageObjectSectionSizes();
}
TearDown();
runtime_.reset();
SetUp(); // Compile multi-image with ImageLayoutB being the last image.
{
CompilationHelper helper;
Compile(ImageHeader::kStorageModeUncompressed, /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
helper, "ImageLayoutB",
{"LMyClass;"});
image_sizes_extra = helper.GetImageObjectSectionSizes();
} // Make sure that the new stuff in the clinit in ImageLayoutB is in the last image and not in the // first two images.
ASSERT_EQ(image_sizes.size(), image_sizes.size()); // Sizes of the object sections should be the same for all but the last image. for (size_t i = 0; i < image_sizes.size() - 1; ++i) {
EXPECT_EQ(image_sizes[i], image_sizes_extra[i]);
} // Last image should be larger since it has a hash map and a string.
EXPECT_LT(image_sizes.back(), image_sizes_extra.back());
}
// Please note that for the following condition to be true, the above values should be chosen in // a way that image_reservation_size != RoundUp(image_size_, kElfSegmentAlignment).
ASSERT_TRUE(!image_header.IsAppImage());
char* magic = const_cast<char*>(image_header.GetMagic());
strcpy(magic, ""); // bad magic
ASSERT_FALSE(image_header.IsValid());
strcpy(magic, "art\n000"); // bad version
ASSERT_FALSE(image_header.IsValid());
}
// Test that pointer to quick code is the same in // a default method of an interface and in a copied method // of a class which implements the interface. This should be true // only if the copied method and the origin method are located in the // same oat file.
TEST_F(ImageTest, TestDefaultMethods) { // TODO(b/376621099): investigate LUCI failures (timeouts?) and re-enable this test. // This is disabled on VM because it times out.
TEST_DISABLED_ON_VM();
// Use this test to compile managed code to catch crashes when compiling the boot class path. // This test already needs to compile some managed methods and by compiling with "speed" we // avoid the need to create a specialized profile for the "speed-profile" compilation. // (Using "speed" shall compile most methods. We could compile more with "everything".)
SetCompilerFilter(CompilerFilter::kSpeed);
CompilationHelper helper;
Compile(ImageHeader::kStorageModeUncompressed, /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
helper, "DefaultMethods",
{"LIface;", "LImpl;", "LIterableBase;"});
// Test the pointer to quick code is the same in origin method // and in the copied method from the same oat file.
ObjPtr<mirror::Class> iface_klass =
class_linker_->LookupClass(self, "LIface;", /*class_loader=*/ nullptr);
ASSERT_NE(nullptr, iface_klass);
ArtMethod* origin = iface_klass->FindInterfaceMethod("defaultMethod", "()V", pointer_size);
ASSERT_NE(nullptr, origin);
ASSERT_OBJ_PTR_EQ(origin->GetDeclaringClass(), iface_klass); constvoid* code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size); // The origin method should have a pointer to quick code
ASSERT_NE(nullptr, code);
ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
ObjPtr<mirror::Class> impl_klass =
class_linker_->LookupClass(self, "LImpl;", /*class_loader=*/ nullptr);
ASSERT_NE(nullptr, impl_klass);
ArtMethod* copied = FindCopiedMethod(origin, impl_klass);
ASSERT_NE(nullptr, copied); // the copied method should have pointer to the same quick code as the origin method
ASSERT_EQ(code, copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size));
// Test the origin method has pointer to quick code // but the copied method has pointer to interpreter // because these methods are in different oat files.
ObjPtr<mirror::Class> iterable_klass =
class_linker_->LookupClass(self, "Ljava/lang/Iterable;", /*class_loader=*/ nullptr);
ASSERT_NE(nullptr, iterable_klass);
origin = iterable_klass->FindClassMethod( "forEach", "(Ljava/util/function/Consumer;)V", pointer_size);
ASSERT_NE(nullptr, origin);
ASSERT_FALSE(origin->IsDirect());
ASSERT_OBJ_PTR_EQ(origin->GetDeclaringClass(), iterable_klass);
code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size); // the origin method should have a pointer to quick code
ASSERT_NE(nullptr, code);
ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
ObjPtr<mirror::Class> iterablebase_klass =
class_linker_->LookupClass(self, "LIterableBase;", /*class_loader=*/ nullptr);
ASSERT_NE(nullptr, iterablebase_klass);
copied = FindCopiedMethod(origin, iterablebase_klass);
ASSERT_NE(nullptr, copied);
code = copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size); // the copied method should have a pointer to interpreter
ASSERT_TRUE(class_linker_->IsQuickToInterpreterBridge(code));
}
// Regression test for dex2oat crash for soft verification failure during // class initialization check from the transactional interpreter while // running the class initializer for another class.
TEST_F(ImageTest, TestSoftVerificationFailureDuringClassInitialization) {
CompilationHelper helper;
Compile(ImageHeader::kStorageModeUncompressed, /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
helper, "VerifySoftFailDuringClinit", /*image_classes=*/ {"LClassToInitialize;"}, /*image_classes_failing_aot_clinit=*/ {"LClassToInitialize;"});
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.