mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 02:17:14 +00:00
f4b34ad31b
When a FinalizerEntry's target gets promoted, the associated external size needs to also get promoted. We were handling the cases where the FinalizerEntry itself was either already old or remained new, but not the case where it was promoted. Failing to promote the external size meant that when the finalizer was collected, external size was subtraced from old space that was still being attributed to new space, so the old space total external size became negative. TEST=ci Bug: https://github.com/dart-lang/sdk/issues/50537 Change-Id: Id2fe2d748311de73f04de367c9cd153d87b74ad1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/272350 Reviewed-by: Daco Harkes <dacoharkes@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
51 lines
1.5 KiB
Dart
51 lines
1.5 KiB
Dart
// Copyright (c) 2022, 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.
|
|
|
|
// Issue https://github.com/dart-lang/sdk/issues/50537
|
|
|
|
// @dart=2.9
|
|
|
|
import "dart:async";
|
|
import "dart:ffi";
|
|
import "dart:io";
|
|
|
|
final libc = DynamicLibrary.process();
|
|
typedef MallocForeign = Pointer<Void> Function(IntPtr size);
|
|
typedef MallocNative = Pointer<Void> Function(int size);
|
|
final malloc = libc.lookupFunction<MallocForeign, MallocNative>('malloc');
|
|
typedef FreeForeign = Void Function(Pointer<Void>);
|
|
final free = libc.lookup<NativeFunction<FreeForeign>>('free');
|
|
final freeFinalizer = NativeFinalizer(free);
|
|
|
|
class Resource implements Finalizable {
|
|
Pointer<Void> _target;
|
|
Resource() : _target = malloc(8) {
|
|
if (_target == nullptr) {
|
|
throw OutOfMemoryError();
|
|
}
|
|
freeFinalizer.attach(this, _target, detach: this, externalSize: 8);
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
if (Platform.isWindows) {
|
|
print("No malloc via self process lookup on Windows");
|
|
return;
|
|
}
|
|
|
|
// Split across turns so the internal finalizer cleanup can run.
|
|
// Cf. https://github.com/dart-lang/sdk/issues/50570
|
|
final sw = Stopwatch()..start();
|
|
step() {
|
|
if (sw.elapsedMilliseconds < 2000) {
|
|
// VM assertion: external size of each generation should always be
|
|
// non-negative.
|
|
List.generate(1000, (_) => new Resource());
|
|
Timer.run(step);
|
|
}
|
|
}
|
|
|
|
Timer.run(step);
|
|
}
|