• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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_COMPILATION_CACHE_TABLE_H_
6 #define V8_OBJECTS_COMPILATION_CACHE_TABLE_H_
7 
8 #include "src/objects/feedback-cell.h"
9 #include "src/objects/hash-table.h"
10 #include "src/objects/js-regexp.h"
11 #include "src/objects/shared-function-info.h"
12 #include "src/roots/roots.h"
13 
14 // Has to be the last include (doesn't have include guards):
15 #include "src/objects/object-macros.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 class CompilationCacheShape : public BaseShape<HashTableKey*> {
21  public:
IsMatch(HashTableKey * key,Object value)22   static inline bool IsMatch(HashTableKey* key, Object value) {
23     return key->IsMatch(value);
24   }
25 
Hash(ReadOnlyRoots roots,HashTableKey * key)26   static inline uint32_t Hash(ReadOnlyRoots roots, HashTableKey* key) {
27     return key->Hash();
28   }
29 
30   static inline uint32_t RegExpHash(String string, Smi flags);
31 
32   static inline uint32_t StringSharedHash(String source,
33                                           SharedFunctionInfo shared,
34                                           LanguageMode language_mode,
35                                           int position);
36 
37   static inline uint32_t StringSharedHash(String source,
38                                           LanguageMode language_mode);
39 
40   static inline uint32_t HashForObject(ReadOnlyRoots roots, Object object);
41 
42   static const int kPrefixSize = 0;
43   // An 'entry' is essentially a grouped collection of slots. Entries are used
44   // in various ways by the different caches; most store the actual key in the
45   // first entry slot, but it may also be used differently.
46   // Why 3 slots? Because of the eval cache.
47   static const int kEntrySize = 3;
48   static const bool kMatchNeedsHoleCheck = true;
49 };
50 
51 class InfoCellPair {
52  public:
53   InfoCellPair() = default;
54   inline InfoCellPair(Isolate* isolate, SharedFunctionInfo shared,
55                       FeedbackCell feedback_cell);
56 
feedback_cell()57   FeedbackCell feedback_cell() const {
58     DCHECK(is_compiled_scope_.is_compiled());
59     return feedback_cell_;
60   }
shared()61   SharedFunctionInfo shared() const {
62     DCHECK(is_compiled_scope_.is_compiled());
63     return shared_;
64   }
65 
has_feedback_cell()66   bool has_feedback_cell() const {
67     return !feedback_cell_.is_null() && is_compiled_scope_.is_compiled();
68   }
has_shared()69   bool has_shared() const {
70     // Only return true if SFI is compiled - the bytecode could have been
71     // flushed while it's in the compilation cache, and not yet have been
72     // removed form the compilation cache.
73     return !shared_.is_null() && is_compiled_scope_.is_compiled();
74   }
75 
76  private:
77   IsCompiledScope is_compiled_scope_;
78   SharedFunctionInfo shared_;
79   FeedbackCell feedback_cell_;
80 };
81 
EXTERN_DECLARE_HASH_TABLE(CompilationCacheTable,CompilationCacheShape)82 EXTERN_DECLARE_HASH_TABLE(CompilationCacheTable, CompilationCacheShape)
83 
84 class CompilationCacheTable
85     : public HashTable<CompilationCacheTable, CompilationCacheShape> {
86  public:
87   NEVER_READ_ONLY_SPACE
88 
89   // The 'script' cache contains SharedFunctionInfos.
90   static MaybeHandle<SharedFunctionInfo> LookupScript(
91       Handle<CompilationCacheTable> table, Handle<String> src,
92       LanguageMode language_mode, Isolate* isolate);
93   static Handle<CompilationCacheTable> PutScript(
94       Handle<CompilationCacheTable> cache, Handle<String> src,
95       LanguageMode language_mode, Handle<SharedFunctionInfo> value,
96       Isolate* isolate);
97 
98   // Eval code only gets cached after a second probe for the
99   // code object. To do so, on first "put" only a hash identifying the
100   // source is entered into the cache, mapping it to a lifetime count of
101   // the hash. On each call to Age all such lifetimes get reduced, and
102   // removed once they reach zero. If a second put is called while such
103   // a hash is live in the cache, the hash gets replaced by an actual
104   // cache entry. Age also removes stale live entries from the cache.
105   // Such entries are identified by SharedFunctionInfos pointing to
106   // either the recompilation stub, or to "old" code. This avoids memory
107   // leaks due to premature caching of eval strings that are
108   // never needed later.
109   static InfoCellPair LookupEval(Handle<CompilationCacheTable> table,
110                                  Handle<String> src,
111                                  Handle<SharedFunctionInfo> shared,
112                                  Handle<Context> native_context,
113                                  LanguageMode language_mode, int position);
114   static Handle<CompilationCacheTable> PutEval(
115       Handle<CompilationCacheTable> cache, Handle<String> src,
116       Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
117       Handle<Context> native_context, Handle<FeedbackCell> feedback_cell,
118       int position);
119 
120   // The RegExp cache contains JSRegExp::data fixed arrays.
121   Handle<Object> LookupRegExp(Handle<String> source, JSRegExp::Flags flags);
122   static Handle<CompilationCacheTable> PutRegExp(
123       Isolate* isolate, Handle<CompilationCacheTable> cache, Handle<String> src,
124       JSRegExp::Flags flags, Handle<FixedArray> value);
125 
126   void Remove(Object value);
127   void Age(Isolate* isolate);
128 
129   DECL_CAST(CompilationCacheTable)
130 
131  private:
132   void RemoveEntry(int entry_index);
133 
134   OBJECT_CONSTRUCTORS(CompilationCacheTable,
135                       HashTable<CompilationCacheTable, CompilationCacheShape>);
136 };
137 
138 }  // namespace internal
139 }  // namespace v8
140 
141 #include "src/objects/object-macros-undef.h"
142 
143 #endif  // V8_OBJECTS_COMPILATION_CACHE_TABLE_H_
144