xref: /aosp_15_r20/art/runtime/dexopt_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "dexopt_test.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
20*795d594fSAndroid Build Coastguard Worker #include <procinfo/process_map.h>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <string>
23*795d594fSAndroid Build Coastguard Worker #include <vector>
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
26*795d594fSAndroid Build Coastguard Worker #include "android-base/strings.h"
27*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/file_utils.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/mem_map.h"
30*795d594fSAndroid Build Coastguard Worker #include "common_runtime_test.h"
31*795d594fSAndroid Build Coastguard Worker #include "compiler_callbacks.h"
32*795d594fSAndroid Build Coastguard Worker #include "dex/art_dex_file_loader.h"
33*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_loader.h"
34*795d594fSAndroid Build Coastguard Worker #include "dex2oat_environment_test.h"
35*795d594fSAndroid Build Coastguard Worker #include "gc/space/image_space.h"
36*795d594fSAndroid Build Coastguard Worker #include "hidden_api.h"
37*795d594fSAndroid Build Coastguard Worker #include "oat/oat.h"
38*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file_assistant.h"
39*795d594fSAndroid Build Coastguard Worker #include "profile/profile_compilation_info.h"
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
SetUp()42*795d594fSAndroid Build Coastguard Worker void DexoptTest::SetUp() {
43*795d594fSAndroid Build Coastguard Worker   ReserveImageSpace();
44*795d594fSAndroid Build Coastguard Worker   Dex2oatEnvironmentTest::SetUp();
45*795d594fSAndroid Build Coastguard Worker }
46*795d594fSAndroid Build Coastguard Worker 
PreRuntimeCreate()47*795d594fSAndroid Build Coastguard Worker void DexoptTest::PreRuntimeCreate() {
48*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
49*795d594fSAndroid Build Coastguard Worker   UnreserveImageSpace();
50*795d594fSAndroid Build Coastguard Worker }
51*795d594fSAndroid Build Coastguard Worker 
PostRuntimeCreate()52*795d594fSAndroid Build Coastguard Worker void DexoptTest::PostRuntimeCreate() { ReserveImageSpace(); }
53*795d594fSAndroid Build Coastguard Worker 
Dex2Oat(const std::vector<std::string> & args,std::string * error_msg)54*795d594fSAndroid Build Coastguard Worker bool DexoptTest::Dex2Oat(const std::vector<std::string>& args, std::string* error_msg) {
55*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> argv;
56*795d594fSAndroid Build Coastguard Worker   if (!CommonRuntimeTest::StartDex2OatCommandLine(&argv, error_msg)) {
57*795d594fSAndroid Build Coastguard Worker     return false;
58*795d594fSAndroid Build Coastguard Worker   }
59*795d594fSAndroid Build Coastguard Worker 
60*795d594fSAndroid Build Coastguard Worker   Runtime* runtime = Runtime::Current();
61*795d594fSAndroid Build Coastguard Worker   if (runtime->GetHiddenApiEnforcementPolicy() == hiddenapi::EnforcementPolicy::kEnabled) {
62*795d594fSAndroid Build Coastguard Worker     argv.push_back("--runtime-arg");
63*795d594fSAndroid Build Coastguard Worker     argv.push_back("-Xhidden-api-policy:enabled");
64*795d594fSAndroid Build Coastguard Worker   }
65*795d594fSAndroid Build Coastguard Worker 
66*795d594fSAndroid Build Coastguard Worker   if (!kIsTargetBuild) {
67*795d594fSAndroid Build Coastguard Worker     argv.push_back("--host");
68*795d594fSAndroid Build Coastguard Worker   }
69*795d594fSAndroid Build Coastguard Worker 
70*795d594fSAndroid Build Coastguard Worker   argv.insert(argv.end(), args.begin(), args.end());
71*795d594fSAndroid Build Coastguard Worker 
72*795d594fSAndroid Build Coastguard Worker   std::string command_line(android::base::Join(argv, ' '));
73*795d594fSAndroid Build Coastguard Worker   return Exec(argv, error_msg);
74*795d594fSAndroid Build Coastguard Worker }
75*795d594fSAndroid Build Coastguard Worker 
GenerateAlternateImage(const std::string & scratch_dir)76*795d594fSAndroid Build Coastguard Worker std::string DexoptTest::GenerateAlternateImage(const std::string& scratch_dir) {
77*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> libcore_dex_files = GetLibCoreDexFileNames();
78*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> libcore_dex_locations = GetLibCoreDexLocations();
79*795d594fSAndroid Build Coastguard Worker 
80*795d594fSAndroid Build Coastguard Worker   std::string image_dir = scratch_dir + GetInstructionSetString(kRuntimeISA);
81*795d594fSAndroid Build Coastguard Worker   int mkdir_result = mkdir(image_dir.c_str(), 0700);
82*795d594fSAndroid Build Coastguard Worker   CHECK_EQ(0, mkdir_result) << image_dir.c_str();
83*795d594fSAndroid Build Coastguard Worker 
84*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> extra_args{
85*795d594fSAndroid Build Coastguard Worker       "--compiler-filter=verify",
86*795d594fSAndroid Build Coastguard Worker       android::base::StringPrintf("--base=0x%08x", ART_BASE_ADDRESS),
87*795d594fSAndroid Build Coastguard Worker   };
88*795d594fSAndroid Build Coastguard Worker   std::string filename_prefix = image_dir + "/boot-interpreter";
89*795d594fSAndroid Build Coastguard Worker   ArrayRef<const std::string> dex_files(libcore_dex_files);
90*795d594fSAndroid Build Coastguard Worker   ArrayRef<const std::string> dex_locations(libcore_dex_locations);
91*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
92*795d594fSAndroid Build Coastguard Worker   bool ok = CompileBootImage(extra_args, filename_prefix, dex_files, dex_locations, &error_msg);
93*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(ok) << error_msg;
94*795d594fSAndroid Build Coastguard Worker 
95*795d594fSAndroid Build Coastguard Worker   return scratch_dir + "boot-interpreter.art";
96*795d594fSAndroid Build Coastguard Worker }
97*795d594fSAndroid Build Coastguard Worker 
GenerateOatForTest(const std::string & dex_location,const std::string & oat_location,CompilerFilter::Filter filter,bool with_alternate_image,const char * compilation_reason,const std::vector<std::string> & extra_args)98*795d594fSAndroid Build Coastguard Worker void DexoptTest::GenerateOatForTest(const std::string& dex_location,
99*795d594fSAndroid Build Coastguard Worker                                     const std::string& oat_location,
100*795d594fSAndroid Build Coastguard Worker                                     CompilerFilter::Filter filter,
101*795d594fSAndroid Build Coastguard Worker                                     bool with_alternate_image,
102*795d594fSAndroid Build Coastguard Worker                                     const char* compilation_reason,
103*795d594fSAndroid Build Coastguard Worker                                     const std::vector<std::string>& extra_args) {
104*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> args;
105*795d594fSAndroid Build Coastguard Worker   args.push_back("--dex-file=" + dex_location);
106*795d594fSAndroid Build Coastguard Worker   args.push_back("--oat-file=" + oat_location);
107*795d594fSAndroid Build Coastguard Worker   args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
108*795d594fSAndroid Build Coastguard Worker   args.push_back("--runtime-arg");
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker   // Use -Xnorelocate regardless of the relocate argument.
111*795d594fSAndroid Build Coastguard Worker   // We control relocation by redirecting the dalvik cache when needed
112*795d594fSAndroid Build Coastguard Worker   // rather than use this flag.
113*795d594fSAndroid Build Coastguard Worker   args.push_back("-Xnorelocate");
114*795d594fSAndroid Build Coastguard Worker 
115*795d594fSAndroid Build Coastguard Worker   ScratchFile profile_file;
116*795d594fSAndroid Build Coastguard Worker   if (CompilerFilter::DependsOnProfile(filter)) {
117*795d594fSAndroid Build Coastguard Worker     // Create a profile with some basic content so that dex2oat
118*795d594fSAndroid Build Coastguard Worker     // doesn't get an empty profile and changes the filter to verify.
119*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
120*795d594fSAndroid Build Coastguard Worker     std::vector<std::unique_ptr<const DexFile>> dex_files;
121*795d594fSAndroid Build Coastguard Worker     ArtDexFileLoader dex_file_loader(dex_location);
122*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(dex_file_loader.Open(
123*795d594fSAndroid Build Coastguard Worker         /*verify=*/false, /*verify_checksum=*/false, &error_msg, &dex_files));
124*795d594fSAndroid Build Coastguard Worker     EXPECT_GE(dex_files.size(), 1U);
125*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<const DexFile>& dex_file = dex_files[0];
126*795d594fSAndroid Build Coastguard Worker     ProfileCompilationInfo info;
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker     info.AddClass(*dex_file, dex::TypeIndex(0));
129*795d594fSAndroid Build Coastguard Worker 
130*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(info.Save(profile_file.GetFd()));
131*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(0, profile_file.GetFile()->Flush());
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker     // Set the argument
134*795d594fSAndroid Build Coastguard Worker     args.push_back("--profile-file=" + profile_file.GetFilename());
135*795d594fSAndroid Build Coastguard Worker   }
136*795d594fSAndroid Build Coastguard Worker 
137*795d594fSAndroid Build Coastguard Worker   std::string image_location = GetImageLocation();
138*795d594fSAndroid Build Coastguard Worker   std::optional<ScratchDir> scratch;
139*795d594fSAndroid Build Coastguard Worker   if (with_alternate_image) {
140*795d594fSAndroid Build Coastguard Worker     scratch.emplace();  // Create the scratch directory for the generated boot image.
141*795d594fSAndroid Build Coastguard Worker     std::string alternate_image_location = GenerateAlternateImage(scratch->GetPath());
142*795d594fSAndroid Build Coastguard Worker     args.push_back("--boot-image=" + alternate_image_location);
143*795d594fSAndroid Build Coastguard Worker   }
144*795d594fSAndroid Build Coastguard Worker 
145*795d594fSAndroid Build Coastguard Worker   if (compilation_reason != nullptr) {
146*795d594fSAndroid Build Coastguard Worker     args.push_back("--compilation-reason=" + std::string(compilation_reason));
147*795d594fSAndroid Build Coastguard Worker   }
148*795d594fSAndroid Build Coastguard Worker 
149*795d594fSAndroid Build Coastguard Worker   args.insert(args.end(), extra_args.begin(), extra_args.end());
150*795d594fSAndroid Build Coastguard Worker 
151*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
152*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
153*795d594fSAndroid Build Coastguard Worker 
154*795d594fSAndroid Build Coastguard Worker   // Verify the odex file was generated as expected.
155*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
156*795d594fSAndroid Build Coastguard Worker                                                    oat_location,
157*795d594fSAndroid Build Coastguard Worker                                                    oat_location,
158*795d594fSAndroid Build Coastguard Worker                                                    /*executable=*/false,
159*795d594fSAndroid Build Coastguard Worker                                                    /*low_4gb=*/false,
160*795d594fSAndroid Build Coastguard Worker                                                    dex_location,
161*795d594fSAndroid Build Coastguard Worker                                                    &error_msg));
162*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
163*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(filter, odex_file->GetCompilerFilter());
164*795d594fSAndroid Build Coastguard Worker 
165*795d594fSAndroid Build Coastguard Worker   if (CompilerFilter::DependsOnImageChecksum(filter)) {
166*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(/*spec=*/"");
167*795d594fSAndroid Build Coastguard Worker     OatFileAssistant oat_file_assistant(dex_location.c_str(),
168*795d594fSAndroid Build Coastguard Worker                                         kRuntimeISA,
169*795d594fSAndroid Build Coastguard Worker                                         context.get(),
170*795d594fSAndroid Build Coastguard Worker                                         /*load_executable=*/false);
171*795d594fSAndroid Build Coastguard Worker 
172*795d594fSAndroid Build Coastguard Worker     bool match = oat_file_assistant.ValidateBootClassPathChecksums(*odex_file);
173*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(!with_alternate_image, match) << error_msg;
174*795d594fSAndroid Build Coastguard Worker   }
175*795d594fSAndroid Build Coastguard Worker }
176*795d594fSAndroid Build Coastguard Worker 
GenerateOdexForTest(const std::string & dex_location,const std::string & odex_location,CompilerFilter::Filter filter,const char * compilation_reason,const std::vector<std::string> & extra_args)177*795d594fSAndroid Build Coastguard Worker void DexoptTest::GenerateOdexForTest(const std::string& dex_location,
178*795d594fSAndroid Build Coastguard Worker                                      const std::string& odex_location,
179*795d594fSAndroid Build Coastguard Worker                                      CompilerFilter::Filter filter,
180*795d594fSAndroid Build Coastguard Worker                                      const char* compilation_reason,
181*795d594fSAndroid Build Coastguard Worker                                      const std::vector<std::string>& extra_args) {
182*795d594fSAndroid Build Coastguard Worker   GenerateOatForTest(dex_location,
183*795d594fSAndroid Build Coastguard Worker                      odex_location,
184*795d594fSAndroid Build Coastguard Worker                      filter,
185*795d594fSAndroid Build Coastguard Worker                      /*with_alternate_image=*/false,
186*795d594fSAndroid Build Coastguard Worker                      compilation_reason,
187*795d594fSAndroid Build Coastguard Worker                      extra_args);
188*795d594fSAndroid Build Coastguard Worker }
189*795d594fSAndroid Build Coastguard Worker 
GenerateOatForTest(const char * dex_location,CompilerFilter::Filter filter,bool with_alternate_image)190*795d594fSAndroid Build Coastguard Worker void DexoptTest::GenerateOatForTest(const char* dex_location,
191*795d594fSAndroid Build Coastguard Worker                                     CompilerFilter::Filter filter,
192*795d594fSAndroid Build Coastguard Worker                                     bool with_alternate_image) {
193*795d594fSAndroid Build Coastguard Worker   std::string oat_location;
194*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
195*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
196*795d594fSAndroid Build Coastguard Worker       dex_location, kRuntimeISA, &oat_location, &error_msg))
197*795d594fSAndroid Build Coastguard Worker       << error_msg;
198*795d594fSAndroid Build Coastguard Worker   GenerateOatForTest(dex_location, oat_location, filter, with_alternate_image);
199*795d594fSAndroid Build Coastguard Worker }
200*795d594fSAndroid Build Coastguard Worker 
GenerateOatForTest(const char * dex_location,CompilerFilter::Filter filter)201*795d594fSAndroid Build Coastguard Worker void DexoptTest::GenerateOatForTest(const char* dex_location, CompilerFilter::Filter filter) {
202*795d594fSAndroid Build Coastguard Worker   GenerateOatForTest(dex_location, filter, /*with_alternate_image=*/false);
203*795d594fSAndroid Build Coastguard Worker }
204*795d594fSAndroid Build Coastguard Worker 
ReserveImageSpace()205*795d594fSAndroid Build Coastguard Worker void DexoptTest::ReserveImageSpace() {
206*795d594fSAndroid Build Coastguard Worker   MemMap::Init();
207*795d594fSAndroid Build Coastguard Worker 
208*795d594fSAndroid Build Coastguard Worker   // Ensure a chunk of memory is reserved for the image space.
209*795d594fSAndroid Build Coastguard Worker   uint64_t reservation_start = ART_BASE_ADDRESS;
210*795d594fSAndroid Build Coastguard Worker   uint64_t reservation_end = ART_BASE_ADDRESS + 384 * MB;
211*795d594fSAndroid Build Coastguard Worker 
212*795d594fSAndroid Build Coastguard Worker   std::vector<android::procinfo::MapInfo> maps;
213*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(android::procinfo::ReadProcessMaps(getpid(), &maps));
214*795d594fSAndroid Build Coastguard Worker   for (const android::procinfo::MapInfo& map_info : maps) {
215*795d594fSAndroid Build Coastguard Worker     ReserveImageSpaceChunk(reservation_start, std::min(map_info.start, reservation_end));
216*795d594fSAndroid Build Coastguard Worker     reservation_start = std::max(reservation_start, map_info.end);
217*795d594fSAndroid Build Coastguard Worker     if (reservation_start >= reservation_end) {
218*795d594fSAndroid Build Coastguard Worker       break;
219*795d594fSAndroid Build Coastguard Worker     }
220*795d594fSAndroid Build Coastguard Worker   }
221*795d594fSAndroid Build Coastguard Worker   ReserveImageSpaceChunk(reservation_start, reservation_end);
222*795d594fSAndroid Build Coastguard Worker }
223*795d594fSAndroid Build Coastguard Worker 
ReserveImageSpaceChunk(uintptr_t start,uintptr_t end)224*795d594fSAndroid Build Coastguard Worker void DexoptTest::ReserveImageSpaceChunk(uintptr_t start, uintptr_t end) {
225*795d594fSAndroid Build Coastguard Worker   if (start < end) {
226*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
227*795d594fSAndroid Build Coastguard Worker     image_reservation_.push_back(MemMap::MapAnonymous("image reservation",
228*795d594fSAndroid Build Coastguard Worker                                                       reinterpret_cast<uint8_t*>(start),
229*795d594fSAndroid Build Coastguard Worker                                                       end - start,
230*795d594fSAndroid Build Coastguard Worker                                                       PROT_NONE,
231*795d594fSAndroid Build Coastguard Worker                                                       /*low_4gb=*/false,
232*795d594fSAndroid Build Coastguard Worker                                                       /*reuse=*/false,
233*795d594fSAndroid Build Coastguard Worker                                                       /*reservation=*/nullptr,
234*795d594fSAndroid Build Coastguard Worker                                                       &error_msg));
235*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(image_reservation_.back().IsValid()) << error_msg;
236*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "Reserved space for image "
237*795d594fSAndroid Build Coastguard Worker               << reinterpret_cast<void*>(image_reservation_.back().Begin()) << "-"
238*795d594fSAndroid Build Coastguard Worker               << reinterpret_cast<void*>(image_reservation_.back().End());
239*795d594fSAndroid Build Coastguard Worker   }
240*795d594fSAndroid Build Coastguard Worker }
241*795d594fSAndroid Build Coastguard Worker 
UnreserveImageSpace()242*795d594fSAndroid Build Coastguard Worker void DexoptTest::UnreserveImageSpace() { image_reservation_.clear(); }
243*795d594fSAndroid Build Coastguard Worker 
244*795d594fSAndroid Build Coastguard Worker }  // namespace art
245