blob: 9d7aff769b0f600df430fea60e06b1607600254b [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Brian Carlstromdb4d5402011-08-09 12:18:28 -070016
Vladimir Marko1352f132017-04-28 15:28:29 +010017#include <string.h>
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070018#include <vector>
19
Vladimir Marko1352f132017-04-28 15:28:29 +010020#include "image_test.h"
Andreas Gampe46ee31b2016-12-14 10:11:49 -080021
Vladimir Marko1352f132017-04-28 15:28:29 +010022#include "image.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070023#include "scoped_thread_state_change-inl.h"
Vladimir Marko1352f132017-04-28 15:28:29 +010024#include "thread.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070025
Brian Carlstromdb4d5402011-08-09 12:18:28 -070026namespace art {
27
Mathieu Chartier496577f2016-09-20 15:33:31 -070028TEST_F(ImageTest, TestImageLayout) {
29 std::vector<size_t> image_sizes;
30 std::vector<size_t> image_sizes_extra;
31 // Compile multi-image with ImageLayoutA being the last image.
32 {
33 CompilationHelper helper;
Artem Udovichenkob3f2b5c2017-01-31 11:49:33 +030034 Compile(ImageHeader::kStorageModeUncompressed, helper, "ImageLayoutA", {"LMyClass;"});
Mathieu Chartier496577f2016-09-20 15:33:31 -070035 image_sizes = helper.GetImageObjectSectionSizes();
36 }
37 TearDown();
38 runtime_.reset();
39 SetUp();
40 // Compile multi-image with ImageLayoutB being the last image.
41 {
42 CompilationHelper helper;
Artem Udovichenkob3f2b5c2017-01-31 11:49:33 +030043 Compile(ImageHeader::kStorageModeUncompressed, helper, "ImageLayoutB", {"LMyClass;"});
Mathieu Chartier496577f2016-09-20 15:33:31 -070044 image_sizes_extra = helper.GetImageObjectSectionSizes();
45 }
46 // Make sure that the new stuff in the clinit in ImageLayoutB is in the last image and not in the
47 // first two images.
48 ASSERT_EQ(image_sizes.size(), image_sizes.size());
49 // Sizes of the images should be the same. These sizes are for the whole image unrounded.
50 for (size_t i = 0; i < image_sizes.size() - 1; ++i) {
51 EXPECT_EQ(image_sizes[i], image_sizes_extra[i]);
52 }
53 // Last image should be larger since it has a hash map and a string.
54 EXPECT_LT(image_sizes.back(), image_sizes_extra.back());
55}
56
Brian Carlstrom179486a2013-09-03 11:51:42 -070057TEST_F(ImageTest, ImageHeaderIsValid) {
58 uint32_t image_begin = ART_BASE_ADDRESS;
59 uint32_t image_size_ = 16 * KB;
Brian Carlstrom179486a2013-09-03 11:51:42 -070060 uint32_t image_roots = ART_BASE_ADDRESS + (1 * KB);
61 uint32_t oat_checksum = 0;
62 uint32_t oat_file_begin = ART_BASE_ADDRESS + (4 * KB); // page aligned
63 uint32_t oat_data_begin = ART_BASE_ADDRESS + (8 * KB); // page aligned
64 uint32_t oat_data_end = ART_BASE_ADDRESS + (9 * KB);
65 uint32_t oat_file_end = ART_BASE_ADDRESS + (10 * KB);
Mathieu Chartiere401d142015-04-22 13:56:20 -070066 ImageSection sections[ImageHeader::kSectionCount];
Brian Carlstrom179486a2013-09-03 11:51:42 -070067 ImageHeader image_header(image_begin,
68 image_size_,
Mathieu Chartiere401d142015-04-22 13:56:20 -070069 sections,
Brian Carlstrom179486a2013-09-03 11:51:42 -070070 image_roots,
71 oat_checksum,
72 oat_file_begin,
73 oat_data_begin,
74 oat_data_end,
Igor Murashkin46774762014-10-22 11:37:02 -070075 oat_file_end,
Mathieu Chartierfbc31082016-01-24 11:59:56 -080076 /*boot_image_begin*/0U,
77 /*boot_image_size*/0U,
78 /*boot_oat_begin*/0U,
79 /*boot_oat_size_*/0U,
Mathieu Chartiere401d142015-04-22 13:56:20 -070080 sizeof(void*),
Mathieu Chartierceb07b32015-12-10 09:33:21 -080081 /*compile_pic*/false,
Mathieu Chartierfbc31082016-01-24 11:59:56 -080082 /*is_pic*/false,
Mathieu Chartierceb07b32015-12-10 09:33:21 -080083 ImageHeader::kDefaultStorageMode,
84 /*data_size*/0u);
Brian Carlstrom179486a2013-09-03 11:51:42 -070085 ASSERT_TRUE(image_header.IsValid());
Mathieu Chartierfbc31082016-01-24 11:59:56 -080086 ASSERT_TRUE(!image_header.IsAppImage());
Brian Carlstrom179486a2013-09-03 11:51:42 -070087
88 char* magic = const_cast<char*>(image_header.GetMagic());
89 strcpy(magic, ""); // bad magic
90 ASSERT_FALSE(image_header.IsValid());
91 strcpy(magic, "art\n000"); // bad version
92 ASSERT_FALSE(image_header.IsValid());
93}
94
Artem Udovichenkob3f2b5c2017-01-31 11:49:33 +030095// Test that pointer to quick code is the same in
96// a default method of an interface and in a copied method
97// of a class which implements the interface. This should be true
98// only if the copied method and the origin method are located in the
99// same oat file.
100TEST_F(ImageTest, TestDefaultMethods) {
101 CompilationHelper helper;
102 Compile(ImageHeader::kStorageModeUncompressed,
103 helper,
104 "DefaultMethods",
105 {"LIface;", "LImpl;", "LIterableBase;"});
106
107 PointerSize pointer_size = class_linker_->GetImagePointerSize();
108 Thread* self = Thread::Current();
109 ScopedObjectAccess soa(self);
110
111 // Test the pointer to quick code is the same in origin method
112 // and in the copied method form the same oat file.
113 mirror::Class* iface_klass = class_linker_->LookupClass(
114 self, "LIface;", ObjPtr<mirror::ClassLoader>());
115 ASSERT_NE(nullptr, iface_klass);
116 ArtMethod* origin = iface_klass->FindDeclaredVirtualMethod(
117 "defaultMethod", "()V", pointer_size);
118 ASSERT_NE(nullptr, origin);
119 const void* code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
120 // The origin method should have a pointer to quick code
121 ASSERT_NE(nullptr, code);
122 ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
123 mirror::Class* impl_klass = class_linker_->LookupClass(
124 self, "LImpl;", ObjPtr<mirror::ClassLoader>());
125 ASSERT_NE(nullptr, impl_klass);
126 ArtMethod* copied = FindCopiedMethod(origin, impl_klass);
127 ASSERT_NE(nullptr, copied);
128 // the copied method should have pointer to the same quick code as the origin method
129 ASSERT_EQ(code, copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size));
130
131 // Test the origin method has pointer to quick code
132 // but the copied method has pointer to interpreter
133 // because these methods are in different oat files.
134 mirror::Class* iterable_klass = class_linker_->LookupClass(
135 self, "Ljava/lang/Iterable;", ObjPtr<mirror::ClassLoader>());
136 ASSERT_NE(nullptr, iterable_klass);
137 origin = iterable_klass->FindDeclaredVirtualMethod(
138 "forEach", "(Ljava/util/function/Consumer;)V", pointer_size);
139 ASSERT_NE(nullptr, origin);
140 code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
141 // the origin method should have a pointer to quick code
142 ASSERT_NE(nullptr, code);
143 ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
144 mirror::Class* iterablebase_klass = class_linker_->LookupClass(
145 self, "LIterableBase;", ObjPtr<mirror::ClassLoader>());
146 ASSERT_NE(nullptr, iterablebase_klass);
147 copied = FindCopiedMethod(origin, iterablebase_klass);
148 ASSERT_NE(nullptr, copied);
149 code = copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
150 // the copied method should have a pointer to interpreter
151 ASSERT_TRUE(class_linker_->IsQuickToInterpreterBridge(code));
152}
153
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700154} // namespace art