• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "dex_cache.h"
18 
19 #include <stdio.h>
20 
21 #include "art_method-inl.h"
22 #include "class_linker.h"
23 #include "common_runtime_test.h"
24 #include "linear_alloc.h"
25 #include "mirror/class_loader-inl.h"
26 #include "mirror/dex_cache-inl.h"
27 #include "handle_scope-inl.h"
28 #include "scoped_thread_state_change-inl.h"
29 
30 namespace art {
31 namespace mirror {
32 
33 class DexCacheTest : public CommonRuntimeTest {};
34 
35 class DexCacheMethodHandlesTest : public DexCacheTest {
36  protected:
SetUpRuntimeOptions(RuntimeOptions * options)37   virtual void SetUpRuntimeOptions(RuntimeOptions* options) OVERRIDE {
38     CommonRuntimeTest::SetUpRuntimeOptions(options);
39   }
40 };
41 
TEST_F(DexCacheTest,Open)42 TEST_F(DexCacheTest, Open) {
43   ScopedObjectAccess soa(Thread::Current());
44   StackHandleScope<1> hs(soa.Self());
45   ASSERT_TRUE(java_lang_dex_file_ != nullptr);
46   Handle<DexCache> dex_cache(
47       hs.NewHandle(class_linker_->AllocAndInitializeDexCache(
48           soa.Self(),
49           *java_lang_dex_file_,
50           Runtime::Current()->GetLinearAlloc())));
51   ASSERT_TRUE(dex_cache != nullptr);
52 
53   EXPECT_TRUE(dex_cache->StaticStringSize() == dex_cache->NumStrings()
54       || java_lang_dex_file_->NumStringIds() == dex_cache->NumStrings());
55   EXPECT_TRUE(dex_cache->StaticTypeSize() == dex_cache->NumResolvedTypes()
56       || java_lang_dex_file_->NumTypeIds() == dex_cache->NumResolvedTypes());
57   EXPECT_EQ(java_lang_dex_file_->NumMethodIds(), dex_cache->NumResolvedMethods());
58   EXPECT_TRUE(dex_cache->StaticArtFieldSize() == dex_cache->NumResolvedFields()
59       || java_lang_dex_file_->NumFieldIds() ==  dex_cache->NumResolvedFields());
60   EXPECT_TRUE(dex_cache->StaticMethodTypeSize() == dex_cache->NumResolvedMethodTypes()
61       || java_lang_dex_file_->NumProtoIds() == dex_cache->NumResolvedMethodTypes());
62 }
63 
TEST_F(DexCacheMethodHandlesTest,Open)64 TEST_F(DexCacheMethodHandlesTest, Open) {
65   ScopedObjectAccess soa(Thread::Current());
66   StackHandleScope<1> hs(soa.Self());
67   ASSERT_TRUE(java_lang_dex_file_ != nullptr);
68   Handle<DexCache> dex_cache(
69       hs.NewHandle(class_linker_->AllocAndInitializeDexCache(
70           soa.Self(),
71           *java_lang_dex_file_,
72           Runtime::Current()->GetLinearAlloc())));
73 
74   EXPECT_TRUE(dex_cache->StaticMethodTypeSize() == dex_cache->NumResolvedMethodTypes()
75       || java_lang_dex_file_->NumProtoIds() == dex_cache->NumResolvedMethodTypes());
76 }
77 
TEST_F(DexCacheTest,LinearAlloc)78 TEST_F(DexCacheTest, LinearAlloc) {
79   ScopedObjectAccess soa(Thread::Current());
80   jobject jclass_loader(LoadDex("Main"));
81   ASSERT_TRUE(jclass_loader != nullptr);
82   StackHandleScope<1> hs(soa.Self());
83   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
84       soa.Decode<mirror::ClassLoader>(jclass_loader)));
85   mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LMain;", class_loader);
86   ASSERT_TRUE(klass != nullptr);
87   LinearAlloc* const linear_alloc = klass->GetClassLoader()->GetAllocator();
88   EXPECT_NE(linear_alloc, runtime_->GetLinearAlloc());
89   EXPECT_TRUE(linear_alloc->Contains(klass->GetDexCache()->GetResolvedMethods()));
90 }
91 
TEST_F(DexCacheTest,TestResolvedFieldAccess)92 TEST_F(DexCacheTest, TestResolvedFieldAccess) {
93   ScopedObjectAccess soa(Thread::Current());
94   jobject jclass_loader(LoadDex("Packages"));
95   ASSERT_TRUE(jclass_loader != nullptr);
96   StackHandleScope<3> hs(soa.Self());
97   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
98       soa.Decode<mirror::ClassLoader>(jclass_loader)));
99   Handle<mirror::Class> klass1 =
100       hs.NewHandle(class_linker_->FindClass(soa.Self(), "Lpackage1/Package1;", class_loader));
101   ASSERT_TRUE(klass1 != nullptr);
102   Handle<mirror::Class> klass2 =
103       hs.NewHandle(class_linker_->FindClass(soa.Self(), "Lpackage2/Package2;", class_loader));
104   ASSERT_TRUE(klass2 != nullptr);
105   EXPECT_EQ(klass1->GetDexCache(), klass2->GetDexCache());
106 
107   EXPECT_NE(klass1->NumStaticFields(), 0u);
108   for (ArtField& field : klass2->GetSFields()) {
109     EXPECT_FALSE((
110         klass1->ResolvedFieldAccessTest</*throw_on_failure*/ false,
111             /*use_referrers_cache*/ false>(klass2.Get(),
112                                            &field,
113                                            field.GetDexFieldIndex(),
114                                            klass1->GetDexCache())));
115   }
116 }
117 
TEST_F(DexCacheMethodHandlesTest,TestResolvedMethodTypes)118 TEST_F(DexCacheMethodHandlesTest, TestResolvedMethodTypes) {
119   ScopedObjectAccess soa(Thread::Current());
120   jobject jclass_loader(LoadDex("MethodTypes"));
121   ASSERT_TRUE(jclass_loader != nullptr);
122 
123   StackHandleScope<5> hs(soa.Self());
124   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
125       soa.Decode<mirror::ClassLoader>(jclass_loader)));
126 
127   Handle<mirror::Class> method_types(
128       hs.NewHandle(class_linker_->FindClass(soa.Self(), "LMethodTypes;", class_loader)));
129   class_linker_->EnsureInitialized(soa.Self(), method_types, true, true);
130 
131   ArtMethod* method1 = method_types->FindVirtualMethod(
132       "method1",
133       "(Ljava/lang/String;)Ljava/lang/String;",
134       kRuntimePointerSize);
135   ArtMethod* method2 = method_types->FindVirtualMethod(
136       "method2",
137       "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
138       kRuntimePointerSize);
139 
140   const DexFile& dex_file = *(method1->GetDexFile());
141   Handle<mirror::DexCache> dex_cache = hs.NewHandle(
142       class_linker_->FindDexCache(Thread::Current(), dex_file));
143 
144   const DexFile::MethodId& method1_id = dex_file.GetMethodId(method1->GetDexMethodIndex());
145   const DexFile::MethodId& method2_id = dex_file.GetMethodId(method2->GetDexMethodIndex());
146 
147   Handle<mirror::MethodType> method1_type = hs.NewHandle(
148       class_linker_->ResolveMethodType(dex_file, method1_id.proto_idx_, dex_cache, class_loader));
149   Handle<mirror::MethodType> method2_type = hs.NewHandle(
150       class_linker_->ResolveMethodType(dex_file, method2_id.proto_idx_, dex_cache, class_loader));
151 
152   EXPECT_EQ(method1_type.Get(), dex_cache->GetResolvedMethodType(method1_id.proto_idx_));
153   EXPECT_EQ(method2_type.Get(), dex_cache->GetResolvedMethodType(method2_id.proto_idx_));
154 
155   // The MethodTypes dex file contains a single interface with two abstract
156   // methods. It must therefore contain precisely two method IDs.
157   ASSERT_EQ(2u, dex_file.NumProtoIds());
158   ASSERT_EQ(dex_file.NumProtoIds(), dex_cache->NumResolvedMethodTypes());
159   MethodTypeDexCacheType* method_types_cache = dex_cache->GetResolvedMethodTypes();
160 
161   for (size_t i = 0; i < dex_file.NumProtoIds(); ++i) {
162     const MethodTypeDexCachePair pair = method_types_cache[i].load(std::memory_order_relaxed);
163     if (pair.index == method1_id.proto_idx_) {
164       ASSERT_EQ(method1_type.Get(), pair.object.Read());
165     } else if (pair.index == method2_id.proto_idx_) {
166       ASSERT_EQ(method2_type.Get(), pair.object.Read());
167     } else {
168       ASSERT_TRUE(false);
169     }
170   }
171 }
172 
173 }  // namespace mirror
174 }  // namespace art
175