1 // Copyright 2019 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_OBJECTS_OSR_OPTIMIZED_CODE_CACHE_H_ 6 #define V8_OBJECTS_OSR_OPTIMIZED_CODE_CACHE_H_ 7 8 #include "src/objects/fixed-array.h" 9 10 // Has to be the last include (doesn't have include guards): 11 #include "src/objects/object-macros.h" 12 13 namespace v8 { 14 namespace internal { 15 16 // This enum is a performance optimization for accessing the OSR code cache - 17 // we can skip cache iteration in many cases unless there are multiple entries 18 // for a particular SharedFunctionInfo. 19 enum OSRCodeCacheStateOfSFI : uint8_t { 20 kNotCached, // Likely state. 21 kCachedOnce, // Unlikely state, one entry. 22 kCachedMultiple, // Very unlikely state, multiple entries. 23 }; 24 25 // TODO(jgruber): There are a few issues with the current implementation: 26 // 27 // - The cache is a flat list, thus any search operation is O(N). This resulted 28 // in optimization attempts, see OSRCodeCacheStateOfSFI. 29 // - We always iterate up to `length` (== capacity). 30 // - We essentially reimplement WeakArrayList, i.e. growth and shrink logic. 31 // - On overflow, new entries always pick slot 0. 32 // 33 // There are a few alternatives: 34 // 35 // 1) we could reuse WeakArrayList logic (but then we'd still have to 36 // implement custom compaction due to our entry tuple structure). 37 // 2) we could reuse CompilationCacheTable (but then we lose weakness and have 38 // to deal with aging). 39 // 3) we could try to base on a weak HashTable variant (EphemeronHashTable?). 40 class V8_EXPORT OSROptimizedCodeCache : public WeakFixedArray { 41 public: 42 DECL_CAST(OSROptimizedCodeCache) 43 44 static Handle<OSROptimizedCodeCache> Empty(Isolate* isolate); 45 46 // Caches the optimized code |code| corresponding to the shared function 47 // |shared| and bailout id |osr_offset| in the OSROptimized code cache. 48 // If the OSR code cache wasn't created before it creates a code cache with 49 // kOSRCodeCacheInitialLength entries. 50 static void Insert(Isolate* isolate, Handle<NativeContext> context, 51 Handle<SharedFunctionInfo> shared, Handle<CodeT> code, 52 BytecodeOffset osr_offset); 53 54 // Returns the code corresponding to the shared function |shared| and 55 // BytecodeOffset |offset| if an entry exists in the cache. Returns an empty 56 // object otherwise. 57 CodeT TryGet(SharedFunctionInfo shared, BytecodeOffset osr_offset, 58 Isolate* isolate); 59 60 std::vector<BytecodeOffset> OsrOffsetsFor(SharedFunctionInfo shared); 61 base::Optional<BytecodeOffset> FirstOsrOffsetFor(SharedFunctionInfo shared); 62 63 // Remove all code objects marked for deoptimization from OSR code cache. 64 void EvictDeoptimizedCode(Isolate* isolate); 65 66 // Reduces the size of the OSR code cache if the number of valid entries are 67 // less than the current capacity of the cache. 68 static void Compact(Isolate* isolate, Handle<NativeContext> context); 69 70 // Sets the OSR optimized code cache to an empty array. 71 static void Clear(Isolate* isolate, NativeContext context); 72 73 enum OSRCodeCacheConstants { 74 kSharedOffset, 75 kCachedCodeOffset, 76 kOsrIdOffset, 77 kEntryLength 78 }; 79 80 static constexpr int kInitialLength = OSRCodeCacheConstants::kEntryLength * 4; 81 static constexpr int kMaxLength = OSRCodeCacheConstants::kEntryLength * 1024; 82 83 // For osr-code-cache-unittest.cc. 84 MaybeObject RawGetForTesting(int index) const; 85 void RawSetForTesting(int index, MaybeObject value); 86 87 private: 88 // Hide raw accessors to avoid terminology confusion. 89 using WeakFixedArray::Get; 90 using WeakFixedArray::Set; 91 92 // Functions that implement heuristics on when to grow / shrink the cache. 93 static int CapacityForLength(int curr_capacity); 94 static bool NeedsTrimming(int num_valid_entries, int curr_capacity); 95 static int GrowOSRCache(Isolate* isolate, 96 Handle<NativeContext> native_context, 97 Handle<OSROptimizedCodeCache>* osr_cache); 98 99 // Helper functions to get individual items from an entry in the cache. 100 CodeT GetCodeFromEntry(int index); 101 SharedFunctionInfo GetSFIFromEntry(int index); 102 BytecodeOffset GetBytecodeOffsetFromEntry(int index); 103 104 inline int FindEntry(SharedFunctionInfo shared, BytecodeOffset osr_offset); 105 inline void ClearEntry(int src, Isolate* isolate); 106 inline void InitializeEntry(int entry, SharedFunctionInfo shared, CodeT code, 107 BytecodeOffset osr_offset); 108 inline void MoveEntry(int src, int dst, Isolate* isolate); 109 110 OBJECT_CONSTRUCTORS(OSROptimizedCodeCache, WeakFixedArray); 111 }; 112 113 } // namespace internal 114 } // namespace v8 115 116 #include "src/objects/object-macros-undef.h" 117 118 #endif // V8_OBJECTS_OSR_OPTIMIZED_CODE_CACHE_H_ 119