11cb0ef41Sopenharmony_ci// Copyright 2019 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_OBJECTS_OSR_OPTIMIZED_CODE_CACHE_H_
61cb0ef41Sopenharmony_ci#define V8_OBJECTS_OSR_OPTIMIZED_CODE_CACHE_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/objects/fixed-array.h"
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci// Has to be the last include (doesn't have include guards):
111cb0ef41Sopenharmony_ci#include "src/objects/object-macros.h"
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cinamespace v8 {
141cb0ef41Sopenharmony_cinamespace internal {
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci// This enum is a performance optimization for accessing the OSR code cache -
171cb0ef41Sopenharmony_ci// we can skip cache iteration in many cases unless there are multiple entries
181cb0ef41Sopenharmony_ci// for a particular SharedFunctionInfo.
191cb0ef41Sopenharmony_cienum OSRCodeCacheStateOfSFI : uint8_t {
201cb0ef41Sopenharmony_ci  kNotCached,       // Likely state.
211cb0ef41Sopenharmony_ci  kCachedOnce,      // Unlikely state, one entry.
221cb0ef41Sopenharmony_ci  kCachedMultiple,  // Very unlikely state, multiple entries.
231cb0ef41Sopenharmony_ci};
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci// TODO(jgruber): There are a few issues with the current implementation:
261cb0ef41Sopenharmony_ci//
271cb0ef41Sopenharmony_ci// - The cache is a flat list, thus any search operation is O(N). This resulted
281cb0ef41Sopenharmony_ci//   in optimization attempts, see OSRCodeCacheStateOfSFI.
291cb0ef41Sopenharmony_ci// - We always iterate up to `length` (== capacity).
301cb0ef41Sopenharmony_ci// - We essentially reimplement WeakArrayList, i.e. growth and shrink logic.
311cb0ef41Sopenharmony_ci// - On overflow, new entries always pick slot 0.
321cb0ef41Sopenharmony_ci//
331cb0ef41Sopenharmony_ci// There are a few alternatives:
341cb0ef41Sopenharmony_ci//
351cb0ef41Sopenharmony_ci// 1) we could reuse WeakArrayList logic (but then we'd still have to
361cb0ef41Sopenharmony_ci//    implement custom compaction due to our entry tuple structure).
371cb0ef41Sopenharmony_ci// 2) we could reuse CompilationCacheTable (but then we lose weakness and have
381cb0ef41Sopenharmony_ci//    to deal with aging).
391cb0ef41Sopenharmony_ci// 3) we could try to base on a weak HashTable variant (EphemeronHashTable?).
401cb0ef41Sopenharmony_ciclass V8_EXPORT OSROptimizedCodeCache : public WeakFixedArray {
411cb0ef41Sopenharmony_ci public:
421cb0ef41Sopenharmony_ci  DECL_CAST(OSROptimizedCodeCache)
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci  static Handle<OSROptimizedCodeCache> Empty(Isolate* isolate);
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci  // Caches the optimized code |code| corresponding to the shared function
471cb0ef41Sopenharmony_ci  // |shared| and bailout id |osr_offset| in the OSROptimized code cache.
481cb0ef41Sopenharmony_ci  // If the OSR code cache wasn't created before it creates a code cache with
491cb0ef41Sopenharmony_ci  // kOSRCodeCacheInitialLength entries.
501cb0ef41Sopenharmony_ci  static void Insert(Isolate* isolate, Handle<NativeContext> context,
511cb0ef41Sopenharmony_ci                     Handle<SharedFunctionInfo> shared, Handle<CodeT> code,
521cb0ef41Sopenharmony_ci                     BytecodeOffset osr_offset);
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  // Returns the code corresponding to the shared function |shared| and
551cb0ef41Sopenharmony_ci  // BytecodeOffset |offset| if an entry exists in the cache. Returns an empty
561cb0ef41Sopenharmony_ci  // object otherwise.
571cb0ef41Sopenharmony_ci  CodeT TryGet(SharedFunctionInfo shared, BytecodeOffset osr_offset,
581cb0ef41Sopenharmony_ci               Isolate* isolate);
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  std::vector<BytecodeOffset> OsrOffsetsFor(SharedFunctionInfo shared);
611cb0ef41Sopenharmony_ci  base::Optional<BytecodeOffset> FirstOsrOffsetFor(SharedFunctionInfo shared);
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci  // Remove all code objects marked for deoptimization from OSR code cache.
641cb0ef41Sopenharmony_ci  void EvictDeoptimizedCode(Isolate* isolate);
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  // Reduces the size of the OSR code cache if the number of valid entries are
671cb0ef41Sopenharmony_ci  // less than the current capacity of the cache.
681cb0ef41Sopenharmony_ci  static void Compact(Isolate* isolate, Handle<NativeContext> context);
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  // Sets the OSR optimized code cache to an empty array.
711cb0ef41Sopenharmony_ci  static void Clear(Isolate* isolate, NativeContext context);
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  enum OSRCodeCacheConstants {
741cb0ef41Sopenharmony_ci    kSharedOffset,
751cb0ef41Sopenharmony_ci    kCachedCodeOffset,
761cb0ef41Sopenharmony_ci    kOsrIdOffset,
771cb0ef41Sopenharmony_ci    kEntryLength
781cb0ef41Sopenharmony_ci  };
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  static constexpr int kInitialLength = OSRCodeCacheConstants::kEntryLength * 4;
811cb0ef41Sopenharmony_ci  static constexpr int kMaxLength = OSRCodeCacheConstants::kEntryLength * 1024;
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  // For osr-code-cache-unittest.cc.
841cb0ef41Sopenharmony_ci  MaybeObject RawGetForTesting(int index) const;
851cb0ef41Sopenharmony_ci  void RawSetForTesting(int index, MaybeObject value);
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci private:
881cb0ef41Sopenharmony_ci  // Hide raw accessors to avoid terminology confusion.
891cb0ef41Sopenharmony_ci  using WeakFixedArray::Get;
901cb0ef41Sopenharmony_ci  using WeakFixedArray::Set;
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  // Functions that implement heuristics on when to grow / shrink the cache.
931cb0ef41Sopenharmony_ci  static int CapacityForLength(int curr_capacity);
941cb0ef41Sopenharmony_ci  static bool NeedsTrimming(int num_valid_entries, int curr_capacity);
951cb0ef41Sopenharmony_ci  static int GrowOSRCache(Isolate* isolate,
961cb0ef41Sopenharmony_ci                          Handle<NativeContext> native_context,
971cb0ef41Sopenharmony_ci                          Handle<OSROptimizedCodeCache>* osr_cache);
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  // Helper functions to get individual items from an entry in the cache.
1001cb0ef41Sopenharmony_ci  CodeT GetCodeFromEntry(int index);
1011cb0ef41Sopenharmony_ci  SharedFunctionInfo GetSFIFromEntry(int index);
1021cb0ef41Sopenharmony_ci  BytecodeOffset GetBytecodeOffsetFromEntry(int index);
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  inline int FindEntry(SharedFunctionInfo shared, BytecodeOffset osr_offset);
1051cb0ef41Sopenharmony_ci  inline void ClearEntry(int src, Isolate* isolate);
1061cb0ef41Sopenharmony_ci  inline void InitializeEntry(int entry, SharedFunctionInfo shared, CodeT code,
1071cb0ef41Sopenharmony_ci                              BytecodeOffset osr_offset);
1081cb0ef41Sopenharmony_ci  inline void MoveEntry(int src, int dst, Isolate* isolate);
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  OBJECT_CONSTRUCTORS(OSROptimizedCodeCache, WeakFixedArray);
1111cb0ef41Sopenharmony_ci};
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci}  // namespace internal
1141cb0ef41Sopenharmony_ci}  // namespace v8
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci#include "src/objects/object-macros-undef.h"
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci#endif  // V8_OBJECTS_OSR_OPTIMIZED_CODE_CACHE_H_
119