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 <stdint.h>
20 #include <stdio.h>
21 #include <memory>
22 
23 #include "art_method-inl.h"
24 #include "class_linker-inl.h"
25 #include "common_compiler_test.h"
26 #include "compiled_class.h"
27 #include "dex_file.h"
28 #include "dex_file_types.h"
29 #include "gc/heap.h"
30 #include "mirror/class-inl.h"
31 #include "mirror/class_loader.h"
32 #include "mirror/dex_cache-inl.h"
33 #include "mirror/object_array-inl.h"
34 #include "mirror/object-inl.h"
35 #include "handle_scope-inl.h"
36 #include "jit/profile_compilation_info.h"
37 #include "scoped_thread_state_change-inl.h"
38 
39 namespace art {
40 
41 class CompilerDriverTest : public CommonCompilerTest {
42  protected:
CompileAll(jobject class_loader)43   void CompileAll(jobject class_loader) REQUIRES(!Locks::mutator_lock_) {
44     TimingLogger timings("CompilerDriverTest::CompileAll", false, false);
45     TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
46     compiler_driver_->CompileAll(class_loader,
47                                  GetDexFiles(class_loader),
48                                  /* verifier_deps */ nullptr,
49                                  &timings);
50     t.NewTiming("MakeAllExecutable");
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     CompileAll(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 
MakeDexFileExecutable(jobject class_loader,const DexFile & dex_file)81   void MakeDexFileExecutable(jobject class_loader, const DexFile& dex_file) {
82     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
83     for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
84       const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
85       const char* descriptor = dex_file.GetClassDescriptor(class_def);
86       ScopedObjectAccess soa(Thread::Current());
87       StackHandleScope<1> hs(soa.Self());
88       Handle<mirror::ClassLoader> loader(
89           hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
90       mirror::Class* c = class_linker->FindClass(soa.Self(), descriptor, loader);
91       CHECK(c != nullptr);
92       const auto pointer_size = class_linker->GetImagePointerSize();
93       for (auto& m : c->GetMethods(pointer_size)) {
94         MakeExecutable(&m);
95       }
96     }
97   }
98 
99   JNIEnv* env_;
100   jclass class_;
101   jmethodID mid_;
102 };
103 
104 // Disabled due to 10 second runtime on host
105 // TODO: Update the test for hash-based dex cache arrays. Bug: 30627598
TEST_F(CompilerDriverTest,DISABLED_LARGE_CompileDexLibCore)106 TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) {
107   CompileAll(nullptr);
108 
109   // All libcore references should resolve
110   ScopedObjectAccess soa(Thread::Current());
111   ASSERT_TRUE(java_lang_dex_file_ != nullptr);
112   const DexFile& dex = *java_lang_dex_file_;
113   ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(soa.Self(), dex);
114   EXPECT_EQ(dex.NumStringIds(), dex_cache->NumStrings());
115   for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
116     const mirror::String* string = dex_cache->GetResolvedString(dex::StringIndex(i));
117     EXPECT_TRUE(string != nullptr) << "string_idx=" << i;
118   }
119   EXPECT_EQ(dex.NumTypeIds(), dex_cache->NumResolvedTypes());
120   for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
121     mirror::Class* type = dex_cache->GetResolvedType(dex::TypeIndex(i));
122     EXPECT_TRUE(type != nullptr) << "type_idx=" << i
123                               << " " << dex.GetTypeDescriptor(dex.GetTypeId(dex::TypeIndex(i)));
124   }
125   EXPECT_EQ(dex.NumMethodIds(), dex_cache->NumResolvedMethods());
126   auto* cl = Runtime::Current()->GetClassLinker();
127   auto pointer_size = cl->GetImagePointerSize();
128   for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
129     ArtMethod* method = dex_cache->GetResolvedMethod(i, pointer_size);
130     EXPECT_TRUE(method != nullptr) << "method_idx=" << i
131                                 << " " << dex.GetMethodDeclaringClassDescriptor(dex.GetMethodId(i))
132                                 << " " << dex.GetMethodName(dex.GetMethodId(i));
133     EXPECT_TRUE(method->GetEntryPointFromQuickCompiledCode() != nullptr) << "method_idx=" << i
134         << " " << dex.GetMethodDeclaringClassDescriptor(dex.GetMethodId(i)) << " "
135         << dex.GetMethodName(dex.GetMethodId(i));
136   }
137   EXPECT_TRUE(dex_cache->StaticArtFieldSize() == dex_cache->NumResolvedFields()
138       || dex.NumFieldIds() ==  dex_cache->NumResolvedFields());
139   for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
140     ArtField* field = dex_cache->GetResolvedField(i, cl->GetImagePointerSize());
141     EXPECT_TRUE(field != nullptr) << "field_idx=" << i
142                                << " " << dex.GetFieldDeclaringClassDescriptor(dex.GetFieldId(i))
143                                << " " << dex.GetFieldName(dex.GetFieldId(i));
144   }
145 
146   // TODO check Class::IsVerified for all classes
147 
148   // TODO: check that all Method::GetCode() values are non-null
149 }
150 
TEST_F(CompilerDriverTest,AbstractMethodErrorStub)151 TEST_F(CompilerDriverTest, AbstractMethodErrorStub) {
152   jobject class_loader;
153   {
154     ScopedObjectAccess soa(Thread::Current());
155     class_loader = LoadDex("AbstractMethod");
156   }
157   ASSERT_TRUE(class_loader != nullptr);
158   EnsureCompiled(class_loader, "AbstractClass", "foo", "()V", true);
159 
160   // Create a jobj_ of ConcreteClass, NOT AbstractClass.
161   jclass c_class = env_->FindClass("ConcreteClass");
162 
163   jmethodID constructor = env_->GetMethodID(c_class, "<init>", "()V");
164 
165   jobject jobj_ = env_->NewObject(c_class, constructor);
166   ASSERT_TRUE(jobj_ != nullptr);
167 
168   // Force non-virtual call to AbstractClass foo, will throw AbstractMethodError exception.
169   env_->CallNonvirtualVoidMethod(jobj_, class_, mid_);
170 
171   EXPECT_EQ(env_->ExceptionCheck(), JNI_TRUE);
172   jthrowable exception = env_->ExceptionOccurred();
173   env_->ExceptionClear();
174   jclass jlame = env_->FindClass("java/lang/AbstractMethodError");
175   EXPECT_TRUE(env_->IsInstanceOf(exception, jlame));
176   {
177     ScopedObjectAccess soa(Thread::Current());
178     Thread::Current()->ClearException();
179   }
180 }
181 
182 class CompilerDriverMethodsTest : public CompilerDriverTest {
183  protected:
GetCompiledMethods()184   std::unordered_set<std::string>* GetCompiledMethods() OVERRIDE {
185     return new std::unordered_set<std::string>({
186       "byte StaticLeafMethods.identity(byte)",
187       "int StaticLeafMethods.sum(int, int, int)",
188       "double StaticLeafMethods.sum(double, double, double, double)"
189     });
190   }
191 };
192 
TEST_F(CompilerDriverMethodsTest,Selection)193 TEST_F(CompilerDriverMethodsTest, Selection) {
194   Thread* self = Thread::Current();
195   jobject class_loader;
196   {
197     ScopedObjectAccess soa(self);
198     class_loader = LoadDex("StaticLeafMethods");
199   }
200   ASSERT_NE(class_loader, nullptr);
201 
202   // Need to enable dex-file writability. Methods rejected to be compiled will run through the
203   // dex-to-dex compiler.
204   for (const DexFile* dex_file : GetDexFiles(class_loader)) {
205     ASSERT_TRUE(dex_file->EnableWrite());
206   }
207 
208   CompileAll(class_loader);
209 
210   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
211   ScopedObjectAccess soa(self);
212   StackHandleScope<1> hs(self);
213   Handle<mirror::ClassLoader> h_loader(
214       hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
215   mirror::Class* klass = class_linker->FindClass(self, "LStaticLeafMethods;", h_loader);
216   ASSERT_NE(klass, nullptr);
217 
218   std::unique_ptr<std::unordered_set<std::string>> expected(GetCompiledMethods());
219 
220   const auto pointer_size = class_linker->GetImagePointerSize();
221   for (auto& m : klass->GetDirectMethods(pointer_size)) {
222     std::string name = m.PrettyMethod(true);
223     const void* code = m.GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
224     ASSERT_NE(code, nullptr);
225     if (expected->find(name) != expected->end()) {
226       expected->erase(name);
227       EXPECT_FALSE(class_linker->IsQuickToInterpreterBridge(code));
228     } else {
229       EXPECT_TRUE(class_linker->IsQuickToInterpreterBridge(code));
230     }
231   }
232   EXPECT_TRUE(expected->empty());
233 }
234 
235 class CompilerDriverProfileTest : public CompilerDriverTest {
236  protected:
GetProfileCompilationInfo()237   ProfileCompilationInfo* GetProfileCompilationInfo() OVERRIDE {
238     ScopedObjectAccess soa(Thread::Current());
239     std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ProfileTestMultiDex");
240 
241     ProfileCompilationInfo info;
242     for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
243       profile_info_.AddMethodIndex(dex_file->GetLocation(), dex_file->GetLocationChecksum(), 1);
244       profile_info_.AddMethodIndex(dex_file->GetLocation(), dex_file->GetLocationChecksum(), 2);
245     }
246     return &profile_info_;
247   }
248 
GetCompilerFilter() const249   CompilerFilter::Filter GetCompilerFilter() const OVERRIDE {
250     // Use a profile based filter.
251     return CompilerFilter::kSpeedProfile;
252   }
253 
GetExpectedMethodsForClass(const std::string & clazz)254   std::unordered_set<std::string> GetExpectedMethodsForClass(const std::string& clazz) {
255     if (clazz == "Main") {
256       return std::unordered_set<std::string>({
257           "java.lang.String Main.getA()",
258           "java.lang.String Main.getB()"});
259     } else if (clazz == "Second") {
260       return std::unordered_set<std::string>({
261           "java.lang.String Second.getX()",
262           "java.lang.String Second.getY()"});
263     } else {
264       return std::unordered_set<std::string>();
265     }
266   }
267 
CheckCompiledMethods(jobject class_loader,const std::string & clazz,const std::unordered_set<std::string> & expected_methods)268   void CheckCompiledMethods(jobject class_loader,
269                             const std::string& clazz,
270                             const std::unordered_set<std::string>& expected_methods) {
271     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
272     Thread* self = Thread::Current();
273     ScopedObjectAccess soa(self);
274     StackHandleScope<1> hs(self);
275     Handle<mirror::ClassLoader> h_loader(
276         hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
277     mirror::Class* klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
278     ASSERT_NE(klass, nullptr);
279 
280     const auto pointer_size = class_linker->GetImagePointerSize();
281     size_t number_of_compiled_methods = 0;
282     for (auto& m : klass->GetVirtualMethods(pointer_size)) {
283       std::string name = m.PrettyMethod(true);
284       const void* code = m.GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
285       ASSERT_NE(code, nullptr);
286       if (expected_methods.find(name) != expected_methods.end()) {
287         number_of_compiled_methods++;
288         EXPECT_FALSE(class_linker->IsQuickToInterpreterBridge(code));
289       } else {
290         EXPECT_TRUE(class_linker->IsQuickToInterpreterBridge(code));
291       }
292     }
293     EXPECT_EQ(expected_methods.size(), number_of_compiled_methods);
294   }
295 
296  private:
297   ProfileCompilationInfo profile_info_;
298 };
299 
TEST_F(CompilerDriverProfileTest,ProfileGuidedCompilation)300 TEST_F(CompilerDriverProfileTest, ProfileGuidedCompilation) {
301   Thread* self = Thread::Current();
302   jobject class_loader;
303   {
304     ScopedObjectAccess soa(self);
305     class_loader = LoadDex("ProfileTestMultiDex");
306   }
307   ASSERT_NE(class_loader, nullptr);
308 
309   // Need to enable dex-file writability. Methods rejected to be compiled will run through the
310   // dex-to-dex compiler.
311   for (const DexFile* dex_file : GetDexFiles(class_loader)) {
312     ASSERT_TRUE(dex_file->EnableWrite());
313   }
314 
315   CompileAll(class_loader);
316 
317   std::unordered_set<std::string> m = GetExpectedMethodsForClass("Main");
318   std::unordered_set<std::string> s = GetExpectedMethodsForClass("Second");
319   CheckCompiledMethods(class_loader, "LMain;", m);
320   CheckCompiledMethods(class_loader, "LSecond;", s);
321 }
322 
323 // Test that a verify only compiler filter updates the CompiledClass map,
324 // which will be used for OatClass.
325 class CompilerDriverVerifyTest : public CompilerDriverTest {
326  protected:
GetCompilerFilter() const327   CompilerFilter::Filter GetCompilerFilter() const OVERRIDE {
328     return CompilerFilter::kVerify;
329   }
330 
CheckVerifiedClass(jobject class_loader,const std::string & clazz) const331   void CheckVerifiedClass(jobject class_loader, const std::string& clazz) const {
332     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
333     Thread* self = Thread::Current();
334     ScopedObjectAccess soa(self);
335     StackHandleScope<1> hs(self);
336     Handle<mirror::ClassLoader> h_loader(
337         hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
338     mirror::Class* klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
339     ASSERT_NE(klass, nullptr);
340     EXPECT_TRUE(klass->IsVerified());
341 
342     CompiledClass* compiled_class = compiler_driver_->GetCompiledClass(
343         ClassReference(&klass->GetDexFile(), klass->GetDexTypeIndex().index_));
344     ASSERT_NE(compiled_class, nullptr);
345     EXPECT_EQ(compiled_class->GetStatus(), mirror::Class::kStatusVerified);
346   }
347 };
348 
TEST_F(CompilerDriverVerifyTest,VerifyCompilation)349 TEST_F(CompilerDriverVerifyTest, VerifyCompilation) {
350   Thread* self = Thread::Current();
351   jobject class_loader;
352   {
353     ScopedObjectAccess soa(self);
354     class_loader = LoadDex("ProfileTestMultiDex");
355   }
356   ASSERT_NE(class_loader, nullptr);
357 
358   CompileAll(class_loader);
359 
360   CheckVerifiedClass(class_loader, "LMain;");
361   CheckVerifiedClass(class_loader, "LSecond;");
362 }
363 
364 // TODO: need check-cast test (when stub complete & we can throw/catch
365 
366 }  // namespace art
367