1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_INTERPRETER_INTERPRETER_CACHE_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_INTERPRETER_INTERPRETER_CACHE_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <array> 21*795d594fSAndroid Build Coastguard Worker #include <atomic> 22*795d594fSAndroid Build Coastguard Worker 23*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h" 24*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 25*795d594fSAndroid Build Coastguard Worker 26*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker class Thread; 29*795d594fSAndroid Build Coastguard Worker 30*795d594fSAndroid Build Coastguard Worker // Small fast thread-local cache for the interpreter. 31*795d594fSAndroid Build Coastguard Worker // It can hold arbitrary pointer-sized key-value pair. 32*795d594fSAndroid Build Coastguard Worker // The interpretation of the value depends on the key. 33*795d594fSAndroid Build Coastguard Worker // Presence of entry might imply some pre-conditions. 34*795d594fSAndroid Build Coastguard Worker // All operations must be done from the owning thread, 35*795d594fSAndroid Build Coastguard Worker // or at a point when the owning thread is suspended. 36*795d594fSAndroid Build Coastguard Worker // 37*795d594fSAndroid Build Coastguard Worker // The key-value pairs stored in the cache currently are: 38*795d594fSAndroid Build Coastguard Worker // iget/iput: The field offset. The field must be non-volatile. 39*795d594fSAndroid Build Coastguard Worker // sget/sput: The ArtField* pointer. The field must be non-volitile. 40*795d594fSAndroid Build Coastguard Worker // invoke: The ArtMethod* pointer (before vtable indirection, etc). 41*795d594fSAndroid Build Coastguard Worker // 42*795d594fSAndroid Build Coastguard Worker // We ensure consistency of the cache by clearing it 43*795d594fSAndroid Build Coastguard Worker // whenever any dex file is unloaded. 44*795d594fSAndroid Build Coastguard Worker // 45*795d594fSAndroid Build Coastguard Worker // Aligned to 16-bytes to make it easier to get the address of the cache 46*795d594fSAndroid Build Coastguard Worker // from assembly (it ensures that the offset is valid immediate value). 47*795d594fSAndroid Build Coastguard Worker class ALIGNED(16) InterpreterCache { 48*795d594fSAndroid Build Coastguard Worker public: 49*795d594fSAndroid Build Coastguard Worker // Aligned since we load the whole entry in single assembly instruction. 50*795d594fSAndroid Build Coastguard Worker using Entry ALIGNED(2 * sizeof(size_t)) = std::pair<const void*, size_t>; 51*795d594fSAndroid Build Coastguard Worker 52*795d594fSAndroid Build Coastguard Worker // 2x size increase/decrease corresponds to ~0.5% interpreter performance change. 53*795d594fSAndroid Build Coastguard Worker // Value of 256 has around 75% cache hit rate. 54*795d594fSAndroid Build Coastguard Worker static constexpr size_t kSize = 256; 55*795d594fSAndroid Build Coastguard Worker InterpreterCache()56*795d594fSAndroid Build Coastguard Worker InterpreterCache() { 57*795d594fSAndroid Build Coastguard Worker // We can not use the Clear() method since the constructor will not 58*795d594fSAndroid Build Coastguard Worker // be called from the owning thread. 59*795d594fSAndroid Build Coastguard Worker data_.fill(Entry{}); 60*795d594fSAndroid Build Coastguard Worker } 61*795d594fSAndroid Build Coastguard Worker 62*795d594fSAndroid Build Coastguard Worker // Clear the whole cache. It requires the owning thread for DCHECKs. 63*795d594fSAndroid Build Coastguard Worker EXPORT void Clear(Thread* owning_thread); 64*795d594fSAndroid Build Coastguard Worker 65*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE bool Get(Thread* self, const void* key, /* out */ size_t* value); 66*795d594fSAndroid Build Coastguard Worker 67*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void Set(Thread* self, const void* key, size_t value); 68*795d594fSAndroid Build Coastguard Worker GetArray()69*795d594fSAndroid Build Coastguard Worker std::array<Entry, kSize>& GetArray() { 70*795d594fSAndroid Build Coastguard Worker return data_; 71*795d594fSAndroid Build Coastguard Worker } 72*795d594fSAndroid Build Coastguard Worker 73*795d594fSAndroid Build Coastguard Worker private: IndexOf(const void * key)74*795d594fSAndroid Build Coastguard Worker static ALWAYS_INLINE size_t IndexOf(const void* key) { 75*795d594fSAndroid Build Coastguard Worker static_assert(IsPowerOfTwo(kSize), "Size must be power of two"); 76*795d594fSAndroid Build Coastguard Worker size_t index = (reinterpret_cast<uintptr_t>(key) >> 2) & (kSize - 1); 77*795d594fSAndroid Build Coastguard Worker DCHECK_LT(index, kSize); 78*795d594fSAndroid Build Coastguard Worker return index; 79*795d594fSAndroid Build Coastguard Worker } 80*795d594fSAndroid Build Coastguard Worker 81*795d594fSAndroid Build Coastguard Worker std::array<Entry, kSize> data_; 82*795d594fSAndroid Build Coastguard Worker }; 83*795d594fSAndroid Build Coastguard Worker 84*795d594fSAndroid Build Coastguard Worker } // namespace art 85*795d594fSAndroid Build Coastguard Worker 86*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_INTERPRETER_INTERPRETER_CACHE_H_ 87