Version 2.14.0-109.0.dev
Merge commit 'a22d5b98fde7e8cf548982a9d683e0ebf350d520' into 'dev'
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 1add15e..7eef9f8 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -145,6 +145,17 @@
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 @@
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);
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index ebdc4c0..94e834f 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -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 @@
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 @@
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 @@
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 @@
const SemiSpace* const to_;
ObjectPtr visiting_;
bool is_remembered_;
+ bool is_card_remembered_;
};
void Scavenger::VerifyStoreBuffers() {
diff --git a/tools/VERSION b/tools/VERSION
index acf070f..f71302f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 108
+PRERELEASE 109
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/create_timestamp_file.py b/tools/create_timestamp_file.py
deleted file mode 100755
index bb48e7f..0000000
--- a/tools/create_timestamp_file.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-import sys
-import os
-
-
-def main(args):
- for file_name in args[1:]:
- dir_name = os.path.dirname(file_name)
- if not os.path.exists(dir_name):
- os.mkdir(dir_name)
- open(file_name, 'w').close()
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv))
diff --git a/tools/list_dart_files_as_depfile.py b/tools/list_dart_files_as_depfile.py
new file mode 100644
index 0000000..84eddee
--- /dev/null
+++ b/tools/list_dart_files_as_depfile.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python3
+# Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+"""Tool for listing Dart source files.
+
+If the first argument is 'relative', the script produces paths relative to the
+current working directory. If the first argument is 'absolute', the script
+produces absolute paths.
+
+Usage:
+ python3 tools/list_dart_files_as_depfile.py <depfile> <directory> <pattern>
+"""
+
+import os
+import re
+import sys
+
+
+def main(argv):
+ depfile = argv[1]
+ directory = argv[2]
+ if not os.path.isabs(directory):
+ directory = os.path.realpath(directory)
+
+ pattern = None
+ if len(argv) > 3:
+ pattern = re.compile(argv[3])
+
+ # Output a GN/Ninja depfile, whose format is a Makefile with one target.
+ out = open(depfile, 'w')
+ out.write(os.path.relpath(depfile))
+ out.write(":")
+
+ for root, directories, files in os.walk(directory):
+ # We only care about actual source files, not generated code or tests.
+ for skip_dir in ['.git', 'gen', 'test']:
+ if skip_dir in directories:
+ directories.remove(skip_dir)
+
+ # If we are looking at the root directory, filter the immediate
+ # subdirectories by the given pattern.
+ if pattern and root == directory:
+ directories[:] = filter(pattern.match, directories)
+
+ for filename in files:
+ if filename.endswith(
+ '.dart') and not filename.endswith('_test.dart'):
+ fullname = os.path.join(directory, root, filename)
+ fullname = fullname.replace(os.sep, '/')
+ out.write(" \"")
+ out.write(fullname)
+ out.write("\"")
+
+ out.write("\n")
+ out.close()
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/utils/create_timestamp.gni b/utils/create_timestamp.gni
index 835700a..3b39299 100644
--- a/utils/create_timestamp.gni
+++ b/utils/create_timestamp.gni
@@ -10,16 +10,15 @@
path = invoker.path
output = invoker.output
action(target_name) {
- list_args = [ path ]
+ script = "$_dart_root/tools/list_dart_files_as_depfile.py"
+ args = [
+ rebase_path(output),
+ path,
+ ]
if (defined(invoker.pattern)) {
- list_args += [ invoker.pattern ]
+ args += [ invoker.pattern ]
}
- files = exec_script("$_dart_root/tools/list_dart_files.py",
- [ "absolute" ] + list_args,
- "list lines")
- inputs = [ "$_dart_root/tools/list_dart_files.py" ] + files
+ depfile = output
outputs = [ output ]
- script = "$_dart_root/tools/create_timestamp_file.py"
- args = [ rebase_path(output) ]
}
}