• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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