1 /* 2 * Copyright (C) 2015 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 "common_runtime_test.h" 18 19 #include "art_method-inl.h" 20 #include "class_linker.h" 21 #include "jit_code_cache.h" 22 #include "scoped_thread_state_change.h" 23 #include "thread-inl.h" 24 25 namespace art { 26 namespace jit { 27 28 class JitCodeCacheTest : public CommonRuntimeTest { 29 public: 30 }; 31 32 TEST_F(JitCodeCacheTest, TestCoverage) { 33 std::string error_msg; 34 constexpr size_t kSize = 1 * MB; 35 std::unique_ptr<JitCodeCache> code_cache( 36 JitCodeCache::Create(kSize, &error_msg)); 37 ASSERT_TRUE(code_cache.get() != nullptr) << error_msg; 38 ASSERT_TRUE(code_cache->CodeCachePtr() != nullptr); 39 ASSERT_EQ(code_cache->CodeCacheSize(), 0u); 40 ASSERT_GT(code_cache->CodeCacheRemain(), 0u); 41 ASSERT_TRUE(code_cache->DataCachePtr() != nullptr); 42 ASSERT_EQ(code_cache->DataCacheSize(), 0u); 43 ASSERT_GT(code_cache->DataCacheRemain(), 0u); 44 ASSERT_EQ(code_cache->CodeCacheRemain() + code_cache->DataCacheRemain(), kSize); 45 ASSERT_EQ(code_cache->NumMethods(), 0u); 46 ScopedObjectAccess soa(Thread::Current()); 47 StackHandleScope<1> hs(soa.Self()); 48 uint8_t* const reserved_code = code_cache->ReserveCode(soa.Self(), 4 * KB); 49 ASSERT_TRUE(reserved_code != nullptr); 50 ASSERT_TRUE(code_cache->ContainsCodePtr(reserved_code)); 51 ASSERT_EQ(code_cache->NumMethods(), 1u); 52 ClassLinker* const cl = Runtime::Current()->GetClassLinker(); 53 auto* method = cl->AllocArtMethodArray(soa.Self(), 1); 54 ASSERT_FALSE(code_cache->ContainsMethod(method)); 55 method->SetEntryPointFromQuickCompiledCode(reserved_code); 56 ASSERT_TRUE(code_cache->ContainsMethod(method)); 57 ASSERT_EQ(code_cache->GetCodeFor(method), reserved_code); 58 // Save the code and then change it. 59 code_cache->SaveCompiledCode(method, reserved_code); 60 method->SetEntryPointFromQuickCompiledCode(nullptr); 61 ASSERT_EQ(code_cache->GetCodeFor(method), reserved_code); 62 const uint8_t data_arr[] = {1, 2, 3, 4, 5}; 63 uint8_t* data_ptr = code_cache->AddDataArray(soa.Self(), data_arr, data_arr + sizeof(data_arr)); 64 ASSERT_TRUE(data_ptr != nullptr); 65 ASSERT_EQ(memcmp(data_ptr, data_arr, sizeof(data_arr)), 0); 66 } 67 68 TEST_F(JitCodeCacheTest, TestOverflow) { 69 std::string error_msg; 70 constexpr size_t kSize = 1 * MB; 71 std::unique_ptr<JitCodeCache> code_cache( 72 JitCodeCache::Create(kSize, &error_msg)); 73 ASSERT_TRUE(code_cache.get() != nullptr) << error_msg; 74 ASSERT_TRUE(code_cache->CodeCachePtr() != nullptr); 75 size_t code_bytes = 0; 76 size_t data_bytes = 0; 77 constexpr size_t kCodeArrSize = 4 * KB; 78 constexpr size_t kDataArrSize = 4 * KB; 79 uint8_t data_arr[kDataArrSize]; 80 std::fill_n(data_arr, arraysize(data_arr), 53); 81 // Add code and data until we are full. 82 uint8_t* code_ptr = nullptr; 83 uint8_t* data_ptr = nullptr; 84 do { 85 code_ptr = code_cache->ReserveCode(Thread::Current(), kCodeArrSize); 86 data_ptr = code_cache->AddDataArray(Thread::Current(), data_arr, data_arr + kDataArrSize); 87 if (code_ptr != nullptr) { 88 code_bytes += kCodeArrSize; 89 } 90 if (data_ptr != nullptr) { 91 data_bytes += kDataArrSize; 92 } 93 } while (code_ptr != nullptr || data_ptr != nullptr); 94 // Make sure we added a reasonable amount 95 CHECK_GT(code_bytes, 0u); 96 CHECK_LE(code_bytes, kSize); 97 CHECK_GT(data_bytes, 0u); 98 CHECK_LE(data_bytes, kSize); 99 CHECK_GE(code_bytes + data_bytes, kSize * 4 / 5); 100 } 101 102 } // namespace jit 103 } // namespace art 104