V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
stub-cache.h
1 // Copyright 2012 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_IC_STUB_CACHE_H_
6 #define V8_IC_STUB_CACHE_H_
7 
8 #include "src/objects/name.h"
9 
10 namespace v8 {
11 namespace internal {
12 
13 // The stub cache is used for megamorphic property accesses.
14 // It maps (map, name, type) to property access handlers. The cache does not
15 // need explicit invalidation when a prototype chain is modified, since the
16 // handlers verify the chain.
17 
18 
20  public:
21  Address address() const { return address_; }
22 
23  private:
24  explicit SCTableReference(Address address) : address_(address) {}
25 
26  Address address_;
27 
28  friend class StubCache;
29 };
30 
31 
32 class StubCache {
33  public:
34  struct Entry {
35  // The values here have plain Address types because they are read
36  // directly from generated code. As a nice side effect, this keeps
37  // #includes lightweight.
38  Address key;
39  // {value} is a tagged heap object reference (weak or strong), equivalent
40  // to a MaybeObject's payload.
41  Address value;
42  // {map} is a tagged Map pointer, or nullptr.
43  Address map;
44  };
45 
46  void Initialize();
47  // Access cache for entry hash(name, map).
48  void Set(Name name, Map map, MaybeObject handler);
49  MaybeObject Get(Name name, Map map);
50  // Clear the lookup table (@ mark compact collection).
51  void Clear();
52 
53  enum Table { kPrimary, kSecondary };
54 
55  SCTableReference key_reference(StubCache::Table table) {
56  return SCTableReference(
57  reinterpret_cast<Address>(&first_entry(table)->key));
58  }
59 
60  SCTableReference map_reference(StubCache::Table table) {
61  return SCTableReference(
62  reinterpret_cast<Address>(&first_entry(table)->map));
63  }
64 
65  SCTableReference value_reference(StubCache::Table table) {
66  return SCTableReference(
67  reinterpret_cast<Address>(&first_entry(table)->value));
68  }
69 
70  StubCache::Entry* first_entry(StubCache::Table table) {
71  switch (table) {
72  case StubCache::kPrimary:
73  return StubCache::primary_;
74  case StubCache::kSecondary:
75  return StubCache::secondary_;
76  }
77  UNREACHABLE();
78  }
79 
80  Isolate* isolate() { return isolate_; }
81 
82  // Setting the entry size such that the index is shifted by Name::kHashShift
83  // is convenient; shifting down the length field (to extract the hash code)
84  // automatically discards the hash bit field.
85  static const int kCacheIndexShift = Name::kHashShift;
86 
87  static const int kPrimaryTableBits = 11;
88  static const int kPrimaryTableSize = (1 << kPrimaryTableBits);
89  static const int kSecondaryTableBits = 9;
90  static const int kSecondaryTableSize = (1 << kSecondaryTableBits);
91 
92  // Some magic number used in the secondary hash computation.
93  static const int kSecondaryMagic = 0xb16ca6e5;
94 
95  static int PrimaryOffsetForTesting(Name name, Map map);
96  static int SecondaryOffsetForTesting(Name name, int seed);
97 
98  // The constructor is made public only for the purposes of testing.
99  explicit StubCache(Isolate* isolate);
100 
101  private:
102  // The stub cache has a primary and secondary level. The two levels have
103  // different hashing algorithms in order to avoid simultaneous collisions
104  // in both caches. Unlike a probing strategy (quadratic or otherwise) the
105  // update strategy on updates is fairly clear and simple: Any existing entry
106  // in the primary cache is moved to the secondary cache, and secondary cache
107  // entries are overwritten.
108 
109  // Hash algorithm for the primary table. This algorithm is replicated in
110  // assembler for every architecture. Returns an index into the table that
111  // is scaled by 1 << kCacheIndexShift.
112  static int PrimaryOffset(Name name, Map map);
113 
114  // Hash algorithm for the secondary table. This algorithm is replicated in
115  // assembler for every architecture. Returns an index into the table that
116  // is scaled by 1 << kCacheIndexShift.
117  static int SecondaryOffset(Name name, int seed);
118 
119  // Compute the entry for a given offset in exactly the same way as
120  // we do in generated code. We generate an hash code that already
121  // ends in Name::kHashShift 0s. Then we multiply it so it is a multiple
122  // of sizeof(Entry). This makes it easier to avoid making mistakes
123  // in the hashed offset computations.
124  static Entry* entry(Entry* table, int offset) {
125  const int multiplier = sizeof(*table) >> Name::kHashShift;
126  return reinterpret_cast<Entry*>(reinterpret_cast<Address>(table) +
127  offset * multiplier);
128  }
129 
130  private:
131  Entry primary_[kPrimaryTableSize];
132  Entry secondary_[kSecondaryTableSize];
133  Isolate* isolate_;
134 
135  friend class Isolate;
136  friend class SCTableReference;
137 
138  DISALLOW_COPY_AND_ASSIGN(StubCache);
139 };
140 } // namespace internal
141 } // namespace v8
142 
143 #endif // V8_IC_STUB_CACHE_H_
Definition: libplatform.h:13
Definition: v8.h:3740