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