Skip to content

Commit 4c985ef

Browse files
Inform the Dart VM when snapshots are safe to use with madvise(DONTNEED).
Bug: dart-lang/sdk#44019 Bug: flutter/flutter#92120
1 parent ed6a7d0 commit 4c985ef

File tree

14 files changed

+106
-25
lines changed

14 files changed

+106
-25
lines changed

fml/mapping.cc

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,19 @@ const uint8_t* DataMapping::GetMapping() const {
8181
return data_.data();
8282
}
8383

84+
bool DataMapping::IsDontNeedSafe() const {
85+
return false;
86+
}
87+
8488
// NonOwnedMapping
8589
NonOwnedMapping::NonOwnedMapping(const uint8_t* data,
8690
size_t size,
87-
const ReleaseProc& release_proc)
88-
: data_(data), size_(size), release_proc_(release_proc) {}
91+
const ReleaseProc& release_proc,
92+
bool dontneed_safe)
93+
: data_(data),
94+
size_(size),
95+
release_proc_(release_proc),
96+
dontneed_safe_(dontneed_safe) {}
8997

9098
NonOwnedMapping::~NonOwnedMapping() {
9199
if (release_proc_) {
@@ -101,6 +109,10 @@ const uint8_t* NonOwnedMapping::GetMapping() const {
101109
return data_;
102110
}
103111

112+
bool NonOwnedMapping::IsDontNeedSafe() const {
113+
return dontneed_safe_;
114+
}
115+
104116
// MallocMapping
105117
MallocMapping::MallocMapping() : data_(nullptr), size_(0) {}
106118

@@ -134,6 +146,10 @@ const uint8_t* MallocMapping::GetMapping() const {
134146
return data_;
135147
}
136148

149+
bool MallocMapping::IsDontNeedSafe() const {
150+
return false;
151+
}
152+
137153
uint8_t* MallocMapping::Release() {
138154
uint8_t* result = data_;
139155
data_ = nullptr;
@@ -174,4 +190,8 @@ const uint8_t* SymbolMapping::GetMapping() const {
174190
return mapping_;
175191
}
176192

193+
bool SymbolMapping::IsDontNeedSafe() const {
194+
return true;
195+
}
196+
177197
} // namespace fml

fml/mapping.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ class Mapping {
2828

2929
virtual const uint8_t* GetMapping() const = 0;
3030

31+
// Whether calling madvise(DONTNEED) on the mapping is non-destructive.
32+
// Generally true for file-mapped memory and false for anonymous memory.
33+
virtual bool IsDontNeedSafe() const = 0;
34+
3135
private:
3236
FML_DISALLOW_COPY_AND_ASSIGN(Mapping);
3337
};
@@ -65,6 +69,9 @@ class FileMapping final : public Mapping {
6569
// |Mapping|
6670
const uint8_t* GetMapping() const override;
6771

72+
// |Mapping|
73+
bool IsDontNeedSafe() const override;
74+
6875
uint8_t* GetMutableMapping();
6976

7077
bool IsValid() const;
@@ -96,6 +103,9 @@ class DataMapping final : public Mapping {
96103
// |Mapping|
97104
const uint8_t* GetMapping() const override;
98105

106+
// |Mapping|
107+
bool IsDontNeedSafe() const override;
108+
99109
private:
100110
std::vector<uint8_t> data_;
101111

@@ -107,7 +117,8 @@ class NonOwnedMapping final : public Mapping {
107117
using ReleaseProc = std::function<void(const uint8_t* data, size_t size)>;
108118
NonOwnedMapping(const uint8_t* data,
109119
size_t size,
110-
const ReleaseProc& release_proc = nullptr);
120+
const ReleaseProc& release_proc = nullptr,
121+
bool dontneed_safe = false);
111122

112123
~NonOwnedMapping() override;
113124

@@ -117,10 +128,14 @@ class NonOwnedMapping final : public Mapping {
117128
// |Mapping|
118129
const uint8_t* GetMapping() const override;
119130

131+
// |Mapping|
132+
bool IsDontNeedSafe() const override;
133+
120134
private:
121135
const uint8_t* const data_;
122136
const size_t size_;
123137
const ReleaseProc release_proc_;
138+
const bool dontneed_safe_;
124139

125140
FML_DISALLOW_COPY_AND_ASSIGN(NonOwnedMapping);
126141
};
@@ -162,6 +177,9 @@ class MallocMapping final : public Mapping {
162177
// |Mapping|
163178
const uint8_t* GetMapping() const override;
164179

180+
// |Mapping|
181+
bool IsDontNeedSafe() const override;
182+
165183
/// Removes ownership of the data buffer.
166184
/// After this is called; the mapping will point to nullptr.
167185
[[nodiscard]] uint8_t* Release();
@@ -186,6 +204,9 @@ class SymbolMapping final : public Mapping {
186204
// |Mapping|
187205
const uint8_t* GetMapping() const override;
188206

207+
// |Mapping|
208+
bool IsDontNeedSafe() const override;
209+
189210
private:
190211
fml::RefPtr<fml::NativeLibrary> native_library_;
191212
const uint8_t* mapping_ = nullptr;

fml/platform/posix/mapping_posix.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ const uint8_t* FileMapping::GetMapping() const {
100100
return mapping_;
101101
}
102102

103+
bool FileMapping::IsDontNeedSafe() const {
104+
return mutable_mapping_ == nullptr;
105+
}
106+
103107
bool FileMapping::IsValid() const {
104108
return valid_;
105109
}

fml/platform/win/mapping_win.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ const uint8_t* FileMapping::GetMapping() const {
115115
return mapping_;
116116
}
117117

118+
bool FileMapping::IsDontNeedSafe() const {
119+
return mutable_mapping_ == nullptr;
120+
}
121+
118122
bool FileMapping::IsValid() const {
119123
return valid_;
120124
}

runtime/dart_isolate.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ void DartIsolate::Flags::SetNullSafetyEnabled(bool enabled) {
7474
flags_.null_safety = enabled;
7575
}
7676

77+
void DartIsolate::Flags::SetIsDontNeedSafe(bool value) {
78+
flags_.snapshot_is_dontneed_safe = value;
79+
}
80+
7781
Dart_IsolateFlags DartIsolate::Flags::Get() const {
7882
return flags_;
7983
}
@@ -139,6 +143,7 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRunningRootIsolate(
139143

140144
isolate_flags.SetNullSafetyEnabled(
141145
isolate_configration->IsNullSafetyEnabled(*isolate_snapshot));
146+
isolate_flags.SetIsDontNeedSafe(isolate_snapshot->IsDontNeedSafe());
142147

143148
auto isolate = CreateRootIsolate(settings, //
144149
isolate_snapshot, //

runtime/dart_isolate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class DartIsolate : public UIDartState {
7070
~Flags();
7171

7272
void SetNullSafetyEnabled(bool enabled);
73+
void SetIsDontNeedSafe(bool value);
7374

7475
Dart_IsolateFlags Get() const;
7576

runtime/dart_snapshot.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,14 @@ const uint8_t* DartSnapshot::GetInstructionsMapping() const {
214214
return instructions_ ? instructions_->GetMapping() : nullptr;
215215
}
216216

217+
bool DartSnapshot::IsDontNeedSafe() const {
218+
if (data_ && !data_->IsDontNeedSafe())
219+
return false;
220+
if (instructions_ && !instructions_->IsDontNeedSafe())
221+
return false;
222+
return true;
223+
}
224+
217225
bool DartSnapshot::IsNullSafetyEnabled(const fml::Mapping* kernel) const {
218226
return ::Dart_DetectNullSafety(
219227
nullptr, // script_uri (unsupported by Flutter)

runtime/dart_snapshot.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ class DartSnapshot : public fml::RefCountedThreadSafe<DartSnapshot> {
151151
///
152152
const uint8_t* GetInstructionsMapping() const;
153153

154+
//----------------------------------------------------------------------------
155+
/// @brief Returns whether both the data and instructions mappings are
156+
/// safe to use with madvise(DONTNEED).
157+
bool IsDontNeedSafe() const;
158+
154159
bool IsNullSafetyEnabled(
155160
const fml::Mapping* application_kernel_mapping) const;
156161

shell/platform/android/apk_asset_provider.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ class APKAssetMapping : public fml::Mapping {
4848
return reinterpret_cast<const uint8_t*>(AAsset_getBuffer(asset_));
4949
}
5050

51+
bool IsDontNeedSafe() const override { return !AAsset_isAllocated(asset_); }
52+
5153
private:
5254
AAsset* const asset_;
5355

shell/platform/darwin/common/buffer_conversions.mm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
return static_cast<const uint8_t*>([data_.get() bytes]);
1919
}
2020

21+
bool IsDontNeedSafe() const override { return false; }
22+
2123
private:
2224
fml::scoped_nsobject<NSData> data_;
2325
FML_DISALLOW_COPY_AND_ASSIGN(NSDataMapping);

shell/platform/fuchsia/flutter/component_v1.cc

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -292,27 +292,28 @@ ComponentV1::ComponentV1(
292292
}
293293
auto hold_snapshot = [snapshot](const uint8_t* _, size_t __) {};
294294
settings_.vm_snapshot_data = [hold_snapshot, vm_data]() {
295-
return std::make_unique<fml::NonOwnedMapping>(vm_data, 0,
296-
hold_snapshot);
295+
return std::make_unique<fml::NonOwnedMapping>(vm_data, 0, hold_snapshot,
296+
true /* dontneed_safe */);
297297
};
298298
settings_.vm_snapshot_instr = [hold_snapshot, vm_instructions]() {
299-
return std::make_unique<fml::NonOwnedMapping>(vm_instructions, 0,
300-
hold_snapshot);
299+
return std::make_unique<fml::NonOwnedMapping>(
300+
vm_instructions, 0, hold_snapshot, true /* dontneed_safe */);
301301
};
302302
settings_.isolate_snapshot_data = [hold_snapshot, isolate_data]() {
303-
return std::make_unique<fml::NonOwnedMapping>(isolate_data, 0,
304-
hold_snapshot);
303+
return std::make_unique<fml::NonOwnedMapping>(
304+
isolate_data, 0, hold_snapshot, true /* dontneed_safe */);
305305
};
306306
settings_.isolate_snapshot_instr = [hold_snapshot,
307307
isolate_instructions]() {
308-
return std::make_unique<fml::NonOwnedMapping>(isolate_instructions, 0,
309-
hold_snapshot);
308+
return std::make_unique<fml::NonOwnedMapping>(
309+
isolate_instructions, 0, hold_snapshot, true /* dontneed_safe */);
310310
};
311311
isolate_snapshot_ = fml::MakeRefCounted<flutter::DartSnapshot>(
312-
std::make_shared<fml::NonOwnedMapping>(isolate_data, 0,
313-
hold_snapshot),
312+
std::make_shared<fml::NonOwnedMapping>(isolate_data, 0, hold_snapshot,
313+
true /* dontneed_safe */),
314314
std::make_shared<fml::NonOwnedMapping>(isolate_instructions, 0,
315-
hold_snapshot));
315+
hold_snapshot,
316+
true /* dontneed_safe */));
316317
} else {
317318
const int namespace_fd = component_data_directory_.get();
318319
settings_.vm_snapshot_data = [namespace_fd]() {

shell/platform/fuchsia/flutter/component_v2.cc

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -310,27 +310,28 @@ ComponentV2::ComponentV2(
310310
}
311311
auto hold_snapshot = [snapshot](const uint8_t* _, size_t __) {};
312312
settings_.vm_snapshot_data = [hold_snapshot, vm_data]() {
313-
return std::make_unique<fml::NonOwnedMapping>(vm_data, 0,
314-
hold_snapshot);
313+
return std::make_unique<fml::NonOwnedMapping>(vm_data, 0, hold_snapshot,
314+
true /* dontneed_safe */);
315315
};
316316
settings_.vm_snapshot_instr = [hold_snapshot, vm_instructions]() {
317-
return std::make_unique<fml::NonOwnedMapping>(vm_instructions, 0,
318-
hold_snapshot);
317+
return std::make_unique<fml::NonOwnedMapping>(
318+
vm_instructions, 0, hold_snapshot, true /* dontneed_safe */);
319319
};
320320
settings_.isolate_snapshot_data = [hold_snapshot, isolate_data]() {
321-
return std::make_unique<fml::NonOwnedMapping>(isolate_data, 0,
322-
hold_snapshot);
321+
return std::make_unique<fml::NonOwnedMapping>(
322+
isolate_data, 0, hold_snapshot, true /* dontneed_safe */);
323323
};
324324
settings_.isolate_snapshot_instr = [hold_snapshot,
325325
isolate_instructions]() {
326-
return std::make_unique<fml::NonOwnedMapping>(isolate_instructions, 0,
327-
hold_snapshot);
326+
return std::make_unique<fml::NonOwnedMapping>(
327+
isolate_instructions, 0, hold_snapshot, true /* dontneed_safe */);
328328
};
329329
isolate_snapshot_ = fml::MakeRefCounted<flutter::DartSnapshot>(
330-
std::make_shared<fml::NonOwnedMapping>(isolate_data, 0,
331-
hold_snapshot),
330+
std::make_shared<fml::NonOwnedMapping>(isolate_data, 0, hold_snapshot,
331+
true /* dontneed_safe */),
332332
std::make_shared<fml::NonOwnedMapping>(isolate_instructions, 0,
333-
hold_snapshot));
333+
hold_snapshot,
334+
true /* dontneed_safe */));
334335
} else {
335336
const int namespace_fd = component_data_directory_.get();
336337
settings_.vm_snapshot_data = [namespace_fd]() {

shell/platform/fuchsia/flutter/file_in_namespace_buffer.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ size_t FileInNamespaceBuffer::GetSize() const {
7070
return size_;
7171
}
7272

73+
bool FileInNamespaceBuffer::IsDontNeedSafe() const {
74+
return true;
75+
}
76+
7377
std::unique_ptr<fml::Mapping> LoadFile(int namespace_fd,
7478
const char* path,
7579
bool executable) {

shell/platform/fuchsia/flutter/file_in_namespace_buffer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ class FileInNamespaceBuffer final : public fml::Mapping {
2525
// |fml::Mapping|
2626
size_t GetSize() const override;
2727

28+
// |fml::Mapping|
29+
bool IsDontNeedSafe() const override;
30+
2831
private:
2932
/// The address that was mapped to the buffer.
3033
void* address_;

0 commit comments

Comments
 (0)