5 #include "src/ic/stub-cache.h" 7 #include "src/ast/ast.h" 8 #include "src/base/bits.h" 9 #include "src/counters.h" 10 #include "src/heap/heap.h" 11 #include "src/ic/ic-inl.h" 16 StubCache::StubCache(Isolate* isolate) : isolate_(isolate) {
19 DCHECK(!IC::IsHandler(MaybeObject()));
22 void StubCache::Initialize() {
23 DCHECK(base::bits::IsPowerOfTwo(kPrimaryTableSize));
24 DCHECK(base::bits::IsPowerOfTwo(kSecondaryTableSize));
31 int StubCache::PrimaryOffset(Name name, Map map) {
32 STATIC_ASSERT(kCacheIndexShift == Name::kHashShift);
34 DCHECK(name->HasHashCode());
41 uint32_t key = map_low32bits + field;
42 return key & ((kPrimaryTableSize - 1) << kCacheIndexShift);
48 int StubCache::SecondaryOffset(Name name,
int seed) {
51 uint32_t key = (seed - name_low32bits) + kSecondaryMagic;
52 return key & ((kSecondaryTableSize - 1) << kCacheIndexShift);
55 int StubCache::PrimaryOffsetForTesting(Name name, Map map) {
56 return PrimaryOffset(name, map);
59 int StubCache::SecondaryOffsetForTesting(Name name,
int seed) {
60 return SecondaryOffset(name, seed);
66 bool CommonStubCacheChecks(StubCache* stub_cache, Name name, Map map,
67 MaybeObject handler) {
70 DCHECK(!Heap::InNewSpace(name));
71 DCHECK(!Heap::InNewSpace(handler));
72 DCHECK(name->IsUniqueName());
73 DCHECK(name->HasHashCode());
74 if (handler->ptr() != kNullAddress) DCHECK(IC::IsHandler(handler));
81 void StubCache::Set(Name name, Map map, MaybeObject handler) {
82 DCHECK(CommonStubCacheChecks(
this, name, map, handler));
85 int primary_offset = PrimaryOffset(name, map);
86 Entry* primary = entry(primary_, primary_offset);
87 MaybeObject old_handler(primary->value);
91 if (old_handler != MaybeObject::FromObject(
92 isolate_->builtins()->builtin(Builtins::kIllegal)) &&
93 primary->map != kNullAddress) {
94 Map old_map = Map::cast(ObjectPtr(primary->map));
95 int seed = PrimaryOffset(Name::cast(ObjectPtr(primary->key)), old_map);
96 int secondary_offset =
97 SecondaryOffset(Name::cast(ObjectPtr(primary->key)), seed);
98 Entry* secondary = entry(secondary_, secondary_offset);
99 *secondary = *primary;
103 primary->key = name.ptr();
104 primary->value = handler.ptr();
105 primary->map = map.ptr();
106 isolate()->counters()->megamorphic_stub_cache_updates()->Increment();
109 MaybeObject StubCache::Get(Name name, Map map) {
110 DCHECK(CommonStubCacheChecks(
this, name, map, MaybeObject()));
111 int primary_offset = PrimaryOffset(name, map);
112 Entry* primary = entry(primary_, primary_offset);
113 if (primary->key == name.ptr() && primary->map == map.ptr()) {
114 return MaybeObject(primary->value);
116 int secondary_offset = SecondaryOffset(name, primary_offset);
117 Entry* secondary = entry(secondary_, secondary_offset);
118 if (secondary->key == name.ptr() && secondary->map == map.ptr()) {
119 return MaybeObject(secondary->value);
121 return MaybeObject();
124 void StubCache::Clear() {
125 MaybeObject empty = MaybeObject::FromObject(
126 isolate_->builtins()->builtin(Builtins::kIllegal));
127 Name empty_string = ReadOnlyRoots(isolate()).empty_string();
128 for (
int i = 0;
i < kPrimaryTableSize;
i++) {
129 primary_[
i].key = empty_string.ptr();
130 primary_[
i].map = kNullAddress;
131 primary_[
i].value = empty.ptr();
133 for (
int j = 0; j < kSecondaryTableSize; j++) {
134 secondary_[j].key = empty_string.ptr();
135 secondary_[j].map = kNullAddress;
136 secondary_[j].value = empty.ptr();