11cb0ef41Sopenharmony_ci// Copyright 2012 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_CODEGEN_COMPILATION_CACHE_H_
61cb0ef41Sopenharmony_ci#define V8_CODEGEN_COMPILATION_CACHE_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/base/hashmap.h"
91cb0ef41Sopenharmony_ci#include "src/objects/compilation-cache-table.h"
101cb0ef41Sopenharmony_ci#include "src/utils/allocation.h"
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cinamespace v8 {
131cb0ef41Sopenharmony_cinamespace internal {
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_citemplate <typename T>
161cb0ef41Sopenharmony_ciclass Handle;
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ciclass RootVisitor;
191cb0ef41Sopenharmony_cistruct ScriptDetails;
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci// The compilation cache consists of several generational sub-caches which uses
221cb0ef41Sopenharmony_ci// this class as a base class. A sub-cache contains a compilation cache tables
231cb0ef41Sopenharmony_ci// for each generation of the sub-cache. Since the same source code string has
241cb0ef41Sopenharmony_ci// different compiled code for scripts and evals, we use separate sub-caches
251cb0ef41Sopenharmony_ci// for different compilation modes, to avoid retrieving the wrong result.
261cb0ef41Sopenharmony_ciclass CompilationSubCache {
271cb0ef41Sopenharmony_ci public:
281cb0ef41Sopenharmony_ci  CompilationSubCache(Isolate* isolate, int generations)
291cb0ef41Sopenharmony_ci      : isolate_(isolate), generations_(generations) {
301cb0ef41Sopenharmony_ci    DCHECK_LE(generations, kMaxGenerations);
311cb0ef41Sopenharmony_ci  }
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci  static constexpr int kFirstGeneration = 0;
341cb0ef41Sopenharmony_ci  static constexpr int kMaxGenerations = 2;
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci  // Get the compilation cache tables for a specific generation.
371cb0ef41Sopenharmony_ci  Handle<CompilationCacheTable> GetTable(int generation);
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  // Accessors for first generation.
401cb0ef41Sopenharmony_ci  Handle<CompilationCacheTable> GetFirstTable() {
411cb0ef41Sopenharmony_ci    return GetTable(kFirstGeneration);
421cb0ef41Sopenharmony_ci  }
431cb0ef41Sopenharmony_ci  void SetFirstTable(Handle<CompilationCacheTable> value) {
441cb0ef41Sopenharmony_ci    DCHECK_LT(kFirstGeneration, generations_);
451cb0ef41Sopenharmony_ci    tables_[kFirstGeneration] = *value;
461cb0ef41Sopenharmony_ci  }
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  // Age the sub-cache by evicting the oldest generation and creating a new
491cb0ef41Sopenharmony_ci  // young generation.
501cb0ef41Sopenharmony_ci  virtual void Age() = 0;
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  // GC support.
531cb0ef41Sopenharmony_ci  void Iterate(RootVisitor* v);
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  // Clear this sub-cache evicting all its content.
561cb0ef41Sopenharmony_ci  void Clear();
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  // Remove given shared function info from sub-cache.
591cb0ef41Sopenharmony_ci  void Remove(Handle<SharedFunctionInfo> function_info);
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  // Number of generations in this sub-cache.
621cb0ef41Sopenharmony_ci  int generations() const { return generations_; }
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci protected:
651cb0ef41Sopenharmony_ci  Isolate* isolate() const { return isolate_; }
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  // Ageing occurs either by removing the oldest generation, or with
681cb0ef41Sopenharmony_ci  // custom logic implemented in CompilationCacheTable::Age.
691cb0ef41Sopenharmony_ci  static void AgeByGeneration(CompilationSubCache* c);
701cb0ef41Sopenharmony_ci  static void AgeCustom(CompilationSubCache* c);
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci private:
731cb0ef41Sopenharmony_ci  Isolate* const isolate_;
741cb0ef41Sopenharmony_ci  const int generations_;
751cb0ef41Sopenharmony_ci  Object tables_[kMaxGenerations];  // One for each generation.
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationSubCache);
781cb0ef41Sopenharmony_ci};
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci// Sub-cache for scripts.
811cb0ef41Sopenharmony_ciclass CompilationCacheScript : public CompilationSubCache {
821cb0ef41Sopenharmony_ci public:
831cb0ef41Sopenharmony_ci  explicit CompilationCacheScript(Isolate* isolate);
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci  MaybeHandle<SharedFunctionInfo> Lookup(Handle<String> source,
861cb0ef41Sopenharmony_ci                                         const ScriptDetails& script_details,
871cb0ef41Sopenharmony_ci                                         LanguageMode language_mode);
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  void Put(Handle<String> source, LanguageMode language_mode,
901cb0ef41Sopenharmony_ci           Handle<SharedFunctionInfo> function_info);
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  void Age() override;
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci private:
951cb0ef41Sopenharmony_ci  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheScript);
961cb0ef41Sopenharmony_ci};
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci// Sub-cache for eval scripts. Two caches for eval are used. One for eval calls
991cb0ef41Sopenharmony_ci// in native contexts and one for eval calls in other contexts. The cache
1001cb0ef41Sopenharmony_ci// considers the following pieces of information when checking for matching
1011cb0ef41Sopenharmony_ci// entries:
1021cb0ef41Sopenharmony_ci// 1. The source string.
1031cb0ef41Sopenharmony_ci// 2. The shared function info of the calling function.
1041cb0ef41Sopenharmony_ci// 3. Whether the source should be compiled as strict code or as sloppy code.
1051cb0ef41Sopenharmony_ci//    Note: Currently there are clients of CompileEval that always compile
1061cb0ef41Sopenharmony_ci//    sloppy code even if the calling function is a strict mode function.
1071cb0ef41Sopenharmony_ci//    More specifically these are the CompileString, DebugEvaluate and
1081cb0ef41Sopenharmony_ci//    DebugEvaluateGlobal runtime functions.
1091cb0ef41Sopenharmony_ci// 4. The start position of the calling scope.
1101cb0ef41Sopenharmony_ciclass CompilationCacheEval : public CompilationSubCache {
1111cb0ef41Sopenharmony_ci public:
1121cb0ef41Sopenharmony_ci  explicit CompilationCacheEval(Isolate* isolate)
1131cb0ef41Sopenharmony_ci      : CompilationSubCache(isolate, 1) {}
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci  InfoCellPair Lookup(Handle<String> source,
1161cb0ef41Sopenharmony_ci                      Handle<SharedFunctionInfo> outer_info,
1171cb0ef41Sopenharmony_ci                      Handle<Context> native_context,
1181cb0ef41Sopenharmony_ci                      LanguageMode language_mode, int position);
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  void Put(Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1211cb0ef41Sopenharmony_ci           Handle<SharedFunctionInfo> function_info,
1221cb0ef41Sopenharmony_ci           Handle<Context> native_context, Handle<FeedbackCell> feedback_cell,
1231cb0ef41Sopenharmony_ci           int position);
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  void Age() override;
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci private:
1281cb0ef41Sopenharmony_ci  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval);
1291cb0ef41Sopenharmony_ci};
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci// Sub-cache for regular expressions.
1321cb0ef41Sopenharmony_ciclass CompilationCacheRegExp : public CompilationSubCache {
1331cb0ef41Sopenharmony_ci public:
1341cb0ef41Sopenharmony_ci  CompilationCacheRegExp(Isolate* isolate, int generations)
1351cb0ef41Sopenharmony_ci      : CompilationSubCache(isolate, generations) {}
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  MaybeHandle<FixedArray> Lookup(Handle<String> source, JSRegExp::Flags flags);
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci  void Put(Handle<String> source, JSRegExp::Flags flags,
1401cb0ef41Sopenharmony_ci           Handle<FixedArray> data);
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  void Age() override;
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci private:
1451cb0ef41Sopenharmony_ci  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheRegExp);
1461cb0ef41Sopenharmony_ci};
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci// The compilation cache keeps shared function infos for compiled
1491cb0ef41Sopenharmony_ci// scripts and evals. The shared function infos are looked up using
1501cb0ef41Sopenharmony_ci// the source string as the key. For regular expressions the
1511cb0ef41Sopenharmony_ci// compilation data is cached.
1521cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE CompilationCache {
1531cb0ef41Sopenharmony_ci public:
1541cb0ef41Sopenharmony_ci  CompilationCache(const CompilationCache&) = delete;
1551cb0ef41Sopenharmony_ci  CompilationCache& operator=(const CompilationCache&) = delete;
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  // Finds the script shared function info for a source
1581cb0ef41Sopenharmony_ci  // string. Returns an empty handle if the cache doesn't contain a
1591cb0ef41Sopenharmony_ci  // script for the given source string with the right origin.
1601cb0ef41Sopenharmony_ci  MaybeHandle<SharedFunctionInfo> LookupScript(
1611cb0ef41Sopenharmony_ci      Handle<String> source, const ScriptDetails& script_details,
1621cb0ef41Sopenharmony_ci      LanguageMode language_mode);
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci  // Finds the shared function info for a source string for eval in a
1651cb0ef41Sopenharmony_ci  // given context.  Returns an empty handle if the cache doesn't
1661cb0ef41Sopenharmony_ci  // contain a script for the given source string.
1671cb0ef41Sopenharmony_ci  InfoCellPair LookupEval(Handle<String> source,
1681cb0ef41Sopenharmony_ci                          Handle<SharedFunctionInfo> outer_info,
1691cb0ef41Sopenharmony_ci                          Handle<Context> context, LanguageMode language_mode,
1701cb0ef41Sopenharmony_ci                          int position);
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci  // Returns the regexp data associated with the given regexp if it
1731cb0ef41Sopenharmony_ci  // is in cache, otherwise an empty handle.
1741cb0ef41Sopenharmony_ci  MaybeHandle<FixedArray> LookupRegExp(Handle<String> source,
1751cb0ef41Sopenharmony_ci                                       JSRegExp::Flags flags);
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  // Associate the (source, kind) pair to the shared function
1781cb0ef41Sopenharmony_ci  // info. This may overwrite an existing mapping.
1791cb0ef41Sopenharmony_ci  void PutScript(Handle<String> source, LanguageMode language_mode,
1801cb0ef41Sopenharmony_ci                 Handle<SharedFunctionInfo> function_info);
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci  // Associate the (source, context->closure()->shared(), kind) triple
1831cb0ef41Sopenharmony_ci  // with the shared function info. This may overwrite an existing mapping.
1841cb0ef41Sopenharmony_ci  void PutEval(Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1851cb0ef41Sopenharmony_ci               Handle<Context> context,
1861cb0ef41Sopenharmony_ci               Handle<SharedFunctionInfo> function_info,
1871cb0ef41Sopenharmony_ci               Handle<FeedbackCell> feedback_cell, int position);
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci  // Associate the (source, flags) pair to the given regexp data.
1901cb0ef41Sopenharmony_ci  // This may overwrite an existing mapping.
1911cb0ef41Sopenharmony_ci  void PutRegExp(Handle<String> source, JSRegExp::Flags flags,
1921cb0ef41Sopenharmony_ci                 Handle<FixedArray> data);
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  // Clear the cache - also used to initialize the cache at startup.
1951cb0ef41Sopenharmony_ci  void Clear();
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  // Remove given shared function info from all caches.
1981cb0ef41Sopenharmony_ci  void Remove(Handle<SharedFunctionInfo> function_info);
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci  // GC support.
2011cb0ef41Sopenharmony_ci  void Iterate(RootVisitor* v);
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci  // Notify the cache that a mark-sweep garbage collection is about to
2041cb0ef41Sopenharmony_ci  // take place. This is used to retire entries from the cache to
2051cb0ef41Sopenharmony_ci  // avoid keeping them alive too long without using them.
2061cb0ef41Sopenharmony_ci  void MarkCompactPrologue();
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci  // Enable/disable compilation cache. Used by debugger to disable compilation
2091cb0ef41Sopenharmony_ci  // cache during debugging so that eval and new scripts are always compiled.
2101cb0ef41Sopenharmony_ci  // TODO(bmeurer, chromium:992277): The RegExp cache cannot be enabled and/or
2111cb0ef41Sopenharmony_ci  // disabled, since it doesn't affect debugging. However ideally the other
2121cb0ef41Sopenharmony_ci  // caches should also be always on, even in the presence of the debugger,
2131cb0ef41Sopenharmony_ci  // but at this point there are too many unclear invariants, and so I decided
2141cb0ef41Sopenharmony_ci  // to just fix the pressing performance problem for RegExp individually first.
2151cb0ef41Sopenharmony_ci  void EnableScriptAndEval();
2161cb0ef41Sopenharmony_ci  void DisableScriptAndEval();
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci private:
2191cb0ef41Sopenharmony_ci  explicit CompilationCache(Isolate* isolate);
2201cb0ef41Sopenharmony_ci  ~CompilationCache() = default;
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  base::HashMap* EagerOptimizingSet();
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci  bool IsEnabledScriptAndEval() const {
2251cb0ef41Sopenharmony_ci    return FLAG_compilation_cache && enabled_script_and_eval_;
2261cb0ef41Sopenharmony_ci  }
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ci  Isolate* isolate() const { return isolate_; }
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci  Isolate* isolate_;
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci  CompilationCacheScript script_;
2331cb0ef41Sopenharmony_ci  CompilationCacheEval eval_global_;
2341cb0ef41Sopenharmony_ci  CompilationCacheEval eval_contextual_;
2351cb0ef41Sopenharmony_ci  CompilationCacheRegExp reg_exp_;
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci  static constexpr int kSubCacheCount = 4;
2381cb0ef41Sopenharmony_ci  CompilationSubCache* subcaches_[kSubCacheCount];
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci  // Current enable state of the compilation cache for scripts and eval.
2411cb0ef41Sopenharmony_ci  bool enabled_script_and_eval_;
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  friend class Isolate;
2441cb0ef41Sopenharmony_ci};
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci}  // namespace internal
2471cb0ef41Sopenharmony_ci}  // namespace v8
2481cb0ef41Sopenharmony_ci
2491cb0ef41Sopenharmony_ci#endif  // V8_CODEGEN_COMPILATION_CACHE_H_
250