[vm/gc] Account larger transferable to old space.
Currently external data is counted twice on the receiver size: once for
received transferable, second for newly created external typed data.
Ensure new space is collected when allocating external at the limit.
TEST=SendReceiveBytesTransferable with verbose-gc
Change-Id: I129d913f89e098b5d3066ce249ac0c4702e1394d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/199842
Commit-Queue: Alexander Aprelev <aam@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index a5d848f..e15ff53 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -1133,6 +1133,7 @@
Exceptions::ThrowArgumentError(error);
UNREACHABLE();
}
+ tpeer->handle()->EnsureFreedExternal(IsolateGroup::Current());
tpeer->ClearData();
const ExternalTypedData& typed_data = ExternalTypedData::Handle(
diff --git a/runtime/tests/vm/dart/transferable_allocations_test.dart b/runtime/tests/vm/dart/transferable_allocations_test.dart
new file mode 100644
index 0000000..ec61786
--- /dev/null
+++ b/runtime/tests/vm/dart/transferable_allocations_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2021, 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.
+
+// Verifies that Transferable (external old space) objects are promptly gc'ed.
+// The test will run out of ia32 3GB heap allocation if objects are not gc'ed.
+
+// VMOptions=--old_gen_heap_size=32
+
+import 'dart:isolate';
+import 'dart:typed_data';
+
+void main() {
+ final data = Uint8List.view(new Uint8List(5 * 1024 * 1024).buffer);
+ for (int i = 0; i < 1000; i++) {
+ TransferableTypedData.fromList(<Uint8List>[data]).materialize();
+ }
+}
diff --git a/runtime/tests/vm/dart_2/transferable_allocations_test.dart b/runtime/tests/vm/dart_2/transferable_allocations_test.dart
new file mode 100644
index 0000000..ec61786
--- /dev/null
+++ b/runtime/tests/vm/dart_2/transferable_allocations_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2021, 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.
+
+// Verifies that Transferable (external old space) objects are promptly gc'ed.
+// The test will run out of ia32 3GB heap allocation if objects are not gc'ed.
+
+// VMOptions=--old_gen_heap_size=32
+
+import 'dart:isolate';
+import 'dart:typed_data';
+
+void main() {
+ final data = Uint8List.view(new Uint8List(5 * 1024 * 1024).buffer);
+ for (int i = 0; i < 1000; i++) {
+ TransferableTypedData.fromList(<Uint8List>[data]).materialize();
+ }
+}
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index 411dbce..616c6bf 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -163,6 +163,9 @@
}
if (old_space_.ReachedHardThreshold()) {
+ if (last_gc_was_old_space_) {
+ CollectNewSpaceGarbage(Thread::Current(), kFull);
+ }
CollectGarbage(kMarkSweep, kExternal);
} else {
CheckStartConcurrentMarking(Thread::Current(), kExternal);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index bdef06a..6f0bc6c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -24851,8 +24851,7 @@
}
TransferableTypedDataPtr TransferableTypedData::New(uint8_t* data,
- intptr_t length,
- Heap::Space space) {
+ intptr_t length) {
TransferableTypedDataPeer* peer = new TransferableTypedDataPeer(data, length);
Thread* thread = Thread::Current();
@@ -24860,7 +24859,8 @@
{
ObjectPtr raw = Object::Allocate(
TransferableTypedData::kClassId, TransferableTypedData::InstanceSize(),
- space, TransferableTypedData::ContainsCompressedPointers());
+ thread->heap()->SpaceForExternal(length),
+ TransferableTypedData::ContainsCompressedPointers());
NoSafepointScope no_safepoint;
thread->heap()->SetPeer(raw, peer);
result ^= raw;
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 8461552..c3361b3 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -11138,9 +11138,7 @@
class TransferableTypedData : public Instance {
public:
- static TransferableTypedDataPtr New(uint8_t* data,
- intptr_t len,
- Heap::Space space = Heap::kNew);
+ static TransferableTypedDataPtr New(uint8_t* data, intptr_t len);
static intptr_t InstanceSize() {
return RoundedAllocationSize(sizeof(UntaggedTransferableTypedData));
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 6617eec..655857e 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1689,7 +1689,7 @@
ASSERT(reader != nullptr);
ASSERT(!Snapshot::IsFull(kind));
- const intptr_t length = reader->Read<int32_t>();
+ const intptr_t length = reader->Read<int64_t>();
const FinalizableData finalizable_data =
static_cast<MessageSnapshotReader*>(reader)->finalizable_data()->Take();
@@ -1726,7 +1726,7 @@
writer->WriteIndexedObject(GetClassId());
writer->WriteTags(writer->GetObjectTags(this));
- writer->Write<int32_t>(length);
+ writer->Write<int64_t>(length);
static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
length, data, tpeer,