Skip to content

Commit 985824d

Browse files
rmacnak-googlecommit-bot@chromium.org
authored andcommitted
[vm] Ask the OS to release the memory for the clustered portion of the snapshot.
This region is mostly unused after loading, but it may be accessed again if - Isolate.spawn is invoke with isolate groups disabled - A secondary snapshot produced by splitting is loaded - An external typed data in the snapshot is accessed (usually a kernel file) - Likely other cases Even if these cases did not exist, the region is often part of a shared library and so unable to be released independently. madvise(DONT_NEED) on this region will cause the OS to release the memory in this region but keep the address space reservation and mapping. If it is touched again, it will be brought back in from the file. If it is not backed by a file, such as malloc memory, it will be brought back in as zeros and the program will likely fail. TEST=ci Bug: #44019 Bug: flutter/flutter#92120 Change-Id: I315a049b0f7d440e181d0a5e87fa6770a2fd4f79 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/216580 Commit-Queue: Ryan Macnak <[email protected]> Reviewed-by: Siva Annamalai <[email protected]>
1 parent bca554f commit 985824d

7 files changed

+49
-3
lines changed

runtime/include/dart_api.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ typedef struct {
608608
bool copy_parent_code;
609609
bool null_safety;
610610
bool is_system_isolate;
611+
bool snapshot_is_dontneed_safe;
611612
} Dart_IsolateFlags;
612613

613614
/**

runtime/vm/app_snapshot.cc

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7833,6 +7833,8 @@ class HeapLocker : public StackResource {
78337833
};
78347834

78357835
void Deserializer::Deserialize(DeserializationRoots* roots) {
7836+
const void* clustered_start = CurrentBufferAddress();
7837+
78367838
Array& refs = Array::Handle(zone_);
78377839
num_base_objects_ = ReadUnsigned();
78387840
num_objects_ = ReadUnsigned();
@@ -7926,8 +7928,8 @@ void Deserializer::Deserialize(DeserializationRoots* roots) {
79267928

79277929
roots->PostLoad(this, refs);
79287930

7929-
#if defined(DEBUG)
79307931
auto isolate_group = thread()->isolate_group();
7932+
#if defined(DEBUG)
79317933
isolate_group->ValidateClassTable();
79327934
if (isolate_group != Dart::vm_isolate()->group()) {
79337935
isolate_group->heap()->Verify();
@@ -7941,6 +7943,13 @@ void Deserializer::Deserialize(DeserializationRoots* roots) {
79417943
clusters_[i]->PostLoad(this, refs, primary);
79427944
}
79437945
}
7946+
7947+
if (isolate_group->snapshot_is_dontneed_safe()) {
7948+
size_t clustered_length = reinterpret_cast<uword>(CurrentBufferAddress()) -
7949+
reinterpret_cast<uword>(clustered_start);
7950+
VirtualMemory::DontNeed(const_cast<void*>(clustered_start),
7951+
clustered_length);
7952+
}
79447953
}
79457954

79467955
#if !defined(DART_PRECOMPILED_RUNTIME)

runtime/vm/isolate.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ typedef FixedCache<intptr_t, CatchEntryMovesRefPtr, 16> CatchEntryMovesCache;
161161
FLAG_use_field_guards) \
162162
V(PRODUCT, should_load_vmservice_library, ShouldLoadVmService, \
163163
load_vmservice_library, false) \
164-
V(NONPRODUCT, use_osr, UseOsr, use_osr, FLAG_use_osr)
164+
V(NONPRODUCT, use_osr, UseOsr, use_osr, FLAG_use_osr) \
165+
V(NONPRODUCT, snapshot_is_dontneed_safe, SnapshotIsDontNeedSafe, \
166+
snapshot_is_dontneed_safe, false)
165167

166168
#define BOOL_ISOLATE_FLAG_LIST_DEFAULT_GETTER(V) \
167169
V(PRODUCT, copy_parent_code, CopyParentCode, copy_parent_code, false) \
@@ -786,7 +788,8 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
786788
V(NullSafetySet) \
787789
V(Obfuscate) \
788790
V(UseFieldGuards) \
789-
V(UseOsr)
791+
V(UseOsr) \
792+
V(SnapshotIsDontNeedSafe)
790793

791794
// Isolate group specific flags.
792795
enum FlagBits {

runtime/vm/virtual_memory.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class VirtualMemory {
4646
static void Protect(void* address, intptr_t size, Protection mode);
4747
void Protect(Protection mode) { return Protect(address(), size(), mode); }
4848

49+
static void DontNeed(void* address, intptr_t size);
50+
4951
// Reserves and commits a virtual memory segment with size. If a segment of
5052
// the requested size cannot be allocated, NULL is returned.
5153
static VirtualMemory* Allocate(intptr_t size,

runtime/vm/virtual_memory_fuchsia.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,21 @@ void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
299299
}
300300
}
301301

302+
void VirtualMemory::DontNeed(void* address, intptr_t size) {
303+
uword start_address = reinterpret_cast<uword>(address);
304+
uword end_address = start_address + size;
305+
uword page_address = Utils::RoundDown(start_address, PageSize());
306+
zx_status_t status = zx_vmar_op_range(
307+
getVmarForAddress(reinterpret_cast<uword>(address)), ZX_VMAR_OP_DONT_NEED,
308+
page_address, end_address - page_address, nullptr, 0);
309+
LOG_INFO("zx_vmar_op_range(DONTNEED, 0x%lx, 0x%lx)\n", page_address,
310+
end_address - page_address);
311+
if (status != ZX_OK) {
312+
FATAL("zx_vmar_op_range(DONTNEED, 0x%lx, 0x%lx) failed: %s\n", page_address,
313+
end_address - page_address, zx_status_get_string(status));
314+
}
315+
}
316+
302317
} // namespace dart
303318

304319
#endif // defined(DART_HOST_OS_FUCHSIA)

runtime/vm/virtual_memory_posix.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,20 @@ void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
560560
end_address - page_address, prot);
561561
}
562562

563+
void VirtualMemory::DontNeed(void* address, intptr_t size) {
564+
uword start_address = reinterpret_cast<uword>(address);
565+
uword end_address = start_address + size;
566+
uword page_address = Utils::RoundDown(start_address, PageSize());
567+
if (madvise(reinterpret_cast<void*>(page_address), end_address - page_address,
568+
MADV_DONTNEED) != 0) {
569+
int error = errno;
570+
const int kBufferSize = 1024;
571+
char error_buf[kBufferSize];
572+
FATAL("madvise error: %d (%s)", error,
573+
Utils::StrError(error, error_buf, kBufferSize));
574+
}
575+
}
576+
563577
} // namespace dart
564578

565579
#endif // defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_LINUX) || \

runtime/vm/virtual_memory_win.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
241241
}
242242
}
243243

244+
void VirtualMemory::DontNeed(void* address, intptr_t size) {}
245+
244246
} // namespace dart
245247

246248
#endif // defined(DART_HOST_OS_WINDOWS)

0 commit comments

Comments
 (0)