xref: /aosp_15_r20/art/runtime/interpreter/interpreter_cache.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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