|  | // Copyright 2017 the V8 project authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef V8_OBJECTS_COMPILATION_CACHE_TABLE_H_ | 
|  | #define V8_OBJECTS_COMPILATION_CACHE_TABLE_H_ | 
|  |  | 
|  | #include "src/objects/feedback-cell.h" | 
|  | #include "src/objects/hash-table.h" | 
|  | #include "src/objects/js-regexp.h" | 
|  | #include "src/objects/shared-function-info.h" | 
|  | #include "src/roots/roots.h" | 
|  |  | 
|  | // Has to be the last include (doesn't have include guards): | 
|  | #include "src/objects/object-macros.h" | 
|  |  | 
|  | namespace v8 { | 
|  | namespace internal { | 
|  |  | 
|  | class CompilationCacheShape : public BaseShape<HashTableKey*> { | 
|  | public: | 
|  | static inline bool IsMatch(HashTableKey* key, Object value) { | 
|  | return key->IsMatch(value); | 
|  | } | 
|  |  | 
|  | static inline uint32_t Hash(ReadOnlyRoots roots, HashTableKey* key) { | 
|  | return key->Hash(); | 
|  | } | 
|  |  | 
|  | static inline uint32_t RegExpHash(String string, Smi flags); | 
|  |  | 
|  | static inline uint32_t StringSharedHash(String source, | 
|  | SharedFunctionInfo shared, | 
|  | LanguageMode language_mode, | 
|  | int position); | 
|  |  | 
|  | static inline uint32_t HashForObject(ReadOnlyRoots roots, Object object); | 
|  |  | 
|  | static const int kPrefixSize = 0; | 
|  | // An 'entry' is essentially a grouped collection of slots. Entries are used | 
|  | // in various ways by the different caches; most store the actual key in the | 
|  | // first entry slot, but it may also be used differently. | 
|  | // Why 3 slots? Because of the eval cache. | 
|  | static const int kEntrySize = 3; | 
|  | static const bool kMatchNeedsHoleCheck = true; | 
|  | }; | 
|  |  | 
|  | class InfoCellPair { | 
|  | public: | 
|  | InfoCellPair() = default; | 
|  | inline InfoCellPair(Isolate* isolate, SharedFunctionInfo shared, | 
|  | FeedbackCell feedback_cell); | 
|  |  | 
|  | FeedbackCell feedback_cell() const { | 
|  | DCHECK(is_compiled_scope_.is_compiled()); | 
|  | return feedback_cell_; | 
|  | } | 
|  | SharedFunctionInfo shared() const { | 
|  | DCHECK(is_compiled_scope_.is_compiled()); | 
|  | return shared_; | 
|  | } | 
|  |  | 
|  | bool has_feedback_cell() const { | 
|  | return !feedback_cell_.is_null() && is_compiled_scope_.is_compiled(); | 
|  | } | 
|  | bool has_shared() const { | 
|  | // Only return true if SFI is compiled - the bytecode could have been | 
|  | // flushed while it's in the compilation cache, and not yet have been | 
|  | // removed form the compilation cache. | 
|  | return !shared_.is_null() && is_compiled_scope_.is_compiled(); | 
|  | } | 
|  |  | 
|  | private: | 
|  | IsCompiledScope is_compiled_scope_; | 
|  | SharedFunctionInfo shared_; | 
|  | FeedbackCell feedback_cell_; | 
|  | }; | 
|  |  | 
|  | EXTERN_DECLARE_HASH_TABLE(CompilationCacheTable, CompilationCacheShape) | 
|  |  | 
|  | class CompilationCacheTable | 
|  | : public HashTable<CompilationCacheTable, CompilationCacheShape> { | 
|  | public: | 
|  | NEVER_READ_ONLY_SPACE | 
|  |  | 
|  | // The 'script' cache contains SharedFunctionInfos. | 
|  | static MaybeHandle<SharedFunctionInfo> LookupScript( | 
|  | Handle<CompilationCacheTable> table, Handle<String> src, | 
|  | Handle<Context> native_context, LanguageMode language_mode); | 
|  | static Handle<CompilationCacheTable> PutScript( | 
|  | Handle<CompilationCacheTable> cache, Handle<String> src, | 
|  | Handle<Context> native_context, LanguageMode language_mode, | 
|  | Handle<SharedFunctionInfo> value); | 
|  |  | 
|  | // Eval code only gets cached after a second probe for the | 
|  | // code object. To do so, on first "put" only a hash identifying the | 
|  | // source is entered into the cache, mapping it to a lifetime count of | 
|  | // the hash. On each call to Age all such lifetimes get reduced, and | 
|  | // removed once they reach zero. If a second put is called while such | 
|  | // a hash is live in the cache, the hash gets replaced by an actual | 
|  | // cache entry. Age also removes stale live entries from the cache. | 
|  | // Such entries are identified by SharedFunctionInfos pointing to | 
|  | // either the recompilation stub, or to "old" code. This avoids memory | 
|  | // leaks due to premature caching of eval strings that are | 
|  | // never needed later. | 
|  | static InfoCellPair LookupEval(Handle<CompilationCacheTable> table, | 
|  | Handle<String> src, | 
|  | Handle<SharedFunctionInfo> shared, | 
|  | Handle<Context> native_context, | 
|  | LanguageMode language_mode, int position); | 
|  | static Handle<CompilationCacheTable> PutEval( | 
|  | Handle<CompilationCacheTable> cache, Handle<String> src, | 
|  | Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value, | 
|  | Handle<Context> native_context, Handle<FeedbackCell> feedback_cell, | 
|  | int position); | 
|  |  | 
|  | // The RegExp cache contains JSRegExp::data fixed arrays. | 
|  | Handle<Object> LookupRegExp(Handle<String> source, JSRegExp::Flags flags); | 
|  | static Handle<CompilationCacheTable> PutRegExp( | 
|  | Isolate* isolate, Handle<CompilationCacheTable> cache, Handle<String> src, | 
|  | JSRegExp::Flags flags, Handle<FixedArray> value); | 
|  |  | 
|  | // The Code cache shares native-context-independent (NCI) code between | 
|  | // contexts. | 
|  | MaybeHandle<Code> LookupCode(Handle<SharedFunctionInfo> key); | 
|  | static Handle<CompilationCacheTable> PutCode( | 
|  | Isolate* isolate, Handle<CompilationCacheTable> cache, | 
|  | Handle<SharedFunctionInfo> key, Handle<Code> value); | 
|  |  | 
|  | void Remove(Object value); | 
|  | void Age(); | 
|  |  | 
|  | DECL_CAST(CompilationCacheTable) | 
|  |  | 
|  | private: | 
|  | void RemoveEntry(int entry_index); | 
|  |  | 
|  | OBJECT_CONSTRUCTORS(CompilationCacheTable, | 
|  | HashTable<CompilationCacheTable, CompilationCacheShape>); | 
|  | }; | 
|  |  | 
|  | }  // namespace internal | 
|  | }  // namespace v8 | 
|  |  | 
|  | #include "src/objects/object-macros-undef.h" | 
|  |  | 
|  | #endif  // V8_OBJECTS_COMPILATION_CACHE_TABLE_H_ |