Commit 5f4de3e0 authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[in-place weak refs] Replace WeakCells in StubCache.

Since the StubCache it's cleared at the end of the GC, it doesn't
matter if it contains weak or strong pointers.

BUG=v8:7308

Change-Id: Ib141e3d411523c67ccb8f8979845a88488d6e4ee
Reviewed-on: https://chromium-review.googlesource.com/1064053
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53311}
parent c6efd592
......@@ -2088,7 +2088,7 @@ void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map,
if (use_stub_cache == kUseStubCache) {
BIND(&stub_cache);
Comment("stub cache probe for fast property load");
VARIABLE(var_handler, MachineRepresentation::kTagged);
TVARIABLE(MaybeObject, var_handler);
Label found_handler(this, &var_handler), stub_cache_miss(this);
TryProbeStubCache(isolate()->load_stub_cache(), receiver, p->name,
&found_handler, &var_handler, &stub_cache_miss);
......@@ -2237,12 +2237,10 @@ Node* AccessorAssembler::StubCacheSecondaryOffset(Node* name, Node* seed) {
return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask)));
}
void AccessorAssembler::TryProbeStubCacheTable(StubCache* stub_cache,
StubCacheTable table_id,
Node* entry_offset, Node* name,
Node* map, Label* if_handler,
Variable* var_handler,
Label* if_miss) {
void AccessorAssembler::TryProbeStubCacheTable(
StubCache* stub_cache, StubCacheTable table_id, Node* entry_offset,
Node* name, Node* map, Label* if_handler,
TVariable<MaybeObject>* var_handler, Label* if_miss) {
StubCache::Table table = static_cast<StubCache::Table>(table_id);
#ifdef DEBUG
if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
......@@ -2274,17 +2272,18 @@ void AccessorAssembler::TryProbeStubCacheTable(StubCache* stub_cache,
DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() -
stub_cache->key_reference(table).address());
Node* handler = Load(MachineType::TaggedPointer(), key_base,
IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize)));
TNode<MaybeObject> handler = ReinterpretCast<MaybeObject>(
Load(MachineType::TaggedPointer(), key_base,
IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize))));
// We found the handler.
var_handler->Bind(handler);
*var_handler = handler;
Goto(if_handler);
}
void AccessorAssembler::TryProbeStubCache(StubCache* stub_cache, Node* receiver,
Node* name, Label* if_handler,
Variable* var_handler,
TVariable<MaybeObject>* var_handler,
Label* if_miss) {
Label try_secondary(this), miss(this);
......@@ -2421,7 +2420,7 @@ void AccessorAssembler::LoadIC(const LoadICParameters* p) {
void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p,
Node* receiver_map,
TNode<HeapObject> feedback,
Variable* var_handler,
TVariable<MaybeObject>* var_handler,
Label* if_handler, Label* miss,
ExitPoint* exit_point) {
Label try_uninitialized(this, Label::kDeferred);
......@@ -2842,26 +2841,7 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) {
&try_uninitialized);
TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name,
&if_handler_from_stub_cache, &var_handler, &miss);
}
BIND(&if_handler_from_stub_cache);
{
// If the stub cache contains a WeakCell pointing to a Map, convert it to an
// in-place weak reference. TODO(marja): This well get simplified once more
// WeakCells are converted into in-place weak references.
Comment("StoreIC_if_handler_from_stub_cache");
GotoIf(TaggedIsSmi(var_handler.value()), &if_handler);
TNode<HeapObject> handler = CAST(var_handler.value());
GotoIfNot(IsWeakCell(handler), &if_handler);
TNode<HeapObject> value = CAST(LoadWeakCellValue(CAST(handler), &miss));
TNode<Map> value_map = LoadMap(value);
GotoIfNot(Word32Or(IsMetaMap(value_map), IsPropertyCellMap(value_map)),
&if_handler);
TNode<MaybeObject> weak_handler = MakeWeak(value);
HandleStoreICHandlerCase(p, weak_handler, &miss, ICMode::kNonGlobalIC);
&if_handler, &var_handler, &miss);
}
BIND(&try_uninitialized);
{
......@@ -3170,7 +3150,7 @@ void AccessorAssembler::GenerateLoadIC_Noninlined() {
Node* context = Parameter(Descriptor::kContext);
ExitPoint direct_exit(this);
VARIABLE(var_handler, MachineRepresentation::kTagged);
TVARIABLE(MaybeObject, var_handler);
Label if_handler(this, &var_handler), miss(this, Label::kDeferred);
Node* receiver_map = LoadReceiverMap(receiver);
......
......@@ -49,7 +49,7 @@ class AccessorAssembler : public CodeStubAssembler {
void GenerateStoreInArrayLiteralIC();
void TryProbeStubCache(StubCache* stub_cache, Node* receiver, Node* name,
Label* if_handler, Variable* var_handler,
Label* if_handler, TVariable<MaybeObject>* var_handler,
Label* if_miss);
Node* StubCachePrimaryOffsetForTesting(Node* name, Node* map) {
......@@ -133,8 +133,9 @@ class AccessorAssembler : public CodeStubAssembler {
// logic not inlined into Ignition bytecode handlers.
void LoadIC(const LoadICParameters* p);
void LoadIC_Noninlined(const LoadICParameters* p, Node* receiver_map,
TNode<HeapObject> feedback, Variable* var_handler,
Label* if_handler, Label* miss, ExitPoint* exit_point);
TNode<HeapObject> feedback,
TVariable<MaybeObject>* var_handler, Label* if_handler,
Label* miss, ExitPoint* exit_point);
Node* LoadDescriptorValue(Node* map, Node* descriptor);
......@@ -286,7 +287,8 @@ class AccessorAssembler : public CodeStubAssembler {
void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id,
Node* entry_offset, Node* name, Node* map,
Label* if_handler, Variable* var_handler,
Label* if_handler,
TVariable<MaybeObject>* var_handler,
Label* if_miss);
};
......
......@@ -39,17 +39,13 @@ Address IC::raw_constant_pool() const {
}
}
bool IC::IsHandler(MaybeObject* object, bool from_stub_cache) {
bool IC::IsHandler(MaybeObject* object) {
HeapObject* heap_object;
return (object->IsSmi() && (object != nullptr)) ||
(object->ToWeakHeapObject(&heap_object) &&
(heap_object->IsMap() || heap_object->IsPropertyCell())) ||
(object->ToStrongHeapObject(&heap_object) &&
(heap_object->IsDataHandler() ||
(from_stub_cache && heap_object->IsWeakCell() &&
(WeakCell::cast(heap_object)->cleared() ||
WeakCell::cast(heap_object)->value()->IsMap() ||
WeakCell::cast(heap_object)->value()->IsPropertyCell())) ||
heap_object->IsCode()));
}
......
......@@ -720,21 +720,7 @@ StubCache* IC::stub_cache() {
void IC::UpdateMegamorphicCache(Handle<Map> map, Handle<Name> name,
const MaybeObjectHandle& handler) {
HeapObject* heap_object;
if (handler->ToWeakHeapObject(&heap_object)) {
// TODO(marja): remove this conversion once megamorphic stub cache supports
// weak handlers.
Handle<Object> weak_cell;
if (heap_object->IsMap()) {
weak_cell = Map::WeakCellForMap(handle(Map::cast(heap_object)));
} else {
weak_cell = isolate_->factory()->NewWeakCell(
handle(PropertyCell::cast(heap_object)));
}
stub_cache()->Set(*name, *map, *weak_cell);
} else {
stub_cache()->Set(*name, *map, handler->ToObject());
}
stub_cache()->Set(*name, *map, *handler);
}
void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) {
......
......@@ -59,8 +59,7 @@ class IC {
IsKeyedStoreIC() || IsStoreInArrayLiteralICKind(kind());
}
static inline bool IsHandler(MaybeObject* object,
bool from_stub_cache = false);
static inline bool IsHandler(MaybeObject* object);
// Nofity the IC system that a feedback has changed.
static void OnFeedbackChanged(Isolate* isolate, FeedbackVector* vector,
......
......@@ -58,31 +58,32 @@ int StubCache::SecondaryOffset(Name* name, int seed) {
namespace {
bool CommonStubCacheChecks(StubCache* stub_cache, Name* name, Map* map,
Object* handler) {
MaybeObject* handler) {
// Validate that the name and handler do not move on scavenge, and that we
// can use identity checks instead of structural equality checks.
DCHECK(!name->GetHeap()->InNewSpace(name));
DCHECK(!name->GetHeap()->InNewSpace(handler));
DCHECK(name->IsUniqueName());
DCHECK(name->HasHashCode());
if (handler) DCHECK(IC::IsHandler(MaybeObject::FromObject(handler), true));
if (handler) DCHECK(IC::IsHandler(handler));
return true;
}
} // namespace
#endif
Object* StubCache::Set(Name* name, Map* map, Object* handler) {
MaybeObject* StubCache::Set(Name* name, Map* map, MaybeObject* handler) {
DCHECK(CommonStubCacheChecks(this, name, map, handler));
// Compute the primary entry.
int primary_offset = PrimaryOffset(name, map);
Entry* primary = entry(primary_, primary_offset);
Object* old_handler = primary->value;
MaybeObject* old_handler = primary->value;
// If the primary entry has useful data in it, we retire it to the
// secondary cache before overwriting it.
if (old_handler != isolate_->builtins()->builtin(Builtins::kIllegal)) {
if (old_handler != MaybeObject::FromObject(
isolate_->builtins()->builtin(Builtins::kIllegal))) {
Map* old_map = primary->map;
int seed = PrimaryOffset(primary->key, old_map);
int secondary_offset = SecondaryOffset(primary->key, seed);
......@@ -98,7 +99,7 @@ Object* StubCache::Set(Name* name, Map* map, Object* handler) {
return handler;
}
Object* StubCache::Get(Name* name, Map* map) {
MaybeObject* StubCache::Get(Name* name, Map* map) {
DCHECK(CommonStubCacheChecks(this, name, map, nullptr));
int primary_offset = PrimaryOffset(name, map);
Entry* primary = entry(primary_, primary_offset);
......@@ -115,7 +116,8 @@ Object* StubCache::Get(Name* name, Map* map) {
void StubCache::Clear() {
Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
MaybeObject* empty = MaybeObject::FromObject(
isolate_->builtins()->builtin(Builtins::kIllegal));
for (int i = 0; i < kPrimaryTableSize; i++) {
primary_[i].key = isolate()->heap()->empty_string();
primary_[i].map = nullptr;
......
......@@ -34,14 +34,14 @@ class StubCache {
public:
struct Entry {
Name* key;
Object* value;
MaybeObject* value;
Map* map;
};
void Initialize();
// Access cache for entry hash(name, map).
Object* Set(Name* name, Map* map, Object* handler);
Object* Get(Name* name, Map* map);
MaybeObject* Set(Name* name, Map* map, MaybeObject* handler);
MaybeObject* Get(Name* name, Map* map);
// Clear the lookup table (@ mark compact collection).
void Clear();
......
......@@ -118,7 +118,6 @@ Handle<Code> CreateCodeOfKind(Code::Kind kind) {
TEST(TryProbeStubCache) {
typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable;
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 3;
CodeAssemblerTester data(isolate, kNumParams);
......@@ -134,14 +133,15 @@ TEST(TryProbeStubCache) {
Label passed(&m), failed(&m);
Variable var_handler(&m, MachineRepresentation::kTagged);
CodeStubAssembler::TVariable<MaybeObject> var_handler(&m);
Label if_handler(&m), if_miss(&m);
m.TryProbeStubCache(&stub_cache, receiver, name, &if_handler, &var_handler,
&if_miss);
m.BIND(&if_handler);
m.Branch(m.WordEqual(expected_handler, var_handler.value()), &passed,
&failed);
m.Branch(m.WordEqual(expected_handler,
m.BitcastMaybeObjectToWord(var_handler.value())),
&passed, &failed);
m.BIND(&if_miss);
m.Branch(m.WordEqual(expected_handler, m.IntPtrConstant(0)), &passed,
......@@ -217,7 +217,7 @@ TEST(TryProbeStubCache) {
Handle<Name> name = names[index % names.size()];
Handle<JSObject> receiver = receivers[index % receivers.size()];
Handle<Code> handler = handlers[index % handlers.size()];
stub_cache.Set(*name, receiver->map(), *handler);
stub_cache.Set(*name, receiver->map(), MaybeObject::FromObject(*handler));
}
// Perform some queries.
......@@ -227,14 +227,14 @@ TEST(TryProbeStubCache) {
int index = rand_gen.NextInt();
Handle<Name> name = names[index % names.size()];
Handle<JSObject> receiver = receivers[index % receivers.size()];
Object* handler = stub_cache.Get(*name, receiver->map());
MaybeObject* handler = stub_cache.Get(*name, receiver->map());
if (handler == nullptr) {
queried_non_existing = true;
} else {
queried_existing = true;
}
Handle<Object> expected_handler(handler, isolate);
Handle<Object> expected_handler(handler->GetHeapObjectOrSmi(), isolate);
ft.CheckTrue(receiver, name, expected_handler);
}
......@@ -243,14 +243,14 @@ TEST(TryProbeStubCache) {
int index2 = rand_gen.NextInt();
Handle<Name> name = names[index1 % names.size()];
Handle<JSObject> receiver = receivers[index2 % receivers.size()];
Object* handler = stub_cache.Get(*name, receiver->map());
MaybeObject* handler = stub_cache.Get(*name, receiver->map());
if (handler == nullptr) {
queried_non_existing = true;
} else {
queried_existing = true;
}
Handle<Object> expected_handler(handler, isolate);
Handle<Object> expected_handler(handler->GetHeapObjectOrSmi(), isolate);
ft.CheckTrue(receiver, name, expected_handler);
}
// Ensure we performed both kind of queries.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment