1 /*
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 */
16
17 #include "driver/compiler_driver.h"
18
19 #include <limits>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <memory>
23
24 #include "art_method-inl.h"
25 #include "base/casts.h"
26 #include "class_linker-inl.h"
27 #include "common_compiler_driver_test.h"
28 #include "compiled_method-inl.h"
29 #include "compiler_callbacks.h"
30 #include "dex/dex_file.h"
31 #include "dex/dex_file_types.h"
32 #include "gc/heap.h"
33 #include "handle_scope-inl.h"
34 #include "mirror/class-inl.h"
35 #include "mirror/class_loader.h"
36 #include "mirror/dex_cache-inl.h"
37 #include "mirror/object-inl.h"
38 #include "mirror/object_array-inl.h"
39 #include "profile/profile_compilation_info.h"
40 #include "scoped_thread_state_change-inl.h"
41
42 namespace art {
43
44 class CompilerDriverTest : public CommonCompilerDriverTest {
45 protected:
CompileAllAndMakeExecutable(jobject class_loader)46 void CompileAllAndMakeExecutable(jobject class_loader) REQUIRES(!Locks::mutator_lock_) {
47 TimingLogger timings("CompilerDriverTest::CompileAllAndMakeExecutable", false, false);
48 dex_files_ = GetDexFiles(class_loader);
49 CompileAll(class_loader, dex_files_, &timings);
50 TimingLogger::ScopedTiming t("MakeAllExecutable", &timings);
51 MakeAllExecutable(class_loader);
52 }
53
EnsureCompiled(jobject class_loader,const char * class_name,const char * method,const char * signature,bool is_virtual)54 void EnsureCompiled(jobject class_loader, const char* class_name, const char* method,
55 const char* signature, bool is_virtual)
56 REQUIRES(!Locks::mutator_lock_) {
57 CompileAllAndMakeExecutable(class_loader);
58 Thread::Current()->TransitionFromSuspendedToRunnable();
59 bool started = runtime_->Start();
60 CHECK(started);
61 env_ = Thread::Current()->GetJniEnv();
62 class_ = env_->FindClass(class_name);
63 CHECK(class_ != nullptr) << "Class not found: " << class_name;
64 if (is_virtual) {
65 mid_ = env_->GetMethodID(class_, method, signature);
66 } else {
67 mid_ = env_->GetStaticMethodID(class_, method, signature);
68 }
69 CHECK(mid_ != nullptr) << "Method not found: " << class_name << "." << method << signature;
70 }
71
MakeAllExecutable(jobject class_loader)72 void MakeAllExecutable(jobject class_loader) {
73 const std::vector<const DexFile*> class_path = GetDexFiles(class_loader);
74 for (size_t i = 0; i != class_path.size(); ++i) {
75 const DexFile* dex_file = class_path[i];
76 CHECK(dex_file != nullptr);
77 MakeDexFileExecutable(class_loader, *dex_file);
78 }
79 }
80
MakeExecutable(ArtMethod * method)81 void MakeExecutable(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
82 CHECK(method != nullptr);
83
84 const void* method_code = nullptr;
85 if (!method->IsAbstract()) {
86 MethodReference method_ref(method->GetDexFile(), method->GetDexMethodIndex());
87 const CompiledMethod* compiled_method = compiler_driver_->GetCompiledMethod(method_ref);
88 // If the code size is 0 it means the method was skipped due to profile guided compilation.
89 if (compiled_method != nullptr && compiled_method->GetQuickCode().size() != 0u) {
90 method_code = CommonCompilerTest::MakeExecutable(compiled_method->GetQuickCode(),
91 compiled_method->GetVmapTable(),
92 compiled_method->GetInstructionSet());
93 LOG(INFO) << "MakeExecutable " << method->PrettyMethod() << " code=" << method_code;
94 }
95 }
96 runtime_->GetInstrumentation()->InitializeMethodsCode(method, /*aot_code=*/ method_code);
97 }
98
MakeDexFileExecutable(jobject class_loader,const DexFile & dex_file)99 void MakeDexFileExecutable(jobject class_loader, const DexFile& dex_file) {
100 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
101 for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
102 const dex::ClassDef& class_def = dex_file.GetClassDef(i);
103 const char* descriptor = dex_file.GetClassDescriptor(class_def);
104 ScopedObjectAccess soa(Thread::Current());
105 StackHandleScope<1> hs(soa.Self());
106 Handle<mirror::ClassLoader> loader(
107 hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
108 ObjPtr<mirror::Class> c = class_linker->FindClass(soa.Self(), descriptor, loader);
109 CHECK(c != nullptr);
110 const auto pointer_size = class_linker->GetImagePointerSize();
111 for (auto& m : c->GetMethods(pointer_size)) {
112 MakeExecutable(&m);
113 }
114 }
115 }
116
117 JNIEnv* env_;
118 jclass class_;
119 jmethodID mid_;
120 std::vector<const DexFile*> dex_files_;
121 };
122
123 // Disabled due to 10 second runtime on host
124 // TODO: Update the test for hash-based dex cache arrays. Bug: 30627598
TEST_F(CompilerDriverTest,DISABLED_LARGE_CompileDexLibCore)125 TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) {
126 CompileAllAndMakeExecutable(nullptr);
127
128 // All libcore references should resolve
129 ScopedObjectAccess soa(Thread::Current());
130 ASSERT_TRUE(java_lang_dex_file_ != nullptr);
131 const DexFile& dex = *java_lang_dex_file_;
132 ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(soa.Self(), dex);
133 for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
134 const ObjPtr<mirror::String> string = dex_cache->GetResolvedString(dex::StringIndex(i));
135 EXPECT_TRUE(string != nullptr) << "string_idx=" << i;
136 }
137 for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
138 const ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(dex::TypeIndex(i));
139 EXPECT_TRUE(type != nullptr)
140 << "type_idx=" << i << " " << dex.GetTypeDescriptor(dex.GetTypeId(dex::TypeIndex(i)));
141 }
142 for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
143 // FIXME: This is outdated for hash-based method array.
144 ArtMethod* method = dex_cache->GetResolvedMethod(i);
145 EXPECT_TRUE(method != nullptr) << "method_idx=" << i
146 << " " << dex.GetMethodDeclaringClassDescriptor(dex.GetMethodId(i))
147 << " " << dex.GetMethodName(dex.GetMethodId(i));
148 EXPECT_TRUE(method->GetEntryPointFromQuickCompiledCode() != nullptr) << "method_idx=" << i
149 << " " << dex.GetMethodDeclaringClassDescriptor(dex.GetMethodId(i)) << " "
150 << dex.GetMethodName(dex.GetMethodId(i));
151 }
152 for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
153 // FIXME: This is outdated for hash-based field array.
154 ArtField* field = dex_cache->GetResolvedField(i);
155 EXPECT_TRUE(field != nullptr) << "field_idx=" << i
156 << " " << dex.GetFieldDeclaringClassDescriptor(dex.GetFieldId(i))
157 << " " << dex.GetFieldName(dex.GetFieldId(i));
158 }
159
160 // TODO check Class::IsVerified for all classes
161
162 // TODO: check that all Method::GetCode() values are non-null
163 }
164
TEST_F(CompilerDriverTest,AbstractMethodErrorStub)165 TEST_F(CompilerDriverTest, AbstractMethodErrorStub) {
166 jobject class_loader;
167 {
168 ScopedObjectAccess soa(Thread::Current());
169 class_loader = LoadDex("AbstractMethod");
170 }
171 ASSERT_TRUE(class_loader != nullptr);
172 EnsureCompiled(class_loader, "AbstractClass", "foo", "()V", true);
173
174 // Create a jobj_ of ConcreteClass, NOT AbstractClass.
175 jclass c_class = env_->FindClass("ConcreteClass");
176
177 jmethodID constructor = env_->GetMethodID(c_class, "<init>", "()V");
178
179 jobject jobj_ = env_->NewObject(c_class, constructor);
180 ASSERT_TRUE(jobj_ != nullptr);
181
182 // Force non-virtual call to AbstractClass foo, will throw AbstractMethodError exception.
183 env_->CallNonvirtualVoidMethod(jobj_, class_, mid_);
184
185 EXPECT_EQ(env_->ExceptionCheck(), JNI_TRUE);
186 jthrowable exception = env_->ExceptionOccurred();
187 env_->ExceptionClear();
188 jclass jlame = env_->FindClass("java/lang/AbstractMethodError");
189 EXPECT_TRUE(env_->IsInstanceOf(exception, jlame));
190 {
191 ScopedObjectAccess soa(Thread::Current());
192 Thread::Current()->ClearException();
193 }
194 }
195
196 class CompilerDriverProfileTest : public CompilerDriverTest {
197 protected:
GetProfileCompilationInfo()198 ProfileCompilationInfo* GetProfileCompilationInfo() override {
199 ScopedObjectAccess soa(Thread::Current());
200 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ProfileTestMultiDex");
201
202 ProfileCompilationInfo info;
203 for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
204 profile_info_.AddMethod(ProfileMethodInfo(MethodReference(dex_file.get(), 1)),
205 ProfileCompilationInfo::MethodHotness::kFlagHot);
206 profile_info_.AddMethod(ProfileMethodInfo(MethodReference(dex_file.get(), 2)),
207 ProfileCompilationInfo::MethodHotness::kFlagHot);
208 }
209 return &profile_info_;
210 }
211
GetCompilerFilter() const212 CompilerFilter::Filter GetCompilerFilter() const override {
213 // Use a profile based filter.
214 return CompilerFilter::kSpeedProfile;
215 }
216
GetExpectedMethodsForClass(const std::string & clazz)217 std::unordered_set<std::string> GetExpectedMethodsForClass(const std::string& clazz) {
218 if (clazz == "Main") {
219 return std::unordered_set<std::string>({
220 "java.lang.String Main.getA()",
221 "java.lang.String Main.getB()"});
222 } else if (clazz == "Second") {
223 return std::unordered_set<std::string>({
224 "java.lang.String Second.getX()",
225 "java.lang.String Second.getY()"});
226 } else {
227 return std::unordered_set<std::string>();
228 }
229 }
230
CheckCompiledMethods(jobject class_loader,const std::string & clazz,const std::unordered_set<std::string> & expected_methods)231 void CheckCompiledMethods(jobject class_loader,
232 const std::string& clazz,
233 const std::unordered_set<std::string>& expected_methods) {
234 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
235 Thread* self = Thread::Current();
236 ScopedObjectAccess soa(self);
237 StackHandleScope<1> hs(self);
238 Handle<mirror::ClassLoader> h_loader(
239 hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
240 ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
241 ASSERT_NE(klass, nullptr);
242
243 const auto pointer_size = class_linker->GetImagePointerSize();
244 size_t number_of_compiled_methods = 0;
245 for (auto& m : klass->GetVirtualMethods(pointer_size)) {
246 std::string name = m.PrettyMethod(true);
247 const void* code = m.GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
248 ASSERT_NE(code, nullptr);
249 if (expected_methods.find(name) != expected_methods.end()) {
250 number_of_compiled_methods++;
251 EXPECT_FALSE(class_linker->IsQuickToInterpreterBridge(code));
252 } else {
253 EXPECT_TRUE(class_linker->IsQuickToInterpreterBridge(code));
254 }
255 }
256 EXPECT_EQ(expected_methods.size(), number_of_compiled_methods);
257 }
258
259 private:
260 ProfileCompilationInfo profile_info_;
261 };
262
TEST_F(CompilerDriverProfileTest,ProfileGuidedCompilation)263 TEST_F(CompilerDriverProfileTest, ProfileGuidedCompilation) {
264 Thread* self = Thread::Current();
265 jobject class_loader;
266 {
267 ScopedObjectAccess soa(self);
268 class_loader = LoadDex("ProfileTestMultiDex");
269 }
270 ASSERT_NE(class_loader, nullptr);
271
272 // Need to enable dex-file writability. Methods rejected to be compiled will run through the
273 // dex-to-dex compiler.
274 for (const DexFile* dex_file : GetDexFiles(class_loader)) {
275 ASSERT_TRUE(dex_file->EnableWrite());
276 }
277
278 CompileAllAndMakeExecutable(class_loader);
279
280 std::unordered_set<std::string> m = GetExpectedMethodsForClass("Main");
281 std::unordered_set<std::string> s = GetExpectedMethodsForClass("Second");
282 CheckCompiledMethods(class_loader, "LMain;", m);
283 CheckCompiledMethods(class_loader, "LSecond;", s);
284 }
285
286 // Test that a verify only compiler filter updates the CompiledClass map,
287 // which will be used for OatClass.
288 class CompilerDriverVerifyTest : public CompilerDriverTest {
289 protected:
GetCompilerFilter() const290 CompilerFilter::Filter GetCompilerFilter() const override {
291 return CompilerFilter::kVerify;
292 }
293
CheckVerifiedClass(jobject class_loader,const std::string & clazz) const294 void CheckVerifiedClass(jobject class_loader, const std::string& clazz) const {
295 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
296 Thread* self = Thread::Current();
297 ScopedObjectAccess soa(self);
298 StackHandleScope<1> hs(self);
299 Handle<mirror::ClassLoader> h_loader(
300 hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
301 ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
302 ASSERT_NE(klass, nullptr);
303 EXPECT_TRUE(klass->IsVerified());
304
305 ClassStatus status;
306 bool found = compiler_driver_->GetCompiledClass(
307 ClassReference(&klass->GetDexFile(), klass->GetDexTypeIndex().index_), &status);
308 ASSERT_TRUE(found);
309 EXPECT_GE(status, ClassStatus::kVerified);
310 }
311 };
312
TEST_F(CompilerDriverVerifyTest,VerifyCompilation)313 TEST_F(CompilerDriverVerifyTest, VerifyCompilation) {
314 Thread* self = Thread::Current();
315 jobject class_loader;
316 {
317 ScopedObjectAccess soa(self);
318 class_loader = LoadDex("ProfileTestMultiDex");
319 }
320 ASSERT_NE(class_loader, nullptr);
321
322 CompileAllAndMakeExecutable(class_loader);
323
324 CheckVerifiedClass(class_loader, "LMain;");
325 CheckVerifiedClass(class_loader, "LSecond;");
326 }
327
328 // Test that a class of status ClassStatus::kRetryVerificationAtRuntime is indeed
329 // recorded that way in the driver.
TEST_F(CompilerDriverVerifyTest,RetryVerifcationStatusCheckVerified)330 TEST_F(CompilerDriverVerifyTest, RetryVerifcationStatusCheckVerified) {
331 Thread* const self = Thread::Current();
332 jobject class_loader;
333 std::vector<const DexFile*> dex_files;
334 const DexFile* dex_file = nullptr;
335 {
336 ScopedObjectAccess soa(self);
337 class_loader = LoadDex("ProfileTestMultiDex");
338 ASSERT_NE(class_loader, nullptr);
339 dex_files = GetDexFiles(class_loader);
340 ASSERT_GT(dex_files.size(), 0u);
341 dex_file = dex_files.front();
342 }
343 SetDexFilesForOatFile(dex_files);
344 callbacks_->SetDoesClassUnloading(true, compiler_driver_.get());
345 ClassReference ref(dex_file, 0u);
346 // Test that the status is read from the compiler driver as expected.
347 static_assert(enum_cast<size_t>(ClassStatus::kLast) < std::numeric_limits<size_t>::max(),
348 "Make sure incrementing the class status does not overflow.");
349 for (size_t i = enum_cast<size_t>(ClassStatus::kRetryVerificationAtRuntime);
350 i <= enum_cast<size_t>(ClassStatus::kLast);
351 ++i) {
352 const ClassStatus expected_status = enum_cast<ClassStatus>(i);
353 // Skip unsupported status that are not supposed to be ever recorded.
354 if (expected_status == ClassStatus::kInitializing ||
355 expected_status == ClassStatus::kInitialized) {
356 continue;
357 }
358 compiler_driver_->RecordClassStatus(ref, expected_status);
359 ClassStatus status = {};
360 ASSERT_TRUE(compiler_driver_->GetCompiledClass(ref, &status));
361 EXPECT_EQ(status, expected_status);
362 }
363 }
364
365 // TODO: need check-cast test (when stub complete & we can throw/catch
366
367 } // namespace art
368