1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-03 08:19:13 +00:00

[vm, gc] Verify remembered cards when verifying the store buffer.

TEST=ci
Change-Id: I004a55902c65d89915ea79c141270a2c2670e53c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/199363
Reviewed-by: Liam Appelbe <liama@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2021-05-11 23:56:08 +00:00 committed by commit-bot@chromium.org
parent 3a3b3e480b
commit 634cccccc6
2 changed files with 60 additions and 14 deletions

View File

@ -145,6 +145,17 @@ class OldPage {
ASSERT((index >= 0) && (index < card_table_size()));
card_table_[index] = 1;
}
bool IsCardRemembered(ObjectPtr const* slot) {
ASSERT(Contains(reinterpret_cast<uword>(slot)));
if (card_table_ == NULL) {
return false;
}
intptr_t offset =
reinterpret_cast<uword>(slot) - reinterpret_cast<uword>(this);
intptr_t index = offset >> kBytesPerCardLog2;
ASSERT((index >= 0) && (index < card_table_size()));
return card_table_[index] != 0;
}
#if defined(DART_COMPRESSED_POINTERS)
void RememberCard(CompressedObjectPtr const* slot) {
ASSERT(Contains(reinterpret_cast<uword>(slot)));
@ -158,6 +169,17 @@ class OldPage {
ASSERT((index >= 0) && (index < card_table_size()));
card_table_[index] = 1;
}
bool IsCardRemembered(CompressedObjectPtr const* slot) {
ASSERT(Contains(reinterpret_cast<uword>(slot)));
if (card_table_ == NULL) {
return false;
}
intptr_t offset =
reinterpret_cast<uword>(slot) - reinterpret_cast<uword>(this);
intptr_t index = offset >> kBytesPerCardLog2;
ASSERT((index >= 0) && (index < card_table_size()));
return card_table_[index] != 0;
}
#endif
void VisitRememberedCards(ObjectPointerVisitor* visitor);

View File

@ -9,6 +9,7 @@
#include "vm/dart_api_state.h"
#include "vm/flag_list.h"
#include "vm/heap/become.h"
#include "vm/heap/pages.h"
#include "vm/heap/pointer_block.h"
#include "vm/heap/safepoint.h"
#include "vm/heap/verifier.h"
@ -867,17 +868,15 @@ class CheckStoreBufferVisitor : public ObjectVisitor,
if (raw_obj->IsPseudoObject()) return;
RELEASE_ASSERT(raw_obj->IsOldObject());
if (raw_obj->untag()->IsCardRemembered()) {
RELEASE_ASSERT(!raw_obj->untag()->IsRemembered());
// TODO(rmacnak): Verify card tables.
return;
}
RELEASE_ASSERT(raw_obj->untag()->IsRemembered() ==
in_store_buffer_->Contains(raw_obj));
visiting_ = raw_obj;
is_remembered_ = raw_obj->untag()->IsRemembered();
is_card_remembered_ = raw_obj->untag()->IsCardRemembered();
if (is_card_remembered_) {
RELEASE_ASSERT(!is_remembered_);
}
raw_obj->untag()->VisitPointers(this);
}
@ -885,12 +884,24 @@ class CheckStoreBufferVisitor : public ObjectVisitor,
for (ObjectPtr* ptr = from; ptr <= to; ptr++) {
ObjectPtr raw_obj = *ptr;
if (raw_obj->IsHeapObject() && raw_obj->IsNewObject()) {
if (!is_remembered_) {
if (is_card_remembered_) {
if (!OldPage::Of(visiting_)->IsCardRemembered(ptr)) {
FATAL3(
"Old object %#" Px " references new object %#" Px
", but the "
"slot's card is not remembered. Consider using rr to watch the "
"slot %p and reverse-continue to find the store with a missing "
"barrier.\n",
static_cast<uword>(visiting_), static_cast<uword>(raw_obj),
ptr);
}
} else if (!is_remembered_) {
FATAL3(
"Old object %#" Px " references new object %#" Px
", but it is not"
" in any store buffer. Consider using rr to watch the slot %p and"
" reverse-continue to find the store with a missing barrier.\n",
", but it is "
"not in any store buffer. Consider using rr to watch the "
"slot %p and reverse-continue to find the store with a missing "
"barrier.\n",
static_cast<uword>(visiting_), static_cast<uword>(raw_obj), ptr);
}
RELEASE_ASSERT(to_->Contains(UntaggedObject::ToAddr(raw_obj)));
@ -904,12 +915,24 @@ class CheckStoreBufferVisitor : public ObjectVisitor,
for (CompressedObjectPtr* ptr = from; ptr <= to; ptr++) {
ObjectPtr raw_obj = ptr->Decompress(heap_base);
if (raw_obj->IsHeapObject() && raw_obj->IsNewObject()) {
if (!is_remembered_) {
if (is_card_remembered_) {
if (!OldPage::Of(visiting_)->IsCardRemembered(ptr)) {
FATAL3(
"Old object %#" Px " references new object %#" Px
", but the "
"slot's card is not remembered. Consider using rr to watch the "
"slot %p and reverse-continue to find the store with a missing "
"barrier.\n",
static_cast<uword>(visiting_), static_cast<uword>(raw_obj),
ptr);
}
} else if (!is_remembered_) {
FATAL3(
"Old object %#" Px " references new object %#" Px
", but it is not"
" in any store buffer. Consider using rr to watch the slot %p and"
" reverse-continue to find the store with a missing barrier.\n",
", but it is "
"not in any store buffer. Consider using rr to watch the "
"slot %p and reverse-continue to find the store with a missing "
"barrier.\n",
static_cast<uword>(visiting_), static_cast<uword>(raw_obj), ptr);
}
RELEASE_ASSERT(to_->Contains(UntaggedObject::ToAddr(raw_obj)));
@ -922,6 +945,7 @@ class CheckStoreBufferVisitor : public ObjectVisitor,
const SemiSpace* const to_;
ObjectPtr visiting_;
bool is_remembered_;
bool is_card_remembered_;
};
void Scavenger::VerifyStoreBuffers() {