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