Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 9fcfec3

Browse files
Avoid creating a vector when constructing Dart typed data objects for platform messages (#18838)
1 parent 1551b74 commit 9fcfec3

File tree

4 files changed

+31
-54
lines changed

4 files changed

+31
-54
lines changed

lib/ui/window/platform_message_response_dart.cc

+3-33
Original file line numberDiff line numberDiff line change
@@ -8,43 +8,12 @@
88

99
#include "flutter/common/task_runners.h"
1010
#include "flutter/fml/make_copyable.h"
11-
#include "flutter/lib/ui/window/window.h"
1211
#include "third_party/tonic/dart_state.h"
1312
#include "third_party/tonic/logging/dart_invoke.h"
13+
#include "third_party/tonic/typed_data/dart_byte_data.h"
1414

1515
namespace flutter {
1616

17-
namespace {
18-
19-
// Avoid copying the contents of messages beyond a certain size.
20-
const int kMessageCopyThreshold = 1000;
21-
22-
void MessageDataFinalizer(void* isolate_callback_data,
23-
Dart_WeakPersistentHandle handle,
24-
void* peer) {
25-
std::vector<uint8_t>* data = reinterpret_cast<std::vector<uint8_t>*>(peer);
26-
delete data;
27-
}
28-
29-
Dart_Handle WrapByteData(std::vector<uint8_t> data) {
30-
if (data.size() < kMessageCopyThreshold) {
31-
return ToByteData(data);
32-
} else {
33-
std::vector<uint8_t>* heap_data = new std::vector<uint8_t>(std::move(data));
34-
return Dart_NewExternalTypedDataWithFinalizer(
35-
Dart_TypedData_kByteData, heap_data->data(), heap_data->size(),
36-
heap_data, heap_data->size(), MessageDataFinalizer);
37-
}
38-
}
39-
40-
Dart_Handle WrapByteData(std::unique_ptr<fml::Mapping> mapping) {
41-
std::vector<uint8_t> data(mapping->GetSize());
42-
memcpy(data.data(), mapping->GetMapping(), mapping->GetSize());
43-
return WrapByteData(std::move(data));
44-
}
45-
46-
} // anonymous namespace
47-
4817
PlatformMessageResponseDart::PlatformMessageResponseDart(
4918
tonic::DartPersistentValue callback,
5019
fml::RefPtr<fml::TaskRunner> ui_task_runner)
@@ -71,7 +40,8 @@ void PlatformMessageResponseDart::Complete(std::unique_ptr<fml::Mapping> data) {
7140
return;
7241
tonic::DartState::Scope scope(dart_state);
7342

74-
Dart_Handle byte_buffer = WrapByteData(std::move(data));
43+
Dart_Handle byte_buffer =
44+
tonic::DartByteData::Create(data->GetMapping(), data->GetSize());
7545
tonic::DartInvoke(callback.Release(), {byte_buffer});
7646
}));
7747
}

lib/ui/window/window.cc

+3-16
Original file line numberDiff line numberDiff line change
@@ -166,25 +166,12 @@ void GetPersistentIsolateData(Dart_NativeArguments args) {
166166
persistent_isolate_data->GetSize()));
167167
}
168168

169-
} // namespace
170-
171169
Dart_Handle ToByteData(const std::vector<uint8_t>& buffer) {
172-
Dart_Handle data_handle =
173-
Dart_NewTypedData(Dart_TypedData_kByteData, buffer.size());
174-
if (Dart_IsError(data_handle))
175-
return data_handle;
176-
177-
Dart_TypedData_Type type;
178-
void* data = nullptr;
179-
intptr_t num_bytes = 0;
180-
FML_CHECK(!Dart_IsError(
181-
Dart_TypedDataAcquireData(data_handle, &type, &data, &num_bytes)));
182-
183-
memcpy(data, buffer.data(), num_bytes);
184-
Dart_TypedDataReleaseData(data_handle);
185-
return data_handle;
170+
return tonic::DartByteData::Create(buffer.data(), buffer.size());
186171
}
187172

173+
} // namespace
174+
188175
WindowClient::~WindowClient() {}
189176

190177
Window::Window(WindowClient* client) : client_(client) {}

lib/ui/window/window.h

-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ namespace flutter {
3535
class FontCollection;
3636
class Scene;
3737

38-
Dart_Handle ToByteData(const std::vector<uint8_t>& buffer);
39-
4038
// Must match the AccessibilityFeatureFlag enum in window.dart.
4139
enum class AccessibilityFeatureFlag : int32_t {
4240
kAccessibleNavigation = 1 << 0,

third_party/tonic/typed_data/dart_byte_data.cc

+25-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,32 @@
88

99
namespace tonic {
1010

11+
namespace {
12+
13+
// For large objects it is more efficient to use an external typed data object
14+
// with a buffer allocated outside the Dart heap.
15+
const int kExternalSizeThreshold = 1000;
16+
17+
void FreeFinalizer(void* isolate_callback_data,
18+
Dart_WeakPersistentHandle handle,
19+
void* peer) {
20+
free(peer);
21+
}
22+
23+
} // anonymous namespace
24+
1125
Dart_Handle DartByteData::Create(const void* data, size_t length) {
12-
auto handle = DartByteData{data, length}.dart_handle();
13-
// The destructor should release the typed data.
14-
return handle;
26+
if (length < kExternalSizeThreshold) {
27+
auto handle = DartByteData{data, length}.dart_handle();
28+
// The destructor should release the typed data.
29+
return handle;
30+
} else {
31+
void* buf = ::malloc(length);
32+
TONIC_DCHECK(buf);
33+
::memcpy(buf, data, length);
34+
return Dart_NewExternalTypedDataWithFinalizer(
35+
Dart_TypedData_kByteData, buf, length, buf, length, FreeFinalizer);
36+
}
1537
}
1638

1739
DartByteData::DartByteData()

0 commit comments

Comments
 (0)