v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
stub-cache.h
Go to the documentation of this file.
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
9#include "src/objects/name.h"
11
12namespace v8 {
13namespace internal {
14
15// The stub cache is used for megamorphic property accesses.
16// It maps (map, name, type) to property access handlers. The cache does not
17// need explicit invalidation when a prototype chain is modified, since the
18// handlers verify the chain.
19
21 public:
22 Address address() const { return address_; }
23
24 private:
26
28
29 friend class StubCache;
30};
31
33 public:
34 struct Entry {
35 // {key} is a tagged Name pointer, may be cleared by setting to empty
36 // string.
38 // {value} is a tagged heap object reference (weak or strong), equivalent
39 // to a Tagged<MaybeObject>'s payload.
41 // {map} is a tagged Map pointer, may be cleared by setting to Smi::zero().
43 };
44
45 void Initialize();
46 // Access cache for entry hash(name, map).
47 void Set(Tagged<Name> name, Tagged<Map> map, Tagged<MaybeObject> handler);
49 // Clear the lookup table (@ mark compact collection).
50 void Clear();
51
53
55 return SCTableReference(
56 reinterpret_cast<Address>(&first_entry(table)->key));
57 }
58
60 return SCTableReference(
61 reinterpret_cast<Address>(&first_entry(table)->map));
62 }
63
65 return SCTableReference(
66 reinterpret_cast<Address>(&first_entry(table)->value));
67 }
68
70 switch (table) {
71 case StubCache::kPrimary:
72 return StubCache::primary_;
73 case StubCache::kSecondary:
74 return StubCache::secondary_;
75 }
77 }
78
79 Isolate* isolate() { return isolate_; }
80
81 // Setting kCacheIndexShift to Name::HashBits::kShift is convenient because it
82 // causes the bit field inside the hash field to get shifted out implicitly.
83 // Note that kCacheIndexShift must not get too large, because
84 // sizeof(Entry) needs to be a multiple of 1 << kCacheIndexShift (see
85 // the static_assert below, in {entry(...)}).
86 static const int kCacheIndexShift = Name::HashBits::kShift;
87
88 static const int kPrimaryTableBits = 11;
89 static const int kPrimaryTableSize = (1 << kPrimaryTableBits);
90 static const int kSecondaryTableBits = 9;
91 static const int kSecondaryTableSize = (1 << kSecondaryTableBits);
92
93 static int PrimaryOffsetForTesting(Tagged<Name> name, Tagged<Map> map);
94 static int SecondaryOffsetForTesting(Tagged<Name> name, Tagged<Map> map);
95
96 // The constructor is made public only for the purposes of testing.
97 explicit StubCache(Isolate* isolate);
98 StubCache(const StubCache&) = delete;
99 StubCache& operator=(const StubCache&) = delete;
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(Tagged<Name> name, Tagged<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(Tagged<Name> name, Tagged<Map> map);
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::HashBits::kShift 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 // The size of {Entry} must be a multiple of 1 << kCacheIndexShift.
126 static_assert((sizeof(*table) >> kCacheIndexShift) << kCacheIndexShift ==
127 sizeof(*table));
128 const int multiplier = sizeof(*table) >> kCacheIndexShift;
129 return reinterpret_cast<Entry*>(reinterpret_cast<Address>(table) +
130 offset * multiplier);
131 }
132
133 private:
134 Entry primary_[kPrimaryTableSize];
135 Entry secondary_[kSecondaryTableSize];
137
138 friend class Isolate;
139 friend class SCTableReference;
140};
141} // namespace internal
142} // namespace v8
143
144#endif // V8_IC_STUB_CACHE_H_
Isolate * isolate_
SCTableReference(Address address)
Definition stub-cache.h:25
StubCache::Entry * first_entry(StubCache::Table table)
Definition stub-cache.h:69
SCTableReference value_reference(StubCache::Table table)
Definition stub-cache.h:64
StubCache & operator=(const StubCache &)=delete
StubCache(const StubCache &)=delete
SCTableReference key_reference(StubCache::Table table)
Definition stub-cache.h:54
SCTableReference map_reference(StubCache::Table table)
Definition stub-cache.h:59
static Entry * entry(Entry *table, int offset)
Definition stub-cache.h:124
int32_t offset
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
Definition graph.h:1231
#define UNREACHABLE()
Definition logging.h:67
#define V8_EXPORT_PRIVATE
Definition macros.h:460
std::unique_ptr< ValueMirror > key