-
Notifications
You must be signed in to change notification settings - Fork 6k
Started looking for the dart plugin registrant at runtime #31418
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -709,6 +709,34 @@ static void InvokeDartPluginRegistrantIfAvailable(Dart_Handle library_handle) { | |
| tonic::LogIfError(tonic::DartInvokeField(plugin_registrant, "register", {})); | ||
| } | ||
|
|
||
| namespace { | ||
| bool EndsWith(const std::string& str, const std::string& ending) { | ||
| if (str.size() >= ending.size()) { | ||
| return (0 == | ||
| str.compare(str.size() - ending.size(), ending.size(), ending)); | ||
| } else { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| Dart_Handle FindDartPluginRegistrantLibrary() { | ||
| // TODO(): Instead of finding this, it could be passed down from the tool. | ||
| Dart_Handle libraries = Dart_GetLoadedLibraries(); | ||
| intptr_t length = 0; | ||
| Dart_ListLength(libraries, &length); | ||
| for (intptr_t i = 0; i < length; ++i) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this grows with the number of packages, right?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's right. I suspect the order of magnitude will never make this an issue. It depends on Dart's implementation of their API but linearly searching through a couple thousand strings shouldn't be significant. Most of the string comparisons will fail on the first char check.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For an internal customer, this resulted in a >300ms regression on startup time on low end Android devices.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't it more like ~275ms? I might be looking at the wrong thing.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, it was just under 300ms - a mean change of about 291ms on low end Android. This represented a 17% regression from before this patch. I think we should revert this. |
||
| Dart_Handle library = Dart_ListGetAt(libraries, i); | ||
| std::string library_name = | ||
| tonic::DartConverter<std::string>::FromDart(Dart_ToString(library)); | ||
| if (EndsWith(library_name, | ||
| "dart_tool/flutter_build/dart_plugin_registrant.dart'")) { | ||
| return library; | ||
| } | ||
| } | ||
| return Dart_Null(); | ||
| } | ||
| } // namespace | ||
|
|
||
| bool DartIsolate::RunFromLibrary(std::optional<std::string> library_name, | ||
| std::optional<std::string> entrypoint, | ||
| const std::vector<std::string>& args) { | ||
|
|
@@ -727,7 +755,12 @@ bool DartIsolate::RunFromLibrary(std::optional<std::string> library_name, | |
| ? tonic::ToDart(entrypoint.value().c_str()) | ||
| : tonic::ToDart("main"); | ||
|
|
||
| InvokeDartPluginRegistrantIfAvailable(library_handle); | ||
| auto dart_plugin_registrant_library = FindDartPluginRegistrantLibrary(); | ||
| if (!Dart_IsNull(dart_plugin_registrant_library)) { | ||
| InvokeDartPluginRegistrantIfAvailable(dart_plugin_registrant_library); | ||
| } else { | ||
| InvokeDartPluginRegistrantIfAvailable(library_handle); | ||
| } | ||
|
|
||
| auto user_entrypoint_function = | ||
| ::Dart_GetField(library_handle, entrypoint_handle); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| // Copyright 2013 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| #include "flutter/runtime/dart_isolate.h" | ||
|
|
||
| #include "flutter/fml/paths.h" | ||
| #include "flutter/runtime/dart_vm.h" | ||
| #include "flutter/runtime/dart_vm_lifecycle.h" | ||
| #include "flutter/testing/dart_isolate_runner.h" | ||
| #include "flutter/testing/fixture_test.h" | ||
| #include "flutter/testing/testing.h" | ||
|
|
||
| // CREATE_NATIVE_ENTRY is leaky by design | ||
| // NOLINTBEGIN(clang-analyzer-core.StackAddressEscape) | ||
|
|
||
| namespace flutter { | ||
| namespace testing { | ||
|
|
||
| const std::string kernel_file_name = "plugin_registrant_kernel_blob.bin"; | ||
| const std::string elf_file_name = "plugin_registrant_app_elf_snapshot.so"; | ||
|
|
||
| class DartIsolateTest : public FixtureTest { | ||
| public: | ||
| DartIsolateTest() : FixtureTest(kernel_file_name, elf_file_name, "") {} | ||
| }; | ||
|
|
||
| TEST_F(DartIsolateTest, DartPluginRegistrantIsNotPresent) { | ||
| ASSERT_FALSE(DartVMRef::IsInstanceRunning()); | ||
|
|
||
| std::vector<std::string> messages; | ||
| fml::AutoResetWaitableEvent latch; | ||
|
|
||
| AddNativeCallback( | ||
| "PassMessage", | ||
| CREATE_NATIVE_ENTRY(([&latch, &messages](Dart_NativeArguments args) { | ||
| auto message = tonic::DartConverter<std::string>::FromDart( | ||
| Dart_GetNativeArgument(args, 0)); | ||
| messages.push_back(message); | ||
| latch.Signal(); | ||
| }))); | ||
|
|
||
| auto settings = CreateSettingsForFixture(); | ||
| auto did_throw_exception = false; | ||
| settings.unhandled_exception_callback = [&](const std::string& error, | ||
| const std::string& stack_trace) { | ||
| did_throw_exception = true; | ||
| return true; | ||
| }; | ||
|
|
||
| auto vm_ref = DartVMRef::Create(settings); | ||
| auto thread = CreateNewThread(); | ||
| TaskRunners task_runners(GetCurrentTestName(), // | ||
| thread, // | ||
| thread, // | ||
| thread, // | ||
| thread // | ||
| ); | ||
|
|
||
| auto kernel_path = | ||
| fml::paths::JoinPaths({GetFixturesPath(), kernel_file_name}); | ||
| auto isolate = | ||
| RunDartCodeInIsolate(vm_ref, settings, task_runners, | ||
| "mainForPluginRegistrantTest", {}, kernel_path); | ||
|
|
||
| ASSERT_TRUE(isolate); | ||
| ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running); | ||
|
|
||
| latch.Wait(); | ||
|
|
||
| ASSERT_EQ(messages.size(), 1u); | ||
| ASSERT_EQ(messages[0], "_PluginRegistrant.register() was called"); | ||
| } | ||
|
|
||
| } // namespace testing | ||
| } // namespace flutter | ||
|
|
||
| // NOLINTEND(clang-analyzer-core.StackAddressEscape) |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,33 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| // Copyright 2013 The Flutter Authors. All rights reserved. | ||||||||||||||||||||||||||||||||||||||||||||||
| // Use of this source code is governed by a BSD-style license that can be | ||||||||||||||||||||||||||||||||||||||||||||||
| // found in the LICENSE file. | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| void passMessage(String message) native 'PassMessage'; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| bool didCallRegistrantBeforeEntrypoint = false; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // Test the Dart plugin registrant. | ||||||||||||||||||||||||||||||||||||||||||||||
| @pragma('vm:entry-point') | ||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there any difference between this file (or test) and engine/runtime/fixtures/runtime_test.dart Lines 164 to 185 in bfb5810
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, the path of the file. The other one can be removed once we land the Framework PR. |
||||||||||||||||||||||||||||||||||||||||||||||
| class _PluginRegistrant { | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| @pragma('vm:entry-point') | ||||||||||||||||||||||||||||||||||||||||||||||
| static void register() { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (didCallRegistrantBeforeEntrypoint) { | ||||||||||||||||||||||||||||||||||||||||||||||
| throw '_registerPlugins is being called twice'; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| didCallRegistrantBeforeEntrypoint = true; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| @pragma('vm:entry-point') | ||||||||||||||||||||||||||||||||||||||||||||||
| void mainForPluginRegistrantTest() { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (didCallRegistrantBeforeEntrypoint) { | ||||||||||||||||||||||||||||||||||||||||||||||
| passMessage('_PluginRegistrant.register() was called'); | ||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||
| passMessage('_PluginRegistrant.register() was not called'); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| void main() {} | ||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you plan to work on this issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope. I have no data to suggest it's worthwhile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you envision passing this from the tool?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't thought about it. Maybe we could make it so the library has a unique name so we can look directly for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok. I'd suggest filing an issue, and including the general idea about how this should be solved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
flutter/flutter#99308