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_H_
6 #define V8_OBJECTS_COMPILATION_CACHE_H_
7 
8 #include "src/objects/hash-table.h"
9 #include "src/objects/js-regexp.h"
10 
11 // Has to be the last include (doesn't have include guards):
12 #include "src/objects/object-macros.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 class CompilationCacheShape : public BaseShape<HashTableKey*> {
18  public:
IsMatch(HashTableKey * key,Object * value)19   static inline bool IsMatch(HashTableKey* key, Object* value) {
20     return key->IsMatch(value);
21   }
22 
Hash(Isolate * isolate,HashTableKey * key)23   static inline uint32_t Hash(Isolate* isolate, HashTableKey* key) {
24     return key->Hash();
25   }
26 
27   static inline uint32_t RegExpHash(String* string, Smi* flags);
28 
29   static inline uint32_t StringSharedHash(String* source,
30                                           SharedFunctionInfo* shared,
31                                           LanguageMode language_mode,
32                                           int position);
33 
34   static inline uint32_t HashForObject(Isolate* isolate, Object* object);
35 
36   static const int kPrefixSize = 0;
37   static const int kEntrySize = 3;
38 };
39 
40 class InfoCellPair {
41  public:
InfoCellPair()42   InfoCellPair() : shared_(nullptr), feedback_cell_(nullptr) {}
InfoCellPair(SharedFunctionInfo * shared,FeedbackCell * feedback_cell)43   InfoCellPair(SharedFunctionInfo* shared, FeedbackCell* feedback_cell)
44       : shared_(shared), feedback_cell_(feedback_cell) {}
45 
feedback_cell()46   FeedbackCell* feedback_cell() const { return feedback_cell_; }
shared()47   SharedFunctionInfo* shared() const { return shared_; }
48 
has_feedback_cell()49   bool has_feedback_cell() const { return feedback_cell_ != nullptr; }
has_shared()50   bool has_shared() const { return shared_ != nullptr; }
51 
52  private:
53   SharedFunctionInfo* shared_;
54   FeedbackCell* feedback_cell_;
55 };
56 
57 // This cache is used in two different variants. For regexp caching, it simply
58 // maps identifying info of the regexp to the cached regexp object. Scripts and
59 // eval code only gets cached after a second probe for the code object. To do
60 // so, on first "put" only a hash identifying the source is entered into the
61 // cache, mapping it to a lifetime count of the hash. On each call to Age all
62 // such lifetimes get reduced, and removed once they reach zero. If a second put
63 // is called while such a hash is live in the cache, the hash gets replaced by
64 // an actual cache entry. Age also removes stale live entries from the cache.
65 // Such entries are identified by SharedFunctionInfos pointing to either the
66 // recompilation stub, or to "old" code. This avoids memory leaks due to
67 // premature caching of scripts and eval strings that are never needed later.
68 class CompilationCacheTable
69     : public HashTable<CompilationCacheTable, CompilationCacheShape>,
70       public NeverReadOnlySpaceObject {
71  public:
72   using NeverReadOnlySpaceObject::GetHeap;
73   using NeverReadOnlySpaceObject::GetIsolate;
74 
75   // Find cached value for a string key, otherwise return null.
76   Handle<Object> Lookup(Handle<String> src, Handle<SharedFunctionInfo> shared,
77                         LanguageMode language_mode);
78   MaybeHandle<SharedFunctionInfo> LookupScript(Handle<String> src,
79                                                Handle<Context> native_context,
80                                                LanguageMode language_mode);
81   InfoCellPair LookupEval(Handle<String> src, Handle<SharedFunctionInfo> shared,
82                           Handle<Context> native_context,
83                           LanguageMode language_mode, int position);
84   Handle<Object> LookupRegExp(Handle<String> source, JSRegExp::Flags flags);
85   static Handle<CompilationCacheTable> Put(Handle<CompilationCacheTable> cache,
86                                            Handle<String> src,
87                                            Handle<SharedFunctionInfo> shared,
88                                            LanguageMode language_mode,
89                                            Handle<Object> value);
90   static Handle<CompilationCacheTable> PutScript(
91       Handle<CompilationCacheTable> cache, Handle<String> src,
92       Handle<Context> native_context, LanguageMode language_mode,
93       Handle<SharedFunctionInfo> value);
94   static Handle<CompilationCacheTable> PutEval(
95       Handle<CompilationCacheTable> cache, Handle<String> src,
96       Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
97       Handle<Context> native_context, Handle<FeedbackCell> feedback_cell,
98       int position);
99   static Handle<CompilationCacheTable> PutRegExp(
100       Isolate* isolate, Handle<CompilationCacheTable> cache, Handle<String> src,
101       JSRegExp::Flags flags, Handle<FixedArray> value);
102   void Remove(Object* value);
103   void Age();
104   static const int kHashGenerations = 10;
105 
106   DECL_CAST(CompilationCacheTable)
107 
108  private:
109   DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable);
110 };
111 
112 }  // namespace internal
113 }  // namespace v8
114 
115 #include "src/objects/object-macros-undef.h"
116 
117 #endif  // V8_OBJECTS_COMPILATION_CACHE_H_
118